diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/CREDITS linux.15p9/CREDITS
--- linux.vanilla/CREDITS	Tue Jan  4 21:18:37 2000
+++ linux.15p9/CREDITS	Mon Feb  7 12:29:21 2000
@@ -253,9 +253,9 @@
 D: Configuration help text support
 D: Linux CD and Support Giveaway List
 
-N: Zoltan Boszormenyi
-E: zboszor@mol.hu
-D: MTRR emulation with Cyrix style ARR registers
+N: Zoltán Böszörményi
+E: zboszor@mail.externet.hu
+D: MTRR emulation with Cyrix style ARR registers, Athlon MTRR support
 
 N: John Boyd
 E: boyd@cis.ohio-state.edu
@@ -1408,7 +1408,7 @@
 S: Netherlands
 
 N: David S. Miller
-E: davem@dm.cobaltmicro.com
+E: davem@redhat.com
 D: Sparc and blue box hacker
 D: Vger Linux mailing list co-maintainer
 D: Linux Emacs elf/qmagic support + other libc/gcc things
@@ -1546,6 +1546,15 @@
 E: orc@pell.chi.il.us
 D: improved memory detection code.
 
+N: Ivan Passos
+E: ivan@cyclades.com
+D: Author of the Cyclades-PC300 synchronous card driver
+D: Maintainer of the Cyclom-Y/Cyclades-Z asynchronous card driver
+S: Cyclades Corp
+S: 41934 Christy St
+S: Fremont, CA 94538
+S: USA
+
 N: Vojtech Pavlik
 E: vojtech@suse.cz
 D: Joystick driver
@@ -1892,6 +1901,13 @@
 S: Cliffwood, New Jersey 07721
 S: USA
 
+N: Andrew Stanley-Jones
+E: asj@lanmedia.com
+D: LanMedia Corp. Device WAN card device driver
+S: #102, 686 W. Maude Ave
+S: Sunyvale, CA 94086
+S: USA
+
 N: Henrik Storner
 E: storner@image.dk
 W: http://www.image.dk/~storner/
@@ -2042,12 +2058,8 @@
 S: Germany
 
 N: Greg Ungerer
-E: gerg@stallion.com
+E: gerg@moreton.com.au
 D: Author of Stallion multiport serial drivers
-S: Stallion Technologies
-S: 33 Woodstock Rd
-S: Toowong, QLD. 4066
-S: Australia
 
 N: Jeffrey A. Uphoff
 E: juphoff@nrao.edu
@@ -2263,6 +2275,13 @@
 D: Xiafs filesystem [defunct]
 S: 542 West 112th Street, 5N
 S: New York, New York 10025
+S: USA
+
+N: Victor Yodaiken
+E: yodaiken@fsmlabs.com
+D: RTLinux (RealTime Linux)
+S: POB 1822 
+S: Socorro NM, 87801
 S: USA
 
 N: Eric Youngdale
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/Documentation/Configure.help linux.15p9/Documentation/Configure.help
--- linux.vanilla/Documentation/Configure.help	Tue Jan  4 21:18:37 2000
+++ linux.15p9/Documentation/Configure.help	Wed Feb 16 18:35:24 2000
@@ -2573,7 +2573,7 @@
 
   You will need the user space program "ipmasqadm" to use these
   additional modules; you can download it from
-  http://juanjox.linuxhq.com/
+  http://juanjox.kernelnotes.org/
 
   All this additional code is still under development and so is
   currently marked EXPERIMENTAL.
@@ -2588,7 +2588,7 @@
   ftp://ftp.netis.com/pub/members/rlynch/
 
   You will also need the ipmasqadm tool available from
-  http://juanjox.linuxhq.com/ .
+  http://juanjox.kernelnotes.org/ .
 
   The ipautofw code is still under development and so is currently
   marked EXPERIMENTAL. If you want to try it, say Y.
@@ -2619,7 +2619,7 @@
   see ftp://ftp.compsoc.net/users/steve/ipportfw/linux21/
 
   You will need the user space program "ipmasqadm" which can be
-  downloaded from http://juanjox.linuxhq.com/
+  downloaded from http://juanjox.kernelnotes.org/
 
   The portfw code is still under development and so is currently
   marked EXPERIMENTAL. If you want to try it, say Y.
@@ -5490,6 +5490,31 @@
   The module will be called cosa.o. For general information about
   modules read Documentation/modules.txt.
 
+Lan Media sync serial boards support
+CONFIG_LANMEDIA
+  This is a driver for the following Lan Media family of serial boards.
+
+  LMC 1000 board allows you to connect synchronous serial devices (for
+  example base-band modems, or any other device with the X.21, V.24,
+  V.35 or V.36 interface) to your Linux box. 
+
+  LMC 1200 with on board DSU board allows you to connect your Linux
+  box dirrectly to a T1 or E1 circuit. 
+
+  LMC 5200 board provides a HSSI interface capable of runnig up to
+  52 mbits per second.
+
+  LMC 5245 board connects directly to a T3 circuit saving the
+  additional external hardware.
+
+  To change setting such as syncPPP vs cisco HDLC or clock source you
+  will need lmcctl.  It it available at ftp.lanmedia.com.
+
+  The driver will be compiled as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called lmc.o. For general information about
+  modules read Documentation/modules.txt.
+
 Red Creek Hardware VPN (EXPERIMENTAL)
 CONFIG_RCPCI
   This is a driver for hardware which provides a Virtual Private
@@ -5941,10 +5966,11 @@
   - SK-9844 (dual link   1000Base-SX)
   - SK-9821 (single link 1000Base-T)
   - SK-9822 (dual link   1000Base-T)
+  The adapters support Jumbo Frames.
   The dual link adapters support a link-failover feature.
   Read Documentation/networking/sk98lin.txt for information about
   optional driver parameters.
-  Questions concerning this driver may be addresse to:
+  Questions concerning this driver may be addressed to:
     linux@syskonnect.de
 
   If you want to compile this driver as a module ( = code which can be
@@ -6584,7 +6610,7 @@
   module, say M here and read Documentation/modules.txt as well as
   Documentation/networking/net-modules.txt.
 
-  Please email feedback to james.banks@caldera.com.
+  Please email feedback to torben.mathiasen@compaq.com.
 
 VIA Rhine support
 CONFIG_VIA_RHINE
@@ -7539,11 +7565,11 @@
   If you don't know whether you need it, then you don't need it:
   answer N.
 
-QNX filesystem support (EXPERIMENTAL)
+QNX4 filesystem support (EXPERIMENTAL)
 CONFIG_QNX4FS_FS  
   This is the filesystem used by the operating system QNX 4. Say Y if
   you intend to mount QNX hard disks or floppies. Unless you say Y to
-  "QNXFS read-write support" below, you will only be able to read
+  "QNX4FS write support" below, you will only be able to read
   these filesystems.
 
   This filesystem support is also available as a module ( = code which
@@ -7551,11 +7577,12 @@
   want). The module is called qnx4.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt. 
 
-  If unsure, say N.
+  If you don't know whether you need it, then you don't need it:
+  answer N.
 
-QNXFS read-write support (FOR TESTING ONLY)
+QNX4FS write support (DANGEROUS)
 CONFIG_QNX4FS_RW
-  Say Y if you want to test write support for QNX filesystems.
+  Say Y if you want to test write support for QNX4 filesystems.
 
 Kernel automounter support
 CONFIG_AUTOFS_FS
@@ -8365,6 +8392,44 @@
   on, it will always be RTS. Read the file Documentation/specialix.txt
   for more information.
 
+Specialix SX card support
+CONFIG_SX
+  This is a driver for the Specialix SX multiport card (both the
+  ISA and the PCI version of both the older SI/XIO and the newer SX
+  variants of the card) which gives you many serial ports. You
+  would need something like this to connect more than two modems to 
+  your Linux box, for instance in order to become a dial-in server.
+  You will also need the specialix_sxtools package to be able to 
+  initialize and use the SX system. This driver does NOT support 
+  the rev 1 cards (+/- 1990), or the EISA version of the card. Sorry.
+
+  If you have one of these cards, say Y here and read the file
+  Documentation/sx.txt. Also it's possible to say M here and
+  compile this driver as kernel loadable module which will be called
+  sx.o.
+
+Specialix RIO system support
+CONFIG_RIO
+  This is a driver for the Specialix RIO hostcard (both the
+  ISA and the PCI versions of the card). This hostcard allows you
+  to connect many remote terminal adapters, each supporting 8 or 16
+  serial ports. These cards are ideal if you have more than 100 
+  terminals that need to be connected to your server. (But don't 
+  worry if you have only 32 ports.... That works too). You will 
+  also need the specialix_riotools to be able to initialize and
+  configure your rio system.  
+
+  If you have one of these cards, say Y here. Also it's possible to 
+  say M here and compile this driver as kernel loadable module which 
+  will be called rio.o.
+
+Specialix OLD RIO/PCI support 
+CONFIG_RIO_OLDPCI
+  This turns on support for the older PCI card. If you include
+  this support, performance on the newer cards will suffer a bit.
+
+  If you have one of these cards, say Y here.
+
 Cyclades async mux support
 CONFIG_CYCLADES
   This is a driver for a card that gives you many serial ports. You
@@ -8976,9 +9041,12 @@
 
   The AMD K6-2 (stepping 8 and above) and K6-3 processors have two
   MTRRs. These are supported.
-  
-  The Centaur C6 (WinChip) has 8 MCRs, allowing write-combining. These
-  are supported.
+
+  The Centaur C6 (WinChip) and WinChip 2&3 processors have 8 MCRs. 
+  These are supported. Note that, due to the design of the WinChip 2&3, 
+  setting the access for normal memory to uncachable or write-combine
+  on these processors will result in instant kernel panic. It is okay 
+  to set this for non-cacheable (video) memory.
 
   Saying Y here also fixes a problem with buggy SMP BIOSes which only
   set the MTRRs for the boot CPU and not the secondary CPUs. This can
@@ -8997,8 +9065,8 @@
 
 Zilog serial support
 CONFIG_SUN_ZS
-  This driver does not exist at this point, so you might as well 
-  say N.
+  If you are asked this question, something is wrong with config scripts.
+  Zilog serial driver is always enabled in sparc architecture.
 
 Double Talk PC internal speech card support
 CONFIG_DTLK
@@ -9025,8 +9093,8 @@
   machines with more than one CPU.
 
   Supporting software is available; for more information, read the
-  Battery Powered Linux mini-HOWTO, available via FTP (user:
-  anonymous) from ftp://metalab.unc.edu/pub/Linux/docs/HOWTO/mini.
+  Battery Powered Linux mini-HOWTO, available from
+  http://www.linuxdoc.org/docs.html#howto .
 
   This driver does not spin down disk drives (see the hdparm(8)
   manpage ("man 8 hdparm") for that), and it doesn't turn off
@@ -9039,9 +9107,7 @@
 
   If you are running Linux on a laptop, you may also want to read the
   Linux Laptop home page on the WWW at
-  http://www.cs.utexas.edu/users/kharker/linux-laptop/ (to browse the
-  WWW, you need to have access to a machine on the Internet that has a
-  program like lynx or netscape). 
+  http://www.cs.utexas.edu/users/kharker/linux-laptop/ .
 
   Generally, if you don't have a battery in your machine, there isn't
   much point in using this driver and you should say N. If you get
@@ -9112,18 +9178,6 @@
   backlight at all, or it might print a lot of errors to the console,
   especially if you are using gpm.
 
-Power off on shutdown 
-CONFIG_APM_POWER_OFF
-  Enable the ability to power off the computer after the Linux kernel
-  is halted. You will need software (e.g., a suitable version of the
-  halt(8) command ("man 8 halt")) to cause the computer to power down.
-  Recent versions of the sysvinit package available from
-  ftp://metalab.unc.edu/pub/Linux/system/daemons/init/ (user:
-  anonymous) contain support for this ("halt -p" shuts down Linux and
-  powers off the computer, if executed from runlevel 0). As with the
-  other APM options, this option may not work reliably with some APM
-  BIOS implementations.
-
 Ignore multiple suspend/standby events
 CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
   This option is necessary on the IBM Thinkpad 560, but should work on
@@ -9161,6 +9215,12 @@
   many of the newer IBM Thinkpads.  If you experience hangs when you
   suspend, try setting this to Y.  Otherwise, say N.
 
+Use real mode APM BIOS call to power off
+CONFIG_APM_REAL_MODE_POWER_OFF
+  Use real mode APM BIOS calls to switch off the computer. This is
+  a work-around for a number of buggy BIOSes. Switch this option on if
+  your computer crashes instead of powering off properly.
+
 Watchdog Timer Support 
 CONFIG_WATCHDOG
   If you say Y here (and to one of the following options) and create a
@@ -10262,11 +10322,16 @@
   If you have trouble with some ugly exchanges try to select this
   option.
 
+Disable keypad protocol option
+CONFIG_HISAX_NO_KEYPAD
+  If you like to send special dialstrings including * or # without
+  using the keypad protocol, select this option.
+
 HiSax Support for german 1TR6
 CONFIG_HISAX_1TR6
   Enable this if you have a old german 1TR6 line.
 
-HiSax Support for Teles 16.0/8.0
+Teles 16.0/8.0
 CONFIG_HISAX_16_0
   This enables HiSax support for the Teles ISDN-cards S0-16.0, S0-8
   and many compatibles. 
@@ -10275,7 +10340,7 @@
   different cards, a different D-channel protocol, or non-standard
   IRQ/port/shmem settings.
 
-HiSax Support for Teles 16.3 or PNP or PCMCIA
+Teles 16.3 or PNP or PCMCIA
 CONFIG_HISAX_16_3
   This enables HiSax support for the Teles ISDN-cards S0-16.3 the
   Teles/Creatix PnP and the Teles PCMCIA.
@@ -10284,17 +10349,17 @@
   different cards, a different D-channel protocol, or non-standard
   IRQ/port settings.
 
-HiSax Support for Teles PCI
+Teles PCI
 CONFIG_HISAX_TELESPCI
   This enables HiSax support for the Teles PCI.
   See Documentation/isdn/README.HiSax on how to configure it.
 
-HiSax Support for Teles S0Box
+Teles S0Box
 CONFIG_HISAX_S0BOX
   This enables HiSax support for the Teles/Creatix parallel port
   S0BOX.  See Documentation/isdn/README.HiSax on how to configure it.
 
-HiSax Support for AVM A1 (Fritz)
+AVM A1 (Fritz)
 CONFIG_HISAX_AVM_A1
   This enables HiSax support for the AVM A1 (aka "Fritz").
   
@@ -10302,17 +10367,17 @@
   different cards, a different D-channel protocol, or non-standard
   IRQ/port settings.
 
-HiSax Support for AVM PnP/PCI (Fritz!PNP/PCI)
+AVM PnP/PCI (Fritz!PNP/PCI)
 CONFIG_HISAX_FRITZPCI
   This enables HiSax support for the AVM "Fritz!PnP" and "Fritz!PCI".
   See Documentation/isdn/README.HiSax on how to configure it.
 
-HiSax Support for AVM A1 PCMCIA (Fritz)
+AVM A1 PCMCIA (Fritz)
 CONFIG_HISAX_AVM_A1_PCMCIA
   This enables HiSax support for the AVM A1 "Fritz!PCMCIA").
   See Documentation/isdn/README.HiSax on how to configure it.
 
-HiSax Support for Elsa cards
+Elsa cards
 CONFIG_HISAX_ELSA
   This enables HiSax support for the Elsa Mircolink ISA cards, for the
   Elsa Quickstep series cards and Elsa PCMCIA.
@@ -10321,7 +10386,7 @@
   different cards, a different D-channel protocol, or non-standard
   IRQ/port settings.
 
-HiSax Support for ITK ix1-micro Revision 2
+ITK ix1-micro Revision 2
 CONFIG_HISAX_IX1MICROR2
   This enables HiSax support for the ITK ix1-micro Revision 2 card.
 
@@ -10329,7 +10394,7 @@
   different cards, a different D-channel protocol, or non-standard
   IRQ/port settings.
 
-HiSax Support for Eicon.Diehl Diva cards
+Eicon.Diehl Diva cards
 CONFIG_HISAX_DIEHLDIVA
   This enables HiSax support for the Eicon.Diehl Diva none PRO
   versions passive ISDN cards.
@@ -10338,16 +10403,16 @@
   different cards, a different D-channel protocol, or non-standard
   IRQ/port settings.
 
-HiSax Support for ASUSCOM cards
+ASUSCOM ISA cards
 CONFIG_HISAX_ASUSCOM
   This enables HiSax support for the AsusCom and their OEM versions
-  passive ISDN cards.
+  passive ISDN ISA cards.
 
   See Documentation/isdn/README.HiSax on how to configure it using the
   different cards, a different D-channel protocol, or non-standard
   IRQ/port settings.
 
-HiSax Support for TELEINT cards
+TELEINT cards
 CONFIG_HISAX_TELEINT
   This enables HiSax support for the TELEINT SA1 semiactiv ISDN card.
 
@@ -10355,7 +10420,7 @@
   different cards, a different D-channel protocol, or non-standard
   IRQ/port settings.
 
-HiSax Support for HFC-S based cards
+HFC-S based cards
 CONFIG_HISAX_HFCS
   This enables HiSax support for the HFC-S 2BDS0 based cards, like
   teles 16.3c.
@@ -10364,7 +10429,7 @@
   different cards, a different D-channel protocol, or non-standard
   IRQ/port settings.
 
-HiSax Support for Sedlbauer cards
+Sedlbauer cards
 CONFIG_HISAX_SEDLBAUER
   This enables HiSax support for the Sedlbauer passive ISDN cards.
 
@@ -10372,21 +10437,21 @@
   different cards, a different D-channel protocol, or non-standard
   IRQ/port settings.
 
-HiSax Support for USR Sportster internal TA
+USR Sportster internal TA
 CONFIG_HISAX_SPORTSTER
   This enables HiSax support for the USR Sportster internal TA card.
 
   See Documentation/isdn/README.HiSax on how to configure it using a
   different D-channel protocol, or non-standard IRQ/port settings.
 
-HiSax Support for MIC card
+MIC card
 CONFIG_HISAX_MIC
   This enables HiSax support for the ITH MIC card. 
 
   See Documentation/isdn/README.HiSax on how to configure it using a
   different D-channel protocol, or non-standard IRQ/port settings.
 
-HiSax Support for NETjet card
+NETjet card
 CONFIG_HISAX_NETJET
   This enables HiSax support for the NetJet from Traverse
   Technologies.
@@ -10394,62 +10459,67 @@
   See Documentation/isdn/README.HiSax on how to configure it using a
   different D-channel protocol, or non-standard IRQ/port settings.
 
-HiSax Support for Niccy PnP/PCI card
+Niccy PnP/PCI card
 CONFIG_HISAX_NICCY
   This enables HiSax support for the Dr. Neuhaus Niccy PnP or PCI. 
 
   See Documentation/isdn/README.HiSax on how to configure it using a
   different D-channel protocol, or non-standard IRQ/port settings.
 
-HiSax Support for Siemens I-Surf card
+Siemens I-Surf card
 CONFIG_HISAX_ISURF
   This enables HiSax support for the Siemens I-Talk/I-Surf card with
   ISAR chip.
   See Documentation/isdn/README.HiSax on how to configure it using a
   different D-channel protocol, or non-standard IRQ/port settings.
 
-HiSax Support for HST Saphir card
+HST Saphir card
 CONFIG_HISAX_HSTSAPHIR
   This enables HiSax support for the HST Saphir card.
   
   See Documentation/isdn/README.HiSax on how to configure it using a
   different D-channel protocol, or non-standard IRQ/port settings.
 
-HiSax Support for Telekom A4T card
+Telekom A4T card
 CONFIG_HISAX_BKM_A4T
   This enables HiSax support for the Telekom A4T card.
   
   See Documentation/isdn/README.HiSax on how to configure it using a
   different D-channel protocol, or non-standard IRQ/port settings.
 
-HiSax Support for Scitel Quadro card
+Scitel Quadro card
 CONFIG_HISAX_SCT_QUADRO
   This enables HiSax support for the Scitel Quadro card.
   
   See Documentation/isdn/README.HiSax on how to configure it using a
   different D-channel protocol, or non-standard IRQ/port settings.
 
-HiSax Support for Gazel cards
+Gazel cards
 CONFIG_HISAX_GAZEL
   This enables HiSax support for the Gazel cards.
 
   See Documentation/isdn/README.HiSax on how to configure it using a
   different D-channel protocol, or non-standard IRQ/port settings.
 
-HiSax Support for HFC PCI-Bus cards
+HFC PCI-Bus cards
 CONFIG_HISAX_HFC_PCI
   This enables HiSax support for the HFC-S PCI 2BDS0 based cards.
   
   For more informations see under Documentation/isdn/README.hfc-pci.
 
-HiSax Support for Winbond W6692 based cards
+Winbond W6692 based cards
 CONFIG_HISAX_W6692
   This enables HiSax support for Winbond W6692 based PCI ISDN cards.
   
   See Documentation/isdn/README.HiSax on how to configure it using a
   different D-channel protocol, or non-standard IRQ/port settings.
 
-HiSax Support for Am7930 (EXPERIMENTAL)
+HFC-S+, HFC-SP, HFC-PCMCIA cards (EXPERIMENTAL)
+CONFIG_HISAX_HFC_SX
+  This enables HiSax support for the HFC-S+, HFC-SP and HFC-PCMCIA cards.
+  This code is not finished yet.
+
+Am7930 (EXPERIMENTAL)
 CONFIG_HISAX_AMD7930
   This enables HiSax support for the AMD7930 chips on some SPARCs.
   This code is not finished yet.
@@ -10584,8 +10654,14 @@
   inserted in and removed from the running kernel whenever you want),
   say M and read Documentation/modules.txt. If unsure, say Y.
 
-#Mostek real time clock support
-#CONFIG_SUN_MOSTEK_RTC
+Mostek real time clock support
+CONFIG_SUN_MOSTEK_RTC
+  The Mostek RTC chip is used on all knows Sun computers except
+  some JavaStation-s. For a JavaStation you need to say Y both here
+  and to CONFIG_RTC.
+
+  Say Y here unless you are building a special purpose kernel.
+
 #
 #Siemens SAB82532 serial support
 #CONFIG_SAB82532
@@ -11200,11 +11276,6 @@
   Choose Y here if you have this FM radio card, and then fill in the 
   port address below.
 
-  If you have GemTeks combined (PnP) sound- and radio card you must use
-  this driver as a module and setup the card with isapnptools. You must
-  also pass the module a suitable io parameter, 0x248 has been reported
-  to be used by these cards.
-
   In order to control your radio card, you will need to use programs
   that are compatible with the Video for Linux API. Information on 
   this API and pointers to "v4l" programs may be found on the WWW at
@@ -11388,6 +11459,12 @@
   Choose Y here if you have this FM radio card, and then fill in the 
   port address below.
 
+  If you have GemTeks combined (PnP) sound- and radio card you might want
+  to use this driver as a module and setup the card with isapnptools. You
+  must also pass the module a suitable io parameter. If you have trouble
+  getting the driver to work with the card as a module, please try building
+  it into the kernel by answering Y.
+
   In order to control your radio card, you will need to use programs
   that are compatible with the Video for Linux API. Information on 
   this API and pointers to "v4l" programs may be found on the WWW at
@@ -11402,8 +11479,9 @@
 
 GemTek i/o port
 CONFIG_RADIO_GEMTEK_PORT
-  Enter either 0x20c, 0x30c, 0x24c or 0x34c here. The card default is
-  0x34c, if you haven't changed the jumper setting on the card.
+  Enter either 0x20c, 0x30c, 0x24c or 0x34c here. 0x20c and 0x248 have
+  been reported to work with the combined sound/radio card. The card
+  default is 0x34c, if you haven't changed the jumper setting on the card.
 
 Trust FM Radio Card
 CONFIG_RADIO_TRUST
@@ -11736,33 +11814,7 @@
   and makes it possible to use all existing applications that
   understands TTY's with an infrared link. Thus you should be able to
   use application like PPP, minicom and others. Enabling this option
-  will create two modules called ircomm and ircomm_tty. For more
-  information go to http://www.pluto.dti.ne.jp/~thiguchi/irda/
-
-IrLPT Protocol
-CONFIG_IRLPT
-  Say Y here if you want to build support for the IrLPT protocol. If
-  you want to compile it as a module, say M here and read
-  Documentation/modules.txt. IrLPT makes it possible to print
-  documents to IrDA capable printers.
-
-IrLPT Client Protocol 
-CONFIG_IRLPT_CLIENT
-  Say Y here if you want to build support for the IrLPT client
-  protocol. If you want to compile it as a module, say M here and read
-  Documentation/modules.txt. The IrLPT client protocol can be used to
-  print documents to IrDA compatible printers like the HP-5MP, or
-  IrLPT printer adapters like the ACTiSYS IR-100M.
-
-IrLPT Server Protocol 
-CONFIG_IRLPT_SERVER
-  Say Y here if you want to build support for the IrLPT server
-  protocol. If you want to compile it as a module, say M here and read
-  Documentation/modules.txt. The IrLPT server protocol makes it
-  possible to use a Linux machine as an infrared printer server for
-  other laptops. So if your Linux machine has a cable connection to a
-  printer, then other laptops can use the Linux machine to print out 
-  documents using infrared communication.
+  will create two modules called ircomm and ircomm-tty.
 
 IrTTY IrDA Device Driver
 CONFIG_IRTTY_SIR
@@ -11799,20 +11851,12 @@
   used for the IrDA chipset in the Corel NetWinder. The driver
   supports SIR, MIR and FIR (4Mbps) speeds.
 
-NSC PC87108 IrDA Device Driver
+NSC IrDA Device Driver
 CONFIG_NSC_FIR
-  Say Y here if you want to build support for the NSC PC87108 IrDA
-  chipset. If you want to compile it as a module, say M here and
-  read Documentation/modules.txt. This drivers currently only supports
-  the ACTiSYS IR2000B ISA card and supports SIR, MIR and FIR (4Mbps)
-  speeds.
-
-Sharp UIRCC IrDA Device Driver
-CONFIG_SHARP_FIR
-  Say Y here if you want to build support for the Sharp UIRCC IrDA
-  chipset. If you want to compile it as a module, say M here and
-  read Documentation/modules.txt. This chipset is used by the Toshiba
-  Tecra laptops.
+  Say Y here if you want to build support for the NSC PC87108 and
+  PC87338 IrDA chipsets. If you want to compile it as a module, say M 
+  here and read Documentation/modules.txt. This driver supports SIR, 
+  MIR and FIR (4Mbps) speeds.
 
 Toshiba Type-O IR Port Device Driver
 CONFIG_TOSHIBA_FIR
@@ -11828,7 +11872,7 @@
   and read Documentation/modules.txt. The ESI dongle attaches to the
   normal 9-pin serial port connector, and can currently only be used
   by IrTTY. To activate support for ESI dongles you will have to
-  insert "irattach -d esi" in the /etc/irda/drivers script.
+  start irattach like this: "irattach -d esi".
 
 ACTiSYS IR-220L and IR220L+ dongle
 CONFIG_ACTISYS_DONGLE
@@ -11837,8 +11881,8 @@
   say M here and read Documentation/modules.txt. The ACTiSYS dongles
   attaches to the normal 9-pin serial port connector, and can
   currently only be used by IrTTY. To activate support for ACTiSYS
-  dongles you will have to insert "irattach -d actisys" or
-  "irattach -d actisys_plus" in the/etc/irda/drivers script.
+  dongles you will have to start irattach like this: 
+  "irattach -d actisys" or "irattach -d actisys+".
 
 Tekram IrMate 210B dongle
 CONFIG_TEKRAM_DONGLE
@@ -11847,7 +11891,7 @@
   and read Documentation/modules.txt. The Tekram dongle attaches to
   the normal 9-pin serial port connector, and can currently only be
   used by IrTTY. To activate support for Tekram dongles you will have
-  to insert "irattach -d tekram" in the /etc/irda/drivers script.
+  to start irattach like this: "irattach -d tekram".
 
 Greenwich GIrBIL dongle
 CONFIG_GIRBIL_DONGLE
@@ -11865,7 +11909,19 @@
   Documentation/modules.txt. The Parallax dongle attaches to the
   normal 9-pin serial port connector, and can currently only be used
   by IrTTY. To activate support for Parallax dongles you will have to
-  insert "irattach -d litelink" in the /etc/irda/drivers script.
+  start irattach like this "irattach -d litelink".
+
+Old Belking dongle
+CONFIG_OLD_BELKING_DONGLE
+  Say Y here if you want to build support for the old Belkin SmartBeam
+  dongle. If you want to compile it as a module, say M here and read
+  Documentation/modules.txt. The Belkin SmartBeam dongle (F5F500) come 
+  in two variants. The only way to distinguish those is to open the 
+  dongle and check the presence of a jumper (the jumper, on the new 
+  dongle, toggle between IrDA and ASK modes). This driver only support 
+  the old dongle. The old dongle is also limited to 9600 b/s (which is 
+  not very fun). To activate support for old Belkin dongles you will 
+  have to start irattach like this: "irattach -d old_dongle".
 
 VME (Motorola and BVM) support
 CONFIG_VME
@@ -12040,6 +12096,33 @@
   If you do not have any Quicknet telephony cards, you can safely
   ignore this option.
  
+CPiA Video For Linux
+CONFIG_VIDEO_CPIA
+  This is the video4linux driver for cameras based on Vision's CPiA
+  (Colour Processor Interface ASIC), such as the Creative Labs Video
+  Blaster Webcam II. If you have one of these cameras, say Y here
+  and select parallel port lowlevel support below (the USB-version,
+  is not supported on this kernel-version) otherwise say N. This will
+  not work with the Creative Webcam III. It is also available as a
+  module (cpia.o).
+
+  For more information (supported camera models, module autoloading, DMA
+  interrupt settings, supported applications, etc.) read
+  Documentation/video4linux/README.cpia.
+
+CPiA Parallel Port Lowlevel Support
+CONFIG_VIDEO_CPIA_PP
+  This is the lowlevel parallel port support for cameras based on
+  Vision's CPiA (Colour Processor Interface ASIC), such as the
+  Creative Webcam II. If you have the parallel port version of one
+  of these cameras, say Y here, otherwise say N. It is also available
+  as a module (cpia_pp.o).
+
+CPiA Parallel Port DMA Support
+CONFIG_VIDEO_CPIA_PP_DMA
+  This will use DMA if possible to reduce CPU usage.  If in doubt,
+  say Y here.
+   
 #
 # A couple of things I keep forgetting:
 #   capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet, 
@@ -12265,6 +12348,6 @@
 # LocalWords:  ACTiSYS Dongle dongle dongles esi actisys IrMate tekram BVM MVME
 # LocalWords:  BVME BVME WRITETHROUGH copyback writethrough fwmark syncookie tu
 # LocalWords:  alphalinux GOBIOS csn chemnitz nat ACARD AMI MegaRAID megaraid
-# LocalWords:  QNXFS ISI isicom xterms Apollos VPN RCPCI rcpci sgi visws pcmcia
+# LocalWords:  QNX4FS ISI isicom xterms Apollos VPN RCPCI rcpci sgi visws pcmcia
 # LocalWords:  IrLPT UIRCC Tecra
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/Documentation/Debugging390.txt linux.15p9/Documentation/Debugging390.txt
--- linux.vanilla/Documentation/Debugging390.txt	Thu Jan  1 01:00:00 1970
+++ linux.15p9/Documentation/Debugging390.txt	Thu Feb 17 13:30:27 2000
@@ -0,0 +1,1941 @@
+              
+                          Debugging on Linux for 390
+			               by
+		Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+		Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation 	       
+                              Best viewed with fixed width fonts 
+
+Overview of Document:
+=====================
+This document is intended to give an good overview of how to debug 
+Linux for S390 it isn't intended as a complete reference & not a
+tutorial on the fundamentals of C & assembly, it dosen't go into
+390 IO in any detail. It is intended to compliment the following
+books.
+Enterprise Systems Architecture/390 Reference Summary SA22-7209-01 & the
+Enterprise Systems Architecture/390 Principles of Operation SA22-7201-05
+& any other worthwhile references you get.
+
+It is intended like the Enterprise Systems Architecture/390 Reference Summary
+to be printed out & used as a quick cheat sheet self help style reference when
+problems occur.
+
+Contents
+========
+S390 Register Set
+Address Spaces on Linux
+Address Spaces on Linux for S390
+The Linux for S390 Kernel Task Structure
+Register Usage & Stackframes on Linux for S390 with glossary
+Compiling programs for debugging on Linux for S390
+Figuring out gcc compile errors
+Debugging Tools
+objdump
+strace
+Debugging under VM
+Stack Tracing under VM
+S390 IO Overview
+Debugging IO on S390 under VM
+GDB on S390
+Stack chaining in gdb by hand
+Examining core dumps
+LDD
+Debugging modules
+The proc file system
+Starting points for debugging scripting languages etc.
+
+S390 Register Set
+================
+The current ESA 390 architecture has the following registers.
+ 
+16 32 bit General propose registers ( r0-r15 or gpr0-gpr15) used for arithmetic & addressing 
+
+16 Control registers ( cr0-cr15 kernel usage only ) used for memory managment,
+interrupt control,debugging control etc.
+
+16 Access registers ( ar0-ar15 ) not used by normal programs but potentially could 
+be used as temporary storage. Their main purpose is their 1 to 1
+association with general purpose registers and are used in
+the kernel for copying data between address spaces.
+
+16 64 bit floating point registers (fp0-fp15 ) IEEE & HFP floating 
+point format compliant on G5 upwards & a Floating point control reg (FPC) 
+4  64 bit registers (fp0,fp2,fp4 & fp6) HFP only on older machines.
+Note:
+Linux (currently) always uses IEEE & emulates G5 IEEE format on older machines,
+( provided the kernel is configured for this ).
+
+
+The PSW is the most important register on the machine it
+is 64 bit & serves the roles of a program counter (pc),
+condition code register,memory space designator.
+In IBM standard notation I am counting bit 0 as the MSB.
+It has several advantages over a normal program counter
+in that you can change address translation & program counter 
+in a single instruction. To change address translation,
+e.g. switching address translation off requires that you
+have a logical=physical mapping for the address you are
+currently running at.
+
+Bit       Value
+
+0         Reserved ( must be 0 ) otherwise specification exception occurs.
+
+1         Program Event Recording 1 PER enabled, 
+	  PER is used to facilititate debugging e.g. single stepping.
+
+2-4       Reserved ( must be 0 ). 
+
+5         Dynamic address translation 1=DAT on.
+
+6         Input/Output interrupt Mask
+
+7         External interrupt Mask used primarily for interprocessor signalling & 
+	  clock interupts.
+
+8-12      PSW Key used for complex memory protection mechanism not used under linux
+
+13        Machine Check Mask 1=enable machine check interrupts
+
+14        Wait State set this to 1 to stop the processor except for interrupts & give 
+	  time to other LPARS used in CPU idle in the kernel to increase overall 
+	  usage of processor resources.
+
+15        Problem state ( if set to 1 certain instructions are disabled )
+	  all linux user programs run with this bit 1 ( useful info for debugging under VM ).
+
+16-17     Address Space Control
+
+	  00 Primary Space Mode when DAT on
+	  The linux kernel currently runs in this mode, CR1 is affiliated with this mode
+	  & points to the primary segment table origin etc.
+
+	  01 Access register mode this mode is used in functions to 
+	  copy data between kernel & user space.
+
+	  10 Secondary space mode not used in linux however CR7 the
+	  register affiliated with this mode is & this & normally
+	  CR13=CR7 to allow us to copy data between kernel & user space.
+	  We do this as follows:
+	  We set ar2 to 0 to designate its
+	  affiliated gpr ( gpr2 )to point to primary=kernel space.
+	  We set ar4 to 1 to designate its
+	  affiliated gpr ( gpr4 ) to point to secondary=home=user space
+	  & then essentially do a memcopy(gpr2,gpr4,size) to
+	  copy data between the address spaces, the reason we use home space for the
+	  kernel & don't keep secondary space free is that code will not run in secondary space.
+
+	  11 Home Space Mode all user programs run in this mode.
+	  it is affiliated with CR13.
+
+18-19     Condition codes (CC)
+
+20	  Fixed point overflow mask if 1=FPU exceptions for this event occur ( normally 0 ) 
+
+21	  Decimal overflow mask if 1=FPU exceptions for this event occur ( normally 0 )
+
+22        Exponent underflow mask if 1=FPU exceptions for this event occur ( normally 0 )
+
+23        Significance Mask if 1=FPU exceptions for this event occur ( normally 0 )
+
+24-31     Reserved Must be 0.
+
+32        1=31 bit addressing mode 0=24 bit addressing mode (for backward compatibility ),
+	  linux always runs with this bit set to 1
+
+33-64     Instruction address.	  
+	  
+Prefix Page
+-----------	  
+This per cpu memory area is too intimately tied to the processor not to mention.
+It exists between the real addresses 0-4096 on the processor & is exchanged 
+with a page in absolute storage by the set prefix instruction in linux'es startup. 
+This page different on each processor.
+Bytes 0-512 ( 200 hex ) are used by the processor itself for holding such
+information as exception indications & entry points for exceptions.
+Bytes after 0xc00 hex are used by linux for per processor globals.
+The closest thing to this on traditional architectures is the interrupt
+vector table. This is a good thing & does simplify some of the kernel coding
+however it means that we now cannot catch stray NULL pointers in the
+kernel without hard coded checks.
+
+
+
+Address Spaces on Linux
+=======================
+
+The traditional Intel Linux is approximately mapped as follows forgive
+the ascii art.
+0xFFFFFFFF 4GB Himem                        *****************
+                                            *               *
+                                            * Kernel Space  *
+                                            *               *
+                                            *****************          ****************
+User Space Himem (typically 0xC0000000 3GB )*  User Stack   *          *              *
+				            *****************          *              *
+					    *  Shared Libs  *          * Next Process *          
+                                            *****************          *     to       *  
+					    *               *    <==   *     Run      *  <==
+					    *  User Program *          *              *
+					    *   Data BSS    *          *              *
+                                            *	 Text       *          *              *
+         			            *   Sections    *          *              *
+0x00000000         			    *****************          ****************
+
+Now it is easy to see that on Intel it is quite easy to recognise a kernel address 
+as being one greater than user space himem ( in this case 0xC0000000).
+& addresses of less than this are the ones in the current running program on this
+processor ( if an smp box ).
+If using the virtual machine ( VM ) as a debugger it is quite difficult to
+know which user process is running as the address space you are looking at
+could be from any process in the run queue.
+Thankfully you normally get lucky as address spaces don't overlap that &
+you can recognise the code at by cross referencing with a dump made by objdump
+( more about that later ).
+
+The limitation of Intels addressing technique is that the linux
+kernel uses a very simple real address to virtual addressing technique
+of Real Address=Virtual Address-User Space Himem.
+This means that on Intel the kernel linux can typically only address
+Himem=0xFFFFFFFF-0xC0000000=1GB & this is all the RAM these machines
+can typically use.
+They can lower User Himem to 2GB or lower & thus be
+able to use 2GB of RAM however this shrinks the maximum size
+of User Space from 3GB to 2GB they have a no win limit of 4GB unless
+they go to 64 Bit.
+
+
+On 390 our limitations & strengths make us slightly different.
+For backward compatibility we are only allowed use 31 bits (2GB)
+of our 32 bit addresses,however, we use entirely separate address 
+spaces for the user & kernel.
+
+This means we can support 2GB of non Extended RAM, & more
+with the Extended memory managment swap device & 64 Bit
+when it comes along.
+
+
+Address Spaces on Linux for S390
+================================
+
+Our addressing scheme is as follows
+
+
+Himem 0x7fffffff 2GB            *****************          ****************
+                                *  User Stack   *          *              *
+				*****************          *              *
+		                *  Shared Libs  *          *              *          
+                                *****************          *              *  
+			        *               *          *    Kernel    *  
+		                *  User Program *          *              *
+		                *   Data BSS    *          *              *
+                                *    Text       *          *              *
+            			*   Sections    *          *              *
+0x00000000                      *****************          ****************
+
+This also means that we need to look at the PSW problem state bit
+or the addressing mode to decide whether we are looking at
+user or kernel space. 
+
+The Linux for S390 Kernel Task Structure
+========================================
+Each process/thread under Linux for S390 has its own kernel task_struct
+defined in linux/include/linux/sched.h
+The S390 on initialisation & resuming of a process on a cpu sets
+the __LC_KERNEL_STACK variable in the spare prefix area for this cpu
+( which we use for per processor globals).
+
+The kernel stack pointer is intimately tied with the task stucture for
+each processor as follows.
+
+            ************************
+            *  1 page kernel stack *
+	    *        ( 4K )        *
+            ************************
+            *   1 page task_struct *        
+            *        ( 4K )        *
+8K aligned  ************************ 
+
+What this means is that we don't need to dedicate any register or global variable
+to point to the current running process & can retrieve it with the following
+very simple construct
+
+static inline struct task_struct * get_current(void)
+{
+        struct task_struct *current;
+        __asm__("lhi   %0,-8192\n\t"
+                "nr    %0,15"
+                : "=r" (current) );
+        return current;
+}
+
+i.e. just anding the current kernel stack pointer with the mask -8192.
+Thankfully because Linux dosen't have support for nested IO interrupts
+& our devices have large buffers can survive interrupts being shut for 
+short amounts of time we don't need a separate stack for interrupts.
+
+
+
+
+Register Usage & Stackframes on Linux for S390
+==============================================
+Overview:
+---------
+This is the code that gcc produces at the top & the bottom of
+each function, it usually is fairly consistent & similar from 
+function to function & if you know its layout you can probalby
+make some headway in finding the ultimate cause of a problem
+after a crash without a source level debugger.
+
+Note: To follow stackframes requires a knowledge of C or Pascal &
+limited knowledge of one assembly language.
+
+Glossary:
+---------
+alloca:
+This is a built in compiler function for runtime allocation
+of extra space on the callers stack which is obviously freed
+up on function exit ( e.g. the caller may choose to allocate nothing
+of a buffer of 4k if required for temporary purposes ), it generates 
+very efficent code ( a few cycles  ) when compared to alternatives 
+like malloc.
+
+automatics: These are local variables on the stack,
+i.e they aren't in registers & they aren't static.
+
+back-chain:
+This is a pointer to the stack pointer before entering a
+framed functions ( see frameless function ) prologue got by 
+deferencing the address of the current stack pointer,
+ i.e. got by accessing the 32 bit value at the stack pointers
+current location.
+
+base-pointer:
+This is a pointer to the back of the literal pool which
+is an area just behind each procedure used to store constants
+in each function.
+
+call-clobbered: The caller probably needs to save these registers if there 
+is something of value in them, on the stack or elsewhere before making a 
+call to another procedure so that it can restore it later.
+
+epilogue:
+The code generated by the compiler to return to the caller.
+
+frameless-function
+A frameless function in Linux for 390 is one which doesn't need 
+more than the 96 bytes given to it by the caller.
+A frameless function never:
+1) Sets up a back chain.
+2) Calls alloca.
+3) Calls other normal functions
+4) Has automatics.
+
+GOT-pointer:
+This is a pointer to the global-offset-table in ELF
+( Executable Linkable Format, Linux'es most common executable format ),
+all globals & shared library objects are found using this pointer.
+
+lazy-binding
+ELF shared libraries are typically only loaded when routines in the shared
+library are actually first called at runtime. This is lazy binding.
+
+procedure-linkage-table
+This is a table found from the GOT which contains pointers to routines
+in other shared libraries which can't be called to by easier means.
+
+prologue:
+The code generated by the compiler to set up the stack frame.
+
+outgoing-args:
+This is extra area allocated on the stack of the calling function if the
+parameters for the callee's cannot all be put in registers, the same
+area can be reused by each function the caller calls.
+
+routine-descriptor:
+A COFF  executable format based concept of a procedure reference 
+actually being 8 bytes or more as opposed to a simple pointer to the routine.
+This is typically defined as follows
+Routine Descriptor offset 0=Pointer to Function
+Routine Descriptor offset 4=Pointer to Table of Contents
+The table of contents/TOC is roughly equivalent to a GOT pointer.
+& it means that shared libraries etc. can be shared between several
+environments each with their own TOC.
+
+ 
+static-chain: This is used in nested functions a concept adopted from pascal 
+by gcc not used in ansi C or C++ ( although quite useful ), basically it
+is a pointer used to reference local variables of enclosing functions.
+You might come across this stuff once or twice in your lifetime.
+
+e.g.
+The function below should return 11 though gcc may get upset & toss warnings 
+about unused variables.
+int FunctionA(int a)
+{
+	int b;
+	FunctionC(int c)
+	{
+		b=c+1;
+	}
+	FunctionC(10);
+	return(b);
+}
+
+
+S390 Register usage
+===================
+r0       used by syscalls/assembly                  call-clobbered
+r1	 used by syscalls/assembly                  call-clobbered
+r2       argument 0 / return value 0                call-clobbered
+r3       argument 1 / return value 1 (if long long) call-clobbered
+r4       argument 2                                 call-clobbered
+r5       argument 3                                 call-clobbered
+r6	 argument 5                                 saved
+r7       pointer-to arguments 5 to ...              saved      
+r8       this & that                                saved
+r9       this & that                                saved
+r10      static-chain ( if nested function )        saved
+r11      frame-pointer ( if function used alloca )  saved
+r12      got-pointer                                saved
+r13      base-pointer                               saved
+r14      return-address                             saved
+r15      stack-pointer                              saved
+
+f0       argument 0 / return value ( float/double ) call-clobbered
+f2       argument 1                                 call-clobbered
+f4                                                  saved
+f6                                                  saved
+The remaining floating points
+f1,f3,f5 f7-f15 are call-clobbered.
+
+Notes:
+------
+1) The only requirement is that registers which are used
+by the callee are saved, e.g. the compiler is perfectly
+capible of using r11 for purposes other than a frame a
+frame pointer if a frame pointer is not needed.
+2) In functions with variable arguments e.g. printf the calling procedure 
+is identical to one without variable arguments & the same number of 
+parameters. However, the prologue of this function is somewhat more
+hairy owing to it having to move these parameters to the stack to
+get va_start, va_arg & va_end to work.
+3) Access registers are currently unused by gcc but are used in
+the kernel. Possibilities exist to use them at the moment for
+temporary storage but it isn't recommended.
+4) Only 4 of the floating point registers are used for
+parameter passing as older machines such as G3 only have only 4
+& it keeps the stack frame compatible with other compilers.
+However with IEEE floating point emulation under linux on the
+older machines you are free to use the other 12.
+5) A long long or double parameter cannot be have the 
+first 4 bytes in a register & the second four bytes in the 
+outgoing args area. It must be purely in the outgoing args
+area if crossing this boundary.
+6) Floating point parameters are mixed with outgoing args
+on the outgoing args area in the order the are passed in as parameters.
+
+Stack Frame Layout
+==================
+0            back chain ( a 0 here signifies end of back chain )
+4            eos ( end of stack, not used on Linux for S390 used in other linkage formats )
+8            glue used in other linkage formats for saved routine descriptors etc.
+12           glue used in other linkage formats for saved routine descriptors etc.
+16           scratch area
+20           scratch area
+24           saved r6 of caller function
+28           saved r7 of caller function
+32           saved r8 of caller function
+36           saved r9 of caller function
+40           saved r10 of caller function
+44           saved r11 of caller function
+48           saved r12 of caller function
+52           saved r13 of caller function
+56           saved r14 of caller function
+60           saved r15 of caller function
+64           saved f4 of caller function
+72           saved f6 of caller function
+80           undefined
+96           outgoing args passed from caller to callee
+96+x         possible stack alignment ( 8 bytes desirable )
+96+x+y       alloca space of caller ( if used )
+96+x+y+z     automatics of caller ( if used )
+0            back-chain
+
+A sample program with comments.
+===============================
+
+Comments on the function test
+-----------------------------
+1) It didn't need to set up a pointer to the constant pool gpr13 as it isn't used
+( :-( ).
+2) This is a frameless function & no stack is bought.
+3) The compiler was clever enough to recognise that it could return the
+value in r2 as well as use it for the passed in parameter ( :-) ).
+4) The basr ( branch relative & save ) trick works as follows the instruction 
+has a special case with r0,r0 with some instruction operands is understood as 
+the literal value 0, some risc architectures also do this ). So now
+we are branching to the next address & the address new program counter is
+in r13,so now we subtract the size of the function prologue we have executed
++ the size of the literal pool to get to the top of the literal pool
+0040037c int test(int b)
+{                                                          # Function prologue below
+  40037c:	90 de f0 34 	stm	%r13,%r14,52(%r15) # Save registers r13 & r14
+  400380:	0d d0       	basr	%r13,%r0           # Set up pointer to constant pool using
+  400382:	a7 da ff fa 	ahi	%r13,-6            # basr trick
+	return(5+b);
+	                                                   # Huge main program
+  400386:	a7 2a 00 05 	ahi	%r2,5              # add 5 to r2
+
+                                                           # Function epilogue below 
+  40038a:	98 de f0 34 	lm	%r13,%r14,52(%r15) # restore registers r13 & 14
+  40038e:	07 fe       	br	%r14               # return
+}
+
+Comments on the function main
+-----------------------------
+1) The compiler did this function optimally ( 8-) )
+
+Literal pool for main.
+400390:	ff ff ff ec 	.long 0xffffffec
+main(int argc,char *argv[])
+{                                                          # Function prologue below
+  400394:	90 bf f0 2c 	stm	%r11,%r15,44(%r15) # Save necessary registers
+  400398:	18 0f       	lr	%r0,%r15           # copy stack pointer to r0
+  40039a:	a7 fa ff a0 	ahi	%r15,-96           # Make area for callee saving 
+  40039e:	0d d0       	basr	%r13,%r0           # Set up r13 to point to
+  4003a0:	a7 da ff f0 	ahi	%r13,-16           # literal pool
+  4003a4:	50 00 f0 00 	st	%r0,0(%r15)        # Save backchain
+
+	return(test(5));                                   # Main Program Below
+  4003a8:	58 e0 d0 00 	l	%r14,0(%r13)       # load relative address of test from
+						           # literal pool
+  4003ac:	a7 28 00 05 	lhi	%r2,5              # Set first parameter to 5
+  4003b0:	4d ee d0 00 	bas	%r14,0(%r14,%r13)  # jump to test setting r14 as return
+							   # address using branch & save instruction.
+
+							   # Function Epilogue below
+  4003b4:	98 bf f0 8c 	lm	%r11,%r15,140(%r15)# Restore necessary registers.
+  4003b8:	07 fe       	br	%r14               # return to do program exit 
+}
+
+
+Compiling programs for debugging on Linux for S390
+==================================================
+Make sure that the gcc is compiling & linking with the -g flag on.
+This is typically done adding/appending the flags -g to the 
+CFLAGS & LDFLAGS variables Makefile of the program concerned.
+
+If using gdb & you would like accurate displays of registers &
+ stack traces compile without optimisation i.e make sure
+that there is no -O2 or similar on the CFLAGS line of the Makefile &
+the emitted gcc commands, obviously this will produce worse code 
+( not advisable for shipment ) but it is an  aid to the debugging process.
+
+This aids debugging because the compiler will copy parameters passed in
+in registers onto the stack so backtracing & looking at passed in
+parameters will work, however some larger programs which use inline functions
+will not compile without optimisation.
+
+Figuring out gcc compile errors
+===============================
+If you are getting a lot of syntax errors compiling a program & the problem
+isn't blatantly obvious from the source.
+It often helps to just preprocess the file, this is done with the -E
+option in gcc.
+What this does is that it runs through the very first phase of compilation
+( compilation in gcc is done in several stages & gcc calls many programs to
+achieve its end result ) with the -E option gcc just calls the gcc preprocessor (cpp).
+The c preprocessor does the following, it joins all the files #included together
+recursively ( #include files can #include other files ) & also the c file you wish to compile.
+It puts a fully qualified path of the #included files in a comment & it
+does macro expansion.
+This is useful for debugging because
+1) You can double check whether the files you expect to be included are the ones
+that are being included ( e.g. double check that you aren't going to the i386 asm directory ).
+2) Check that macro definitions aren't clashing with typedefs,
+3) Check that definitons aren't being used before they are being included.
+4) Helps put the line emitting the error under the microscope if it contains macros.
+
+For convenience the Linux kernel's makefile will do preprocessing automatically for you
+by suffixing the file you want built with .i ( instead of .o )
+
+e.g.
+from the linux directory type
+make arch/s390/kernel/signal.i
+this will build
+
+s390-gcc -D__KERNEL__ -I/home1/barrow/linux/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
+-fno-strict-aliasing -D__SMP__ -pipe -fno-strength-reduce   -E arch/s390/kernel/signal.c
+> arch/s390/kernel/signal.i  
+
+Now look at signal.i you should see something like.
+
+
+# 1 "/home1/barrow/linux/include/asm/types.h" 1
+typedef unsigned short umode_t;
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+If instead you are getting errors further down e.g.
+unknown instruction:2515 "move.l" or better still unknown instruction:2515 
+"Fixme not implemented yet, call Martin" you are probably are attempting to compile some code 
+meant for another architecture or code that is simply not implemented, with a fixme statement
+stuck into the inline assembly code so that the author of the file now knows he has work to do.
+To look at the assembly emitted by gcc just before it is about to call gas ( the gnu assembler )
+use the -S option.
+Again for your convenience the Linux kernel's Makefile will hold your hand &
+do all this donkey work for you also by building the file with the .s suffix.
+e.g.
+from the Linux directory type 
+make arch/s390/kernel/signal.s 
+
+s390-gcc -D__KERNEL__ -I/home1/barrow/linux/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
+-fno-strict-aliasing -D__SMP__ -pipe -fno-strength-reduce  -S arch/s390/kernel/signal.c 
+-o arch/s390/kernel/signal.s  
+
+
+This will output something like, ( please note the constant pool & the useful comments
+in the prologue to give you a hand at interpreting it ).
+
+.LC54:
+	.string	"misaligned (__u16 *) in __xchg\n"
+.LC57:
+	.string	"misaligned (__u32 *) in __xchg\n"
+.L$PG1: # Pool sys_sigsuspend
+.LC192:
+	.long	-262401
+.LC193:
+	.long	-1
+.LC194:
+	.long	schedule-.L$PG1
+.LC195:
+	.long	do_signal-.L$PG1
+	.align 4
+.globl sys_sigsuspend
+	.type	 sys_sigsuspend,@function
+sys_sigsuspend:
+#	leaf function           0
+#	automatics              16
+#	outgoing args           0
+#	need frame pointer      0
+#	call alloca             0
+#	has varargs             0
+#	incoming args (stack)   0
+#	function length         168
+	STM	8,15,32(15)
+	LR	0,15
+	AHI	15,-112
+	BASR	13,0
+.L$CO1:	AHI	13,.L$PG1-.L$CO1
+	ST	0,0(15)
+	LR    8,2
+	N     5,.LC192-.L$PG1(13) 
+
+Debugging Tools:
+================
+
+objdump
+=======
+This is a tool with many options the most useful being ( if compiled with -g).
+objdump --source <victim program or object file> > <victims debug listing >
+
+
+The whole kernel can be compiled like this ( Doing this will make a 17MB kernel
+& a 200 MB listing ) however you have to strip it before building the image
+using the strip command to make it a more reasonable size to boot it.
+
+A source/assembly mixed dump of the kernel can be done with the line
+objdump --source vmlinux > vmlinux.lst
+Also if the file isn't compiled -g this will output as much debugging information
+as it can ( e.g. function names ), however, this is very slow as it spends lots
+of time searching for debugging info, the following self explanitory line should be used 
+instead if the code isn't compiled -g.
+objdump --disassemble-all --syms vmlinux > vmlinux.lst  
+as it is much faster
+
+As hard drive space is valuble most of us use the following approach.
+1) Look at the emitted psw on the console to find the crash address in the kernel.
+2) Look at the file System.map ( in the linux directory ) produced when building 
+the kernel to find the closest address less than the current PSW to find the
+offending function.
+3) use grep or similar to search the source tree looking for the source file
+ with this function if you don't know where it is.
+4) rebuild this object file with -g on, as an example suppose the file was
+( /arch/s390/kernel/signal.o ) 
+5) Assuming the file with the erroneous function is signal.c Move to the base of the 
+Linux source tree
+6) rm /arch/s390/kernel/signal.o
+7) make /arch/s390/kernel/signal.o
+8) watch the gcc command line emitted
+9) type it in again or alernatively cut & paste it on the console adding the -g option.
+10) objdump --source arch/s390/kernel/signal.o > signal.lst
+This will output the source & the assembly intermixed, as the snippet below shows
+This will unfortunately output addresses which aren't the same
+as the kernel ones you should be able to get around the mental arithmetic
+by playing with the --adjust-vma parameter to objdump.
+
+extern inline void spin_lock(spinlock_t *lp)
+{
+      a0:       18 34           lr      %r3,%r4
+      a2:       a7 3a 03 bc     ahi     %r3,956
+        __asm__ __volatile("    lhi   1,-1\n"
+      a6:       a7 18 ff ff     lhi     %r1,-1
+      aa:       1f 00           slr     %r0,%r0
+      ac:       ba 01 30 00     cs      %r0,%r1,0(%r3)
+      b0:       a7 44 ff fd     jm      aa <sys_sigsuspend+0x2e>
+        saveset = current->blocked;
+      b4:       d2 07 f0 68     mvc     104(8,%r15),972(%r4)
+      b8:       43 cc
+        return (set->sig[0] & mask) != 0;
+} 
+
+6) If debugging under VM go down to that section in the document for more info.
+
+
+strace:
+-------
+Q. What is it ?
+A. It is a tool for intercepting calls to the kernel & logging them
+to a file & on the screen.
+
+Q. What use is it ?
+A. You can used it to find out what files a particular program opens.
+
+
+
+Example 1
+---------
+If you wanted to know does ping work but didn't have the source 
+strace ping -c 1 127.0.0.1  
+& then look at the man pages for each of the syscalls below,
+( In fact this is sometimes easier than looking at some spagetti
+source which conditionally compiles for several architectures )
+Not everything that it throws out needs to make sense immeadiately
+
+Just looking quickly you can see that it is making up a RAW socket
+for the ICMP protocol.
+Doing an alarm(10) for a 10 second timeout
+& doing a gettimeofday call before & after each read to see 
+how long the replies took, & writing some text to stdout so the user
+has an idea what is going on.
+
+socket(PF_INET, SOCK_RAW, IPPROTO_ICMP) = 3
+getuid()                                = 0
+setuid(0)                               = 0
+stat("/usr/share/locale/C/libc.cat", 0xbffff134) = -1 ENOENT (No such file or directory)
+stat("/usr/share/locale/libc/C", 0xbffff134) = -1 ENOENT (No such file or directory)
+stat("/usr/local/share/locale/C/libc.cat", 0xbffff134) = -1 ENOENT (No such file or directory)
+getpid()                                = 353
+setsockopt(3, SOL_SOCKET, SO_BROADCAST, [1], 4) = 0
+setsockopt(3, SOL_SOCKET, SO_RCVBUF, [49152], 4) = 0
+fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(3, 1), ...}) = 0
+mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40008000
+ioctl(1, TCGETS, {B9600 opost isig icanon echo ...}) = 0
+write(1, "PING 127.0.0.1 (127.0.0.1): 56 d"..., 42PING 127.0.0.1 (127.0.0.1): 56 data bytes
+) = 42
+sigaction(SIGINT, {0x8049ba0, [], SA_RESTART}, {SIG_DFL}) = 0 
+sigaction(SIGALRM, {0x8049600, [], SA_RESTART}, {SIG_DFL}) = 0
+gettimeofday({948904719, 138951}, NULL) = 0
+sendto(3, "\10\0D\201a\1\0\0\17#\2178\307\36"..., 64, 0, {sin_family=AF_INET,
+sin_port=htons(0), sin_addr=inet_addr("127.0.0.1")}, 16) = 64
+sigaction(SIGALRM, {0x8049600, [], SA_RESTART}, {0x8049600, [], SA_RESTART}) = 0
+sigaction(SIGALRM, {0x8049ba0, [], SA_RESTART}, {0x8049600, [], SA_RESTART}) = 0
+alarm(10)                               = 0
+recvfrom(3, "E\0\0T\0005\0\0@\1|r\177\0\0\1\177"..., 192, 0, 
+{sin_family=AF_INET, sin_port=htons(50882), sin_addr=inet_addr("127.0.0.1")}, [16]) = 84
+gettimeofday({948904719, 160224}, NULL) = 0
+recvfrom(3, "E\0\0T\0006\0\0\377\1\275p\177\0"..., 192, 0, 
+{sin_family=AF_INET, sin_port=htons(50882), sin_addr=inet_addr("127.0.0.1")}, [16]) = 84
+gettimeofday({948904719, 166952}, NULL) = 0
+write(1, "64 bytes from 127.0.0.1: icmp_se"..., 
+5764 bytes from 127.0.0.1: icmp_seq=0 ttl=255 time=28.0 ms
+
+Example 2
+---------
+strace passwd 2>&1 | grep open
+produces the following output
+open("/etc/ld.so.cache", O_RDONLY)      = 3
+open("/opt/kde/lib/libc.so.5", O_RDONLY) = -1 ENOENT (No such file or directory)
+open("/lib/libc.so.5", O_RDONLY)        = 3
+open("/dev", O_RDONLY)                  = 3
+open("/var/run/utmp", O_RDONLY)         = 3
+open("/etc/passwd", O_RDONLY)           = 3
+open("/etc/shadow", O_RDONLY)           = 3
+open("/etc/login.defs", O_RDONLY)       = 4
+open("/dev/tty", O_RDONLY)              = 4 
+
+The 2>&1 is done to redirect stderr to stdout & grep is then filtering this input 
+through the pipe for each line containing the string open.
+
+
+Example 3
+---------
+Getting sophistocated
+telnetd crashes on & I don't know why
+Steps
+-----
+1) Replace the following line in /etc/inetd.conf
+telnet  stream  tcp     nowait  root    /usr/sbin/in.telnetd -h 
+with
+telnet  stream  tcp     nowait  root    /blah
+
+2) Create the file /blah with the following contents to start tracing telnetd 
+#!/bin/bash
+/usr/bin/strace -o/t1 -f /usr/sbin/in.telnetd -h 
+3) chmod 700 /blah to make it executable only to root
+4)
+killall -HUP inetd
+or ps aux | grep inetd
+get inetd's process id
+& kill -HUP inetd to restart it.
+
+Important options
+-----------------
+-o is used to tell strace to output to a file in our case t1 in the root directory
+-f is to follow children i.e.
+e.g in our case above telnetd will start the login process & subsequently a shell like bash.
+You will be able to tell which is which from the process ID's listed on the left hand side
+of the strace output.
+-p<pid> will tell strace to attach to a running process, yup this can be done provided
+ it isn't being traced or debugged already & you have enough privileges,
+the reason 2 processes cannot trace or debug the same program is that strace
+becomes the parent process of the one being debugged & processes ( unlike people )
+can have only one parent.
+
+
+However the file /t1 will get big quite quickly
+to test it telnet 127.0.0.1
+
+now look at what files in.telnetd execve'd
+413   execve("/usr/sbin/in.telnetd", ["/usr/sbin/in.telnetd", "-h"], [/* 17 vars */]) = 0
+414   execve("/bin/login", ["/bin/login", "-h", "localhost", "-p"], [/* 2 vars */]) = 0 
+
+Whey it worked!.
+
+
+Other hints:
+------------
+If the program is not very interactive ( i.e. not much keyboard input )
+& is crashing in one architecture but not in another you can do 
+an strace of both programs under as identical a scenario as you can
+on both architectures outputting to a file then.
+do a diff of the two traces using the diff program
+i.e.
+diff output1 output2
+& maybe you'll be able to see where the call paths differed, this
+is possibly near the cause of the crash. 
+
+More info
+---------
+Look at man pages for strace & the various syscalls
+e.g. man strace, man alarm, man socket.
+
+
+Debugging under VM
+==================
+
+Notes
+-----
+Addresses & values in the VM debugger are always hex never decimal
+Address ranges are of the format <HexValue1>-<HexValue2> or <HexValue1>.<HexValue2> 
+e.g. The address range  0x2000 to 0x3000 can be described described as
+2000-3000 or 2000.1000
+
+The VM Debugger is case insensitive.
+
+VM's strengths are usually other debuggers weaknesses you can get at any resource
+no matter how sensitive e.g. memory managment resources,change address translation
+in the PSW. For kernel hacking you will reap dividends if you get good at it.
+
+The VM Debugger displays operators but not operands, probably because some
+of it was written when memory was expensive & the programmer was probably proud that
+it fitted into 2k of memory & the programmers & didn't want to shock hardcore VM'ers by
+changing the interface :-), also the debugger displays useful information on the same line & 
+the author of the code probably felt that it was a good idea not to go over 
+the 80 columns on the screen. 
+
+As some of you are probably in a panic now this isn't as unintuitive as it may seem
+as the 390 instructions are easy to decode mentally & you can make a good guess at a lot 
+of them as all the operands are nibble ( half byte aligned ) & if you have an objdump listing
+also it is quite easy to follow, if you don't have an objdump listing keep a copy of
+the ESA Reference Summary & look at between pages 2 & 7 or alternatively the
+ESA principles of operation.
+e.g. even I can guess that 
+0001AFF8' LR    180F        CC 0
+is a ( load register ) lr r0,r15 
+
+Also it is very easy to tell the length of a 390 instruction from the 2 most significant
+bits in the instruction ( not that this info is really useful except if you are trying to
+make sense of a hexdump of code ).
+Here is a table
+Bits                    Instruction Length
+------------------------------------------
+00                          2 Bytes
+01                          4 Bytes
+10                          4 Bytes
+11                          6 Bytes
+
+
+
+
+The debugger also displays other useful info on the same line such as the
+addresses being operated on destination addresses of branches & condition codes.
+e.g.  
+00019736' AHI   A7DAFF0E    CC 1
+000198BA' BRC   A7840004 -> 000198C2'   CC 0
+000198CE' STM   900EF068 >> 0FA95E78    CC 2
+
+
+
+Useful VM debugger commands
+===========================
+
+I suppose I'd better mention this before I start
+to list the current active traces do 
+Q TR
+there can be a maximum of 255 of these per set
+( more about trace sets later ).
+To stop traces issue a
+TR END.
+To delete a particular breakpoint issue
+TR DEL <breakpoint number>
+
+The PA1 key drops to CP mode so you can issue debugger commands,
+Doing alt c (on my 3270 console at least ) clears the screen. 
+hitting b <enter> comes back to the running operating system
+from cp mode ( in our case linux ).
+It is typically useful to add shortcuts to your profile.exec file
+if you have one ( this is roughly equivalent to autoexec.bat in DOS ).
+file here are a few from mine.
+/* this gives me command history on issuing f12 */
+set pf12 retrieve 
+/* this continues */
+set pf8 imm b
+/* goes to trace set a */
+set pf1 imm tr goto a
+/* goes to trace set b */
+set pf2 imm tr goto b
+/* goes to trace set c */
+set pf3 imm tr goto c
+
+
+
+Instruction Tracing
+-------------------
+Setting a simple breakpoint
+TR I PSWA <address>
+To debug a particular function try
+TR I R <function address range>
+TR I on its own will single step.
+TR I DATA <MNEMONIC> <OPTIONAL RANGE> will trace for particular mnemonics
+e.g.
+TR I DATA 4D R 0197BC.4000
+will trace for BAS'es ( opcode 4D ) in the range 0197BC.4000
+if you were inclined you could add traces for all branch instructions &
+suffix them with the run prefix so you would have a backtrace on screen 
+when a program crashes.
+TR BR <INTO OR FROM> will trace branches into or out of an address.
+e.g.
+TR BR INTO 0 is often quite useful if a program is getting awkward & deciding
+to branch to 0 & crashing as this will stop at the address before in jumps to 0.
+
+
+
+Displaying & modifying Registers
+--------------------------------
+D G will display all the gprs
+D X will display all the control registers
+D AR will display all the access registers
+D AR4-7 will display access registers 4 to 7
+CPU ALL D G will display the GRPS of all CPUS in the configuration
+D PSW will display the current PSW
+st PSW 2000 will put the value 2000 into the PSW &
+cause crash your machine.
+D PREFIX
+
+
+Displaying Memory
+-----------------
+To display memory mapped using the current PSW's mapping try
+D <range>
+To make VM display a message each time it hits a particular address & continue try
+D I<range> will disassemble/display a range of instructions.
+ST addr 32 bit word will store a 32 bit aligned address
+D T<range> will display the EBCDIC in an address ( if you are that way inclined )
+D R<range> will display real addresses ( without DAT ) but with prefixing.
+There are other complex options to display if you need to get at say home space
+but are in primary space the easiest thing to do is to temporarily
+modify the PSW to the other addressing mode, display the stuff & then
+restore it. 
+ 
+Hints
+-----
+If you want to issue a debugger command without halting your virtual machine with the
+PA1 key try prefixing the command with #CP e.g.
+#cp tr i pswa 2000
+also suffixing most debugger commands with RUN will cause them not
+to stop just display the mnemonic at the current instruction on the console.
+If you have several breakpoints you want to put into your program &
+you get fed up of cross referencing with System.map
+you can do the following trick for several symbols.
+grep do_signal System.map 
+which emits the following among other things
+0001f4e0 T do_signal 
+now you can do
+TR I PSWA 0001f4e0 cmd msg * do_signal
+This sends a message to your own console each time do_signal is entered.
+( As an aside I wrote a perl script once which automatically generated a REXX
+script with breakpoints on every kernel procedure, this isn't a good idea
+because there are thousands of these routines & VM can only set 255 breakpoints
+at a time so you nearly had to spend as long pruning the file down as you would 
+entering the msg's by hand ),however, the trick might be useful for a single object file.
+
+
+Tracing Program Exceptions
+--------------------------
+If you get a crash which says something like
+illegal operation or specification exception followed by a register dump
+You can restart linux & trace these using the tr prog <range or value> trace option.
+
+The most common ones you will normally be tracing for is
+1=operation exception
+2=privileged operation exception
+4=protection exception
+5=addressing exception
+6=specification exception
+10=segment translation exception
+11=page translation exception
+
+The full list of these is on page 22 of the current ESA Reference Summary.
+e.g.
+tr prog 10 will trace segment translation exceptions.
+tr prog on its own will trace all program interruption codes.
+
+Trace Sets
+----------
+On starting VM you are initially in the INITIAL trace set.
+You can do a Q TR to verify this.
+If you have a complex tracing situation where you wish to wait for instance 
+till a driver is open before you start tracing IO, but know in your
+heart that you are going to have to make several runs through the code till you
+have a clue whats going on. 
+
+What you can do is
+TR I PSWA <Driver open address>
+hit b to continue till breakpoint
+reach the breakpoint
+now do your
+TR GOTO B 
+TR IO 7c08-7c09 or whatever & trace tour IO
+to got back to the initial trace set do
+TR GOTO INITIAL
+& the TR I PSWA <Driver open address> will be the only active breakpoint again.
+
+
+Tracing linux syscalls under VM
+-------------------------------
+Syscalls are implemented on Linux for S390 by the Supervisor call instruction (SVC) there 256 
+possibilities of these as the instruction is made up of a  0xA opcode & the second byte being
+the syscall number. They are traced using the simple command.
+TR SVC  <Optional value or range>
+the syscalls are defined in linux/include/asm-s390/unistd.h
+e.g. to trace all file opens just do
+TR SVC 5 ( as this is the syscall number of open )
+
+
+SMP Specific commands
+---------------------
+To find out how many cpus you have
+Q CPUS displays all the CPU's available to your virtual machine
+To find the cpu that the current cpu VM debugger commands are being directed at do
+Q CPU to change the current cpu cpu VM debugger commands are being directed at do
+CPU <desired cpu no>
+
+On a SMP guest issue a command to all CPUs try prefixing the command with cpu all.
+To issue a command to a particular cpu try cpu <cpu number> e.g.
+CPU 01 TR I R 2000.3000
+If you are running on a guest with several cpus & you have a IO related problem
+& cannot follow the flow of code but you know it isnt smp related.
+from the bash prompt issue
+shutdown -h now or halt.
+do a Q CPUS to find out how many cpus you have
+detach each one of them from cp except cpu 0 
+by issueing a 
+DETACH CPU 01-(number of cpus in configuration)
+& reboot linux.
+TR SIGP will trace inter processor signal processor instructions.
+
+
+Help for displaying ascii textstrings
+-------------------------------------
+As textstrings are cannot be displayed in ASCII under the VM debugger ( I love EBDIC too ) I have 
+written this little program which will convert a command line of hex digits to ascii text
+which can be compiled under linux & you can copy the hex digits from your x3270 terminal to
+your xterm if you are debugging from a linuxbox.
+
+This is quite useful when looking at a parameter passed in as a text string
+under VM ( unless you are good at decoding ASCII in your head ).
+
+e.g. consider tracing an open syscall
+TR SVC 5
+We have stopped at a breakpoint
+000151B0' SVC   0A05     -> 0001909A'   CC 0
+
+D 20.8 to check the SVC old psw in the prefix area & see was it from userspace
+( for the layout of the prefix area consult P18 of the ESA 390 Reference Summary 
+if you have it available ).
+V00000020  070C2000 800151B2
+The problem state bit wasn't set &  it's also too early in the boot sequence
+for it to be a userspace SVC if it was we would have to temporarily switch the 
+psw to user space addressing so we could get at the first parameter of the open in
+gpr2.
+Next do a 
+D G2
+GPR  2 =  00014CB4
+Now display what gpr2 is pointing to
+D 00014CB4.20
+V00014CB4  2F646576 2F636F6E 736F6C65 00001BF5
+V00014CC4  FC00014C B4001001 E0001000 B8070707
+Now copy the text till the first 00 hex ( which is the end of the string
+to an xterm & do hex2ascii on it.
+hex2ascii 2F646576 2F636F6E 736F6C65 00 
+outputs
+Decoded Hex:=/ d e v / c o n s o l e 0x00 
+We were opening the console device,
+
+You can compile the code below yourself for practice :-),
+/*
+ *    hex2ascii.c
+ *    a useful little tool for converting a hexadecimal command line to ascii
+ *
+ *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ *    (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation.
+ */   
+#include <stdio.h>
+
+int main(int argc,char *argv[])
+{
+  int cnt1,cnt2,len,toggle=0;
+  int startcnt=1;
+  unsigned char c,hex;
+  
+  if(argc>1&&(strcmp(argv[1],"-a")==0))
+     startcnt=2;
+  printf("Decoded Hex:=");
+  for(cnt1=startcnt;cnt1<argc;cnt1++)
+  {
+    len=strlen(argv[cnt1]);
+    for(cnt2=0;cnt2<len;cnt2++)
+    {
+       c=argv[cnt1][cnt2];
+       if(c>='0'&&c<='9')
+	  c=c-'0';
+       if(c>='A'&&c<='F')
+	  c=c-'A'+10;
+       if(c>='a'&&c<='F')
+	  c=c-'a'+10;
+       switch(toggle)
+       {
+	  case 0:
+	     hex=c<<4;
+	     toggle=1;
+	  break;
+	  case 1:
+	     hex+=c;
+	     if(hex<32||hex>127)
+	     {
+		if(startcnt==1)
+		   printf("0x%02X ",(int)hex);
+		else
+		   printf(".");
+	     }
+	     else
+	     {
+	       printf("%c",hex);
+	       if(startcnt==1)
+		  printf(" ");
+	     }
+	     toggle=0;
+	  break;
+       }
+    }
+  }
+  printf("\n");
+}
+
+Stack tracing under VM
+----------------------
+A basic backtrace
+-----------------
+
+Here are the tricks I use 9 out of 10 times it works pretty well,
+
+When your backchain reaches a dead end
+--------------------------------------
+This can happen when an exception happens in the kernel & the kernel is entered twice
+if you reach the NULL pointer at the end of the back chain you should be
+able to sniff further back if you follow the following tricks.
+1) A kernel address should be easy to recognise since it is in
+primary space & the problem state bit isn't set & also
+The Hi bit of the address is set.
+2) Another backchain should also be easy to recognise since it is an 
+address pointing to another address approximately 100 bytes or 0x70 hex
+behind the current stackpointer.
+
+
+Here is some practice.
+boot the kernel & hit PA1 at some random time
+d g to display the gprs, this should display something like
+GPR  0 =  00000001  00156018  0014359C  00000000
+GPR  4 =  00000001  001B8888  000003E0  00000000
+GPR  8 =  00100080  00100084  00000000  000FE000
+GPR 12 =  00010400  8001B2DC  8001B36A  000FFED8
+Note that GPR14 is a return address but as we are real men we are going to
+trace the stack.
+display 0x40 bytes after the stack pointer.
+
+V000FFED8  000FFF38 8001B838 80014C8E 000FFF38
+V000FFEE8  00000000 00000000 000003E0 00000000
+V000FFEF8  00100080 00100084 00000000 000FE000
+V000FFF08  00010400 8001B2DC 8001B36A 000FFED8
+
+
+Ah now look at whats in sp+56 (sp+0x38) this is 8001B36A our saved r14 if
+you look above at our stackframe & also agrees with GPR14.
+
+now backchain 
+d 000FFF38.40
+we now are taking the contents of SP to get our first backchain.
+
+V000FFF38  000FFFA0 00000000 00014995 00147094
+V000FFF48  00147090 001470A0 000003E0 00000000
+V000FFF58  00100080 00100084 00000000 001BF1D0
+V000FFF68  00010400 800149BA 80014CA6 000FFF38
+
+This displays a 2nd return address of 80014CA6
+
+now do d 000FFFA0.40 for our 3rd backchain
+
+V000FFFA0  04B52002 0001107F 00000000 00000000
+V000FFFB0  00000000 00000000 FF000000 0001107F
+V000FFFC0  00000000 00000000 00000000 00000000
+V000FFFD0  00010400 80010802 8001085A 000FFFA0
+
+
+our 3rd return address is 8001085A
+
+as the 04B52002 looks suspiciously like rubbish it is fair to assume that the kernel entry routines
+for the sake of optimisation dont set up a backchain.
+
+now look at System.map to see if the addresses make any sense.
+
+grep -i 0001b3 System.map
+outputs among other things
+0001b304 T cpu_idle 
+so 8001B36A
+is cpu_idle+0x66 ( quiet the cpu is asleep, don't wake it )
+
+
+grep -i 00014 System.map 
+produces among other things
+00014a78 T start_kernel  
+so 0014CA6 is start_kernel+some hex number I can't add in my head.
+
+grep -i 00108 System.map 
+this produces
+00010800 T _stext
+so   8001085A is _stext+0x5a
+
+Congrats you've done your first backchain.
+
+
+
+S390 IO Overview
+================
+
+I am not going to give a course in 390 IO architecture as this would take me quite a
+while & I'm no expert. Instead I'll give a 390 IO architecture summary for Dummies if you have 
+the ESA principles of operation available read this instead. If nothing else you may find a few 
+useful keywords in here & be able to use them on a web search engine like altavista to find 
+more useful information.
+
+Unlike other bus architectures modern 390 systems do their IO using mostly
+fibre optics & devices such as tapes & disks can be shared between several mainframes,
+also S390 can support upto 65536 devices while a high end PC based system might be choking 
+with around 64. Here is some of the common IO terminology
+
+Subchannel:
+This is the logical number most IO commands use to talk to an IO device there can be upto
+0x10000 (65536) of these in a configuration typically there is a few hundred. Under VM
+for simplicity they are allocated contiguously, however on the native hardware they are not
+they typically stay consistent between boots provided no new hardware is inserted or removed.
+Under Linux for 390 we use these as IRQ's & also when issuing an IO command (CLEAR SUBCHANNEL,
+HALT SUBCHANNEL,MODIFY SUBCHANNEL,RESUME SUBCHANNEL,START SUBCHANNEL,STORE SUBCHANNEL & 
+TEST SUBCHANNEL ) we use this as the ID of the device we wish to talk to, the most
+important of these instructions are START SUBCHANNEL ( to start IO ), TEST SUBCHANNEL ( to check
+whether the IO completed successfully ), & HALT SUBCHANNEL ( to kill IO ), a subchannel
+can have up to 8 channel paths to a device this offers redunancy if one is not available.
+
+
+Device Number:
+This number remains static & Is closely tied to the hardware, there are 65536 of these
+also they are made up of a CHPID ( Channel Path ID, the most significant 8 bits ) 
+& another lsb 8 bits. These remain static even if more devices are inserted or removed
+from the hardware, there is a 1 to 1 mapping between Subchannels & Device Numbers provided
+devices arent inserted or removed.
+
+Channel Control Words:
+CCWS are linked lists of instructions initially pointed to by an operation request block (ORB),
+which is initially given to Start Subchannel (SSCH) command along with the subchannel number
+for the IO subsystem to process while the CPU continues executing normal code.
+These come in two flavours, Format 0 ( 24 bit for backward )
+compatibility & Format 1 ( 31 bit ). These are typically used to issue read & write 
+( & many other instructions ) they consist of a length field & an absolute address field.
+For each IO typically get 1 or 2 interrupts one for channel end ( primary status ) when the
+channel is idle & the second for device end ( secondary status ) sometimes you get both
+concurrently, you check how the IO went on by issueing a TEST SUBCHANNEL at each interrupt,
+from which you receive an Interruption response block (IRB). If you get channel & device end 
+status in the IRB without channel checks etc. your IO probably went okay. If you didn't you
+probably need a doctorto examine the IRB & extended status word etc.
+If an error occurs more sophistocated control units have a facitity known as
+concurrent sense this means that if an error occurs Extended sense information will
+be presented in the Extended status word in the IRB if not you have to issue a
+subsequent SENSE CCW command after the test subchannel. 
+
+
+TPI( Test pending interrupt) can also be used for polled IO but in multitasking multiprocessor
+systems it isn't recommended except for checking special cases ( i.e. non looping checks for
+pending IO etc. ).
+
+Store Subchannel & Modify Subchannel can be used to examine & modify operating characteristics
+of a subchannel ( e.g. channel paths ).
+
+Other IO related Terms:
+Sysplex: S390's Clustering Technology
+QDIO: S390's new high speed IO architecture to support devices such as gigabit ethernet,
+this architecture is also designed to be forward compatible with up & coming 64 bit machines.
+
+
+General Concepts 
+
+Input Output Processors (IOP's) are responsible for communicating between
+the mainframe CPU's & the channel & relieve the mainframe CPU's from the
+burden of communicating with IO devices directly, this allows the CPU's to 
+concentrate on data processing. 
+
+IOP's can use one or more links ( known as channel paths ) to talk to each 
+IO device. It first checks for path availability & chooses an available one,
+then starts ( & sometimes terminates IO ).
+There are two types of channel path ESCON & the Paralell IO interface.
+
+IO devices are attached to control units, control units provide the
+logic to interface the channel paths & channel path IO protocols to 
+the IO devices, they can be integrated with the devices or housed separately
+& often talk to several similar devices ( typical examples would be raid 
+controllers or a control unit which connects to 1000 3270 terminals ).
+
+
+    +---------------------------------------------------------------+
+    | +-----+ +-----+ +-----+ +-----+  +----------+  +----------+   |
+    | | CPU | | CPU | | CPU | | CPU |  |  Main    |  | Expanded |   |
+    | |     | |     | |     | |     |  |  Memory  |  |  Storage |   |
+    | +-----+ +-----+ +-----+ +-----+  +----------+  +----------+   | 
+    |---------------------------------------------------------------+
+    |   IOP        |      IOP      |       IOP                      |
+    |---------------------------------------------------------------
+    | C | C | C | C | C | C | C | C | C | C | C | C | C | C | C | C | 
+    ----------------------------------------------------------------
+         ||                                              ||
+         ||  Bus & Tag Channel Path                      || ESCON
+         ||  ======================                      || Channel
+         ||  ||                  ||                      || Path
+    +----------+               +----------+         +----------+
+    |          |               |          |         |          |
+    |    CU    |               |    CU    |         |    CU    |
+    |          |               |          |         |          |
+    +----------+               +----------+         +----------+
+       |      |                     |                |       |
++----------+ +----------+      +----------+   +----------+ +----------+
+|I/O Device| |I/O Device|      |I/O Device|   |I/O Device| |I/O Device|
++----------+ +----------+      +----------+   +----------+ +----------+
+  CPU = Central Processing Unit    
+  C = Channel                      
+  IOP = IP Processor               
+  CU = Control Unit
+
+The 390 IO systems come in 2 flavours the current 390 machines support both
+
+The Older 360 & 370 Interface,sometimes called the paralell I/O interface,
+sometimes called Bus-and Tag & sometimes Original Equipment Manufacturers
+Interface (OEMI).
+
+This byte wide paralell channel path/bus has parity & data on the "Bus" cable 
+& control lines on the "Tag" cable. These can operate in byte multiplex mode for
+sharing between several slow devices or burst mode & monopolize the channel for the
+whole burst. Upto 256 devices can be addressed  on one of these cables. These cables are
+about one inch in diameter. The maximum unextended length supported by these cables is
+125 Meters but this can be extended up to 2km with a fibre optic channel extended 
+such as a 3044. The maximum burst speed supported is 4.5 megabytes per second however
+some really old processors support only transfer rates of 3.0, 2.0 & 1.0 MB/sec.
+One of these paths can be daisy chained to up to 8 control units.
+
+
+ESCON if fibre optic it is also called FICON 
+Was introduced by IBM in 1990. Has 2 fibre optic cables & uses either leds or lasers
+for communication at a signaling rate of upto 200 megabits/sec. As 10bits are transferred
+for every 8 bits info this drops to 160 megabits/sec & to 18.6 Megabytes/sec once
+control info & CRC are added. ESCON only operates in burst mode.
+ 
+ESCONs typical max cable length is 3km for the led version & 20km for the laser version
+known as XDF ( extended distance facility ). This can be further extended by using an
+ESCON director which triples the above mentioned ranges. Unlike Bus & Tag as ESCON is
+serial it uses a packet switching architecture the standard Bus & Tag control protocol
+is however present within the packets. Upto 256 devices can be attached to each control 
+unit that uses one of these interfaces.
+
+Common 390 Devices include:
+Network adapters typically OSA2,3172's,2116's & OSA-E gigabit ethernet adapters,
+Consoles 3270 & 3215 ( a teletype emulated under linux for a line mode console ).
+DASD's direct access storage devices ( otherwise known as hard disks ).
+Tape Drives.
+CTC ( Channel to Channel Adapters ),
+ESCON or Paralell Cables used as a very high speed serial link
+between 2 machines. We use 2 cables under linux to do a bi-directional serial link.
+
+
+Debugging IO on S390 under VM
+=============================
+
+Now we are ready to go on with IO tracing commands under VM
+
+A few self explanatory queries:
+Q OSA
+Q CTC
+Q DISK
+Q DASD
+
+Q osa on my machine returns
+OSA  7C08 ON OSA   7C08 SUBCHANNEL = 0000
+OSA  7C09 ON OSA   7C09 SUBCHANNEL = 0001
+OSA  7C14 ON OSA   7C14 SUBCHANNEL = 0002
+OSA  7C15 ON OSA   7C15 SUBCHANNEL = 0003
+
+Now using the device numbers returned by this command we will
+Trace the io starting up on the first device 7c08 & 7c09
+In our simplest case we can trace the 
+start subchannels
+like TR SSCH 7C08-7C09
+or the halt subchannels
+or TR HSCH 7C08-7C09
+MSCH's ,STSCH's I think you can guess the rest
+
+Ingo's favourite trick is tracing all the IO's & CCWS & spooling them into the reader of another
+VM guest so he can ftp the logfile back to his own machine.I'll do a small bit of this & give you
+ a look at the output.
+
+1) Spool stdout to VM guest linux4's reader
+SP PRT TO * 
+2) Fill linux4's reader with the trace
+TR IO 7c08-7c09 INST INT CCW PRT RUN
+3) Start up linux 
+i 00c  
+4) Finish the trace
+TR END
+5) close the reader
+C PRT
+6) list reader contents
+RDRLIST
+7) copy it to linux4's minidisk 
+RECEIVE / LOG TXT A1 ( replace
+8)
+filel & press F11 to look at it
+You should see someting like.
+
+00020942' SSCH  B2334000    0048813C    CC 0    SCH 0000    DEV 7C08
+          CPA 000FFDF0   PARM 00E2C9C4    KEY 0  FPI C0  LPM 80
+          CCW    000FFDF0  E4200100 00487FE8   0000  E4240100 ........
+          IDAL                                      43D8AFE8
+          IDAL                                      0FB76000
+00020B0A'   I/O DEV 7C08 -> 000197BC'   SCH 0000   PARM 00E2C9C4
+00021628' TSCH  B2354000 >> 00488164    CC 0    SCH 0000    DEV 7C08
+          CCWA 000FFDF8   DEV STS 0C  SCH STS 00  CNT 00EC
+           KEY 0   FPI C0  CC 0   CTLS 4007
+00022238' STSCH B2344000 >> 00488108    CC 0    SCH 0000    DEV 7C08
+
+If you don't like messing up your readed ( because you possibly booted from it )
+you can alternatively spool it to another readers guest.
+
+
+GDB on S390
+===========
+N.B. if compiling for debugging gdb works better without optimisation 
+( see Compiling programs for debugging )
+
+invocation
+----------
+gdb <victim program> <optional corefile>
+
+Online help
+-----------
+help: gives help on commands
+e.g.
+help
+help display
+Note gdb's online help is very good use it.
+
+
+Assembly
+--------
+info registers: displays registers other than floating point.
+info all-registers: displays floating points as well.
+disassemble: dissassembles
+e.g.
+disassemble without parameters will disassemble the current function
+disassemble $pc $pc+10 
+
+Viewing & modifying variables
+-----------------------------
+print or p: displays variable or register
+e.g. p/x $sp will display the stack pointer
+
+display: prints variable or register each time program stops
+e.g.
+display/x $pc will display the program counter
+display argc
+
+undisplay : undo's display's
+
+info breakpoints: shows all current breakpoints
+
+info stack: shows stack back trace ( if this dosent work too well, I'll show you the
+stacktrace by hand below ).
+
+info locals: displays local variables.
+
+info args: display current procedure arguments.
+
+set args: will set argc & argv each time the victim program is invoked.
+
+set <variable>=value
+set argc=100
+set $pc=0
+
+
+
+Modifying execution
+-------------------
+step: steps n lines of sourcecode
+step steps 1 line.
+step 100 steps 100 lines of code.
+
+next: like step except this will not step into subroutines
+
+stepi: steps a single machine code instruction.
+e.g. stepi 100
+
+nexti: steps a single machine code instruction but will not step into subroutines.
+
+finish: will run until exit of the current routine
+
+run: (re)starts a program
+
+cont: continues a program
+
+quit: exits gdb.
+
+
+breakpoints
+------------
+
+break
+sets a breakpoint
+e.g.
+
+break main
+
+break *$pc
+
+break *0x400618
+
+heres a really useful one for large programs
+rbr
+Set a breakpoint for all functions matching REGEXP
+e.g.
+rbr 390
+will set a breakpoint with all functions with 390 in their name.
+
+info breakpoints
+lists all breakpoints
+
+delete: delete breakpoint by number or delete them all
+e.g.
+delete 1 will delete the first breakpoint
+delete will delete them all
+
+watch: This will set a watchpoint ( usually hardware assisted ),
+This will watch a variable till it changes
+e.g.
+watch cnt, will watch the variable cnt till it changes.
+As an aside unfortunately gdb's, architecture independent watchpoint code
+is inconsistent & not very good, watchpoints usually work but not always.
+
+info watchpoints: Display currently active watchpoints
+
+condition: ( another useful one )
+Specify breakpoint number N to break only if COND is true.
+Usage is `condition N COND', where N is an integer and COND is an
+expression to be evaluated whenever breakpoint N is reached.
+
+
+
+User defined functions/macros
+-----------------------------
+define: ( Note this is very very useful,simple & powerful )
+usage define <name> <list of commands> end
+
+examples which you should consider putting into .gdbinit in your home directory
+define d
+stepi
+disassemble $pc $pc+10
+end
+
+define e
+nexti
+disassemble $pc $pc+10
+end
+
+
+Other hard to classify stuff
+----------------------------
+signal n:
+sends the victim program a signal.
+e.g. signal 3 will send a SIGQUIT.
+
+info signals:
+what gdb does when the victim receives certain signals.
+
+list:
+e.g.
+list lists current function source
+list 1,10 list first 10 lines of curret file.
+list test.c:1,10
+
+
+directory:
+Adds directories to be searched for source if gdb cannot find the source.
+(note it is a bit sensititive about slashes ) 
+e.g. To add the root of the filesystem to the searchpath do
+directory //
+
+
+call <function>
+This calls a function in the victim program, this is pretty powerful
+e.g.
+(gdb) call printf("hello world")
+outputs:
+$1 = 11 
+
+You might now be thinking that the line above didn't work, something extra had to be done.
+(gdb) call fflush(stdout)
+hello world$2 = 0
+As an aside the debugger also calls malloc & free under the hood 
+to make space for the "hello world" string.
+
+
+
+hints
+-----
+1) command completion works just like bash 
+( if you are a bad typist like me this really helps )
+e.g. hit br <TAB> & cursor up & down :-).
+
+2) if you have a debugging problem that takes a few steps to recreate
+put the steps into a file called .gdbinit in your current working directory
+if you have defined a few extra useful user defined commands put these in 
+your home directory & they will be read each time gdb is launched.
+
+A typical .gdbinit file might be.
+break main
+run
+break runtime_exception
+cont 
+
+
+stack chaining in gdb by hand
+-----------------------------
+This is done using a the same trick described for VM 
+p/x (*($sp+56))&0x7fffffff get the first backchain.
+this outputs 
+$5 = 0x528f18 
+on my machine.
+Now you can use 
+info symbol (*($sp+56))&0x7fffffff 
+you might see something like.
+rl_getc + 36 in section .text  telling you what is located at address 0x528f18
+Now do.
+p/x (*(*$sp+56))&0x7fffffff 
+This outputs
+$6 = 0x528ed0
+Now do.
+info symbol (*(*$sp+56))&0x7fffffff
+rl_read_key + 180 in section .text
+now do
+p/x (*(**$sp+56))&0x7fffffff
+& so on.
+
+
+
+Note: Remember gdb has history just like bash you don't need to retype the
+whole line just use the up & down arrows.
+
+
+
+For more info
+-------------
+From your linuxbox do 
+man gdb or info gdb.
+
+core dumps
+----------
+What a core dump ?,
+A core dump is a file generated by the kernel ( if allowed ) which contains the registers,
+& all active pages of the program which has crashed.
+From this file gdb will allow you to look at the registers & stack trace & memory of the
+program as if it just crashed on your system, it is usually called core & created in the
+current working directory.
+This is very useful in that a customer can mail a core dump to a technical support department
+& the technical support department can reconstruct what happened.
+Provided the have an indentical copy of this program with debugging symbols compiled in & 
+the source base of this build is available.
+In short it is far more useful than something like a crash log could ever hope to be.
+
+In theory all that is missing to restart a core dumped program is a kernel patch which
+will do the following.
+1) Make a new kernel task structure
+2) Reload all the dumped pages back into the kernels memory managment structures.
+3) Do the required clock fixups
+4) Get all files & network connections for the process back into an identical state ( really difficult ).
+5) A few more difficult things I haven't thought of.
+
+
+
+Why have I never seen one ?.
+Probably because you haven't used the command 
+ulimit -c unlimited in bash
+to allow core dumps, now do 
+ulimit -a 
+to verify that the limit was accepted.
+
+A sample core dump
+To create this I'm going to do
+ulimit -c unlimited
+gdb 
+to launch gdb (my victim app. ) now be bad & do the following from another 
+telnet/xterm session to the same machine
+ps -aux | grep gdb
+kill -SIGSEGV <gdb's pid>
+or alternatively use killall -SIGSEGV gdb if you have the killall command.
+Now look at the core dump.
+./gdb ./gdb core
+Displays the following
+GNU gdb 4.18
+Copyright 1998 Free Software Foundation, Inc.
+GDB is free software, covered by the GNU General Public License, and you are
+welcome to change it and/or distribute copies of it under certain conditions.
+Type "show copying" to see the conditions.
+There is absolutely no warranty for GDB.  Type "show warranty" for details.
+This GDB was configured as "s390-ibm-linux"...
+Core was generated by `./gdb'.
+Program terminated with signal 11, Segmentation fault.
+Reading symbols from /usr/lib/libncurses.so.4...done.
+Reading symbols from /lib/libm.so.6...done.
+Reading symbols from /lib/libc.so.6...done.
+Reading symbols from /lib/ld-linux.so.2...done.
+#0  0x40126d1a in read () from /lib/libc.so.6
+Setting up the environment for debugging gdb.
+Breakpoint 1 at 0x4dc6f8: file utils.c, line 471.
+Breakpoint 2 at 0x4d87a4: file top.c, line 2609.
+(top-gdb) info stack
+#0  0x40126d1a in read () from /lib/libc.so.6
+#1  0x528f26 in rl_getc (stream=0x7ffffde8) at input.c:402
+#2  0x528ed0 in rl_read_key () at input.c:381
+#3  0x5167e6 in readline_internal_char () at readline.c:454
+#4  0x5168ee in readline_internal_charloop () at readline.c:507
+#5  0x51692c in readline_internal () at readline.c:521
+#6  0x5164fe in readline (prompt=0x7ffff810 "\177˙řx\177˙÷Ř\177˙řxŔ")
+    at readline.c:349
+#7  0x4d7a8a in command_line_input (prrompt=0x564420 "(gdb) ", repeat=1,
+    annotation_suffix=0x4d6b44 "prompt") at top.c:2091
+#8  0x4d6cf0 in command_loop () at top.c:1345
+#9  0x4e25bc in main (argc=1, argv=0x7ffffdf4) at main.c:635
+
+
+LDD
+===
+This is a program which lists the shared libraries which a library needs.
+e.g.
+ ldd ./gdb
+outputs
+libncurses.so.4 => /usr/lib/libncurses.so.4 (0x40018000)
+libm.so.6 => /lib/libm.so.6 (0x4005e000)
+libc.so.6 => /lib/libc.so.6 (0x40084000)
+/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
+
+Debugging modules
+=================
+As modules are dynamically loaded into the kernel their address can be
+anywhere to get around this use the -m option with insmod to emit a load
+map which can be piped into a file if required.
+
+The proc file system
+====================
+What is it ?.
+It is a filesystem created by the kernel with files which are created on demand
+by the kernel if read, or can be used to modify kernel parameters,
+it is a powerful concept.
+
+e.g.
+
+cat /proc/sys/net/ipv4/ip_forward 
+On my machine outputs 
+0 
+telling me ip_forwarding is not on to switch it on I can do
+echo 1 >  /proc/sys/net/ipv4/ip_forward
+cat it again
+cat /proc/sys/net/ipv4/ip_forward 
+On my machine now outputs
+1
+IP forwarding is on.
+There is a lot of useful info in here best found by going in & having a look around,
+so I'll take you through some entries I consider important.
+
+All the processes running on the machine have there own entry defined by
+/proc/<pid>
+So lets have a look at the init process
+cd /proc/1
+
+cat cmdline
+emits
+init [2]
+
+cd /proc/1/fd
+This contains numerical entries of all the open files,
+some of these you can cat e.g. stdout (2)
+
+cat /proc/29/maps
+on my machine emits
+
+00400000-00478000 r-xp 00000000 5f:00 4103       /bin/bash
+00478000-0047e000 rw-p 00077000 5f:00 4103       /bin/bash
+0047e000-00492000 rwxp 00000000 00:00 0
+40000000-40015000 r-xp 00000000 5f:00 14382      /lib/ld-2.1.2.so
+40015000-40016000 rw-p 00014000 5f:00 14382      /lib/ld-2.1.2.so
+40016000-40017000 rwxp 00000000 00:00 0
+40017000-40018000 rw-p 00000000 00:00 0
+40018000-4001b000 r-xp 00000000 5f:00 14435      /lib/libtermcap.so.2.0.8
+4001b000-4001c000 rw-p 00002000 5f:00 14435      /lib/libtermcap.so.2.0.8
+4001c000-4010d000 r-xp 00000000 5f:00 14387      /lib/libc-2.1.2.so
+4010d000-40111000 rw-p 000f0000 5f:00 14387      /lib/libc-2.1.2.so
+40111000-40114000 rw-p 00000000 00:00 0
+40114000-4011e000 r-xp 00000000 5f:00 14408      /lib/libnss_files-2.1.2.so
+4011e000-4011f000 rw-p 00009000 5f:00 14408      /lib/libnss_files-2.1.2.so
+7fffd000-80000000 rwxp ffffe000 00:00 0
+
+
+Showing us the shared libraries init uses where they are in memory
+& memory access permissions for each virtual memory area.
+
+/proc/1/cwd is a softlink to the current working directory.
+/proc/1/root is the root of the filesystem for this process. 
+
+/proc/1/mem is the current running processes memory which you
+can read & write to like a file.
+strace uses this sometimes as it is a bit faster than the
+rather inefficent ptrace interface for peeking at DATA.
+
+
+cat status 
+
+Name:   init
+State:  S (sleeping)
+Pid:    1
+PPid:   0
+Uid:    0       0       0       0
+Gid:    0       0       0       0
+Groups:
+VmSize:      408 kB
+VmLck:         0 kB
+VmRSS:       208 kB
+VmData:       24 kB
+VmStk:         8 kB
+VmExe:       368 kB
+VmLib:         0 kB
+SigPnd: 0000000000000000
+SigBlk: 0000000000000000
+SigIgn: 7fffffffd7f0d8fc
+SigCgt: 00000000280b2603
+CapInh: 00000000fffffeff
+CapPrm: 00000000ffffffff
+CapEff: 00000000fffffeff
+
+User PSW:    070de000 80414146
+task: 004b6000 tss: 004b62d8 ksp: 004b7ca8 pt_regs: 004b7f68
+User GPRS:
+00000400  00000000  0000000b  7ffffa90
+00000000  00000000  00000000  0045d9f4
+0045cafc  7ffffa90  7fffff18  0045cb08
+00010400  804039e8  80403af8  7ffff8b0
+User ACRS:
+00000000  00000000  00000000  00000000
+00000001  00000000  00000000  00000000
+00000000  00000000  00000000  00000000
+00000000  00000000  00000000  00000000
+Kernel BackChain  CallChain    BackChain  CallChain
+       004b7ca8   8002bd0c     004b7d18   8002b92c
+       004b7db8   8005cd50     004b7e38   8005d12a
+       004b7f08   80019114                     
+Showing among other things memory usage & status of some signals &
+the processes'es registers from the kernel task_structure
+as well as a backchain which may be useful if a process crashes
+in the kernel for some unknown reason.
+
+Starting points for debugging scripting languages etc.
+======================================================
+
+bash/sh
+
+bash -x <scriptname>
+e.g. bash -x /usr/bin/bashbug
+displays the following lines as it executes them.
++ MACHINE=i586
++ OS=linux-gnu
++ CC=gcc
++ CFLAGS= -DPROGRAM='bash' -DHOSTTYPE='i586' -DOSTYPE='linux-gnu' -DMACHTYPE='i586-pc-linux-gnu' -DSHELL -DHAVE_CONFIG_H   -I. -I. -I./lib -O2 -pipe
++ RELEASE=2.01
++ PATCHLEVEL=1
++ RELSTATUS=release
++ MACHTYPE=i586-pc-linux-gnu   
+
+perl -d <scriptname> runs the perlscript in a fully intercative debugger
+<like gdb>.
+Type 'h' in the debugger for help.
+
+for debugging java type
+jdb <filename> another fully interactive gdb style debugger.
+& type ? in the debugger for help.
+
+
+References:
+-----------
+Enterprise Systems Architecture Reference Summary
+Enterprise Systems Architecture Principles of Operation
+Hartmut Penners 390 stack frame sheet.
+IBM Mainframe Channel Attachment a technology brief from a CISCO webpage
+Various bits of man & info pages of Linux.
+Linux & GDB source.
+Various info & man pages.
+CMS Help on tracing commands.
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/Documentation/README.DAC960 linux.15p9/Documentation/README.DAC960
--- linux.vanilla/Documentation/README.DAC960	Sat Aug 28 20:00:52 1999
+++ linux.15p9/Documentation/README.DAC960	Sun Jan 23 08:01:00 2000
@@ -1,17 +1,17 @@
 	   Mylex DAC960/DAC1100 PCI RAID Controller Driver for Linux
 
-			Version 2.2.4 for Linux 2.2.11
-			Version 2.0.4 for Linux 2.0.37
+			Version 2.2.5 for Linux 2.2.14
+			Version 2.0.5 for Linux 2.0.38
 
 			      PRODUCTION RELEASE
 
-				23 August 1999
+				23 January 2000
 
 			       Leonard N. Zubkoff
 			       Dandelion Digital
 			       lnz@dandelion.com
 
-	 Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
+	 Copyright 1998-2000 by Leonard N. Zubkoff <lnz@dandelion.com>
 
 
 				 INTRODUCTION
@@ -87,7 +87,9 @@
 The following list comprises the supported DAC960 and DAC1100 PCI RAID
 Controllers as of the date of this document.  It is recommended that anyone
 purchasing a Mylex PCI RAID Controller not in the following table contact the
-author beforehand to verify that it is or will be supported.
+author beforehand to verify that it is or will be supported.  The eXtremeRAID
+2000, eXtremeRAID 3000, and AcceleRAID 352 have an entirely new firmware
+interface and are not yet supported by this driver.
 
 eXtremeRAID 1100 (DAC1164P)
 	    3 Wide Ultra-2/LVD SCSI channels
@@ -163,16 +165,16 @@
 
 			      DRIVER INSTALLATION
 
-This distribution was prepared for Linux kernel version 2.2.11 or 2.0.37.
+This distribution was prepared for Linux kernel version 2.2.14 or 2.0.38.
 
 To install the DAC960 RAID driver, you may use the following commands,
 replacing "/usr/src" with wherever you keep your Linux kernel source tree:
 
   cd /usr/src
-  tar -xvzf DAC960-2.2.4.tar.gz (or DAC960-2.0.4.tar.gz)
+  tar -xvzf DAC960-2.2.5.tar.gz (or DAC960-2.0.5.tar.gz)
   mv README.DAC960 linux/Documentation
   mv DAC960.[ch] linux/drivers/block
-  patch -p0 < DAC960.patch
+  patch -p0 < DAC960.patch (driver 2.0.5 only)
   cd linux
   make config
   make depend
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/Documentation/cpqarray.txt linux.15p9/Documentation/cpqarray.txt
--- linux.vanilla/Documentation/cpqarray.txt	Sat Aug 14 02:27:12 1999
+++ linux.15p9/Documentation/cpqarray.txt	Mon Feb  7 12:23:16 2000
@@ -1,11 +1,5 @@
 This driver is for Compaq's SMART2 Intellegent Disk Array Controllers.
 
-WARNING:
---------
-
-This driver comes with NO WARRANTY.  It is not officially supported by
-Compaq.  Do not call technical support.  Use at your own risk.
-
 Supported Cards:
 ----------------
 
@@ -22,6 +16,7 @@
 	* Integrated Smart Array Controller
 	* SA 4200
 	* SA 4250ES
+	* SA 431
 
 It should also work with some really old Disk array adapters, but I am
 unable to test against these cards:
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/Documentation/isdn/README.HiSax linux.15p9/Documentation/isdn/README.HiSax
--- linux.vanilla/Documentation/isdn/README.HiSax	Wed Oct 20 01:12:32 1999
+++ linux.15p9/Documentation/isdn/README.HiSax	Wed Jan 26 23:08:43 2000
@@ -64,6 +64,7 @@
 Gazel ISDN cards
 HFC-PCI based cards
 Winbond W6692 based cards
+HFC-S+, HFC-SP/PCMCIA cards
 
 Note: PCF, PCF-Pro: up to now, only the ISDN part is supported
       PCC-8: not tested yet
@@ -72,6 +73,7 @@
       Teles PCI is EXPERIMENTAL
       Teles S0Box is EXPERIMENTAL
       Eicon.Diehl Diva U interface not tested
+      HFC-S+, HFC-SP/PCMCIA are experimental
 
 If you know other passive cards with the Siemens chipset, please let me know.
 To use the PNP cards you need the isapnptools.
@@ -184,6 +186,7 @@
    34	Gazel ISDN cards (PCI)   none
    35	HFC 2BDS0 PCI            none
    36	W6692 based PCI cards    none
+   37   HFC 2BDS0 S+, SP/PCMCIA  irq,io (pcmcia must be set with cardmgr)
 
 
 At the moment IRQ sharing is only possible with PCI cards. Please make sure
@@ -288,6 +291,7 @@
    34	Gazel ISDN cards (PCI)  no parameter
    35	HFC 2BDS0 PCI           no parameter
    36	W6692 based PCI cards   none
+   37   HFC 2BDS0 S+,SP/PCMCIA  pa=irq, pb=io
 
 Running the driver
 ------------------
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/Documentation/magic-number.txt linux.15p9/Documentation/magic-number.txt
--- linux.vanilla/Documentation/magic-number.txt	Sun Aug  9 20:15:49 1998
+++ linux.15p9/Documentation/magic-number.txt	Wed Feb 16 18:35:24 2000
@@ -48,7 +48,7 @@
 PG_MAGIC	      'P'	  pg_{read,write}_hdr include/linux/pg.h
 MKISS_DRIVER_MAGIC    0x04bf      mkiss_channel     drivers/net/mkiss.h
 RISCOM8_MAGIC         0x0907      riscom_port       drivers/char/riscom8.h
-APM_BIOS_MAGIC        0x4101      apm_bios_struct   include/linux/apm_bios.h
+APM_BIOS_MAGIC        0x4101      apm_user          arch/i386/kernel/apm.c
 CYCLADES_MAGIC        0x4359      cyclades_port     include/linux/cyclades.h
 FASYNC_MAGIC          0x4601      fasync_struct     include/linux/fs.h
 PTY_MAGIC	      0x5001	  (none at the moment)
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/Documentation/networking/bonding.txt linux.15p9/Documentation/networking/bonding.txt
--- linux.vanilla/Documentation/networking/bonding.txt	Thu Jan  1 01:00:00 1970
+++ linux.15p9/Documentation/networking/bonding.txt	Mon Feb  7 12:18:49 2000
@@ -0,0 +1,128 @@
+Installation:
+
+Apply patch.  (if your reading this in
+/usr/src/linux/Documentation/networking/bonding.txt, then it's already
+applied.)
+
+Run make menuconfig/xconfig/config, and select 'bonding device' in
+network devices.
+
+Build the new kernel/modules.
+
+Get update ifenslave.c (included in tar file.) (location to be determined.)
+
+install ifenslave.c; do:
+	gcc -O2 -o ifenslave ifenslave.c
+	cp ifenslave /sbin/ifenslave
+
+Modify /etc/conf.modules by adding the line:
+	alias bond0 bonding
+
+If you running a RH5.0 or newer distribution, do:
+
+cd /etc/sysconfig/network-scripts
+cp ifcfg-eth0 ifcfg-bond0
+edit ifcfg-bond0, and make it look the following:
+
+DEVICE=bond0
+USERCTL=no
+ONBOOT=yes
+BOOTPROTO=none
+BROADCAST=XXX.XXX.XXX.255
+NETWORK=XXX.XXX.XXX.0
+NETMASK=255.255.255.0
+IPADDR=XXX.XXX.XXX.XXX
+
+(put the approiate values for you network in where the XXX's are at.)
+
+Then, edit ifcfg-eth0/ifcfg-eth1 (and all the other slave devices), and make them
+look like this:
+
+DEVICE=eth0
+USERCTL=no
+ONBOOT=yes
+MASTER=bond0
+SLAVE=yes
+BOOTPROTO=none
+
+Reboot, and the network should come up bonded together.
+
+For other distributions, you need to do something like:
+
+/sbin/ifconfig bond0 addresss netmask xxx.xxx.xxx.xxx broadcast xxx.xxx.xxx.xxx up
+/sbin/ifenslave bond0 eth0
+/sbin/ifenslave bond0 eth1
+
+When properly configured, it will look this:
+
+[root]# /sbin/ifconfig
+bond0     Link encap:Ethernet  HWaddr 00:C0:F0:1F:37:B4  
+          inet addr:XXX.XXX.XXX.YYY  Bcast:XXX.XXX.XXX.255  Mask:255.255.252.0
+          UP BROADCAST RUNNING MASTER MULTICAST  MTU:1500  Metric:1
+          RX packets:7224794 errors:0 dropped:0 overruns:0 frame:0
+          TX packets:3286647 errors:1 dropped:0 overruns:1 carrier:0
+          collisions:0 txqueuelen:0 
+
+eth0      Link encap:Ethernet  HWaddr 00:C0:F0:1F:37:B4  
+          inet addr:XXX.XXX.XXX.YYY  Bcast:XXX.XXX.XXX.255  Mask:255.255.252.0
+          UP BROADCAST RUNNING SLAVE MULTICAST  MTU:1500  Metric:1
+          RX packets:3573025 errors:0 dropped:0 overruns:0 frame:0
+          TX packets:1643167 errors:1 dropped:0 overruns:1 carrier:0
+          collisions:0 txqueuelen:100 
+          Interrupt:10 Base address:0x1080 
+
+eth1      Link encap:Ethernet  HWaddr 00:C0:F0:1F:37:B4  
+          inet addr:XXX.XXX.XXX.YYY  Bcast:XXX.XXX.XXX.255  Mask:255.255.252.0
+          UP BROADCAST RUNNING SLAVE MULTICAST  MTU:1500  Metric:1
+          RX packets:3651769 errors:0 dropped:0 overruns:0 frame:0
+          TX packets:1643480 errors:0 dropped:0 overruns:0 carrier:0
+          collisions:0 txqueuelen:100 
+          Interrupt:9 Base address:0x1400 
+
+Questions:
+
+1.  Is it SMP safe?
+
+	Yes.  The old 2.0.xx channel bonding patch wasn't SMP safe.
+This one was designed from the start to be SMP safe.
+
+2.  What type of cards can it work with it?
+
+	Any Ethernet type cards (ie, you can even mix cards - a tulip
+and a 3com 3c905, for example).  You can even bond together Gigabit
+Ethernet cards!
+
+3.  How many bond devices can I have?
+
+	Just one at this time.
+
+4.  How many slaves can a bond device have?
+
+	Limited by the number of cards you can place in your system.
+
+5.  What happens when a slave dies?
+
+	Currently, the ethernet drivers don't really handle this
+situation very well.  The tulip driver never stalls; it just starts to
+throw packets away!
+
+6.  If this was fixed, can bonding be used for High Availability?
+
+	Yes!
+
+7.  Which switches/systems does it work with?
+
+	Cisco 5500 series (look for EtherChannel support).
+	SunTrunking software.
+
+8.  Where does the bond0 device get it's mac address from?
+
+	It's taken from the first slave device.  If you remove that
+first slave device, the MAC address continues to be associated with
+it.  If you wish to remove that MAC address, you have to ifconfig
+bond0 down, and then modprobe -r bonding.  If you wish, you can also
+assign a MAC address when you ifconfig the bond0 device.
+
+9.  Which transmit policy is used?
+
+	Round robin, based on order of enslaving.
\ No newline at end of file
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/Documentation/networking/dmfe.txt linux.15p9/Documentation/networking/dmfe.txt
--- linux.vanilla/Documentation/networking/dmfe.txt	Thu Jan  1 01:00:00 1970
+++ linux.15p9/Documentation/networking/dmfe.txt	Sat Jan 22 02:48:07 2000
@@ -0,0 +1,63 @@
+  dmfe.c: Version 1.28        01/18/2000
+
+        A Davicom DM9102(A)/DM9132/DM9801 fast ethernet driver for Linux. 
+        Copyright (C) 1997  Sten Wang
+
+        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.
+
+
+  A. Compiler command:
+
+     A-1: For normal single processor kernel
+          "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall 
+            -Wstrict-prototypes -O6 -c dmfe.c"
+
+     A-2: For single processor and enable kernel module version function
+          "gcc -DMODULE -DMODVERSIONS -D__KERNEL__ -I/usr/src/linux/net/inet 
+            -Wall -Wstrict-prototypes -O6 -c dmfe.c"
+
+     A-3: For multiple processors(SMP) and enable the module version function
+          "gcc -D__SMP__ -DMODULE -DMODVERSIONS -D__KERNEL__ -I/usr/src/linux
+           /net/inet -Wall -Wstrict-prototypes -O6 -c dmfe.c"
+
+
+  B. The following steps teach you how to active DM9102 board:
+
+        1. Used the upper compiler command to compile dmfe.c
+
+        2. Insert dmfe module into kernel
+           "insmod dmfe"        ;;Auto Detection Mode (Suggest)
+           "insmod dmfe mode=0" ;;Force 10M Half Duplex
+           "insmod dmfe mode=1" ;;Force 100M Half Duplex
+           "insmod dmfe mode=4" ;;Force 10M Full Duplex
+           "insmod dmfe mode=5" ;;Force 100M Full Duplex
+
+        3. Config a dm9102 network interface
+           "ifconfig eth0 172.22.3.18"
+                          ^^^^^^^^^^^ Your IP address
+
+        4. Active the IP routing table. For some distributions, it is not
+           necessary. You can type "route" to check.
+
+           "route add default eth0"
+
+
+        5. Well done. Your DM9102 adapter actived now.
+
+
+   C. Object files description:
+        1. dmfe_rh61.o:       	For Redhat 6.1
+
+        If you can make sure your kernel version, you can rename
+        to dmfe.o and directly use it without re-compiling.
+
+
+  Author: Sten Wang, 886-3-5798797-8517, E-mail: sten_wang@davicom.com.tw
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/Documentation/networking/sk98lin.txt linux.15p9/Documentation/networking/sk98lin.txt
--- linux.vanilla/Documentation/networking/sk98lin.txt	Tue Jan  4 21:18:38 2000
+++ linux.15p9/Documentation/networking/sk98lin.txt	Wed Feb 16 18:29:09 2000
@@ -3,7 +3,7 @@
 
 sk98lin.txt created 11-Nov-1999
 
-Readme File for sk98lin.o v3.02
+Readme File for sk98lin.o v3.04
 SK-NET Gigabit Ethernet Adapter SK-98xx Driver for Linux
 
 This file contains
@@ -24,8 +24,8 @@
 ============
 
 The sk98lin driver supports the SysKonnect SK-NET Gigabit Ethernet
-Adapter SK-98xx family on Linux 2.2.x.
-It has been tested with Linux on Intel/x86 and ALPHA machines.
+Adapter SK-98xx family on Linux 2.2.x and above.
+It has been tested with Linux on Intel/x86, ALPHA and UltraSPARC machines.
 From v3.02 on, the driver is integrated in the linux kernel source.
 ***
 
@@ -132,7 +132,8 @@
 module with 'insmod'. The configuration tools of some distributions
 can also give parameters to the driver module.
 If you use the kernel module loader, you can set driver parameters
-in the file /etc/conf.modules. Insert a line of the form:
+in the file /etc/modules.conf (or old name: /etc/conf.modules).
+Insert a line of the form:
 
 options sk98lin ...
 
@@ -281,14 +282,12 @@
 the large frames. If one adapter is not set to receive large frames,
 it will simply drop them.
 
-NOTE: If you look at the statistics (with netstat) in large frame
-      mode while there is traffic on the net, you will see the
-      RX error counter go up. This is because the adapter hardware
-      counts received large frames as errors, although they are
-      received correctly. So ignore this counter in that case.
-
 You can switch back to the standard ethernet frame size with:
   ifconfig eth0 mtu 1500
+
+To make this setting persitent, add a script with the 'ifconfig'
+line to the system startup sequence (named something like "S99sk98lin"
+in /etc/rc.d/rc2.d).
 ***
 
 
@@ -374,15 +373,27 @@
 (8) HISTORY
 ===========
 
-VERSION 3.02
+VERSION 3.04 (In-Kernel version)
+Problems fixed:
+- Driver start failed on UltraSPARC
+- Rx checksum calculation for big endian machines did not work
+- Jumbo frames were counted as input-errors in netstat
+
+VERSION 3.03 (Standalone version)
+Problems fixed:
+- Compilation did not find script "printver.sh" if "." not in PATH
+Known limitations:
+- None
+
+VERSION 3.02 (In-Kernel version)
 Problems fixed:
 - None
 New Features:
-- Integration in linux kernel source.
+- Integration in Linux kernel source (2.2.14 and 2.3.29) 
 Known limitations:
 - None
 
-VERSION 3.02
+VERSION 3.01
 Problems fixed:
 - None
 New Features:
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/Documentation/networking/tlan.txt linux.15p9/Documentation/networking/tlan.txt
--- linux.vanilla/Documentation/networking/tlan.txt	Tue Jan  4 21:18:38 2000
+++ linux.15p9/Documentation/networking/tlan.txt	Wed Feb 16 18:28:31 2000
@@ -1,25 +1,4 @@
-
-
-I haven't had any time to do anything for a long time, and this isn't
-likely to change.  So there's a driver here for anyone looking to
-carry forward a project :)
-
-For those who are looking for help, I can't.  I haven't looked at
-a kernel since the early 2.0 series, so I won't know what's going on.
-Your best chance at help would be joining the TLAN mailing list and
-posting your question there.
-
-You can join by sending "subscribe tlan" in the body of an email to
-majordomo@vuser.vu.union.edu.
-
-Thanks to those who have (and who will ;) put work in to keep the TLAN
-driver working as the kernel moves on.
-
-James
-james@sovereign.org
-
-
-TLAN driver for Linux, version 1.0
+TLAN driver for Linux, version 1.2
 README
 
 
@@ -57,43 +36,7 @@
     but I do not expect any problems.
     
 
-II.  Building the Driver.
-
-    The TLAN driver may be compiled into the kernel, or it may be compiled
-    as a module separately, or in the kernel.  A patch is included for
-    2.0.29 (which also works for 2.0.30, 2.0.31, and 2.0.32).
-
-    To compile it as part of the kernel:
-        1. Download and untar the TLAN driver package.
-	2. If your kernel is 2.1.45 or later, you do not need to patch the
-           kernel sources.  Copy the tlan.c and tlan.h to drivers/net in
-           the kernel source tree.
-        3. Otherwise, apply the appropriate patch for your kernel.  For
-	   example:
-
-	       cd /usr/src/linux
-               patch -p1 < kernel.2.0.29
-
-        4. Copy the files tlan.c and tlan.h from the TLAN package to the
-           directory drivers/net in the Linux kernel source tree.
-        5. Configure your kernel for the TLAN driver.  Answer 'Y' when
-           prompted to ask about experimental code (the first question).
-           Then answer 'Y' when prompted if to include TI ThunderLAN
-           support.  If you want the driver compiled as a module, answer 'M'
-           instead of 'Y'.
-        6. Make the kernel and, if necessary, the modules.
-    
-    To compile the TLAN driver independently:
-        1. Download and untar the TLAN driver package.
-        2. Change to the tlan directory.
-        3. If you are NOT using a versioned kernel (ie, want an non-
-           versioned module), edit the Makefile, and comment out the
-           line:
-                 MODVERSIONS = -DMODVERSIONS
-        4. Run 'make'.
-
-
-III.  Driver Options
+II.  Driver Options
 	1. You can append debug=x to the end of the insmod line to get
            debug messages, where x is a bit field where the bits mean
 	   the following:
@@ -110,15 +53,15 @@
 	   device that does not have an AUI/BNC connector will probably
 	   cause it to not function correctly.)
 
-	4. You can set duplex=1 to force half duplex, and duplex=2 to
+	3. You can set duplex=1 to force half duplex, and duplex=2 to
 	   force full duplex.
 
-	5. You can set speed=10 to force 10Mbs operation, and speed=100Mbs
+	4. You can set speed=10 to force 10Mbs operation, and speed=100
 	   to force 100Mbs operation. (I'm not sure what will happen
 	   if a card which only supports 10Mbs is forced into 100Mbs
 	   mode.)
 
-	3. If the driver is built into the kernel, you can use the 3rd
+	5. If the driver is built into the kernel, you can use the 3rd
 	   and 4th parameters to set aui and debug respectively.  For
 	   example:
 
@@ -136,13 +79,13 @@
 		0x10 = use 10BaseT
 		0x20 = use 100BaseTx
 
+	6. This driver can be used as a loadable module. Se net-modules.txt
+	   for details.
 
-IV.  Things to try if you have problems.
+III.  Things to try if you have problems.
 	1. Make sure your card's PCI id is among those listed in
 	   section I, above.
-	1. Make sure routing is correct.
-	2. If you are using a 2.1.x kernel, try to duplicate the
-	   problem on a 2.0.x (preferably 2.0.29 or 2.0.30) kernel.
+	2. Make sure routing is correct.
 
 
 There is also a tlan mailing list which you can join by sending "subscribe tlan"
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/Documentation/scsi-generic.txt linux.15p9/Documentation/scsi-generic.txt
--- linux.vanilla/Documentation/scsi-generic.txt	Sat Aug 14 02:26:45 1999
+++ linux.15p9/Documentation/scsi-generic.txt	Wed Jan 12 01:27:40 2000
@@ -1,17 +1,18 @@
-            Notes on Linux's SG driver version 2.1.34
+            Notes on Linux's SG driver version 2.1.36
             -----------------------------------------
-                                                        990606
+                                                        20000110
 
 Introduction
 ============
-Sg is one of the four "high level" SCSI device drivers along with
-sd, st and sr (disk, tape and CDROM respectively). Sg is more generalized
-(but lower level) than its siblings and tends to be used on SCSI devices
-that don't fit into the already serviced categories. Thus sg is used for
-scanners, cd writers and reading audio cds digitally amongst other things.
+The SCSI Generic driver (sg) is one of the four "high level" SCSI device
+drivers along with sd, st and sr (disk, tape and CDROM respectively). Sg
+is more generalized (but lower level) than its siblings and tends to be
+used on SCSI devices that don't fit into the already serviced categories.
+Thus sg is used for scanners, cd writers and reading audio cds digitally
+amongst other things.
 
 These are notes on the Linux SCSI generic packet device driver (sg)
-describing version 2.1.34 . The original driver was written by Lawrence
+describing version 2.1.36 . The original driver was written by Lawrence
 Foard and remained in place with minimal changes since circa 1992.
 Version 2 of this driver remains backward compatible (binary and
 source **) with the original. It adds scatter gather, command queuing,
@@ -27,12 +28,12 @@
 of the document is version 1.5 dated 7th May 1996. It can found at
 ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO-SCSI-Programming-HOWTO .
 A copy of this document can be found at:
-http://www.torque.net/sg/p/original/HOWTO-SCSI-Programming-HOWTO .
+http://www.torque.net/sg/p/original/HOWTO-SCSI-Programming-HOWTO.txt .
 
 ** It is possible to write applications that perform differently
 depending on whether they are using the original or this version of
-the sg device driver. The author is not aware of any useful 
-pre-existing applications that have problems with version 2 (yet).
+the sg device driver. The author is not aware of any useful
+pre-existing applications that have problems with version 2.
 
 
 Architecture
@@ -52,12 +53,12 @@
 system calls of open(), close(), read(), write() and ioctl(). Two other
 related system calls: poll() and fcntl() are added to this list and
 how they interact with the sg device driver is documented later.
- 
-An SG device is accessed by write()ing SCSI commands plus any associated 
+
+An SG device is accessed by write()ing SCSI commands plus any associated
 outgoing data to it; the resulting status codes and any incoming data are
 then obtained by a read() call. The device can be opened O_NONBLOCK
 (non-blocking) and poll() used to monitor its progress. The device may be
-opened O_EXCL which excludes other "sg" users from this device (but not 
+opened O_EXCL which excludes other "sg" users from this device (but not
 "sd", "st" or "sr" users). The buffer given to the write() call is made
 up as follows:
         - struct sg_header image (see below)
@@ -71,6 +72,12 @@
 The given SCSI command has its LUN field overwritten by the LUN value of
 the associated sg device that has been open()ed.
 
+SCSI commands are only attempted once (i.e. there are no internal
+retries). If appropriate (e.g. a SCSI READ) the data buffer is copied back
+to user space irrespective of the values of the various SCSI related
+error/status codes. [Some adapters that use an old error interface in
+the SCSI mid level ignore the retry count and retry certain errors.]
+
 
 sg_header
 =========
@@ -96,11 +103,11 @@
 input variable, it is not read by sg internally (only written).
 
 The 'reply_len' is the length of the data the corresponding read()
-will/should request (including the sg_header). 
+will/should request (including the sg_header).
 
 The 'pack_id' is not acted upon by the sg device driver but is conveyed
 back to the corresponding read() so it can be used for sequencing by an
-application. 
+application.
 
 The 'result' is also bizarre, turning certain types of host codes to 0 (no
 error), EBUSY or EIO. With better error reporting now available, the
@@ -138,7 +145,7 @@
     unsigned int driver_status:8;   /* [o] driver status+suggestion */
     unsigned int other_flags:10;    /* unused */
     unsigned char sense_buffer[SG_MAX_SENSE]; /* [o] Output in 3 cases:
-           when target_status is CHECK_CONDITION or 
+           when target_status is CHECK_CONDITION or
            when target_status is COMMAND_TERMINATED or
            when (driver_status & DRIVER_SENSE) is true. */
 };      /* This structure is 36 bytes long on i386 */
@@ -164,7 +171,7 @@
 values are (found in <scsi/scsi.h>):
 /* N.B. 1 bit offset from usual SCSI status values */
 #define GOOD                 0x00
-#define CHECK_CONDITION      0x01  
+#define CHECK_CONDITION      0x01
 #define CONDITION_GOOD       0x02
 #define BUSY                 0x04
 #define INTERMEDIATE_GOOD    0x08
@@ -175,7 +182,7 @@
 When the 'target_status' is CHECK_CONDITION or COMMAND_TERMINATED the
 'sense_buffer' is output. Note that when (driver_status & DRIVER_SENSE)
 is true then the 'sense_buffer' is also output (this seems to occur when
-the ide-scsi emulation is used). When the 'sense_buffer' is output the 
+the ide-scsi emulation is used). When the 'sense_buffer' is output the
 SCSI Sense Key can be found at (sense_buffer[2] & 0x0f) .
 
 The 'host_status' field is always output and has the following values
@@ -269,12 +276,12 @@
 Returns a file descriptor if >= 0 , otherwise -1 implies an error.
 
 Error codes (value in 'errno' after -1 returned):
-EACCES          Either the user doesn't have appropriate permissions on 
+EACCES          Either the user doesn't have appropriate permissions on
                 'filename' or attempted to use both O_RDONLY and O_EXCL
 EBUSY           O_NONBLOCK set and some user of this sg device has O_EXCL
                 set while someone is already using this device
 EINTR           while waiting for an "exclusive" lock to clear, a signal
-                is received, just try again ...        
+                is received, just try again ...
 ENODEV          sg not compiled into kernel or the kernel cannot find the
                 sg module (or it can't initialize itself (low memory??))
 ENOENT          given filename not found
@@ -320,12 +327,13 @@
                 This is more likely to happen when queuing commands,
                 so wait a bit (eg usleep(10000) ) before trying again
 EDOM            a) command queuing off: a packet is already queued
-                b) command queuing on: too many packets queued 
+                b) command queuing on: too many packets queued
                    (SG_MAX_QUEUE exceeded)
-                c) SCSI command length given in SG_NEXT_CMD_LEN too long
 EFAULT          'buffer' for 'count' bytes is an invalid memory range
-EIO             incoming buffer too short. It should be at least (6 +
-                sizeof(struct sg_header))==42 bytes long
+EIO             a) incoming buffer too short. It should be at least
+                   (6 + sizeof(struct sg_header))==42 bytes long
+                b) SCSI command length given in SG_NEXT_CMD_LEN too long
+                c) reply_len negative
 ENOMEM          can't get memory for DMA. Take evasive action ...
 ENXIO           either scsi sub-system is currently processing some error
                 (eg doing a device reset) or the sg driver/module removed
@@ -334,7 +342,7 @@
 
 read(int sg_fd, void * buffer, size_t count)
 --------------------------------------------
-Read() is used to receive a packet containing 1 mandatory part and 1 
+Read() is used to receive a packet containing 1 mandatory part and 1
 optional part. The mandatory part is:
   - a control block (an instance of struct sg_header)
 The optional part is:
@@ -343,7 +351,7 @@
 sufficient to accommodate this packet to avoid truncation. Truncation occurs
 if count < sg_header::replylen .
 
-By default, read() will return the oldest packet queued up. If the 
+By default, read() will return the oldest packet queued up. If the
 SG_SET_FORCE_PACK_ID,1 ioctl() is active then read() will attempt to
 fetch the packet whose pack_id (given earlier to write()) matches the
 sg_header::pack_id given to this read(). If not available it will either
@@ -356,12 +364,16 @@
 DMA-ed by the SCSI device. This driver is currently unable to provide
 such an underrun indication.
 
+If the SCSI device reports an error then a REQUEST SENSE is automatically
+done and the output is placed in the sense_buffer array which is in the
+control block. This action is sometimes called "auto-sense".
+
 Error codes (value in 'errno' after -1 returned):
 EAGAIN          either no waiting packet or requested packet is not
                 available while O_NONBLOCK flag was set
 EFAULT          'buffer' for 'count' bytes is an invalid memory range
 EINTR           while waiting for a packet, a signal is received, just
-                try again ...        
+                try again ...
 EIO             if the 'count' given to read() is < sizeof(struct sg_header)
                 and the 'result' element in sg_header is non-zero. Not a
                 recommended error reporting technique
@@ -380,11 +392,11 @@
 flight".
 
 A process that has an open file descriptor to an sg device may be aborted
-(eg by a kill signal). In this case, the kernel automatically calls close 
+(eg by a kill signal). In this case, the kernel automatically calls close
 (which is called 'sg_release()' in the version 2 driver) to facilitate
 the cleanup mentioned above.
 
-A problem persists in version 2.1.34 if the sg driver is a module and is
+A problem persists in version 2.1.36 if the sg driver is a module and is
 removed while packets are still "in flight".
 
 Returns 0 if successful, otherwise -1 implies an error.
@@ -394,7 +406,7 @@
 
 ioctl(int sg_fd, int command, ...)  [sg specific]
 -------------------------------------------------
-Ken Thompson (or perhaps some other Unix luminary) described ioctl() as 
+Ken Thompson (or perhaps some other Unix luminary) described ioctl() as
 the "garbage bin of Unix". This driver compounds the situation by adding
 more ...
 If a ioctl command is not recognized by sg (and the various lower levels
@@ -417,7 +429,8 @@
 for this file descriptor. The unit is a "jiffy". Packets that are
 already "in flight" will not be affected. The default value is set
 on open() and is SG_DEFAULT_TIMEOUT (defined in sg.h). This default is
-currently 1 minute and may not be long enough for formats.
+currently 1 minute and may not be long enough for formats. Negative
+values will yield an EIO error.
 
 SG_EMULATED_HOST:
 Assumes 3rd argument points to an int and outputs a flag indicating
@@ -426,33 +439,31 @@
 while 0 is not.
 
 SG_SET_TRANSFORM  W:
-Third argument is ignored. Only is meaningful when SG_EMULATED host has
-yielded 1 (ie the low-level is the ide-scsi device driver); otherwise
-an EINVAL error occurs. The default state is to _not_ transform SCSI
-commands to the corresponding ATAPI commands but pass them straight
-through as is. [Only certain classes of SCSI commands need to be
-transformed to their ATAPI equivalents.] Making this ioctl command causes
-transforms to occur thereafter. Subsequent calls to this ioctl command
-have no additional effect. Beware, this state will affect all devices
-(and hence all related sg file descriptors) associated with this ide-scsi
-"bus".
-The author of ide-scsi has pointed out that this is not the intended
-behaviour which is a 3rd argument of 0 to disable transforms and 1 to
-enable transforms. Note the 3rd argument is an 'int' not a 'int *'.
-Perhaps the intended behaviour will be implemented soon.
+Only is meaningful when SG_EMULATED host has yielded 1 (i.e. the low-level
+is the ide-scsi device driver); otherwise an EINVAL error occurs. The
+default state is to _not_ transform SCSI commands to the corresponding
+ATAPI commands but pass them straight through as is. [Only certain classes
+of SCSI commands need to be transformed to their ATAPI equivalents.]
+The third argument is interpreted as an integer. When it is non-zero then
+a flag is set inside the ide-scsi driver that transforms subsequent
+commands sent to this driver. When zero is passed as the 3rd argument to
+this ioctl then the flag within the ide-scsi driver is cleared and
+subsequent commands are not transformed. Beware, this state will affect
+all devices (and hence all related sg file descriptors) associated with
+this ide-scsi "bus".
 
 SG_GET_TRANSFORM:
 Third argument is ignored. Only is meaningful when SG_EMULATED host has
 yielded 1 (ie the low-level is the ide-scsi device driver); otherwise
 an EINVAL error occurs. Returns 0 to indicate _not_ transforming SCSI
-to ATAPI commands (default). Returns 1 when it is transforming.
+to ATAPI commands (default). Returns 1 when it is transforming them.
 
 SG_SET_FORCE_LOW_DMA +:
 Assumes 3rd argument points to an int containing 0 or 1. 0 (default)
 means sg decides whether to use memory above 16 Mbyte level (on i386)
 based on the host adapter being used by this SCSI device. Typically
 PCI SCSI adapters will indicate they can DMA to the whole 32 bit address
-space. 
+space.
 If 1 is given then the host adapter is overridden and only memory below
 the 16MB level is used for DMA. A requirement for this should be
 extremely rare. If the "reserved" buffer allocated on open() is not in
@@ -469,15 +480,21 @@
 
 SG_GET_SCSI_ID +:
 Assumes 3rd argument is pointing to an object of type Sg_scsi_id (see
-sg.h) and populates it. That structure contains ints for host_no, 
-channel, scsi_id, lun and scsi_type. Most of this information is 
-available from other sources (eg SCSI_IOCTL_GET_IDLUN and 
-SCSI_IOCTL_GET_BUS_NUMBER) but tends to be awkward to collect.
+sg.h) and populates it. That structure contains ints for host_no,
+channel, scsi_id, lun, scsi_type, allowable commands per lun and
+queue_depth. Most of this information is available from other sources
+(eg SCSI_IOCTL_GET_IDLUN and SCSI_IOCTL_GET_BUS_NUMBER) but tends to be
+awkward to collect.
+Allowable commands per lun and queue_depth give an insight to the
+command queuing capabilities of the adapters and the device. The latter
+overrides the former (logically) and the former is only of interest
+if it is equal to queue_depth which probably indicates the device
+does not support queueing commands (e.g. most scanners).
 
 SG_SET_FORCE_PACK_ID +:
 Assumes 3rd argument is pointing to an int. 0 (default) instructs read()
 to return the oldest (written) packet if multiple packets are
-waiting to be read (when command queuing is being used). 
+waiting to be read (when command queuing is being used).
 1 instructs read() to view the sg_header::pack_id as input and return the
 oldest packet matching that pack_id or wait until it arrives (or yield
 EAGAIN if O_NONBLOCK is in force). As a special case the pack_id of -1
@@ -524,7 +541,7 @@
 device then an EBUSY error occurs. Per device sequencing was the original
 semantics and allowed, for example different processes to "share" the
 device, one perhaps write()ing with the other one read()ing. This command
-is supplied if anyone needs those semantics. Per file descriptor 
+is supplied if anyone needs those semantics. Per file descriptor
 sequencing, perhaps with the use of the O_EXCL flag, seems more sensible.
 
 SG_GET_MERGE_FD +:
@@ -548,7 +565,7 @@
 SG_SET_UNDERRUN_FLAG +:
 Assumes 3rd argument is pointing to an int. 0 (current default, set by
 SG_DEF_UNDERRUN_FLAG in sg.h) requests underruns be ignored. 1 requests
-that underruns be flagged. [The only low level driver that acts on this 
+that underruns be flagged. [The only low level driver that acts on this
 at the moment is the aic7xxx which yields a DID_ERROR error on underrun.]
 Only the current file descriptor is affected by this command (unless
 "per device" sequencing has been selected).
@@ -571,7 +588,13 @@
 
 SG_GET_VERSION_NUM +:
 Assumes 3rd argument points to an int. The version number is then placed
-in that int. A sg version such as 2.1.34 will yield "20134" from this ioctl.
+in that int. A sg version such as 2.1.36 will yield "20136" from this ioctl.
+
+SG_SCSI_RESET +:
+Assumes 3rd argument points to an int. Unfortunately doesn't currently
+do much (may in the future after other issues are resolved). Yields an
+EBUSY error if the SCSI bus or the associated device is being reset
+when this ioctl() is called, otherwise returns 0.
 
 SG_SET_DEBUG +:
 Assumes 3rd argument is pointing to an int. 0 (default) turns debugging
@@ -641,13 +664,16 @@
 
 Utility and Test Programs
 =========================
-See the README file in the sg_utils<date>.tgz tarball. At the time of
-writing this was sg_utils990527.tgz .
+See the README file in the sg_utils<date>.tgz tarball. Look on the
+http://www.torque.net/sg website for the latest version.
 
 Briefly, that tarball contains the following utilities:
 sg_dd512        'dd' like program that assumes 512 byte blocks size
 sg_dd2048       'dd' like program that assumes 2048 byte blocks size
+sg_dd2352       'dd' like program that assumes 2352 byte blocks size
 sgq_dd512       like 'sg_dd512' but does command queuing on "if"
+sgp_dd          probably the most flexible 'dd' variant. It uses POSIX
+                threads, block size set by "bs=..." plus other options.
 sg_scan         outputs information (optionally Inquiry) on SCSI devices
 sg_rbuf         tests SCSI bus transfer speed (without physical IO)
 sg_whoami       outputs info (optionally capacity) of given SCSI device
@@ -657,6 +683,9 @@
 It also contains the following test programs:
 sg_debug        outputs sg driver state to console/log file
 sg_poll         tests asynchronous notification
+sg_runt_ex      example run time selection program for application authors
+sg_simple1      example program first time users
+sg_simple2      like sg_simple1 but with more primitive error processing
 sg_inquiry      does a SCSI Inquiry command (from original HOWTO)
 sg_tst_med      checks presence of media (from original HOWTO)
 
@@ -664,36 +693,40 @@
 SCSI 2 errors and warnings. This code is used by most of the above
 utility and test programs.
 
-The following programs: sg_dd512, sg_dd2048, sg_scan, sg_rbuf, sg_tst_med, 
-sg_inquiry and sginfo, can be compiled either for this new sg driver _or_
-the original sg driver.
+The following programs: sg_dd512, sg_dd2048, sg_dd2352, sg_scan, sg_runt_ex,
+sg_rbuf, sg_tst_med, sg_inquiry and sginfo, can be compiled either for this
+new sg driver _or_ the original sg driver (in 2.0 or 2.2 series kernels).
+sg_runt_ex can be run on 2.0, 2.2 or 2.3 series kernels even if it is
+compiled on a different series (eg compiled on 2.0, run on 2.2).
 
 
 Header files
 ============
 User applications need to find the correct "sg.h" header file matching
-their kernel in order to write code using the sg device driver. This is 
+their kernel in order to write code using the sg device driver. This is
 sometimes more difficult than it should be. The correct "sg.h" will usually
-be found at /usr/src/linux/include/scsi/sg.h . Another important header 
+be found at /usr/src/linux/include/scsi/sg.h . Another important header
 file is "scsi.h" which will be in the same directory.
 
-Several distributions have taken their own copies of these files and placed
-them in /usr/include/scsi which is where "#include <scsi/sg.h>" would go
-looking. The directory /usr/include/scsi _should_ be a symbolic link to
-/usr/src/linux/include/scsi/ . It was is Redhat 5.1 and 5.2 but it is
-not is Redhat 6.0 . Some other distributions have the same problem. To
-solve this (as root) do the following:
-
-# cd /usr/include
-# mv scsi scsi_orig
-# ln -s ../src/linux/include/scsi scsi
-
-This doesn't seem to be a problem with /usr/include/linux (at least in
-Redhat where it is a symbolic link) so it is hard to understand why
-/usr/include/scsi is defined the way it is. The fact the
-/usr/include/linux is a symbolic link opens up the following solution
-proposed by the author of cdparanoia (Monty):
-#include <linux/../scsi/sg.h>
+When "#include <scsi/sg.h>" is written in an application then this refers
+to the file /usr/include/scsi/sg.h . A problem sometimes arises because
+the files in the /usr/include/scsi directory are controlled by the GNU
+library people who maintain glibc. Unfortunately these 2 versions of
+the sg.h header file are not always in sync. [This was the case in Redhat
+6.0 and 6.1 .] Glibc 2.1.3 and later versions should get this right.
+
+If this is a problem, the user may need to copy sg.h (and scsi.h) from
+the kernel source includes to /usr/include scsi. If the user can change
+the effected source code then another approach is to rely on the fact that
+/usr/src/linux is a symbolic link to /usr/src/linux/include/linux and
+change the sg.h include to look like:
+    #include <linux/../scsi/sg.h>
+This solution is used by the author of cdparanoia (Monty) in his application.
+
+[Former scsi generic documents suggested adding a symbolic link to
+bypass this problem but that is not popular with the glibc maintainers.
+I would like to thank Andreas Jaeger <aj@suse.de> for his contributions
+on this subject.]
 
 
 Extra information in scsi-generic_long.txt
@@ -709,6 +742,27 @@
    - shortcomings
    - future directions
    - an appendix with some SCSI 2 information in it
+
+
+References
+==========
+http://www.t10.org      Very important site for SCSI related information.
+                        Contains SCSI 2 and 3 draft standards.
+http://www.andante.org/scsi.html
+                        This is Eric Youngdale's site. Eric is primarily
+                        responsible for the Linux SCSI architecture and
+                        its mid-level implementation.
+http://www.kernel.dk    Jens Axboe's site for Linux cdrom matters including
+                        the SCSI "sr" driver.
+http://www.torque.net/sg
+                        My site with sg related information.
+newsgroup:linux-scsi@vger.rutgers.edu
+                        Newsgroup for Linux related SCSI matters
+/usr/src/linux/MAINTAINERS
+                        This is a file in the Linux kernel source that
+                        contains up to date information about who maintains
+                        what and where information can be found. Links to
+                        SCSI adapter information are also here.
 
 
 Conclusion
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/Documentation/sound/Maestro linux.15p9/Documentation/sound/Maestro
--- linux.vanilla/Documentation/sound/Maestro	Tue Jan  4 21:18:38 2000
+++ linux.15p9/Documentation/sound/Maestro	Wed Feb  9 15:46:57 2000
@@ -24,7 +24,7 @@
 
 The various families of Maestro are mostly identical as far as this 
 driver is concerned.  It doesn't touch the DSP parts that differ (though
-it could for FM synthesis)
+it could for FM synthesis).
 
 Driver OSS Behavior
 --------------------
@@ -91,8 +91,33 @@
 ( dsps_order=2 ).  These devices act as fully distinct units and use
 separate channels in the maestro.
 
+Power Management
+----------------
+
+As of version 0.14, this driver has a minimal understanding of PCI
+Power Management.  If it finds a valid power management capability
+on the PCI device it will attempt to use the power management
+functions of the maestro.  It will only do this on Maestro 2Es and
+only on machines that are known to function well.  You can
+force the use of power management by setting the 'use_pm' module
+option to 1, or can disable it entirely by setting it to 0.
+
+When using power management, the driver does a few things
+differently.  It will keep the chip in a lower power mode
+when the module is inserted but /dev/dsp is not open.  This
+allows the mixer to function but turns off the clocks
+on other parts of the chip.  When /dev/dsp is opened the chip
+is brought into full power mode, and brought back down
+when it is closed.  It also powers down the chip entirely
+when the module is removed or the machine is shutdown.  This
+can have nonobvious consequences.  CD audio may not work
+after a power managing driver is removed.  Also, software that
+doesn't understand power management may not be able to talk
+to the powered down chip until the machine goes through a hard
+reboot to bring it back.
+
 .. more details ..
------------------
+------------------
 
 drivers/sound/maestro.c contains comments that hopefully explain
 the maestro implementation.
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/Documentation/sysrq.txt linux.15p9/Documentation/sysrq.txt
--- linux.vanilla/Documentation/sysrq.txt	Sat Aug 28 20:00:53 1999
+++ linux.15p9/Documentation/sysrq.txt	Wed Feb 16 18:35:24 2000
@@ -35,7 +35,7 @@
 'b'     - Will immediately reboot the system without syncing or unmounting
           your disks.
 
-'o'     - Will shut your system off via APM (if configured and supported).
+'o'     - Will shut your system off (if configured and supported).
 
 's'     - Will attempt to sync all mounted filesystems.
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/Documentation/video4linux/README.cpia linux.15p9/Documentation/video4linux/README.cpia
--- linux.vanilla/Documentation/video4linux/README.cpia	Thu Jan  1 01:00:00 1970
+++ linux.15p9/Documentation/video4linux/README.cpia	Mon Feb  7 12:30:39 2000
@@ -0,0 +1,204 @@
+This is a driver for the CPiA PPC2 driven parallel connected
+Camera. For example the Creative WebcamII is CPiA driven.
+
+   Š [1]Peter Pregler, Linz 2000, published under the [2]GNU GPL
+
+---------------------------------------------------------------------------
+
+USAGE:
+
+General:
+========
+
+1) Make sure you have created the video devices (/dev/video*):
+
+- if you have a recent MAKEDEV do a 'cd /dev;./MAKEDEV video'
+- otherwise do a:
+
+cd /dev
+mknod video0 c 81 0
+ln -s video0 video
+
+2) Compile the kernel (see below for the list of options to use),
+   configure your parport and reboot.
+
+3) If all worked well you should get messages similar
+   to the following (your versions may be different) on the console:
+
+V4L-Driver for Vision CPiA based cameras v0.5.0
+parport0: read2 timeout.
+parport0: Multimedia device, VLSI Vision Ltd PPC2
+Parallel port driver for Vision CPiA based camera
+  using DMA mode (irq 7, DMA 3)
+  CPIA Version: 1.20 (2.0)
+  CPIA PnP-ID: 0553:0002:0100
+  VP-Version: 1.0 0100
+  1 camera(s) found
+
+
+As modules:
+===========
+
+Make sure you have selected the following kernel options (you can
+select all stuff as modules):
+
+The cpia-stuff is in the section 'Character devices -> Video For Linux'.
+The PnP-stuff is in the section 'Plug and Play support'.
+The parport-stuff is in the section 'General setup'.
+
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PNP=y
+CONFIG_PNP_PARPORT=m
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_CPIA=m
+CONFIG_VIDEO_CPIA_PP=m
+CONFIG_VIDEO_CPIA_PP_DMA=y
+
+For autoloading of all those modules you need to tell kerneld some
+stuff. Add the following line to your kerneld config-file
+(e.g. /etc/modules.conf or wherever your distribution does store that
+stuff):
+
+options parport_pc dma=3 irq=7
+alias char-major-81 cpia_pp
+
+The first line tells the dma/irq channels to use. Those _must_ match
+the settings of your BIOS. Do NOT simply use the values above.  See
+Documentation/parport.txt for more information about this. The second
+line associates the video-device file with the driver. Of cause you
+can also load the modules once upon boot (usually done in /etc/modules).
+
+Linked into the kernel:
+=======================
+
+Make sure you have selected the following kernel options. Note that
+you cannot compile the parport-stuff as modules and the cpia-driver
+statically (the other way round is okay though).
+
+The cpia-stuff is in the section 'Character devices -> Video For Linux'.
+The PnP-stuff is in the section 'Plug and Play support'.
+The parport-stuff is in the section 'General setup'.
+
+CONFIG_PARPORT=y
+CONFIG_PARPORT_PC=y
+CONFIG_PNP=y
+CONFIG_PNP_PARPORT=y
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_CPIA=y
+CONFIG_VIDEO_CPIA_PP=y
+CONFIG_VIDEO_CPIA_PP_DMA=y
+
+To use DMA/irq you will need to tell the kernel upon boot time the
+hardware configuration of the parport. You can give the boot-parameter
+at the LILO-prompt or specify it in lilo.conf. I use the following
+append-line in lilo.conf:
+
+        append="parport=0x378,7,3"
+
+See Documentation/parport.txt for more information about the
+configuration of the parport and the values given above. Do not simply
+use the values given above.
+
+---------------------------------------------------------------------------
+FEATURES:
+
+- mmap/read v4l-interface (but no overlay)
+- image formats: CIF/QCIF, SIF/QSIF, various others used by isabel;
+  note: all sizes except CIF/QCIF are implemented by clipping, i.e.
+  pixels are not uploaded from the camera
+- palettes: VIDEO_PALETTE_GRAY, VIDEO_PALETTE_RGB565, VIDEO_PALETTE_RGB555,
+  VIDEO_PALETTE_RGB24, VIDEO_PALETTE_RGB32, VIDEO_PALETTE_YUYV,
+  VIDEO_PALETTE_UYVY, VIDEO_PALETTE_YUV422
+- DMA-transfer for Intel-architecture
+- state information (color balance, exposure, ...) is preserved between
+  device opens
+- complete control over camera via proc-interface (_all_ camera settings are
+  supported), there is also a python-gtk application available for this
+- works under SMP (but the driver is completly serialized and synchronous)
+  so you get no benefit from SMP
+- might work for non-Intel architecture, let me know about this
+
+---------------------------------------------------------------------------
+TESTED APPLICATIONS:
+
+- a simple test application based on Xt is available at [3]
+- another test-application based on gqcam-0.4 (uses GTK)
+- gqcam-0.5 should work
+- xawtv-3.x (also the webcam)
+- xawtv-2.46
+- w3cam (cgi-interface and vidcat, e.g. you may try out 'vidcat  |xv
+  -maxpect -root -quit +noresetroot -rmode 5 -')
+- vic, the MBONE video conferencing tool (version 2.8ucl4-1)
+- isabel 3R4beta (barely working, but AFAICT all the problems are on
+  their side)
+- camserv-0.40
+
+See [3] for pointers to v4l-applications.
+
+---------------------------------------------------------------------------
+KNOWN PROBLEMS:
+
+- some applications do not handle the image format correctly, you will
+  see strange horizontal stripes instead of a nice picture -> make sure
+  your application does use a supported image size or queries the driver
+  for the actually used size (reason behind this: the camera cannot
+  provide any image format, so if size NxM is requested the driver will
+  use a format to the closest fitting N1xM1, the application should now
+  query for this granted size, most applications do not).
+- all the todo ;)
+- if there is not enough light and the picture is too dark try to
+  adjust the SetSensorFPS setting, automatic frame rate adjustment
+  has its price
+- do not try out isabel 3R4beta (built 135), you will be disappointed
+- my linux box crashed during a ppp-dialup session lately for an unknown
+  reason, the driver was idle, but who knows. So there might be
+  so buffer overflow somewhere, you are warned anyway
+
+---------------------------------------------------------------------------
+TODO:
+
+- port to linux 2.3.X
+- using ieee1284 support in the kernel (when it works)
+- multiple camera support (struct camera or something) - This should work,
+  but hasn't been tested yet.
+- architecture independence
+- integrate USB support
+- SMP-safe asynchronous mmap interface
+- nibble mode for old parport interfaces
+- streamin capture, this should give a performance gain
+
+---------------------------------------------------------------------------
+IMPLEMENTATION NOTES:
+
+The camera can act in two modes, streaming or grabbing. Right now a
+polling grab-scheme is used. Maybe interrupt driven streaming will be
+used for a ansychronous mmap interface in the next major release of the
+driver. This might give a better frame rate.
+
+---------------------------------------------------------------------------
+THANKS (in no particular order):
+
+- Karoly Erdei <Karoly.Erdei@risc.uni-linz.ac.at> and RISC-Linz for being
+  my boss ;) resp. my employer and for providing me the hardware and
+  allow me to devote some working time to this project
+- Bas Huisman <bhuism@cs.utwente.nl> for writing the initial parport code
+- Scott J. Bertin <sbertin@mindspring.com> for cleanups, the proc-filesystem
+  and much more
+- Jarl Totland <Jarl.Totland@bdc.no> for setting up the mailing list 
+  and maintaining the web-server[3]
+- Manuel J. Petit de Gabriel <mpetit@dit.upm.es> for providing help
+  with Isabel (http://isabel.dit.upm.es/)
+- Henry Bruce <whb@vvl.co.uk> for providing developers information about
+  the CPiA chip, I wish all companies would treat Linux as seriously
+- FIXME for fixes related to the 1.02 firmware
+- special kudos to all the tester whose machines crashed and/or
+  will crash. :)
+
+---------------------------------------------------------------------------
+REFERENCES
+
+   1. http://www.risc.uni-linz.ac.at/people/ppregler
+      mailto:Peter_Pregler@email.com
+   2. see the file COPYING in the top directory of the kernel tree
+   3. http://home.eunet.no/~jtotland/vision/
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/MAINTAINERS linux.15p9/MAINTAINERS
--- linux.vanilla/MAINTAINERS	Tue Jan  4 21:18:38 2000
+++ linux.15p9/MAINTAINERS	Wed Feb  9 15:45:54 2000
@@ -216,7 +216,7 @@
 
 CYCLADES ASYNC MUX DRIVER
 P:	Ivan Passos
-M:	Ivan Passos <ivan@cyclades.com>
+M:	ivan@cyclades.com
 W:	http://www.cyclades.com/
 S:	Supported
 
@@ -463,6 +463,12 @@
 W:	http://www.suse.cz/development/joystick/
 S:	Maintained
 
+KCTT DRIVER FOR ANTENNA ROTORS
+P:	Jean-Paul Roubelat
+M:	jpr@f6fbb.org
+L:	linux-hams@vger.rutgers.edu
+S:	Maintained
+
 KERNEL AUTOMOUNTER (AUTOFS)
 P:	H. Peter Anvin
 M:	hpa@zytor.com
@@ -476,6 +482,12 @@
 W:	http://csua.berkeley.edu/~gam3/knfsd
 S:	Maintained
 
+LANMEDIA WAN CARD DRIVER
+P:	Andrew Stanley-Jones
+M:	asj@lanmedia.com
+W:      http://www.lanmedia.com/
+S:	Supported
+
 LAPB module
 P:	Henner Eisen
 M:	eis@baty.hanse.de
@@ -542,8 +554,8 @@
 S:	Maintained
 
 MODULE SUPPORT [GENERAL], KERNELD
-P:	Richard Henderson
-M:	richard@gnu.ai.mit.edu
+P:	Keith Owens
+M:	kaos@ocs.com.au
 L:	linux-kernel@vger.rutgers.edu
 S:	Maintained
 
@@ -694,6 +706,13 @@
 L:	linux-ppp@vger.rutgers.edu
 S:	Maintained
 
+QNX4 FILESYSTEM
+P:	Anders Larsen
+M:	al@alarsen.net
+L:	linux-kernel@vger.rutgers.edu
+W:	http://www.alarsen.net/linux/qnx4fs/
+S:	Maintained
+
 REAL TIME CLOCK DRIVER
 P:	Paul Gortmaker
 M:	p_gortmaker@yahoo.com
@@ -701,8 +720,8 @@
 S:	Maintained
 
 ROSE NETWORK LAYER
-P:	Frederic Rible
-M:	frible@teaser.fr
+P:	Jean-Paul Roubelat
+M:	jpr@f6fbb.org
 L:	linux-hams@vger.rutgers.edu
 S:	Maintained
 
@@ -712,6 +731,13 @@
 L:	linux-kernel@vger.rutgers.edu
 S:	Maintained
 
+RTLINUX  REALTIME  LINUX
+P:	Victor Yodaiken
+M:	yodaiken@fsmlabs.com
+L:	rtl@rtlinux.org
+W:	www.rtlinux.org
+S:	Maintained
+
 SBPCD CDROM DRIVER
 P:	Eberhard Moenkeberg
 M:	emoenke@gwdg.de
@@ -795,9 +821,7 @@
 S:	Supported
 
 STALLION TECHNOLOGIES MULTIPORT SERIAL BOARDS
-P:	Greg Ungerer
 M:	support@stallion.oz.au
-M:	gerg@stallion.com
 W:	http://www.stallion.com
 S:	Supported
 
@@ -902,6 +926,12 @@
 P:	Henner Eisen
 M:	eis@baty.hanse.de
 L:	linux-x25@vger.rutgers.edu
+S:	Maintained
+
+YAM DRIVER FOR AX.25
+P:	Jean-Paul Roubelat
+M:	jpr@f6fbb.org
+L:	linux-hams@vger.rutgers.edu
 S:	Maintained
 
 Z85230 SYNCHRONOUS DRIVER
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/Makefile linux.15p9/Makefile
--- linux.vanilla/Makefile	Tue Jan  4 21:18:38 2000
+++ linux.15p9/Makefile	Thu Feb 17 23:04:25 2000
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 2
-SUBLEVEL = 14
-EXTRAVERSION = 
+SUBLEVEL = 15
+EXTRAVERSION = pre9
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
@@ -313,7 +313,7 @@
 MODFLAGS += -DMODVERSIONS -include $(HPATH)/linux/modversions.h
 endif
 
-modules: $(patsubst %, _mod_%, $(SUBDIRS))
+modules: include/config/MARKER $(patsubst %, _mod_%, $(SUBDIRS))  
 
 $(patsubst %, _mod_%, $(SUBDIRS)) : include/linux/version.h
 	$(MAKE) -C $(patsubst _mod_%, %, $@) CFLAGS="$(CFLAGS) $(MODFLAGS)" MAKING_MODULES=1 modules
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/alpha/kernel/Makefile linux.15p9/arch/alpha/kernel/Makefile
--- linux.vanilla/arch/alpha/kernel/Makefile	Tue Jan  4 21:18:38 2000
+++ linux.15p9/arch/alpha/kernel/Makefile	Thu Jan 13 22:46:56 2000
@@ -134,7 +134,7 @@
 	./check_asm > $(TOPDIR)/include/asm-alpha/asm_offsets.h
 
 check_asm: check_asm.c
-	gcc -o $@ $< -I$(TOPDIR)/include -D__KERNEL__ -ffixed-8
+	$(CC) -o $@ $< -I$(TOPDIR)/include -D__KERNEL__ -ffixed-8
 
 clean::
 	rm -f check_asm
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/alpha/kernel/irq.c linux.15p9/arch/alpha/kernel/irq.c
--- linux.vanilla/arch/alpha/kernel/irq.c	Tue Jan  4 21:18:39 2000
+++ linux.15p9/arch/alpha/kernel/irq.c	Thu Feb 17 19:43:55 2000
@@ -893,11 +893,11 @@
 	printk("PC = %016lx PS=%04lx\n", regs.pc, regs.ps);
 }
 
-void __init
-init_IRQ(void)
+unsigned long __init init_IRQ(unsigned long memory)
 {
 	wrent(entInt, 0);
 	alpha_mv.init_irq();
+	return memory;
 }
 
 /*
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/alpha/kernel/sys_nautilus.c linux.15p9/arch/alpha/kernel/sys_nautilus.c
--- linux.vanilla/arch/alpha/kernel/sys_nautilus.c	Tue Jan  4 21:18:39 2000
+++ linux.15p9/arch/alpha/kernel/sys_nautilus.c	Thu Jan 13 22:35:04 2000
@@ -30,6 +30,7 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/reboot.h>
+#include <linux/mc146818rtc.h>
 
 #include <asm/ptrace.h>
 #include <asm/system.h>
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/alpha/mm/fault.c linux.15p9/arch/alpha/mm/fault.c
--- linux.vanilla/arch/alpha/mm/fault.c	Tue Jan  4 21:18:39 2000
+++ linux.15p9/arch/alpha/mm/fault.c	Tue Jan 18 00:54:47 2000
@@ -150,8 +150,10 @@
 	if ((fixup = search_exception_table(regs->pc)) != 0) {
 		unsigned long newpc;
 		newpc = fixup_exception(dpf_reg, fixup, regs->pc);
+#if 0
 		printk("%s: Exception at [<%lx>] (%lx)\n",
 		       current->comm, regs->pc, newpc);
+#endif
 		regs->pc = newpc;
 		goto out_unlock;
 	}
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/arm/kernel/irq.c linux.15p9/arch/arm/kernel/irq.c
--- linux.vanilla/arch/arm/kernel/irq.c	Wed Dec 23 17:44:40 1998
+++ linux.15p9/arch/arm/kernel/irq.c	Thu Feb 17 13:44:04 2000
@@ -414,7 +414,7 @@
  */
 #include <asm/arch/irq.h>
 
-__initfunc(void init_IRQ(void))
+unsigned long __init init_IRQ(unsigned long memory)
 {
 	extern void init_dma(void);
 	int irq;
@@ -430,4 +430,5 @@
 	init_FIQ();
 #endif
 	init_dma();
+	return memory;
 }
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/i386/Makefile linux.15p9/arch/i386/Makefile
--- linux.vanilla/arch/i386/Makefile	Wed Oct 20 01:12:33 1999
+++ linux.15p9/arch/i386/Makefile	Thu Jan 13 22:46:56 2000
@@ -65,7 +65,7 @@
 vmlinux: arch/i386/vmlinux.lds
 
 arch/i386/vmlinux.lds: arch/i386/vmlinux.lds.S FORCE
-	gcc -E -C -P -I$(HPATH) -imacros $(HPATH)/asm-i386/page_offset.h -Ui386 arch/i386/vmlinux.lds.S >arch/i386/vmlinux.lds
+	$(CPP) -C -P -I$(HPATH) -imacros $(HPATH)/asm-i386/page_offset.h -Ui386 arch/i386/vmlinux.lds.S >arch/i386/vmlinux.lds
 
 FORCE: ;
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/i386/boot/compressed/head.S linux.15p9/arch/i386/boot/compressed/head.S
--- linux.vanilla/arch/i386/boot/compressed/head.S	Sun Mar 29 20:31:16 1998
+++ linux.15p9/arch/i386/boot/compressed/head.S	Wed Jan 12 01:29:43 2000
@@ -53,7 +53,7 @@
 	xorl %eax,%eax			# Back to 0
 	mov  %cx,%ax			# SP low 16 bits
 	movl %eax,%esp
-	pushl 0				# Clear NT
+	pushl $0			# Clear NT
 	popfl
 	ljmp $(__KERNEL_CS), $0x100000    # Into C and sanity
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/i386/boot/setup.S linux.15p9/arch/i386/boot/setup.S
--- linux.vanilla/arch/i386/boot/setup.S	Sat Aug 14 02:27:13 1999
+++ linux.15p9/arch/i386/boot/setup.S	Wed Feb 16 18:35:24 2000
@@ -343,7 +343,6 @@
 	mov ax,cs		! aka #SETUPSEG
 	sub ax,#DELTA_INITSEG	! aka #INITSEG
 	mov ds,ax
-	mov ds,ax
 	xor ax,ax
 	mov [0xa0], ax		! set table length to 0
 	mov ah, #0xc0
@@ -404,7 +403,11 @@
 	int	0x15		! ignore return code
 
 	mov	ax,#0x05303	! 32 bit connect
-	xor	bx,bx
+	xor	ebx,ebx
+	xor	cx,cx		! paranoia
+	xor	dx,dx		!   ...
+	xor	esi,esi		!   ...
+	xor	di,di		!   ...
 	int	0x15
 	jc	no_32_apm_bios	! error
 
@@ -420,6 +423,7 @@
 !
 	mov	ax,#0x05300	! APM BIOS installation check
 	xor	bx,bx
+	xor	cx,cx		! paranoia
 	int	0x15
 	jc	apm_disconnect	! error -> should not happen, tidy up
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/i386/config.in linux.15p9/arch/i386/config.in
--- linux.vanilla/arch/i386/config.in	Tue Jan  4 21:18:39 2000
+++ linux.15p9/arch/i386/config.in	Wed Feb 16 18:35:24 2000
@@ -104,16 +104,16 @@
 fi
 
 bool 'Advanced Power Management BIOS support' CONFIG_APM
-if [ "$CONFIG_APM" = "y" ]; then
+if [ "$CONFIG_APM" != "n" ]; then
   bool '   Ignore USER SUSPEND' CONFIG_APM_IGNORE_USER_SUSPEND
   bool '   Enable PM at boot time' CONFIG_APM_DO_ENABLE
   bool '   Make CPU Idle calls when idle' CONFIG_APM_CPU_IDLE
   bool '   Enable console blanking using APM' CONFIG_APM_DISPLAY_BLANK
-  bool '   Power off on shutdown' CONFIG_APM_POWER_OFF
   bool '   Ignore multiple suspend' CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
   bool '   Ignore multiple suspend/resume cycles' CONFIG_APM_IGNORE_SUSPEND_BOUNCE
   bool '   RTC stores time in GMT' CONFIG_APM_RTC_IS_GMT
   bool '   Allow interrupts during APM BIOS calls' CONFIG_APM_ALLOW_INTS
+  bool '   Use real mode APM BIOS call to power off' CONFIG_APM_REAL_MODE_POWER_OFF
 fi
 
 endmenu
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/i386/defconfig linux.15p9/arch/i386/defconfig
--- linux.vanilla/arch/i386/defconfig	Sat Aug 28 20:00:53 1999
+++ linux.15p9/arch/i386/defconfig	Fri Jan 21 18:27:35 2000
@@ -96,8 +96,10 @@
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_BLK_DEV_RAM is not set
 # CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_DEV_DAC960 is not set
 CONFIG_PARIDE_PARPORT=y
 # CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_DEV_HD is not set
 
 #
@@ -131,6 +133,12 @@
 # CONFIG_ATALK is not set
 
 #
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+# CONFIG_PHONE_IXJ is not set
+
+#
 # SCSI support
 #
 CONFIG_SCSI=y
@@ -159,6 +167,7 @@
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
@@ -175,6 +184,7 @@
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_NCR53C406A is not set
 # CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_SIM710 is not set
 # CONFIG_SCSI_NCR53C7xx is not set
 # CONFIG_SCSI_NCR53C8XX is not set
 CONFIG_SCSI_SYM53C8XX=y
@@ -201,9 +211,18 @@
 # Network device support
 #
 CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
 # CONFIG_ARCNET is not set
 CONFIG_DUMMY=m
 # CONFIG_EQUALIZER is not set
+# CONFIG_NET_SB1000 is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
 CONFIG_NET_ETHERNET=y
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -214,27 +233,43 @@
 # CONFIG_PCNET32 is not set
 # CONFIG_APRICOT is not set
 # CONFIG_CS89x0 is not set
+# CONFIG_DM9102 is not set
 # CONFIG_DE4X5 is not set
 # CONFIG_DEC_ELCP is not set
+# CONFIG_DEC_ELCP_OLD is not set
 # CONFIG_DGRS is not set
 CONFIG_EEXPRESS_PRO100=y
 # CONFIG_NE2K_PCI is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_SIS900 is not set
 # CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
-# CONFIG_DLCI is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
 # CONFIG_NET_RADIO is not set
+
+#
+# Token ring devices
+#
 # CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+
+#
+# Wan interfaces
+#
 # CONFIG_HOSTESS_SV11 is not set
 # CONFIG_COSA is not set
 # CONFIG_SEALEVEL_4021 is not set
-# CONFIG_RCPCI is not set
+# CONFIG_COMX is not set
+# CONFIG_DLCI is not set
 # CONFIG_WAN_DRIVERS is not set
-# CONFIG_LAPBETHER is not set
-# CONFIG_X25_ASY is not set
+# CONFIG_SBNI is not set
 
 #
 # Amateur Radio support
@@ -242,7 +277,7 @@
 # CONFIG_HAMRADIO is not set
 
 #
-# IrDA subsystem support
+# IrDA (infrared) support
 #
 # CONFIG_IRDA is not set
 
@@ -278,6 +313,11 @@
 CONFIG_PSMOUSE=y
 CONFIG_82C710_MOUSE=y
 # CONFIG_PC110_PAD is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
 # CONFIG_QIC02_TAPE is not set
 # CONFIG_WATCHDOG is not set
 # CONFIG_NVRAM is not set
@@ -287,11 +327,6 @@
 # Video For Linux
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Joystick support
-#
-# CONFIG_JOYSTICK is not set
 # CONFIG_DTLK is not set
 
 #
@@ -327,7 +362,6 @@
 #
 # CONFIG_CODA_FS is not set
 CONFIG_NFS_FS=y
-# CONFIG_NFSD_SUN is not set
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 # CONFIG_SMB_FS is not set
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/i386/kernel/apm.c linux.15p9/arch/i386/kernel/apm.c
--- linux.vanilla/arch/i386/kernel/apm.c	Tue Jan  4 21:18:39 2000
+++ linux.15p9/arch/i386/kernel/apm.c	Wed Feb 16 18:35:24 2000
@@ -1,6 +1,6 @@
 /* -*- linux-c -*-
  * APM BIOS driver for Linux
- * Copyright 1994-1999 Stephen Rothwell (sfr@linuxcare.com)
+ * Copyright 1994-2000 Stephen Rothwell (sfr@linuxcare.com)
  *
  * Initial development of this driver was funded by NEC Australia P/L
  *	and NEC Corporation
@@ -33,6 +33,9 @@
  * Nov 1998, Version 1.7
  * Jan 1999, Version 1.8
  * Jan 1999, Version 1.9
+ * Oct 1999, Version 1.10
+ * Nov 1999, Version 1.11
+ * Jan 2000, Version 1.12
  *
  * History:
  *    0.6b: first version in official kernel, Linux 1.3.46
@@ -90,6 +93,39 @@
  *         Use CONFIG_SMP instead of __SMP__
  *         Ignore BOUNCES for three seconds.
  *         Stephen Rothwell
+ *   1.10: Fix for Thinkpad return code.
+ *         Merge 2.2 and 2.3 drivers.
+ *         Remove APM dependencies in arch/i386/kernel/process.c
+ *         Remove APM dependencies in drivers/char/sysrq.c
+ *         Reset time across standby.
+ *         Allow more inititialisation on SMP.
+ *         Remove CONFIG_APM_POWER_OFF and make it boot time
+ *         configurable (default on).
+ *         Make debug only a boot time parameter (remove APM_DEBUG).
+ *         Try to blank all devices on any error.
+ *   1.11: Remove APM dependencies in drivers/char/console.c
+ *         Fix for bioses that don't zero the top part of the
+ *         entrypoint offset (Mario Sitta <sitta@al.unipmn.it>)
+ *         (reported by Panos Katsaloulis <teras@writeme.com>).
+ *         Real mode power off patch (Walter Hofmann
+ *         <Walter.Hofmann@physik.stud.uni-erlangen.de>).
+ *   1.12: Remove CONFIG_SMP as the compiler will optimize
+ *         the code away anyway (smp_num_cpus == 1 in UP)
+ *         noted by Artur Skawina <skawina@geocities.com>.
+ *         Make power off under SMP work again.
+ *         Fix thinko with initial engaging of BIOS.
+ *         Make sure power off only happens on CPU 0
+ *         (Paul "Rusty" Russell <rusty@linuxcare.com>).
+ *         Do error notification to user mode if BIOS calls fail.
+ *         Move entrypoint offset fix to ...boot/setup.S
+ *         where it belongs (Cosmos <gis88564@cis.nctu.edu.tw>).
+ *         Remove smp-power-off. SMP users must now specify
+ *         "apm=power-off" on the kernel command line. Suggested
+ *         by Jim Avera <jima@hal.com>, modified by Alan Cox
+ *         <alan@lxorguk.ukuu.org.uk>.
+ *         Register the /proc/apm entry even on SMP so that
+ *         scripts that check for it before doing power off
+ *         work (Jim Avera <jima@hal.com>).
  *
  * APM 1.1 Reference:
  *
@@ -106,11 +142,8 @@
  *   Intel Corporation, Microsoft Corporation. Advanced Power Management
  *   (APM) BIOS Interface Specification, Revision 1.2, February 1996.
  *
- * [This document is available from Intel at:
- *    http://www.intel.com/IAL/powermgm
- *  or Microsoft at
- *    http://www.microsoft.com/windows/thirdparty/hardware/pcfuture.htm
- * ]
+ * [This document is available from Microsoft at:
+ *    http://www.microsoft.com/hwdev/busbios/amp_12.htm]
  */
 
 #include <linux/config.h>
@@ -122,21 +155,44 @@
 #include <linux/timer.h>
 #include <linux/fcntl.h>
 #include <linux/malloc.h>
-#include <linux/linkage.h>
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
 #include <linux/miscdevice.h>
 #include <linux/apm_bios.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/desc.h>
+#include <asm/softirq.h>
+
+/* 2.2-2.3 Compatability defines */
+#define DECLARE_WAIT_QUEUE_HEAD(w) struct wait_queue *w = NULL
+#define DECLARE_WAITQUEUE(w,c) struct wait_queue w = {(c), NULL}
+#define __setup(x, y)
+#define module_init(x)
+#define set_current_state(a) current->state = (a)
+#define create_proc_info_entry(n, m, b, g) \
+	{ \
+		struct proc_dir_entry *r = create_proc_entry(n, m, b); \
+		if (r) r->get_info = g; \
+	}
 
 EXPORT_SYMBOL(apm_register_callback);
 EXPORT_SYMBOL(apm_unregister_callback);
 
 extern unsigned long get_cmos_time(void);
+extern void machine_real_restart(unsigned char *, int);
+
+extern void (*acpi_idle)(void);
+extern void (*acpi_power_off)(void);
+#ifdef CONFIG_MAGIC_SYSRQ
+extern void (*sysrq_power_off)(void);
+#endif
+#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
+extern int (*console_blank_hook)(int);
+#endif
 
 /*
  * The apm_bios device is one of the misc char devices.
@@ -144,51 +200,13 @@
  */
 #define	APM_MINOR_DEV	134
 
-/* Configurable options:
- *
- * CONFIG_APM_IGNORE_USER_SUSPEND: define to ignore USER SUSPEND requests.
- * This is necessary on the NEC Versa M series, which generates these when
- * resuming from SYSTEM SUSPEND.  However, enabling this on other laptops
- * will cause the laptop to generate a CRITICAL SUSPEND when an appropriate
- * USER SUSPEND is ignored -- this may prevent the APM driver from updating
- * the system time on a RESUME.
- *
- * CONFIG_APM_DO_ENABLE: enable APM features at boot time.  From page 36 of
- * the specification: "When disabled, the APM BIOS does not automatically
- * power manage devices, enter the Standby State, enter the Suspend State,
- * or take power saving steps in response to CPU Idle calls."  This driver
- * will make CPU Idle calls when Linux is idle (unless this feature is
- * turned off -- see below).  This should always save battery power, but
- * more complicated APM features will be dependent on your BIOS
- * implementation.  You may need to turn this option off if your computer
- * hangs at boot time when using APM support, or if it beeps continuously
- * instead of suspending.  Turn this off if you have a NEC UltraLite Versa
- * 33/C or a Toshiba T400CDT.  This is off by default since most machines
- * do fine without this feature.
- *
- * CONFIG_APM_CPU_IDLE: enable calls to APM CPU Idle/CPU Busy inside the
- * idle loop.  On some machines, this can activate improved power savings,
- * such as a slowed CPU clock rate, when the machine is idle.  These idle
- * call is made after the idle loop has run for some length of time (e.g.,
- * 333 mS).  On some machines, this will cause a hang at boot time or
- * whenever the CPU becomes idle.
- *
- * CONFIG_APM_DISPLAY_BLANK: enable console blanking using the APM.  Some
- * laptops can use this to turn of the LCD backlight when the VC screen
- * blanker blanks the screen.  Note that this is only used by the VC screen
- * blanker, and probably won't turn off the backlight when using X11.  Some
- * problems have been reported when using this option with gpm (if you'd
- * like to debug this, please do so).
- *
- * CONFIG_APM_IGNORE_MULTIPLE_SUSPEND: The IBM TP560 bios seems to insist
- * on returning multiple suspend/standby events whenever one occurs.  We
- * really only need one at a time, so just ignore any beyond the first.
- * This is probably safe on most laptops.
- *
- * If you are debugging the APM support for your laptop, note that code for
- * all of these options is contained in this file, so you can #define or
- * #undef these on the next line to avoid recompiling the whole kernel.
+/*
+ * See Documentation/Config.help for the configuration options.
  *
+ * Various options can be changed at boot time as follows:
+ *	apm=on/off			enable/disable APM
+ *	    [no-]debug			log some debugging messages
+ *	    [no-]power-off		power off on shutdown
  */
 
 /* KNOWN PROBLEM MACHINES:
@@ -207,11 +225,6 @@
  */
 
 /*
- * Define to have debug messages.
- */
-#undef APM_DEBUG
-
-/*
  * Define to always call the APM BIOS busy routine even if the clock was
  * not slowed by the idle routine.
  */
@@ -255,7 +268,7 @@
 
 /*
  * If CONFIG_APM_IGNORE_SUSPEND_BOUNCE is defined then
- * ignore suspend events for this amount of time
+ * ignore suspend events for this amount of time after a resume
  */
 #define BOUNCE_INTERVAL		(3 * HZ)
 
@@ -266,25 +279,32 @@
 		__asm__ __volatile__("movl %%" #seg ",%0" : "=m" (where))
 
 /*
- * Forward declarations
+ * Maximum number of events stored
  */
-static void	suspend(void);
-static void	standby(void);
-static void	set_time(void);
-
-static void	check_events(void);
-static void	do_apm_timer(unsigned long);
-
-static int	do_open(struct inode *, struct file *);
-static int	do_release(struct inode *, struct file *);
-static ssize_t	do_read(struct file *, char *, size_t , loff_t *);
-static unsigned int do_poll(struct file *, poll_table *);
-static int	do_ioctl(struct inode *, struct file *, u_int, u_long);
+#define APM_MAX_EVENTS		20
 
-static int	apm_get_info(char *, char **, off_t, int, int);
+/*
+ * The per-file APM data
+ */
+struct apm_user {
+	int		magic;
+	struct apm_user *	next;
+	int		suser: 1;
+	int		suspend_wait: 1;
+	int		suspend_result;
+	int		suspends_pending;
+	int		standbys_pending;
+	int		suspends_read;
+	int		standbys_read;
+	int		event_head;
+	int		event_tail;
+	apm_event_t	events[APM_MAX_EVENTS];
+};
 
-extern int	apm_register_callback(int (*)(apm_event_t));
-extern void	apm_unregister_callback(int (*)(apm_event_t));
+/*
+ * The magic number in apm_user
+ */
+#define APM_BIOS_MAGIC		0x4101
 
 /*
  * Local variables
@@ -293,8 +313,6 @@
 	unsigned long	offset;
 	unsigned short	segment;
 }				apm_bios_entry;
-static int			apm_enabled = 0;
-static int			smp_hack = 0;
 #ifdef CONFIG_APM_CPU_IDLE
 static int			clock_slowed = 0;
 #endif
@@ -313,15 +331,20 @@
 #endif
 static int			debug = 0;
 static int			apm_disabled = 0;
+#ifdef CONFIG_SMP
+static int			power_off_enabled = 0;
+#else
+static int			power_off_enabled = 1;
+#endif
 
-static struct wait_queue *	process_list = NULL;
-static struct apm_bios_struct *	user_list = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
+static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
+static struct apm_user *	user_list = NULL;
 
 static struct timer_list	apm_timer;
 
-static char			driver_version[] = "1.9";	/* no spaces */
+static char			driver_version[] = "1.12";	/* no spaces */
 
-#ifdef APM_DEBUG
 static char *	apm_event_name[] = {
 	"system standby",
 	"system suspend",
@@ -338,28 +361,6 @@
 };
 #define NR_APM_EVENT_NAME	\
 		(sizeof(apm_event_name) / sizeof(apm_event_name[0]))
-#endif
-
-static struct file_operations apm_bios_fops = {
-	NULL,		/* lseek */
-	do_read,
-	NULL,		/* write */
-	NULL,		/* readdir */
-	do_poll,
-	do_ioctl,
-	NULL,		/* mmap */
-	do_open,
-	NULL,		/* flush */
-	do_release,
-	NULL,		/* fsync */
-	NULL		/* fasync */
-};
-
-static struct miscdevice apm_device = {
-	APM_MINOR_DEV,
-	"apm",
-	&apm_bios_fops
-};
 
 typedef struct callback_list_t {
 	int (*				callback)(apm_event_t);
@@ -416,9 +417,10 @@
 #	define APM_DO_CLI
 #endif
 #ifdef APM_ZERO_SEGS
+#	define APM_DECL_SEGS \
+		unsigned int saved_fs; unsigned int saved_gs;
 #	define APM_DO_SAVE_SEGS \
-		savesegment(fs, saved_fs); \
-		savesegment(gs, saved_gs)
+		savesegment(fs, saved_fs); savesegment(gs, saved_gs)
 #	define APM_DO_ZERO_SEGS \
 		"pushl %%ds\n\t" \
 		"pushl %%es\n\t" \
@@ -431,25 +433,28 @@
 		"popl %%es\n\t" \
 		"popl %%ds\n\t"
 #	define APM_DO_RESTORE_SEGS \
-		loadsegment(fs, saved_fs); \
-		loadsegment(gs, saved_gs)
+		loadsegment(fs, saved_fs); loadsegment(gs, saved_gs)
 #else
+#	define APM_DECL_SEGS
 #	define APM_DO_SAVE_SEGS
 #	define APM_DO_ZERO_SEGS
 #	define APM_DO_POP_SEGS
 #	define APM_DO_RESTORE_SEGS
 #endif
 
-static u8 apm_bios_call(u32 eax_in, u32 ebx_in, u32 ecx_in,
+static u8 apm_bios_call(u32 func, u32 ebx_in, u32 ecx_in,
 	u32 *eax, u32 *ebx, u32 *ecx, u32 *edx, u32 *esi)
 {
-	unsigned int	saved_fs;
-	unsigned int	saved_gs;
+	APM_DECL_SEGS
 	unsigned long	flags;
 
 	__save_flags(flags);
 	APM_DO_CLI;
 	APM_DO_SAVE_SEGS;
+	/*
+	 * N.B. We do NOT need a cld after the BIOS call
+	 * because we always save and restore the flags.
+	 */
 	__asm__ __volatile__(APM_DO_ZERO_SEGS
 		"pushl %%edi\n\t"
 		"pushl %%ebp\n\t"
@@ -460,7 +465,7 @@
 		APM_DO_POP_SEGS
 		: "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx),
 		  "=S" (*esi)
-		: "a" (eax_in), "b" (ebx_in), "c" (ecx_in)
+		: "a" (func), "b" (ebx_in), "c" (ecx_in)
 		: "memory", "cc");
 	APM_DO_RESTORE_SEGS;
 	__restore_flags(flags);
@@ -471,12 +476,10 @@
  * This version only returns one value (usually an error code)
  */
 
-static u8 apm_bios_call_simple(u32 eax_in, u32 ebx_in, u32 ecx_in,
-	u32 *eax)
+static u8 apm_bios_call_simple(u32 func, u32 ebx_in, u32 ecx_in, u32 *eax)
 {
 	u8		error;
-	unsigned int	saved_fs;
-	unsigned int	saved_gs;
+	APM_DECL_SEGS
 	unsigned long	flags;
 
 	__save_flags(flags);
@@ -485,6 +488,10 @@
 	{
 		int	cx, dx, si;
 
+		/*
+		 * N.B. We do NOT need a cld after the BIOS call
+		 * because we always save and restore the flags.
+		 */
 		__asm__ __volatile__(APM_DO_ZERO_SEGS
 			"pushl %%edi\n\t"
 			"pushl %%ebp\n\t"
@@ -495,7 +502,7 @@
 			APM_DO_POP_SEGS
 			: "=a" (*eax), "=b" (error), "=c" (cx), "=d" (dx),
 			  "=S" (si)
-			: "a" (eax_in), "b" (ebx_in), "c" (ecx_in)
+			: "a" (func), "b" (ebx_in), "c" (ecx_in)
 			: "memory", "cc");
 	}
 	APM_DO_RESTORE_SEGS;
@@ -503,11 +510,11 @@
 	return error;
 }
 
-static int apm_driver_version(u_short *val)
+static int __init apm_driver_version(u_short *val)
 {
 	u32	eax;
 
-	if (apm_bios_call_simple(0x530e, 0, *val, &eax))
+	if (apm_bios_call_simple(APM_FUNC_VERSION, 0, *val, &eax))
 		return (eax >> 8) & 0xff;
 	*val = eax;
 	return APM_SUCCESS;
@@ -520,7 +527,8 @@
 	u32	ecx;
 	u32	dummy;
 
-	if (apm_bios_call(0x530b, 0, 0, &eax, &ebx, &ecx, &dummy, &dummy))
+	if (apm_bios_call(APM_FUNC_GET_EVENT, 0, 0, &eax, &ebx, &ecx,
+			&dummy, &dummy))
 		return (eax >> 8) & 0xff;
 	*event = ebx;
 	if (apm_bios_info.version < 0x0102)
@@ -534,58 +542,122 @@
 {
 	u32	eax;
 
-	if (apm_bios_call_simple(0x5307, what, state, &eax))
+	if (apm_bios_call_simple(APM_FUNC_SET_STATE, what, state, &eax))
 		return (eax >> 8) & 0xff;
 	return APM_SUCCESS;
 }
 
 static int apm_set_power_state(u_short state)
 {
-	return set_power_state(0x0001, state);
+	return set_power_state(APM_DEVICE_ALL, state);
 }
 
-void apm_power_off(void)
+#ifdef CONFIG_APM_CPU_IDLE
+static int apm_do_idle(void)
 {
-	/*
-	 * smp_hack == 2 means that we would have enabled APM support
-	 * except there is more than one processor and so most of
-	 * the APM stuff is unsafe.  We will still try power down
-	 * because is is useful to some people and they know what
-	 * they are doing because they booted with the smp-power-off
-	 * kernel option.
-	 */
-	if (apm_enabled || (smp_hack == 2))
-		(void) apm_set_power_state(APM_STATE_OFF);
+	u32	dummy;
+
+	if (apm_bios_call_simple(APM_FUNC_IDLE, 0, 0, &dummy))
+		return 0;
+
+#ifdef ALWAYS_CALL_BUSY
+	clock_slowed = 1;
+#else
+	clock_slowed = (apm_bios_info.flags & APM_IDLE_SLOWS_CLOCK) != 0;
+#endif
+	return 1;
 }
 
-#ifdef CONFIG_APM_DISPLAY_BLANK
-/* Called by apm_display_blank and apm_display_unblank when apm_enabled. */
-static int apm_set_display_power_state(u_short state)
+static void apm_do_busy(void)
 {
-	int	error;
+	u32	dummy;
 
-	/* Blank the first display device */
-	error = set_power_state(0x0100, state);
-	if (error == APM_BAD_DEVICE)
-		/* try to blank them all instead */
-		error = set_power_state(0x01ff, state);
-	return error;
+	if (clock_slowed) {
+		(void) apm_bios_call_simple(APM_FUNC_BUSY, 0, 0, &dummy);
+		clock_slowed = 0;
+	}
+}
+
+extern int hlt_counter;
+
+static void apm_cpu_idle(void)
+{
+	while (!current->need_resched) {
+		if (!boot_cpu_data.hlt_works_ok)
+			continue;
+		if (hlt_counter)
+			continue;
+		/* If there is an error calling the idle routine,
+		 we should hlt if possible.  We need to check
+		 need_resched again because an interrupt
+		 may have occurred in apm_do_idle(). */
+		start_bh_atomic();
+		if (!apm_do_idle() && !current->need_resched)
+			asm volatile("sti ; hlt" : : : "memory");
+		end_bh_atomic();
+ 		if (current->need_resched) 
+ 			break;
+		schedule();
+	}
+	apm_do_busy();
 }
 #endif
 
-#ifdef CONFIG_APM_DO_ENABLE
-static int __init apm_enable_power_management(void)
+#ifdef CONFIG_SMP
+static int apm_magic(void * unused)
+{
+	while (1)
+		schedule();
+}
+#endif
+
+static void apm_power_off(void)
+{
+#ifdef CONFIG_APM_REAL_MODE_POWER_OFF
+	unsigned char	po_bios_call[] = {
+		0xb8, 0x00, 0x10,	/* movw  $0x1000,ax  */
+		0x8e, 0xd0,		/* movw  ax,ss       */
+		0xbc, 0x00, 0xf0,	/* movw  $0xf000,sp  */
+		0xb8, 0x07, 0x53,	/* movw  $0x5307,ax  */
+		0xbb, 0x01, 0x00,	/* movw  $0x0001,bx  */
+		0xb9, 0x03, 0x00,	/* movw  $0x0003,cx  */
+		0xcd, 0x15		/* int   $0x15       */
+	};
+#endif
+
+	/*
+	 * This may be called on an SMP machine.
+	 */
+#ifdef CONFIG_SMP
+	/* Many bioses don't like being called from CPU != 0 */
+	while (cpu_number_map[smp_processor_id()] != 0) {
+		kernel_thread(apm_magic, NULL,
+			CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD);
+		schedule();
+	}
+#endif
+#ifdef CONFIG_APM_REAL_MODE_POWER_OFF
+	machine_real_restart(po_bios_call, sizeof(po_bios_call));
+#else
+	(void) apm_set_power_state(APM_STATE_OFF);
+#endif
+}
+
+static int apm_enable_power_management(int enable)
 {
 	u32	eax;
 
-	if (apm_bios_call_simple(0x5308,
-			(apm_bios_info.version > 0x100) ? 0x0001 : 0xffff,
-			1, &eax))
+	if ((enable == 0) && (apm_bios_info.flags & APM_BIOS_DISENGAGED))
+		return APM_NOT_ENGAGED;
+	if (apm_bios_call_simple(APM_FUNC_ENABLE_PM, APM_DEVICE_BALL,
+			enable, &eax))
 		return (eax >> 8) & 0xff;
-	apm_bios_info.flags &= ~APM_BIOS_DISABLED;
+	if (enable)
+		apm_bios_info.flags &= ~APM_BIOS_DISABLED;
+	else
+		apm_bios_info.flags |= APM_BIOS_DISABLED;
 	return APM_SUCCESS;
 }
-#endif
 
 static int apm_get_power_status(u_short *status, u_short *bat, u_short *life)
 {
@@ -595,7 +667,8 @@
 	u32	edx;
 	u32	dummy;
 
-	if (apm_bios_call(0x530a, 1, 0, &eax, &ebx, &ecx, &edx, &dummy))
+	if (apm_bios_call(APM_FUNC_GET_STATUS, APM_DEVICE_ALL, 0,
+			&eax, &ebx, &ecx, &edx, &dummy))
 		return (eax >> 8) & 0xff;
 	*status = ebx;
 	*bat = ecx;
@@ -603,6 +676,7 @@
 	return APM_SUCCESS;
 }
 
+#if 0
 static int apm_get_battery_status(u_short which, u_short *status,
 				  u_short *bat, u_short *life, u_short *nbat)
 {
@@ -620,7 +694,7 @@
 		return apm_get_power_status(status, bat, life);
 	}
 
-	if (apm_bios_call(0x530a, (0x8000 | (which)), 0, &eax,
+	if (apm_bios_call(APM_FUNC_GET_STATUS, (0x8000 | (which)), 0, &eax,
 			&ebx, &ecx, &edx, &esi))
 		return (eax >> 8) & 0xff;
 	*status = ebx;
@@ -629,13 +703,23 @@
 	*nbat = esi;
 	return APM_SUCCESS;
 }
+#endif
 
-static int __init apm_engage_power_management(u_short device)
+static int apm_engage_power_management(u_short device, int enable)
 {
 	u32	eax;
 
-	if (apm_bios_call_simple(0x530f, device, 1, &eax))
+	if ((enable == 0) && (device == APM_DEVICE_ALL)
+	    && (apm_bios_info.flags & APM_BIOS_DISABLED))
+		return APM_DISABLED;
+	if (apm_bios_call_simple(APM_FUNC_ENGAGE_PM, device, enable, &eax))
 		return (eax >> 8) & 0xff;
+	if (device == APM_DEVICE_ALL) {
+		if (enable)
+			apm_bios_info.flags &= ~APM_BIOS_DISENGAGED;
+		else
+			apm_bios_info.flags |= APM_BIOS_DISENGAGED;
+	}
 	return APM_SUCCESS;
 }
 
@@ -652,37 +736,28 @@
 			str, err);
 }
 
-/* Called from console driver -- must make sure apm_enabled. */
-int apm_display_blank(void)
+#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
+static int apm_console_blank(int blank)
 {
-#ifdef CONFIG_APM_DISPLAY_BLANK
 	int	error;
+	u_short	state;
 
-	if (!apm_enabled)
-		return 0;
-	error = apm_set_display_power_state(APM_STATE_STANDBY);
+	state = blank ? APM_STATE_STANDBY : APM_STATE_READY;
+	/* Blank the first display device */
+	error = set_power_state(0x100, state);
+	if ((error != APM_SUCCESS) && (error != APM_NO_ERROR)) {
+		/* try to blank them all instead */
+		error = set_power_state(0x1ff, state);
+		if ((error != APM_SUCCESS) && (error != APM_NO_ERROR))
+			/* try to blank device one instead */
+			error = set_power_state(0x101, state);
+	}
 	if ((error == APM_SUCCESS) || (error == APM_NO_ERROR))
 		return 1;
-	apm_error("set display standby", error);
-#endif
+	apm_error("set display", error);
 	return 0;
 }
-
-/* Called from console driver -- must make sure apm_enabled. */
-int apm_display_unblank(void)
-{
-#ifdef CONFIG_APM_DISPLAY_BLANK
-	int error;
-
-	if (!apm_enabled)
-		return 0;
-	error = apm_set_display_power_state(APM_STATE_READY);
-	if ((error == APM_SUCCESS) || (error == APM_NO_ERROR))
-		return 1;
-	apm_error("set display ready", error);
 #endif
-	return 0;
-}
 
 int apm_register_callback(int (*callback)(apm_event_t))
 {
@@ -710,23 +785,23 @@
 	kfree_s(old, sizeof(callback_list_t));
 }
 
-static int queue_empty(struct apm_bios_struct * as)
+static int queue_empty(struct apm_user *as)
 {
 	return as->event_head == as->event_tail;
 }
 
-static apm_event_t get_queued_event(struct apm_bios_struct * as)
+static apm_event_t get_queued_event(struct apm_user *as)
 {
 	as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
 	return as->events[as->event_tail];
 }
 
-static int queue_event(apm_event_t event, struct apm_bios_struct *sender)
+static void queue_event(apm_event_t event, struct apm_user *sender)
 {
-	struct apm_bios_struct *	as;
+	struct apm_user *	as;
 
 	if (user_list == NULL)
-		return 0;
+		return;
 	for (as = user_list; as != NULL; as = as->next) {
 		if (as == sender)
 			continue;
@@ -734,10 +809,8 @@
 		if (as->event_head == as->event_tail) {
 			static int notified;
 
-			if (notified == 0) {
+			if (notified++ == 0)
 			    printk(KERN_ERR "apm: an event queue overflowed\n");
-			    notified = 1;
-			}
 			as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
 		}
 		as->events[as->event_head] = event;
@@ -757,29 +830,26 @@
 			break;
 		}
 	}
-	wake_up_interruptible(&process_list);
-	return 1;
+	wake_up_interruptible(&apm_waitqueue);
 }
 
 static void set_time(void)
 {
 	unsigned long	flags;
 
-	if (!got_clock_diff)	/* Don't know time zone, can't set clock */
-		return;
-
-	save_flags(flags);
-	cli();
-	CURRENT_TIME = get_cmos_time() + clock_cmos_diff;
-	restore_flags(flags);
+	if (got_clock_diff) {	/* Must know time zone in order to set clock */
+		save_flags(flags);
+		cli();
+		CURRENT_TIME = get_cmos_time() + clock_cmos_diff;
+		restore_flags(flags);
+	}
 }
 
-static void suspend(void)
+static void get_time_diff(void)
 {
+#ifndef CONFIG_APM_RTC_IS_GMT
 	unsigned long	flags;
-	int		err;
 
-#ifndef CONFIG_APM_RTC_IS_GMT
 	/*
 	 * Estimate time zone so that set_time can update the clock
 	 */
@@ -790,11 +860,13 @@
 	got_clock_diff = 1;
 	restore_flags(flags);
 #endif
+}
 
-	err = apm_set_power_state(APM_STATE_SUSPEND);
-	if ((err != APM_SUCCESS) && (err != APM_NO_ERROR))
-		apm_error("suspend", err);
+static void reinit_timer(void)
+{
 #ifdef INIT_TIMER_AFTER_SUSPEND
+	unsigned long	flags;
+
 	save_flags(flags);
 	cli();
 	/* set the clock to 100 Hz */
@@ -806,13 +878,34 @@
 	udelay(10);
 	restore_flags(flags);
 #endif
+}
+
+static int suspend(void)
+{
+	int		err;
+	int		ret;
+	struct apm_user	*as;
+
+	get_time_diff();
+	err = apm_set_power_state(APM_STATE_SUSPEND);
+	reinit_timer();
 	set_time();
+	ret = (err == APM_SUCCESS) || (err == APM_NO_ERROR);
+	if (!ret)
+		apm_error("suspend", err);
+	for (as = user_list; as != NULL; as = as->next) {
+		as->suspend_wait = 0;
+		as->suspend_result = (ret ? 0 : -EIO);
+	}
+	wake_up_interruptible(&apm_suspend_waitqueue);
+	return err;
 }
 
 static void standby(void)
 {
 	int	err;
 
+	get_time_diff();
 	err = apm_set_power_state(APM_STATE_STANDBY);
 	if ((err != APM_SUCCESS) && (err != APM_NO_ERROR))
 		apm_error("standby", err);
@@ -837,8 +930,8 @@
 	return 0;
 }
 
-static void send_event(apm_event_t event, apm_event_t undo,
-		       struct apm_bios_struct *sender)
+static int send_event(apm_event_t event, apm_event_t undo,
+		       struct apm_user *sender)
 {
 	callback_list_t *	call;
 	callback_list_t *	fix;
@@ -849,11 +942,12 @@
 				fix->callback(undo);
 			if (apm_bios_info.version > 0x100)
 				apm_set_power_state(APM_STATE_REJECT);
-			return;
+			return 0;
 		}
 	}
 
 	queue_event(event, sender);
+	return 1;
 }
 
 static void check_events(void)
@@ -865,14 +959,14 @@
 #endif
 
 	while ((event = get_event()) != 0) {
-#ifdef APM_DEBUG
-		if (event <= NR_APM_EVENT_NAME)
-			printk(KERN_DEBUG "apm: received %s notify\n",
-			       apm_event_name[event - 1]);
-		else
-			printk(KERN_DEBUG "apm: received unknown "
-			       "event 0x%02x\n", event);
-#endif
+		if (debug) {
+			if (event <= NR_APM_EVENT_NAME)
+				printk(KERN_DEBUG "apm: received %s notify\n",
+				       apm_event_name[event - 1]);
+			else
+				printk(KERN_DEBUG "apm: received unknown "
+				       "event 0x%02x\n", event);
+		}
 #ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
 		if (ignore_bounce
 		    && ((jiffies - last_resume) > BOUNCE_INTERVAL))
@@ -883,12 +977,15 @@
 		case APM_USER_STANDBY:
 #ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
 			if (waiting_for_resume)
-				return;
-			waiting_for_resume = 1;
+				break;
+#endif
+			if (send_event(event, APM_STANDBY_RESUME, NULL)) {
+#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
+				waiting_for_resume = 1;
 #endif
-			send_event(event, APM_STANDBY_RESUME, NULL);
-			if (standbys_pending <= 0)
-				standby();
+				if (standbys_pending <= 0)
+					standby();
+			}
 			break;
 
 		case APM_USER_SUSPEND:
@@ -904,12 +1001,15 @@
 #endif
 #ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
 			if (waiting_for_resume)
-				return;
-			waiting_for_resume = 1;
+				break;
 #endif
-			send_event(event, APM_NORMAL_RESUME, NULL);
-			if (suspends_pending <= 0)
-				suspend();
+			if (send_event(event, APM_NORMAL_RESUME, NULL)) {
+#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
+				waiting_for_resume = 1;
+#endif
+				if (suspends_pending <= 0)
+					(void) suspend();
+			}
 			break;
 
 		case APM_NORMAL_RESUME:
@@ -926,9 +1026,9 @@
 			send_event(event, 0, NULL);
 			break;
 
+		case APM_CAPABILITY_CHANGE:
 		case APM_LOW_BATTERY:
 		case APM_POWER_STATUS_CHANGE:
-		case APM_CAPABILITY_CHANGE:
 			send_event(event, 0, NULL);
 			break;
 
@@ -937,74 +1037,33 @@
 			break;
 
 		case APM_CRITICAL_SUSPEND:
-			suspend();
+			(void) suspend();
 			break;
 		}
 	}
 }
 
-static void do_apm_timer(unsigned long unused)
+static void apm_event_handler(unsigned long unused)
 {
-	int	err;
-
-	static int	pending_count = 0;
+	static int	pending_count = 4;
+	int		err;
 
-	if (((standbys_pending > 0) || (suspends_pending > 0))
-	    && (apm_bios_info.version > 0x100)
-	    && (pending_count-- <= 0)) {
+	if ((standbys_pending > 0) || (suspends_pending > 0)) {
+		if ((apm_bios_info.version > 0x100) && (pending_count-- < 0)) {
+			pending_count = 4;
+			err = apm_set_power_state(APM_STATE_BUSY);
+			if (err)
+				apm_error("busy", err);
+		}
+	} else
 		pending_count = 4;
-
-		err = apm_set_power_state(APM_STATE_BUSY);
-		if (err)
-			apm_error("busy", err);
-	}
-
-	if (!(((standbys_pending > 0) || (suspends_pending > 0))
-	      && (apm_bios_info.version == 0x100)))
-		check_events();
-
+	check_events();
 	init_timer(&apm_timer);
 	apm_timer.expires = APM_CHECK_TIMEOUT + jiffies;
 	add_timer(&apm_timer);
 }
 
-/* Called from sys_idle, must make sure apm_enabled. */
-int apm_do_idle(void)
-{
-#ifdef CONFIG_APM_CPU_IDLE
-	u32	dummy;
-
-	if (!apm_enabled)
-		return 0;
-
-	if (apm_bios_call_simple(0x5305, 0, 0, &dummy))
-		return 0;
-
-	clock_slowed = (apm_bios_info.flags & APM_IDLE_SLOWS_CLOCK) != 0;
-	return 1;
-#else
-	return 0;
-#endif
-}
-
-/* Called from sys_idle, must make sure apm_enabled. */
-void apm_do_busy(void)
-{
-#ifdef CONFIG_APM_CPU_IDLE
-	u32	dummy;
-
-	if (apm_enabled
-#ifndef ALWAYS_CALL_BUSY
-		&& clock_slowed
-#endif
-	) {
-		(void) apm_bios_call_simple(0x5306, 0, 0, &dummy);
-		clock_slowed = 0;
-	}
-#endif
-}
-
-static int check_apm_bios_struct(struct apm_bios_struct *as, const char *func)
+static int check_apm_user(struct apm_user *as, const char *func)
 {
 	if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) {
 		printk(KERN_ERR "apm: %s passed bad filp", func);
@@ -1015,33 +1074,37 @@
 
 static ssize_t do_read(struct file *fp, char *buf, size_t count, loff_t *ppos)
 {
-	struct apm_bios_struct *	as;
+	struct apm_user *	as;
 	int			i;
 	apm_event_t		event;
-	struct wait_queue	wait = { current,	NULL };
+	DECLARE_WAITQUEUE(wait, current);
 
 	as = fp->private_data;
-	if (check_apm_bios_struct(as, "read"))
+	if (check_apm_user(as, "read"))
 		return -EIO;
 	if (count < sizeof(apm_event_t))
 		return -EINVAL;
 	if (queue_empty(as)) {
 		if (fp->f_flags & O_NONBLOCK)
 			return -EAGAIN;
-		add_wait_queue(&process_list, &wait);
+		add_wait_queue(&apm_waitqueue, &wait);
 repeat:
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (queue_empty(as) && !signal_pending(current)) {
 			schedule();
 			goto repeat;
 		}
 		current->state = TASK_RUNNING;
-		remove_wait_queue(&process_list, &wait);
+		remove_wait_queue(&apm_waitqueue, &wait);
 	}
 	i = count;
 	while ((i >= sizeof(event)) && !queue_empty(as)) {
 		event = get_queued_event(as);
-		copy_to_user(buf, &event, sizeof(event));
+		if (copy_to_user(buf, &event, sizeof(event))) {
+			if (i < count)
+				break;
+			return -EFAULT;
+		}
 		switch (event) {
 		case APM_SYS_SUSPEND:
 		case APM_USER_SUSPEND:
@@ -1065,12 +1128,12 @@
 
 static unsigned int do_poll(struct file *fp, poll_table * wait)
 {
-	struct apm_bios_struct * as;
+	struct apm_user * as;
 
 	as = fp->private_data;
-	if (check_apm_bios_struct(as, "select"))
+	if (check_apm_user(as, "poll"))
 		return 0;
-	poll_wait(fp, &process_list, wait);
+	poll_wait(fp, &apm_waitqueue, wait);
 	if (!queue_empty(as))
 		return POLLIN | POLLRDNORM;
 	return 0;
@@ -1079,10 +1142,11 @@
 static int do_ioctl(struct inode * inode, struct file *filp,
 		    u_int cmd, u_long arg)
 {
-	struct apm_bios_struct *	as;
+	struct apm_user *	as;
+	DECLARE_WAITQUEUE(wait, current);
 
 	as = filp->private_data;
-	if (check_apm_bios_struct(as, "ioctl"))
+	if (check_apm_user(as, "ioctl"))
 		return -EIO;
 	if (!as->suser)
 		return -EPERM;
@@ -1092,9 +1156,8 @@
 			as->standbys_read--;
 			as->standbys_pending--;
 			standbys_pending--;
-		}
-		else
-			send_event(APM_USER_STANDBY, APM_STANDBY_RESUME, as);
+		} else if (!send_event(APM_USER_STANDBY, APM_STANDBY_RESUME, as))
+			return -EAGAIN;
 		if (standbys_pending <= 0)
 			standby();
 		break;
@@ -1103,11 +1166,25 @@
 			as->suspends_read--;
 			as->suspends_pending--;
 			suspends_pending--;
+		} else if (!send_event(APM_USER_SUSPEND, APM_NORMAL_RESUME, as))
+			return -EAGAIN;
+		if (suspends_pending <= 0) {
+			if (!suspend())
+				return -EIO;
+		} else {
+			as->suspend_wait = 1;
+			add_wait_queue(&apm_suspend_waitqueue, &wait);
+			while (1) {
+				set_current_state(TASK_INTERRUPTIBLE);
+				if ((as->suspend_wait == 0)
+				    || signal_pending(current))
+					break;
+				schedule();
+			}
+			current->state = TASK_RUNNING;
+			remove_wait_queue(&apm_suspend_waitqueue, &wait);
+			return as->suspend_result;
 		}
-		else
-			send_event(APM_USER_SUSPEND, APM_NORMAL_RESUME, as);
-		if (suspends_pending <= 0)
-			suspend();
 		break;
 	default:
 		return -EINVAL;
@@ -1117,12 +1194,12 @@
 
 static int do_release(struct inode * inode, struct file * filp)
 {
-	struct apm_bios_struct *	as;
+	struct apm_user *	as;
 
 	as = filp->private_data;
-	filp->private_data = NULL;
-	if (check_apm_bios_struct(as, "release"))
+	if (check_apm_user(as, "release"))
 		return 0;
+	filp->private_data = NULL;
 	if (as->standbys_pending > 0) {
 		standbys_pending -= as->standbys_pending;
 		if (standbys_pending <= 0)
@@ -1131,12 +1208,12 @@
 	if (as->suspends_pending > 0) {
 		suspends_pending -= as->suspends_pending;
 		if (suspends_pending <= 0)
-			suspend();
+			(void) suspend();
 	}
 	if (user_list == as)
 		user_list = as->next;
 	else {
-		struct apm_bios_struct *	as1;
+		struct apm_user *	as1;
 
 		for (as1 = user_list;
 		     (as1 != NULL) && (as1->next != as);
@@ -1153,9 +1230,9 @@
 
 static int do_open(struct inode * inode, struct file * filp)
 {
-	struct apm_bios_struct *	as;
+	struct apm_user *	as;
 
-	as = (struct apm_bios_struct *)kmalloc(sizeof(*as), GFP_KERNEL);
+	as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL);
 	if (as == NULL) {
 		printk(KERN_ERR "apm: cannot allocate struct of size %d bytes",
 		       sizeof(*as));
@@ -1179,13 +1256,12 @@
 	return 0;
 }
 
-int apm_get_info(char *buf, char **start, off_t fpos, int length, int dummy)
+static int apm_get_info(char *buf, char **start, off_t fpos, int length, int dummy)
 {
 	char *		p;
 	unsigned short	bx;
 	unsigned short	cx;
 	unsigned short	dx;
-	unsigned short	nbat;
 	unsigned short	error;
 	unsigned short  ac_line_status = 0xff;
 	unsigned short  battery_status = 0xff;
@@ -1194,11 +1270,10 @@
 	int             time_units     = -1;
 	char            *units         = "?";
 
-	if (!apm_enabled)
-		return 0;
 	p = buf;
 
-	if (!(error = apm_get_power_status(&bx, &cx, &dx))) {
+	if ((smp_num_cpus == 1) &&
+	    !(error = apm_get_power_status(&bx, &cx, &dx))) {
 		ac_line_status = (bx >> 8) & 0xff;
 		battery_status = bx & 0xff;
 		if ((cx & 0xff) != 0xff)
@@ -1216,7 +1291,7 @@
 	   from the Get Power Status (0x0a) call unless otherwise noted.
 
 	   0) Linux driver version (this will change if format changes)
-	   1) APM BIOS Version.  Usually 1.0 or 1.1.
+	   1) APM BIOS Version.  Usually 1.0, 1.1 or 1.2.
 	   2) APM flags from APM Installation Check (0x00):
 	      bit 0: APM_16_BIT_SUPPORT
 	      bit 1: APM_32_BIT_SUPPORT
@@ -1226,13 +1301,14 @@
 	   3) AC line status
 	      0x00: Off-line
 	      0x01: On-line
-	      0x02: On backup power (APM BIOS 1.1 only)
+	      0x02: On backup power (BIOS >= 1.1 only)
 	      0xff: Unknown
 	   4) Battery status
 	      0x00: High
 	      0x01: Low
 	      0x02: Critical
 	      0x03: Charging
+	      0x04: Selected battery not present (BIOS >= 1.2 only)
 	      0xff: Unknown
 	   5) Battery flag
 	      bit 0: High
@@ -1264,6 +1340,106 @@
 	return p - buf;
 }
 
+static int __init apm(void *unused)
+{
+	unsigned short	bx;
+	unsigned short	cx;
+	unsigned short	dx;
+	unsigned short	error;
+	char *		power_stat;
+	char *		bat_stat;
+
+	if (apm_bios_info.version > 0x100) {
+		/*
+		 * We only support BIOSs up to version 1.2
+		 */
+		if (apm_bios_info.version > 0x0102)
+			apm_bios_info.version = 0x0102;
+		if (apm_driver_version(&apm_bios_info.version) != APM_SUCCESS) {
+			/* Fall back to an APM 1.0 connection. */
+			apm_bios_info.version = 0x100;
+		}
+	}
+	if (debug && (smp_num_cpus == 1)) {
+		printk(KERN_INFO "apm: Connection version %d.%d\n",
+			(apm_bios_info.version >> 8) & 0xff,
+			apm_bios_info.version & 0xff);
+
+		error = apm_get_power_status(&bx, &cx, &dx);
+		if (error)
+			printk(KERN_INFO "apm: power status not available\n");
+		else {
+			switch ((bx >> 8) & 0xff) {
+			case 0: power_stat = "off line"; break;
+			case 1: power_stat = "on line"; break;
+			case 2: power_stat = "on backup power"; break;
+			default: power_stat = "unknown"; break;
+			}
+			switch (bx & 0xff) {
+			case 0: bat_stat = "high"; break;
+			case 1: bat_stat = "low"; break;
+			case 2: bat_stat = "critical"; break;
+			case 3: bat_stat = "charging"; break;
+			default: bat_stat = "unknown"; break;
+			}
+			printk(KERN_INFO
+			       "apm: AC %s, battery status %s, battery life ",
+			       power_stat, bat_stat);
+			if ((cx & 0xff) == 0xff)
+				printk("unknown\n");
+			else
+				printk("%d%%\n", cx & 0xff);
+			if (apm_bios_info.version > 0x100) {
+				printk(KERN_INFO
+				       "apm: battery flag 0x%02x, battery life ",
+				       (cx >> 8) & 0xff);
+				if (dx == 0xffff)
+					printk("unknown\n");
+				else
+					printk("%d %s\n", dx & 0x7fff,
+						(dx & 0x8000) ?
+						"minutes" : "seconds");
+			}
+		}
+	}
+
+#ifdef CONFIG_APM_DO_ENABLE
+	if (apm_bios_info.flags & APM_BIOS_DISABLED) {
+		/*
+		 * This call causes my NEC UltraLite Versa 33/C to hang if it
+		 * is booted with PM disabled but not in the docking station.
+		 * Unfortunate ...
+		 */
+		error = apm_enable_power_management(1);
+		if (error) {
+			apm_error("enable power management", error);
+			return -1;
+		}
+	}
+#endif
+	if ((apm_bios_info.flags & APM_BIOS_DISENGAGED)
+	    && (apm_bios_info.version > 0x0100)) {
+		error = apm_engage_power_management(APM_DEVICE_ALL, 1);
+		if (error) {
+			apm_error("engage power management", error);
+			return -1;
+		}
+	}
+
+	/* Install our power off handler.. */
+	if (power_off_enabled)
+		acpi_power_off = apm_power_off;
+#ifdef CONFIG_MAGIC_SYSRQ
+	sysrq_power_off = apm_power_off;
+#endif
+#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
+	if (smp_num_cpus == 1)
+		console_blank_hook = apm_console_blank;
+#endif
+
+	return 0;
+}
+
 void __init apm_setup(char *str, int *dummy)
 {
 	int	invert;
@@ -1278,27 +1454,37 @@
 			str += 3;
 		if (strncmp(str, "debug", 5) == 0)
 			debug = !invert;
-		if (strncmp(str, "smp-power-off", 13) == 0)
-			smp_hack = !invert;
+		if (strncmp(str, "power-off", 9) == 0)
+			power_off_enabled = !invert;
 		str = strchr(str, ',');
 		if (str != NULL)
 			str += strspn(str, ", \t");
 	}
 }
 
-void __init apm_bios_init(void)
-{
-	unsigned short	bx;
-	unsigned short	cx;
-	unsigned short	dx;
-	unsigned short	error;
-	char *		power_stat;
-	char *		bat_stat;
-	static struct proc_dir_entry *ent;
+__setup("apm=", apm_setup);
+
+static struct file_operations apm_bios_fops = {
+	read:		do_read,
+	poll:		do_poll,
+	ioctl:		do_ioctl,
+	open:		do_open,
+	release:	do_release,
+};
 
+static struct miscdevice apm_device = {
+	APM_MINOR_DEV,
+	"apm",
+	&apm_bios_fops
+};
+
+#define APM_INIT_ERROR_RETURN	return
+
+void __init apm_init(void)
+{
 	if (apm_bios_info.version == 0) {
 		printk(KERN_INFO "apm: BIOS not found.\n");
-		return;
+		APM_INIT_ERROR_RETURN;
 	}
 	printk(KERN_INFO
 		"apm: BIOS version %d.%d Flags 0x%02x (Driver version %s)\n",
@@ -1308,7 +1494,7 @@
 		driver_version);
 	if ((apm_bios_info.flags & APM_32_BIT_SUPPORT) == 0) {
 		printk(KERN_INFO "apm: no 32 bit BIOS support\n");
-		return;
+		APM_INIT_ERROR_RETURN;
 	}
 
 	/*
@@ -1337,7 +1523,11 @@
 
 	if (apm_disabled) {
 		printk(KERN_NOTICE "apm: disabled on user request.\n");
-		return;
+		APM_INIT_ERROR_RETURN;
+	}
+	if ((smp_num_cpus > 1) && !power_off_enabled) {
+		printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n");
+		APM_INIT_ERROR_RETURN;
 	}
 
 	/*
@@ -1359,18 +1549,16 @@
 	set_base(gdt[APM_DS >> 3],
 		 __va((unsigned long)apm_bios_info.dseg << 4));
 #ifndef APM_RELAX_SEGMENTS
-	if (apm_bios_info.version == 0x100)
+	if (apm_bios_info.version == 0x100) {
 #endif
-	{
 		/* For ASUS motherboard, Award BIOS rev 110 (and others?) */
 		_set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 - 1);
 		/* For some unknown machine. */
 		_set_limit((char *)&gdt[APM_CS_16 >> 3], 64 * 1024 - 1);
 		/* For the DEC Hinote Ultra CT475 (and others?) */
 		_set_limit((char *)&gdt[APM_DS >> 3], 64 * 1024 - 1);
-	}
 #ifndef APM_RELAX_SEGMENTS
-	else {
+	} else {
 		_set_limit((char *)&gdt[APM_CS >> 3],
 			(apm_bios_info.cseg_len - 1) & 0xffff);
 		_set_limit((char *)&gdt[APM_CS_16 >> 3],
@@ -1379,98 +1567,27 @@
 			(apm_bios_info.dseg_len - 1) & 0xffff);
 	}
 #endif
-#ifdef CONFIG_SMP
-	if (smp_num_cpus > 1) {
-		printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n");
-		if (smp_hack)
-			smp_hack = 2;
-		return;
-	}
-#endif
-	if (apm_bios_info.version > 0x100) {
-		/*
-		 * We only support BIOSs up to version 1.2
-		 */
-		if (apm_bios_info.version > 0x0102)
-			apm_bios_info.version = 0x0102;
-		if (apm_driver_version(&apm_bios_info.version) != APM_SUCCESS) {
-			/* Fall back to an APM 1.0 connection. */
-			apm_bios_info.version = 0x100;
-		}
-	}
-	if (debug) {
-		printk(KERN_INFO "apm: Connection version %d.%d\n",
-			(apm_bios_info.version >> 8) & 0xff,
-			apm_bios_info.version & 0xff );
 
-		error = apm_get_power_status(&bx, &cx, &dx);
-		if (error)
-			printk(KERN_INFO "apm: power status not available\n");
-		else {
-			switch ((bx >> 8) & 0xff) {
-			case 0: power_stat = "off line"; break;
-			case 1: power_stat = "on line"; break;
-			case 2: power_stat = "on backup power"; break;
-			default: power_stat = "unknown"; break;
-			}
-			switch (bx & 0xff) {
-			case 0: bat_stat = "high"; break;
-			case 1: bat_stat = "low"; break;
-			case 2: bat_stat = "critical"; break;
-			case 3: bat_stat = "charging"; break;
-			default: bat_stat = "unknown"; break;
-			}
-			printk(KERN_INFO
-			       "apm: AC %s, battery status %s, battery life ",
-			       power_stat, bat_stat);
-			if ((cx & 0xff) == 0xff)
-				printk("unknown\n");
-			else
-				printk("%d%%\n", cx & 0xff);
-			if (apm_bios_info.version > 0x100) {
-				printk(KERN_INFO
-				       "apm: battery flag 0x%02x, battery life ",
-				       (cx >> 8) & 0xff);
-				if (dx == 0xffff)
-					printk("unknown\n");
-				else
-					printk("%d %s\n", dx & 0x7fff,
-						(dx & 0x8000) ?
-						"minutes" : "seconds");
-			}
-		}
-	}
+	apm(0);
 
-#ifdef CONFIG_APM_DO_ENABLE
-	if (apm_bios_info.flags & APM_BIOS_DISABLED) {
-		/*
-		 * This call causes my NEC UltraLite Versa 33/C to hang if it
-		 * is booted with PM disabled but not in the docking station.
-		 * Unfortunate ...
-		 */
-		error = apm_enable_power_management();
-		if (error) {
-			apm_error("enable power management", error);
-			return;
-		}
-	}
-#endif
-	if (((apm_bios_info.flags & APM_BIOS_DISABLED) == 0)
-	    && (apm_bios_info.version > 0x0100)) {
-		if (apm_engage_power_management(0x0001) == APM_SUCCESS)
-			apm_bios_info.flags &= ~APM_BIOS_DISENGAGED;
+	create_proc_info_entry("apm", 0, 0, apm_get_info);
+
+	if (smp_num_cpus > 1) {
+		printk(KERN_NOTICE
+		   "apm: disabled - APM is not SMP safe (power off active).\n");
+		APM_INIT_ERROR_RETURN;
 	}
 
 	init_timer(&apm_timer);
-	apm_timer.function = do_apm_timer;
+	apm_timer.function = apm_event_handler;
 	apm_timer.expires = APM_CHECK_TIMEOUT + jiffies;
 	add_timer(&apm_timer);
 
-	ent = create_proc_entry("apm", 0, 0);
-	if (ent != NULL)
-		ent->get_info = apm_get_info;
-
 	misc_register(&apm_device);
 
-	apm_enabled = 1;
+#ifdef CONFIG_APM_CPU_IDLE
+	acpi_idle = apm_cpu_idle;
+#endif
 }
+
+module_init(apm_init)
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/i386/kernel/bios32.c linux.15p9/arch/i386/kernel/bios32.c
--- linux.vanilla/arch/i386/kernel/bios32.c	Tue Jan  4 21:18:39 2000
+++ linux.15p9/arch/i386/kernel/bios32.c	Wed Feb 16 18:32:54 2000
@@ -1030,6 +1030,56 @@
  * Exceptions for specific devices. Usually work-arounds for fatal design flaws.
  */
 
+static void __init pci_fixup_peer_bus_scan(unsigned char busno, unsigned char busmax)
+{
+	struct pci_bus *bus;
+	if((busno == 0) && (busmax > 0))
+		busno++;
+	while(busno != 0) {
+		pci_scan_peer_bridge(busno);
+		for(bus=&pci_root;bus;bus=bus->next)
+			if(bus->number == busno)
+				break;
+		if(bus==NULL) {
+			return;
+		}
+		if(bus->subordinate < busmax)
+			busno = bus->subordinate + 1;
+		else
+			busno = 0;
+	}
+}
+
+static void __init pci_fixup_rcc(struct pci_dev *d)
+{
+	/*
+	 * Find and scan busses behind RCC LE north bridge chips
+	 */
+	struct pci_bus *bus;
+	unsigned char busno, busmax;
+	pci_probe |= PCI_NO_PEER_FIXUP;
+	pci_read_config_byte(d, 0x44, &busno);
+	pci_read_config_byte(d, 0x45, &busmax);
+	printk("PCI: Scanning RCC HE/LE Peer Bus Bridge %02x/%02x\n",
+		PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
+	pci_fixup_peer_bus_scan(busno, busmax);
+}
+
+static void __init pci_fixup_compaq(struct pci_dev *d)
+{
+	/*
+	 * Find and scan busses behind RCC LE north bridge chips
+	 */
+	struct pci_bus *bus;
+	unsigned char busno, busmax;
+	pci_probe |= PCI_NO_PEER_FIXUP;
+	pci_read_config_byte(d, 0xc8, &busno);
+	pci_read_config_byte(d, 0xc9, &busmax);
+	printk("PCI: Scanning Compaq Peer Bus Bridge %02x/%02x\n",
+		PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
+	pci_fixup_peer_bus_scan(busno, busmax);
+}
+
 static void __init pci_fixup_i450nx(struct pci_dev *d)
 {
 	/*
@@ -1043,10 +1093,7 @@
 		pci_read_config_byte(d, reg++, &suba);
 		pci_read_config_byte(d, reg++, &subb);
 		DBG("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb);
-		if (busno)
-			pci_scan_peer_bridge(busno);	/* Bus A */
-		if (suba < subb)
-			pci_scan_peer_bridge(suba+1);	/* Bus B */
+		pci_fixup_peer_bus_scan(busno,subb);
 	}
 	pci_probe |= PCI_NO_PEER_FIXUP;
 }
@@ -1071,6 +1118,9 @@
 
 static struct dev_ex __initdata dev_ex_table[] = {
  { PCI_VENDOR_ID_INTEL,		PCI_DEVICE_ID_INTEL_82451NX,	pci_fixup_i450nx, 	"Scanning peer host bridges" },
+ { PCI_VENDOR_ID_RCC,		PCI_DEVICE_ID_RCC_HE,	pci_fixup_rcc, 	"Scanning peer host bridges" },
+ { PCI_VENDOR_ID_RCC,		PCI_DEVICE_ID_RCC_LE,	pci_fixup_rcc, 	"Scanning peer host bridges" },
+ { PCI_VENDOR_ID_COMPAQ,	PCI_DEVICE_ID_COMPAQ_6010,	pci_fixup_compaq, 	"Scanning peer host bridges" },
  { PCI_VENDOR_ID_UMC,		PCI_DEVICE_ID_UMC_UM8886BF,	pci_fixup_umc_ide,	"Working around UM8886BF bugs" }
 };
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/i386/kernel/io_apic.c linux.15p9/arch/i386/kernel/io_apic.c
--- linux.vanilla/arch/i386/kernel/io_apic.c	Tue Jan  4 21:18:39 2000
+++ linux.15p9/arch/i386/kernel/io_apic.c	Wed Feb  9 21:57:54 2000
@@ -1277,6 +1277,37 @@
 	}
 }
 
+/* Patch to set the IO-APIC physical IDs based on the values stored in the MPC table */
+/* by Matt Domsch <Matt_Domsch@dell.com>  Tue Dec 21 12:25:05 CST 1999 */
+
+static void __init setup_ioapic_ids_from_mpc(void)
+{
+	struct IO_APIC_reg_00 reg_00;
+	/*
+	 * Set the IOAPIC ID to the value stored in the MPC table.
+	 */
+	int apic;
+	for (apic = 0; apic < mp_apic_entries; apic++) {
+		/* Read the register 0 value */
+		*(int *)&reg_00 = io_apic_read(apic, 0);
+		
+		if(reg_00.ID != mp_apics[apic].mpc_apicid) {
+			/* Change the value */
+			printk("...changing IO-APIC physical APIC ID to %d\n", mp_apics[apic].mpc_apicid);
+			reg_00.ID = mp_apics[apic].mpc_apicid;
+			io_apic_write(apic, 0, *(int *)&reg_00);
+
+			/*
+			 * Sanity check
+			 */
+			*(int *)&reg_00 = io_apic_read(apic, 0);
+			if (reg_00.ID != mp_apics[apic].mpc_apicid)
+				panic("could not set ID");
+		}
+	}
+}
+
+
 /*
  *
  * IRQ's that are handled by the old PIC in all cases:
@@ -1336,9 +1367,11 @@
 	 * Set up the IO-APIC IRQ routing table by parsing the MP-BIOS
 	 * mptable:
 	 */
+	setup_ioapic_ids_from_mpc();
 	setup_IO_APIC_irqs();
 	init_IO_APIC_traps();
 	check_timer();
 
 	print_IO_APIC();
 }
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/i386/kernel/irq.c linux.15p9/arch/i386/kernel/irq.c
--- linux.vanilla/arch/i386/kernel/irq.c	Wed Oct 20 01:12:33 1999
+++ linux.15p9/arch/i386/kernel/irq.c	Thu Feb 17 13:45:00 2000
@@ -1064,7 +1064,7 @@
 	}
 }
 
-__initfunc(void init_IRQ(void))
+unsigned long __init init_IRQ(unsigned long memory)
 {
 	int i;
 
@@ -1128,6 +1128,7 @@
 	setup_x86_irq(2, &irq2);
 	setup_x86_irq(13, &irq13);
 #endif
+	return memory;
 }
 
 #ifdef CONFIG_X86_IO_APIC
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/i386/kernel/mtrr.c linux.15p9/arch/i386/kernel/mtrr.c
--- linux.vanilla/arch/i386/kernel/mtrr.c	Sat Aug 28 20:00:53 1999
+++ linux.15p9/arch/i386/kernel/mtrr.c	Wed Jan 12 01:35:36 2000
@@ -139,41 +139,41 @@
 	       Changed locking to spin with reschedule.
 	       Made use of new <smp_call_function>.
   v1.28
-    19990201   Zoltan Boszormenyi <zboszor@mol.hu>
+    19990201   Zoltán Böszörményi <zboszor@mail.externet.hu>
 	       Extended the driver to be able to use Cyrix style ARRs.
     19990204   Richard Gooch <rgooch@atnf.csiro.au>
 	       Restructured Cyrix support.
   v1.29
-    19990204   Zoltan Boszormenyi <zboszor@mol.hu>
+    19990204   Zoltán Böszörményi <zboszor@mail.externet.hu>
 	       Refined ARR support: enable MAPEN in set_mtrr_prepare()
 	       and disable MAPEN in set_mtrr_done().
     19990205   Richard Gooch <rgooch@atnf.csiro.au>
 	       Minor cleanups.
   v1.30
-    19990208   Zoltan Boszormenyi <zboszor@mol.hu>
+    19990208   Zoltán Böszörményi <zboszor@mail.externet.hu>
                Protect plain 6x86s (and other processors without the
                Page Global Enable feature) against accessing CR4 in
                set_mtrr_prepare() and set_mtrr_done().
     19990210   Richard Gooch <rgooch@atnf.csiro.au>
 	       Turned <set_mtrr_up> and <get_mtrr> into function pointers.
   v1.31
-    19990212   Zoltan Boszormenyi <zboszor@mol.hu>
+    19990212   Zoltán Böszörményi <zboszor@mail.externet.hu>
                Major rewrite of cyrix_arr_init(): do not touch ARRs,
                leave them as the BIOS have set them up.
                Enable usage of all 8 ARRs.
                Avoid multiplications by 3 everywhere and other
                code clean ups/speed ups.
-    19990213   Zoltan Boszormenyi <zboszor@mol.hu>
+    19990213   Zoltán Böszörményi <zboszor@mail.externet.hu>
                Set up other Cyrix processors identical to the boot cpu.
                Since Cyrix don't support Intel APIC, this is l'art pour l'art.
                Weigh ARRs by size:
                If size <= 32M is given, set up ARR# we were given.
                If size >  32M is given, set up ARR7 only if it is free,
                fail otherwise.
-    19990214   Zoltan Boszormenyi <zboszor@mol.hu>
+    19990214   Zoltán Böszörményi <zboszor@mail.externet.hu>
                Also check for size >= 256K if we are to set up ARR7,
                mtrr_add() returns the value it gets from set_mtrr()
-    19990218   Zoltan Boszormenyi <zboszor@mol.hu>
+    19990218   Zoltán Böszörményi <zboszor@mail.externet.hu>
                Remove Cyrix "coma bug" workaround from here.
                Moved to linux/arch/i386/kernel/setup.c and
                linux/include/asm-i386/bugs.h
@@ -187,7 +187,7 @@
     19990305   Richard Gooch <rgooch@atnf.csiro.au>
 	       Temporarily disable AMD support now MTRR capability flag is set.
   v1.32
-    19990308   Zoltan Boszormenyi <zboszor@mol.hu>
+    19990308   Zoltán Böszörményi <zboszor@mail.externet.hu>
 	       Adjust my changes (19990212-19990218) to Richard Gooch's
 	       latest changes. (19990228-19990305)
   v1.33
@@ -197,7 +197,7 @@
 	       Support K6-II/III based on Alan Cox's <alan@redhat.com> patches.
   v1.34
     19990511   Bart Hartgers <bart@etpmod.phys.tue.nl>
-	       Support Centaur C6 MCR's.
+	       Support Centaur C6 MCRs.
     19990512   Richard Gooch <rgooch@atnf.csiro.au>
 	       Minor cleanups.
   v1.35
@@ -210,6 +210,9 @@
     19990819   Alan Cox <alan@redhat.com>
     	       Tested Zoltan's changes on a pre production Athlon - 100%
     	       success. Fixed one fall through check to be Intel only.
+    19991116   Bart Hartgers <bart@etpmod.phys.tue.nl>
+               Changed Centaur/IDT WinChip support to include WinChip 2.
+               (WC 2 kindly provided by IDT).
 */
 
 #include <linux/types.h>
@@ -581,18 +584,31 @@
     return;
 }   /*  End Function amd_get_mtrr  */
 
-static struct
+static struct CENTAUR_MCR_CTX
 {
-    unsigned long high;
-    unsigned long low;
-} centaur_mcr[8];
+   unsigned type_bits[MTRR_NUM_TYPES];
+   struct {
+      u32 low;
+      u32 high;
+   } mcr[8];
+} *centaur_ctx=NULL;
 
 static void centaur_get_mcr (unsigned int reg, unsigned long *base,
 			     unsigned long *size, mtrr_type *type)
 {
-    *base = centaur_mcr[reg].high & 0xfffff000;
-    *size = (~(centaur_mcr[reg].low & 0xfffff000))+1;
-    *type = MTRR_TYPE_WRCOMB;	/*  If it is there, it is write-combining  */
+    unsigned i;
+    u32 tb;
+    tb = centaur_ctx->mcr[reg].low & 0xfff;
+    *base = centaur_ctx->mcr[reg].high & 0xfffff000;
+    *size = (~(centaur_ctx->mcr[reg].low & 0xfffff000))+1;
+    if (*size) {
+        for( i=0; i<MTRR_NUM_TYPES; ++i)
+	    if (centaur_ctx->type_bits[i]==tb) {
+	        *type = (mtrr_type) i;
+	        return;
+	    }
+        *size = 0;
+    }
 }   /*  End Function centaur_get_mcr  */
 
 static void (*get_mtrr) (unsigned int reg, unsigned long *base,
@@ -716,6 +732,7 @@
     unsigned long low, high;
 
     if (do_safe) set_mtrr_prepare( &ctxt );
+   
     if (size == 0)
     {
         /*  Disable  */
@@ -724,12 +741,13 @@
     else
     {
         high = base & 0xfffff000; /* base works on 4K pages... */
-        low = ((~(size-1))&0xfffff000);
-        low |= 0x1f;		  /* only support write-combining... */
+        low = ((~(size-1))&0xfffff000)|(centaur_ctx->type_bits[type]);
     }
-    centaur_mcr[reg].high = high;
-    centaur_mcr[reg].low = low;
+    centaur_ctx->mcr[reg].high = high;
+    centaur_ctx->mcr[reg].low = low;
+   
     wrmsr (0x110 + reg, low, high);
+   
     if (do_safe) set_mtrr_done( &ctxt );
 }   /*  End Function centaur_set_mtrr_up  */
 
@@ -1078,6 +1096,12 @@
     unsigned long lbase, lsize, last;
 
     if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return -ENODEV;
+    if (type >= MTRR_NUM_TYPES)
+    {
+	printk ("mtrr: type: %u illegal\n", type);
+	return -EINVAL;
+    }
+   
     switch (boot_cpu_data.x86_vendor)
     {
       case X86_VENDOR_AMD:
@@ -1113,13 +1137,12 @@
 	}
         if (boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR)
 	{
-	    if (type != MTRR_TYPE_WRCOMB)
-	    {
-		printk ("mtrr: only write-combining is supported\n");
+	    if (centaur_ctx->type_bits[type]==0) {
+		printk ("mtrr: type not supported\n");
 		return -EINVAL;
 	    }
 	}
-	else if (base + size < 0x100000)
+	else if (base + size < 0x100000) /* Cyrix */
 	{
 	    printk ("mtrr: cannot set region below 1 MiB (0x%lx,0x%lx)\n",
 		    base, size);
@@ -1141,11 +1164,6 @@
 	return -EINVAL;
 	/*break;*/
     }
-    if (type >= MTRR_NUM_TYPES)
-    {
-	printk ("mtrr: type: %u illegal\n", type);
-	return -EINVAL;
-    }
     /*  If the type is WC, check that this processor supports it  */
     if ( (type == MTRR_TYPE_WRCOMB) && !have_wrcomb () )
     {
@@ -1172,7 +1190,8 @@
 	/*  New region is enclosed by an existing region  */
 	if (ltype != type)
 	{
-	    if (type == MTRR_TYPE_UNCACHABLE) continue;
+	    if ((boot_cpu_data.x86_vendor != X86_VENDOR_CENTAUR) && 
+	        (type == MTRR_TYPE_UNCACHABLE)) continue;
 	    spin_unlock (&main_lock);
 	    printk ( "mtrr: type mismatch for %lx,%lx old: %s new: %s\n",
 		     base, size, attrib_to_str (ltype), attrib_to_str (type) );
@@ -1652,7 +1671,51 @@
 {
     unsigned i;
     struct set_mtrr_context ctxt;
-
+    u32 low,high;
+    u32 mcr_ctrl_value;
+    unsigned mcr_type;
+    /* Deduce the MCR traits type for this processor.
+     * The documentation of the WinChip 2 suggests that we can read the
+     * MCR_CTRL register for all WinChips, but this hangs on my C6.
+     * -> Work around this.
+     */
+    if ((boot_cpu_data.x86 == 5) && (boot_cpu_data.x86_model == 4)) {
+	/* C6 */
+	mcr_type = 0;
+    } else {
+	rdmsr (0x120, low, high );
+	mcr_type = (low>>17)&0x7;
+    }
+    centaur_ctx = kmalloc( sizeof( struct CENTAUR_MCR_CTX ), GFP_KERNEL );
+    if (centaur_ctx == NULL) {
+        printk("mtrr: Could not allocate memory. Disabling MTRR.\n");
+        boot_cpu_data.x86_capability &= ~X86_FEATURE_MTRR;
+        return;
+    }
+    for( i=0; i<MTRR_NUM_TYPES; ++i) {
+        centaur_ctx->type_bits[i] = 0;
+    }
+    switch( mcr_type ) {
+      case 0:
+        centaur_ctx->type_bits[ MTRR_TYPE_WRCOMB ] = 0x0f;
+        centaur_ctx->type_bits[ MTRR_TYPE_WRBACK ] = 0x1f;
+        mcr_ctrl_value = 0x01f0001f;
+        break;
+      case 1:
+        centaur_ctx->type_bits[ MTRR_TYPE_UNCACHABLE ] = 0x02;
+        centaur_ctx->type_bits[ MTRR_TYPE_WRCOMB ]     = 0x13;
+        centaur_ctx->type_bits[ MTRR_TYPE_WRTHROUGH ]  = 0x11;
+        centaur_ctx->type_bits[ MTRR_TYPE_WRBACK ]     = 0x19;
+        mcr_ctrl_value = 0x01f2005f;
+        break;
+      default:
+        kfree( centaur_ctx );
+        centaur_ctx = NULL;
+        printk ("mtrr: Centaur MCR traits version %u not supported. "
+		"Disabling MTRR.\n", mcr_type);
+	boot_cpu_data.x86_capability &= ~X86_FEATURE_MTRR;
+        return;
+    }
     set_mtrr_prepare (&ctxt);
     /* Unfortunately, MCR's are read-only, so there is no way to
      * find out what the bios might have done.
@@ -1661,14 +1724,16 @@
      * This way we are sure that the centaur_mcr array contains the actual
      * values. The disadvantage is that any BIOS tweaks are thus undone.
      */
+    /* switch off MCR's first */
+    wrmsr (0x120, 0, 0 );
     for (i = 0; i < 8; ++i)
     {
-        centaur_mcr[i].high = 0;
-	centaur_mcr[i].low = 0;
+        centaur_ctx->mcr[i].high = 0;
+	centaur_ctx->mcr[i].low = 0;
 	wrmsr (0x110 + i , 0, 0);
     }
     /*  Throw the main write-combining switch...  */
-    wrmsr (0x120, 0x01f0001f, 0);
+    wrmsr (0x120, mcr_ctrl_value, 0);
     set_mtrr_done (&ctxt);
 }   /*  End Function centaur_mcr_init  */
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/i386/kernel/process.c linux.15p9/arch/i386/kernel/process.c
--- linux.vanilla/arch/i386/kernel/process.c	Wed Oct 20 01:12:33 1999
+++ linux.15p9/arch/i386/kernel/process.c	Wed Feb 16 18:35:24 2000
@@ -31,9 +31,6 @@
 #include <linux/smp.h>
 #include <linux/reboot.h>
 #include <linux/init.h>
-#if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF)
-#include <linux/apm_bios.h>
-#endif
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -52,15 +49,20 @@
 
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
 
-#ifdef CONFIG_APM
-extern int  apm_do_idle(void);
-extern void apm_do_busy(void);
-#endif
-
-static int hlt_counter=0;
+int hlt_counter=0;
 
 #define HARD_IDLE_TIMEOUT (HZ / 3)
 
+/*
+ * Powermanagement idle function, if any..
+ */
+void (*acpi_idle)(void) = NULL;
+
+/*
+ * Power off function, if any
+ */
+void (*acpi_power_off)(void) = NULL;
+
 void disable_hlt(void)
 {
 	hlt_counter++;
@@ -71,34 +73,7 @@
 	hlt_counter--;
 }
 
-#ifndef __SMP__
-
-static void hard_idle(void)
-{
-	while (!current->need_resched) {
-		if (boot_cpu_data.hlt_works_ok && !hlt_counter) {
-#ifdef CONFIG_APM
-				/* If the APM BIOS is not enabled, or there
-				 is an error calling the idle routine, we
-				 should hlt if possible.  We need to check
-				 need_resched again because an interrupt
-				 may have occurred in apm_do_idle(). */
-			start_bh_atomic();
-			if (!apm_do_idle() && !current->need_resched)
-				__asm__("hlt");
-			end_bh_atomic();
-#else
-			__asm__("hlt");
-#endif
-	        }
- 		if (current->need_resched) 
- 			break;
-		schedule();
-	}
-#ifdef CONFIG_APM
-	apm_do_busy();
-#endif
-}
+#ifndef CONFIG_SMP
 
 /*
  * The idle loop on a uniprocessor i386..
@@ -116,8 +91,8 @@
 		if (work)
 			start_idle = jiffies;
 
-		if (jiffies - start_idle > HARD_IDLE_TIMEOUT) 
-			hard_idle();
+		if (acpi_idle && (jiffies - start_idle > HARD_IDLE_TIMEOUT))
+			acpi_idle();
 		else  {
 			if (boot_cpu_data.hlt_works_ok && !hlt_counter && !current->need_resched)
 		        	__asm__("hlt");
@@ -255,7 +230,10 @@
 	0x74, 0x02,				/*    jz    f                */
 	0x0f, 0x08,				/*    invd                   */
 	0x24, 0x10,				/* f: andb  $0x10,al         */
-	0x66, 0x0f, 0x22, 0xc0,			/*    movl  %eax,%cr0        */
+	0x66, 0x0f, 0x22, 0xc0			/*    movl  %eax,%cr0        */
+};
+static unsigned char jump_to_bios [] =
+{
 	0xea, 0x00, 0x00, 0xff, 0xff		/*    ljmp  $0xffff,$0x0000  */
 };
 
@@ -268,32 +246,13 @@
 			break;
 }
 
-void machine_restart(char * __unused)
+/*
+ * Switch to real mode and then execute the code
+ * specified by the code and length parameters.
+ * We assume that length will aways be less that 100!
+ */
+void machine_real_restart(unsigned char *code, int length)
 {
-#if __SMP__
-	/*
-	 * turn off the IO-APIC, so we can do a clean reboot
-	 */
-	init_pic_mode();
-#endif
-
-	if(!reboot_thru_bios) {
-		/* rebooting needs to touch the page at absolute addr 0 */
-		*((unsigned short *)__va(0x472)) = reboot_mode;
-		for (;;) {
-			int i;
-			for (i=0; i<100; i++) {
-				kb_wait();
-				udelay(50);
-				outb(0xfe,0x64);         /* pulse reset low */
-				udelay(50);
-			}
-			/* That didn't work - force a triple fault.. */
-			__asm__ __volatile__("lidt %0": :"m" (no_idt));
-			__asm__ __volatile__("int3");
-		}
-	}
-
 	cli();
 
 	/* Write zero to CMOS register number 0x0f, which the BIOS POST
@@ -343,8 +302,9 @@
 	   off paging.  Copy it near the end of the first page, out of the way
 	   of BIOS variables. */
 
-	memcpy ((void *) (0x1000 - sizeof (real_mode_switch)),
+	memcpy ((void *) (0x1000 - sizeof (real_mode_switch) - 100),
 		real_mode_switch, sizeof (real_mode_switch));
+	memcpy ((void *) (0x1000 - 100), code, length);
 
 	/* Set up the IDT for real mode. */
 
@@ -375,7 +335,36 @@
 
 	__asm__ __volatile__ ("ljmp $0x0008,%0"
 				:
-				: "i" ((void *) (0x1000 - sizeof (real_mode_switch))));
+				: "i" ((void *) (0x1000 - sizeof (real_mode_switch) - 100)));
+}
+
+void machine_restart(char * __unused)
+{
+#if CONFIG_SMP
+	/*
+	 * turn off the IO-APIC, so we can do a clean reboot
+	 */
+	init_pic_mode();
+#endif
+
+	if(!reboot_thru_bios) {
+		/* rebooting needs to touch the page at absolute addr 0 */
+		*((unsigned short *)__va(0x472)) = reboot_mode;
+		for (;;) {
+			int i;
+			for (i=0; i<100; i++) {
+				kb_wait();
+				udelay(50);
+				outb(0xfe,0x64);         /* pulse reset low */
+				udelay(50);
+			}
+			/* That didn't work - force a triple fault.. */
+			__asm__ __volatile__("lidt %0": :"m" (no_idt));
+			__asm__ __volatile__("int3");
+		}
+	}
+
+	machine_real_restart(jump_to_bios, sizeof(jump_to_bios));
 }
 
 void machine_halt(void)
@@ -384,9 +373,8 @@
 
 void machine_power_off(void)
 {
-#if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF)
-	apm_power_off();
-#endif
+	if (acpi_power_off)
+		acpi_power_off();
 }
 
 
@@ -432,7 +420,7 @@
  *  - if you use SMP you have a beefy enough machine that
  *    this shouldn't matter..
  */
-#ifndef __SMP__
+#ifndef CONFIG_SMP
 #define EXTRA_TASK_STRUCT	16
 static struct task_struct * task_struct_stack[EXTRA_TASK_STRUCT];
 static int task_struct_stack_ptr = -1;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/i386/kernel/setup.c linux.15p9/arch/i386/kernel/setup.c
--- linux.vanilla/arch/i386/kernel/setup.c	Tue Jan  4 21:18:39 2000
+++ linux.15p9/arch/i386/kernel/setup.c	Wed Feb 16 18:35:24 2000
@@ -7,8 +7,8 @@
  *  and Martin Mares, November 1997.
  *
  *  Force Cyrix 6x86(MX) and M II processors to report MTRR capability
- *  and fix against Cyrix "coma bug" by
- *      Zoltan Boszormenyi <zboszor@mol.hu> February 1999.
+ *  and Cyrix "coma bug" recognition by
+ *      Zoltán Böszörményi <zboszor@mail.externet.hu> February 1999.
  * 
  *  Force Centaur C6 processors to report MTRR capability.
  *      Bart Hartgers <bart@etpmod.phys.tue.nl>, May 199.
@@ -44,9 +44,7 @@
 #include <linux/delay.h>
 #include <linux/config.h>
 #include <linux/init.h>
-#ifdef CONFIG_APM
 #include <linux/apm_bios.h>
-#endif
 #ifdef CONFIG_BLK_DEV_RAM
 #include <linux/blk.h>
 #endif
@@ -84,9 +82,7 @@
  */
 struct drive_info_struct { char dummy[32]; } drive_info;
 struct screen_info screen_info;
-#ifdef CONFIG_APM
 struct apm_bios_info apm_bios_info;
-#endif
 struct sys_desc_table_struct {
 	unsigned short length;
 	unsigned char table[0];
@@ -277,9 +273,7 @@
  	ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
  	drive_info = DRIVE_INFO;
  	screen_info = SCREEN_INFO;
-#ifdef CONFIG_APM
 	apm_bios_info = APM_BIOS_INFO;
-#endif
 	if( SYS_DESC_TABLE.length != 0 ) {
 		MCA_bus = SYS_DESC_TABLE.table[3] &0x2;
 		machine_id = SYS_DESC_TABLE.table[0];
@@ -394,7 +388,7 @@
 	*memory_start_p = memory_start;
 	*memory_end_p = memory_end;
 
-#ifdef __SMP__
+#ifdef CONFIG_SMP
 	/*
 	 *	Save possible boot-time SMP configuration:
 	 */
@@ -436,14 +430,14 @@
 
 __initfunc(static int get_model_name(struct cpuinfo_x86 *c))
 {
-	unsigned int n, dummy, *v;
+	unsigned int n, dummy, *v, ecx, edx;
 
 	/* Actually we must have cpuid or we could never have
 	 * figured out that this was AMD from the vendor info :-).
 	 */
 
 	cpuid(0x80000000, &n, &dummy, &dummy, &dummy);
-	if (n < 4)
+	if (n < 0x80000004)
 		return 0;
 	cpuid(0x80000001, &dummy, &dummy, &dummy, &(c->x86_capability));
 	v = (unsigned int *) c->x86_model_id;
@@ -459,6 +453,18 @@
 	    (boot_cpu_data.x86_mask >= 8)))
 		c->x86_capability |= X86_FEATURE_MTRR;
 
+	if (n >= 0x80000005){
+		cpuid(0x80000005, &dummy, &dummy, &ecx, &edx);
+		printk("CPU: L1 I Cache: %dK  L1 D Cache: %dK\n",
+			ecx>>24, edx>>24);
+		c->x86_cache_size=(ecx>>24)+(edx>>24);
+	}
+	if (n >= 0x80000006){
+		cpuid(0x80000006, &dummy, &dummy, &ecx, &edx);
+		printk("CPU: L2 Cache: %dK\n", ecx>>16);
+		c->x86_cache_size = ecx>>16;
+	}
+
 	return 1;
 }
 
@@ -529,14 +535,6 @@
 			break;
 		case 6:	/* An Athlon. We can trust the BIOS probably */
 		{
-			
-			u32 ecx, edx, dummy;
-			cpuid(0x80000005, &dummy, &dummy, &ecx, &edx);
-			printk("L1 I Cache: %dK  L1 D Cache: %dK\n",
-				ecx>>24, edx>>24);
-			cpuid(0x80000006, &dummy, &dummy, &ecx, &edx);
-			printk("L2 Cache: %dK\n", ecx>>16);
-			c->x86_cache_size = ecx>>16;
 			break;
 		}
 		
@@ -667,10 +665,18 @@
                 /* It isnt really a PCI quirk directly, but the cure is the
        	           same. The MediaGX has deep magic SMM stuff that handles the
                    SB emulation. It thows away the fifo on disable_dma() which
-                   is wrong and ruins the audio. */
+                   is wrong and ruins the audio. 
+                   
+                   Bug2: VSA1 has a wrap bug so that using maximum sized DMA 
+                   causes bad things. According to NatSemi VSA2 has another
+                   bug to do with 'hlt'. I've not seen any boards using VSA2
+                   and X doesn't seem to support it either so who cares 8).
+                   VSA1 we work around however.
+                   
+                  */
 
 		printk(KERN_INFO "Working around Cyrix MediaGX virtual DMA bug.\n");
-                isa_dma_bridge_buggy = 1;
+                isa_dma_bridge_buggy = 2;
                   	                                                                     	        
 #endif
 		/* GXm supports extended cpuid levels 'ala' AMD */
@@ -975,7 +981,7 @@
 	int i, n;
 
 	for(n=0; n<NR_CPUS; n++, c++) {
-#ifdef __SMP__
+#ifdef CONFIG_SMP
 		if (!(cpu_online_map & (1<<n)))
 			continue;
 #endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/i386/kernel/smp.c linux.15p9/arch/i386/kernel/smp.c
--- linux.vanilla/arch/i386/kernel/smp.c	Tue Jan  4 21:18:39 2000
+++ linux.15p9/arch/i386/kernel/smp.c	Tue Jan 18 01:06:40 2000
@@ -795,6 +795,208 @@
 	return memory_start;
 }
 
+#ifdef CONFIG_X86_TSC
+/*
+ * TSC synchronization.
+ *
+ * We first check wether all CPUs have their TSC's synchronized,
+ * then we print a warning if not, and always resync.
+ */
+
+static atomic_t tsc_start_flag = ATOMIC_INIT(0);
+static atomic_t tsc_count_start = ATOMIC_INIT(0);
+static atomic_t tsc_count_stop = ATOMIC_INIT(0);
+static unsigned long long tsc_values[NR_CPUS] = { 0, };
+
+#define NR_LOOPS 5
+
+extern unsigned long fast_gettimeoffset_quotient;
+
+/*
+ * accurate 64-bit division, expanded to 32-bit divisions. Not terribly
+ * optimized but we need it at boot time only anyway.
+ *
+ * result == a / b
+ *        == (a1 + a2*(2^32)) / b
+ *        == a1/b + a2*(2^32/b)
+ *        == a1/b + a2*((2^32-1)/b) + a2/b + (a2*((2^32-1) % b))/b
+ *                    ^---- (this multiplication can overflow)
+ */
+
+unsigned long long div64 (unsigned long long a, unsigned long long b)
+{
+	unsigned int a1, a2, b0;
+	unsigned long long res;
+
+	if (b > 0x00000000ffffffffULL)
+		return 0;
+	if (!b)
+		panic("huh?\n");
+
+	b0 = (unsigned int) b;
+	a1 = ((unsigned int*)&a)[0];
+	a2 = ((unsigned int*)&a)[1];
+
+	res = a1/b0 +
+		(unsigned long long)a2 * (unsigned long long)(0xffffffff/b0) +
+		a2 / b0 +
+		(a2 * (0xffffffff % b0)) / b0;
+
+        return res;
+}
+
+
+static void __init synchronize_tsc_bp (void)
+{
+	int i;
+	unsigned long long t0;
+	unsigned long long sum, avg;
+	long long delta;
+	unsigned long one_usec;
+	int buggy = 0;
+
+	printk("checking TSC synchronization across CPUs: ");
+
+	one_usec = ((1<<30)/fast_gettimeoffset_quotient)*(1<<2);
+	
+	atomic_set(&tsc_start_flag, 1);
+	wmb();
+
+	/*
+	 * We loop a few times to get a primed instruction cache,
+	 * then the last pass is more or less synchronized and
+	 * the BP and APs set their cycle counters to zero all at
+	 * once. This reduces the chance of having random offsets
+	 * between the processors, and guarantees that the maximum
+	 * delay between the cycle counters is never bigger than
+	 * the latency of information-passing (cachelines) between
+	 * two CPUs.
+	 */
+	for (i = 0; i < NR_LOOPS; i++) {
+		/*
+		 * all APs synchronize but they loop on '== num_cpus'
+		 */
+		while (atomic_read(&tsc_count_start) != smp_num_cpus-1) mb();
+		atomic_set(&tsc_count_stop, 0);
+		wmb();
+		/*
+		 * this lets the APs save their current TSC:
+		 */
+		atomic_inc(&tsc_count_start);
+
+		rdtscll(tsc_values[smp_processor_id()]);
+		/*
+		 * We clear the TSC in the last loop:
+		 */
+		if (i == NR_LOOPS-1)
+			CLEAR_TSC;
+
+		/*
+		 * Wait for all APs to leave the synchronization point:
+		 */
+		while (atomic_read(&tsc_count_stop) != smp_num_cpus-1) mb();
+		atomic_set(&tsc_count_start, 0);
+		wmb();
+		atomic_inc(&tsc_count_stop);
+	}
+
+	sum = 0;
+	for (i = 0; i < NR_CPUS; i++) {
+		if (!(cpu_online_map & (1 << i)))
+			continue;
+
+		t0 = tsc_values[i];
+		sum += t0;
+	}
+	avg = div64(sum, smp_num_cpus);
+
+	sum = 0;
+	for (i = 0; i < NR_CPUS; i++) {
+		if (!(cpu_online_map & (1 << i)))
+			continue;
+
+		delta = tsc_values[i] - avg;
+		if (delta < 0)
+			delta = -delta;
+		/*
+		 * We report bigger than 2 microseconds clock differences.
+		 */
+		if (delta > 2*one_usec) {
+			long realdelta;
+			if (!buggy) {
+				buggy = 1;
+				printk("\n");
+			}
+			realdelta = div64(delta, one_usec);
+			if (tsc_values[i] < avg)
+				realdelta = -realdelta;
+		
+			printk("BIOS BUG: CPU#%d improperly initialized, has %ld usecs TSC skew! FIXED.\n",
+				i, realdelta);
+		}
+				
+		sum += delta;
+	}
+	if (!buggy)
+		printk("passed.\n");
+
+#if 0
+	printk("CPU%d read locks\n", smp_processor_id());
+	read_lock_irq(&tasklist_lock);
+
+	printk("CPU%d delays 2 secs\n", smp_processor_id());
+	mdelay(1000);
+
+	printk("CPU%d does IRQ0 ...\n", smp_processor_id());
+	asm volatile ("int $0x51");
+
+	printk("CPU%d back from IRQ0 ???\n", smp_processor_id());
+	read_unlock(&tasklist_lock);
+#endif
+}
+
+static void __init synchronize_tsc_ap (void)
+{
+	int i;
+
+	/*
+	 * smp_num_cpus is not necessarily known at the time
+	 * this gets called, so we first wait for the BP to
+	 * finish SMP initialization:
+	 */
+	while (!atomic_read(&tsc_start_flag)) mb();
+
+	for (i = 0; i < NR_LOOPS; i++) {
+		atomic_inc(&tsc_count_start);
+		while (atomic_read(&tsc_count_start) != smp_num_cpus) mb();
+
+		rdtscll(tsc_values[smp_processor_id()]);
+		if (i == NR_LOOPS-1)
+			CLEAR_TSC;
+
+		atomic_inc(&tsc_count_stop);
+		while (atomic_read(&tsc_count_stop) != smp_num_cpus) mb();
+	}
+
+#if 0
+	printk("CPU%d clis\n", smp_processor_id());
+	cli();
+
+	printk("CPU%d delays 4 secs\n", smp_processor_id());
+	mdelay(4000);
+
+	printk("CPU%d does write_lock ...\n", smp_processor_id());
+	write_lock_irq(&tasklist_lock);
+
+	printk("CPU%d back from write lock???\n", smp_processor_id());
+	write_unlock_irq(&tasklist_lock);
+	sti();
+#endif
+}
+#undef NR_LOOPS
+
+#endif
+
 extern void calibrate_delay(void);
 
 void __init smp_callin(void)
@@ -880,6 +1082,13 @@
 	 *	Allow the master to continue.
 	 */
 	set_bit(cpuid, (unsigned long *)&cpu_callin_map[0]);
+
+#ifdef CONFIG_X86_TSC
+	/*
+	 *	Synchronize the TSC with the BP
+	 */
+ 	synchronize_tsc_ap ();
+#endif
 }
 
 int cpucount = 0;
@@ -1401,7 +1610,9 @@
 		printk(KERN_WARNING "WARNING: SMP operation may be unreliable with B stepping processors.\n");
 	SMP_PRINTK(("Boot done.\n"));
 
+	ack_APIC_irq();
 	cache_APIC_registers();
+	ack_APIC_irq();
 #ifndef CONFIG_VISWS
 	/*
 	 * Here we can be sure that there is an IO-APIC in the system. Let's
@@ -1412,8 +1623,15 @@
 #endif
 
 smp_done:
-}
 
+#ifdef CONFIG_X86_TSC
+	/*
+	 * Synchronize the TSC with the AP
+	 */
+	if (cpucount)
+	 	synchronize_tsc_bp();
+#endif
+}
 
 /*
  * the following functions deal with sending IPIs between CPUs.
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/i386/kernel/time.c linux.15p9/arch/i386/kernel/time.c
--- linux.vanilla/arch/i386/kernel/time.c	Sat Aug 14 02:26:10 1999
+++ linux.15p9/arch/i386/kernel/time.c	Tue Jan 18 01:06:40 2000
@@ -74,7 +74,7 @@
  * Equal to 2^32 * (1 / (clocks per usec) ).
  * Initialized in time_init.
  */
-static unsigned long fast_gettimeoffset_quotient=0;
+unsigned long fast_gettimeoffset_quotient=0;
 
 extern rwlock_t xtime_lock;
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/m68k/kernel/ints.c linux.15p9/arch/m68k/kernel/ints.c
--- linux.vanilla/arch/m68k/kernel/ints.c	Sat Aug 14 02:26:26 1999
+++ linux.15p9/arch/m68k/kernel/ints.c	Thu Feb 17 13:47:25 2000
@@ -76,17 +76,17 @@
 void (*mach_free_irq) (unsigned int, void *) = dummy_free_irq;
 
 /*
- * void init_IRQ(void)
+ * unsigned long init_IRQ(unsigned long memory)
  *
- * Parameters:	None
+ * Parameters:	Memory base
  *
- * Returns:	Nothing
+ * Returns:	New memory base
  *
  * This function should be called during kernel startup to initialize
  * the IRQ handling routines.
  */
 
-__initfunc(void init_IRQ(void))
+unsigned long __init init_IRQ(unsigned long memory)
 {
 	int i;
 
@@ -102,6 +102,7 @@
 		nodes[i].handler = NULL;
 
 	mach_init_IRQ ();
+	return memory;
 }
 
 irq_node_t *new_irq_node(void)
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/mips/kernel/irq.c linux.15p9/arch/mips/kernel/irq.c
--- linux.vanilla/arch/mips/kernel/irq.c	Sat Aug 14 02:27:14 1999
+++ linux.15p9/arch/mips/kernel/irq.c	Thu Feb 17 13:49:19 2000
@@ -376,11 +376,12 @@
 	outb(cached_21, 0x21);
 }
 
-__initfunc(void init_IRQ(void))
+unsigned long init_IRQ(unsigned long memory)
 {
 	irq_cannonicalize = i8259_irq_cannonicalize;
 	/* i8259_init(); */
 	irq_setup();
+	return memory;
 }
 
 EXPORT_SYMBOL(irq_cannonicalize);
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/ppc/kernel/gemini_pci.c linux.15p9/arch/ppc/kernel/gemini_pci.c
--- linux.vanilla/arch/ppc/kernel/gemini_pci.c	Tue Jan  4 21:18:40 2000
+++ linux.15p9/arch/ppc/kernel/gemini_pci.c	Fri Jan 21 19:02:47 2000
@@ -77,188 +77,20 @@
 	return PCIBIOS_SUCCESSFUL;
 }
 
-struct gemini_device {
-	unsigned short vendor, device;
-	unsigned char irq;
-	unsigned short cmd;
-	unsigned char cache_line, latency;
-	void (*init)(struct pci_dev *dev);
-};
-
-static struct gemini_device gemini_map[] = {
-	{ PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C885, 11, 0x15, 32, 248, NULL },
-	{ PCI_VENDOR_ID_NCR, 0x701, 10, 0, 0, 0, NULL },
-	{ PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_CA91C042, 3, 0, 0, 0, NULL },
-	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_MPIC, 0xff, 0, 0, 0, NULL },
-	{ PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_670, 0xff, 0, 0, 0, NULL },
-	{ PCI_VENDOR_ID_MOTOROLA, PCI_DEVICE_ID_MOTOROLA_MPC106, 0xff, 0, 0, 0, NULL },
-};
-
-static int gemini_map_count = (sizeof( gemini_map ) /
-                               sizeof( gemini_map[0] ));
-
- 
-
-/*  This just sets up the known devices on the board. */
-__initfunc(static void mapin_device( struct pci_dev *dev ))
-{
-	struct gemini_device *p;
-	unsigned short cmd;
-	int i;
-  
-
-	for( i=0; i < gemini_map_count; i++ ) {
-		p = &(gemini_map[i]);
-    
-		if ( p->vendor == dev->vendor && 
-		     p->device == dev->device ) {
-     
-			if (p->irq != 0xff) {
-				pci_write_config_byte( dev, PCI_INTERRUPT_LINE, p->irq );
-				dev->irq = p->irq;
-			}
-
-			if (p->cmd) {
-				pci_read_config_word( dev, PCI_COMMAND, &cmd );
-				pci_write_config_word( dev, PCI_COMMAND, (p->cmd|cmd));
-			}
-
-			if (p->cache_line)
-				pci_write_config_byte( dev, PCI_CACHE_LINE_SIZE, p->cache_line );
- 
-			if (p->latency)
-				pci_write_config_byte( dev, PCI_LATENCY_TIMER, p->latency );
-		}
-	}
-}
-
-#define KB 1024
-#define MB (KB*KB)
-
-#define ALIGN(val,align) (((val) + ((align) -1))&(~((align) -1)))
-#define MAX(a,b)   (((a) > (b)) ? (a) : (b))
-
-#define FIRST_IO_ADDR 0x10000
-#define FIRST_MEM_ADDR 0x02000000
-
-#define GEMINI_PCI_MEM_BASE (0xf0000000)
-#define GEMINI_PCI_IO_BASE  (0xfe800000)
-
-static unsigned long pci_mem_base = GEMINI_PCI_MEM_BASE;
-static unsigned long pci_io_base = GEMINI_PCI_IO_BASE;
-
-static unsigned int io_base = FIRST_IO_ADDR;
-static unsigned int mem_base = FIRST_MEM_ADDR;
-
-
-
-__initfunc(static void layout_dev( struct pci_dev *dev ))
+__initfunc(void gemini_pcibios_fixup(void))
 {
-	int i;
 	struct pci_bus *bus;
-	unsigned short cmd;
-	unsigned int reg, base, mask, size, alignto, type;
-
-	bus = dev->bus;
-
-	/* make any known settings happen */
-	mapin_device( dev );
-
-	gemini_pcibios_read_config_word( bus->number, dev->devfn, PCI_COMMAND, &cmd );
-
-	for( reg = PCI_BASE_ADDRESS_0, i=0; reg <= PCI_BASE_ADDRESS_5; reg += 4, i++ ) {
-    
-		/* MPIC already done */
-		if (dev->vendor == PCI_VENDOR_ID_IBM &&
-		    dev->device == PCI_DEVICE_ID_IBM_MPIC)
-			return;
-
-		gemini_pcibios_write_config_dword( bus->number, dev->devfn, reg, 0xffffffff );
-		gemini_pcibios_read_config_dword( bus->number, dev->devfn, reg, &base );
-		if (!base) {
-			dev->base_address[i] = 0;
-			continue;
-		}
-
-		if (base & PCI_BASE_ADDRESS_SPACE_IO) {
-			cmd |= PCI_COMMAND_IO;
-			base &= PCI_BASE_ADDRESS_IO_MASK;
-			mask = (~base << 1) | 0x1;
-			size = (mask & base) & 0xffffffff;
-			alignto = MAX(0x400, size);
-			base = ALIGN(io_base, alignto);
-			io_base = base + size;
-			gemini_pcibios_write_config_dword( bus->number, dev->devfn, reg, 
-							   ((pci_io_base + base) & 0x00ffffff) | 0x1);
-			dev->base_address[i] = (pci_io_base + base) | 0x1;
-		}
-
-		else {
-			cmd |= PCI_COMMAND_MEMORY;
-			type = base & PCI_BASE_ADDRESS_MEM_TYPE_MASK;
-			mask = (~base << 1) | 0x1;
-			size = (mask & base) & 0xffffffff;
-			switch( type ) {
-
-			case PCI_BASE_ADDRESS_MEM_TYPE_32:
-				break;
-			case PCI_BASE_ADDRESS_MEM_TYPE_64:
-				printk("Warning: Ignoring 64-bit device; slot %d, function %d.\n",
-				       PCI_SLOT( dev->devfn ), PCI_FUNC( dev->devfn ));
-				reg += 4;
-				continue;
-			}
-
-			alignto = MAX(0x1000, size);
-			base = ALIGN(mem_base, alignto);
-			mem_base = base + size;
-			gemini_pcibios_write_config_dword( bus->number, dev->devfn,
-							   reg, (pci_mem_base + base));
-			dev->base_address[i] = pci_mem_base + base;
-		}
-	}
-
-	if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
-		cmd |= PCI_COMMAND_IO;
-
-	gemini_pcibios_write_config_word( bus->number, dev->devfn, PCI_COMMAND,
-					  (cmd|PCI_COMMAND_MASTER));
-
-}
-
-__initfunc(static void layout_bus( struct pci_bus *bus ))
-{
 	struct pci_dev *dev;
+	int i;
 
-	if (!bus->devices && !bus->children)
-		return;
-
-	io_base = ALIGN(io_base, 4*KB);
-	mem_base = ALIGN(mem_base, 4*KB);
-
-	for( dev = bus->devices; dev; dev = dev->sibling ) {
-		if (((dev->class >> 16) != PCI_BASE_CLASS_BRIDGE) ||
-		    ((dev->class >> 8) == PCI_CLASS_BRIDGE_OTHER))
-			layout_dev( dev );
+	for(bus = &pci_root; bus; bus = bus->children) {
+	    for(dev = bus->devices; dev; dev = dev->sibling) {
+		for(i = 0; i < 6; i++) {
+		    if (dev->base_address[i] & PCI_COMMAND_IO)
+			dev->base_address[i] |= (0xfe << 24);
+		}
+	    }
 	}
-}
-
-
-__initfunc(void gemini_pcibios_fixup(void))
-{
-	struct pci_bus *bus;
-	unsigned long orig_mem_base, orig_io_base;
-
-	orig_mem_base = pci_mem_base;
-	orig_io_base = pci_io_base;
-
-	for( bus = &pci_root; bus; bus = bus->children )
-		layout_bus( bus );
-
-	pci_mem_base = orig_mem_base;
-	pci_io_base = orig_io_base;
-
-
 }
 
 decl_config_access_method(gemini);
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/ppc/kernel/head.S linux.15p9/arch/ppc/kernel/head.S
--- linux.vanilla/arch/ppc/kernel/head.S	Tue Jan  4 21:18:40 2000
+++ linux.15p9/arch/ppc/kernel/head.S	Mon Feb  7 12:25:55 2000
@@ -1739,6 +1739,7 @@
 	.globl	__secondary_start_psurge
 __secondary_start_psurge:
 	li	r24,1			/* cpu # */
+	li	r3,0			/* starting physical address */
 	b	__secondary_start
 
 	.globl	__secondary_hold
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/ppc/kernel/irq.c linux.15p9/arch/ppc/kernel/irq.c
--- linux.vanilla/arch/ppc/kernel/irq.c	Tue Jan  4 21:18:40 2000
+++ linux.15p9/arch/ppc/kernel/irq.c	Thu Feb 17 13:50:08 2000
@@ -296,16 +296,17 @@
 	return 0;
 }
 
-void __init init_IRQ(void)
+unsigned long __init init_IRQ(unsigned long memory)
 {
 	static int once = 0;
 
 	if ( once )
-		return;
+		return memory;
 	else
 		once++;
 	
 	ppc_md.init_IRQ();
+	return memory;
 }
 
 #ifdef __SMP__
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/ppc/kernel/pmac_setup.c linux.15p9/arch/ppc/kernel/pmac_setup.c
--- linux.vanilla/arch/ppc/kernel/pmac_setup.c	Tue Jan  4 21:18:40 2000
+++ linux.15p9/arch/ppc/kernel/pmac_setup.c	Wed Jan 12 01:11:15 2000
@@ -47,6 +47,7 @@
 #include <asm/pgtable.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
+#include <asm/dma.h>
 #include <asm/pci-bridge.h>
 #include <asm/adb.h>
 #include <asm/cuda.h>
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/ppc/kernel/pmac_time.c linux.15p9/arch/ppc/kernel/pmac_time.c
--- linux.vanilla/arch/ppc/kernel/pmac_time.c	Sat Aug 28 20:00:53 1999
+++ linux.15p9/arch/ppc/kernel/pmac_time.c	Fri Jan 21 17:52:39 2000
@@ -56,7 +56,11 @@
 	struct adb_request req;
 
 	/* Get the time from the RTC */
-	switch (adb_hardware) {
+	if (adb_controller == 0)
+		return 0;
+	/* adb_controller->kind, not adb_hardware, since that doesn't
+	   get set until we call adb_init - paulus. */
+	switch (adb_controller->kind) {
 	case ADB_VIACUDA:
 		if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0)
 			return 0;
@@ -68,8 +72,10 @@
 		return (req.reply[3] << 24) + (req.reply[4] << 16)
 			+ (req.reply[5] << 8) + req.reply[6] - RTC_OFFSET;
 	case ADB_VIAPMU:
-		if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0)
+		if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) {
+			printk("pmac_read_rtc_time: pmu_request failed\n");
 			return 0;
+		}
 		while (!req.complete)
 			pmu_poll();
 		if (req.reply_len != 5)
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/ppc/kernel/prom.c linux.15p9/arch/ppc/kernel/prom.c
--- linux.vanilla/arch/ppc/kernel/prom.c	Tue Jan  4 21:18:40 2000
+++ linux.15p9/arch/ppc/kernel/prom.c	Thu Jan 27 15:35:53 2000
@@ -89,6 +89,7 @@
 
 prom_entry prom = 0;
 ihandle prom_chosen = 0, prom_stdout = 0;
+int prom_version = 0;
 
 extern char *klimit;
 char *bootpath = 0;
@@ -273,7 +274,7 @@
 	char type[16], *path;
 #endif	
 	unsigned long mem;
-	ihandle prom_rtas, prom_mmu;
+	ihandle prom_rtas, prom_mmu, prom_op;
 	unsigned long offset = reloc_offset();
 	int l;
 	char *p, *d;
@@ -411,6 +412,25 @@
 	RELOC(of_stdout_device) = PTRUNRELOC(p);
 	mem += strlen(p) + 1;
 
+	/* Find the OF version */
+	prom_op = call_prom(RELOC("finddevice"), 1, 1, RELOC("/openprom"));
+	RELOC(prom_version) = 0;
+	if (prom_op != (void*)-1) {
+	    char model[64];
+	    int sz;
+	    sz = (int)call_prom(RELOC("getprop"), 4, 1, prom_op, RELOC("model"), model, 64);
+	    if (sz > 0) {
+	    	char *c;
+		for (c = model; *c; c++)
+		    if (*c >= '0' && *c <= '9') {
+			RELOC(prom_version) = *c - '0';
+			break;
+		    }
+	    }
+	}
+	if (RELOC(prom_version) >= 3)
+		prom_print(RELOC("OF Version 3 detected.\n"));
+
 	/* Get the boot device and translate it to a full OF pathname. */
 	p = (char *) mem;
 	l = (int) call_prom(RELOC("getprop"), 4, 1, RELOC(prom_chosen),
@@ -482,10 +502,17 @@
 			prom_print(RELOC(" done\n"));
 	}
 
-	if ((int) call_prom(RELOC("getprop"), 4, 1, RELOC(prom_chosen),
+	/* If we are already running at 0xc0000000, we assume we were loaded by
+	 * an OF bootloader which did set a BAT for us. This breaks OF translate
+	 * so we force phys to be 0
+	 */
+	if (offset == 0)
+		phys = 0;
+	else {
+ 	    if ((int) call_prom(RELOC("getprop"), 4, 1, RELOC(prom_chosen),
 			    RELOC("mmu"), &prom_mmu, sizeof(prom_mmu)) <= 0) {	
 		prom_print(RELOC(" no MMU found\n"));
-	} else {
+	    } else {
 		int nargs;
 		struct prom_args prom_args;
 		nargs = 4;
@@ -503,8 +530,9 @@
 			prom_print(RELOC(" (translate failed) "));
 		else
 			phys = (unsigned long)prom_args.args[nargs+3];
+	    }
 	}
-
+	    
 #ifdef CONFIG_SMP
 	/*
 	 * With CHRP SMP we need to use the OF to start the other
@@ -580,7 +608,16 @@
 		else
 			prom_print(RELOC("...failed\n"));
 	}
-#endif	
+#endif /* CONFIG_SMP */
+	
+	/* If OpenFirmware version >= 3, then use quiesce call */
+	if (RELOC(prom_version) >= 3) {
+	    prom_print(RELOC("Calling quiesce ...\n"));
+	    call_prom(RELOC("quiesce"), 0, 0);
+	    offset = reloc_offset();
+	    phys = offset + KERNELBASE;
+	}
+
 	return phys;
 }
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/ppc/kernel/smp.c linux.15p9/arch/ppc/kernel/smp.c
--- linux.vanilla/arch/ppc/kernel/smp.c	Tue Jan  4 21:18:40 2000
+++ linux.15p9/arch/ppc/kernel/smp.c	Fri Jan 21 19:02:47 2000
@@ -441,6 +441,8 @@
 	 */
 	if ( _machine & (_MACH_gemini|_MACH_chrp|_MACH_prep) )
 		do_openpic_setup_cpu();
+	if ( _machine == _MACH_gemini )
+	        gemini_init_l2();
 	while(!smp_commenced)
 		barrier();
 	__sti();
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/ppc/mm/fault.c linux.15p9/arch/ppc/mm/fault.c
--- linux.vanilla/arch/ppc/mm/fault.c	Sat Aug 14 02:26:47 1999
+++ linux.15p9/arch/ppc/mm/fault.c	Fri Jan 21 17:52:39 2000
@@ -48,7 +48,7 @@
 unsigned int probingmem = 0;
 
 extern void die_if_kernel(char *, struct pt_regs *, long);
-void bad_page_fault(struct pt_regs *, unsigned long);
+void bad_page_fault(struct pt_regs *, unsigned long, unsigned long);
 void do_page_fault(struct pt_regs *, unsigned long, unsigned long);
 
 /*
@@ -60,6 +60,7 @@
 {
 	struct vm_area_struct * vma;
 	struct mm_struct *mm = current->mm;
+	int fault;
 
 	/*printk("address: %08lx nip:%08lx code: %08lx %s%s%s%s%s%s\n",
 	       address,regs->nip,error_code,
@@ -82,23 +83,11 @@
 			return;
 	}
 #endif
-	if (in_interrupt()) {
-		static int complained;
-		if (complained < 20) {
-			++complained;
-			printk("page fault in interrupt handler, addr=%lx\n",
-			       address);
-			show_regs(regs);
-#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
-			if (debugger_kernel_faults)
-				debugger(regs);
-#endif
-		}
-	}
-	if (current == NULL) {
-		bad_page_fault(regs, address);
+	if (in_interrupt() || mm == &init_mm) {
+		bad_page_fault(regs, address, error_code);
 		return;
 	}
+
 	down(&mm->mmap_sem);
 	vma = find_vma(mm, address);
 	if (!vma)
@@ -115,6 +104,7 @@
 	if (error_code & 0x95700000)
 		/* an error such as lwarx to I/O controller space,
 		   address matching DABR, eciwx, etc. */
+		goto bad_area;
 #endif /* CONFIG_6xx */
 #ifdef CONFIG_8xx
         /* The MPC8xx seems to always set 0x80000000, which is
@@ -123,10 +113,9 @@
          */
 	if (error_code & 0x10000000)
                 /* Guarded storage error. */
-#endif /* CONFIG_8xx */
 		goto bad_area;
-	
-	
+#endif /* CONFIG_8xx */
+
 	/* a write */
 	if (error_code & 0x02000000) {
 		if (!(vma->vm_flags & VM_WRITE))
@@ -139,8 +128,13 @@
 		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
 			goto bad_area;
 	}
-	if (!handle_mm_fault(current, vma, address, error_code & 0x02000000))
-		goto bad_area;
+
+ survive:
+	fault = handle_mm_fault(current, vma, address, error_code & 0x2000000);
+	if (!fault)
+		goto do_sigbus;
+	if (fault < 0)
+		goto out_of_memory;
 	up(&mm->mmap_sem);
 	/*
 	 * keep track of tlb+htab misses that are good addrs but
@@ -151,36 +145,72 @@
 	return;
 
 bad_area:
-
 	up(&mm->mmap_sem);
 	pte_errors++;	
-	bad_page_fault(regs, address);
+	bad_page_fault(regs, address, error_code);
+	return;
+
+/*
+ * We ran out of memory, or some other thing happened to us that made
+ * us unable to handle the page fault gracefully.
+ */
+out_of_memory:
+	if (current->pid == 1) {
+		current->policy |= SCHED_YIELD;
+		schedule();
+		goto survive;
+	}
+	up(&mm->mmap_sem);
+	if (user_mode(regs)) {
+		printk("VM: killing process %s\n", current->comm);
+		do_exit(SIGKILL);
+	}
+	bad_page_fault(regs, address, error_code);
+	return;
+
+do_sigbus:
+	up(&mm->mmap_sem);
+
+	/*
+	 * Send a sigbus, regardless of whether we were in kernel
+	 * or user mode.
+	 */
+	force_sig(SIGBUS, current);
+
+	/* Kernel mode? Handle exceptions or die */
+	if (!user_mode(regs))
+		bad_page_fault(regs, address, error_code);
 }
 
 void
-bad_page_fault(struct pt_regs *regs, unsigned long address)
+bad_page_fault(struct pt_regs *regs, unsigned long address, unsigned long err)
 {
 	unsigned long fixup;
 	if (user_mode(regs)) {
 		force_sig(SIGSEGV, current);
 		return;
 	}
-	
+
 	/* Are we prepared to handle this fault?  */
 	if ((fixup = search_exception_table(regs->nip)) != 0) {
 		regs->nip = fixup;
 		return;
 	}
 
-	/* kernel has accessed a bad area */
+	/* kernel has accessed a bad address */
+	if (address < PAGE_SIZE)
+		printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
+	else
+		printk(KERN_ALERT "Unable to handle kernel paging request");
+	printk(" at virtual address %08lx (error %lx)\n", address, err);
 	show_regs(regs);
-	print_backtrace( (unsigned long *)regs->gpr[1] );
 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
 	if (debugger_kernel_faults)
 		debugger(regs);
 #endif
+	print_backtrace((unsigned long *)regs->gpr[1]);
 	panic("kernel access of bad area pc %lx lr %lx address %lX tsk %s/%d",
-	      regs->nip,regs->link,address,current->comm,current->pid);
+	      regs->nip, regs->link, address, current->comm, current->pid);
 }
 
 #ifdef CONFIG_8xx
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/boot/Makefile linux.15p9/arch/s390/boot/Makefile
--- linux.vanilla/arch/s390/boot/Makefile	Tue Jan  4 21:18:40 2000
+++ linux.15p9/arch/s390/boot/Makefile	Thu Feb 17 13:30:27 2000
@@ -14,18 +14,15 @@
 
 include $(TOPDIR)/Rules.make
 
+.S.o:
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o
+
 %.lnk: %.o
 	$(LD) -Ttext 0x0 -o $@ $<
 
 %.boot: %.lnk
 	$(OBJCOPY) -O binary $< $@
 
-silo: silo.c
-	$(CROSS_COMPILE)gcc $< -o $@
-
-dasdfmt: dasdfmt.c
-	$(CROSS_COMPILE)gcc $< -o $@
-
 image: $(CONFIGURE) $(TOPDIR)/vmlinux \
 	iplfba.boot ipleckd.boot 
 	$(OBJCOPY) -O binary $(TOPDIR)/vmlinux image
@@ -36,5 +33,5 @@
 dep:
 
 clean:
-	rm -f image listing silo dasdfmt iplfba.boot ipleckd.boot
+	rm -f image listing iplfba.boot ipleckd.boot
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/boot/dasdfmt.c linux.15p9/arch/s390/boot/dasdfmt.c
--- linux.vanilla/arch/s390/boot/dasdfmt.c	Tue Jan  4 21:18:40 2000
+++ linux.15p9/arch/s390/boot/dasdfmt.c	Thu Jan  1 01:00:00 1970
@@ -1,559 +0,0 @@
-/*
- *
- * dasdfmt.c
- *
- *  S390 version
- *    Copyright (C) 1999 IBM Corporation
- *    Author(s): Utz Bacher (utz.bacher@de.ibm.com)
- *
- * Still to do:
- *   detect non-switch parameters and complain about them
- */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-#include <getopt.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <dirent.h>
-
-#define EXIT_MISUSE 1
-#define TEMPFILENAME "/tmp/ddfXXXXXX"
-#define TEMPFILENAMECHARS 8  /* 8 characters are fixed in all temp filenames */
-#define IOCTL_COMMAND 'D' << 8
-#define SLASHDEV "/dev/"
-#define PROC_DASD_DEVICES "/proc/dasd/devices"
-#define DASD_DRIVER_NAME "dasd"
-#define PROC_LINE_LENGTH 80
-#define ERR_LENGTH 80
-
-#define MAX_FILELEN NAME_MAX+PATH_MAX
-
-#define GIVEN_DEVNO 1
-#define GIVEN_MAJOR 2
-#define GIVEN_MINOR 4
-
-#define CHECK_START 1
-#define CHECK_END 2
-#define CHECK_BLKSIZE 4
-#define CHECK_ALL ~0
-
-#define ERRMSG(x...) {fflush(stdout);fprintf(stderr,x);}
-#define ERRMSG_EXIT(ec,x...) {fflush(stdout);fprintf(stderr,x);exit(ec);}
-
-#define CHECK_SPEC_MAX_ONCE(i,str) \
-	{if (i>1) \
-		ERRMSG_EXIT(EXIT_MISUSE,"%s: " str " " \
-			"can only be specified once\n",prog_name);}
-
-#define PARSE_PARAM_INTO(x,param,base,str) \
-	{x=(int)strtol(param,&endptr,base); \
-	if (*endptr) \
-		ERRMSG_EXIT(EXIT_MISUSE,"%s: " str " " \
-			"is in invalid format\n",prog_name);}
-
-typedef struct {
-	int start_unit;
-	int stop_unit;
-	int blksize;
-} format_data_t;
-
-char prog_name[]="dasd_format";
-char tempfilename[]=TEMPFILENAME;
-
-void
-exit_usage(int exitcode)
-{
-	printf("Usage: %s [-tvV] [-s start_track] [-e end_track] \n",prog_name);
-	printf("       [-b blocksize] -f dev_filename | -n 390_devno\n");
-	exit(exitcode);
-}
-
-void
-get_xno_from_xno(int *devno,int *major_no,int *minor_no,int mode)
-{
-	FILE *file;
-	int d,mi,ma,rc;
-	char line[PROC_LINE_LENGTH];
-
-	file=fopen(PROC_DASD_DEVICES,"r");
-	if (file==NULL)
-		ERRMSG_EXIT(EXIT_FAILURE,"%s: failed to open " \
-			PROC_DASD_DEVICES ": %s (do you have the /proc " \
-			"filesystem enabled?)\n",prog_name,strerror(errno));
-
-	fgets(line,sizeof(line),file); /* omit first line */
-	while (fgets(line,sizeof(line),file)!=NULL) {
-		rc=sscanf(line,"%X%d%d",&d,&ma,&mi);
-		if ( (rc==3) &&
-			!((d!=*devno)&&(mode&GIVEN_DEVNO)) &&
-			!((ma!=*major_no)&&(mode&GIVEN_MAJOR)) &&
-			!((mi!=*minor_no)&&(mode&GIVEN_MINOR)) ) {
-			*devno=d;
-			*major_no=ma;
-			*minor_no=mi;
-			/* yes, this is a quick exit, but the easiest way */
-			fclose(file);
-			return;
-			break;
-		}
-	}
-	fclose(file);
-
-	ERRMSG_EXIT(EXIT_FAILURE,"%s: failed to find device in the /proc " \
-		"filesystem (are you sure to have the right param line?)\n",
-		prog_name);
-}
-
-char *
-get_devname_from_devno(int devno,int verbosity)
-{
-	int major_no,minor_no;
-	int file_major,file_minor;
-	struct stat stat_buf;
-	int rc;
-	int found;
-	char *devname;
-	char tmpname[MAX_FILELEN];
-
-	DIR *dp;
-	struct dirent *direntp;
-
-	/**** get minor number ****/
-	get_xno_from_xno(&devno,&major_no,&minor_no,GIVEN_DEVNO);
-
-	/**** get device file ****/
-	if ((dp=opendir(SLASHDEV)) == NULL)
-		ERRMSG_EXIT(EXIT_FAILURE,"%s: unable to read " SLASHDEV \
-			"\n",prog_name);
-	found=0;
-	while ((direntp=readdir(dp)) != NULL) {
-		strcpy(tmpname,SLASHDEV);
-		strcat(tmpname,direntp->d_name);
-		rc=stat(tmpname,&stat_buf);
-		if (!rc) {
-			file_major=(stat_buf.st_rdev>>8)&0xff;
-			file_minor=stat_buf.st_rdev&0xff;
-			if ((file_major==major_no) && (file_minor==minor_no)) {
-				found=1;
-				break;
-			}
-		}
-	}
-	if (found) {
-		devname=malloc(strlen(direntp->d_name));
-		strcpy(devname,tmpname);
-	}
-	rc=closedir(dp);
-	if (rc<0) ERRMSG("%s: unable to close directory " SLASHDEV \
-		"; continuing\n",prog_name);
-	if (found)
-		return devname;
-
-	if (verbosity>=1)
-		printf("I didn't find device node in " SLASHDEV \
-			"; trying to create a temporary node\n");
-
-	/**** get temp file and create device node *****/
-	rc=mkstemp(tempfilename);
-	if (rc==-1)
-		ERRMSG_EXIT(EXIT_FAILURE,"%s: failed to get temporary " \
-			"filename: %s\n",prog_name,strerror(errno));
-	close(rc);
-	rc=unlink(tempfilename);
-	
-	rc=mknod(tempfilename,S_IFBLK|0600,(major_no<<8)+minor_no);
-	if (rc)
-		ERRMSG_EXIT(EXIT_FAILURE,"%s: failed to create temporary " \
-			"device node %s: %s\n",prog_name,tempfilename,
-			strerror(errno));
-	return tempfilename;
-}
-
-char *
-check_param(int mode,format_data_t data)
-{
-	char *s;
-
-	if (NULL==(s=malloc(ERR_LENGTH)))
-		ERRMSG_EXIT(EXIT_FAILURE,"%s: not enough memory.\n",prog_name);
-
-	if ((mode&CHECK_START)&&(data.start_unit<0)) {
-		strcpy(s,"start track must be greater than zero");
-		goto exit;
-	}
-	if ((mode&CHECK_END)&&(data.stop_unit<-1)) {
-		strcpy(s,"end track must be -1 or greater than zero");
-		goto exit;
-	}
-	if ((mode&CHECK_END)&&(data.start_unit>data.stop_unit)&&
-		(data.stop_unit!=-1)) {
-		strcpy(s,"end track must be higher than start track");
-		goto exit;
-	}
-
-	if ((mode&CHECK_BLKSIZE)&&(data.blksize<1)) {
-		strcpy(s,"blocksize must be a positive integer");
-		goto exit;
-	}
-	if (mode&CHECK_BLKSIZE) while (data.blksize>0) {
-		if ((data.blksize%2)&&(data.blksize!=1)) {
-			strcpy(s,"blocksize must be a power of 2");
-			goto exit;
-		}
-		data.blksize/=2;
-	}
-
-	free(s);
-	return NULL;
-exit:
-	return s;
-}
-
-#define ASK_PRINTOUT printf("Please enter %s",output)
-#define ASK_GETBUFFER fgets(buffer,sizeof(buffer),stdin)
-#define ASK_SCANFORNUMBER(var) rc=sscanf(buffer,"%d%c",&var,&c)
-#define ASK_COMPLAIN_FORMAT if ((rc==2)&&(c=='\n')) rc=1; \
-	if (rc==-1) rc=1; /* this happens, if enter is pressed */ \
-	if (rc!=1) printf(" -- wrong input, try again.\n")
-#define ASK_CHECK_PARAM(mode) str=check_param(mode,params); \
-		if (str!=NULL) { printf(" -- %s\n",str); rc=0; free(str); }
-
-format_data_t
-ask_user_for_data(format_data_t params)
-{
-	char buffer[20]; /* should be enough for inputing track numbers */
-	char c;
-	int i,rc;
-	char *str;
-	char output[60],o2[12];
-
-	i=params.start_unit;
-	do {
-		params.start_unit=i;
-		sprintf(output,"the start track of the range to format " \
-			"[%d]: ",i);
-		ASK_PRINTOUT;
-		ASK_GETBUFFER;
-		ASK_SCANFORNUMBER(params.start_unit);
-		ASK_COMPLAIN_FORMAT;
-		ASK_CHECK_PARAM(CHECK_START);
-	} while (rc!=1);
-
-	i=params.stop_unit;
-	do {
-		params.stop_unit=i;
-		sprintf(output,"the end track of the range to format [");
-		if (i==-1) sprintf(o2,"END]: "); else
-			sprintf(o2,"%d]: ",i);
-		strcat(output,o2);
-		ASK_PRINTOUT;
-		ASK_GETBUFFER;
-		if ( (!strcasecmp(buffer,"end")) ||
-			(!strcasecmp(buffer,"end\n")) ) {
-			rc=1;
-			params.stop_unit=-1;
-		} else {
-			ASK_SCANFORNUMBER(params.stop_unit);
-			ASK_COMPLAIN_FORMAT;
-			ASK_CHECK_PARAM(CHECK_END);
-		}
-	} while (rc!=1);
-
-	i=params.blksize;
-	do {
-		params.blksize=i;
-		sprintf(output,"the blocksize of the formatting [%d]: ",i);
-		ASK_PRINTOUT;
-		ASK_GETBUFFER;
-		ASK_SCANFORNUMBER(params.blksize);
-		ASK_COMPLAIN_FORMAT;
-		ASK_CHECK_PARAM(CHECK_BLKSIZE);
-	} while (rc!=1);
-
-	return params;
-}
-
-void
-do_format_dasd(char *dev_name,format_data_t format_params,int testmode,
-	int verbosity,int withoutprompt)
-{
-	int fd,rc;
-	struct stat stat_buf;
-	int minor_no,major_no,devno;
-	char inp_buffer[5]; /* to contain yes */
-
-	fd=open(dev_name,O_RDWR);
-	if (fd==-1)
-		ERRMSG_EXIT(EXIT_FAILURE,"%s: error opening device %s: " \
-			"%s\n",prog_name,dev_name,strerror(errno));
-
-	if (verbosity>=1) {
-	}
-
-	rc=stat(dev_name,&stat_buf);
-	if (rc) {
-		ERRMSG_EXIT(EXIT_FAILURE,"%s: error occured during stat: " \
-			"%s\n",prog_name,strerror(errno));
-	} else {
-		if (!S_ISBLK(stat_buf.st_mode))
-			ERRMSG_EXIT(EXIT_FAILURE,"%s: file is not a " \
-				"blockdevice.\n",prog_name);
-		major_no=(stat_buf.st_rdev>>8)&0xff;
-		minor_no=stat_buf.st_rdev&0xff;
-	}
-	
-	if ( ((withoutprompt)&&(verbosity>=1)) ||
-		(!withoutprompt) ) {
-		get_xno_from_xno(&devno,&major_no,&minor_no,
-			GIVEN_MAJOR|GIVEN_MINOR);
-		printf("\nI am going to format the device %s in the " \
-			"following way:\n",dev_name);
-		printf("   Device number of device : 0x%x\n",devno);
-		printf("   Major number of device  : %u\n",major_no);
-		printf("   Minor number of device  : %u\n",minor_no);
-		printf("   Start track             : %d\n" \
-			,format_params.start_unit);
-		printf("   End track               : ");
-		if (format_params.stop_unit==-1)
-			printf("last track of disk\n");
-		else
-			printf("%d\n",format_params.stop_unit);
-		printf("   Blocksize               : %d\n" \
-			,format_params.blksize);
-		if (testmode) printf("Test mode active, omitting ioctl.\n");
-	}
-
-	while (!testmode) {
-		if (!withoutprompt) {
-			printf("\n--->> ATTENTION! <<---\n");
-			printf("All data in the specified range of that " \
-				"device will be lost.\nType yes to continue" \
-				", no will leave the disk untouched: ");
-			fgets(inp_buffer,sizeof(inp_buffer),stdin);
-			if (strcasecmp(inp_buffer,"yes") &&
-				strcasecmp(inp_buffer,"yes\n")) {
-				printf("Omitting ioctl call (disk will " \
-					"NOT be formatted).\n");
-				break;
-			}
-		}
-
-		if ( !(  (withoutprompt)&&(verbosity<1) ))
-			printf("Formatting the device. This may take a " \
-				"while (get yourself a coffee).\n");
-		rc=ioctl(fd,IOCTL_COMMAND,format_params);
-		if (rc)
-			ERRMSG_EXIT(EXIT_FAILURE,"%s: the dasd driver " \
-				"returned with the following error " \
-				"message:\n%s\n",prog_name,strerror(errno));
-		printf("Finished formatting the device.\n");
-
-		break;
-	}
-
-	rc=close(fd);
-	if (rc)
-		ERRMSG("%s: error during close: " \
-			"%s; continuing.\n",prog_name,strerror(errno));
-}
-
-
-
-int main(int argc,char *argv[]) {
-	int verbosity;
-	int testmode;
-	int withoutprompt;
-
-	char *dev_name;
-	int devno;
-	char *dev_filename,*devno_param_str,*range_param_str;
-	char *start_param_str,*end_param_str,*blksize_param_str;
-	
-	format_data_t format_params;
-
-	int rc;
-	int oc;
-	char *endptr;
-
-	char c1,c2,cbuffer[6]; /* should be able to contain -end plus 1 char */
-	int i1,i2;
-	char *str;
-
-	int start_specified,end_specified,blksize_specified;
-	int devfile_specified,devno_specified,range_specified;
-
-	/******************* initialization ********************/
-
-	endptr=NULL;
-
-	/* set default values */
-	format_params.start_unit=0;
-	format_params.stop_unit=-1;
-	format_params.blksize=1024;
-	testmode=0;
-	verbosity=0;
-	withoutprompt=0;
-	start_specified=end_specified=blksize_specified=0;
-	devfile_specified=devno_specified=range_specified=0;
-
-	/*************** parse parameters **********************/
-
-	/* avoid error message generated by getopt */
-	opterr=0;
-
-	while ( (oc=getopt(argc,argv,"r:s:e:b:n:f:hty?vV")) !=EOF) {
-		switch (oc) {
-		case 'y':
-			withoutprompt=1;
-			break;
-
-		case 't':
-			testmode=1;
-			break;
-
-		case 'v':
-			verbosity++;
-			break;
-
-		case '?': /* fall-through */
-		case ':':
-			exit_usage(EXIT_MISUSE);
-
-		case 'h':
-			exit_usage(0);
-
-		case 'V':
-			printf("%s version 0.99\n",prog_name);
-			exit(0);
-
-		case 's' :
-			start_param_str=optarg;
-			start_specified++;
-			break;
-			
-		case 'e' :
-			end_param_str=optarg;
-			end_specified++;
-			break;
-
-		case 'b' :
-			blksize_param_str=optarg;
-			blksize_specified++;
-			break;
-			
-		case 'n' :
-			devno_param_str=optarg;
-			devno_specified++;
-			break;
-		
-		case 'f' :
-			dev_filename=optarg;
-			devfile_specified++;
-			break;
-		case 'r' :
-			range_param_str=optarg;
-			range_specified++;
-			break;
-		}
-	}
-
-	/* set default values */
-
-	/******************** checking of parameters **************/
-
-	/* convert range into -s and -e */
-	CHECK_SPEC_MAX_ONCE(range_specified,"formatting range");
-
-	while (range_specified) {
-		start_specified++;
-		end_specified++;
-
-		/* scan for 1 or 2 integers, separated by a dash */
-		rc=sscanf(range_param_str,"%d%c%d%c",&i1,&c1,&i2,&c2);
-		if ((rc==3)&&(c1=='-')) {
-			format_params.start_unit=i1;
-			format_params.stop_unit=i2;
-			break;
-		}
-		if (rc==1) {
-			format_params.start_unit=i1;
-			break;
-		}
-
-		/* scan for integer and -END */
-		rc=sscanf(range_param_str,"%d%s",&i1,cbuffer);
-		if ((rc==2)&&(!strcasecmp(cbuffer,"-END"))) {
-			format_params.start_unit=i1;
-			format_params.stop_unit=-1;
-			break;
-		}
-		ERRMSG_EXIT(EXIT_MISUSE,"%s: specified range " \
-			"is in invalid format\n",prog_name);
-	}
-
-	if ((!devfile_specified)&&(!devno_specified))
-		ERRMSG_EXIT(EXIT_MISUSE,"%s: device to format " \
-			"not specified\n",prog_name);
-
-	if ((devfile_specified+devno_specified)>1)
-		ERRMSG_EXIT(EXIT_MISUSE,"%s: device to format " \
-			"can only be specified once\n",prog_name);
-
-	if ((!start_specified)&&(!end_specified)&&(!range_specified)&&
-		(!blksize_specified)) {
-		format_params=ask_user_for_data(format_params);
-	}
-
-	CHECK_SPEC_MAX_ONCE(start_specified,"start track");
-	CHECK_SPEC_MAX_ONCE(end_specified,"end track");
-	CHECK_SPEC_MAX_ONCE(blksize_specified,"blocksize");
-
-	if (devno_specified)
-		PARSE_PARAM_INTO(devno,devno_param_str,16,"device number");
-	if (start_specified&&!range_specified)
-		PARSE_PARAM_INTO(format_params.start_unit,start_param_str,10,
-			"start track");
-	if (end_specified&&!range_specified)
-		PARSE_PARAM_INTO(format_params.stop_unit,end_param_str,10,
-			"end track");
-	if (blksize_specified)
-		PARSE_PARAM_INTO(format_params.blksize,blksize_param_str,10,
-			"blocksize");
-
-	/***********get dev_name *********************/
-	dev_name=(devno_specified)?
-		get_devname_from_devno(devno,verbosity):
-		dev_filename;
-
-	/*** range checking *********/
-	str=check_param(CHECK_ALL,format_params);
-	if (str!=NULL) ERRMSG_EXIT(EXIT_MISUSE,"%s: %s\n",prog_name,str);
-
-	/*************** issue the real command *****************/
-	do_format_dasd(dev_name,format_params,testmode,verbosity,
-		withoutprompt);
-
-	/*************** cleanup ********************************/
-	if (strncmp(dev_name,TEMPFILENAME,TEMPFILENAMECHARS)==0) {
-		rc=unlink(dev_name);
-		if ((rc)&&(verbosity>=1))
-			ERRMSG("%s: temporary device node %s could not be " \
-				"removed: %s\n",prog_name,dev_name,
-				strerror(errno));
-	} else {
-		if (devno_specified) {
-			/* so we have allocated space for the filename */
-			free(dev_name);
-		}
-	}
-
-	return 0;
-}
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/boot/ipleckd.S linux.15p9/arch/s390/boot/ipleckd.S
--- linux.vanilla/arch/s390/boot/ipleckd.S	Tue Jan  4 21:18:40 2000
+++ linux.15p9/arch/s390/boot/ipleckd.S	Thu Feb 17 13:30:27 2000
@@ -3,7 +3,7 @@
 #    IPL record for 3380/3390 DASD
 #
 #  S390 version
-#    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+#    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
 #    Author(s): Holger Smolinski <Holger.Smolinski@de.ibm.com>
 #
 #
@@ -17,6 +17,11 @@
 # r13:	base register 	index to 0x0000
 # r14:	callers address
 # r15:	temporary save register (we have no stack!)
+
+# storage layout:
+
+#include <asm/lowcore.h>
+	
 	.org 0
 .psw:	.long 0x00080000,0x80000000+_start
 .ccw1:	.long 0x06000000,0x00001000     # Re-Read enough of bootsector to start
@@ -25,23 +30,22 @@
 	.org 0x58
 .Lextn:	.long	0x000a0000,0x00000000+.Lextn
 .Lsvcn:	.long	0x000a0000,0x00000000+.Lsvcn
-.Lprgn:	.long	0x000a0000,0x00000000+.Lprgn
+.Lprgn:	.long	0x00080000,0x00000000+.Lecs
 .Lmcn:	.long	0x000a0000,0x00000000+.Lmcn
 .Lion:	.long   0x00080000,0x80000000+.Lionewaddr
 
-	.org 0xd0	
-.Lnull:	
-	.long 0x00000000,0x00000000
 	.org 0xe0
 .Llstad:.long 	0x00000000,0x00000000	# sectorno + ct of bootlist
 
 	.org 0xf0			# Lets start now...
 _start: .globl _start
-	l  	%r1,0xb8		# get IPL-subchannel from lowcore
+	l  	%r1,__LC_SUBCHANNEL_ID	# get IPL-subchannel from lowcore
+	st	%r1,__LC_IPLDEV         # keep it for reipl
 	stsch	.Lrdcdata
-	oi      .Lrdcdata+5,0x80        # enable ssch
-	oi	.Lrdcdata+27,0x01	# enalbe concurrent sense
+	oi      .Lrdcdata+5,0x84        # enable ssch and multipath mode
+.Lecs:  xi	.Lrdcdata+27,0x01	# enable concurrent sense
 	msch	.Lrdcdata
+        xi      .Lprgn,6                # restore Wait and d/a bit in PCnew PSW
 	l	%r2,.Lparm
 	mvc     0x0(8,%r2),.Lnull      # set parmarea to null
 	lctl	%c6,%c6,.Lc6     	# enable all interrupts
@@ -89,14 +93,12 @@
 	j	.Lkcont
 .Lzeroes:
 	lr	%r2,%r3
-	slr	%r3,%r3
+.L001:	slr	%r3,%r3
 	icm	%r3,3,.Lcountarea+6      # get blocksize
-.L008:	slr	%r5,%r5			# no bytes to move
-	mvcle	%r2,%r4,0(%r10)		# fill zeroes to storage
+	slr	%r5,%r5			# no bytes to move
+.L008:	mvcle	%r2,%r4,0   		# fill zeroes to storage
 	jo	.L008			# until block is filled
-	bctr	%r4,0			# skip to next block
-	a  	%r2,.Lcountarea+6       # proceed loadaddress
-	jnz	.Lzeroes		# proceed for additional blocks
+	brct	%r4,.L001   		# skip to next block
 .Lkcont:	
 	ahi	%r10,8
 	j	.Lkloop
@@ -143,6 +145,11 @@
 	lhi	%r6,12			# setup r6 correct!
 	j	.L011
 .L010:	
+        clc     .Lrdcdata+3(2),.L9343
+        jne     .L013
+        lhi     %r6,9
+        j       .L011
+.L013:
 	lhi	%r6,10	
 .L011:	
 	# loop for nbl times
@@ -222,8 +229,6 @@
 
 # FIXME pre-initialized data should be listed first
 # NULLed storage can be taken from anywhere ;) 
-.L3390:	
-	.word	0x3390
 .Lblklst:	
 	.long   0x00002000     
 	.align 8
@@ -233,12 +238,17 @@
 	.long 0x020a0000,0x00000000+.Ltpi
 .Lorb:	
 	.long 0x0049504c,0x0080ff00	# intparm is " IPL"
-	.long 0x00000000		# CCW address
 .Lc6:	.long 0xff000000
 .Lstart:
 	.long	0x00010000              # do not separate .Lstart and .Lparm
 .Lparm:	
 	.long	0x00008000              # they are loaded with a LM
+.L3390:
+	.word 	0x3390
+.L9343:
+	.word	0x9343
+.Lnull:	
+	.long 0x00000000,0x00000000
 .Lrdcdata:
 	.long 0x00000000,0x00000000
 	.long 0x00000000,0x00000000
@@ -270,7 +280,7 @@
 	.long 0x06000001,0x00000000
 	.long 0x00000000,0x01000000
 	.long 0x12345678
-	.org 0x3c8
+	.org 0x7c8
 .Lrdcccw:				# CCW read device characteristics
 	.long 0x64400040,0x00000000+.Lrdcdata
 	.long 0x63400010,0x00000000+.Ldedata
@@ -282,7 +292,7 @@
 	.long 0x47400010,0x00000000+.Llodata
 .Lrdccw:	
 	.long 0x86400000,0x00000000
-	.org 0x400
+	.org 0x800
 # end of pre initialized data is here CCWarea follows
 # from here we load 1k blocklist 
 # end of function
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/boot/silo.c linux.15p9/arch/s390/boot/silo.c
--- linux.vanilla/arch/s390/boot/silo.c	Tue Jan  4 21:18:40 2000
+++ linux.15p9/arch/s390/boot/silo.c	Thu Jan  1 01:00:00 1970
@@ -1,408 +0,0 @@
-/*
- *  arch/s390/boot/silo.c
- *
- *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
- *    Author(s): Holger Smolinski <linux390@de.ibm.com>
- */
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <limits.h>
-#include <dirent.h>
-#include <linux/fs.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <asm/ioctl.h>
-
-/* from dasd.h */
-#define DASD_PARTN_BITS 2
-#define BIODASDRWTB _IOWR('D',5,int)
-/* end */
-
-#define PRINT_LEVEL(x,y...) if ( silo_options.verbosity >= x ) printf(y)
-#define ERROR_LEVEL(x,y...) if ( silo_options.verbosity >= x ) fprintf(stderr,y)
-#define TOGGLE(x) ((x)=((x)?(0):(1)))
-#define GETARG(x) {int len=strlen(optarg);x=malloc(len);strncpy(x,optarg,len);PRINT_LEVEL(1,"%s set to %s\n",#x,optarg);}
-
-#define ITRY(x) if ( (x) == -1 ) { ERROR_LEVEL(0,"%s (line:%d) '%s' returned %d='%s'\n", __FILE__,__LINE__,#x,errno,strerror(errno)); usage(); exit(1); }
-#define NTRY(x) if ( (x) == 0 ) { ERROR_LEVEL(0,"%s (line:%d) '%s' returned %d='%s'\n", __FILE__,__LINE__,#x,errno,strerror(errno)); usage(); exit(1); }
-
-#define MAX_CLUSTERS 256
-#define PARTN_MASK ((1 << DASD_PARTN_BITS) - 1)
-
-struct silo_options
-  {
-    short int verbosity;
-    struct
-      {
-	unsigned char testonly;
-      }
-    flags;
-    char *image;
-    char *ipldevice;
-    char *parmfile;
-    char *ramdisk;
-    char *bootsect;
-  }
-silo_options =
-{
-  1,				/* verbosity */
-  {
-    0,				/* testonly */
-  }
-  ,
-    "./image",			/* image */
-    NULL,			/* ipldevice */
-    NULL,			/* parmfile */
-    NULL,			/* initrd */
-    "ipleckd.boot",		/* bootsector */
-};
-
-struct blockdesc
-  {
-    unsigned long off;
-    unsigned short ct;
-    unsigned long addr;
-  };
-
-struct blocklist
-  {
-    struct blockdesc blk[MAX_CLUSTERS];
-    unsigned short ix;
-  };
-
-void
-usage (void)
-{
-  printf ("Usage:\n");
-  printf ("silo -d ipldevice [additional options]\n");
-  printf ("-d /dev/node : set ipldevice to /dev/node\n");
-  printf ("-f image : set image to image\n");
-  printf ("-p parmfile : set parameter file to parmfile\n");
-  printf ("-b bootsect : set bootsector to bootsect\n");
-  printf ("Additional options\n");
-  printf ("-v: increase verbosity level\n");
-  printf ("-v#: set verbosity level to #\n");
-  printf ("-t: toggle testonly flag\n");
-  printf ("-h: print this message\n");
-  printf ("-?: print this message\n");
-}
-
-int
-parse_options (struct silo_options *o, int argc, char *argv[])
-{
-  int rc = 0;
-  int oc;
-  if (argc == 1)
-    {
-      usage ();
-      exit (0);
-    }
-  while ((oc = getopt (argc, argv, "f:d:p:r:b:B:h?v::t")) != -1)
-    {
-      switch (oc)
-	{
-	case 't':
-	  TOGGLE (o->flags.testonly);
-	  PRINT_LEVEL (1, "Testonly flag is now %sactive\n", o->flags.testonly ? "" : "in");
-	  break;
-	case 'v':
-	  {
-	    unsigned short v;
-	    if (optarg && sscanf (optarg, "%hu", &v))
-	      o->verbosity = v;
-	    else
-	      o->verbosity++;
-	    PRINT_LEVEL (1, "Verbosity value is now %hu\n", o->verbosity);
-	    break;
-	  }
-	case 'h':
-	case '?':
-	  usage ();
-	  break;
-	case 'd':
-	  GETARG (o->ipldevice);
-	  break;
-	case 'f':
-	  GETARG (o->image);
-	  break;
-	case 'p':
-	  GETARG (o->parmfile);
-	  break;
-	case 'r':
-	  GETARG (o->ramdisk);
-	  break;
-	case 'b':
-	  GETARG (o->bootsect);
-	  break;
-	default:
-	  rc = EINVAL;
-	  break;
-	}
-    }
-  return rc;
-}
-
-int
-verify_device (char *name)
-{
-  int rc = 0;
-  struct stat dst;
-  struct stat st;
-  ITRY (stat (name, &dst));
-  if (S_ISBLK (dst.st_mode))
-    {
-      if (!(MINOR (dst.st_rdev) & PARTN_MASK))
-	{
-	  rc = dst.st_rdev;
-	}
-      else
-	/* invalid MINOR & PARTN_MASK */
-	{
-	  ERROR_LEVEL (1, "Cannot boot from partition %d %d %d",
-		       (int) PARTN_MASK, (int) MINOR (dst.st_rdev), (int) (PARTN_MASK & MINOR (dst.st_rdev)));
-	  rc = -1;
-	  errno = EINVAL;
-	}
-    }
-  else
-    /* error S_ISBLK */
-    {
-      ERROR_LEVEL (1, "%s is no block device\n", name);
-      rc = -1;
-      errno = EINVAL;
-    }
-  return rc;
-}
-
-int
-verify_file (char *name, int dev)
-{
-  int rc = 0;
-  struct stat dst;
-  struct stat st;
-  int bs = 1024;
-  int l;
-  ITRY (stat (name, &dst));
-  if (S_ISREG (dst.st_mode))
-    {
-      if ((unsigned) MAJOR (dev) == (unsigned) MAJOR (dst.st_dev) && (unsigned) MINOR (dev) == (unsigned) (MINOR (dst.st_dev) & ~PARTN_MASK))
-	{
-	  /* whatever to do if all is ok... */
-	}
-      else
-	/* devicenumber doesn't match */
-	{
-	  ERROR_LEVEL (1, "%s is not on device (%d/%d) but on (%d/%d)\n", name, (unsigned) MAJOR (dev), (unsigned) MINOR (dev), (unsigned) MAJOR (dst.st_dev), (unsigned) (MINOR (dst.st_dev) & ~PARTN_MASK));
-	  rc = -1;
-	  errno = EINVAL;
-	}
-    }
-  else
-    /* error S_ISREG */
-    {
-      ERROR_LEVEL (1, "%s is neither regular file nor linkto one\n", name);
-      rc = -1;
-      errno = EINVAL;
-    }
-  return rc;
-}
-
-int
-verify_options (struct silo_options *o)
-{
-  int rc = 0;
-  int dev = 0;
-  int crc = 0;
-  if (!o->ipldevice || !o->image || !o->bootsect)
-    {
-      usage ();
-      exit (1);
-    }
-  PRINT_LEVEL (1, "IPL device is: '%s'", o->ipldevice);
-
-  ITRY (dev = verify_device (o->ipldevice));
-  PRINT_LEVEL (2, "...ok...(%d/%d)", (unsigned short) MAJOR (dev), (unsigned short) MINOR (dev));
-  PRINT_LEVEL (1, "\n");
-
-  PRINT_LEVEL (0, "bootsector is: '%s'", o->bootsect);
-  ITRY (verify_file (o->bootsect, dev));
-  PRINT_LEVEL (1, "...ok...");
-  PRINT_LEVEL (0, "\n");
-
-  PRINT_LEVEL (0, "Kernel image is: '%s'", o->image);
-  ITRY (verify_file (o->image, dev));
-  PRINT_LEVEL (1, "...ok...");
-  PRINT_LEVEL (0, "\n");
-
-  if (o->parmfile)
-    {
-      PRINT_LEVEL (0, "parameterfile is: '%s'", o->parmfile);
-      ITRY (verify_file (o->parmfile, dev));
-      PRINT_LEVEL (1, "...ok...");
-      PRINT_LEVEL (0, "\n");
-    }
-
-  if (o->ramdisk)
-    {
-      PRINT_LEVEL (0, "initialramdisk is: '%s'", o->ramdisk);
-      ITRY (verify_file (o->ramdisk, dev));
-      PRINT_LEVEL (1, "...ok...");
-      PRINT_LEVEL (0, "\n");
-    }
-
-  return crc;
-}
-
-
-int
-add_file_to_blocklist (char *name, struct blocklist *lst, long addr)
-{
-  int fd;
-  int devfd;
-  struct stat fst;
-  int i;
-  int blk;
-  int bs;
-  int blocks;
-
-  int rc = 0;
-
-  ITRY (fd = open (name, O_RDONLY));
-  ITRY (fstat (fd, &fst));
-  ITRY (mknod ("/tmp/silodev", S_IFBLK | S_IRUSR | S_IWUSR, fst.st_dev));
-  ITRY (devfd = open ("/tmp/silodev", O_RDONLY));
-  ITRY (ioctl (fd, FIGETBSZ, &bs));
-  blocks = (fst.st_size + bs - 1) / bs;
-  for (i = 0; i < blocks; i++)
-    {
-      blk = i;
-      ITRY (ioctl (fd, FIBMAP, &blk));
-      if (blk)
-	{
-	  int oldblk = blk;
-	  ITRY (ioctl (devfd, BIODASDRWTB, &blk));
-	  if (blk <= 0)
-	    {
-	      ERROR_LEVEL (0, "BIODASDRWTB on blk %d returned %d\n", oldblk, blk);
-	      break;
-	    }
-	}
-      else
-	{
-	  PRINT_LEVEL (1, "Filled hole on blk %d\n", i);
-	}
-      if (lst->ix == 0 || i == 0  || 
-	  lst->blk[lst->ix - 1].ct >= 128 ||
-	  (lst->blk[lst->ix - 1].off + lst->blk[lst->ix - 1].ct != blk &&
-	   !(lst->blk[lst->ix - 1].off == 0 && blk == 0)))
-	{
-	  if (lst->ix >= MAX_CLUSTERS)
-	    {
-	      rc = 1;
-	      errno = ENOMEM;
-	      break;
-	    }
-	  lst->blk[lst->ix].off = blk;
-	  lst->blk[lst->ix].ct = 1;
-	  lst->blk[lst->ix].addr = addr + i * bs;
-	  lst->ix++;
-	}
-      else
-	{
-	  lst->blk[lst->ix - 1].ct++;
-	}
-    }
-  ITRY(unlink("/tmp/silodev"));
-  return rc;
-}
-
-int
-write_bootsect (char *ipldevice, char *bootsect, struct blocklist *blklst)
-{
-  int i;
-  int s_fd, d_fd, b_fd, bd_fd;
-  struct stat s_st, d_st, b_st;
-  int rc=0;
-  int bs, boots;
-  char buffer[4096];
-  ITRY (d_fd = open (ipldevice, O_RDWR | O_SYNC));
-  ITRY (fstat (d_fd, &d_st));
-  ITRY (s_fd = open ("boot.map", O_RDWR | O_TRUNC | O_CREAT | O_SYNC));
-  ITRY (verify_file (bootsect, d_st.st_rdev));
-  for (i = 0; i < blklst->ix; i++)
-    {
-      int offset = blklst->blk[i].off;
-      int addrct = blklst->blk[i].addr | (blklst->blk[i].ct & 0xff);
-      PRINT_LEVEL (1, "ix %i: offset: %06x count: %02x address: 0x%08x\n", i, offset, blklst->blk[i].ct & 0xff, blklst->blk[i].addr);
-      NTRY (write (s_fd, &offset, sizeof (int)));
-      NTRY (write (s_fd, &addrct, sizeof (int)));
-    }
-  ITRY (ioctl (s_fd,FIGETBSZ, &bs));
-  ITRY (stat ("boot.map", &s_st));
-  if (s_st.st_size > bs )
-    {
-      ERROR_LEVEL (0,"boot.map is larger than one block\n");
-      rc = -1;
-      errno = EINVAL;
-    }
-  boots=0;
-  ITRY (mknod ("/tmp/silodev", S_IFBLK | S_IRUSR | S_IWUSR, s_st.st_dev));
-  ITRY (bd_fd = open ("/tmp/silodev", O_RDONLY));
-  ITRY ( ioctl(s_fd,FIBMAP,&boots));
-  ITRY (ioctl (bd_fd, BIODASDRWTB, &boots));
-  PRINT_LEVEL (1, "Bootmap is in block no: 0x%08x\n", boots);
-  close (bd_fd);
-  close(s_fd);
-  ITRY (unlink("/tmp/silodev"));
-  /* Now patch the bootsector */
-  ITRY (b_fd = open (bootsect, O_RDONLY));
-  NTRY (read (b_fd, buffer, 4096));
-  memset (buffer + 0xe0, 0, 8);
-  *(int *) (buffer + 0xe0) = boots;
-  NTRY (write (d_fd, buffer, 4096));
-  NTRY (write (d_fd, buffer, 4096));
-  close (b_fd);
-  close (d_fd);
-  return rc;
-}
-
-int
-do_silo (struct silo_options *o)
-{
-  int rc = 0;
-
-  int device_fd;
-  int image_fd;
-  struct blocklist blklist;
-  memset (&blklist, 0, sizeof (struct blocklist));
-  ITRY (add_file_to_blocklist (o->image, &blklist, 0x00000000));
-  if (o->parmfile)
-    {
-      ITRY (add_file_to_blocklist (o->parmfile, &blklist, 0x00008000));
-    }
-  if (o->ramdisk)
-    {
-      ITRY (add_file_to_blocklist (o->ramdisk, &blklist, 0x00800000));
-    }
-  ITRY (write_bootsect (o->ipldevice, o->bootsect, &blklist));
-
-  return rc;
-}
-
-int
-main (int argct, char *argv[])
-{
-  int rc = 0;
-  ITRY (parse_options (&silo_options, argct, argv));
-  ITRY (verify_options (&silo_options));
-  ITRY (do_silo (&silo_options));
-  return rc;
-}
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/defconfig linux.15p9/arch/s390/defconfig
--- linux.vanilla/arch/s390/defconfig	Tue Jan  4 21:18:41 2000
+++ linux.15p9/arch/s390/defconfig	Thu Feb 17 13:30:27 2000
@@ -52,10 +52,10 @@
 #
 CONFIG_NETDEVICES=y
 CONFIG_CTC=y
-# CONFIG_IUCV is not set
+CONFIG_IUCV=y
 # CONFIG_DUMMY is not set
 CONFIG_NET_ETHERNET=y
-# CONFIG_TR is not set
+CONFIG_TR=y
 
 #
 # S/390 Terminal and Console options
@@ -127,13 +127,15 @@
 CONFIG_EXT2_FS=y
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_EFS_FS is not set
 
 #
 # Network File Systems
 #
 # CONFIG_CODA_FS is not set
 CONFIG_NFS_FS=y
-# CONFIG_NFSD is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_SUN is not set
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 # CONFIG_SMB_FS is not set
@@ -154,4 +156,3 @@
 #
 # CONFIG_PROFILE is not set
 # CONFIG_REMOTE_DEBUG is not set
-# CONFIG_MAGIC_SYSRQ is not set
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/kernel/Makefile linux.15p9/arch/s390/kernel/Makefile
--- linux.vanilla/arch/s390/kernel/Makefile	Tue Jan  4 21:18:41 2000
+++ linux.15p9/arch/s390/kernel/Makefile	Thu Feb 17 13:30:27 2000
@@ -20,9 +20,9 @@
 O_TARGET := kernel.o
 O_OBJS   := lowcore.o entry.o bitmap.o traps.o time.o process.o irq.o \
             setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
-            s390fpu.o s390io.o 
+            s390fpu.o s390io.o reipl.o
 
-OX_OBJS  := s390ksyms.o
+OX_OBJS  := s390_ksyms.o
 MX_OBJS  :=
 
 ifdef CONFIG_SMP
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/kernel/entry.S linux.15p9/arch/s390/kernel/entry.S
--- linux.vanilla/arch/s390/kernel/entry.S	Tue Jan  4 21:18:41 2000
+++ linux.15p9/arch/s390/kernel/entry.S	Thu Feb 17 13:30:59 2000
@@ -3,7 +3,7 @@
  *    S390 low-level entry points.
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  *               Hartmut Penner (hp@de.ibm.com),
  *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
@@ -51,10 +51,14 @@
 /* fpu registers are saved & restored by the gdb stub itself */
 SP_FPC       =  (SP_CRREGS+(NUM_CRS*CR_SIZE))
 SP_FPRS      =  (SP_FPC+FPC_SIZE+FPC_PAD_SIZE)
-SP_SIZE      =  (SP_FPRS+(NUM_FPRS*FPR_SIZE))
+/* SP_PGM_OLD_ILC etc are not part of pt_regs & they are not 
+ defined in ptrace.h but space is needed for this too */
+SP_PGM_OLD_ILC= (SP_FPRS+(NUM_FPRS*FPR_SIZE))
 #else
-SP_SIZE      =  (SP_TRAP+4)
+SP_PGM_OLD_ILC= (SP_TRAP+4)
 #endif
+SP_SVC_STEP   = (SP_PGM_OLD_ILC+4) 
+SP_SIZE      =  (SP_SVC_STEP+4)
 /*
  * these defines are offsets into the thread_struct
  */
@@ -186,9 +190,6 @@
         lctl    %c9,%c11,_TSS_PER(%r3)  # Nope we didn't
 RES_DN1:
         stm     %r6,%r15,24(%r15)       # store resume registers of prev task
-	iac     %r1                     # get address space control bits
-        sacf    0
-	st      %r1,4(%r15)
         st      %r15,_TSS_KSP(%r2) # store kernel stack ptr to prev->tss.ksp
         lhi     %r0,-8192
         nr      %r0,%r15
@@ -204,8 +205,6 @@
         lctl    %c7,%c7,_TSS_USERSEG(%r3)   # load secondary-space for new task
         lctl    %c13,%c13,_TSS_USERSEG(%r3) # load home-space for new task
         lr      %r2,%r0                 # return task_struct of last task
-        l       %r1,4(%r15)
-        sacf    0(%r1)                  # set address space control bits
         lm      %r6,%r15,24(%r15)       # load resume registers of next task
         br      %r14
 
@@ -228,6 +227,7 @@
   sysc_fork:          .long  sys_fork
   sysc_vfork:         .long  sys_vfork
   sysc_sigreturn:     .long  sys_sigreturn
+  sysc_rt_sigreturn:  .long  sys_rt_sigreturn
   sysc_execve:        .long  sys_execve
   sysc_sigsuspend:    .long  sys_sigsuspend
   sysc_rt_sigsuspend: .long  sys_rt_sigsuspend
@@ -235,6 +235,8 @@
 	.globl  system_call
 system_call:
         SAVE_ALL(0x20)
+	XC      SP_SVC_STEP(4,%r15),SP_SVC_STEP(%r15)
+pgm_system_call:	
         basr    %r13,0
         ahi     %r13,sysc_lit-.   # setup base pointer R13 to sysc_lit
         slr     %r8,%r8           # gpr 8 is call save (-> tracesys)
@@ -253,7 +255,6 @@
 sysc_return:
         GET_CURRENT               # load pointer to task_struct to R9
         tm      SP_PSW+1(%r15),0x01 # returning to user ?
-#        tm      SP_PSW+2(%r15),0xc0 # returning to user or kernel thread ?
         jno     sysc_leave        # no-> skip bottom half, resched & signal
 #
 # check, if bottom-half has to be done
@@ -272,7 +273,8 @@
         icm     %r0,15,sigpending(%r9)   # get sigpending from task_struct
         jnz     sysc_signal_return
 sysc_leave:
-  
+	icm     %r0,15,SP_SVC_STEP(%r15)   # get sigpending from task_struct
+        jnz     pgm_svcret
 	stnsm   24(%r15),disable  # disable I/O and ext. interrupts
         RESTORE_ALL
 
@@ -363,17 +365,23 @@
 sys_execve_glue:        
         la      %r2,SP_PTREGS(%r15)    # load pt_regs
         l       %r1,sysc_execve-sysc_lit(%r13)
+	lr      %r12,%r14             # save return address
         basr    %r14,%r1              # call sys_execve
         ltr     %r2,%r2               # check if execve failed
-        jnz     sysc_return-4         # it did fail -> store result in gpr2
-        j       sysc_return           # SKIP ST 2,SP_R2(15) after BASR 14,8
-                                      # in system_call
+        bnz     0(%r12)               # it did fail -> store result in gpr2
+        b       4(%r12)               # SKIP ST 2,SP_R2(15) after BASR 14,8
+                                      # in system_call/sysc_tracesys
 
 sys_sigreturn_glue:     
         la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
         l       %r1,sysc_sigreturn-sysc_lit(%r13)
         br      %r1                   # branch to sys_sigreturn
 
+sys_rt_sigreturn_glue:     
+        la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
+        l       %r1,sysc_rt_sigreturn-sysc_lit(%r13)
+        br      %r1                   # branch to sys_sigreturn
+
 #
 # sigsuspend and rt_sigsuspend need pt_regs as an additional
 # parameter and they have to skip the store of %r2 into the
@@ -387,7 +395,7 @@
         lr      %r3,%r2               # move history0 parameter
         la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter
         l       %r1,sysc_sigsuspend-sysc_lit(%r13)
-	la      %r14,sysc_return-sysc_lit(%r13) # skip store of return value
+	la      %r14,4(%r14)          # skip store of return value
         br      %r1                   # branch to sys_sigsuspend
 
 sys_rt_sigsuspend_glue: 
@@ -395,7 +403,7 @@
         lr      %r3,%r2               # move unewset parameter
         la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter
         l       %r1,sysc_rt_sigsuspend-sysc_lit(%r13)
-	la      %r14,sysc_return-sysc_lit(%r13) # skip store of return value
+	la      %r14,4(%r14)          # skip store of return value
         br      %r1                   # branch to sys_rt_sigsuspend
 
 	.globl  sys_call_table	
@@ -422,7 +430,7 @@
         .long  sys_lseek
         .long  sys_getpid               /* 20 */
         .long  sys_mount
-        .long  sys_umount
+        .long  sys_oldumount
         .long  sys_setuid
         .long  sys_getuid
         .long  sys_stime                /* 25 */
@@ -452,7 +460,7 @@
         .long  sys_geteuid
         .long  sys_getegid              /* 50 */
         .long  sys_acct
-        .long  sys_ni_syscall           /* old phys syscall holder */
+        .long  sys_umount
         .long  sys_ni_syscall           /* old lock syscall holder */
         .long  sys_ioctl
         .long  sys_fcntl                /* 55 */
@@ -573,7 +581,7 @@
         .long  sys_setresgid             /* 170 */
         .long  sys_getresgid
         .long  sys_prctl
-        .long  sys_rt_sigreturn
+        .long  sys_rt_sigreturn_glue
         .long  sys_rt_sigaction
         .long  sys_rt_sigprocmask        /* 175 */
         .long  sys_rt_sigpending
@@ -591,70 +599,9 @@
         .long  sys_ni_syscall            /* streams1 */
         .long  sys_ni_syscall            /* streams2 */
         .long  sys_vfork_glue            /* 190 */
+	.rept  254-190
         .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall            /* 195 */
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall     /* 205 */
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall    /* 215 */
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall    /* 225 */
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall    /* 235 */
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall    /* 245 */
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
-        .long  sys_ni_syscall
+	.endr
         .long  sys_msgcp         /* 255 */
 
 /*
@@ -694,27 +641,19 @@
         lpsw    0x28
 # it was a single stepped SVC that is causing all the trouble
 pgm_svcper:
-        st      %r15,__LC_SAVE_AREA
-        l       %r15,__LC_PGM_NEW_PSW+4  # prepare return psw
-        ahi     %r15,pgm_svcret-pgm_check_handler
-        st      %r15,__LC_PGM_OLD_PSW+4  # use pgm old psw as temp storage
-        tm      __LC_SVC_OLD_PSW,0x01    # test problem state of svc old psw
-        jz      .+8
-        l       %r15,__LC_KERNEL_STACK   # load ksp
-        ahi     %r15,-16
-        srl     %r15,3                   # align stack pointer to 8
-        sll     %r15,3
-        mvc     0(4,%r15),__LC_SAVE_AREA # save user r15
-        mvc     4(4,%r15),__LC_PGM_ILC   # save program check information
-        mvc     8(8,%r15),__LC_SVC_OLD_PSW # save return point
-        mvc     __LC_SVC_OLD_PSW(8),__LC_PGM_OLD_PSW # move prepared return pt.
-        j       system_call              # now do the svc
+	SAVE_ALL(0x20)
+	mvi     SP_SVC_STEP(%r15),1 # make SP_SVC_STEP nonzero
+	mvc     SP_PGM_OLD_ILC(4,%r15),__LC_PGM_ILC # save program check information	
+        j       pgm_system_call              # now do the svc
 pgm_svcret:
-        mvc     __LC_PGM_OLD_PSW(8),8(%r15) # return point is svc return point
-        mvc     __LC_PGM_ILC(4),4(%r15)  # restore program check info
-        l       %r15,0(%r15)             # restore user r15
+        mvc     __LC_PGM_ILC(4),SP_PGM_OLD_ILC(%r15)  # restore program check info
+	lhi     %r0,0x28
+	st      %r0,SP_TRAP(%r15) # set new trap indicator
+	j       pgm_no_sv	 
 pgm_sv:
         SAVE_ALL(0x28)
+pgm_no_sv:
+	XC      SP_SVC_STEP(4,%r15),SP_SVC_STEP(%r15)
         basr    %r13,0
         ahi     %r13,pgm_lit-.    # setup base pointer R13 to $PGMDAT
         lh      %r7,__LC_PGM_ILC  # load instruction length
@@ -782,7 +721,6 @@
 io_return:
         GET_CURRENT               # load pointer to task_struct to R9
         tm      SP_PSW+1(%r15),0x01 # returning to user ?
-#        tm      SP_PSW+2(%r15),0x80 # returning to user or kernel thread ?
         jz      io_leave          # no-> skip resched & signal
         stosm   24(%r15),0x03     # reenable interrupts
 #
@@ -958,4 +896,10 @@
         .long  0x000a0000,0x00000000
 restart_go:
 #endif
+
+
+
+
+
+
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/kernel/gdb-stub.c linux.15p9/arch/s390/kernel/gdb-stub.c
--- linux.vanilla/arch/s390/kernel/gdb-stub.c	Tue Jan  4 21:18:41 2000
+++ linux.15p9/arch/s390/kernel/gdb-stub.c	Thu Feb 17 13:30:59 2000
@@ -562,7 +562,7 @@
 			".globl	breakinst\n"
 			"breakinst:\t.word   %0\n\t"
 			:
-			: "i" (BREAKPOINT_U16)
+			: "i" (S390_BREAKPOINT_U16)
 				:
 				);
 }
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/kernel/head.S linux.15p9/arch/s390/kernel/head.S
--- linux.vanilla/arch/s390/kernel/head.S	Tue Jan  4 21:18:41 2000
+++ linux.15p9/arch/s390/kernel/head.S	Thu Feb 17 13:30:59 2000
@@ -2,7 +2,7 @@
  *  arch/s390/kernel/head.S
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Hartmut Penner (hp@de.ibm.com),
  *               Martin Schwidefsky (schwidefsky@de.ibm.com),
  *
@@ -24,7 +24,34 @@
 
 #ifndef CONFIG_IPL
         .org   0
-        .long  0x00080000,0x80000000+start     # Just a restart PSW
+        .long  0x00080000,0x80000000+iplstart  # Just a restart PSW
+
+iplstart:
+        l     %r12,.Lparm                      # pointer to parameter area
+#
+# find out memory size
+#
+        mvc   104(8,0),.Lpcmem0          # setup program check handler
+        slr   %r2,%r2
+        lhi   %r3,1
+        sll   %r3,20
+.Lloop0:
+        l     %r0,0(%r2)                 # test page
+        ar    %r2,%r3                    # add 1M
+        jnm   .Lloop0                    # r1 < 0x80000000 -> loop
+.Lchkmem0:
+        n     %r2,.L4malign0             # align to multiples of 4M
+        st    %r2,MEMORY_SIZE-PARMAREA(%r12)  # store memory size
+        slr   %r2,%r2
+        st    %r2,INITRD_SIZE-PARMAREA(%r12)  # null ramdisk
+        st    %r2,INITRD_START-PARMAREA(%r12)
+        j     start
+
+.Lparm: .long  PARMAREA
+.L4malign0:.long 0xffc00000
+        .align 8
+.Lpcmem0:.long  0x00080000,0x80000000 + .Lchkmem0
+
 #else
 #ifdef CONFIG_IPL_TAPE
 #define IPL_BS 1024
@@ -51,7 +78,28 @@
 	l     %r1,0xb8                         # load ipl subchannel number
         lhi   %r2,IPL_BS                       # load start address
         bras  %r14,.Lloader                    # load rest of ipl image
+        st    %r1,__LC_IPLDEV                  # store ipl device number
         l     %r12,.Lparm                      # pointer to parameter area
+
+#
+# find out memory size
+#
+        mvc   104(8,0),.Lpcmem0          # setup program check handler
+        slr   %r2,%r2
+        lhi   %r3,1
+        sll   %r3,20
+.Lloop0:
+        l     %r0,0(%r2)                 # test page
+        ar    %r2,%r3                    # add 1M
+        jnm   .Lloop0                    # r1 < 0x80000000 -> loop
+.Lchkmem0:
+        n     %r2,.L4malign0             # align to multiples of 4M
+        st    %r2,MEMORY_SIZE-PARMAREA(%r12)  # store memory size
+        c     %r2,.Lbigmem               # more than 64 MB of memory ?
+        jl    .Lmemok                    # if yes load ramdisk to 32 MB
+        mvc   INITRD_START-PARMAREA(4,%r12),.Lrdstart
+.Lmemok:
+
 #
 # load parameter file from tape
 #
@@ -59,26 +107,30 @@
         bras  %r14,.Lloader                    # load parameter file
         ltr   %r2,%r2                          # got anything ?
         jz    .Lnopf
-	chi   %r2,896
+	chi   %r2,895
 	jnh   .Lnotrunc
-	lhi   %r2,896
+	lhi   %r2,895
 .Lnotrunc:
 	l     %r4,INITRD_START-PARMAREA(%r12)
-	clc   0(6,%r4),.Lebcdic                # prefix EBCDIC in parm file ?
-	jne   .Lnocv
-	ahi   %r4,6                            # skip EBCDIC
-	ahi   %r2,-6
-	jnp   .Lnopf
+        la    %r5,0(%r4,%r2)
+        lr    %r3,%r2
+.Lidebc:
+        tm    0(%r5),0x80                      # high order bit set ?
+        jo    .Ldocv                           #  yes -> convert from EBCDIC
+        ahi   %r5,-1
+        brct  %r3,.Lidebc
+        j     .Lnocv
+.Ldocv:
         l     %r3,.Lcvtab
         tr    0(256,%r4),0(%r3)                # convert parameters to ascii
         tr    256(256,%r4),0(%r3)
         tr    512(256,%r4),0(%r3)
-        tr    768(128,%r4),0(%r3)
+        tr    768(122,%r4),0(%r3)
 .Lnocv: la    %r3,COMMAND_LINE-PARMAREA(%r12)  # load adr. of command line
 	mvc   0(256,%r3),0(%r4)
 	mvc   256(256,%r3),256(%r4)
 	mvc   512(256,%r3),512(%r4)
-	mvc   768(128,%r3),768(%r4)
+	mvc   768(122,%r3),768(%r4)
         slr   %r0,%r0
         j     .Lcntlp
 .Ldelspc:
@@ -197,10 +249,13 @@
 .Lcr6:  .long  0xff000000
         .align 8
 .Lcrash:.long  0x000a0000,0x00000000
+.Lpcmem0:.long  0x00080000,0x80000000 + .Lchkmem0
 .Lparm: .long  PARMAREA
+.L4malign0:.long 0xffc00000
+.Lbigmem:.long 0x04000000
+.Lrdstart:.long 0x02000000
 .Lldret:.long  0
 .Lsnsret: .long 0
-.Lebcdic:.long 0xc5c2c3c4,0xc9c30000
 .Lcvtab:.long  _ebcasc                         # ebcdic to ascii table
 
 #endif  /* CONFIG_IPL_TAPE */
@@ -235,31 +290,62 @@
 
         .org   0xf0
 iplstart:
-        stidp __LC_CPUID                       # store cpuid
-	tm    __LC_CPUID,0xff                  # running under VM ?
-	jno   start                            #   no -> skip loader part
 	l     %r1,0xb8                         # load ipl subchannel number
         lhi   %r2,0x730                        # load start address
         bras  %r14,.Lloader                    # load rest of ipl image
-
+        st    %r1,__LC_IPLDEV                  # store ipl device number
 	l     %r12,.Lparm                      # pointer to parameter area
 
 #
+# find out memory size
+#
+        mvc   104(8,0),.Lpcmem0           # setup program check handler
+        slr   %r2,%r2
+        lhi   %r3,1
+        sll   %r3,20
+.Lloop0:
+        l     %r0,0(%r2)                 # test page
+        ar    %r2,%r3                    # add 1M
+        jnm   .Lloop0                    # r1 < 0x80000000 -> loop
+.Lchkmem0:
+        n     %r2,.L4malign0             # align to multiples of 4M
+        st    %r2,MEMORY_SIZE-PARMAREA(%r12)  # store memory size
+        c     %r2,.Lbigmem               # more than 64 MB of memory ?
+        jl    .Lmemok                    # if yes load ramdisk to 32 MB
+        mvc   INITRD_START-PARMAREA(4,%r12),.Lrdstart
+.Lmemok:
+
+#
 # load parameter file from reader
 #
-        la    %r2,COMMAND_LINE-PARMAREA(%r12)  # load adr. of command line
+        l     %r2,INITRD_START-PARMAREA(%r12)  # use ramdisk location as temp
         bras  %r14,.Lloader                    # load parameter file
         ltr   %r2,%r2                          # got anything ?
         jz    .Lnopf
-        la    %r3,COMMAND_LINE-PARMAREA(%r12)  # load adr. of command line
-        l     %r4,.Lcvtab                 
-        tr    0(256,3),0(4)                    # convert parameters to ascii
-        l     %r4,.Lcvtab                 
-        tr    256(256,3),0(4)
-        l     %r4,.Lcvtab                 	
-        tr    512(256,3),0(4)
-        l     %r4,.Lcvtab                 	
-        tr    768(128,3),0(4)            
+        chi   %r2,895
+        jnh   .Lnotrunc
+        lhi   %r2,895
+.Lnotrunc:
+        l     %r4,INITRD_START-PARMAREA(%r12)
+        la    %r5,0(%r4,%r2)
+        lr    %r3,%r2
+.Lidebc:
+        tm    0(%r5),0x80                      # high order bit set ?
+        jo    .Ldocv                           #  yes -> convert from EBCDIC
+        ahi   %r5,-1
+        brct  %r3,.Lidebc
+        j     .Lnocv
+.Ldocv:
+        l     %r3,.Lcvtab
+        tr    0(256,%r4),0(%r3)                # convert parameters to ascii
+        tr    256(256,%r4),0(%r3)
+        tr    512(256,%r4),0(%r3)
+        tr    768(122,%r4),0(%r3)
+.Lnocv: la    %r3,COMMAND_LINE-PARMAREA(%r12)  # load adr. of command line
+        mvc   0(256,%r3),0(%r4)
+        mvc   256(256,%r3),256(%r4)
+        mvc   512(256,%r3),512(%r4)
+        mvc   768(122,%r3),768(%r4)
         slr   %r0,%r0
         j     .Lcntlp
 .Ldelspc:
@@ -289,6 +375,10 @@
 #
 # everything loaded, reset files in reader, then go for it
 #
+        stidp __LC_CPUID                       # store cpuid
+        lh    %r0,__LC_CPUID+4                 # get cpu version
+        chi   %r0,0x7490                       # running on P/390 ?
+        je   start                             #   no -> skip reset
         la    %r2,.Lreset              
         lhi   %r3,26
         .long 0x83230008
@@ -358,13 +448,16 @@
 .Lcr6:  .long  0xff000000
 .Lloadp:.long  0,0
 .Lparm:	.long  PARMAREA
+.L4malign0:.long 0xffc00000
+.Lbigmem:.long 0x04000000
+.Lrdstart:.long 0x02000000
 .Lcvtab:.long  _ebcasc                         # ebcdic to ascii table
 .Lreset:.byte  0xc3,0xc8,0xc1,0xd5,0xc7,0xc5,0x40,0xd9,0xc4,0xd9,0x40
         .byte  0xc1,0xd3,0xd3,0x40,0xd2,0xc5,0xc5,0xd7,0x40,0xd5,0xd6
         .byte  0xc8,0xd6,0xd3,0xc4             # "change rdr all keep nohold"
         .align 8
-.Lcrash:
-        .long  0x000a0000,0x00000000
+.Lpcmem0:.long  0x00080000,0x80000000 + .Lchkmem0
+.Lcrash:.long  0x000a0000,0x00000000
 .Lnewpsw:
         .long  0x00080000,0x80000000+.Lioint
 .Lwaitpsw:
@@ -395,8 +488,11 @@
 	l     %r12,.Lparm1-.LPG1(%r13)   # pointer to parameter area
 
 #
-# find out memory size
+# find out memory size. That is done in the ipl loader too but for
+# ipl from dasd the size of the memory has to be detected too...
 #
+        icm   %r0,15,MEMORY_SIZE-PARMAREA(%r12)
+        jnz   .Lsizeok
 	mvc   104(8,0),.Lpcmem-.LPG1(%r13) # setup program check handler
         slr   %r1,%r1
         lhi   %r2,1
@@ -408,6 +504,7 @@
 .Lchkmem:
 	n     %r1,.L4malign-.LPG1(%r13)  # align to multiples of 4M
 	st    %r1,MEMORY_SIZE-PARMAREA(%r12)  # store memory size
+.Lsizeok:
 
 #
 # find out if we are running under VM
@@ -417,6 +514,11 @@
 	jno    .Lnovm
         oi     MACHINE_FLAGS+3-PARMAREA(%r12),1    # set VM flag
 .Lnovm:
+        lh     %r0,__LC_CPUID+4         # get cpu version
+        chi    %r0,0x7490               # running on a P/390 ?
+        jne    .Lnop390
+        oi     MACHINE_FLAGS+3-PARMAREA(%r12),4    # set P/390 flag
+.Lnop390:
 
 #
 # find out if we have an IEEE fpu
@@ -428,27 +530,10 @@
         oi     MACHINE_FLAGS+3-PARMAREA(%r12),2    # set IEEE fpu flag
 .Lchkfpu:
 
-#
-# move ramdisk to the end of storage, out of the way of the paging tables
-#
-        icm   %r2,15,INITRD_START-PARMAREA(%r12)  # load adr. of ramdisk
-        jz    .Lnocprd
-        icm   %r3,15,INITRD_SIZE-PARMAREA(%r12)   # store size of ramdisk
-        jz    .Lnocprd
-        l     %r4,MEMORY_SIZE-PARMAREA(%r12)
-        sr    %r4,%r3
-        srl   %r4,12
-        sll   %r4,12
-        st    %r4,INITRD_START-PARMAREA(%r12)
-        lr    %r5,%r3
-.Lcprd:
-        mvcle %r4,%r2,0
-        jo    .Lcprd
-.Lnocprd:
         lpsw  .Lentry-.LPG1(13)         # jump to _stext in primary-space,
                                         # virtual and never return ...
         .align 8
-.Lentry:.long  0x0408C000,0x80000000 + _stext
+.Lentry:.long  0x04080000,0x80000000 + _stext
 .Lpstd: .long  .Lpgd+0x7F               # segment-table
 .Lcr0:  .long  0x04b50002
 .Lpcmem:.long  0x00080000,0x80000000 + .Lchkmem
@@ -492,11 +577,14 @@
 #
 # Setup lowcore
 #
+        l     %r1,__LC_IPLDEV           # load ipl device number
         spx   .Lprefix-.LPG2(%r13)      # set prefix to linux lowcore
+        st    %r1,__LC_IPLDEV           # store ipl device number
         l     %r15,.Linittu-.LPG2(%r13)
         ahi   %r15,8192                 # init_task_union + 8191
         st    %r15,__LC_KERNEL_STACK    # set end of kernel stack
         ahi   %r15,-96
+        xc    0(4,%r15),0(%r15)         # set backchain to zero
         lhi   %r0,-1
         st    %r0,__LC_KERNEL_LEVEL     # set interrupt count to -1
 #
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/kernel/irq.c linux.15p9/arch/s390/kernel/irq.c
--- linux.vanilla/arch/s390/kernel/irq.c	Tue Jan  4 21:18:41 2000
+++ linux.15p9/arch/s390/kernel/irq.c	Thu Feb 17 13:40:47 2000
@@ -2,16 +2,15 @@
  *  arch/s390/kernel/irq.c
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Ingo Adlung (adlung@de.ibm.com)
  *
  *  Derived from "arch/i386/kernel/irq.c"
  *    Copyright (C) 1992, 1999 Linus Torvalds, Ingo Molnar
  *
  *  S/390 I/O interrupt processing and I/O request processing is
- *  implemented in linux/arch/s390/do_io.c
+ *   implemented in arch/s390/kernel/s390io.c
  */
-
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/kernel_stat.h>
@@ -37,10 +36,7 @@
 #include <asm/delay.h>
 #include <asm/lowcore.h>
 
-#include "irq.h"
-
-
-void s390_init_IRQ(void);
+unsigned long s390_init_IRQ(unsigned long);
 void s390_free_irq(unsigned int irq, void *dev_id);
 int  s390_request_irq( unsigned int   irq,
                        void           (*handler)(int, void *, struct pt_regs *),
@@ -49,24 +45,8 @@
                        void          *dev_id);
 
 atomic_t nmi_counter;
+
 spinlock_t s390_bh_lock = SPIN_LOCK_UNLOCKED;
-/*
- * Dummy controller type for unused interrupts
- */
-int  do_none(unsigned int irq, int cpu, struct pt_regs * regs) { return 0;}
-int  enable_none(unsigned int irq) { return(-ENODEV); }
-int  disable_none(unsigned int irq) { return(-ENODEV); }
-
-struct hw_interrupt_type no_irq_type = {
-	"none",
-	do_none,
-	enable_none,
-	disable_none
-};
-
-irq_desc_t irq_desc[NR_IRQS] = {
-	[0 ... (NR_IRQS-1)] = { 0, &no_irq_type, },
-};
 
 #if 0
 /*
@@ -82,9 +62,6 @@
 #endif
 
 #if 0
-static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
-#endif
-
 int get_irq_list(char *buf)
 {
 	int i, j;
@@ -92,14 +69,22 @@
 	char *p = buf;
 
 	p += sprintf(p, "           ");
+
 	for (j=0; j<smp_num_cpus; j++)
 		p += sprintf(p, "CPU%d       ",j);
+
 	*p++ = '\n';
 
-	for (i = 0 ; i < NR_IRQS ; i++) {
-		action = irq_desc[i].action;
+	for (i = 0 ; i < NR_IRQS ; i++)
+	{
+		if (ioinfo[i] == INVALID_STORAGE_AREA)
+			continue;
+
+		action = ioinfo[i]->irq_desc.action;
+		
 		if (!action)
 			continue;
+
 		p += sprintf(p, "%3d: ",i);
 #ifndef __SMP__
 		p += sprintf(p, "%10u ", kstat_irqs(i));
@@ -108,20 +93,27 @@
 			p += sprintf(p, "%10u ",
 				     kstat.irqs[cpu_logical_map(j)][i]);
 #endif
-		p += sprintf(p, " %14s", irq_desc[i].handler->typename);
+		p += sprintf(p, " %14s", ioinfo[i]->irq_desc.handler->typename);
 		p += sprintf(p, "  %s", action->name);
 
-		for (action=action->next; action; action = action->next) {
+		for (action=action->next; action; action = action->next)
+		{
 			p += sprintf(p, ", %s", action->name);
-		}
+
+		} /* endfor */
+
 		*p++ = '\n';
-	}
+	
+	} /* endfor */
+
 	p += sprintf(p, "NMI: %10u\n", atomic_read(&nmi_counter));
 #ifdef __SMP__
 	p += sprintf(p, "IPI: %10u\n", atomic_read(&ipi_count));
 #endif
+
 	return p - buf;
 }
+#endif
 
 /*
  * Global interrupt locks for SMP. Allow interrupts to come in on any
@@ -376,43 +368,48 @@
 	int                status;
 
 	status = 0;
-	action = irq_desc[irq].action;
 
-	if (action) {
+	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+		return( -ENODEV);
+
+	action = ioinfo[irq]->irq_desc.action;
+
+	if (action)
+	{
 		status |= 1;
 
 		if (!(action->flags & SA_INTERRUPT))
 			__sti();
 
-		do {
+		do
+		{
 			status |= action->flags;
 			action->handler(irq, action->dev_id, regs);
 			action = action->next;
 		} while (action);
+
 		if (status & SA_SAMPLE_RANDOM)
 			add_interrupt_randomness(irq);
 		__cli();
-	}
+
+	} /* endif */
 
 	return status;
 }
 
-
 void enable_nop(int irq)
 {
 }
 
-__initfunc(void init_IRQ(void))
+unsigned long __init init_IRQ(unsigned long memory)
 {
-
-   s390_init_IRQ();
-
+	return s390_init_IRQ( memory);
 }
 
 
 void free_irq(unsigned int irq, void *dev_id)
 {
-   s390_free_irq( irq, dev_id);
+	s390_free_irq( irq, dev_id);
 }
 
 
@@ -422,7 +419,6 @@
                  const char    *devname,
                  void          *dev_id)
 {
-   return( s390_request_irq( irq, handler, irqflags, devname, dev_id ) );
-
+	return( s390_request_irq( irq, handler, irqflags, devname, dev_id ) );
 }
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/kernel/irq.h linux.15p9/arch/s390/kernel/irq.h
--- linux.vanilla/arch/s390/kernel/irq.h	Tue Jan  4 21:18:41 2000
+++ linux.15p9/arch/s390/kernel/irq.h	Thu Jan  1 01:00:00 1970
@@ -1,723 +0,0 @@
-#ifndef __irq_h
-#define __irq_h
-
-#include <asm/irq.h>
-#include <asm/hardirq.h>
-
-/*
- * Interrupt controller descriptor. This is all we need
- * to describe about the low-level hardware.
- */
-struct hw_interrupt_type {
-        const char   *typename;
-        int         (*handle)(unsigned int irq,
-                              int cpu,
-                              struct pt_regs * regs);
-        int         (*enable) (unsigned int irq);
-        int         (*disable)(unsigned int irq);
-};
-
-
-/*
- * Status: reason for being disabled: somebody has
- * done a "disable_irq()" or we must not re-enter the
- * already executing irq..
- */
-#define IRQ_INPROGRESS  1
-#define IRQ_DISABLED    2
-#define IRQ_PENDING     4
-
-/*
- * path management control word
- */
-typedef struct {
-      unsigned long  intparm;      /* interruption parameter */
-      unsigned int   res0 : 2;     /* reserved zeros */
-      unsigned int   isc  : 3;     /* interruption sublass */
-      unsigned int   res5 : 3;     /* reserved zeros */
-      unsigned int   ena  : 1;     /* enabled */
-      unsigned int   lm   : 2;     /* limit mode */
-      unsigned int   mme  : 2;     /* measurement-mode enable */
-      unsigned int   mp   : 1;     /* multipath mode */
-      unsigned int   tf   : 1;     /* timing facility */
-      unsigned int   dnv  : 1;     /* device number valid */
-      unsigned int   dev  : 16;    /* device number */
-      unsigned char  lpm;          /* logical path mask */
-      unsigned char  pnom;         /* path not operational mask */
-      unsigned char  lpum;         /* last path used mask */
-      unsigned char  pim;          /* path installed mask */
-      unsigned short mbi;          /* measurement-block index */
-      unsigned char  pom;          /* path operational mask */
-      unsigned char  pam;          /* path available mask */
-      unsigned char  chpid[8];     /* CHPID 0-7 (if available) */
-      unsigned int   unused1 : 8;  /* reserved zeros */
-      unsigned int   st      : 3;  /* subchannel type */
-      unsigned int   unused2 : 20; /* reserved zeros */
-      unsigned int   csense  : 1;  /* concurrent sense; can be enabled ...*/
-                                   /*  ... per MSCH, however, if facility */
-                                   /*  ... is not installed, this results */
-                                   /*  ... in an operand exception.       */
-   } pmcw_t;
-
-/*
- * subchannel status word
- */
-typedef struct {
-      unsigned int   key  : 4; /* subchannel key */
-      unsigned int   sctl : 1; /* suspend control */
-      unsigned int   eswf : 1; /* ESW format */
-      unsigned int   cc   : 2; /* deferred condition code */
-      unsigned int   fmt  : 1; /* format */
-      unsigned int   pfch : 1; /* prefetch */
-      unsigned int   isic : 1; /* initial-status interruption control */
-      unsigned int   alcc : 1; /* address-limit checking control */
-      unsigned int   ssi  : 1; /* supress-suspended interruption */
-      unsigned int   zcc  : 1; /* zero condition code */
-      unsigned int   ectl : 1; /* extended control */
-      unsigned int   pno  : 1;     /* path not operational */
-      unsigned int   res  : 1;     /* reserved */
-      unsigned int   fctl : 3;     /* function control */
-      unsigned int   actl : 7;     /* activity control */
-      unsigned int   stctl : 5;    /* status control */
-      unsigned long  cpa;          /* channel program address */
-      unsigned int   dstat : 8;    /* device status */
-      unsigned int   cstat : 8;    /* subchannel status */
-      unsigned int   count : 16;   /* residual count */
-   } scsw_t;
-
-#define SCSW_FCTL_CLEAR_FUNC     0x1
-#define SCSW_FCTL_HALT_FUNC      0x2
-#define SCSW_FCTL_START_FUNC     0x4
-
-#define SCSW_ACTL_SUSPENDED      0x1
-#define SCSW_ACTL_DEVACT         0x2
-#define SCSW_ACTL_SCHACT         0x4
-#define SCSW_ACTL_CLEAR_PEND     0x8
-#define SCSW_ACTL_HALT_PEND      0x10
-#define SCSW_ACTL_START_PEND     0x20
-#define SCSW_ACTL_RESUME_PEND    0x40
-
-#define SCSW_STCTL_STATUS_PEND   0x1
-#define SCSW_STCTL_SEC_STATUS    0x2
-#define SCSW_STCTL_PRIM_STATUS   0x4
-#define SCSW_STCTL_INTER_STATUS  0x8
-#define SCSW_STCTL_ALERT_STATUS  0x10
-
-#define DEV_STAT_ATTENTION       0x80
-#define DEV_STAT_STAT_MOD        0x40
-#define DEV_STAT_CU_END          0x20
-#define DEV_STAT_BUSY            0x10
-#define DEV_STAT_CHN_END         0x08
-#define DEV_STAT_DEV_END         0x04
-#define DEV_STAT_UNIT_CHECK      0x02
-#define DEV_STAT_UNIT_EXCEP      0x01
-
-#define SCHN_STAT_PCI            0x80
-#define SCHN_STAT_INCORR_LEN     0x40
-#define SCHN_STAT_PROG_CHECK     0x20
-#define SCHN_STAT_PROT_CHECK     0x10
-#define SCHN_STAT_CHN_DATA_CHK   0x08
-#define SCHN_STAT_CHN_CTRL_CHK   0x04
-#define SCHN_STAT_INTF_CTRL_CHK  0x02
-#define SCHN_STAT_CHAIN_CHECK    0x01
-
-/*
- * subchannel information block
- */
-typedef struct {
-      pmcw_t pmcw;             /* path management control word */
-      scsw_t scsw;             /* subchannel status word */
-      char mda[12];            /* model dependent area */
-   } schib_t;
-
-typedef struct {
-      char            cmd_code;/* command code */
-      char            flags;   /* flags, like IDA adressing, etc. */
-      unsigned short  count;   /* byte count */
-      void           *cda;     /* data address */
-   } ccw1_t __attribute__ ((aligned(8)));
-
-#define CCW_FLAG_DC             0x80
-#define CCW_FLAG_CC             0x40
-#define CCW_FLAG_SLI            0x20
-#define CCW_FLAG_SKIP           0x10
-#define CCW_FLAG_PCI            0x08
-#define CCW_FLAG_IDA            0x04
-#define CCW_FLAG_SUSPEND        0x02
-
-#define CCW_CMD_BASIC_SENSE     0x04
-#define CCW_CMD_TIC             0x08
-#define CCW_CMD_SENSE_ID        0xE4
-#define CCW_CMD_NOOP            0x03
-#define CCW_CMD_RDC             0x64
-
-#define SENSE_MAX_COUNT         0x20
-
-/*
- * architectured values for first sense byte
- */
-#define SNS0_CMD_REJECT         0x80
-#define SNS_CMD_REJECT          SNS0_CMD_REJECT
-#define SNS0_INTERVENTION_REQ   0x40
-#define SNS0_BUS_OUT_CHECK      0x20
-#define SNS0_EQUIPMENT_CHECK    0x10
-#define SNS0_DATA_CHECK         0x08
-#define SNS0_OVERRUN            0x04
-
-/*
- * operation request block
- */
-typedef struct {
-      unsigned long  intparm;  /* interruption parameter */
-      unsigned int   key  : 4; /* flags, like key, suspend control, etc. */
-      unsigned int   spnd : 1; /* suspend control */
-      unsigned int   res1 : 3; /* reserved */
-      unsigned int   fmt  : 1; /* format control */
-      unsigned int   pfch : 1; /* prefetch control */
-      unsigned int   isic : 1; /* initial-status-interruption control */
-      unsigned int   alcc : 1; /* address-limit-checking control */
-      unsigned int   ssic : 1; /* suppress-suspended-interr. control */
-      unsigned int   res2 : 3; /* reserved */
-      unsigned int   lpm  : 8; /* logical path mask */
-      unsigned int   ils  : 1; /* incorrect length */
-      unsigned int   zero : 7; /* reserved zeros */
-      ccw1_t        *cpa;      /* channel program address */
-   }  __attribute__ ((packed,aligned(4))) orb_t;
-
-typedef struct {
-      unsigned int res0  : 4;  /* reserved */
-      unsigned int pvrf  : 1;  /* path-verification-required flag */
-      unsigned int cpt   : 1;  /* channel-path timeout */
-      unsigned int fsavf : 1;  /* Failing storage address validity flag */
-      unsigned int cons  : 1;  /* concurrent-sense */
-      unsigned int res8  : 2;  /* reserved */
-      unsigned int scnt  : 6;  /* sense count if cons == 1 */
-      unsigned int res16 : 16; /* reserved */
-   } erw_t;
-
-/*
- * subchannel logout area
- */
-typedef struct {
-      unsigned int res0  : 1;  /* reserved */
-      unsigned int esf   : 7;  /* extended status flags */
-      unsigned int lpum  : 8;  /* last path used mask */
-      unsigned int res16 : 1;  /* reserved */
-      unsigned int fvf   : 5;  /* field-validity flags */
-      unsigned int sacc  : 2;  /* storage access code */
-      unsigned int termc : 2;  /* termination code */
-      unsigned int devsc : 1;  /* device-status check */
-      unsigned int serr  : 1;  /* secondary error */
-      unsigned int ioerr : 1;  /* i/o-error alert */
-      unsigned int seqc  : 3;  /* sequence code */
-   } sublog_t ;
-
-/*
- * Format 0 Extended Status Word (ESW)
- */
-typedef struct {
-      sublog_t      sublog;    /* subchannel logout */
-      erw_t         erw;       /* extended report word */
-      void         *faddr;     /* failing address */
-      unsigned int  zeros[2];  /* 2 fullwords of zeros */
-   } esw0_t;
-
-/*
- * Format 1 Extended Status Word (ESW)
- */
-typedef struct {
-      unsigned char  zero0;    /* reserved zeros */
-      unsigned char  lpum;     /* last path used mask */
-      unsigned short zero16;   /* reserved zeros */
-      erw_t          erw;      /* extended report word */
-      unsigned int   zeros[3]; /* 2 fullwords of zeros */
-   } esw1_t;
-
-/*
- * Format 2 Extended Status Word (ESW)
- */
-typedef struct {
-      unsigned char  zero0;    /* reserved zeros */
-      unsigned char  lpum;     /* last path used mask */
-      unsigned short dcti;     /* device-connect-time interval */
-      erw_t          erw;      /* extended report word */
-      unsigned int   zeros[3]; /* 2 fullwords of zeros */
-   } esw2_t;
-
-/*
- * Format 3 Extended Status Word (ESW)
- */
-typedef struct {
-      unsigned char  zero0;    /* reserved zeros */
-      unsigned char  lpum;     /* last path used mask */
-      unsigned short res;      /* reserved */
-      erw_t          erw;      /* extended report word */
-      unsigned int   zeros[3]; /* 2 fullwords of zeros */
-   } esw3_t;
-
-typedef union {
-      esw0_t esw0;
-      esw1_t esw1;
-      esw2_t esw2;
-      esw3_t esw3;
-   } esw_t;
-
-/*
- * interruption response block
- */
-typedef struct {
-      scsw_t scsw;             /* subchannel status word */
-      esw_t  esw;              /* extended status word */
-      char   ecw[32];          /* extended control word */
-   } irb_t __attribute__ ((aligned(4)));
-
-/*
- * TPI info structure
- */
-typedef struct {
-      unsigned int res : 16;   /* reserved 0x00000001 */
-      unsigned int irq : 16;   /* aka. subchannel number */
-      unsigned int intparm;    /* interruption parameter */
-   } tpi_info_t;
-
-
-/*
- * This is the "IRQ descriptor", which contains various information
- * about the irq, including what kind of hardware handling it has,
- * whether it is disabled etc etc.
- *
- * Pad this out to 32 bytes for cache and indexing reasons.
- */
-typedef struct {
-      unsigned int              status;    /* IRQ status - IRQ_INPROGRESS, IRQ_DISABLED */
-      struct hw_interrupt_type *handler;   /* handle/enable/disable functions */
-      struct irqaction         *action;    /* IRQ action list */
-      unsigned int              unused[3];
-      spinlock_t                irq_lock;
-   } irq_desc_t;
-
-//
-// command information word  (CIW) layout
-//
-typedef struct _ciw {
-   unsigned int et       :  2; // entry type
-   unsigned int reserved :  2; // reserved
-   unsigned int ct       :  4; // command type
-   unsigned int cmd      :  8; // command
-   unsigned int count    : 16; // count
-   } ciw_t;
-
-#define CIW_TYPE_RCD    0x0    // read configuration data
-#define CIW_TYPE_SII    0x1    // set interface identifier
-#define CIW_TYPE_RNI    0x2    // read node identifier
-
-//
-// sense-id response buffer layout
-//
-typedef struct {
-  /* common part */
-      unsigned char  reserved;     /* always 0x'FF' */
-      unsigned short cu_type;      /* control unit type */
-      unsigned char  cu_model;     /* control unit model */
-      unsigned short dev_type;     /* device type */
-      unsigned char  dev_model;    /* device model */
-      unsigned char  unused;       /* padding byte */
-  /* extended part */
-      ciw_t    ciw[62];            /* variable # of CIWs */
-   }  __attribute__ ((packed,aligned(4))) senseid_t;
-
-/*
- * sense data
- */
-typedef struct {
-      unsigned char res[32];   /* reserved   */
-      unsigned char data[32];  /* sense data */
-   } sense_t;
-
-/*
- * device status area, to be provided by the device driver
- *  when calling request_irq() as parameter "dev_id", later
- *  tied to the "action" control block.
- *
- * Note : No data area must be added after union ii or the
- *         effective devstat size calculation will fail !
- */
-typedef struct {
-     unsigned int  devno;    /* device number, aka. "cuu" from irb */
-     unsigned int  intparm;  /* interrupt parameter */
-     unsigned char cstat;    /* channel status - accumulated */
-     unsigned char dstat;    /* device status - accumulated */
-     unsigned char lpum;     /* last path used mask from irb */
-     unsigned char unused;   /* not used - reserved */
-     unsigned int  flag;     /* flag : see below */
-     unsigned long cpa;      /* CCW address from irb at primary status */
-     unsigned int  rescnt;   /* res. count from irb at primary status */
-     unsigned int  scnt;     /* sense count, if DEVSTAT_FLAG_SENSE_AVAIL */
-     union {
-        irb_t   irb;         /* interruption response block */
-        sense_t sense;       /* sense information */
-        } ii;                /* interrupt information */
-  } devstat_t;
-
-#define DEVSTAT_FLAG_SENSE_AVAIL   0x00000001
-#define DEVSTAT_NOT_OPER           0x00000002
-#define DEVSTAT_START_FUNCTION     0x00000004
-#define DEVSTAT_HALT_FUNCTION      0x00000008
-#define DEVSTAT_STATUS_PENDING     0x00000010
-#define DEVSTAT_FINAL_STATUS       0x80000000
-
-/*
- * Flags used as input parameters for do_IO()
- */
-#define DOIO_EARLY_NOTIFICATION 0x01    /* allow for I/O completion ... */
-                                        /* ... notification after ... */
-                                        /* ... primary interrupt status */
-#define DOIO_RETURN_CHAN_END       DOIO_EARLY_NOTIFICATION
-#define DOIO_VALID_LPM          0x02    /* LPM input parameter is valid */
-#define DOIO_WAIT_FOR_INTERRUPT 0x04    /* wait synchronously for interrupt */
-#define DOIO_REPORT_ALL         0x08    /* report all interrupt conditions */
-#define DOIO_ALLOW_SUSPEND      0x10    /* allow for channel prog. suspend */
-#define DOIO_DENY_PREFETCH      0x20    /* don't allow for CCW prefetch */
-#define DOIO_SUPPRESS_INTER     0x40    /* suppress intermediate inter. */
-                                        /* ... for suspended CCWs */
-
-/*
- * do_IO()
- *
- * Start a S/390 channel program. When the interrupt arrives
- *  handle_IRQ_event() is called, which eventually calls the
- *  IRQ handler, either immediately, delayed (dev-end missing,
- *  or sense required) or never (no IRQ handler registered -
- *  should never occur, as the IRQ (subchannel ID) should be
- *  disabled if no handler is present. Depending on the action
- *  taken, do_IO() returns :  0      - Success
- *                           -EIO    - Status pending
- *                                        see : action->dev_id->cstat
- *                                              action->dev_id->dstat
- *                           -EBUSY  - Device busy
- *                           -ENODEV - Device not operational
- */
-int do_IO( int            irq,          /* IRQ aka. subchannel number */
-           ccw1_t        *cpa,          /* logical channel program address */
-           unsigned long  initparm,     /* interruption parameter */
-           unsigned char  lpm,          /* logical path mask */
-           unsigned long  flag);        /* flags : see above */
-
-int start_IO( int            irq,       /* IRQ aka. subchannel number */
-              ccw1_t        *cpa,       /* logical channel program address */
-              unsigned long  intparm,   /* interruption parameter */
-              unsigned char  lpm,       /* logical path mask */
-              unsigned long  flag);     /* flags : see above */
-
-int resume_IO( int irq);                /* IRQ aka. subchannel number */
-
-int halt_IO( int          irq,          /* IRQ aka. subchannel number */
-             int          intparm,      /* dummy intparm */
-             unsigned int flag);        /* possible DOIO_WAIT_FOR_INTERRUPT */
-
-
-int process_IRQ( struct pt_regs regs,
-                 unsigned int   irq,
-                 unsigned int   intparm);
-
-
-int enable_cpu_sync_isc ( int irq );
-int disable_cpu_sync_isc( int irq );
-
-typedef struct {
-     int          irq;                  /* irq, aka. subchannel */
-     unsigned int devno;                /* device number */
-     unsigned int status;               /* device status */
-     senseid_t    sid_data;             /* senseID data */
-     } dev_info_t;
-
-int get_dev_info( int irq, dev_info_t *);   /* to be eliminated - don't use */
-
-int get_dev_info_by_irq  ( int irq, dev_info_t *pdi);
-int get_dev_info_by_devno( unsigned int devno, dev_info_t *pdi);
-
-int          get_irq_by_devno( unsigned int devno );
-unsigned int get_devno_by_irq( int irq );
-
-int read_dev_chars( int irq, void **buffer, int length );
-int read_conf_data( int irq, void **buffer, int *length );
-
-extern senseid_t senseid[NR_IRQS];
-
-extern irq_desc_t irq_desc[NR_IRQS];
-
-extern int handle_IRQ_event(unsigned int, int cpu, struct pt_regs *);
-
-extern int set_cons_dev(int irq);
-extern int reset_cons_dev(int irq);
-extern int wait_cons_dev(int irq);
-
-/*
- * Some S390 specific IO instructions as inline
- */
-
-extern __inline__ int stsch(int irq, volatile schib_t *addr)
-{
-        int ccode;
-
-        __asm__ __volatile__(
-                "LR 1,%1\n\t"
-                "STSCH 0(%2)\n\t"
-                "IPM %0\n\t"
-                "SRL %0,28\n\t"
-                : "=d" (ccode) : "r" (irq | 0x10000L), "a" (addr)
-                : "cc", "1" );
-        return ccode;
-}
-
-extern __inline__ int msch(int irq, volatile schib_t *addr)
-{
-        int ccode;
-
-        __asm__ __volatile__(
-                "LR 1,%1\n\t"
-                "MSCH 0(%2)\n\t"
-                "IPM %0\n\t"
-                "SRL %0,28\n\t"
-                : "=d" (ccode) : "r" (irq | 0x10000L), "a" (addr)
-                : "cc", "1" );
-        return ccode;
-}
-
-extern __inline__ int msch_err(int irq, volatile schib_t *addr)
-{
-        int ccode;
-
-        __asm__ __volatile__(
-                "    lr   1,%1\n"
-                "    msch 0(%2)\n"
-                "0:  ipm  %0\n"
-                "    srl  %0,28\n"
-                "1:\n"
-                ".section .fixup,\"ax\"\n"
-                "2:  l    %0,%3\n"
-                "    bras 1,3f\n"
-                "    .long 1b\n"
-                "3:  l    1,0(1)\n"
-                "    br   1\n"
-                ".previous\n"
-                ".section __ex_table,\"a\"\n"
-                "   .align 4\n"
-                "   .long 0b,2b\n"
-                ".previous"
-                : "=d" (ccode)
-                : "r" (irq | 0x10000L), "a" (addr), "i" (__LC_PGM_ILC)
-                : "cc", "1" );
-        return ccode;
-}
-
-extern __inline__ int tsch(int irq, volatile irb_t *addr)
-{
-        int ccode;
-
-        __asm__ __volatile__(
-                "LR 1,%1\n\t"
-                "TSCH 0(%2)\n\t"
-                "IPM %0\n\t"
-                "SRL %0,28\n\t"
-                : "=d" (ccode) : "r" (irq | 0x10000L), "a" (addr)
-                : "cc", "1" );
-        return ccode;
-}
-
-extern __inline__ int tpi( volatile tpi_info_t *addr)
-{
-        int ccode;
-
-        __asm__ __volatile__(
-                "TPI 0(%1)\n\t"
-                "IPM %0\n\t"
-                "SRL %0,28\n\t"
-                : "=d" (ccode) : "a" (addr)
-                : "cc", "1" );
-        return ccode;
-}
-
-extern __inline__ int ssch(int irq, volatile orb_t *addr)
-{
-        int ccode;
-
-        __asm__ __volatile__(
-                "LR 1,%1\n\t"
-                "SSCH 0(%2)\n\t"
-                "IPM %0\n\t"
-                "SRL %0,28\n\t"
-                : "=d" (ccode) : "r" (irq | 0x10000L), "a" (addr)
-                : "cc", "1" );
-        return ccode;
-}
-
-extern __inline__ int rsch(int irq)
-{
-        int ccode;
-
-        __asm__ __volatile__(
-                "LR 1,%1\n\t"
-                "RSCH\n\t"
-                "IPM %0\n\t"
-                "SRL %0,28\n\t"
-                : "=d" (ccode) : "r" (irq | 0x10000L)
-                : "cc", "1" );
-        return ccode;
-}
-
-extern __inline__ int csch(int irq)
-{
-        int ccode;
-
-        __asm__ __volatile__(
-                "LR 1,%1\n\t"
-                "CSCH\n\t"
-                "IPM %0\n\t"
-                "SRL %0,28\n\t"
-                : "=d" (ccode) : "r" (irq | 0x10000L)
-                : "cc", "1" );
-        return ccode;
-}
-
-extern __inline__ int hsch(int irq)
-{
-        int ccode;
-
-        __asm__ __volatile__(
-                "LR 1,%1\n\t"
-                "HSCH\n\t"
-                "IPM %0\n\t"
-                "SRL %0,28\n\t"
-                : "=d" (ccode) : "r" (irq | 0x10000L)
-                : "cc", "1" );
-        return ccode;
-}
-
-extern __inline__ int iac( void)
-{
-        int ccode;
-
-        __asm__ __volatile__(
-                "IAC %0\n\t"
-                "IPM %0\n\t"
-                "SRL %0,28\n\t"
-                : "=d" (ccode) : : "cc");
-        return ccode;
-}
-
-typedef struct {
-     unsigned int vrdcdvno : 16;   /* device number (input) */
-     unsigned int vrdclen  : 16;   /* data block length (input) */
-     unsigned int vrdcvcla : 8;    /* virtual device class (output) */
-     unsigned int vrdcvtyp : 8;    /* virtual device type (output) */
-     unsigned int vrdcvsta : 8;    /* virtual device status (output) */
-     unsigned int vrdcvfla : 8;    /* virtual device flags (output) */
-     unsigned int vrdcrccl : 8;    /* real device class (output) */
-     unsigned int vrdccrty : 8;    /* real device type (output) */
-     unsigned int vrdccrmd : 8;    /* real device model (output) */
-     unsigned int vrdccrft : 8;    /* real device feature (output) */
-     } __attribute__ ((packed,aligned(4))) diag210_t;
-
-void VM_virtual_device_info( int        devno,   /* device number */
-                             senseid_t *ps );    /* ptr to senseID data */
-
-extern __inline__ int diag210( diag210_t * addr)
-{
-        int ccode;
-
-        __asm__ __volatile__(
-                "LR 1,%1\n\t"
-                ".long 0x83110210\n\t"
-                "IPM %0\n\t"
-                "SRL %0,28\n\t"
-                : "=d" (ccode) : "a" (addr)
-                : "cc", "1" );
-        return ccode;
-}
-
-/*
- * Various low-level irq details needed by irq.c, process.c,
- * time.c, io_apic.c and smp.c
- *
- * Interrupt entry/exit code at both C and assembly level
- */
-
-void mask_irq(unsigned int irq);
-void unmask_irq(unsigned int irq);
-
-#define MAX_IRQ_SOURCES 128
-
-extern spinlock_t irq_controller_lock;
-
-#ifdef __SMP__
-
-#include <asm/atomic.h>
-
-static inline void irq_enter(int cpu, unsigned int irq)
-{
-        hardirq_enter(cpu);
-        while (test_bit(0,&global_irq_lock)) {
-                eieio();
-        }
-}
-
-static inline void irq_exit(int cpu, unsigned int irq)
-{
-        hardirq_exit(cpu);
-        release_irqlock(cpu);
-}
-
-
-#else
-
-#define irq_enter(cpu, irq)     (++local_irq_count[cpu])
-#define irq_exit(cpu, irq)      (--local_irq_count[cpu])
-
-#endif
-
-#define __STR(x) #x
-#define STR(x) __STR(x)
-
-#ifdef __SMP__
-
-/*
- *      SMP has a few special interrupts for IPI messages
- */
-
-#endif /* __SMP__ */
-
-/*
- * x86 profiling function, SMP safe. We might want to do this in
- * assembly totally?
- */
-static inline void s390_do_profile (unsigned long addr)
-{
-#if 0
-        if (prof_buffer && current->pid) {
-                addr -= (unsigned long) &_stext;
-                addr >>= prof_shift;
-                /*
-                 * Don't ignore out-of-bounds EIP values silently,
-                 * put them into the last histogram slot, so if
-                 * present, they will show up as a sharp peak.
-                 */
-                if (addr > prof_len-1)
-                        addr = prof_len-1;
-                atomic_inc((atomic_t *)&prof_buffer[addr]);
-        }
-#endif
-}
-
-#define s390irq_spin_lock(irq) \
-        spin_lock(&(irq_desc[irq].irq_lock))
-
-#define s390irq_spin_unlock(irq) \
-        spin_unlock(&(irq_desc[irq].irq_lock))
-
-#define s390irq_spin_lock_irqsave(irq,flags) \
-        spin_lock_irqsave(&(irq_desc[irq].irq_lock), flags)
-#define s390irq_spin_unlock_irqrestore(irq,flags) \
-        spin_unlock_irqrestore(&(irq_desc[irq].irq_lock), flags)
-#endif
-
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/kernel/process.c linux.15p9/arch/s390/kernel/process.c
--- linux.vanilla/arch/s390/kernel/process.c	Tue Jan  4 21:18:41 2000
+++ linux.15p9/arch/s390/kernel/process.c	Thu Feb 17 13:31:37 2000
@@ -2,7 +2,7 @@
  *  arch/s390/kernel/process.c
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  *               Hartmut Penner (hp@de.ibm.com),
  *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
@@ -45,7 +45,6 @@
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/misc390.h>
-#include "irq.h"
 
 spinlock_t semaphore_wake_lock = SPIN_LOCK_UNLOCKED;
 
@@ -163,8 +162,10 @@
 		{
 			regno=(line-sp_gprs1)*4;
 			linelen=sprintf(buff,"%08x  %08x  %08x  %08x\n",
-			       regs->gprs[regno], regs->gprs[regno+1],
-			       regs->gprs[regno+2], regs->gprs[regno+3]);
+					regs->gprs[regno], 
+					regs->gprs[regno+1],
+					regs->gprs[regno+2],
+					regs->gprs[regno+3]);
 		}
 		break;
 	case sp_acrs:
@@ -176,8 +177,10 @@
 		{
 			regno=(line-sp_acrs1)*4;
 			linelen=sprintf(buff,"%08x  %08x  %08x  %08x\n",
-					regs->acrs[regno], regs->acrs[regno+1],
-					regs->acrs[regno+2], regs->acrs[regno+3]);
+					regs->acrs[regno],
+					regs->acrs[regno+1],
+					regs->acrs[regno+2],
+					regs->acrs[regno+3]);
 		}
 		break;
 	case sp_kern_backchain:
@@ -283,7 +286,13 @@
             unsigned long gprs[10];    /* gprs 6 -15                       */
             unsigned long fprs[4];     /* fpr 4 and 6                      */
             unsigned long empty[4];
-            struct pt_regs childregs;
+#if CONFIG_REMOTE_DEBUG
+		gdb_pt_regs childregs;
+#else
+		pt_regs childregs;
+#endif
+		__u32   pgm_old_ilc;     /* single step magic from entry.S */
+		__u32   pgm_svc_step;
           } *frame;
 
         frame = (struct stack_frame *) (2*PAGE_SIZE + (unsigned long) p) -1;
@@ -299,10 +308,10 @@
 
         /* fake return stack for resume(), don't go back to schedule */
         frame->gprs[9]  = (unsigned long) frame;
-
+	frame->pgm_svc_step=0; /* Nope we aren't single stepping an svc */
         /* save fprs, if used in last task */
 	save_fp_regs(&p->tss.fp_regs);
-        p->tss.user_seg = __pa((unsigned long) p->mm->pgd) | _USER_SEG_TABLE_LEN;
+        p->tss.user_seg = __pa((unsigned long) p->mm->pgd) | _SEGMENT_TABLE;
         p->tss.fs = USER_DS;
         /* Don't copy debug registers */
         memset(&p->tss.per_info,0,sizeof(p->tss.per_info));
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/kernel/ptrace.c linux.15p9/arch/s390/kernel/ptrace.c
--- linux.vanilla/arch/s390/kernel/ptrace.c	Tue Jan  4 21:18:41 2000
+++ linux.15p9/arch/s390/kernel/ptrace.c	Thu Feb 17 13:31:37 2000
@@ -2,7 +2,7 @@
  *  arch/s390/kernel/ptrace.c
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
  *
  *  Based on PowerPC version 
@@ -226,7 +226,9 @@
 static int read_long(struct task_struct * tsk, unsigned long addr,
 	unsigned long * result)
 {
-	struct vm_area_struct * vma = find_extend_vma(tsk, addr);
+	struct vm_area_struct * vma;
+	addr=ADDR_BITS_REMOVE(addr);
+	vma= find_extend_vma(tsk, addr);
 
 	if (!vma)
 		return -EIO;
@@ -268,7 +270,10 @@
 static int write_long(struct task_struct * tsk, unsigned long addr,
 	unsigned long data)
 {
-	struct vm_area_struct * vma = find_extend_vma(tsk, addr);
+	struct vm_area_struct * vma;
+
+	addr=ADDR_BITS_REMOVE(addr);
+	vma = find_extend_vma(tsk, addr);
 
 	if (!vma)
 		return -EIO;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/kernel/reipl.S linux.15p9/arch/s390/kernel/reipl.S
--- linux.vanilla/arch/s390/kernel/reipl.S	Thu Jan  1 01:00:00 1970
+++ linux.15p9/arch/s390/kernel/reipl.S	Thu Feb 17 13:31:37 2000
@@ -0,0 +1,72 @@
+/*
+ *  arch/s390/kernel/reipl.S
+ *
+ *  S390 version
+ *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com)
+ */
+
+#include <asm/lowcore.h>
+
+		.globl	do_reipl
+do_reipl:	basr	%r13,0
+.Lpg0:		lpsw	.Lnewpsw-.Lpg0(%r13)
+.Lpg1:		lctl	%c6,%c6,.Lall-.Lpg0(%r13)
+                lr      %r1,%r2
+        	mvc     __LC_PGM_NEW_PSW(8,0),.Lpcnew-.Lpg0(%r13)
+                stsch   .Lschib-.Lpg0(%r13)                                    
+	        oi      .Lschib+5-.Lpg0(%r13),0x84 
+.Lecs:  	xi      .Lschib+27-.Lpg0(%r13),0x01 
+        	msch    .Lschib-.Lpg0(%r13) 
+		ssch	.Liplorb-.Lpg0(%r13)           
+		jz	.L001   
+		bas	%r14,.Ldisab-.Lpg0(%r13)
+.L001:		mvc	__LC_IO_NEW_PSW(8,0),.Lionew-.Lpg0(%r13)	
+.Ltpi:		lpsw	.Lwaitpsw-.Lpg0(%r13)          
+.Lcont:		c	%r1,__LC_SUBCHANNEL_ID(%r0)
+		jnz	.Ltpi
+		clc	__LC_IO_INT_PARM(4),.Liplorb-.Lpg0(%r13)
+		jnz	.Ltpi
+		tsch	.Liplirb-.Lpg0(%r13)           
+		tm	.Liplirb+9-.Lpg0(%r13),0xbf
+                jz      .L002
+                bas     %r14,.Ldisab-.Lpg0(%r13)    
+.L002:		tm	.Liplirb+8-.Lpg0(%r13),0xf3    
+                jz      .L003
+                bas     %r14,.Ldisab-.Lpg0(%r13)	
+.L003:		spx	.Lnull-.Lpg0(%r13)
+		st 	%r1,__LC_SUBCHANNEL_ID(%r0)	
+                lpsw 	0
+		sigp    0,0,0(6)               
+.Ldisab:	st      %r14,.Ldispsw+4-.Lpg0(%r13)
+		lpsw	.Ldispsw-.Lpg0(%r13)
+                .align 	8
+.Lall:		.long	0xff000000;
+.Lnull:		.long   0x00000000
+                .align 	8
+.Lnewpsw:	.long   0x00080000,0x80000000+.Lpg1
+.Lpcnew:  	.long   0x00080000,0x80000000+.Lecs
+.Lionew:	.long   0x00080000,0x80000000+.Lcont
+.Lwaitpsw:	.long	0x020a0000,0x00000000+.Ltpi
+.Ldispsw:	.long   0x000a0000,0x00000000
+.Liplccws:	.long   0x02000000,0x60000018
+		.long   0x08000008,0x20000001
+.Liplorb:	.long	0x0049504c,0x0000ff80
+		.long	0x00000000+.Liplccws
+.Lschib:        .long   0x00000000,0x00000000
+		.long   0x00000000,0x00000000
+		.long   0x00000000,0x00000000
+		.long   0x00000000,0x00000000
+		.long   0x00000000,0x00000000
+		.long   0x00000000,0x00000000
+.Liplirb:	.long	0x00000000,0x00000000
+		.long	0x00000000,0x00000000
+		.long	0x00000000,0x00000000
+		.long	0x00000000,0x00000000
+		.long	0x00000000,0x00000000
+		.long	0x00000000,0x00000000
+		.long	0x00000000,0x00000000
+		.long	0x00000000,0x00000000
+	
+
+	
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/kernel/s390_ksyms.c linux.15p9/arch/s390/kernel/s390_ksyms.c
--- linux.vanilla/arch/s390/kernel/s390_ksyms.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/arch/s390/kernel/s390_ksyms.c	Thu Feb 17 13:31:37 2000
@@ -0,0 +1,26 @@
+/*
+ *  arch/s390/kernel/s390_ksyms.c
+ *
+ *  S390 version
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <asm/irq.h>
+#include <asm/string.h>
+
+EXPORT_SYMBOL(get_dev_info_by_irq);
+EXPORT_SYMBOL(get_dev_info_by_devno);
+EXPORT_SYMBOL(get_irq_by_devno);
+EXPORT_SYMBOL(get_devno_by_irq);
+EXPORT_SYMBOL(get_irq_first);
+EXPORT_SYMBOL(get_irq_next);
+EXPORT_SYMBOL(halt_IO);
+EXPORT_SYMBOL(resume_IO);
+EXPORT_SYMBOL(do_IO);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(init_mm);
+EXPORT_SYMBOL(_oi_bitmap);
+EXPORT_SYMBOL(_ni_bitmap);
+EXPORT_SYMBOL(_zb_findmap);
+EXPORT_SYMBOL(kernel_thread);
+EXPORT_SYMBOL(ioinfo);
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/kernel/s390io.c linux.15p9/arch/s390/kernel/s390io.c
--- linux.vanilla/arch/s390/kernel/s390io.c	Tue Jan  4 21:18:41 2000
+++ linux.15p9/arch/s390/kernel/s390io.c	Thu Feb 17 13:32:33 2000
@@ -3,7 +3,8 @@
  *   S/390 common I/O routines
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) 1999, 2000 IBM Deutschland Entwicklung GmbH,
+                               IBM Corporation
  *    Author(s): Ingo Adlung (adlung@de.ibm.com)
  */
 
@@ -27,9 +28,7 @@
 #include <asm/pgtable.h>
 #include <asm/delay.h>
 #include <asm/lowcore.h>
-
-#include "irq.h"
-#include "s390io.h"
+#include <asm/s390io.h>
 
 #undef CONFIG_DEBUG_IO    
 
@@ -37,16 +36,31 @@
 
 struct irqaction  init_IRQ_action;
 unsigned int      highest_subchannel;
-senseid_t         senseid[NR_IRQS];
-schib_t           schiblock[NR_IRQS];
-ioinfo_t          ioinfo[NR_IRQS];
+ioinfo_t         *ioinfo_head = NULL;
+ioinfo_t         *ioinfo_tail = NULL;
+ioinfo_t         *ioinfo[__MAX_SUBCHANNELS] = {
+	[0 ... (__MAX_SUBCHANNELS-1)] = INVALID_STORAGE_AREA
+};
 spinlock_t        sync_isc;                 // synchronous irq processing lock
 psw_t             io_sync_wait;             // wait PSW for sync IO, prot. by sync_isc
 psw_t             io_new_psw;               // save I/O new PSW, prot. by sync_isc
 int               cons_dev          = -1;   // identify console device
 int               init_IRQ_complete = 0;
+schib_t           init_schib;
 
-extern struct hw_interrupt_type no_irq_type;
+/*
+ * Dummy controller type for unused interrupts
+ */
+int  do_none(unsigned int irq, int cpu, struct pt_regs * regs) { return 0;}
+int  enable_none(unsigned int irq) { return(-ENODEV); }
+int  disable_none(unsigned int irq) { return(-ENODEV); }
+
+struct hw_interrupt_type no_irq_type = {
+	"none",
+	do_none,
+	enable_none,
+	disable_none
+};
 
 static void init_IRQ_handler( int irq, void *dev_id, struct pt_regs *regs);
 static int  s390_setup_irq(unsigned int irq, struct irqaction * new);
@@ -54,7 +68,7 @@
 static void s390_device_recognition( void);
 static int  s390_validate_subchannel( int irq);
 static int  s390_SenseID( int irq, senseid_t *sid);
-static int  s390_process_IRQ( unsigned int irq, unsigned int intparm);
+static int  s390_process_IRQ( unsigned int irq );
 
 extern int do_none(unsigned int irq, int cpu, struct pt_regs * regs);
 extern int enable_none(unsigned int irq);
@@ -63,7 +77,13 @@
 
 asmlinkage void do_IRQ( struct pt_regs regs,
                         unsigned int   irq,
-                        unsigned int   intparm );
+                        __u32          s390_intparm );
+
+//
+// fix me ! must be removed with 2.3.x and follow-up releases
+//
+static void * alloc_bootmem( unsigned long size);
+static unsigned long memory_start = 0;
 
 void s390_displayhex(char *str,void *ptr,s32 cnt);
 
@@ -73,6 +93,7 @@
 	u32	*currptr=(u32 *)ptr;
 
 	printk("\n%s\n",str);
+
 	for(cnt1=0;cnt1<cnt;cnt1+=16)
 	{
 		printk("%08X ",(u32)currptr);
@@ -94,7 +115,7 @@
 	int               retval;
 	struct irqaction *action;
 
-	if (irq >= NR_IRQS)
+	if (irq >= __MAX_SUBCHANNELS)
 		return -EINVAL;
 
 	if ( !handler || !dev_id )
@@ -147,7 +168,7 @@
 
 	unsigned int count = 0;
 
-	if ( irq >= NR_IRQS )
+	if ( irq >= __MAX_SUBCHANNELS || ioinfo[irq] == INVALID_STORAGE_AREA )
 	{
 		return;
 
@@ -167,37 +188,42 @@
 	 * disable the device and reset all IRQ info if
 	 *  the IRQ is actually owned by the handler ...
 	 */
-	if ( irq_desc[irq].action )
+	if ( ioinfo[irq]->irq_desc.action )
 	{
-		if ( irq_desc[irq].action->dev_id == dev_id ||
-		     dev_id == REIPL_DEVID_MAGIC )
+		if (    (dev_id == ioinfo[irq]->irq_desc.action->dev_id  )
+		     || (dev_id == (devstat_t *)REIPL_DEVID_MAGIC) )
 		{
-			ioinfo[irq].ui.flags.unready = 1; /* start deregister */
+			/* start deregister */
+			ioinfo[irq]->ui.flags.unready = 1;
 
 			do
          {
-				ret = irq_desc[irq].handler->disable(irq);
+				ret = ioinfo[irq]->irq_desc.handler->disable(irq);
 
 				count++;
 
 				if ( count == 3 )
 				{
-					panic( "free_irq() - device busy, retry count exceeded\n");
+					printk( KERN_CRIT"free_irq(%04X) "
+					       "- device %04X busy, retry "
+					       "count exceeded\n",
+					       irq,
+					       ioinfo[irq]->devstat.devno);
 
 				} /* endif */
 
 			} while ( ret == -EBUSY );
 
 			if ( init_IRQ_complete )
-            kfree( irq_desc[irq].action );
+				kfree( ioinfo[irq]->irq_desc.action );
 
-			irq_desc[irq].action           = NULL;
-			ioinfo[irq].ui.flags.ready     = 0;
+			ioinfo[irq]->irq_desc.action  = NULL;
+			ioinfo[irq]->ui.flags.ready   = 0;
 
-			irq_desc[irq].handler->enable  = &enable_none;
-			irq_desc[irq].handler->disable = &disable_none;
+			ioinfo[irq]->irq_desc.handler->enable  = &enable_none;
+			ioinfo[irq]->irq_desc.handler->disable = &disable_none;
 
-			ioinfo[irq].ui.flags.unready   = 0; /* deregister ended */
+			ioinfo[irq]->ui.flags.unready = 0; /* deregister ended */
 
 			s390irq_spin_unlock_irqrestore( irq, flags);
 		}
@@ -228,14 +254,17 @@
 	unsigned long flags;
 	int           ret;
 
+	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+		return( -ENODEV);
+
 	s390irq_spin_lock_irqsave(irq, flags);
 
 	/*
 	 * At this point we may actually have a pending interrupt being active
 	 * on another CPU. So don't touch the IRQ_INPROGRESS bit..
 	 */
-	irq_desc[irq].status |= IRQ_DISABLED;
-	ret = irq_desc[irq].handler->disable(irq);
+	ioinfo[irq]->irq_desc.status |= IRQ_DISABLED;
+	ret = ioinfo[irq]->irq_desc.handler->disable(irq);
 	s390irq_spin_unlock_irqrestore(irq, flags);
 
 	synchronize_irq();
@@ -248,10 +277,13 @@
 	unsigned long flags;
 	int           ret;
 
+	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+		return( -ENODEV);
+
 	s390irq_spin_lock_irqsave(irq, flags);
 
-	irq_desc[irq].status = 0;
-	ret                  = irq_desc[irq].handler->enable(irq);
+	ioinfo[irq]->irq_desc.status = 0;
+	ret = ioinfo[irq]->irq_desc.handler->enable(irq);
 
 	s390irq_spin_unlock_irqrestore(irq, flags);
 
@@ -273,18 +305,21 @@
 
    } /* endif */
 
+	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+		return( -ENODEV);
+
 	/*
 	 * If a previous disable request is pending we reset it. However, this
 	 *  status implies that the device may (still) be not-operational.
 	 */
-	if (  ioinfo[irq].ui.flags.d_disable )
+	if (  ioinfo[irq]->ui.flags.d_disable )
 	{
-		ioinfo[irq].ui.flags.d_disable = 0;
+		ioinfo[irq]->ui.flags.d_disable = 0;
 		ret                            = 0;
 	}
 	else
 	{
-		ccode = stsch(irq, &(ioinfo[irq].schib) );
+		ccode = stsch(irq, &(ioinfo[irq]->schib) );
 
       if ( ccode )
       {
@@ -292,11 +327,11 @@
       }
       else
       {
-   		ioinfo[irq].schib.pmcw.ena = 1;
+			ioinfo[irq]->schib.pmcw.ena = 1;
 
          do
          {
-            ccode = msch( irq, &(ioinfo[irq].schib) );
+				ccode = msch( irq, &(ioinfo[irq]->schib) );
 
    		   switch (ccode) {
             case 0:
@@ -305,30 +340,38 @@
 
             case 1:
 	   			/*
-		   		 * very bad, requires interrupt alike processing, where
-			   	 *  "rbh" is a dummy parameter for interface compatibility
-				    *  only. Bottom-half handling cannot be required as
-   				 *  this must be an unsolicited interrupt (!busy).
+					 * very bad, requires interrupt alike
+					 *  processing, where "rbh" is a dummy
+					 *  parameter for interface compatibility
+					 *  only. Bottom-half handling cannot be
+					 *  required as this must be an
+					 *  unsolicited interrupt (!busy).
 	   			 */
 
-		   	   ioinfo[irq].ui.flags.s_pend = 1;
+					ioinfo[irq]->ui.flags.s_pend = 1;
 
-		   		s390_process_IRQ( irq, 0 );
+					s390_process_IRQ( irq );
 
-		   	   ioinfo[irq].ui.flags.s_pend = 0;
+					ioinfo[irq]->ui.flags.s_pend = 0;
 
-			   	ret = -EIO;    /* might be overwritten on ... */
-                              /* ... re-driving the msch()   */
+					ret = -EIO;    /* might be overwritten */
+					               /* ... on re-driving    */
+					               /* ... the msch() */
                retry--;
                break;
 
             case 3:
-		   	   ioinfo[irq].ui.flags.oper = 0;
+					ioinfo[irq]->ui.flags.oper = 0;
                ret = -ENODEV;
                break;
 
             default:
-               panic( "enable_subchannel() : ccode 2 on msch() received !\n");
+					printk( KERN_CRIT"enable_subchannel(%04X) "
+					        " : ccode 2 on msch() for device "
+					        "%04X received !\n",
+					        irq,
+					        ioinfo[irq]->devstat.devno);
+
                ret = -ENODEV; // never reached
             }
 
@@ -355,7 +398,11 @@
 	{
 		ret = -ENODEV;
 	}
-	else if ( ioinfo[irq].ui.flags.busy )
+	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+	{
+		return( -ENODEV);
+   }
+	else if ( ioinfo[irq]->ui.flags.busy )
 	{
 		/*
 		 * the disable function must not be called while there are
@@ -370,22 +417,22 @@
 		 *  disabling when the next interrupt occurs - unless the
 		 *  irq is re-requested prior to the interrupt to occur.
 		 */
-		cc = stsch(irq, &(ioinfo[irq].schib) );
+		cc = stsch(irq, &(ioinfo[irq]->schib) );
 
 		if ( cc == 3 )
 		{
-			ioinfo[irq].ui.flags.oper      = 0;
-			ioinfo[irq].ui.flags.d_disable = 1;
+			ioinfo[irq]->ui.flags.oper      = 0;
+			ioinfo[irq]->ui.flags.d_disable = 1;
 
 			ret = 0;
 		}
 		else // cc == 0
 		{
-			ioinfo[irq].schib.pmcw.ena = 0;
+			ioinfo[irq]->schib.pmcw.ena = 0;
 
          do
          {
-   			cc = msch( irq, &(ioinfo[irq].schib) );
+				cc = msch( irq, &(ioinfo[irq]->schib) );
 
 	   		switch (cc) {
 		   	case 0 :
@@ -394,19 +441,20 @@
 
    			case 1 :
 	   			/*
-		   		 * very bad, requires interrupt alike processing, where
-			   	 *  "rbh" is a dummy parameter for interface compatibility
-				    *  only. Bottom-half handling cannot be required as
-   				 *  this must be an unsolicited interrupt (!busy).
-	   			 */
-		   	   ioinfo[irq].ui.flags.s_pend = 1;
-
-		   		s390_process_IRQ( irq, 0 );
-
-		   	   ioinfo[irq].ui.flags.s_pend = 0;
-
-			   	ret = -EBUSY;  /* might be overwritten on ... */
-                              /* ... re-driving the msch()   */
+					 * very bad, requires interrupt alike
+  					 *  processing, where "rbh" is a dummy
+					 *  parm for interface compatibility
+					 *  only. Bottom-half handling cannot
+					 *  be required as this must be an
+					 *  unsolicited interrupt (!busy).
+					 */
+					ioinfo[irq]->ui.flags.s_pend = 1;
+					s390_process_IRQ( irq );
+					ioinfo[irq]->ui.flags.s_pend = 0;
+
+					ret = -EBUSY;  /* might be overwritten  */
+					               /* ... on re-driving the */
+					               /* ... msch() call       */
                retry--;
 				   break;
 
@@ -414,22 +462,28 @@
 	   			/*
 		   		 * *** must not occur !                                    ***
 			   	 * ***                                                     ***
-				    * *** indicates our internal interrupt accounting is out  ***
+					 * *** indicates our internal        ***
+					 * *** interrupt accounting is out   ***
    				 * ***  of sync ===> panic()                               ***
 	   			 */
-		   		panic( "disable_subchannel() : unexpected busy condition !\n");
+					printk( KERN_CRIT"disable_subchannel(%04X) "
+					        "- unexpected busy condition for "
+							  "device %04X received !\n",
+					        irq,
+					        ioinfo[irq]->devstat.devno);
                ret = -ENODEV; // never reached
 				   break;
 
    			case 3 :
 	   			/*
-		   		 * should hardly occur but not impossible ...
+					 * should hardly occur ?!
 			   	 */
-   				ioinfo[irq].ui.flags.oper      = 0;
-	   			ioinfo[irq].ui.flags.d_disable = 1;
+					ioinfo[irq]->ui.flags.oper      = 0;
+					ioinfo[irq]->ui.flags.d_disable = 1;
 
-		   		ret = 0; /* if the device has gone we don't ... */
-                        /* ... need to disable it anymore !    */
+					ret = 0; /* if the device has gone we */
+					         /* ... don't need to disable */
+					         /* ... it anymore !    */
 			   	break;
 
    			default :
@@ -454,22 +508,27 @@
 	unsigned long      flags;
 	int                rc = 0;
 
+	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+	{
+		return( -ENODEV);
+   }
+
 	/*
 	 * The following block of code has to be executed atomically
 	 */
 	s390irq_spin_lock_irqsave( irq, flags);
 
-	if ( irq_desc[irq].action == NULL )
+	if ( ioinfo[irq]->irq_desc.action == NULL )
 	{
-      irq_desc[irq].action           = new;
-		irq_desc[irq].status           = 0;
-		irq_desc[irq].handler->enable  = &enable_subchannel;
-		irq_desc[irq].handler->disable = &disable_subchannel;
-		irq_desc[irq].handler->handle  = &handle_IRQ_event;
+		ioinfo[irq]->irq_desc.action           = new;
+		ioinfo[irq]->irq_desc.status           = 0;
+		ioinfo[irq]->irq_desc.handler->enable  = &enable_subchannel;
+		ioinfo[irq]->irq_desc.handler->disable = &disable_subchannel;
+		ioinfo[irq]->irq_desc.handler->handle  = &handle_IRQ_event;
 
-		ioinfo[irq].ui.flags.ready     = 1;
+		ioinfo[irq]->ui.flags.ready            = 1;
 
-		irq_desc[irq].handler->enable(irq);
+		ioinfo[irq]->irq_desc.handler->enable(irq);
 	}
 	else
 	{
@@ -486,19 +545,26 @@
 	return( rc);
 }
 
+/*
+ * we need boot memory during init processing but don't have
+ *  kmalloc() available yet. Linux 2.3 introduced alloc_bootmem()
+ *  we kind of emulate for the time being.
+ */
+static void * alloc_bootmem( unsigned long size)
+{
+   void * ret = (void *)memory_start;
+
+   memory_start += size;
 
-void s390_init_IRQ( void )
+   return( ret );
+}
+
+unsigned long s390_init_IRQ( unsigned long memstart)
 {
 	unsigned long flags;     /* PSW flags */
 	long          cr6 __attribute__ ((aligned (8)));
-	int           irq;       /* counter for I/O subchannels */
 
-	for (irq=0; irq<NR_IRQS; irq++)
-	{
-		irq_desc[irq].status = 0;
-		irq_desc[irq].handler = &no_irq_type;
-
-	} /* endfor */
+        memory_start = memstart;
 
 	// Hopefully bh_count's will get set when we copy the prefix lowcore
 	// structure to other CPI's ( DJB )
@@ -536,6 +602,8 @@
    init_IRQ_complete = 1;
 
 	__restore_flags(flags);
+
+        return( memory_start );
 }
 
 
@@ -549,9 +617,9 @@
 
 
 int s390_start_IO( int            irq,      /* IRQ */
-                   ccw1_t        *cpa,      /* logical channel program addr */
-                   unsigned long  intparm,  /* interruption parameter */
-                   unsigned char  lpm,      /* logical path mask */
+                   ccw1_t        *cpa,      /* logical channel prog addr */
+                   unsigned long  user_intparm,  /* interruption parameter */
+                   __u8           lpm,      /* logical path mask */
                    unsigned long  flag)     /* flags */
 {
 	int            ccode;
@@ -570,30 +638,29 @@
 
 	} /* endif */
 
-	memset( &(ioinfo[irq].orb), '\0', sizeof( orb_t) );
+	memset( &(ioinfo[irq]->orb), '\0', sizeof( orb_t) );
 
 	/*
 	 * setup ORB
 	 */
-	ioinfo[irq].orb.intparm = intparm;
-	ioinfo[irq].orb.fmt     = 1;
+	ioinfo[irq]->orb.fmt     = 1;
 
-	ioinfo[irq].orb.pfch = !(flag & DOIO_DENY_PREFETCH);
-	ioinfo[irq].orb.spnd =  (flag & DOIO_ALLOW_SUSPEND);
-	ioinfo[irq].orb.ssic =  (    (flag & DOIO_ALLOW_SUSPEND )
+	ioinfo[irq]->orb.pfch = !(flag & DOIO_DENY_PREFETCH);
+	ioinfo[irq]->orb.spnd =  (flag & DOIO_ALLOW_SUSPEND);
+	ioinfo[irq]->orb.ssic =  (    (flag & DOIO_ALLOW_SUSPEND )
 	                          && (flag & DOIO_SUPPRESS_INTER) );
 
 	if ( flag & DOIO_VALID_LPM )
 	{
-		ioinfo[irq].orb.lpm = lpm;
+		ioinfo[irq]->orb.lpm = lpm;
 	}
 	else
 	{
-		ioinfo[irq].orb.lpm = ioinfo[irq].schib.pmcw.pam;
+		ioinfo[irq]->orb.lpm = ioinfo[irq]->schib.pmcw.pam;
 
 	} /* endif */
 
-	ioinfo[irq].orb.cpa = (ccw1_t *)virt_to_phys( cpa);
+	ioinfo[irq]->orb.cpa = (ccw1_t *)virt_to_phys( cpa);
 
 	/*
 	 * If sync processing was requested we lock the sync ISC, modify the
@@ -605,7 +672,7 @@
 		//
 		// check whether we run recursively (sense processing)
 		//
-		if ( !ioinfo[irq].ui.flags.syncio )
+		if ( !ioinfo[irq]->ui.flags.syncio )
 		{
 			spin_lock_irqsave( &sync_isc, psw_flags);
  	
@@ -614,14 +681,12 @@
 			if ( ret )
 			{
 				spin_unlock_irqrestore( &sync_isc, psw_flags);
- 		
-				// sigh, there should be a single exit point only ...
 				return( ret);
 			}
 			else
 			{
-				sync_isc_locked             = 1; // local setting
-				ioinfo[irq].ui.flags.syncio = 1; // global setting
+				sync_isc_locked              = 1; // local
+				ioinfo[irq]->ui.flags.syncio = 1; // global
 
 			} /* endif */  	
  	
@@ -632,37 +697,37 @@
 	/*
 	 * Issue "Start subchannel" and process condition code
 	 */
-	ccode = ssch( irq, &(ioinfo[irq].orb) );
+	ccode = ssch( irq, &(ioinfo[irq]->orb) );
 
 	switch ( ccode ) {
 	case 0:
 
-      if ( !ioinfo[irq].ui.flags.w4sense )
+		if ( !ioinfo[irq]->ui.flags.w4sense )
       {
 			/*
-			 * initialize the device driver specific devstat irb area
+			 * init the device driver specific devstat irb area
 			 *
-			 * Note : don´t clear saved irb information in case of sense !
+			 * Note : don´t clear saved irb info in case of sense !
 			 */
-			memset( &((devstat_t *) irq_desc[irq].action->dev_id)->ii.irb,
+			memset( &((devstat_t *)ioinfo[irq]->irq_desc.action->dev_id)->ii.irb,
 				'\0', sizeof( irb_t) );
 		} /* endif */
 
 		/*
 		 * initialize device status information
 		 */
-		ioinfo[irq].ui.flags.busy   = 1;
-		ioinfo[irq].ui.flags.doio   = 1;
+		ioinfo[irq]->ui.flags.busy   = 1;
+		ioinfo[irq]->ui.flags.doio   = 1;
 
-		ioinfo[irq].devstat.intparm = intparm;
-		ioinfo[irq].devstat.cstat   = 0;
-		ioinfo[irq].devstat.dstat   = 0;
-		ioinfo[irq].devstat.lpum    = 0;
-		ioinfo[irq].devstat.flag    = DEVSTAT_START_FUNCTION;
-		ioinfo[irq].devstat.scnt    = 0;
+		ioinfo[irq]->u_intparm       = user_intparm;
+		ioinfo[irq]->devstat.cstat   = 0;
+		ioinfo[irq]->devstat.dstat   = 0;
+		ioinfo[irq]->devstat.lpum    = 0;
+		ioinfo[irq]->devstat.flag    = DEVSTAT_START_FUNCTION;
+		ioinfo[irq]->devstat.scnt    = 0;
 
-		ioinfo[irq].ui.flags.fast   = 0;
-		ioinfo[irq].ui.flags.repall = 0;
+		ioinfo[irq]->ui.flags.fast   = 0;
+		ioinfo[irq]->ui.flags.repall = 0;
 
 		/*
 		 * Check for either early (FAST) notification requests
@@ -671,21 +736,21 @@
 		 */
 		if ( flag & DOIO_RETURN_CHAN_END )
 		{
-			ioinfo[irq].ui.flags.fast = 1;
+			ioinfo[irq]->ui.flags.fast = 1;
 		}
 		else if ( flag & DOIO_REPORT_ALL )
 		{
-			ioinfo[irq].ui.flags.repall = 1;
+			ioinfo[irq]->ui.flags.repall = 1;
 
 		} /* endif */
 
 		if ( flag & DOIO_VALID_LPM )
 		{
-			ioinfo[irq].lpm = lpm;         /* specific path */
+			ioinfo[irq]->lpm = lpm;         /* specific path */
 		}
 		else
 		{
-			ioinfo[irq].lpm = 0xff;        /* any path */
+			ioinfo[irq]->lpm = 0xff;        /* any path */
 
 		} /* endif */
 
@@ -700,7 +765,7 @@
 		if ( flag & DOIO_WAIT_FOR_INTERRUPT )
 		{
 			int              io_sub;
-			int              io_parm;
+			__u32            io_parm;
          psw_t            io_new_psw;
          int              ccode;
 
@@ -708,11 +773,12 @@
          struct _lowcore *lc    = NULL;
 
          /*
-          * We shouldn't perform a TPI loop, waiting for an interrupt
-          *  to occur, but should load a WAIT PSW instead. Otherwise
-          *  we may keep the channel subsystem busy, not able to present
-          *  the interrupt. When our sync. interrupt arrived we reset
-          *  the I/O old PSW to its original value.
+			 * We shouldn't perform a TPI loop, waiting for an
+			 *  interrupt to occur, but should load a WAIT PSW
+			 *  instead. Otherwise we may keep the channel subsystem
+			 *  busy, not able to present the interrupt. When our
+			 *  sync. interrupt arrived we reset the I/O old PSW to
+			 *  its original value.
           */
          memcpy( &io_new_psw, &lc->io_new_psw, sizeof(psw_t));
 
@@ -746,27 +812,28 @@
 					break;
 			} /* endswitch */
 
-	      io_sync_wait.addr = (unsigned long) &&io_wakeup | 0x80000000L;
+			io_sync_wait.addr =   (unsigned long) &&io_wakeup
+					    | 0x80000000L;
 
 			/*
 			 * Martin didn't like modifying the new PSW, now we take
 			 *  a fast exit in do_IRQ() instead
 			 */
-			*(int *)__LC_SYNC_IO_WORD  = 1;
+			*(__u32 *)__LC_SYNC_IO_WORD  = 1;
 
 			do
 			{
 
       		asm volatile ( "lpsw %0" : : "m" (io_sync_wait) );
 io_wakeup:
-				io_parm = *(int *)__LC_IO_INT_PARM;
-				io_sub  = (int)*(short *)__LC_SUBCHANNEL_NR;
+				io_parm = *(__u32 *)__LC_IO_INT_PARM;
+				io_sub  = (__u32)*(__u16 *)__LC_SUBCHANNEL_NR;
 
-				ready = s390_process_IRQ( io_sub, io_parm);
+				ready = s390_process_IRQ( io_sub );
 
 			} while ( !((io_sub == irq) && (ready == 1)) );
 
-			*(int *)__LC_SYNC_IO_WORD = 0;
+			*(__u32 *)__LC_SYNC_IO_WORD = 0;
 
 		} /* endif */
 
@@ -774,35 +841,35 @@
 
 	case 1 :            /* status pending */
 
-		ioinfo[irq].devstat.flag |= DEVSTAT_STATUS_PENDING;
+		ioinfo[irq]->devstat.flag |= DEVSTAT_STATUS_PENDING;
 
 		/*
 		 * initialize the device driver specific devstat irb area
 		 */
-		memset( &((devstat_t *) irq_desc[irq].action->dev_id)->ii.irb,
+		memset( &((devstat_t *) ioinfo[irq]->irq_desc.action->dev_id)->ii.irb,
 		        '\0', sizeof( irb_t) );
 
       /*
        * Let the common interrupt handler process the pending status.
        *  However, we must avoid calling the user action handler, as
-       *  it won't be prepared to handle a pending status during do_IO()
-       *  processing inline. This also implies that process_IRQ must
-       *  terminate synchronously - especially if device sensing is
-       *  required.
-       */
-      ioinfo[irq].ui.flags.s_pend   = 1;
-		ioinfo[irq].ui.flags.busy     = 1;
-		ioinfo[irq].ui.flags.doio     = 1;
-
-	   s390_process_IRQ( irq, intparm );
-
-      ioinfo[irq].ui.flags.s_pend   = 0;
-		ioinfo[irq].ui.flags.busy     = 0;
-		ioinfo[irq].ui.flags.doio     = 0;
-		ioinfo[irq].ui.flags.repall   = 0;
-		ioinfo[irq].ui.flags.w4final  = 0;
+		 *  it won't be prepared to handle a pending status during
+		 *  do_IO() processing inline. This also implies that process_IRQ
+		 *  must terminate synchronously - especially if device sensing
+		 *  is required.
+		 */
+		ioinfo[irq]->ui.flags.s_pend   = 1;
+		ioinfo[irq]->ui.flags.busy     = 1;
+		ioinfo[irq]->ui.flags.doio     = 1;
+
+		s390_process_IRQ( irq );
+
+		ioinfo[irq]->ui.flags.s_pend   = 0;
+		ioinfo[irq]->ui.flags.busy     = 0;
+		ioinfo[irq]->ui.flags.doio     = 0;
+		ioinfo[irq]->ui.flags.repall   = 0;
+		ioinfo[irq]->ui.flags.w4final  = 0;
 
-		ioinfo[irq].devstat.flag     |= DEVSTAT_FINAL_STATUS;
+		ioinfo[irq]->devstat.flag     |= DEVSTAT_FINAL_STATUS;
 
 		/*
 		 * In multipath mode a condition code 3 implies the last path
@@ -811,47 +878,48 @@
 		 *  results in return code EIO as well as 3 with another path
 		 *  than the one used (i.e. path available mask is non-zero).
 		 */
-		if ( ioinfo[irq].devstat.ii.irb.scsw.cc == 3 )
+		if ( ioinfo[irq]->devstat.ii.irb.scsw.cc == 3 )
 		{
 			ret                        = -ENODEV;
-			ioinfo[irq].devstat.flag  |= DEVSTAT_NOT_OPER;
-			ioinfo[irq].ui.flags.oper  = 0;
+			ioinfo[irq]->devstat.flag  |= DEVSTAT_NOT_OPER;
+			ioinfo[irq]->ui.flags.oper  = 0;
 
 #if CONFIG_DEBUG_IO
       	{
 	      char buffer[80];
 
-		   stsch(irq, &(ioinfo[irq].schib) );
+			stsch(irq, &(ioinfo[irq]->schib) );
 
    	   sprintf( buffer, "s390_start_IO(%04X) - irb for "
 			         "device %04X, after status pending\n",
 			         irq,
-			         ioinfo[irq].devstat.devno );
+			         ioinfo[irq]->devstat.devno );
 
 			s390_displayhex( buffer,
-			                 &(ioinfo[irq].devstat.ii.irb) ,
+			                 &(ioinfo[irq]->devstat.ii.irb) ,
 			                 sizeof(irb_t));
 
    	   sprintf( buffer, "s390_start_IO(%04X) - schib for "
 			         "device %04X, after status pending\n",
 			         irq,
-			         ioinfo[irq].devstat.devno );
+			         ioinfo[irq]->devstat.devno );
 
 			s390_displayhex( buffer,
-			                 &(ioinfo[irq].schib) ,
+			                 &(ioinfo[irq]->schib) ,
 			                 sizeof(schib_t));
 
 
-			if (ioinfo[irq].devstat.flag  & DEVSTAT_FLAG_SENSE_AVAIL)
+			if (ioinfo[irq]->devstat.flag & DEVSTAT_FLAG_SENSE_AVAIL)
          {
-	   	   sprintf( buffer, "s390_start_IO(%04X) - sense data for "
+				sprintf( buffer, "s390_start_IO(%04X) - sense "
+				         "data for "
 				         "device %04X, after status pending\n",
 				         irq,
-				         ioinfo[irq].devstat.devno );
+				         ioinfo[irq]->devstat.devno );
 
 				s390_displayhex( buffer,
-     ((devstat_t *)(irq_desc[irq].action->dev_id))->ii.sense.data,
-     ((devstat_t *)(irq_desc[irq].action->dev_id))->rescnt);
+		((devstat_t *)(ioinfo[irq]->irq_desc.action->dev_id))->ii.sense.data,
+		((devstat_t *)(ioinfo[irq]->irq_desc.action->dev_id))->rescnt);
 
          }
       	}
@@ -860,8 +928,8 @@
 		else
 		{
 			ret                        = -EIO;
-			ioinfo[irq].devstat.flag  &= ~DEVSTAT_NOT_OPER;
-			ioinfo[irq].ui.flags.oper  = 1;
+			ioinfo[irq]->devstat.flag  &= ~DEVSTAT_NOT_OPER;
+			ioinfo[irq]->ui.flags.oper  = 1;
 
 		} /* endif */
 
@@ -875,28 +943,27 @@
 	default:            /* device not operational */
 
 		ret                          = -ENODEV;
-		ioinfo[irq].ui.flags.oper    = 0;
+		ioinfo[irq]->ui.flags.oper    = 0;
 
-		ioinfo[irq].devstat.flag    |= DEVSTAT_NOT_OPER;
-		ioinfo[irq].devstat.intparm  = intparm;
+		ioinfo[irq]->devstat.flag    |= DEVSTAT_NOT_OPER;
 
-		memcpy( irq_desc[irq].action->dev_id,
-			&(ioinfo[irq].devstat),
+		memcpy( ioinfo[irq]->irq_desc.action->dev_id,
+			&(ioinfo[irq]->devstat),
 			sizeof( devstat_t) );
 
 #if CONFIG_DEBUG_IO
       	{
 	      char buffer[80];
 
-		   stsch(irq, &(ioinfo[irq].schib) );
+   			stsch(irq, &(ioinfo[irq]->schib) );
 
    	   sprintf( buffer, "s390_start_IO(%04X) - schib for "
 			         "device %04X, after 'not oper' status\n",
 			         irq,
-			         ioinfo[irq].devstat.devno );
+			         ioinfo[irq]->devstat.devno );
 
 			s390_displayhex( buffer,
-			                 &(ioinfo[irq].schib),
+			                 &(ioinfo[irq]->schib),
 			                 sizeof(schib_t));
       	}
 #endif
@@ -912,7 +979,7 @@
 		spin_unlock_irqrestore( &sync_isc, psw_flags);
 
 		sync_isc_locked             = 0;    // local setting
-	   ioinfo[irq].ui.flags.syncio = 0;    // global setting
+		ioinfo[irq]->ui.flags.syncio = 0;    // global setting
 
 	} /* endif */
 
@@ -921,8 +988,8 @@
 
 int do_IO( int            irq,          /* IRQ */
            ccw1_t        *cpa,          /* channel program address */
-           unsigned long  intparm,      /* interruption parameter */
-           unsigned char  lpm,          /* logical path mask */
+           unsigned long  user_intparm, /* interruption parameter */
+           __u8           lpm,          /* logical path mask */
            unsigned long  flag)         /* flags : see above */
 {
 	int ret = 0;
@@ -933,8 +1000,13 @@
 
 	} /* endif */
 
+	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+	{
+		return( -ENODEV);
+   }
+
 	/* handler registered ?    */
-	if ( !ioinfo[irq].ui.flags.ready )
+	if ( !ioinfo[irq]->ui.flags.ready )
 	{
 		return( -ENODEV );
 
@@ -944,27 +1016,28 @@
 	 * Note: We ignore the device operational status - if not operational,
 	 *        the SSCH will lead to an -ENODEV condition ...
 	 */
-	if ( !ioinfo[irq].ui.flags.busy )         /* last I/O completed ? */
+	if ( !ioinfo[irq]->ui.flags.busy )         /* last I/O completed ? */
 	{
-		ret = s390_start_IO( irq, cpa, intparm, lpm, flag);
+		ret = s390_start_IO( irq, cpa, user_intparm, lpm, flag);
 	}
-	else if ( ioinfo[irq].ui.flags.fast )
+	else if ( ioinfo[irq]->ui.flags.fast )
 	{
 		/*
-		 * If primary status was received and ending status is missing, the
-		 *  device driver won't be notified on the ending status if early
-		 *  (fast) interrupt notification was requested. Therefore we have
-		 *  to queue the next incoming request. If halt_IO() is issued while
-		 *  there is a request queued, a HSCH needs to be issued and the queued
-		 *  request must be deleted but its intparm must be returned (see
-		 *  halt_IO() processing)
+		 * If primary status was received and ending status is missing,
+		 *  the device driver won't be notified on the ending status
+		 *  if early (fast) interrupt notification was requested.
+		 *  Therefore we have to queue the next incoming request. If
+		 *  halt_IO() is issued while there is a request queued, a HSCH
+		 *  needs to be issued and the queued request must be deleted
+		 *  but its intparm must be returned (see halt_IO() processing)
 		 */
-		if ( ioinfo[irq].ui.flags.w4final && !ioinfo[irq].ui.flags.doio_q )
+		if (     ioinfo[irq]->ui.flags.w4final
+           && !ioinfo[irq]->ui.flags.doio_q )
 		{
-			ioinfo[irq].qflag    = flag;
-			ioinfo[irq].qcpa     = cpa;
-			ioinfo[irq].qintparm = intparm;
-			ioinfo[irq].qlpm     = lpm;
+			ioinfo[irq]->qflag    = flag;
+			ioinfo[irq]->qcpa     = cpa;
+			ioinfo[irq]->qintparm = user_intparm;
+			ioinfo[irq]->qlpm     = lpm;
 		}
 		else
 		{
@@ -995,10 +1068,15 @@
 
 	} /* endif */
 
+	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+	{
+		return( -ENODEV);
+   }
+
 	/*
 	 * We allow for 'resume' requests only for active I/O operations
 	 */
-	if ( ioinfo[irq].ui.flags.busy )
+	if ( ioinfo[irq]->ui.flags.busy )
 	{
 		int ccode;
 
@@ -1009,8 +1087,7 @@
 				break;
 
 			case 1 :
-		   	s390_process_IRQ( irq,
-				                  ioinfo[irq].devstat.intparm );
+		  	s390_process_IRQ( irq );
 				ret = -EBUSY;
 				break;
 
@@ -1023,8 +1100,8 @@
 				 * useless to wait for request completion
 				 *  as device is no longer operational !
 				 */
-				ioinfo[irq].ui.flags.oper = 0;
-				ioinfo[irq].ui.flags.busy = 0;
+			ioinfo[irq]->ui.flags.oper = 0;
+			ioinfo[irq]->ui.flags.busy = 0;
 				ret                       = -ENODEV;
 				break;
 
@@ -1047,7 +1124,7 @@
  *       interrupt with the halt_IO() request.
  */
 int halt_IO( int          irq,
-             int          intparm,
+             unsigned long user_intparm,
              unsigned int flag)  /* possible DOIO_WAIT_FOR_INTERRUPT */
 {
 	int            ret;
@@ -1060,10 +1137,16 @@
 	{
 		ret = -ENODEV;
 	}
+
+	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+	{
+		return( -ENODEV);
+   }
+
 	/*
 	 * we only allow for halt_IO if the device has an I/O handler associated
 	 */
-	else if ( !ioinfo[irq].ui.flags.ready )
+	else if ( !ioinfo[irq]->ui.flags.ready )
 	{
 		ret = -ENODEV;
 	}
@@ -1071,30 +1154,31 @@
 	 * we ignore the halt_io() request if ending_status was received but
 	 *  a SENSE operation is waiting for completion.
 	 */
-	else if ( ioinfo[irq].ui.flags.w4sense )
+	else if ( ioinfo[irq]->ui.flags.w4sense )
 	{
 		ret = 0;
 	}
 	/*
 	 * We don't allow for halt_io with a sync do_IO() requests pending.
 	 */
-	else if ( ioinfo[irq].ui.flags.syncio )
+	else if ( ioinfo[irq]->ui.flags.syncio )
 	{
 		ret = -EBUSY;
 	}
 	else
 	{
 		/*
-		 * If sync processing was requested we lock the sync ISC, modify the
-		 *  device to present interrupts for this ISC only and switch the
-		 *  CPU to handle this ISC + the console ISC exclusively.
+		 * If sync processing was requested we lock the sync ISC,
+		 *  modify the device to present interrupts for this ISC only
+		 *  and switch the CPU to handle this ISC + the console ISC
+		 *  exclusively.
 		 */
 		if ( flag & DOIO_WAIT_FOR_INTERRUPT )
 		{
 			//
 			// check whether we run recursively (sense processing)
 			//
-			if ( !ioinfo[irq].ui.flags.syncio )
+			if ( !ioinfo[irq]->ui.flags.syncio )
 			{
 				spin_lock_irqsave( &sync_isc, psw_flags);
   	
@@ -1102,15 +1186,14 @@
 
 				if ( ret )
 				{
-					spin_unlock_irqrestore( &sync_isc, psw_flags);
-  		
-					// sigh, there should be a single exit point only ...
+					spin_unlock_irqrestore( &sync_isc,
+					                        psw_flags);
 					return( ret);
 				}
 				else
 				{
-					sync_isc_locked             = 1; // local setting
-					ioinfo[irq].ui.flags.syncio = 1; // global setting
+					sync_isc_locked              = 1; // local
+					ioinfo[irq]->ui.flags.syncio = 1; // global
 
 				} /* endif */  	
   	
@@ -1126,22 +1209,22 @@
 		switch ( ccode ) {
 		case 0:
 
-			ioinfo[irq].ui.flags.haltio = 1;
+			ioinfo[irq]->ui.flags.haltio = 1;
 
-			if ( !ioinfo[irq].ui.flags.doio )
+			if ( !ioinfo[irq]->ui.flags.doio )
 			{
-				ioinfo[irq].ui.flags.busy   = 1;
-				ioinfo[irq].devstat.intparm = intparm;
-				ioinfo[irq].devstat.cstat   = 0;
-				ioinfo[irq].devstat.dstat   = 0;
-				ioinfo[irq].devstat.lpum    = 0;
-				ioinfo[irq].devstat.flag    = DEVSTAT_HALT_FUNCTION;
-				ioinfo[irq].devstat.scnt    = 0;
+				ioinfo[irq]->ui.flags.busy   = 1;
+				ioinfo[irq]->u_intparm       = user_intparm;
+				ioinfo[irq]->devstat.cstat   = 0;
+				ioinfo[irq]->devstat.dstat   = 0;
+				ioinfo[irq]->devstat.lpum    = 0;
+				ioinfo[irq]->devstat.flag    = DEVSTAT_HALT_FUNCTION;
+				ioinfo[irq]->devstat.scnt    = 0;
 
 			}
 			else
 			{
-				ioinfo[irq].devstat.flag   |= DEVSTAT_HALT_FUNCTION;
+				ioinfo[irq]->devstat.flag   |= DEVSTAT_HALT_FUNCTION;
 
 			} /* endif */
 
@@ -1156,7 +1239,7 @@
 			if ( flag & DOIO_WAIT_FOR_INTERRUPT )
 			{
 				int              io_sub;
-				int              io_parm;
+				__u32            io_parm;
   		      psw_t            io_new_psw;
             int              ccode;
   	
@@ -1164,13 +1247,17 @@
 	         struct _lowcore *lc    = NULL;
 
 	         /*
-	          * We shouldn't perform a TPI loop, waiting for an interrupt
-	          *  to occur, but should load a WAIT PSW instead. Otherwise
-	          *  we may keep the channel subsystem busy, not able to present
-	          *  the interrupt. When our sync. interrupt arrived we reset
-	          *  the I/O old PSW to its original value.
-	          */
-	         memcpy( &io_new_psw, &lc->io_new_psw, sizeof(psw_t));
+				 * We shouldn't perform a TPI loop, waiting for
+				 *  an interrupt to occur, but should load a
+				 *  WAIT PSW instead. Otherwise we may keep the
+				 *  channel subsystem busy, not able to present
+				 *  the interrupt. When our sync. interrupt
+				 *  arrived we reset the I/O old PSW to its
+				 *  original value.
+				 */
+				memcpy( &io_new_psw,
+				        &lc->io_new_psw,
+				        sizeof(psw_t));
 
 				ccode = iac();
 
@@ -1202,27 +1289,28 @@
 						break;
 				} /* endswitch */
 
-		      io_sync_wait.addr = (unsigned long) &&hio_wakeup | 0x80000000L;
+				io_sync_wait.addr =   (unsigned long)&&hio_wakeup
+						    | 0x80000000L;
 
 				/*
 				 * Martin didn't like modifying the new PSW, now we take
 				 *  a fast exit in do_IRQ() instead
 				 */
-				*(int *)__LC_SYNC_IO_WORD  = 1;
+				*(__u32 *)__LC_SYNC_IO_WORD  = 1;
 
 				do
 				{
 
 	      		asm volatile ( "lpsw %0" : : "m" (io_sync_wait) );
 hio_wakeup:
-				   io_parm = *(int *)__LC_IO_INT_PARM;
-				   io_sub  = (int)*(__u16 *)__LC_SUBCHANNEL_NR;
+				   io_parm = *(__u32 *)__LC_IO_INT_PARM;
+				   io_sub  = (__u32)*(__u16 *)__LC_SUBCHANNEL_NR;
 
-				   ready = s390_process_IRQ( io_sub, io_parm);
+				   ready = s390_process_IRQ( io_sub );
 
 				} while ( !((io_sub == irq) && (ready == 1)) );
 
-				*(int *)__LC_SYNC_IO_WORD = 0;
+				*(__u32 *)__LC_SYNC_IO_WORD = 0;
 
 			} /* endif */
 
@@ -1231,54 +1319,55 @@
 
 		case 1 :            /* status pending */
 	
-			ioinfo[irq].devstat.flag |= DEVSTAT_STATUS_PENDING;
+			ioinfo[irq]->devstat.flag |= DEVSTAT_STATUS_PENDING;
 
 			/*
 			 * initialize the device driver specific devstat irb area
 			 */
-			memset( &((devstat_t *) irq_desc[irq].action->dev_id)->ii.irb,
+			memset( &((devstat_t *) ioinfo[irq]->irq_desc.action->dev_id)->ii.irb,
 			        '\0', sizeof( irb_t) );
 
 	      /*
-   	    * Let the common interrupt handler process the pending status.
-	       *  However, we must avoid calling the user action handler, as
-	       *  it won't be prepared to handle a pending status during do_IO()
-	       *  processing inline. This also implies that s390_process_IRQ must
-	       *  terminate synchronously - especially if device sensing is
-	       *  required.
-	       */
-	      ioinfo[irq].ui.flags.s_pend   = 1;
-			ioinfo[irq].ui.flags.busy     = 1;
-			ioinfo[irq].ui.flags.doio     = 1;
-
-		   s390_process_IRQ( irq, intparm );
-
-	      ioinfo[irq].ui.flags.s_pend   = 0;
-			ioinfo[irq].ui.flags.busy     = 0;
-			ioinfo[irq].ui.flags.doio     = 0;
-			ioinfo[irq].ui.flags.repall   = 0;
-			ioinfo[irq].ui.flags.w4final  = 0;
+			 * Let the common interrupt handler process the pending
+			 *  status. However, we must avoid calling the user
+			 *  action handler, as it won't be prepared to handle
+                        *  a pending status during do_IO() processing inline.
+			 *  This also implies that s390_process_IRQ must
+			 *  terminate synchronously - especially if device
+			 *  sensing is required.
+			 */
+			ioinfo[irq]->ui.flags.s_pend   = 1;
+			ioinfo[irq]->ui.flags.busy     = 1;
+			ioinfo[irq]->ui.flags.doio     = 1;
+
+			s390_process_IRQ( irq );
+			
+			ioinfo[irq]->ui.flags.s_pend   = 0;
+			ioinfo[irq]->ui.flags.busy     = 0;
+			ioinfo[irq]->ui.flags.doio     = 0;
+			ioinfo[irq]->ui.flags.repall   = 0;
+			ioinfo[irq]->ui.flags.w4final  = 0;
 
-			ioinfo[irq].devstat.flag     |= DEVSTAT_FINAL_STATUS;
+			ioinfo[irq]->devstat.flag     |= DEVSTAT_FINAL_STATUS;
 
 			/*
-			 * In multipath mode a condition code 3 implies the last path
-			 *  has gone, except we have previously restricted the I/O to
-			 *  a particular path. A condition code 1 (0 won't occur)
-			 *  results in return code EIO as well as 3 with another path
-			 *  than the one used (i.e. path available mask is non-zero).
+			 * In multipath mode a condition code 3 implies the last
+			 *  path has gone, except we have previously restricted
+			 *  the I/O to a particular path. A condition code 1
+			 *  (0 won't occur) results in return code EIO as well
+			 *  as 3 with another path than the one used (i.e. path available mask is non-zero).
 			 */
-			if ( ioinfo[irq].devstat.ii.irb.scsw.cc == 3 )
+			if ( ioinfo[irq]->devstat.ii.irb.scsw.cc == 3 )
 			{
 				ret                        = -ENODEV;
-				ioinfo[irq].devstat.flag  |= DEVSTAT_NOT_OPER;
-				ioinfo[irq].ui.flags.oper  = 0;
+				ioinfo[irq]->devstat.flag  |= DEVSTAT_NOT_OPER;
+				ioinfo[irq]->ui.flags.oper  = 0;
 			}
 			else
 			{
 				ret                        = -EIO;
-				ioinfo[irq].devstat.flag  &= ~DEVSTAT_NOT_OPER;
-				ioinfo[irq].ui.flags.oper  = 1;
+				ioinfo[irq]->devstat.flag  &= ~DEVSTAT_NOT_OPER;
+				ioinfo[irq]->ui.flags.oper  = 1;
 
 			} /* endif */
 
@@ -1300,7 +1389,7 @@
 	   	  && ( sync_isc_locked                ) )
 		{
 			sync_isc_locked             = 0;    // local setting
-		   ioinfo[irq].ui.flags.syncio = 0;    // global setting
+		   ioinfo[irq]->ui.flags.syncio = 0;    // global setting
   	
 			disable_cpu_sync_isc( irq );
   	
@@ -1324,7 +1413,7 @@
  */
 asmlinkage void do_IRQ( struct pt_regs regs,
                         unsigned int   irq,
-                        unsigned int   intparm )
+                        __u32          s390_intparm )
 {
 #ifdef CONFIG_FAST_IRQ
 	int			ccode;
@@ -1332,7 +1421,18 @@
 	int			new_irq;
 #endif
 	int			use_irq     = irq;
-	long			use_intparm = intparm;
+//	__u32       use_intparm = s390_intparm;
+
+	//
+	// fix me !!!
+	//
+	// We need to schedule device recognition, the interrupt stays
+	//  pending. We need to dynamically allocate an ioinfo structure.
+	//
+	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+	{
+		return;
+	}
 
 	/*
 	 * take fast exit if CPU is in sync. I/O state
@@ -1341,7 +1441,7 @@
 	 *       interrupts prior to return as this was the initial
 	 *       entry condition to synchronous I/O.
 	 */
- 	if (    *(int *)__LC_SYNC_IO_WORD )
+ 	if (    *(__u32 *)__LC_SYNC_IO_WORD )
 	{
 		regs.psw.mask &= ~(_PSW_WAIT_MASK_BIT | _PSW_IO_MASK_BIT);
 
@@ -1355,7 +1455,7 @@
 	do {
 #endif /*  CONFIG_FAST_IRQ */
 
-		s390_process_IRQ( use_irq, use_intparm);
+		s390_process_IRQ( use_irq );
 
 #ifdef CONFIG_FAST_IRQ
 
@@ -1368,7 +1468,7 @@
 			break;  	// no, leave ...
 
 		new_irq     = tpi_info.irq;
-		use_intparm = tpi_info.intparm;
+//		use_intparm = tpi_info.intparm;
 
 		/*
 		 * if the interrupt is for a different irq we
@@ -1403,8 +1503,7 @@
  * Returns: 0 - no ending status received, no further action taken
  *          1 - interrupt handler was called with ending status
  */
-int s390_process_IRQ( unsigned int   irq,
-                      unsigned int   intparm)
+int s390_process_IRQ( unsigned int irq )
 {
 	int               ccode;      /* condition code from tsch() operation */
 	int               irb_cc;     /* condition code from irb */
@@ -1418,11 +1517,13 @@
 	int               issense         = 0;
 	int               ending_status   = 0;
 	int               allow4handler   = 1;
+	int               chnchk          = 0;
+#if 0
 	int               cpu             = smp_processor_id();
 
 	kstat.irqs[cpu][irq]++;
-
-	action = irq_desc[irq].action;
+#endif
+	action = ioinfo[irq]->irq_desc.action;
 
 	/*
 	 * It might be possible that a device was not-oper. at the time
@@ -1432,9 +1533,13 @@
 	 */
 	if ( action == NULL )
 	{
-		if ( !ioinfo[irq].ui.flags.d_disable )
+		if ( !ioinfo[irq]->ui.flags.d_disable )
 		{
-			panic( "do_IRQ() : error, no irq_action available !\n");
+			printk( KERN_CRIT"s390_process_IRQ(%04X) "
+			        "- no interrupt handler registered"
+					  "for device %04X !\n",
+			        irq,
+			        ioinfo[irq]->devstat.devno);
 
 		} /* endif */
 
@@ -1458,40 +1563,40 @@
 	 *         issued for an idle device, the intparm must not
 	 *         be taken from lowcore, but from the devstat area.
 	 */
-	ccode = tsch( irq, &(ioinfo[irq].devstat.ii.irb) );
+	ccode = tsch( irq, &(ioinfo[irq]->devstat.ii.irb) );
 
 	//
 	// We must only accumulate the status if initiated by do_IO() or halt_IO()
 	//
-	if ( ioinfo[irq].ui.flags.busy )
+	if ( ioinfo[irq]->ui.flags.busy )
 	{
-		ioinfo[irq].devstat.dstat   |= ioinfo[irq].devstat.ii.irb.scsw.dstat;
-		ioinfo[irq].devstat.cstat   |= ioinfo[irq].devstat.ii.irb.scsw.cstat;
+		ioinfo[irq]->devstat.dstat |= ioinfo[irq]->devstat.ii.irb.scsw.dstat;
+		ioinfo[irq]->devstat.cstat |= ioinfo[irq]->devstat.ii.irb.scsw.cstat;
 	}
 	else
 	{
-		ioinfo[irq].devstat.dstat    = ioinfo[irq].devstat.ii.irb.scsw.dstat;
-		ioinfo[irq].devstat.cstat    = ioinfo[irq].devstat.ii.irb.scsw.cstat;
+		ioinfo[irq]->devstat.dstat  = ioinfo[irq]->devstat.ii.irb.scsw.dstat;
+		ioinfo[irq]->devstat.cstat  = ioinfo[irq]->devstat.ii.irb.scsw.cstat;
 
-		ioinfo[irq].devstat.flag     = 0;   // reset status flags
+		ioinfo[irq]->devstat.flag   = 0;   // reset status flags
 
 	} /* endif */
 
-	ioinfo[irq].devstat.lpum     = ioinfo[irq].devstat.ii.irb.esw.esw1.lpum;
+	ioinfo[irq]->devstat.lpum = ioinfo[irq]->devstat.ii.irb.esw.esw1.lpum;
 
-	if ( ioinfo[irq].ui.flags.doio)
+	if ( ioinfo[irq]->ui.flags.busy)
 	{
-		ioinfo[irq].devstat.intparm  = intparm;
+		ioinfo[irq]->devstat.intparm  = ioinfo[irq]->u_intparm;
 
 	} /* endif */
 
 	/*
 	 * reset device-busy bit if no longer set in irb
 	 */
-	if (   (ioinfo[irq].devstat.dstat & DEV_STAT_BUSY                   )
-	    && ((ioinfo[irq].devstat.ii.irb.scsw.dstat & DEV_STAT_BUSY) == 0))
+	if (   (ioinfo[irq]->devstat.dstat & DEV_STAT_BUSY                   )
+	    && ((ioinfo[irq]->devstat.ii.irb.scsw.dstat & DEV_STAT_BUSY) == 0))
 	{
-		ioinfo[irq].devstat.dstat &= ~DEV_STAT_BUSY;
+		ioinfo[irq]->devstat.dstat &= ~DEV_STAT_BUSY;
 
 	} /* endif */
 
@@ -1499,31 +1604,31 @@
 	 * Save residual count and CCW information in case primary and
 	 *  secondary status are presented with different interrupts.
 	 */
-	if ( ioinfo[irq].devstat.ii.irb.scsw.stctl & SCSW_STCTL_PRIM_STATUS )
+	if ( ioinfo[irq]->devstat.ii.irb.scsw.stctl & SCSW_STCTL_PRIM_STATUS )
 	{
-		ioinfo[irq].devstat.rescnt = ioinfo[irq].devstat.ii.irb.scsw.count;
+		ioinfo[irq]->devstat.rescnt = ioinfo[irq]->devstat.ii.irb.scsw.count;
 
 #if CONFIG_DEBUG_IO
       if ( irq != cons_dev )
          printk( "s390_process_IRQ( %04X ) : "
                  "residual count from irb after tsch() %d\n",
-                 irq, ioinfo[irq].devstat.rescnt );
+                 irq, ioinfo[irq]->devstat.rescnt );
 #endif
 	} /* endif */
 
-	if ( ioinfo[irq].devstat.ii.irb.scsw.cpa != 0 )
+	if ( ioinfo[irq]->devstat.ii.irb.scsw.cpa != 0 )
 	{
-		ioinfo[irq].devstat.cpa = ioinfo[irq].devstat.ii.irb.scsw.cpa;
+		ioinfo[irq]->devstat.cpa = ioinfo[irq]->devstat.ii.irb.scsw.cpa;
 
 	} /* endif */
 
-	irb_cc = ioinfo[irq].devstat.ii.irb.scsw.cc;
+	irb_cc = ioinfo[irq]->devstat.ii.irb.scsw.cc;
 
 	//
 	// check for any kind of channel or interface control check but don't
 	//  issue the message for the console device
 	//
-	if (    (ioinfo[irq].devstat.ii.irb.scsw.cstat
+	if (    (ioinfo[irq]->devstat.ii.irb.scsw.cstat
 	            & (  SCHN_STAT_CHN_DATA_CHK
 	               | SCHN_STAT_CHN_CTRL_CHK
 	               | SCHN_STAT_INTF_CTRL_CHK )       )
@@ -1531,22 +1636,24 @@
 	{
 		printk( "Channel-Check or Interface-Control-Check "
 		        "received\n"
-		        " ... device %X on subchannel %X, dev_stat "
-		        ": %X sch_stat : %X\n",
-		        ioinfo[irq].devstat.devno,
+		        " ... device %04X on subchannel %04X, dev_stat "
+		        ": %02X sch_stat : %02X\n",
+		        ioinfo[irq]->devstat.devno,
 		        irq,
-		        ioinfo[irq].devstat.dstat,
-		        ioinfo[irq].devstat.cstat);
+		        ioinfo[irq]->devstat.dstat,
+		        ioinfo[irq]->devstat.cstat);
+
+		chnchk = 1;
 
 	} /* endif */
 
-	issense = ioinfo[irq].devstat.ii.irb.esw.esw0.erw.cons;
+	issense = ioinfo[irq]->devstat.ii.irb.esw.esw0.erw.cons;
 
 	if ( issense )
 	{
-		ioinfo[irq].devstat.scnt  =
-		             ioinfo[irq].devstat.ii.irb.esw.esw0.erw.scnt;
-		ioinfo[irq].devstat.flag |=
+		ioinfo[irq]->devstat.scnt  =
+		             ioinfo[irq]->devstat.ii.irb.esw.esw0.erw.scnt;
+		ioinfo[irq]->devstat.flag |=
 		             DEVSTAT_FLAG_SENSE_AVAIL;
                   	
 		sdevstat = sizeof( devstat_t);
@@ -1555,7 +1662,7 @@
       if ( irq != cons_dev )
          printk( "s390_process_IRQ( %04X ) : "
                  "concurrent sense bytes avail %d\n",
-                 irq, ioinfo[irq].devstat.scnt );
+                 irq, ioinfo[irq]->devstat.scnt );
 #endif
 	}
 	else
@@ -1568,16 +1675,29 @@
 	switch ( irb_cc ) {
 	case 1:      /* status pending */
 
-		ioinfo[irq].devstat.flag |= DEVSTAT_STATUS_PENDING;
+		ioinfo[irq]->devstat.flag |= DEVSTAT_STATUS_PENDING;
 
 	case 0:      /* normal i/o interruption */
 
-		fctl  = ioinfo[irq].devstat.ii.irb.scsw.fctl;
-		stctl = ioinfo[irq].devstat.ii.irb.scsw.stctl;
-		actl  = ioinfo[irq].devstat.ii.irb.scsw.actl;
+		fctl  = ioinfo[irq]->devstat.ii.irb.scsw.fctl;
+		stctl = ioinfo[irq]->devstat.ii.irb.scsw.stctl;
+		actl  = ioinfo[irq]->devstat.ii.irb.scsw.actl;
+
+		if ( chnchk && (ioinfo[irq]->senseid.cu_type == 0x3088))
+		{
+			char buffer[80];
+   	
+			sprintf( buffer, "s390_process_IRQ(%04X) - irb for "
+			         "device %04X after channel check\n",
+			         irq,
+			         ioinfo[irq]->devstat.devno );
 
+			s390_displayhex( buffer,
+			                 &(ioinfo[irq]->devstat.ii.irb) ,
+			                 sizeof(irb_t));
+		} /* endif */
 			
-		ioinfo[irq].stctl |= stctl;
+		ioinfo[irq]->stctl |= stctl;
 
 		ending_status =    ( stctl & SCSW_STCTL_SEC_STATUS                          )
 			|| ( stctl == (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)         )
@@ -1597,25 +1717,25 @@
 #if CONFIG_DEBUG_IO
 		if (     ( irq != cons_dev                 )
 			 && !( stctl & SCSW_STCTL_ALERT_STATUS )
-			 &&  ( ioinfo[irq].ui.flags.busy == 0  ) )
+			 &&  ( ioinfo[irq]->ui.flags.busy == 0  ) )
 		{
 	      char buffer[80];
 
 			printk( "Unsolicited interrupt received for device %04X on subchannel %04X\n"
 				" ... device status : %02X subchannel status : %02X\n",
-				ioinfo[irq].devstat.devno,
+				ioinfo[irq]->devstat.devno,
 				irq,
-				ioinfo[irq].devstat.dstat,
-				ioinfo[irq].devstat.cstat);
+				ioinfo[irq]->devstat.dstat,
+				ioinfo[irq]->devstat.cstat);
 
    	   sprintf( buffer, "s390_process_IRQ(%04X) - irb for "
 			         "device %04X, ending_status %d\n",
 			         irq,
-			         ioinfo[irq].devstat.devno,
+			         ioinfo[irq]->devstat.devno,
 		   	      ending_status);
 
 			s390_displayhex( buffer,
-			                 &(ioinfo[irq].devstat.ii.irb) ,
+			                 &(ioinfo[irq]->devstat.ii.irb) ,
 			                 sizeof(irb_t));
 
 		} /* endif */
@@ -1624,18 +1744,18 @@
 		 * Check whether we must issue a SENSE CCW ourselves if there is no
 		 *  concurrent sense facility installed for the subchannel.
 		 *
-		 * Note: We should check for ioinfo[irq].ui.flags.consns but VM
+		 * Note: We should check for ioinfo[irq]->ui.flags.consns but VM
 		 *       violates the ESA/390 architecture and doesn't present an
 		 *       operand exception for virtual devices without concurrent
 		 *       sense facility available/supported when enabling the
        *       concurrent sense facility.
 		 */
-		if (    (    ( ioinfo[irq].devstat.ii.irb.scsw.dstat & DEV_STAT_UNIT_CHECK )
+		if (    (    ( ioinfo[irq]->devstat.ii.irb.scsw.dstat & DEV_STAT_UNIT_CHECK )
 			       && ( !issense                                                    ) )
-           || ( ioinfo[irq].ui.flags.delsense && ending_status                     ) )
+           || ( ioinfo[irq]->ui.flags.delsense && ending_status                     ) )
 		{
 			int            ret_io;
-			ccw1_t        *s_ccw  = &ioinfo[irq].senseccw;
+			ccw1_t        *s_ccw  = &ioinfo[irq]->senseccw;
 			unsigned long  s_flag = 0;
 
          if (ending_status)
@@ -1646,12 +1766,12 @@
 			    *  sensing. When finally calling the IRQ handler we must not overlay
 			    *  the original device status but copy the sense data only.
 			    */
-			   memcpy( irq_desc[irq].action->dev_id,
-				        &(ioinfo[irq].devstat),
+				memcpy( ioinfo[irq]->irq_desc.action->dev_id,
+				        &(ioinfo[irq]->devstat),
 				        sizeof( devstat_t) );
 
 			   s_ccw->cmd_code = CCW_CMD_BASIC_SENSE;
-			   s_ccw->cda      = (char *)virt_to_phys( ioinfo[irq].devstat.ii.sense.data);
+				s_ccw->cda      = (char *)virt_to_phys( ioinfo[irq]->devstat.ii.sense.data);
 			   s_ccw->count    = SENSE_MAX_COUNT;
 			   s_ccw->flags    = CCW_FLAG_SLI;
 
@@ -1659,7 +1779,7 @@
 			    * If free_irq() or a sync do_IO/s390_start_IO() is in
 			    *  process we have to sense synchronously
 			    */
-			   if ( ioinfo[irq].ui.flags.unready || ioinfo[irq].ui.flags.syncio )
+				if ( ioinfo[irq]->ui.flags.unready || ioinfo[irq]->ui.flags.syncio )
 			   {
 				   s_flag = DOIO_WAIT_FOR_INTERRUPT;
 
@@ -1679,16 +1799,16 @@
 			    */
 			   allow4handler                 = 0;
 
-			   ioinfo[irq].ui.flags.fast     = 0;
-			   ioinfo[irq].ui.flags.repall   = 0;
-			   ioinfo[irq].ui.flags.w4final  = 0;
-			   ioinfo[irq].ui.flags.delsense = 0;
-
-			   ioinfo[irq].devstat.cstat     = 0;
-			   ioinfo[irq].devstat.dstat     = 0;
-			   ioinfo[irq].devstat.rescnt    = SENSE_MAX_COUNT;
+				ioinfo[irq]->ui.flags.fast     = 0;
+				ioinfo[irq]->ui.flags.repall   = 0;
+				ioinfo[irq]->ui.flags.w4final  = 0;
+				ioinfo[irq]->ui.flags.delsense = 0;
+
+				ioinfo[irq]->devstat.cstat     = 0;
+				ioinfo[irq]->devstat.dstat     = 0;
+				ioinfo[irq]->devstat.rescnt    = SENSE_MAX_COUNT;
 
-			   ioinfo[irq].ui.flags.w4sense = 1;
+				ioinfo[irq]->ui.flags.w4sense  = 1;
 			
 			   ret_io = s390_start_IO( irq,
 				                        s_ccw,
@@ -1705,10 +1825,10 @@
 				 *  intermediate status to the device interrupt
 				 *  handler.
 				 */
-				ioinfo[irq].ui.flags.fast     = 0;
-				ioinfo[irq].ui.flags.repall   = 0;
+				ioinfo[irq]->ui.flags.fast     = 0;
+				ioinfo[irq]->ui.flags.repall   = 0;
 
-				ioinfo[irq].ui.flags.delsense = 1;
+				ioinfo[irq]->ui.flags.delsense = 1;
 				allow4handler                 = 0;
 
 			} /* endif */
@@ -1727,11 +1847,12 @@
 		if ( allow4handler )
 		{
 			allow4handler =    ending_status
-	  		   || ( ioinfo[irq].ui.flags.repall                                      )
-		      || ( ioinfo[irq].devstat.ii.irb.scsw.cstat & SCHN_STAT_PCI            )
-	  			|| ( (ioinfo[irq].ui.flags.fast ) && (stctl & SCSW_STCTL_PRIM_STATUS) )
-	  			|| ( ioinfo[irq].ui.flags.oper == 0                                   );
-		}
+			   || ( ioinfo[irq]->ui.flags.repall                                      )
+			   || ( ioinfo[irq]->devstat.ii.irb.scsw.cstat & SCHN_STAT_PCI            )
+				|| ( (ioinfo[irq]->ui.flags.fast ) && (stctl & SCSW_STCTL_PRIM_STATUS) )
+				|| ( ioinfo[irq]->ui.flags.oper == 0                                   );
+
+		} /* endif */
 
       /*
        * We used to copy the device status information right before
@@ -1749,9 +1870,9 @@
 			 *  bytes only as the original status information was
 			 *  saved prior to sense already.
 			 */
-			if ( ioinfo[irq].ui.flags.w4sense )
+			if ( ioinfo[irq]->ui.flags.w4sense )
 			{
-				int sense_count = SENSE_MAX_COUNT-ioinfo[irq].devstat.rescnt;
+				int sense_count = SENSE_MAX_COUNT-ioinfo[irq]->devstat.rescnt;
 
 #if CONFIG_DEBUG_IO
       if ( irq != cons_dev )
@@ -1759,27 +1880,32 @@
                  "BASIC SENSE bytes avail %d\n",
                  irq, sense_count );
 #endif
-				ioinfo[irq].ui.flags.w4sense           = 0;
+				ioinfo[irq]->ui.flags.w4sense          = 0;
 				((devstat_t *)(action->dev_id))->flag |= DEVSTAT_FLAG_SENSE_AVAIL;
 				((devstat_t *)(action->dev_id))->scnt  = sense_count;
 
 				if (sense_count >= 0)
+				{
 					memcpy( ((devstat_t *)(action->dev_id))->ii.sense.data,
-						&(ioinfo[irq].devstat.ii.sense.data), sense_count);
+					        &(ioinfo[irq]->devstat.ii.sense.data),
+					        sense_count);
+				}
             else
-#if 0
+				{
+#if 1
 					panic( "s390_process_IRQ(%04x) encountered "
 					       "negative sense count\n",
 					       irq);
 #else
-					printk( "s390_process_IRQ(%04x) encountered "
+					printk( KERN_CRIT"s390_process_IRQ(%04x) encountered "
 					        "negative sense count\n",
 					        irq);
 #endif
+				} /* endif */
 			}
 			else
 			{
-				memcpy( action->dev_id, &(ioinfo[irq].devstat), sdevstat );
+				memcpy( action->dev_id, &(ioinfo[irq]->devstat), sdevstat );
 
 			}  /* endif */
 
@@ -1788,9 +1914,10 @@
       /*
        * for status pending situations other than deferred interrupt
 		 *  conditions detected by s390_process_IRQ() itself we must not
-		 *  call the handler.
+		 *  call the handler. This will synchronously be reported back
+		 *  to the caller instead, e.g. when detected during do_IO().
        */
-		if ( ioinfo[irq].ui.flags.s_pend )
+		if ( ioinfo[irq]->ui.flags.s_pend )
 			allow4handler = 0;
 
 		/*
@@ -1803,18 +1930,18 @@
 			 *  We only reset the busy condition when we are sure that no further
 			 *   interrupt is pending for the current I/O request (ending_status).
 			 */
-			if ( ending_status || !ioinfo[irq].ui.flags.oper )
+			if ( ending_status || !ioinfo[irq]->ui.flags.oper )
 			{
-				ioinfo[irq].ui.flags.oper     = 1;  /* dev IS oper */
+				ioinfo[irq]->ui.flags.oper     = 1;  /* dev IS oper */
 
-				ioinfo[irq].ui.flags.busy     = 0;
-				ioinfo[irq].ui.flags.doio     = 0;
-				ioinfo[irq].ui.flags.haltio   = 0;
-				ioinfo[irq].ui.flags.fast     = 0;
-				ioinfo[irq].ui.flags.repall   = 0;
-				ioinfo[irq].ui.flags.w4final  = 0;
+				ioinfo[irq]->ui.flags.busy     = 0;
+				ioinfo[irq]->ui.flags.doio     = 0;
+				ioinfo[irq]->ui.flags.haltio   = 0;
+				ioinfo[irq]->ui.flags.fast     = 0;
+				ioinfo[irq]->ui.flags.repall   = 0;
+				ioinfo[irq]->ui.flags.w4final  = 0;
 
-				ioinfo[irq].devstat.flag              |= DEVSTAT_FINAL_STATUS;
+				ioinfo[irq]->devstat.flag             |= DEVSTAT_FINAL_STATUS;
 				((devstat_t *)(action->dev_id))->flag |= DEVSTAT_FINAL_STATUS;
 
 				action->handler( irq, action->dev_id, &regs);
@@ -1823,23 +1950,23 @@
 				// reset intparm after final status or we will badly present unsolicited
 				//  interrupts with a intparm value possibly no longer valid.
 				//
-				ioinfo[irq].devstat.intparm   = 0;
+				ioinfo[irq]->devstat.intparm   = 0;
 
 				//
 				// Was there anything queued ? Start the pending channel program
 				//  if there is one.
 				//
-				if ( ioinfo[irq].ui.flags.doio_q )
+				if ( ioinfo[irq]->ui.flags.doio_q )
 				{
 					int ret;
 
 					ret = s390_start_IO( irq,
-							               ioinfo[irq].qcpa,
-							               ioinfo[irq].qintparm,
-							               ioinfo[irq].qlpm,
-							               ioinfo[irq].qflag);
+							               ioinfo[irq]->qcpa,
+							               ioinfo[irq]->qintparm,
+							               ioinfo[irq]->qlpm,
+							               ioinfo[irq]->qflag);
 
-					ioinfo[irq].ui.flags.doio_q = 0;
+					ioinfo[irq]->ui.flags.doio_q = 0;
 
 					/*
 					 * If s390_start_IO() failed call the device's interrupt
@@ -1858,7 +1985,7 @@
 			}
 			else
 			{
-				ioinfo[irq].ui.flags.w4final = 1;
+				ioinfo[irq]->ui.flags.w4final = 1;
 				action->handler( irq, action->dev_id, &regs);
 
 			} /* endif */
@@ -1869,16 +1996,16 @@
 
 	case 3:      /* device not operational */
 
-		ioinfo[irq].ui.flags.oper    = 0;
+		ioinfo[irq]->ui.flags.oper    = 0;
 
-		ioinfo[irq].ui.flags.busy    = 0;
-		ioinfo[irq].ui.flags.doio    = 0;
-		ioinfo[irq].ui.flags.haltio  = 0;
-
-		ioinfo[irq].devstat.cstat    = 0;
-		ioinfo[irq].devstat.dstat    = 0;
-		ioinfo[irq].devstat.flag    |= DEVSTAT_NOT_OPER;
-		ioinfo[irq].devstat.flag    |= DEVSTAT_FINAL_STATUS;
+		ioinfo[irq]->ui.flags.busy    = 0;
+		ioinfo[irq]->ui.flags.doio    = 0;
+		ioinfo[irq]->ui.flags.haltio  = 0;
+
+		ioinfo[irq]->devstat.cstat    = 0;
+		ioinfo[irq]->devstat.dstat    = 0;
+		ioinfo[irq]->devstat.flag    |= DEVSTAT_NOT_OPER;
+		ioinfo[irq]->devstat.flag    |= DEVSTAT_FINAL_STATUS;
 
 		/*
 		 * When we find a device "not oper" we save the status
@@ -1891,7 +2018,8 @@
 		 *       interrupts on "not oper" conditions.
 		 */
 
-		if ( ioinfo[irq].ui.flags.fast && ioinfo[irq].ui.flags.w4final )
+		if (    ( ioinfo[irq]->ui.flags.fast    )
+		     && ( ioinfo[irq]->ui.flags.w4final ) )
 		{
 			/*
 			 * If a new request was queued already, we have
@@ -1899,23 +2027,23 @@
 			 *  queued request by switching the "intparm" value
 			 *  and notify the interrupt handler.
 			 */
-			if ( ioinfo[irq].ui.flags.doio_q )
+			if ( ioinfo[irq]->ui.flags.doio_q )
 			{
-				ioinfo[irq].devstat.intparm   = ioinfo[irq].qintparm;
+				ioinfo[irq]->devstat.intparm = ioinfo[irq]->qintparm;
 
 			} /* endif */
 
 		} /* endif */
 
-		ioinfo[irq].ui.flags.fast    = 0;
-		ioinfo[irq].ui.flags.repall  = 0;
-		ioinfo[irq].ui.flags.w4final = 0;
+		ioinfo[irq]->ui.flags.fast    = 0;
+		ioinfo[irq]->ui.flags.repall  = 0;
+		ioinfo[irq]->ui.flags.w4final = 0;
 
-		memcpy( action->dev_id, &(ioinfo[irq].devstat), sdevstat );
+		memcpy( action->dev_id, &(ioinfo[irq]->devstat), sdevstat );
 
-		ioinfo[irq].devstat.intparm  = 0;
+		ioinfo[irq]->devstat.intparm  = 0;
 
-		if ( !ioinfo[irq].ui.flags.s_pend )
+		if ( !ioinfo[irq]->ui.flags.s_pend )
 		   action->handler( irq, action->dev_id, &regs);
 
 		ending_status    = 1;
@@ -1958,24 +2086,28 @@
 	{
 		rc = -ENODEV;
 	}
+	else if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+	{
+		return( -ENODEV);
+   }
 	else
 	{
 		/*
 		 * modify the indicated console device to operate
 		 *  on special console interrupt sublass 7
 		 */
-		ccode = stsch( irq, &(ioinfo[irq].schib) );
+		ccode = stsch( irq, &(ioinfo[irq]->schib) );
 
 		if (ccode)
 		{
 			rc                        = -ENODEV;
-			ioinfo[irq].devstat.flag |= DEVSTAT_NOT_OPER;
+			ioinfo[irq]->devstat.flag |= DEVSTAT_NOT_OPER;
 		}
 		else
 		{
-			ioinfo[irq].schib.pmcw.isc = 7;
+			ioinfo[irq]->schib.pmcw.isc = 7;
 
-			ccode = msch( irq, &(ioinfo[irq].schib) );
+			ccode = msch( irq, &(ioinfo[irq]->schib) );
 
 			if (ccode)
 			{
@@ -2015,25 +2147,29 @@
 	{
 		rc = -ENODEV;
 	}
+	else if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+	{
+		return( -ENODEV);
+   }
 	else
 	{
 		/*
 		 * reset the indicated console device to operate
 		 *  on default console interrupt sublass 3
 		 */
-		ccode = stsch( irq, &(ioinfo[irq].schib) );
+		ccode = stsch( irq, &(ioinfo[irq]->schib) );
 
 		if (ccode)
 		{
 			rc                        = -ENODEV;
-			ioinfo[irq].devstat.flag |= DEVSTAT_NOT_OPER;
+			ioinfo[irq]->devstat.flag |= DEVSTAT_NOT_OPER;
 		}
 		else
 		{
 
-			ioinfo[irq].schib.pmcw.isc = 3;
+			ioinfo[irq]->schib.pmcw.isc = 3;
 
-			ccode = msch( irq, &(ioinfo[irq].schib) );
+			ccode = msch( irq, &(ioinfo[irq]->schib) );
 
 			if (ccode)
 			{
@@ -2071,7 +2207,7 @@
 		 * before entering the spinlock we may already have
 		 *  processed the interrupt on a different CPU ...
 		 */
-		if ( ioinfo[irq].ui.flags.busy == 1 )
+		if ( ioinfo[irq]->ui.flags.busy == 1 )
 		{
 			long cr6 __attribute__ ((aligned (8)));
 
@@ -2086,15 +2222,14 @@
 			do {
 				tpi_info_t tpi_info;
 				if (tpi(&tpi_info) == 1) {
-					s390_process_IRQ(tpi_info.irq,
-					    	         tpi_info.intparm);
+					s390_process_IRQ( tpi_info.irq );
 				} else {
 					s390irq_spin_unlock(irq);
 					tod_wait(100);
 					s390irq_spin_lock(irq);
 				}
 				eieio();
-			} while (ioinfo[irq].ui.flags.busy == 1);
+			} while (ioinfo[irq]->ui.flags.busy == 1);
 
 			/*
 			 * restore previous isc value
@@ -2125,17 +2260,17 @@
 	int             count = 0;
 	int             rc    = 0;
 
-	if ( irq <= highest_subchannel )
+	if ( irq <= highest_subchannel && ioinfo[irq] != INVALID_STORAGE_AREA )
 	{
-		ccode = stsch( irq, &(ioinfo[irq].schib) );
+		ccode = stsch( irq, &(ioinfo[irq]->schib) );
 
 		if ( !ccode )
 		{
-			ioinfo[irq].schib.pmcw.isc = 5;
+			ioinfo[irq]->schib.pmcw.isc = 5;
 
 			do
 			{
-				ccode = msch( irq, &(ioinfo[irq].schib) );
+				ccode = msch( irq, &(ioinfo[irq]->schib) );
 
 				if (ccode == 0 )
 				{
@@ -2162,11 +2297,11 @@
 					//
 					// process pending status
 					//
-			      ioinfo[irq].ui.flags.s_pend = 1;
+			      ioinfo[irq]->ui.flags.s_pend = 1;
 
-					s390_process_IRQ( irq, 0 );
+					s390_process_IRQ( irq );
 
-			      ioinfo[irq].ui.flags.s_pend = 0;
+			      ioinfo[irq]->ui.flags.s_pend = 0;
 
 					count++;
 
@@ -2201,13 +2336,13 @@
 	int     ccode;
 	long    cr6 __attribute__ ((aligned (8)));
 
-	if ( irq <= highest_subchannel )
+	if ( irq <= highest_subchannel && ioinfo[irq] != INVALID_STORAGE_AREA )
 	{
-		ccode = stsch( irq, &(ioinfo[irq].schib) );
+		ccode = stsch( irq, &(ioinfo[irq]->schib) );
 
-		ioinfo[irq].schib.pmcw.isc = 3;
+		ioinfo[irq]->schib.pmcw.isc = 3;
 
-		ccode = msch( irq, &(ioinfo[irq].schib) );
+		ccode = msch( irq, &(ioinfo[irq]->schib) );
 
 		if (ccode)
 		{
@@ -2236,8 +2371,15 @@
 	return( rc);
 }
 
-void VM_virtual_device_info( int        devno,   /* device number                 */
-                             senseid_t *ps )     /* pointer to sense ID data area */
+//
+// Input :
+//   devno - device number
+//   ps    - pointer to sense ID data area
+//
+// Output : none
+//
+void VM_virtual_device_info( unsigned int  devno,
+                             senseid_t    *ps )
 {
 	diag210_t  diag_data;
 	int        ccode;
@@ -2269,7 +2411,7 @@
 
 		break;
 
-	case 40:
+	case 0x40:
 
 		switch (diag_data.vrdcvtyp) {
 		case 0xC0:
@@ -2537,9 +2679,13 @@
   {
     return( -ENODEV );
 
-  } /* endif */
+	}
+	else if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+	{
+		return( -ENODEV);
+   }
 
-  if ( ioinfo[irq].ui.flags.oper == 0 )
+	if ( ioinfo[irq]->ui.flags.oper == 0 )
   {
     return( -ENODEV );
 
@@ -2556,11 +2702,13 @@
   __save_flags(flags);
   __cli();
 
-  rdc_ccw = &ioinfo[irq].senseccw;
+	rdc_ccw = &ioinfo[irq]->senseccw;
 
-  if ( !ioinfo[irq].ui.flags.ready )
+	if ( !ioinfo[irq]->ui.flags.ready )
   {
-    ret = request_irq( irq, init_IRQ_handler, 0, "RDC", &devstat );
+		ret = request_irq( irq,
+		                   init_IRQ_handler,
+		                   0, "RDC", &devstat );
 
     if ( !ret )
     {
@@ -2601,7 +2749,7 @@
 		                        0,          // n/a
 		                        DOIO_WAIT_FOR_INTERRUPT );
          retry--;
-         devflag = ((devstat_t *)(irq_desc[irq].action->dev_id))->flag;
+				devflag = ((devstat_t *)(ioinfo[irq]->irq_desc.action->dev_id))->flag;
 
       } while (    ( retry                                     )
 	             && ( ret || (devflag & DEVSTAT_STATUS_PENDING) ) );
@@ -2650,10 +2798,14 @@
    if ( (irq > highest_subchannel) || (irq < 0 ) )
    {
       return( -ENODEV );
+   }
+	else if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+	{
+		return( -ENODEV);
 
    } /* endif */
 
-   if ( ioinfo[irq].ui.flags.oper == 0 )
+   if ( ioinfo[irq]->ui.flags.oper == 0 )
    {
       return( -ENODEV );
 
@@ -2664,7 +2816,7 @@
     */
    for ( ; (found == 0) && (ciw_cnt < 62); ciw_cnt++ )
    {
-      if ( senseid[irq].ciw[ciw_cnt].ct == CIW_TYPE_RCD )
+      if ( ioinfo[irq]->senseid.ciw[ciw_cnt].ct == CIW_TYPE_RCD )
       {
          found = 1;
       	break;
@@ -2674,7 +2826,7 @@
 
    if ( found )
    {
-       ccw1_t    *rcd_ccw = &ioinfo[irq].senseccw;
+		ccw1_t    *rcd_ccw = &ioinfo[irq]->senseccw;
        devstat_t  devstat;
        char      *rcd_buf;
        int        devflag;
@@ -2685,9 +2837,11 @@
    	 __save_flags(flags);
 	    __cli();
 
-       if ( !ioinfo[irq].ui.flags.ready )
+		if ( !ioinfo[irq]->ui.flags.ready )
        {
-          ret = request_irq( irq, init_IRQ_handler, 0, "RCD", &devstat );
+			ret = request_irq( irq,
+			                   init_IRQ_handler,
+			                   0, "RCD", &devstat );
 
           if ( !ret )
           {
@@ -2699,13 +2853,14 @@
 
        if ( !ret )
        {
-          rcd_buf  = kmalloc( senseid[irq].ciw[ciw_cnt].count, GFP_KERNEL);
+			rcd_buf = kmalloc( ioinfo[irq]->senseid.ciw[ciw_cnt].count,
+			                   GFP_KERNEL);
 
           do
           {
-     		    rcd_ccw->cmd_code = senseid[irq].ciw[ciw_cnt].cmd;
+				rcd_ccw->cmd_code = ioinfo[irq]->senseid.ciw[ciw_cnt].cmd;
 	   	    rcd_ccw->cda      = (char *)virt_to_phys( rcd_buf );
-             rcd_ccw->count    = senseid[irq].ciw[ciw_cnt].count;
+				rcd_ccw->count    = ioinfo[irq]->senseid.ciw[ciw_cnt].count;
 		       rcd_ccw->flags    = CCW_FLAG_SLI;
 
              ret = s390_start_IO( irq,
@@ -2716,7 +2871,7 @@
 
              retry--;
 
-             devflag = ((devstat_t *)(irq_desc[irq].action->dev_id))->flag;
+				devflag = ((devstat_t *)(ioinfo[irq]->irq_desc.action->dev_id))->flag;
 
           } while (    ( retry                                     )
                     && ( ret || (devflag & DEVSTAT_STATUS_PENDING) ) );
@@ -2733,7 +2888,7 @@
         */
        if ( !ret )
        {
-          *length = senseid[irq].ciw[ciw_cnt].count;
+			*length = ioinfo[irq]->senseid.ciw[ciw_cnt].count;
           *buffer = rcd_buf;
 
        } /* endif */
@@ -2751,16 +2906,111 @@
 
 }
 
-
 int get_dev_info( int irq, dev_info_t *pdi)
 {
    return( get_dev_info_by_irq( irq, pdi) );
 }
 
+
+static int __inline__ get_next_available_irq( ioinfo_t *pi)
+{
+	int ret_val;
+
+	while ( TRUE )
+	{
+		if ( pi->ui.flags.oper )
+		{
+			ret_val = pi->irq;
+			break;
+		}
+		else
+		{
+			pi = pi->next;
+
+			//
+			// leave at end of list unconditionally
+			//
+			if ( pi == NULL )
+			{
+				ret_val = -ENODEV;
+				break;
+			}
+
+		} /* endif */
+
+	} /* endwhile */
+
+	return ret_val;
+}
+
+
+int get_irq_first( void )
+{
+   int ret_irq;
+
+	if ( ioinfo_head )
+	{
+		if ( ioinfo_head->ui.flags.oper )
+		{
+			ret_irq = ioinfo_head->irq;
+		}
+		else if ( ioinfo_head->next )
+		{
+			ret_irq = get_next_available_irq( ioinfo_head->next );
+
+		}
+		else
+		{
+			ret_irq = -ENODEV;
+   	
+		} /* endif */
+	}
+	else
+	{
+		ret_irq = -ENODEV;
+
+	} /* endif */
+
+	return ret_irq;
+}
+
+int get_irq_next( int irq )
+{
+	int ret_irq;	
+
+	if ( ioinfo[irq] != INVALID_STORAGE_AREA )
+	{
+		if ( ioinfo[irq]->next )
+		{
+			if ( ioinfo[irq]->next->ui.flags.oper )
+			{
+				ret_irq = ioinfo[irq]->next->irq;
+			}
+			else
+			{
+				ret_irq = get_next_available_irq( ioinfo[irq]->next );
+
+			} /* endif */
+		}
+		else
+		{
+			ret_irq = -ENODEV;     	
+
+		} /* endif */
+	}
+	else
+	{
+		ret_irq = -EINVAL;
+
+	} /* endif */
+
+	return ret_irq;
+}
+
 int get_dev_info_by_irq( int irq, dev_info_t *pdi)
 {
 
-	if ( irq > highest_subchannel )
+	if ( irq > highest_subchannel || irq < 0 )
 	{
 		return -ENODEV;
 	}
@@ -2768,24 +3018,35 @@
 	{
       return -EINVAL;
 	}
+	else if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+	{
+		return( -ENODEV);
+	}
 	else
 	{
-	   pdi->devno = ioinfo[irq].schib.pmcw.dev;
+		pdi->devno = ioinfo[irq]->schib.pmcw.dev;
       pdi->irq   = irq;
 
-      if ( ioinfo[irq].ui.flags.oper )
+		if ( ioinfo[irq]->ui.flags.oper )
       {
 		   pdi->status = 0;
-	   	memcpy( &(pdi->sid_data), &senseid[irq], sizeof( senseid_t));
+			memcpy( &(pdi->sid_data),
+			        &ioinfo[irq]->senseid,
+			        sizeof( senseid_t));
       }
       else
       {
 		   pdi->status = DEVSTAT_NOT_OPER;
-	   	memcpy( &(pdi->sid_data), '\0', sizeof( senseid_t));
+			memcpy( &(pdi->sid_data),
+			        '\0',
+			        sizeof( senseid_t));
          pdi->sid_data.cu_type = 0xFFFF;
 
       } /* endif */
 
+		if ( ioinfo[irq]->ui.flags.ready )
+			pdi->status |= DEVSTAT_DEVICE_OWNED;
+
 		return 0;
 
 	} /* endif */
@@ -2812,15 +3073,17 @@
       for ( i=0; i <= highest_subchannel; i++ )
       {
 
-         if ( ioinfo[i].schib.pmcw.dev == devno )
+			if (    ioinfo[i] != INVALID_STORAGE_AREA
+			     && ioinfo[i]->schib.pmcw.dev == devno )
          {
-            if ( ioinfo[i].ui.flags.oper )
+				if ( ioinfo[i]->ui.flags.oper )
             {
 		         pdi->status = 0;
                pdi->irq    = i;
 		         pdi->devno  = devno;
+
 	   	      memcpy( &(pdi->sid_data),
-                       &senseid[i],
+					        &ioinfo[i]->senseid,
                        sizeof( senseid_t));
             }
             else
@@ -2828,11 +3091,15 @@
 		         pdi->status = DEVSTAT_NOT_OPER;
                pdi->irq    = i;
                pdi->devno  = devno;
+	
 	   	      memcpy( &(pdi->sid_data), '\0', sizeof( senseid_t));
                pdi->sid_data.cu_type = 0xFFFF;
 
             } /* endif */
 
+				if ( ioinfo[i]->ui.flags.ready )
+					pdi->status |= DEVSTAT_DEVICE_OWNED;
+
             rc = 0; /* found */
             break;
 
@@ -2855,7 +3122,9 @@
 	{
       for ( i=0; i <= highest_subchannel; i++ )
       {
-         if ( devno == ioinfo[i].schib.pmcw.dev )
+			if (    (ioinfo[i] != INVALID_STORAGE_AREA )
+			     && (ioinfo[i]->schib.pmcw.dev == devno)
+			     && (ioinfo[i]->schib.pmcw.dnv == 1    ) )
          {
             rc = i;
             break;
@@ -2867,13 +3136,14 @@
 	} /* endif */
 
    return( rc);
-
 }
 
 unsigned int get_devno_by_irq( int irq )
 {
 
-	if ( irq > highest_subchannel )
+	if (    ( irq > highest_subchannel            )
+	     || ( irq < 0                             )
+	     || ( ioinfo[irq] == INVALID_STORAGE_AREA ) )
 	{
 		return -1;
 
@@ -2883,10 +3153,13 @@
     * we don't need to check for the device be operational
     *  as the initial STSCH will always present the device
     *  number defined by the IOCDS regardless of the device
-    *  existing or not.
+	 *  existing or not. However, there could be subchannels
+	 *  defined who's device number isn't valid ...
     */
-   return( ioinfo[irq].schib.pmcw.dev );
-
+	if ( ioinfo[irq]->schib.pmcw.dnv )
+		return( ioinfo[irq]->schib.pmcw.dev );
+	else
+		return -1;
 }
 
 /*
@@ -2907,10 +3180,11 @@
        * We issue the SenseID command on I/O subchannels we think are
        *  operational only.
        */
-      if ( 	  ( schiblock[irq].pmcw.st == 0    )
-           && ( ioinfo[irq].ui.flags.oper == 1 ) )
+		if (    ( ioinfo[irq] != INVALID_STORAGE_AREA )	
+		     && ( ioinfo[irq]->schib.pmcw.st == 0     )
+		     && ( ioinfo[irq]->ui.flags.oper == 1     ) )
       {
-         s390_SenseID( irq, &senseid[irq] );
+			s390_SenseID( irq, &ioinfo[irq]->senseid );
 
       } /* endif */
 
@@ -2930,7 +3204,6 @@
 void s390_process_subchannels( void)
 {
    int   isValid;
-
 	int   irq = 0;   /* Evaluate all subchannels starting with 0 ... */
 
 	do
@@ -2939,7 +3212,7 @@
 
       irq++;
 
-	} while ( isValid && irq < NR_IRQS );
+  	} while ( isValid && irq < __MAX_SUBCHANNELS );
 
 	highest_subchannel = --irq;
 
@@ -2959,45 +3232,120 @@
    int   retry;     /* retry count for status pending conditions */
 	int   ccode;     /* condition code for stsch() only */
 	int   ccode2;    /* condition code for other I/O routines */
+	schib_t *p_schib;
 
 	/*
 	 * The first subchannel that is not-operational (ccode==3)
 	 *  indicates that there aren't any more devices available.
 	 */
-	ccode = stsch( irq, &schiblock[irq]);
+	if (    ( init_IRQ_complete                   )
+	     && ( ioinfo[irq] != INVALID_STORAGE_AREA ) )
+	{
+		p_schib = &ioinfo[irq]->schib;
+	}
+	else
+	{
+		p_schib = &init_schib;
+
+	} /* endif */
+
+	ccode = stsch( irq, p_schib);
 
    if ( ccode == 0)
    {
    	/*
 	    * ... just being curious we check for non I/O subchannels
 		 */
-		if ( schiblock[irq].pmcw.st )
+		if ( p_schib->pmcw.st )
 		{
 			printk( "Subchannel %04X reports "
 			        "non-I/O subchannel type %04X\n",
 			        irq,
-			        schiblock[irq].pmcw.st);
+			        p_schib->pmcw.st);
 
-			ioinfo[irq].ui.flags.oper = 0;
+			if ( ioinfo[irq] != INVALID_STORAGE_AREA )
+				ioinfo[irq]->ui.flags.oper = 0;
 
 		} /* endif */
 
-		if ( !schiblock[irq].pmcw.dnv )
+		if ( p_schib->pmcw.dnv )
+		{
+			if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+			{	
+
+				if ( !init_IRQ_complete )
 		{
+					ioinfo[irq] =
+					   (ioinfo_t *)alloc_bootmem( sizeof(ioinfo_t));
+				}
+				else
+				{
+					ioinfo[irq] =
+					   (ioinfo_t *)kmalloc( sizeof(ioinfo_t),
+				                           GFP_KERNEL );
+
+				} /* endif */
+
+				memset( ioinfo[irq], '\0', sizeof( ioinfo_t));
+				memcpy( &ioinfo[irq]->schib,
+			           &init_schib,
+			           sizeof( schib_t));
+				ioinfo[irq]->irq_desc.status  = IRQ_DISABLED;
+				ioinfo[irq]->irq_desc.handler = &no_irq_type;
+			
 			/*
-			 * don't process invalid device numbers ...
+				 * We have to insert the new ioinfo element
+				 *  into the linked list, either at its head,
+				 *  its tail or insert it.
 			 */
-			ioinfo[irq].ui.flags.oper = 0;
+				if ( ioinfo_head == NULL )  /* first element */
+				{
+					ioinfo_head = ioinfo[irq];
+					ioinfo_tail = ioinfo[irq];
 		}
-		else
+				else if (irq < ioinfo_head->irq) /* new head */
+				{
+					ioinfo[irq]->next = ioinfo_head;
+					ioinfo_head->prev = ioinfo[irq];
+					ioinfo_head       = ioinfo[irq];
+				}
+				else if (irq > ioinfo_tail->irq) /* new tail */
+				{
+					ioinfo_tail->next = ioinfo[irq];
+					ioinfo[irq]->prev = ioinfo_tail;
+					ioinfo_tail       = ioinfo[irq];
+				}
+				else /* insert element */
+				{
+					ioinfo_t *pi = ioinfo_head;
+
+					do              
+					{
+						if ( irq < pi->next->irq )
 		{
+							ioinfo[irq]->next = pi->next;
+							ioinfo[irq]->prev = pi;
+							pi->next->prev    = ioinfo[irq];
+							pi->next          = ioinfo[irq];
+							break;
+						
+						} /* endif */
+
+						pi = pi->next;
+
+					} while ( 1 );
+      	
+				} /* endif */
+
+			} /* endif */
+
 			printk( "Detected device %04X on subchannel %04X"
 			        " - PIM = %02X, PAM = %02X, POM = %02X\n",
-			        schiblock[irq].pmcw.dev,
+			        ioinfo[irq]->schib.pmcw.dev,
 			        irq,
-			        schiblock[irq].pmcw.pim,
-			        schiblock[irq].pmcw.pam,
-			        schiblock[irq].pmcw.pom);
+			        ioinfo[irq]->schib.pmcw.pim,
+			        ioinfo[irq]->schib.pmcw.pam,
+			        ioinfo[irq]->schib.pmcw.pom);
 
 			/*
 			 * We now have to initially ...
@@ -3009,41 +3357,41 @@
 			 * Note : we don't enable the device here, this is temporarily
 			 *        done during device sensing below.
 			 */
-			schiblock[irq].pmcw.isc    = 3;     /* could be smth. else ... */
-			schiblock[irq].pmcw.csense = 1;     /* concurrent sense */
-			schiblock[irq].pmcw.ena    = 0;     /* force disable it */
+			ioinfo[irq]->schib.pmcw.isc     = 3; /* could be smth. else */
+			ioinfo[irq]->schib.pmcw.csense  = 1; /* concurrent sense */
+			ioinfo[irq]->schib.pmcw.ena     = 0; /* force disable it */
+			ioinfo[irq]->schib.pmcw.intparm =
+			                     ioinfo[irq]->schib.pmcw.dev;
 
-			if (    ( schiblock[irq].pmcw.pim != 0    )
-			     && ( schiblock[irq].pmcw.pim != 0x80 ) )
+			if (    ( ioinfo[irq]->schib.pmcw.pim != 0    )
+			     && ( ioinfo[irq]->schib.pmcw.pim != 0x80 ) )
 			{
-				schiblock[irq].pmcw.mp     = 1;     /* multipath mode */
+				ioinfo[irq]->schib.pmcw.mp     = 1;     /* multipath mode */
 
 			} /* endif */
 
 			/*
 			 * initialize ioinfo structure
 		    */
-			ioinfo[irq].irq             = irq;
-			ioinfo[irq].ui.flags.busy   = 0;
-			ioinfo[irq].ui.flags.ready  = 0;
-			ioinfo[irq].ui.flags.oper   = 1;
-			ioinfo[irq].devstat.intparm = irq;
-			ioinfo[irq].devstat.devno   = schiblock[irq].pmcw.dev;
-
-			memcpy( &(ioinfo[irq].schib), &(schiblock[irq]), sizeof( schib_t));
+			ioinfo[irq]->irq             = irq;
+			ioinfo[irq]->ui.flags.busy   = 0;
+			ioinfo[irq]->ui.flags.ready  = 0;
+			ioinfo[irq]->ui.flags.oper   = 1;
+			ioinfo[irq]->devstat.intparm = 0;
+			ioinfo[irq]->devstat.devno   = ioinfo[irq]->schib.pmcw.dev;
 
          retry = 5;
 
          do
 			{
-			   ccode2 = msch_err( irq, &schiblock[irq]);
+				ccode2 = msch_err( irq, &ioinfo[irq]->schib);
 
             switch (ccode2) {
             case 0:  // successful completion
 			      //
 				   // concurrent sense facility available ...
 				   //
-				   ioinfo[irq].ui.flags.consns = 1;
+					ioinfo[irq]->ui.flags.consns = 1;
                break;
 
             case 1:  // status pending
@@ -3051,7 +3399,7 @@
                // How can we have a pending status as device is
                //  disabled for interrupts ? Anyway, clear it ...
                //
-		         tsch( irq, &(ioinfo[irq].devstat.ii.irb) );
+					tsch( irq, &(ioinfo[irq]->devstat.ii.irb) );
                retry--;
                break;
 
@@ -3060,7 +3408,7 @@
                break;
 
             case 3:  // not operational
-				   ioinfo[irq].ui.flags.oper = 0;
+					ioinfo[irq]->ui.flags.oper = 0;
                retry                     = 0;
                break;
 
@@ -3073,23 +3421,19 @@
 						 * re-issue the modify subchannel without trying to
 						 *  enable the concurrent sense facility
 						 */
-						schiblock[irq].pmcw.csense = 0;
+						ioinfo[irq]->schib.pmcw.csense = 0;
 
-						memcpy( &(ioinfo[irq].schib),
-						        &(schiblock[irq]),
-						        sizeof( schib_t));
-
-						ccode2 = msch_err( irq, &schiblock[irq]);
+						ccode2 = msch_err( irq, &ioinfo[irq]->schib);
 
 						if ( ccode2 != 0 )
 						{
 						   printk( " ... modify subchannel (2) failed with CC = %X\n",
 						           ccode2 );
-						   ioinfo[irq].ui.flags.oper = 0;
+							ioinfo[irq]->ui.flags.oper = 0;
 						}
 						else
 						{
-						   ioinfo[irq].ui.flags.consns = 0;
+							ioinfo[irq]->ui.flags.consns = 0;
 
 						} /* endif */
 					}
@@ -3097,7 +3441,7 @@
 					{
 						printk( " ... modify subchannel (1) failed with CC = %X\n",
 						        ccode2);
-						ioinfo[irq].ui.flags.oper = 0;
+						ioinfo[irq]->ui.flags.oper = 0;
 
 					} /* endif */
 
@@ -3156,15 +3500,19 @@
 	{
 		return( -ENODEV );
 
+	}
+	else if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+	{
+		return( -ENODEV);
 	} /* endif */
 
-	if ( ioinfo[irq].ui.flags.oper == 0 )
+	if ( ioinfo[irq]->ui.flags.oper == 0 )
 	{
 		return( -ENODEV );
 
 	} /* endif */
 
-	if ( !ioinfo[irq].ui.flags.ready )
+	if ( !ioinfo[irq]->ui.flags.ready )
 	{
 		/*
 		 * Perform SENSE ID command processing. We have to request device
@@ -3188,10 +3536,10 @@
 		sense_ccw.count    = sizeof( senseid_t);
 		sense_ccw.flags    = CCW_FLAG_SLI;
 
-		senseid[irq].cu_type    = 0xFFFF;  /* initialize fields ... */
-		senseid[irq].cu_model   = 0;
-		senseid[irq].dev_type   = 0;
-		senseid[irq].dev_model  = 0;
+		ioinfo[irq]->senseid.cu_type    = 0xFFFF;  /* initialize fields ... */
+		ioinfo[irq]->senseid.cu_model   = 0;
+		ioinfo[irq]->senseid.dev_type   = 0;
+		ioinfo[irq]->senseid.dev_model  = 0;
 
 		/*
 		 * We now issue a SenseID request. In case of BUSY
@@ -3214,7 +3562,7 @@
 #if CONFIG_DEBUG_IO
 					printk( "Device %04X on Subchannel %04X "
 					        "reports pending status, retry : %d\n",
-					        schiblock[irq].pmcw.dev,
+					        ioinfo[irq]->schib.pmcw.dev,
 					        irq,
 					        retry);
 #endif
@@ -3238,7 +3586,7 @@
 						        " retry %d, cnt %02d,"
 						        " sns :"
 						        " %02X%02X%02X%02X %02X%02X%02X%02X ...\n",
-						        schiblock[irq].pmcw.dev,
+						        ioinfo[irq]->schib.pmcw.dev,
 						        retry,
 						        devstat.scnt,
 						        devstat.ii.sense.data[0],
@@ -3257,7 +3605,7 @@
 				{
 					printk( "Device %04X on Subchannel %04X "
 					        "became 'not operational'\n",
-					        schiblock[irq].pmcw.dev,
+					        ioinfo[irq]->schib.pmcw.dev,
 					        irq);
 
 					retry = 0;
@@ -3290,7 +3638,7 @@
 		if (    ( sid->cu_type == 0xFFFF )
 		     && ( MACHINE_IS_VM              ) )
 		{
-			VM_virtual_device_info( schiblock[irq].pmcw.dev,
+			VM_virtual_device_info( ioinfo[irq]->schib.pmcw.dev,
 			                        sid );
 		} /* endif */
 
@@ -3304,22 +3652,22 @@
 			 *  consider the device "not operational".
 			 */
 			printk( "Unknown device %04X on subchannel %04X\n",
-			        schiblock[irq].pmcw.dev,
+			        ioinfo[irq]->schib.pmcw.dev,
 			        irq);
-			ioinfo[irq].ui.flags.oper = 0;
+			ioinfo[irq]->ui.flags.oper = 0;
 
 		} /* endif */
 
 		/*
 		 * Issue device info message if unit was operational .
 		 */
-		if ( ioinfo[irq].ui.flags.oper )
+		if ( ioinfo[irq]->ui.flags.oper )
 		{
 			if ( sid->dev_type != 0 )
 			{
 				printk( "Device %04X reports: CU  Type/Mod = %04X/%02X,"
 				        " Dev Type/Mod = %04X/%02X\n",
-				        schiblock[irq].pmcw.dev,
+				        ioinfo[irq]->schib.pmcw.dev,
 				        sid->cu_type,
 				        sid->cu_model,
 				        sid->dev_type,
@@ -3329,7 +3677,7 @@
 			{
 				printk( "Device %04X reports:"
 				        " Dev Type/Mod = %04X/%02X\n",
-				        schiblock[irq].pmcw.dev,
+				        ioinfo[irq]->schib.pmcw.dev,
 				        sid->cu_type,
 				        sid->cu_model);
 
@@ -3337,7 +3685,7 @@
 
 		} /* endif */
 
-		if ( ioinfo[irq].ui.flags.oper )
+		if ( ioinfo[irq]->ui.flags.oper )
 			irq_ret = 0;
 		else
 			irq_ret = -ENODEV;
@@ -3350,37 +3698,16 @@
 void do_crw_pending(void)
 {
 }
-#ifdef CONFIG_READIPL_ENABLED
+
+/* added by Holger Smolinski for reipl support in reipl.S */
 void 
-do_reipl ( int sch ) 
+reipl ( int sch )
 {
-	static ccw1_t iplccw[2] = {
-		{ CCW_CMD_READ_IPL, CCW_FLAG_CC, 24, 0x00000000 },
-		{ CCW_CMD_TIC     , CCW_FLAG_CC,  0, 0x00000008 }
-	};
-	static orb_t  iplorb = {
-	  0,
-	};
-	static psw_t psw_0 = {0,};
-	static long cr6_0 = 0x0;
-	static psw_t psw_1 = {0,};
-	static long cr6_1 = 0x0;
         int i;
 
-	/* First disable all Devices/IRQs */
 	for ( i = 0; i < highest_subchannel; i ++ ) {
 	  free_irq ( i, (void*)REIPL_DEVID_MAGIC );
 	}
-	/* re enable the one device */
-	enable_subchannel (sch);
-	__asm__ __volatile__ ( "spx 0" );
-	__asm__ __volatile__ ( "lpsw %0" ::  "m" (psw_0) ); /* disable all */
-	__asm__ __volatile__ ( "lctl 6,6,%0" : : "m" (cr6_0) ); 
-	__asm__ __volatile__ ( "lr 1,%0\n" 
-			       "ssch %1\n"
-			       :: "d" (sch), "m" (iplorb) : "1" );
-	__asm__ __volatile__ ( "lctl 6,6,%0" :: "m" (cr6_1) );
-	__asm__ __volatile__ ( "lpsw %0" ::  "m" (psw_1) );
-	__asm__ __volatile__ ( "lpsw 0" ); /* restart */
+	do_reipl( 0x10000 | sch );
 }
-#endif
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/kernel/s390io.h linux.15p9/arch/s390/kernel/s390io.h
--- linux.vanilla/arch/s390/kernel/s390io.h	Tue Jan  4 21:18:41 2000
+++ linux.15p9/arch/s390/kernel/s390io.h	Thu Jan  1 01:00:00 1970
@@ -1,72 +0,0 @@
-/*
- *  arch/s390/kernel/s390io.h
- *
- *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
- *    Author(s): Ingo Adlung (adlung@de.ibm.com)
- */
-
-#ifndef __s390io_h
-#define __s390io_h
-
-/*
- * Private data structure used by do_IO()
- *
- * Note : If bit flags are added, the "unused" value must be
- *        decremented accordingly !
- */
-typedef struct {
-      unsigned int  irq;           /* aka. subchannel number */
-      union {
-         unsigned int info;
-         struct {
-            unsigned int  busy      : 1;  /* device currently in use */
-            unsigned int  oper      : 1;  /* device is operational */
-            unsigned int  fast      : 1;  /* post with "channel end", ...    */
-                                          /* ... don't wait for "device end" */
-                                          /* ... from do_IO() parameters     */
-            unsigned int  ready     : 1;  /* interrupt handler registered */
-            unsigned int  haltio    : 1;  /* halt_IO in process */
-            unsigned int  doio      : 1;  /* do_IO in process */
-            unsigned int  doio_q    : 1;  /* do_IO queued - only possible ... */
-                                          /* ... if 'fast' is set too */
-            unsigned int  w4final   : 1;  /* wait for final status, internally */
-                                          /* ... used with 'fast' setting only */
-            unsigned int  repall    : 1;  /* report every interrupt status */
-            unsigned int  unready   : 1;  /* deregister irq handler in process */
-            unsigned int  d_disable : 1;  /* delayed disabling required */
-            unsigned int  w4sense   : 1;  /* SENSE status pending */
-            unsigned int  syncio    : 1;  /* synchronous I/O requested */
-            unsigned int  consns    : 1;  /* concurrent sense is available */
-            unsigned int  delsense  : 1;  /* delayed SENSE required */
-            unsigned int  s_pend    : 1;  /* status pending condition */
-            unsigned int  unused    : 16; /* unused */
-               } __attribute__ ((packed)) flags;
-         } ui;
-      unsigned int  lpm;           /* logical path mask to be used ... */
-                                   /* ... from do_IO() parms. Only ... */
-                                   /* ... valid if vlpm is set too.    */
-      schib_t       schib;         /* subchannel information block */
-      orb_t         orb;           /* operation request block */
-      devstat_t     devstat;       /* device status */
-      ccw1_t       *qcpa;          /* queued channel program */
-      ccw1_t        senseccw;      /* ccw for sense command */
-      unsigned int  stctl;         /* accumulated status control from irb */
-      unsigned int  qintparm;      /* queued interruption parameter  */
-      unsigned long qflag;         /* queued flags */
-      unsigned char qlpm;          /* queued logical path mask */
-
-   } __attribute__ ((aligned(8))) ioinfo_t;
-
-#define IOINFO_FLAGS_BUSY    0x80000000
-#define IOINFO_FLAGS_OPER    0x40000000
-#define IOINFO_FLAGS_FAST    0x20000000
-#define IOINFO_FLAGS_READY   0x10000000
-#define IOINFO_FLAGS_HALTIO  0x08000000
-#define IOINFO_FLAGS_DOIO    0x04000000
-#define IOINFO_FLAGS_DOIO_Q  0x02000000
-#define IOINFO_FLAGS_W4FINAL 0x01000000
-#define IOINFO_FLAGS_REPALL  0x00800000
-
-#endif  /* __s390io_h */
-
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/kernel/s390ksyms.c linux.15p9/arch/s390/kernel/s390ksyms.c
--- linux.vanilla/arch/s390/kernel/s390ksyms.c	Tue Jan  4 21:18:41 2000
+++ linux.15p9/arch/s390/kernel/s390ksyms.c	Thu Jan  1 01:00:00 1970
@@ -1,22 +0,0 @@
-/*
- *  arch/s390/kernel/s390ksyms.c
- *
- *  S390 version
- */
-
-#include "irq.h"
-#include "asm/string.h"
-
-EXPORT_SYMBOL(get_dev_info_by_irq);
-EXPORT_SYMBOL(get_dev_info_by_devno);
-EXPORT_SYMBOL(get_irq_by_devno);
-EXPORT_SYMBOL(get_devno_by_irq);
-EXPORT_SYMBOL(halt_IO);
-EXPORT_SYMBOL(irq_desc);
-EXPORT_SYMBOL(do_IO);
-EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(init_mm);
-EXPORT_SYMBOL(_oi_bitmap);
-EXPORT_SYMBOL(_ni_bitmap);
-EXPORT_SYMBOL(_zb_findmap);
-
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/kernel/setup.c linux.15p9/arch/s390/kernel/setup.c
--- linux.vanilla/arch/s390/kernel/setup.c	Tue Jan  4 21:18:41 2000
+++ linux.15p9/arch/s390/kernel/setup.c	Thu Feb 17 13:32:33 2000
@@ -2,7 +2,7 @@
  *  arch/s390/kernel/setup.c
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Hartmut Penner (hp@de.ibm.com),
  *               Martin Schwidefsky (schwidefsky@de.ibm.com)
  *
@@ -102,12 +102,15 @@
 #ifndef __SMP__
 void machine_restart(char * __unused)
 {
+  reipl(S390_lowcore.ipl_device); 
+#if 0
         if (MACHINE_IS_VM) {
                 cpcmd("IPL", NULL, 0);
         } else {
                 /* FIXME: how to reipl ? */
                 disabled_wait(2);
         }
+#endif
 }
 
 void machine_halt(void)
@@ -151,11 +154,9 @@
 __initfunc(void setup_arch(char **cmdline_p,
         unsigned long * memory_start_p, unsigned long * memory_end_p))
 {
-        unsigned long memory_start, memory_end;
-        char c = ' ', *to = command_line, *from = COMMAND_LINE;
         static unsigned int smptrap=0;
-        unsigned long delay = 0;
-        int len = 0;
+        unsigned long memory_start, memory_end;
+        char c, cn, *to, *from;
 
         if (smptrap)
                 return;
@@ -187,10 +188,6 @@
         rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
         rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
 #endif
-	/* nasty stuff with PARMAREAs. we use head.S or parameterline
-	  if (!MOUNT_ROOT_RDONLY)
-	  root_mountflags &= ~MS_RDONLY;
-	*/
         memory_start = (unsigned long) &_end;    /* fixit if use $CODELO etc*/
 	memory_end = MEMORY_SIZE;
         init_task.mm->start_code = PAGE_OFFSET;
@@ -202,6 +199,9 @@
         memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
         saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
 
+        c = ' ';
+        from = COMMAND_LINE;
+        to = command_line;
         for (;;) {
                 /*
                  * "mem=XXX[kKmM]" sets memsize != 32M
@@ -219,6 +219,8 @@
                         }
                 }
                 if (c == ' ' && strncmp(from, "ipldelay=", 9) == 0) {
+                        unsigned long delay;
+
 			if (to != command_line) to--;
                         delay = simple_strtoul(from+9, &from, 0);
 			if (*from == 's' || *from == 'S') {
@@ -230,10 +232,13 @@
 			}
 			tod_wait(delay);
                 }
-                c = *(from++);
-                if (!c)
+                cn = *(from++);
+                if (!cn)
                         break;
-                if (COMMAND_LINE_SIZE <= ++len)
+                if (cn == ' ' && c == ' ')
+                        continue;  /* remove additional spaces */
+                c = cn;
+                if (to - command_line >= COMMAND_LINE_SIZE)
                         break;
                 *(to++) = c;
         }
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/kernel/signal.c linux.15p9/arch/s390/kernel/signal.c
--- linux.vanilla/arch/s390/kernel/signal.c	Tue Jan  4 21:18:41 2000
+++ linux.15p9/arch/s390/kernel/signal.c	Thu Feb 17 13:33:59 2000
@@ -2,15 +2,18 @@
  *  arch/s390/kernel/signal.c
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
  *
- *  based on PPC & i386 signal handling by  Linus Torvalds &  Gary Thomas 
+ *    Based on Intel version
+ * 
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  *
  *  1997-11-28  Modified for POSIX.1b signals by Richard Henderson
  */
 
 #include <linux/config.h>
+
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
@@ -24,38 +27,36 @@
 #include <linux/stddef.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
-#if CONFIG_BINFMT_TOC
-#include <linux/toc.h>
-#endif
-/*
- * These are the flags in the MSR that the user is allowed to change
- * by modifying the saved value of the MSR on the stack.  SE and BE
- * should not be in this list since gdb may want to change these.  I.e,
- * you should be able to step out of a signal handler to see what
- * instruction executes next after the signal handler completes.
- * Alternately, if you stepped into a signal handler, you should be
- * able to continue 'til the next breakpoint from within the signal
- * handler, even if the handler returns.
- */
-
 
-#define __390_TO_DO__    0
-#define __390_NEEDED__   0 
 #define DEBUG_SIG 0
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-#ifndef MIN
-#define MIN(a,b) (((a) < (b)) ? (a) : (b))
-#endif
-
-int do_signal(struct pt_regs *reg,sigset_t *oldset);
-extern int sys_wait4(pid_t pid, unsigned long *stat_addr,
-		     int options, unsigned long *ru);
-
-
+/* pretcode & sig are used to store the return addr on Intel
+   & the signal no as the first parameter we do this differently
+   using gpr14 & gpr2. */
+
+#define SIGFRAME_COMMON \
+__u8     callee_used_stack[__SIGNAL_FRAMESIZE]; \
+struct sigcontext sc; \
+sigregs sregs; \
+__u8 retcode[S390_SYSCALL_SIZE];
 
+typedef struct 
+{
+	SIGFRAME_COMMON
+} sigframe;
 
+typedef struct 
+{
+	SIGFRAME_COMMON
+	struct siginfo info;
+	struct ucontext uc;
+} rt_sigframe;
+
+asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
+			 int options, unsigned long *ru);
+asmlinkage int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
 
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
@@ -81,10 +82,6 @@
 	  }
 }
 
-
-//
-// N.B. This hasn't been tested it just compiles easily
-//
 asmlinkage int sys_rt_sigsuspend(struct pt_regs * regs,sigset_t *unewset, size_t sigsetsize)
 {
 	sigset_t saveset, newset;
@@ -103,8 +100,8 @@
 	recalc_sigpending(current);
 	spin_unlock_irq(&current->sigmask_lock);
 	regs->gprs[2]	= -EINTR;
-	while (1) 
-	  {
+
+	while (1) {
 		current->state = TASK_INTERRUPTIBLE;
 		schedule();
 		if (do_signal(regs, &saveset))
@@ -112,28 +109,14 @@
 	  }
 }
 
-asmlinkage int sys_rt_sigreturn(unsigned long __unused)
-{
-	printk("sys_rt_sigreturn(): %s/%d not yet implemented.\n",
-	       current->comm,current->pid);
-	do_exit(SIGSEGV);
-}
-
 asmlinkage int
-sys_sigaltstack(const stack_t *uss, stack_t *uoss)
-{
-	struct pt_regs *regs = (struct pt_regs *) &uss;
-	return do_sigaltstack(uss, uoss, regs->gprs[15]);
-}
-
-
-asmlinkage int sys_sigaction(int sig, const struct old_sigaction *act,struct old_sigaction *oact)
+sys_sigaction(int sig, const struct old_sigaction *act,
+	      struct old_sigaction *oact)
 {
 	struct k_sigaction new_ka, old_ka;
 	int ret;
 
-	if (act) 
-	  {
+	if (act) {
 		old_sigset_t mask;
 		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
 		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
@@ -146,181 +129,268 @@
 
 	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 
-	if (!ret && oact) 
-	  {
+	if (!ret && oact) {
 		if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
-
-
-		    __put_user((u32)old_ka.sa.sa_handler,&oact->sa_handler) ||
-		    __put_user((u32)old_ka.sa.sa_restorer, &oact->sa_restorer))
+		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
+		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
 			return -EFAULT;
 		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
 		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
 	  }
+
 	return ret;
 }
 
-/*
- * When we have signals to deliver, we set up on the
- * user stack, going down from the original stack pointer:
- *	a sigregs struct
- *	one or more sigcontext structs
- *	a gap of __SIGNAL_FRAMESIZE bytes
- *
- * Each of these things must be a multiple of 16 bytes in size.
- *
- * XXX ultimately we will have to stack up a siginfo and ucontext
- * for each rt signal.
- */
+asmlinkage int
+sys_sigaltstack(const stack_t *uss, stack_t *uoss)
+{
+	struct pt_regs *regs = (struct pt_regs *) &uss;
+	return do_sigaltstack(uss, uoss, regs->gprs[15]);
+}
 
-struct sigregs {
-	user_regs_struct user_regs;
 
-        unsigned short   tramp[1];
-        /* Programs using the rs6000/xcoff abi can save up to 19 gp regs
-           and 18 fp regs below sp before decrementing it. */
-};   
 
 
-int sys_sigreturn(struct pt_regs *regs)
+static int save_sigregs(struct pt_regs *regs,sigregs *sregs)
 {
-	struct sigcontext_struct *sc, sigctx;
-	struct sigregs *sr;
-	int ret;
-        user_regs_struct saved_regs;  
+	int err;
+	s390_fp_regs fpregs;
+  
+	err = __copy_to_user(&sregs->regs,regs,sizeof(s390_regs_common));
+	if(!err)
+	{
+		save_fp_regs(&fpregs);
+		err=__copy_to_user(&sregs->fpregs,&fpregs,sizeof(fpregs));
+	}
+	return(err);
+	
+}
+
+static int restore_sigregs(struct pt_regs *regs,sigregs *sregs)
+{
+	int err;
+	s390_fp_regs fpregs;
+	psw_t saved_psw=regs->psw;
+	err=__copy_from_user(regs,&sregs->regs,sizeof(s390_regs_common));
+	if(!err)
+	{
+		regs->orig_gpr2 = -1;		/* disable syscall checks */
+		regs->psw.mask=(saved_psw.mask&~PSW_MASK_DEBUGCHANGE)|
+		(regs->psw.mask&PSW_MASK_DEBUGCHANGE);
+		regs->psw.addr=(saved_psw.addr&~PSW_ADDR_DEBUGCHANGE)|
+		(regs->psw.addr&PSW_ADDR_DEBUGCHANGE);
+		err=__copy_from_user(&fpregs,&sregs->fpregs,sizeof(fpregs));
+		if(!err)
+			restore_fp_regs(&fpregs);
+	}
+	return(err);
+}
+
+static int
+restore_sigcontext(struct sigcontext *sc, pt_regs *regs,
+		 sigregs *sregs,sigset_t *set)
+{
+	unsigned int err;
+
+	err=restore_sigregs(regs,sregs);
+	if(!err)
+		err=__copy_from_user(&set->sig,&sc->oldmask,SIGMASK_COPY_SIZE);
+		return(err);
+}
+
+int sigreturn_common(struct pt_regs *regs,int framesize)
+{
+	sigframe *frame = (sigframe *)regs->gprs[15];
 	sigset_t set;
-	unsigned long prevsp;
-	routine_descriptor tempdes;
 
-	sc = (struct sigcontext_struct *)(regs->gprs[15] + __SIGNAL_FRAMESIZE);
-	if (copy_from_user(&sigctx, sc, sizeof(sigctx)))
-		goto badframe;
-	memcpy(&set.sig[0],&sigctx.oldmask[0],SIGMASK_COPY_SIZE);
+	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+		return -1;
+	if (restore_sigcontext(&frame->sc,regs,&frame->sregs,&set))
+	        return -1;
 	sigdelsetmask(&set, ~_BLOCKABLE);
 	spin_lock_irq(&current->sigmask_lock);
 	current->blocked = set;
 	recalc_sigpending(current);
 	spin_unlock_irq(&current->sigmask_lock);
+	return 0;
+}
 
-	sc++;			/* Look at next sigcontext */
-	if (sc == (struct sigcontext_struct *)(sigctx.regs)) {
-		/* Last stacked signal - restore registers */
-		sr = (struct sigregs *) sigctx.regs;
-		if (copy_from_user(&saved_regs, &sr->user_regs,
-				   sizeof(sr->user_regs)))
-			goto badframe;
-		saved_regs.psw.mask=(regs->psw.mask&~PSW_MASK_DEBUGCHANGE)
-			|(saved_regs.psw.mask&PSW_MASK_DEBUGCHANGE);
-		saved_regs.psw.addr=(regs->psw.addr&~PSW_ADDR_DEBUGCHANGE)
-			|(saved_regs.psw.addr&PSW_ADDR_DEBUGCHANGE);
-		memcpy(regs,&saved_regs,sizeof(s390_regs));
-		restore_fp_regs(&saved_regs.fp_regs);
-		ret = regs->gprs[2];
+asmlinkage int sys_sigreturn(struct pt_regs *regs)
+{
 
-	} else {
-		/* More signals to go */
-		regs->gprs[15] = (unsigned long)sc - __SIGNAL_FRAMESIZE;
-		if (copy_from_user(&sigctx, sc, sizeof(sigctx)))
+	if (sigreturn_common(regs,sizeof(sigframe)))
 			goto badframe;
-		sr = (struct sigregs *) sigctx.regs;
-		regs->gprs[2] = ret = sigctx.signal;
-#if DEBUG_SIG
-		regs->gprs[3] = (unsigned long) sr; // My best guess says this is used for debugging only DJB
-#endif
-		regs->gprs[14] = (unsigned long) sr->tramp; // return address
+	return regs->gprs[2];
 		
-		if(uses_routine_descriptors())
-		{
-		   if(copy_from_user(&tempdes,(char *)sigctx.handler,sizeof(tempdes)))
-		      goto badframe;
-		   fix_routine_descriptor_regs(&tempdes,regs);
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
 		}
-		else
-		   regs->psw.addr = FIX_PSW(sigctx.handler);
 
-		if (get_user(prevsp, &sr->user_regs.gprs[15])
-		    || put_user(prevsp, (unsigned long *) regs->gprs[15]))
+asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
+{
+	rt_sigframe *frame = (rt_sigframe *)regs->gprs[15];
+	stack_t st;
+
+	if (sigreturn_common(regs,sizeof(rt_sigframe)))
 			goto badframe;
-	}
-	return ret;
+	if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
+		goto badframe;
+	/* It is more difficult to avoid calling this function than to
+	   call it and ignore errors.  */
+	do_sigaltstack(&st, NULL, regs->gprs[15]);
+	return regs->gprs[2];
 
 badframe:
-	lock_kernel();
-	do_exit(SIGSEGV);
+	force_sig(SIGSEGV, current);
+	return 0;
 }	
 
-
 /*
  * Set up a signal frame.
  */
-void setup_frame(struct pt_regs *regs, struct sigregs *frame,unsigned long newsp)
+
+
+/*
+ * Determine which stack to use..
+ */
+static inline void *
+get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
 {
-	struct sigcontext_struct *sc = (struct sigcontext_struct *) newsp;
-	s390_fp_regs fpregs;
+	unsigned long sp;
 
-	routine_descriptor tempdes,*tempdesptr;
+	/* Default to using normal stack */
+	sp = regs->gprs[15];
 
-	if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto badframe;
-	save_fp_regs(&fpregs);
-	if (__copy_to_user(&frame->user_regs, regs, sizeof(s390_regs))
-	    || __copy_to_user(&frame->user_regs.fp_regs,&fpregs,sizeof(fpregs))
-	    || __put_user(0x0A77, &frame->tramp[0]))    /* SVC 0x77 */
-		goto badframe;
-	newsp -= __SIGNAL_FRAMESIZE;
-	if (put_user(regs->gprs[15], (unsigned long *)newsp) || get_user(regs->gprs[2], &sc->signal))
-		goto badframe;
+	/* This is the X/Open sanctioned signal stack switching.  */
+	if (ka->sa.sa_flags & SA_ONSTACK) {
+		if (! on_sig_stack(sp))
+			sp = current->sas_ss_sp + current->sas_ss_size;
+	}
 
-	if(uses_routine_descriptors())
-	{
-	    if(get_user(tempdesptr, (routine_descriptor **)& sc->handler)
-	       || copy_from_user(&tempdes,tempdesptr,sizeof(tempdes)))
-	       goto badframe;
-	    fix_routine_descriptor_regs(&tempdes,regs);
+	/* This is the legacy signal stack switching. */
+	else if (!user_mode(regs) &&
+		 !(ka->sa.sa_flags & SA_RESTORER) &&
+		 ka->sa.sa_restorer) {
+		sp = (unsigned long) ka->sa.sa_restorer;
 	}
-	else
+
+	return (void *)((sp - frame_size) & -8ul);
+}
+
+static void *setup_frame_common(int sig, struct k_sigaction *ka,
+			sigset_t *set, struct pt_regs * regs,
+				int frame_size,u16 retcode)
 	{
-	   if(get_user(regs->psw.addr, (void **) & sc->handler))
-		goto badframe;
-	   regs->psw.addr=FIX_PSW(regs->psw.addr);
+	sigframe *frame;
+	int err;
+
+	frame = get_sigframe(ka, regs,frame_size);
+	if (!access_ok(VERIFY_WRITE, frame,frame_size))
+		return 0;
+	err = save_sigregs(regs,&frame->sregs);
+	if(!err)
+		err=__put_user(&frame->sregs,&frame->sc.sregs);
+	if(!err)
+
+		err=__copy_to_user(&frame->sc.oldmask,&set->sig,SIGMASK_COPY_SIZE);
+	if(!err)
+	{
+		regs->gprs[2]=(current->exec_domain
+		           && current->exec_domain->signal_invmap
+		           && sig < 32
+		           ? current->exec_domain->signal_invmap[sig]
+		           : sig);
+		/* Set up registers for signal handler */
+		regs->gprs[15] = (addr_t)frame;
+		regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
+	}
+	/* Set up to return from userspace.  If provided, use a stub
+	   already in userspace.  */
+	if (ka->sa.sa_flags & SA_RESTORER) {
+                regs->gprs[14] = FIX_PSW(ka->sa.sa_restorer);
+	} else {
+                regs->gprs[14] = FIX_PSW(frame->retcode);
+		err |= __put_user(retcode, (u16 *)(frame->retcode));
 	}
-	regs->gprs[15] = newsp;
+	return(err ? 0:frame);
+}
+
+static void setup_frame(int sig, struct k_sigaction *ka,
+			sigset_t *set, struct pt_regs * regs)
+{
+
+	if(!setup_frame_common(sig,ka,set,regs,sizeof(sigframe),
+		    (S390_SYSCALL_OPCODE|__NR_sigreturn)))
+		goto give_sigsegv;
 #if DEBUG_SIG
-	regs->gprs[3] = (unsigned long) frame;
+	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
+		current->comm, current->pid, frame, regs->eip, frame->pretcode);
 #endif
-	regs->gprs[14] = (unsigned long) frame->tramp;
-
 	return;
 
-badframe:
+give_sigsegv:
+	if (sig == SIGSEGV)
+		ka->sa.sa_handler = SIG_DFL;
+	force_sig(SIGSEGV, current);
+}
+
+static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+			   sigset_t *set, struct pt_regs * regs)
+{
+	rt_sigframe *frame;
+	addr_t      orig_sp=regs->gprs[15];
+	int err;
+
+	if((frame=setup_frame_common(sig,ka,set,regs,sizeof(rt_sigframe),
+		    (S390_SYSCALL_OPCODE|__NR_rt_sigreturn)))==0)
+		goto give_sigsegv;
+	
+	err = __copy_to_user(&frame->info, info, sizeof(*info));
+
+	/* Create the ucontext.  */
+	err |= __put_user(0, &frame->uc.uc_flags);
+	err |= __put_user(0, &frame->uc.uc_link);
+	err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+	err |= __put_user(sas_ss_flags(orig_sp),
+			  &frame->uc.uc_stack.ss_flags);
+	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+	regs->gprs[3] = (u32)&frame->info;
+	regs->gprs[4] = (u32)&frame->uc;
+
+	if (err)
+		goto give_sigsegv;
+
 #if DEBUG_SIG
-	printk("badframe in setup_frame, regs=%p frame=%p newsp=%lx\n",
-	       regs, frame, newsp);
+	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
+		current->comm, current->pid, frame, regs->eip, frame->pretcode);
 #endif
-	lock_kernel();
-	do_exit(SIGSEGV);
+	return;
+
+give_sigsegv:
+	if (sig == SIGSEGV)
+		ka->sa.sa_handler = SIG_DFL;
+	force_sig(SIGSEGV, current);
 }
 
 /*
  * OK, we're invoking a handler
  */
-void
-handle_signal(unsigned long sig, struct k_sigaction *ka,
-	      siginfo_t *info, sigset_t *oldset, struct pt_regs * regs,
-	      unsigned long *newspp, unsigned long frame)
-{
-	struct sigcontext_struct *sc;
 
-	if (regs->trap == 0x20) /* System Call! */
-	{
-		switch(regs->gprs[2])
+static void
+handle_signal(unsigned long sig, struct k_sigaction *ka,
+	      siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
 		{
+	/* Are we from a system call? */
+	if (regs->orig_gpr2 >= 0) {
+		/* If so, check system call restarting.. */
+		switch (regs->gprs[2]) {
 		case -ERESTARTNOHAND:
 				regs->gprs[2] = -EINTR;
 				break;
+
 		case -ERESTARTSYS:
-			if (!(ka->sa.sa_flags & SA_RESTART)) 
-			{
+				if (!(ka->sa.sa_flags & SA_RESTART)) {
 				regs->gprs[2] = -EINTR;
 				break;
 			}
@@ -328,20 +398,14 @@
 		case -ERESTARTNOINTR:
 			regs->gprs[2] = regs->orig_gpr2;
 			regs->psw.addr -= 2;	      
-                        /* Back up & retry system call */
 		}
 	}
-	/* Put another sigcontext on the stack */
-	*newspp -= sizeof(*sc);
-	sc = (struct sigcontext_struct *) *newspp;
-	if (verify_area(VERIFY_WRITE, sc, sizeof(*sc)))
-		goto badframe;
 
-	if (__put_user((unsigned long) ka->sa.sa_handler, &sc->handler)
-	    || copy_to_user(&sc->oldmask[0],&oldset->sig[0],SIGMASK_COPY_SIZE)
-	    || __put_user((u32)((struct pt_regs *)frame), &sc->regs)
-	    || __put_user(sig, &sc->signal))
-		goto badframe;
+	/* Set up the stack frame */
+	if (ka->sa.sa_flags & SA_SIGINFO)
+		setup_rt_frame(sig, ka, info, oldset, regs);
+	else
+		setup_frame(sig, ka, oldset, regs);
 
 	if (ka->sa.sa_flags & SA_ONESHOT)
 		ka->sa.sa_handler = SIG_DFL;
@@ -353,35 +417,34 @@
 		recalc_sigpending(current);
 		spin_unlock_irq(&current->sigmask_lock);
 	}
-	return;
-
-badframe:
-#if DEBUG_SIG
-	printk("badframe in handle_signal, regs=%p frame=%lx newsp=%lx\n",
-	       regs, frame, *newspp);
-	printk("sc=%p sig=%d ka=%p info=%p oldset=%p\n", sc, sig, ka, info, oldset);
-#endif
-	lock_kernel();
-	do_exit(SIGSEGV);
 }
 
-
 /*
  * Note that 'init' is a special process: it doesn't get signals it doesn't
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
+ *
+ * Note that we go through the signals twice: once to check the signals that
+ * the kernel can handle, and then we build all the user-level signal handling
+ * stack-frames in one go after that.
  */
 int do_signal(struct pt_regs *regs,sigset_t *oldset)
 {
 	siginfo_t info;
 	struct k_sigaction *ka;
-	unsigned long frame, newsp;
+
+	/*
+	 * We want the common case to go fast, which
+	 * is why we may in certain cases get here from
+	 * kernel mode. Just return without doing anything
+	 * if so.
+	 */
+	if (!user_mode(regs))
+		return 1;
 
 	if (!oldset)
 		oldset = &current->blocked;
 
-	newsp = frame = regs->gprs[15] - sizeof(struct sigregs);
-
 	for (;;) {
 		unsigned long signr;
 
@@ -479,41 +542,19 @@
 		}
 
 		/* Whee!  Actually deliver the signal.  */
-		handle_signal(signr, ka, &info, oldset, regs, &newsp, frame);
+		handle_signal(signr, ka, &info, oldset, regs);
+		return 1;
 	}
 
-	if (
-	    regs->trap == 0x20 /* System Call! */ &&
-	    ((int)regs->gprs[2] == -ERESTARTNOHAND ||
-	     (int)regs->gprs[2] == -ERESTARTSYS ||
-	     (int)regs->gprs[2] == -ERESTARTNOINTR)) {
+	/* Did we come from a system call? */
+	if ( regs->trap == 0x20 /* System Call! */ ) {
+		/* Restart the system call - no handlers present */
+		if (regs->gprs[2] == -ERESTARTNOHAND ||
+		    regs->gprs[2] == -ERESTARTSYS ||
+		    regs->gprs[2] == -ERESTARTNOINTR) {
 		regs->gprs[2] = regs->orig_gpr2;
-		regs->psw.addr -= 2;	      /* Back up & retry system call */
+			regs->psw.addr -= 2;
 	}
-
-	if (newsp == frame)
-		return 0;		/* no signals delivered */
-
-	setup_frame(regs, (struct sigregs *) frame, newsp);
-	return 1;
 }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+	return 0;
+}
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/kernel/smp.c linux.15p9/arch/s390/kernel/smp.c
--- linux.vanilla/arch/s390/kernel/smp.c	Tue Jan  4 21:18:41 2000
+++ linux.15p9/arch/s390/kernel/smp.c	Thu Feb 17 13:34:15 2000
@@ -2,7 +2,7 @@
  *  arch/s390/kernel/smp.c
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
  *               Martin Schwidefsky (schwidefsky@de.ibm.com)
  *
@@ -33,7 +33,7 @@
 #include <asm/string.h>
 
 #include "cpcmd.h"
-#include "irq.h"
+#include <asm/irq.h>
 
 /* prototypes */
 extern void update_one_process( struct task_struct *p,
@@ -85,12 +85,15 @@
 void do_machine_restart(void)
 {
         smp_send_stop();
+	reipl(S390_lowcore.ipl_device); 
+#if 0
         if (MACHINE_IS_VM) {
                 cpcmd("IPL", NULL, 0);
         } else {
                 /* FIXME: how to reipl ? */
                 disabled_wait(2);
         }
+#endif
 }
 
 void machine_restart(char * __unused) 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/kernel/time.c linux.15p9/arch/s390/kernel/time.c
--- linux.vanilla/arch/s390/kernel/time.c	Tue Jan  4 21:18:41 2000
+++ linux.15p9/arch/s390/kernel/time.c	Thu Feb 17 13:34:15 2000
@@ -31,8 +31,6 @@
 #include <linux/timex.h>
 #include <linux/config.h>
 
-#include "irq.h"
-
 
 extern volatile unsigned long lost_ticks;
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/kernel/traps.c linux.15p9/arch/s390/kernel/traps.c
--- linux.vanilla/arch/s390/kernel/traps.c	Tue Jan  4 21:18:41 2000
+++ linux.15p9/arch/s390/kernel/traps.c	Thu Feb 17 13:34:15 2000
@@ -2,7 +2,7 @@
  *  arch/s390/kernel/traps.c
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
  *
@@ -255,7 +255,7 @@
 		get_user(*((__u16 *) opcode), location);
 	else
 		*((__u16 *)opcode)=*((__u16 *)location);
-	if(*((__u16 *)opcode)==BREAKPOINT_U16)
+	if(*((__u16 *)opcode)==S390_BREAKPOINT_U16)
         {
 		if(do_debugger_trap(regs,SIGTRAP))
 			do_sig=1;
@@ -443,6 +443,8 @@
         pgm_check_table[4] = &do_page_fault;
         pgm_check_table[0x10] = &do_page_fault;
         pgm_check_table[0x11] = &do_page_fault;
+        pgm_check_table[0x1C] = &privileged_op;
+
 }
 
 
@@ -456,6 +458,13 @@
 		per_info->lowcore.words.access_id=S390_lowcore.per_access_id;
 	}
 	if(do_debugger_trap(regs,SIGTRAP))
+	{
+		/* I've seen this possibly a task structure being reused ? */
 		printk("Spurious per exception detected\n");
+		printk("switching off per tracing for this task.\n");
+		show_crashed_task_info();
+		/* Hopefully switching off per tracing will help us survive */
+		regs->psw.mask &= ~PSW_PER_MASK;
+	}
 }
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/tools/dasdfmt/dasdfmt.8 linux.15p9/arch/s390/tools/dasdfmt/dasdfmt.8
--- linux.vanilla/arch/s390/tools/dasdfmt/dasdfmt.8	Thu Jan  1 01:00:00 1970
+++ linux.15p9/arch/s390/tools/dasdfmt/dasdfmt.8	Thu Feb 17 13:34:25 2000
@@ -0,0 +1,74 @@
+.TH DASDFMT 8 "Tue Jan 25 2000"
+.UC 4
+.SH NAME
+dasdfmt \- formatting of DSAD (ECKD) disk drives.
+.SH SYNOPSIS
+\fBdasdfmt\fR [-tvyV] [-b \fIblockSize\fR] [\fIblockRange\fI]
+	\fIdiskSpec\fR
+.SH DESCRIPTION
+\fBdasdfmt\fR formats a DASD (ECKD) disk drive to prepare it
+for usage with Linux for S/390. \fBWARNING\fR: Incautious usage of
+\fBdasdfmt\fR can result in \fBLOSS OF DATA\fR.
+
+.SH OPTIONS
+.TP
+\fB-t\fR
+Disables any modification of the disk drive. \fBdasdfmt\fR just prints
+out, what it \fBwould\fR do.
+
+.TP
+\fB-v\fR
+Increases verbosity.
+
+.TP
+\fB-y\fR 
+Start formatting without further user-confirmation.
+
+.TP
+\fB-V\fR 
+Print version number and exit.
+
+.TP
+\fB-b\fR \fIblockSize\fR
+Specify blocksize to be used. \fIblocksize\fR must be a positive integer
+and always be a power of two. Due due some limitations in the driver,
+it is \fBstrongly\fR recommended to use a \fIblockSize\fR of \fI4096\fR.
+
+.TP
+\fIblockRange\fR
+This parameter specifies the number of the first and last block to be
+formatted. If this parameter is \fBomitted\fR, formatting the \fBwhole\fR disk
+is assumed. The \fIblockRange\fR can be specified in two different formats:
+.sp
+	\fB-s\fR \fIstartBlock\fR \fB-e\fR \fIendBlock\fR
+.br
+or
+.br
+	\fB-r\fR \fIstartBlock\fR-\fIendBlock\fR
+.sp
+If \fIstartBlock\fR is omitted, block \fB0\fR is assumed. If
+\fIendBlock\fR is omitted, the last block of the disk is assumed.
+
+.TP
+\fIdiskSpec\fR
+This parameter specified the device to be formatted. It also can be
+given in two variants:
+.sp
+	\fB-f\fR \fB/dev/dd\fR\fIX\fR
+.br
+or
+.br
+	\fB-n\fR \fIdevnum\fR
+.sp
+The first form uses the commonly used
+.SM UNIX
+device notation where \fIX\fR is a single lowercase letter.
+The second form uses simply the VM vdev number.
+
+.SH BUGS
+None so far ;-)
+
+.SH AUTHOR
+.nf
+This man-page was written by Fritz Elfert <felfert@to.com>
+.fi
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/tools/dasdfmt/dasdfmt.c linux.15p9/arch/s390/tools/dasdfmt/dasdfmt.c
--- linux.vanilla/arch/s390/tools/dasdfmt/dasdfmt.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/arch/s390/tools/dasdfmt/dasdfmt.c	Thu Feb 17 13:34:37 2000
@@ -0,0 +1,639 @@
+/*
+ *
+ * dasdfmt.c
+ *
+ *  S390 version
+ *    Copyright (C) 1999,2000 IBM Corporation
+ *    Author(s): Utz Bacher, <utz.bacher@de.ibm.com>
+ *
+ *  Device-in-use-checks by Fritz Elfert, <felfert@to.com>
+ *
+ * Still to do:
+ *   detect non-switch parameters ("dasdfmt -n 170 XY") and complain about them 
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <getopt.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <dirent.h>
+#include <mntent.h>
+#include "../../../drivers/s390/block/dasd.h" /* uses DASD_PARTN_BITS */
+#define __KERNEL__ /* we want to use kdev_t and not have to define it */
+#include <linux/kdev_t.h>
+#undef __KERNEL__
+
+#define EXIT_MISUSE 1
+#define EXIT_BUSY 2
+#define TEMPFILENAME "/tmp/ddfXXXXXX"
+#define TEMPFILENAMECHARS 8  /* 8 characters are fixed in all temp filenames */
+#define IOCTL_COMMAND 'D' << 8
+#define SLASHDEV "/dev/"
+#define PROC_DASD_DEVICES "/proc/dasd/devices"
+#define DASD_DRIVER_NAME "dasd"
+#define PROC_LINE_LENGTH 80
+#define ERR_LENGTH 80
+
+#define MAX_FILELEN NAME_MAX+PATH_MAX
+
+#define GIVEN_DEVNO 1
+#define GIVEN_MAJOR 2
+#define GIVEN_MINOR 4
+
+#define CHECK_START 1
+#define CHECK_END 2
+#define CHECK_BLKSIZE 4
+#define CHECK_ALL ~0
+
+#define ERRMSG(x...) {fflush(stdout);fprintf(stderr,x);}
+#define ERRMSG_EXIT(ec,x...) {fflush(stdout);fprintf(stderr,x);exit(ec);}
+
+#define CHECK_SPEC_MAX_ONCE(i,str) \
+	{if (i>1) \
+		ERRMSG_EXIT(EXIT_MISUSE,"%s: " str " " \
+			"can only be specified once\n",prog_name);}
+
+#define PARSE_PARAM_INTO(x,param,base,str) \
+	{x=(int)strtol(param,&endptr,base); \
+	if (*endptr) \
+		ERRMSG_EXIT(EXIT_MISUSE,"%s: " str " " \
+			"is in invalid format\n",prog_name);}
+
+typedef struct {
+	int start_unit;
+	int stop_unit;
+	int blksize;
+} format_data_t;
+
+char prog_name[]="dasd_format";
+char tempfilename[]=TEMPFILENAME;
+
+void
+exit_usage(int exitcode)
+{
+	printf("Usage: %s [-htvyV] [-b blocksize] <range> <diskspec>\n\n",
+	       prog_name);
+	printf("       where <range> is either\n");
+	printf("           -s start_track -e end_track\n");
+	printf("       or\n");
+	printf("           -r start_track-end_track\n");
+	printf("       and <diskspec> is either\n");
+	printf("           -f /dev/ddX\n");
+	printf("       or\n");
+	printf("           -n <s390-devnr>\n");
+	exit(exitcode);
+}
+
+void
+get_xno_from_xno(int *devno,kdev_t *major_no,kdev_t *minor_no,int mode)
+{
+	FILE *file;
+	int d,rc;
+	kdev_t mi,ma;
+	int mi_i,ma_i; /* for scanf :-( */
+	char line[PROC_LINE_LENGTH];
+
+	file=fopen(PROC_DASD_DEVICES,"r");
+	if (file==NULL)
+		ERRMSG_EXIT(EXIT_FAILURE,"%s: failed to open " \
+			PROC_DASD_DEVICES ": %s (do you have the /proc " \
+			"filesystem enabled?)\n",prog_name,strerror(errno));
+
+	fgets(line,sizeof(line),file); /* omit first line */
+	while (fgets(line,sizeof(line),file)!=NULL) {
+		rc=sscanf(line,"%X%d%d",&d,&ma_i,&mi_i);
+		ma=ma_i;
+		mi=mi_i;
+		if ( (rc==3) &&
+			!((d!=*devno)&&(mode&GIVEN_DEVNO)) &&
+			!((ma!=*major_no)&&(mode&GIVEN_MAJOR)) &&
+			!((mi!=*minor_no)&&(mode&GIVEN_MINOR)) ) {
+			*devno=d;
+			*major_no=ma;
+			*minor_no=mi;
+			/* yes, this is a quick exit, but the easiest way */
+			fclose(file);
+			return;
+		}
+	}
+	fclose(file);
+
+	ERRMSG_EXIT(EXIT_FAILURE,"%s: failed to find device in the /proc " \
+		"filesystem (are you sure to have the right param line?)\n",
+		prog_name);
+}
+
+char *
+get_devname_from_devno(int devno,int verbosity)
+{
+	kdev_t major_no,minor_no;
+	kdev_t file_major,file_minor;
+	struct stat stat_buf;
+	int rc;
+	int found;
+	char *devname;
+	char tmpname[MAX_FILELEN];
+
+	DIR *dp;
+	struct dirent *direntp;
+
+	/**** get minor number ****/
+	get_xno_from_xno(&devno,&major_no,&minor_no,GIVEN_DEVNO);
+
+	/**** get device file ****/
+	if ((dp=opendir(SLASHDEV)) == NULL)
+		ERRMSG_EXIT(EXIT_FAILURE,"%s: unable to read " SLASHDEV \
+			"\n",prog_name);
+	found=0;
+	while ((direntp=readdir(dp)) != NULL) {
+		strcpy(tmpname,SLASHDEV);
+		strcat(tmpname,direntp->d_name);
+		rc=stat(tmpname,&stat_buf);
+		if (!rc) {
+			file_major=MAJOR(stat_buf.st_rdev);
+			file_minor=MINOR(stat_buf.st_rdev);
+			if ((file_major==major_no) && (file_minor==minor_no)) {
+				found=1;
+				break;
+			}
+		}
+	}
+	if (found) {
+		devname=malloc(strlen(direntp->d_name));
+		strcpy(devname,tmpname);
+	}
+	rc=closedir(dp);
+	if (rc<0) ERRMSG("%s: unable to close directory " SLASHDEV \
+		"; continuing\n",prog_name);
+	if (found)
+		return devname;
+
+	if (verbosity>=1)
+		printf("I didn't find device node in " SLASHDEV \
+			"; trying to create a temporary node\n");
+
+	/**** get temp file and create device node *****/
+	rc=mkstemp(tempfilename);
+	if (rc==-1)
+		ERRMSG_EXIT(EXIT_FAILURE,"%s: failed to get temporary " \
+			"filename: %s\n",prog_name,strerror(errno));
+	close(rc);
+	rc=unlink(tempfilename);
+	
+	rc=mknod(tempfilename,S_IFBLK|0600,MKDEV(major_no,minor_no));
+	if (rc)
+		ERRMSG_EXIT(EXIT_FAILURE,"%s: failed to create temporary " \
+			"device node %s: %s\n",prog_name,tempfilename,
+			strerror(errno));
+	return tempfilename;
+}
+
+char *
+check_param(int mode,format_data_t data)
+{
+	char *s;
+
+	if (NULL==(s=malloc(ERR_LENGTH)))
+		ERRMSG_EXIT(EXIT_FAILURE,"%s: not enough memory.\n",prog_name);
+
+	if ((mode&CHECK_START)&&(data.start_unit<0)) {
+		strcpy(s,"start track must be greater than zero");
+		goto exit;
+	}
+	if ((mode&CHECK_END)&&(data.stop_unit<-1)) {
+		strcpy(s,"end track must be -1 or greater than zero");
+		goto exit;
+	}
+	if ((mode&CHECK_END)&&(data.start_unit>data.stop_unit)&&
+		(data.stop_unit!=-1)) {
+		strcpy(s,"end track must be higher than start track");
+		goto exit;
+	}
+
+	if ((mode&CHECK_BLKSIZE)&&(data.blksize<1)) {
+		strcpy(s,"blocksize must be a positive integer");
+		goto exit;
+	}
+	if (mode&CHECK_BLKSIZE) while (data.blksize>0) {
+		if ((data.blksize%2)&&(data.blksize!=1)) {
+			strcpy(s,"blocksize must be a power of 2");
+			goto exit;
+		}
+		data.blksize/=2;
+	}
+
+	free(s);
+	return NULL;
+exit:
+	return s;
+}
+
+#define ASK_PRINTOUT printf("Please enter %s",output)
+#define ASK_GETBUFFER fgets(buffer,sizeof(buffer),stdin)
+#define ASK_SCANFORNUMBER(var) rc=sscanf(buffer,"%d%c",&var,&c)
+#define ASK_COMPLAIN_FORMAT if ((rc==2)&&(c=='\n')) rc=1; \
+	if (rc==-1) rc=1; /* this happens, if enter is pressed */ \
+	if (rc!=1) printf(" -- wrong input, try again.\n")
+#define ASK_CHECK_PARAM(mode) str=check_param(mode,params); \
+		if (str!=NULL) { printf(" -- %s\n",str); rc=0; free(str); }
+
+format_data_t
+ask_user_for_data(format_data_t params)
+{
+	char buffer[20]; /* should be enough for inputing track numbers */
+	char c;
+	int i,rc;
+	char *str;
+	char output[60],o2[12];
+
+	i=params.start_unit;
+	do {
+		params.start_unit=i;
+		sprintf(output,"the start track of the range to format " \
+			"[%d]: ",i);
+		ASK_PRINTOUT;
+		ASK_GETBUFFER;
+		ASK_SCANFORNUMBER(params.start_unit);
+		ASK_COMPLAIN_FORMAT;
+		ASK_CHECK_PARAM(CHECK_START);
+	} while (rc!=1);
+
+	i=params.stop_unit;
+	do {
+		params.stop_unit=i;
+		sprintf(output,"the end track of the range to format [");
+		if (i==-1) sprintf(o2,"END]: "); else
+			sprintf(o2,"%d]: ",i);
+		strcat(output,o2);
+		ASK_PRINTOUT;
+		ASK_GETBUFFER;
+		if ( (!strcasecmp(buffer,"end")) ||
+			(!strcasecmp(buffer,"end\n")) ) {
+			rc=1;
+			params.stop_unit=-1;
+		} else {
+			ASK_SCANFORNUMBER(params.stop_unit);
+			ASK_COMPLAIN_FORMAT;
+			ASK_CHECK_PARAM(CHECK_END);
+		}
+	} while (rc!=1);
+
+	i=params.blksize;
+	do {
+		params.blksize=i;
+		sprintf(output,"the blocksize of the formatting [%d]: ",i);
+		ASK_PRINTOUT;
+		ASK_GETBUFFER;
+		ASK_SCANFORNUMBER(params.blksize);
+		ASK_COMPLAIN_FORMAT;
+		ASK_CHECK_PARAM(CHECK_BLKSIZE);
+	} while (rc!=1);
+
+	return params;
+}
+
+/* Check if the device we are going to format is mounted.
+ * If true, complain and exit.
+ */
+void
+check_mounted(int major, int minor)
+{
+	FILE *f;
+	int ishift = 0;
+	struct mntent *ment;
+	struct stat stbuf;
+	char line[128];
+
+	/* If whole disk to be formatted ... */
+	if ((minor % (1U << DASD_PARTN_BITS)) == 0) {
+		/* ... ignore partition-selector */
+		minor >>= DASD_PARTN_BITS;
+		ishift = DASD_PARTN_BITS;
+	}
+	/*
+	 * first, check filesystems
+	 */
+	if (!(f = fopen(_PATH_MOUNTED, "r")))
+		ERRMSG_EXIT(EXIT_FAILURE, "%s: %s\n", _PATH_MOUNTED,
+			strerror(errno));
+	while ((ment = getmntent(f))) {
+		if (stat(ment->mnt_fsname, &stbuf) == 0)
+			if ((major == MAJOR(stbuf.st_rdev)) &&
+				(minor == (MINOR(stbuf.st_rdev)>>ishift))) {
+				ERRMSG("%s: device is mounted on %s!!\n",
+					prog_name,ment->mnt_dir);
+				ERRMSG_EXIT(EXIT_BUSY, "If you really want to "
+					"format it, please unmount it.\n");
+			}
+	}
+	fclose(f);
+	/*
+	 * second, check active swap spaces
+	 */
+	if (!(f = fopen("/proc/swaps", "r")))
+		ERRMSG_EXIT(EXIT_FAILURE, "/proc/swaps: %s", strerror(errno));
+	/*
+	 * skip header line
+	 */
+	fgets(line, sizeof(line), f);
+	while (fgets(line, sizeof(line), f)) {
+		char *p;
+		for (p = line; *p && (!isspace(*p)); p++) ;
+		*p = '\0';
+		if (stat(line, &stbuf) == 0)
+			if ((major == MAJOR(stbuf.st_rdev)) &&
+				(minor == (MINOR(stbuf.st_rdev)>>ishift))) {
+				ERRMSG("%s: the device is in use for "
+					"swapping!!\n",prog_name);
+				ERRMSG_EXIT(EXIT_BUSY, "If you really want to "
+					"format it, please use swapoff %s.\n",
+					line);
+			}
+	}
+	fclose(f);
+}
+
+void
+do_format_dasd(char *dev_name,format_data_t format_params,int testmode,
+	int verbosity,int withoutprompt)
+{
+	int fd,rc;
+	struct stat stat_buf;
+	kdev_t minor_no,major_no;
+	int devno;
+	char inp_buffer[5]; /* to contain yes */
+
+	fd=open(dev_name,O_RDWR);
+	if (fd==-1)
+		ERRMSG_EXIT(EXIT_FAILURE,"%s: error opening device %s: " \
+			"%s\n",prog_name,dev_name,strerror(errno));
+
+	if (verbosity>=1) {
+	}
+
+	rc=stat(dev_name,&stat_buf);
+	if (rc) {
+		ERRMSG_EXIT(EXIT_FAILURE,"%s: error occured during stat: " \
+			"%s\n",prog_name,strerror(errno));
+	} else {
+		if (!S_ISBLK(stat_buf.st_mode))
+			ERRMSG_EXIT(EXIT_FAILURE,"%s: file is not a " \
+				"blockdevice.\n",prog_name);
+		major_no=MAJOR(stat_buf.st_rdev);
+		minor_no=MINOR(stat_buf.st_rdev);
+	}
+	check_mounted(major_no, minor_no);
+	
+	if ( ((withoutprompt)&&(verbosity>=1)) ||
+		(!withoutprompt) ) {
+		get_xno_from_xno(&devno,&major_no,&minor_no,
+			GIVEN_MAJOR|GIVEN_MINOR);
+		printf("\nI am going to format the device %s in the " \
+			"following way:\n",dev_name);
+		printf("   Device number of device : 0x%x\n",devno);
+		printf("   Major number of device  : %u\n",major_no);
+		printf("   Minor number of device  : %u\n",minor_no);
+		printf("   Start track             : %d\n" \
+			,format_params.start_unit);
+		printf("   End track               : ");
+		if (format_params.stop_unit==-1)
+			printf("last track of disk\n");
+		else
+			printf("%d\n",format_params.stop_unit);
+		printf("   Blocksize               : %d\n" \
+			,format_params.blksize);
+		if (testmode) printf("Test mode active, omitting ioctl.\n");
+	}
+
+	while (!testmode) {
+		if (!withoutprompt) {
+			printf("\n--->> ATTENTION! <<---\n");
+			printf("All data in the specified range of that " \
+				"device will be lost.\nType yes to continue" \
+				", no will leave the disk untouched: ");
+			fgets(inp_buffer,sizeof(inp_buffer),stdin);
+			if (strcasecmp(inp_buffer,"yes") &&
+				strcasecmp(inp_buffer,"yes\n")) {
+				printf("Omitting ioctl call (disk will " \
+					"NOT be formatted).\n");
+				break;
+			}
+		}
+
+		if ( !(  (withoutprompt)&&(verbosity<1) ))
+			printf("Formatting the device. This may take a " \
+				"while (get yourself a coffee).\n");
+		rc=ioctl(fd,IOCTL_COMMAND,format_params);
+		if (rc)
+			ERRMSG_EXIT(EXIT_FAILURE,"%s: the dasd driver " \
+				"returned with the following error " \
+				"message:\n%s\n",prog_name,strerror(errno));
+		printf("Finished formatting the device.\n");
+
+		break;
+	}
+
+	rc=close(fd);
+	if (rc)
+		ERRMSG("%s: error during close: " \
+			"%s; continuing.\n",prog_name,strerror(errno));
+}
+
+
+
+int main(int argc,char *argv[]) {
+	int verbosity;
+	int testmode;
+	int withoutprompt;
+
+	char *dev_name;
+	int devno;
+	char *dev_filename,*devno_param_str,*range_param_str;
+	char *start_param_str,*end_param_str,*blksize_param_str;
+	
+	format_data_t format_params;
+
+	int rc;
+	int oc;
+	char *endptr;
+
+	char c1,c2,cbuffer[6]; /* should be able to contain -end plus 1 char */
+	int i1,i2;
+	char *str;
+
+	int start_specified,end_specified,blksize_specified;
+	int devfile_specified,devno_specified,range_specified;
+
+	/******************* initialization ********************/
+
+	endptr=NULL;
+
+	/* set default values */
+	format_params.start_unit=0;
+	format_params.stop_unit=-1;
+	format_params.blksize=4096;
+	testmode=0;
+	verbosity=0;
+	withoutprompt=0;
+	start_specified=end_specified=blksize_specified=0;
+	devfile_specified=devno_specified=range_specified=0;
+
+	/*************** parse parameters **********************/
+
+	/* avoid error message generated by getopt */
+	opterr=0;
+
+	while ( (oc=getopt(argc,argv,"r:s:e:b:n:f:hty?vV")) !=EOF) {
+		switch (oc) {
+		case 'y':
+			withoutprompt=1;
+			break;
+
+		case 't':
+			testmode=1;
+			break;
+
+		case 'v':
+			verbosity++;
+			break;
+
+		case '?': /* fall-through */
+		case ':':
+			exit_usage(EXIT_MISUSE);
+
+		case 'h':
+			exit_usage(0);
+
+		case 'V':
+			printf("%s version 0.99\n",prog_name);
+			exit(0);
+
+		case 's' :
+			start_param_str=optarg;
+			start_specified++;
+			break;
+			
+		case 'e' :
+			end_param_str=optarg;
+			end_specified++;
+			break;
+
+		case 'b' :
+			blksize_param_str=optarg;
+			blksize_specified++;
+			break;
+			
+		case 'n' :
+			devno_param_str=optarg;
+			devno_specified++;
+			break;
+		
+		case 'f' :
+			dev_filename=optarg;
+			devfile_specified++;
+			break;
+		case 'r' :
+			range_param_str=optarg;
+			range_specified++;
+			break;
+		}
+	}
+
+	/******************** checking of parameters **************/
+
+	/* convert range into -s and -e */
+	CHECK_SPEC_MAX_ONCE(range_specified,"formatting range");
+
+	while (range_specified) {
+		start_specified++;
+		end_specified++;
+
+		/* scan for 1 or 2 integers, separated by a dash */
+		rc=sscanf(range_param_str,"%d%c%d%c",&i1,&c1,&i2,&c2);
+		if ((rc==3)&&(c1=='-')) {
+			format_params.start_unit=i1;
+			format_params.stop_unit=i2;
+			break;
+		}
+		if (rc==1) {
+			format_params.start_unit=i1;
+			break;
+		}
+
+		/* scan for integer and -END */
+		rc=sscanf(range_param_str,"%d%s",&i1,cbuffer);
+		if ((rc==2)&&(!strcasecmp(cbuffer,"-END"))) {
+			format_params.start_unit=i1;
+			format_params.stop_unit=-1;
+			break;
+		}
+		ERRMSG_EXIT(EXIT_MISUSE,"%s: specified range " \
+			"is in invalid format\n",prog_name);
+	}
+
+	if ((!devfile_specified)&&(!devno_specified))
+		ERRMSG_EXIT(EXIT_MISUSE,"%s: device to format " \
+			"not specified\n",prog_name);
+
+	if ((devfile_specified+devno_specified)>1)
+		ERRMSG_EXIT(EXIT_MISUSE,"%s: device to format " \
+			"can only be specified once\n",prog_name);
+
+	if ((!start_specified)&&(!end_specified)&&(!range_specified)&&
+		(!blksize_specified)) {
+		format_params=ask_user_for_data(format_params);
+	}
+
+	CHECK_SPEC_MAX_ONCE(start_specified,"start track");
+	CHECK_SPEC_MAX_ONCE(end_specified,"end track");
+	CHECK_SPEC_MAX_ONCE(blksize_specified,"blocksize");
+
+	if (devno_specified)
+		PARSE_PARAM_INTO(devno,devno_param_str,16,"device number");
+	if (start_specified&&!range_specified)
+		PARSE_PARAM_INTO(format_params.start_unit,start_param_str,10,
+			"start track");
+	if (end_specified&&!range_specified)
+		PARSE_PARAM_INTO(format_params.stop_unit,end_param_str,10,
+			"end track");
+	if (blksize_specified)
+		PARSE_PARAM_INTO(format_params.blksize,blksize_param_str,10,
+			"blocksize");
+
+	/***********get dev_name *********************/
+	dev_name=(devno_specified)?
+		get_devname_from_devno(devno,verbosity):
+		dev_filename;
+
+	/*** range checking *********/
+	str=check_param(CHECK_ALL,format_params);
+	if (str!=NULL) ERRMSG_EXIT(EXIT_MISUSE,"%s: %s\n",prog_name,str);
+
+	/*************** issue the real command *****************/
+	do_format_dasd(dev_name,format_params,testmode,verbosity,
+		withoutprompt);
+
+	/*************** cleanup ********************************/
+	if (strncmp(dev_name,TEMPFILENAME,TEMPFILENAMECHARS)==0) {
+		rc=unlink(dev_name);
+		if ((rc)&&(verbosity>=1))
+			ERRMSG("%s: temporary device node %s could not be " \
+				"removed: %s\n",prog_name,dev_name,
+				strerror(errno));
+	} else {
+		if (devno_specified) {
+			/* so we have allocated space for the filename */
+			free(dev_name);
+		}
+	}
+
+	return 0;
+}
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/tools/silo/Makefile linux.15p9/arch/s390/tools/silo/Makefile
--- linux.vanilla/arch/s390/tools/silo/Makefile	Thu Jan  1 01:00:00 1970
+++ linux.15p9/arch/s390/tools/silo/Makefile	Thu Feb 17 13:34:37 2000
@@ -0,0 +1,8 @@
+all: silo
+
+silo: silo.o cfg.o
+	$(CROSS_COMPILE)gcc -o $@ $^
+
+clean:
+	rm -f *.o silo
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/tools/silo/cfg.c linux.15p9/arch/s390/tools/silo/cfg.c
--- linux.vanilla/arch/s390/tools/silo/cfg.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/arch/s390/tools/silo/cfg.c	Thu Feb 17 13:34:37 2000
@@ -0,0 +1,373 @@
+/* cfg.c  -  Configuration file parser */
+
+/* Copyright 1992-1997 Werner Almesberger. See file COPYING for details. */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "cfg.h"
+
+#define MAX_TOKEN 200
+#define MAX_VAR_NAME MAX_TOKEN
+
+static FILE *file;
+static char flag_set;
+static char *last_token = NULL,*last_item = NULL,*last_value = NULL;
+static int line_num;
+static char *file_name = NULL;
+static int back = 0; /* can go back by one char */
+
+
+void pdie(char *msg)
+{
+    fflush(stdout);
+    perror(msg);
+    exit(1);
+}
+
+
+void die(char *fmt,...)
+{
+    va_list ap;
+
+    fflush(stdout);
+    va_start(ap,fmt);
+    vfprintf(stderr,fmt,ap);
+    va_end(ap);
+    fputc('\n',stderr);
+    exit(1);
+}
+
+char *pstrdup(const char *str)
+{
+    char *this;
+
+    if ((this = strdup(str)) == NULL) pdie("Out of memory");
+    return this;
+}
+
+int cfg_open(char *name)
+{
+    if (!strcmp(name,"-")) file = stdin;
+    else if (!(file = fopen(file_name = name,"r"))) pdie(name);
+    line_num = 1;
+    return fileno(file);
+}
+
+void cfg_error(char *msg,...)
+{
+    va_list ap;
+
+    fflush(stdout);
+    va_start(ap,msg);
+    vfprintf(stderr,msg,ap);
+    va_end(ap);
+    if (!file_name) fputc('\n',stderr);
+    else fprintf(stderr," near line %d in file %s\n",line_num,file_name);
+    exit(1);
+}
+
+
+static int next_raw(void)
+{
+    int ch;
+
+    if (!back) return getc(file);
+    ch = back;
+    back = 0;
+    return ch;
+}
+
+
+static int next(void)
+{
+    static char *var;
+    char buffer[MAX_VAR_NAME+1];
+    int ch,braced;
+    char *put;
+
+    if (back) {
+	ch = back;
+	back = 0;
+	return ch;
+    }
+    if (var && *var) return *var++;
+    ch = getc(file);
+    if (ch == '\\') {
+	ch = getc(file);
+	if (ch == '$') return ch;
+	ungetc(ch,file);
+	return '\\';
+    }
+    if (ch != '$') return ch;
+    ch = getc(file);
+    braced = ch == '{';
+    put = buffer;
+    if (!braced) *put++ = ch;
+    while (1) {
+	ch = getc(file);
+#if 0
+	if (!braced && ch < ' ') {
+	    ungetc(ch,file);
+	    break;
+	}
+#endif
+	if (ch == EOF) cfg_error("EOF in variable name");
+	if (ch < ' ') cfg_error("control character in variable name");
+	if (braced && ch == '}') break;
+	if (!braced && !isalpha(ch) && !isdigit(ch) && ch != '_') {
+	    ungetc(ch,file);
+	    break;
+	}
+	if (put-buffer == MAX_VAR_NAME) cfg_error("variable name too long");
+	*put++ = ch;
+    }
+    *put = 0;
+    if (!(var = getenv(buffer))) cfg_error("unknown variable \"%s\"",buffer);
+    return next();
+}
+
+
+static void again(int ch)
+{
+    if (back) die("internal error: again invoked twice");
+    back = ch;
+}
+
+
+static char *cfg_get_token(void)
+{
+    char buf[MAX_TOKEN+1];
+    char *here;
+    int ch,escaped;
+
+    if (last_token) {
+	here = last_token;
+	last_token = NULL;
+	return here;
+    }
+    while (1) {
+	while ((ch = next()), ch == ' ' || ch == '\t' || ch == '\n')
+	    if (ch == '\n') line_num++;
+	if (ch == EOF) return NULL;
+	if (ch != '#') break;
+	while ((ch = next_raw()), ch != '\n')
+	    if (ch == EOF) return NULL;
+	line_num++;
+    }
+    if (ch == '=') return pstrdup("=");
+    if (ch == '"') {
+	here = buf;
+	while (here-buf < MAX_TOKEN) {
+	    if ((ch = next()) == EOF) cfg_error("EOF in quoted string");
+	    if (ch == '"') {
+		*here = 0;
+		return pstrdup(buf);
+	    }
+	    if (ch == '\\') {
+		ch = next();
+		if (ch != '"' && ch != '\\' && ch != '\n')
+		    cfg_error("Bad use of \\ in quoted string");
+		if (ch == '\n') {
+		    while ((ch = next()), ch == ' ' || ch == '\t');
+		    if (!ch) continue;
+		    again(ch);
+		    ch = ' ';
+		}
+	    }
+	    if (ch == '\n' || ch == '\t')
+		cfg_error("\\n and \\t are not allowed in quoted strings");
+	    *here++ = ch;
+	}
+	cfg_error("Quoted string is too long");
+	return 0; /* not reached */
+    }
+    here = buf;
+    escaped = 0;
+    while (here-buf < MAX_TOKEN) {
+	if (escaped) {
+	    if (ch == EOF) cfg_error("\\ precedes EOF");
+	    if (ch == '\n') line_num++;
+	    else *here++ = ch == '\t' ? ' ' : ch;
+	    escaped = 0;
+	}
+	else {
+	    if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '#' ||
+	      ch == '=' || ch == EOF) {
+		again(ch);
+		*here = 0;
+		return pstrdup(buf);
+	    }
+	    if (!(escaped = (ch == '\\'))) *here++ = ch;
+	}
+	ch = next();
+    }
+    cfg_error("Token is too long");
+    return 0; /* not reached */
+}
+
+
+static void cfg_return_token(char *token)
+{
+    last_token = token;
+}
+
+
+static int cfg_next(char **item,char **value)
+{
+    char *this;
+
+    if (last_item) {
+	*item = last_item;
+	*value = last_value;
+	last_item = NULL;
+	return 1;
+    }
+    *value = NULL;
+    if (!(*item = cfg_get_token())) return 0;
+    if (!strcmp(*item,"=")) cfg_error("Syntax error");
+    if (!(this = cfg_get_token())) return 1;
+    if (strcmp(this,"=")) {
+	cfg_return_token(this);
+	return 1;
+    }
+    if (!(*value = cfg_get_token())) cfg_error("Value expected at EOF");
+    if (!strcmp(*value,"=")) cfg_error("Syntax error after %s",*item);
+    return 1;
+}
+
+
+static void cfg_return(char *item,char *value)
+{
+    last_item = item;
+    last_value = value;
+}
+
+
+void cfg_init(CONFIG *table)
+{
+    while (table->type != cft_end) {
+	switch (table->type) {
+	    case cft_strg:
+		if (table->data) free(table->data);
+	    case cft_flag:
+		table->data = NULL;
+		break;
+	    case cft_link:
+		table = ((CONFIG *) table->action)-1;
+		break;
+	    default:
+		die("Unknown syntax code %d",table->type);
+	}
+	table++;
+    }
+}
+
+
+static int cfg_do_set(CONFIG *table,char *item,char *value,int copy,
+    void *context)
+{
+    CONFIG *walk;
+
+    for (walk = table; walk->type != cft_end; walk++) {
+	if (walk->name && !strcasecmp(walk->name,item)) {
+	    if (value && walk->type != cft_strg)
+		cfg_error("'%s' doesn't have a value",walk->name);
+	    if (!value && walk->type == cft_strg)
+		cfg_error("Value expected for '%s'",walk->name);
+	    if (walk->data) {
+		if (walk->context == context)
+		    cfg_error("Duplicate entry '%s'",walk->name);
+		else {
+		    fprintf(stderr,"Ignoring entry '%s'\n",walk->name);
+		    if (!copy) free(value);
+		    return 1;
+		}
+	    }
+	    if (walk->type == cft_flag) walk->data = &flag_set;
+	    else if (walk->type == cft_strg) {
+		    if (copy) walk->data = pstrdup(value);
+		    else walk->data = value;
+	    }
+	    walk->context = context;
+	    if (walk->action) ((void (*)(void)) walk->action)();
+	    break;
+	}
+	if (walk->type == cft_link) walk = ((CONFIG *) walk->action)-1;
+    }
+    if (walk->type != cft_end) return 1;
+    cfg_return(item,value);
+    return 0;
+}
+
+
+void cfg_set(CONFIG *table,char *item,char *value,void *context)
+{
+    if (!cfg_do_set(table,item,value,1,context))
+	cfg_error("cfg_set: Can't set %s",item);
+}
+
+
+void cfg_unset(CONFIG *table,char *item)
+{
+    CONFIG *walk;
+
+    for (walk = table; walk->type != cft_end; walk++)
+	if (walk->name && !strcasecmp(walk->name,item)) {
+	    if (!walk->data) die("internal error (cfg_unset %s, unset)",item);
+	    if (walk->type == cft_strg) free(walk->data);
+	    walk->data = NULL;
+	    return;
+	}
+    die("internal error (cfg_unset %s, unknown",item);
+}
+
+
+int cfg_parse(CONFIG *table)
+{
+    char *item,*value;
+
+    while (1) {
+	if (!cfg_next(&item,&value)) return 0;
+	if (!cfg_do_set(table,item,value,0,table)) return 1;
+	free(item);
+    }
+}
+
+
+int cfg_get_flag(CONFIG *table,char *item)
+{
+    CONFIG *walk;
+
+    for (walk = table; walk->type != cft_end; walk++) {
+	if (walk->name && !strcasecmp(walk->name,item)) {
+	    if (walk->type != cft_flag)
+		die("cfg_get_flag: operating on non-flag %s",item);
+	    return !!walk->data;
+	}
+	if (walk->type == cft_link) walk = ((CONFIG *) walk->action)-1;
+    }
+    die("cfg_get_flag: unknown item %s",item);
+    return 0; /* not reached */
+}
+
+
+char *cfg_get_strg(CONFIG *table,char *item)
+{
+    CONFIG *walk;
+
+    for (walk = table; walk->type != cft_end; walk++) {
+	if (walk->name && !strcasecmp(walk->name,item)) {
+	    if (walk->type != cft_strg)
+		die("cfg_get_strg: operating on non-string %s",item);
+	    return walk->data;
+	}
+	if (walk->type == cft_link) walk = ((CONFIG *) walk->action)-1;
+    }
+    die("cfg_get_strg: unknown item %s",item);
+    return 0; /* not reached */
+}
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/tools/silo/cfg.h linux.15p9/arch/s390/tools/silo/cfg.h
--- linux.vanilla/arch/s390/tools/silo/cfg.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/arch/s390/tools/silo/cfg.h	Thu Feb 17 13:34:37 2000
@@ -0,0 +1,58 @@
+/* cfg.h  -  Configuration file parser */
+
+/* Copyright 1992-1996 Werner Almesberger. See file COPYING for details. */
+
+
+#ifndef CFG_H
+#define CFG_H
+
+typedef enum { cft_strg, cft_flag, cft_link, cft_end } CONFIG_TYPE;
+
+typedef struct {
+    CONFIG_TYPE type;
+    char *name;
+    void *action;
+    void *data;
+    void *context;
+} CONFIG;
+
+extern int cfg_open(char *name);
+
+/* Opens the configuration file. Returns the file descriptor of the open
+   file. */
+
+extern void cfg_error(char *msg,...);
+
+/* Signals an error while parsing the configuration file and terminates the
+   program. */
+
+extern void cfg_init(CONFIG *table);
+
+/* Initializes the specified table. */
+
+extern void cfg_set(CONFIG *table,char *item,char *value,void *context);
+
+/* Sets the specified variable in table. If the variable has already been set
+   since the last call to cfg_init, a warning message is issued if the context
+   keys don't match or a fatal error is reported if they do. */
+
+extern void cfg_unset(CONFIG *table,char *item);
+
+/* Unsets the specified variable in table. It is a fatal error if the variable
+   was not set. */
+
+extern int cfg_parse(CONFIG *table);
+
+/* Parses the configuration file for variables contained in table. A non-zero
+   value is returned if a variable not found in table has been met. Zero is
+   returned if EOF has been reached. */
+
+extern int cfg_get_flag(CONFIG *table,char *item);
+
+/* Returns one if the specified variable is set, zero if it isn't. */
+
+extern char *cfg_get_strg(CONFIG *table,char *item);
+
+/* Returns the value of the specified variable if it is set, NULL otherwise. */
+
+#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/tools/silo/silo.c linux.15p9/arch/s390/tools/silo/silo.c
--- linux.vanilla/arch/s390/tools/silo/silo.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/arch/s390/tools/silo/silo.c	Thu Feb 17 13:34:37 2000
@@ -0,0 +1,509 @@
+/*
+ *  arch/s390/boot/silo.c
+ *
+ *  S390 version
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Holger Smolinski <linux390@de.ibm.com>
+ *
+ *               Fritz Elfert <felfert@to.com> contributed support for
+ *                	/etc/silo.conf based on Intel's lilo
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <limits.h>
+#include <dirent.h>
+#include <linux/fs.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <asm/ioctl.h>
+
+#include "cfg.h"
+
+CONFIG cf_options[] = {
+  { cft_strg, "append",		NULL,		NULL,NULL },
+  { cft_strg, "image",		NULL,		NULL,NULL },
+  { cft_strg, "ipldevice",	NULL,		NULL,NULL },
+  { cft_strg, "bootsect",	NULL,		NULL,NULL },
+  { cft_strg, "map",		NULL,		NULL,NULL },
+  { cft_strg, "parmfile",	NULL,		NULL,NULL },
+  { cft_strg, "ramdisk",	NULL,		NULL,NULL },
+  { cft_strg, "root",		NULL,		NULL,NULL },
+  { cft_flag, "readonly",	NULL,		NULL,NULL },
+  { cft_strg, "verbose",	NULL,		NULL,NULL },
+  { cft_end,  NULL,		NULL,		NULL,NULL }
+};
+  
+/* from dasd.h */
+#define DASD_PARTN_BITS 2
+#define BIODASDRWTB _IOWR('D',5,int)
+/* end */
+
+#define SILO_CFG "/etc/silo.conf"
+
+#define PRINT_LEVEL(x,y...) if ( silo_options.verbosity >= x ) printf(y)
+#define ERROR_LEVEL(x,y...) if ( silo_options.verbosity >= x ) fprintf(stderr,y)
+#define TOGGLE(x) ((x)=((x)?(0):(1)))
+#define GETARG(x) {int len=strlen(optarg);x=malloc(len);strncpy(x,optarg,len);PRINT_LEVEL(1,"%s set to %s\n",#x,optarg);}
+
+#define ITRY(x) if ( (x) == -1 ) { ERROR_LEVEL(0,"%s (line:%d) '%s' returned %d='%s'\n", __FILE__,__LINE__,#x,errno,strerror(errno)); usage(); exit(1); }
+#define NTRY(x) if ( (x) == 0 ) { ERROR_LEVEL(0,"%s (line:%d) '%s' returned %d='%s'\n", __FILE__,__LINE__,#x,errno,strerror(errno)); usage(); exit(1); }
+
+#define MAX_CLUSTERS 256
+#define PARTN_MASK ((1 << DASD_PARTN_BITS) - 1)
+
+#define SILO_VERSION "1.1"
+
+struct silo_options
+  {
+    short int verbosity;
+    struct
+      {
+	unsigned char testonly;
+      }
+    flags;
+    char *image;
+    char *ipldevice;
+    char *parmfile;
+    char *ramdisk;
+    char *bootsect;
+    char *conffile;
+  }
+silo_options =
+{
+  1,				/* verbosity */
+  {
+    0,				/* testonly */
+  }
+  ,
+    "./image",			/* image */
+    NULL,			/* ipldevice */
+    NULL,			/* parmfile */
+    NULL,			/* initrd */
+    "ipleckd.boot",		/* bootsector */
+    SILO_CFG                    /* silo.conf file */
+};
+
+struct blockdesc
+  {
+    unsigned long off;
+    unsigned short ct;
+    unsigned long addr;
+  };
+
+struct blocklist
+  {
+    struct blockdesc blk[MAX_CLUSTERS];
+    unsigned short ix;
+  };
+
+void
+usage (void)
+{
+  printf ("Usage:\n");
+  printf ("silo -d ipldevice [additional options]\n");
+  printf ("-d /dev/node : set ipldevice to /dev/node\n");
+  printf ("-f image : set image to image\n");
+  printf ("-F conffile : specify configuration file (/etc/silo.conf)\n");
+  printf ("-p parmfile : set parameter file to parmfile\n");
+  printf ("-b bootsect : set bootsector to bootsect\n");
+  printf ("Additional options\n");
+  printf ("-v: increase verbosity level\n");
+  printf ("-v#: set verbosity level to #\n");
+  printf ("-t: toggle testonly flag\n");
+  printf ("-h: print this message\n");
+  printf ("-?: print this message\n");
+  printf ("-V: print version\n");
+}
+
+int
+read_cfg(struct silo_options *o)
+{
+	if (access(o->conffile, R_OK) && (errno == ENOENT))
+		return 0;
+	/* If errno != ENOENT, let cfg_open report an error */
+	cfg_open(o->conffile);
+	cfg_parse(cf_options);
+	o->ipldevice = cfg_get_strg(cf_options, "ipldevice");
+	o->image = cfg_get_strg(cf_options, "image");
+	o->parmfile = cfg_get_strg(cf_options, "parmfile");
+	o->ramdisk = cfg_get_strg(cf_options, "ramdisk");
+	o->bootsect = cfg_get_strg(cf_options, "bootsect");
+	if (cfg_get_strg(cf_options, "verbose")) {
+		unsigned short v;
+		sscanf (cfg_get_strg(cf_options, "verbose"), "%hu", &v);
+		o->verbosity = v;
+	}
+	return 1;
+}
+
+char *
+gen_tmpparm()
+{
+	char *append = cfg_get_strg(cf_options, "append");
+	char *root = cfg_get_strg(cf_options, "root");
+	int ro = cfg_get_flag(cf_options, "readonly");
+	FILE *f;
+	char *fn;
+	char *tmpdir=NULL,*save=NULL;
+
+	if (!append && !root && !ro)
+		return NULL;
+
+	tmpdir=getenv("TMPDIR");
+        if (tmpdir) {
+          NTRY( save=(char*)malloc(strlen(tmpdir)));
+          NTRY( strcpy(save,tmpdir));
+        }
+        ITRY( setenv("TMPDIR",".",1));
+	NTRY( fn = tempnam(NULL,"parm."));
+	NTRY( f = fopen(fn, "w"));
+	if (root)
+		fprintf(f, "root=%s ", root);
+	if (ro)
+		fprintf(f, "ro ");
+	if (append)
+		fprintf(f, "%s", append);
+	fprintf(f, "\n");
+	fclose(f);
+        if ( save )
+          ITRY( setenv("TMPDIR",save,1)); 
+	return strdup(fn);
+}
+
+int
+parse_options (struct silo_options *o, int argc, char *argv[])
+{
+  int rc = 0;
+  int oc;
+
+  read_cfg(o);
+  while ((oc = getopt (argc, argv, "Vf:F:d:p:r:b:B:h?v::t")) != -1)
+    {
+      switch (oc)
+	{
+	case 'V':
+	  printf("silo version: %s\n",SILO_VERSION);
+	  exit(0);
+	case 't':
+	  TOGGLE (o->flags.testonly);
+	  PRINT_LEVEL (1, "Testonly flag is now %sactive\n", o->flags.testonly ? "" : "in");
+	  break;
+	case 'v':
+	  {
+	    unsigned short v;
+	    if (optarg && sscanf (optarg, "%hu", &v))
+	      o->verbosity = v;
+	    else
+	      o->verbosity++;
+	    PRINT_LEVEL (1, "Verbosity value is now %hu\n", o->verbosity);
+	    break;
+	  }
+	case 'h':
+	case '?':
+	  usage ();
+	  exit(0);
+	case 'd':
+	  GETARG (o->ipldevice);
+	  break;
+	case 'f':
+	  GETARG (o->image);
+	  break;
+        case 'F':                         
+ 	   GETARG (o->conffile);              
+ 	   break;                          
+	case 'p':
+	  GETARG (o->parmfile);
+	  break;
+	case 'r':
+	  GETARG (o->ramdisk);
+	  break;
+	case 'b':
+	  GETARG (o->bootsect);
+	  break;
+	default:
+	  rc = EINVAL;
+	  break;
+	}
+    }
+
+  return rc;
+}
+
+int
+verify_device (char *name)
+{
+  int rc = 0;
+  struct stat dst;
+  struct stat st;
+  ITRY (stat (name, &dst));
+  if (S_ISBLK (dst.st_mode))
+    {
+      if (!(MINOR (dst.st_rdev) & PARTN_MASK))
+	{
+	  rc = dst.st_rdev;
+	}
+      else
+	/* invalid MINOR & PARTN_MASK */
+	{
+	  ERROR_LEVEL (1, "Cannot boot from partition %d %d %d",
+		       (int) PARTN_MASK, (int) MINOR (dst.st_rdev), (int) (PARTN_MASK & MINOR (dst.st_rdev)));
+	  rc = -1;
+	  errno = EINVAL;
+	}
+    }
+  else
+    /* error S_ISBLK */
+    {
+      ERROR_LEVEL (1, "%s is no block device\n", name);
+      rc = -1;
+      errno = EINVAL;
+    }
+  return rc;
+}
+
+int
+verify_file (char *name, int dev)
+{
+  int rc = 0;
+  struct stat dst;
+  struct stat st;
+  int bs = 1024;
+  int l;
+  ITRY (stat (name, &dst));
+  if (S_ISREG (dst.st_mode))
+    {
+      if ((unsigned) MAJOR (dev) == (unsigned) MAJOR (dst.st_dev) && (unsigned) MINOR (dev) == (unsigned) (MINOR (dst.st_dev) & ~PARTN_MASK))
+	{
+	  /* whatever to do if all is ok... */
+	}
+      else
+	/* devicenumber doesn't match */
+	{
+	  ERROR_LEVEL (1, "%s is not on device (%d/%d) but on (%d/%d)\n", name, (unsigned) MAJOR (dev), (unsigned) MINOR (dev), (unsigned) MAJOR (dst.st_dev), (unsigned) (MINOR (dst.st_dev) & ~PARTN_MASK));
+	  rc = -1;
+	  errno = EINVAL;
+	}
+    }
+  else
+    /* error S_ISREG */
+    {
+      ERROR_LEVEL (1, "%s is neither regular file nor linkto one\n", name);
+      rc = -1;
+      errno = EINVAL;
+    }
+  return rc;
+}
+
+int
+verify_options (struct silo_options *o)
+{
+  int rc = 0;
+  int dev = 0;
+  int crc = 0;
+  if (!o->ipldevice || !o->image || !o->bootsect)
+    {
+      usage ();
+      exit (1);
+    }
+  PRINT_LEVEL (1, "IPL device is: '%s'", o->ipldevice);
+
+  ITRY (dev = verify_device (o->ipldevice));
+  PRINT_LEVEL (2, "...ok...(%d/%d)", (unsigned short) MAJOR (dev), (unsigned short) MINOR (dev));
+  PRINT_LEVEL (1, "\n");
+
+  PRINT_LEVEL (0, "bootsector is: '%s'", o->bootsect);
+  ITRY (verify_file (o->bootsect, dev));
+  PRINT_LEVEL (1, "...ok...");
+  PRINT_LEVEL (0, "\n");
+
+  PRINT_LEVEL (0, "Kernel image is: '%s'", o->image);
+  ITRY (verify_file (o->image, dev));
+  PRINT_LEVEL (1, "...ok...");
+  PRINT_LEVEL (0, "\n");
+
+  if (o->parmfile)
+    {
+      PRINT_LEVEL (0, "parameterfile is: '%s'", o->parmfile);
+      ITRY (verify_file (o->parmfile, dev));
+      PRINT_LEVEL (1, "...ok...");
+      PRINT_LEVEL (0, "\n");
+    }
+
+  if (o->ramdisk)
+    {
+      PRINT_LEVEL (0, "initialramdisk is: '%s'", o->ramdisk);
+      ITRY (verify_file (o->ramdisk, dev));
+      PRINT_LEVEL (1, "...ok...");
+      PRINT_LEVEL (0, "\n");
+    }
+
+  return crc;
+}
+
+
+int
+add_file_to_blocklist (char *name, struct blocklist *lst, long addr)
+{
+  int fd;
+  int devfd;
+  struct stat fst;
+  int i;
+  int blk;
+  int bs;
+  int blocks;
+
+  int rc = 0;
+
+  ITRY (fd = open (name, O_RDONLY));
+  ITRY (fstat (fd, &fst));
+  ITRY (mknod ("/tmp/silodev", S_IFBLK | S_IRUSR | S_IWUSR, fst.st_dev));
+  ITRY (devfd = open ("/tmp/silodev", O_RDONLY));
+  ITRY (ioctl (fd, FIGETBSZ, &bs));
+  blocks = (fst.st_size + bs - 1) / bs;
+  for (i = 0; i < blocks; i++)
+    {
+      blk = i;
+      ITRY (ioctl (fd, FIBMAP, &blk));
+      if (blk)
+	{
+	  int oldblk = blk;
+	  ITRY (ioctl (devfd, BIODASDRWTB, &blk));
+	  if (blk <= 0)
+	    {
+	      ERROR_LEVEL (0, "BIODASDRWTB on blk %d returned %d\n", oldblk, blk);
+	      break;
+	    }
+	}
+      else
+	{
+	  PRINT_LEVEL (1, "Filled hole on blk %d\n", i);
+	}
+      if (lst->ix == 0 || i == 0  || 
+	  lst->blk[lst->ix - 1].ct >= 128 ||
+	  (lst->blk[lst->ix - 1].off + lst->blk[lst->ix - 1].ct != blk &&
+	   !(lst->blk[lst->ix - 1].off == 0 && blk == 0)))
+	{
+	  if (lst->ix >= MAX_CLUSTERS)
+	    {
+	      rc = 1;
+	      errno = ENOMEM;
+	      break;
+	    }
+	  lst->blk[lst->ix].off = blk;
+	  lst->blk[lst->ix].ct = 1;
+	  lst->blk[lst->ix].addr = addr + i * bs;
+	  lst->ix++;
+	}
+      else
+	{
+	  lst->blk[lst->ix - 1].ct++;
+	}
+    }
+  ITRY(unlink("/tmp/silodev"));
+  return rc;
+}
+
+int
+write_bootsect (char *ipldevice, char *bootsect, struct blocklist *blklst)
+{
+  int i;
+  int s_fd, d_fd, b_fd, bd_fd;
+  struct stat s_st, d_st, b_st;
+  int rc=0;
+  int bs, boots;
+  char *mapname;
+  char *tmpdev;
+  char buffer[4096]={0,};
+  ITRY (d_fd = open (ipldevice, O_RDWR | O_SYNC));
+  ITRY (fstat (d_fd, &d_st));
+  if (!(mapname = cfg_get_strg(cf_options, "map")))
+    mapname = "boot.map";
+  ITRY (s_fd = open (mapname, O_RDWR | O_TRUNC | O_CREAT | O_SYNC));
+  ITRY (verify_file (bootsect, d_st.st_rdev));
+  for (i = 0; i < blklst->ix; i++)
+    {
+      int offset = blklst->blk[i].off;
+      int addrct = blklst->blk[i].addr | (blklst->blk[i].ct & 0xff);
+      PRINT_LEVEL (1, "ix %i: offset: %06x count: %02x address: 0x%08x\n", i, offset, blklst->blk[i].ct & 0xff, blklst->blk[i].addr);
+      NTRY (write (s_fd, &offset, sizeof (int)));
+      NTRY (write (s_fd, &addrct, sizeof (int)));
+    }
+  ITRY (ioctl (s_fd,FIGETBSZ, &bs));
+  ITRY (stat (mapname, &s_st));
+  if (s_st.st_size > bs )
+    {
+      ERROR_LEVEL (0,"%s is larger than one block\n", mapname);
+      rc = -1;
+      errno = EINVAL;
+    }
+  boots=0;
+  NTRY ( tmpdev = tmpnam(NULL) );
+  ITRY (mknod (tmpdev, S_IFBLK | S_IRUSR | S_IWUSR, s_st.st_dev));
+  ITRY (bd_fd = open (tmpdev, O_RDONLY));
+  ITRY ( ioctl(s_fd,FIBMAP,&boots));
+  ITRY (ioctl (bd_fd, BIODASDRWTB, &boots));
+  PRINT_LEVEL (1, "Bootmap is in block no: 0x%08x\n", boots);
+  close (bd_fd);
+  close(s_fd);
+  ITRY (unlink(tmpdev));
+  /* Now patch the bootsector */
+  ITRY (b_fd = open (bootsect, O_RDONLY));
+  NTRY (read (b_fd, buffer, 4096));
+  memset (buffer + 0xe0, 0, 8);
+  *(int *) (buffer + 0xe0) = boots;
+  if ( ! silo_options.flags.testonly ) {
+    NTRY (write (d_fd, buffer, 4096));
+    NTRY (write (d_fd, buffer, 4096));
+  }
+  close (b_fd);
+  close (d_fd);
+  return rc;
+}
+
+int
+do_silo (struct silo_options *o)
+{
+  int rc = 0;
+  char *tmp_parmfile = NULL;
+
+  int device_fd;
+  int image_fd;
+  struct blocklist blklist;
+  memset (&blklist, 0, sizeof (struct blocklist));
+  ITRY (add_file_to_blocklist (o->image, &blklist, 0x00000000));
+  if (o->parmfile)
+    {
+      ITRY (add_file_to_blocklist (o->parmfile, &blklist, 0x00008000));
+    }
+  else
+    {
+      if ((tmp_parmfile = gen_tmpparm()))
+          ITRY (add_file_to_blocklist (tmp_parmfile, &blklist, 0x00008000));
+    }
+  if (o->ramdisk)
+    {
+      ITRY (add_file_to_blocklist (o->ramdisk, &blklist, 0x00800000));
+    }
+  ITRY (write_bootsect (o->ipldevice, o->bootsect, &blklist));
+  if (tmp_parmfile)
+  	ITRY (remove (tmp_parmfile));
+
+  return rc;
+}
+
+int
+main (int argct, char *argv[])
+{
+  int rc = 0;
+  ITRY (parse_options (&silo_options, argct, argv));
+  ITRY (verify_options (&silo_options));
+  ITRY (do_silo (&silo_options));
+  return rc;
+}
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/s390/tools/silo/silo.conf linux.15p9/arch/s390/tools/silo/silo.conf
--- linux.vanilla/arch/s390/tools/silo/silo.conf	Thu Jan  1 01:00:00 1970
+++ linux.15p9/arch/s390/tools/silo/silo.conf	Thu Feb 17 13:34:37 2000
@@ -0,0 +1,7 @@
+ipldevice = /dev/dasd00
+image = /boot/image
+bootsect = /boot/ipleckd.boot
+map = /boot/boot.map
+root = /dev/dasd01
+readonly
+append = "dasd=200-20f"
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc/config.in linux.15p9/arch/sparc/config.in
--- linux.vanilla/arch/sparc/config.in	Wed Oct 20 01:12:33 1999
+++ linux.15p9/arch/sparc/config.in	Mon Feb  7 12:20:21 2000
@@ -103,6 +103,25 @@
 
 if [ "$CONFIG_NET" = "y" ]; then
 	source net/Config.in
+	mainmenu_option next_comment
+	comment 'Amateur Radio support'
+	bool 'Amateur Radio support' CONFIG_HAMRADIO
+	if [ "$CONFIG_HAMRADIO" != "n" ] ; then
+		comment 'Packet Radio protocols'
+		tristate 'Amateur Radio AX.25 Level 2 protocol' CONFIG_AX25
+		if [ "$CONFIG_AX25" != "n" ]; then
+			bool '   AX.25 DAMA Slave support' CONFIG_AX25_DAMA_SLAVE
+#			bool '   AX.25 DAMA Master support' CONFIG_AX25_DAMA_MASTER
+			dep_tristate '   Amateur Radio NET/ROM protocol' CONFIG_NETROM $CONFIG_AX25
+			dep_tristate '   Amateur Radio X.25 PLP (Rose)' CONFIG_ROSE $CONFIG_AX25
+
+			comment 'AX.25 network device drivers'
+			dep_tristate 'Serial port KISS driver' CONFIG_MKISS $CONFIG_AX25
+			dep_tristate 'Serial port 6PACK driver' CONFIG_6PACK $CONFIG_AX25
+		fi
+	fi
+
+	endmenu
 fi
 
 mainmenu_option next_comment
@@ -139,7 +158,7 @@
 	mainmenu_option next_comment
 	comment 'SCSI low-level drivers'
 
-	bool 'Sparc ESP Scsi Driver' CONFIG_SCSI_SUNESP $CONFIG_SCSI
+	tristate 'Sparc ESP Scsi Driver' CONFIG_SCSI_SUNESP $CONFIG_SCSI
 	tristate 'PTI Qlogic,ISP Driver' CONFIG_SCSI_QLOGICPTI $CONFIG_SCSI
 	endmenu
 fi
@@ -154,6 +173,7 @@
 	bool 'Network device support' CONFIG_NETDEVICES
 	if [ "$CONFIG_NETDEVICES" = "y" ]; then
 		tristate 'Dummy net driver support' CONFIG_DUMMY
+		tristate 'Bonding driver support' CONFIG_BONDING
 		tristate 'PPP (point-to-point) support' CONFIG_PPP
 		if [ ! "$CONFIG_PPP" = "n" ]; then
 		   comment 'CCP compressors for PPP are only built as modules.'
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc/defconfig linux.15p9/arch/sparc/defconfig
--- linux.vanilla/arch/sparc/defconfig	Wed Oct 20 01:12:33 1999
+++ linux.15p9/arch/sparc/defconfig	Mon Feb  7 12:20:21 2000
@@ -146,6 +146,11 @@
 # CONFIG_NET_SCHED is not set
 
 #
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
 # ISDN subsystem
 #
 # CONFIG_ISDN is not set
@@ -198,6 +203,7 @@
 #
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
+CONFIG_BONDING=m
 CONFIG_PPP=m
 
 #
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc/kernel/ebus.c linux.15p9/arch/sparc/kernel/ebus.c
--- linux.vanilla/arch/sparc/kernel/ebus.c	Tue Oct 27 17:52:20 1998
+++ linux.15p9/arch/sparc/kernel/ebus.c	Fri Jan 21 17:50:17 2000
@@ -1,9 +1,10 @@
-/* $Id: ebus.c,v 1.2 1998/10/07 11:35:16 jj Exp $
+/* $Id: ebus.c,v 1.2.2.1 2000/01/21 01:05:35 davem Exp $
  * ebus.c: PCI to EBus bridge device.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
  *
  * Adopted for sparc by V. Roganov and G. Raiko.
+ * Fixes for different platforms by Pete Zaitcev.
  */
 
 #include <linux/config.h>
@@ -25,9 +26,9 @@
 #undef DEBUG_FILL_EBUS_DEV
 
 #ifdef PROM_DEBUG
-#define dprintf prom_printf
+#define dprintk prom_printf
 #else
-#define dprintf printk
+#define dprintk printk
 #endif
 
 struct linux_ebus *ebus_chain = 0;
@@ -48,6 +49,9 @@
 extern int envctrl_init(void);
 #endif
 
+/* We are together with pcic.c under CONFIG_PCI. */
+extern unsigned int pcic_pin_to_irq(unsigned int, char *name);
+
 static inline unsigned long ebus_alloc(size_t size)
 {
 	return (unsigned long)kmalloc(size, GFP_ATOMIC);
@@ -66,6 +70,7 @@
 	strcpy(dev->prom_name, lbuf);
 
 	len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs));
+	if (len == -1) len = 0;
 	dev->num_addrs = len / sizeof(regs[0]);
 
 	for (i = 0; i < dev->num_addrs; i++) {
@@ -77,22 +82,36 @@
 		dev->base_address[i] = dev->parent->base_address[regs[i]];
 	}
 
+	/*
+	 * Houston, we have a problem...
+	 * Sometimes PROM supplies absolutely meaningless properties.
+	 * Still, we take what it gives since we have nothing better.
+	 * Children of ebus may be wired on any input pin of PCIC.
+	 */
 	len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
 	if ((len == -1) || (len == 0)) {
 		dev->num_irqs = 0;
-		/*
-		 * Oh, well, some PROMs don't export interrupts
-		 * property to children of EBus devices...
-		 *
-		 * Be smart about PS/2 keyboard and mouse.
-		 */
-		if (!strcmp(dev->parent->prom_name, "8042")) {
+		dev->irqs[0] = 0;
+		if (dev->parent->num_irqs != 0) {
 			dev->num_irqs = 1;
 			dev->irqs[0] = dev->parent->irqs[0];
+/* P3 remove */ printk("EBUS: dev %s irq %d from parent\n", dev->prom_name, dev->irqs[0]);
 		}
 	} else {
 		dev->num_irqs = len / sizeof(irqs[0]);
-		printk("FIXME: %s irq(%d)\n", dev->prom_name, irqs[0]);
+		if (irqs[0] == 0 || irqs[0] >= 8) {
+			/*
+			 * XXX Zero is a valid pin number...
+			 * This works as long as Ebus is not wired to INTA#.
+			 */
+			printk("EBUS: %s got bad irq %d from PROM\n",
+			    dev->prom_name, irqs[0]);
+			dev->num_irqs = 0;
+			dev->irqs[0] = 0;
+		} else {
+			dev->irqs[0] = pcic_pin_to_irq(irqs[0], dev->prom_name);
+/* P3 remove */ printk("EBUS: dev %s irq %d from PROM\n", dev->prom_name, dev->irqs[0]);
+		}
 	}
 
 #ifdef DEBUG_FILL_EBUS_DEV
@@ -131,7 +150,30 @@
 	dev->num_addrs = len / sizeof(struct linux_prom_registers);
 
 	for (i = 0; i < dev->num_addrs; i++) {
-		n = (regs[i].which_io - 0x10) >> 2;
+		/*
+		 * XXX Collect JE-1 PROM
+		 * 
+		 * Example - JS-E with 3.11:
+		 *  /ebus
+		 *      regs 
+		 *        0x00000000, 0x0, 0x00000000, 0x0, 0x00000000,
+		 *        0x82000010, 0x0, 0xf0000000, 0x0, 0x01000000,
+		 *        0x82000014, 0x0, 0x38800000, 0x0, 0x00800000,
+		 *      ranges
+		 *        0x00, 0x00000000, 0x02000010, 0x0, 0x0, 0x01000000,
+		 *        0x01, 0x01000000, 0x02000014, 0x0, 0x0, 0x00800000,
+		 *  /ebus/8042
+		 *      regs
+		 *        0x00000001, 0x00300060, 0x00000008,
+		 *        0x00000001, 0x00300060, 0x00000008,
+		 */
+		n = regs[i].which_io;
+		if (n >= 4) {
+			/* XXX This is copied from old JE-1 by Gleb. */
+			n = (regs[i].which_io - 0x10) >> 2;
+		} else {
+			;
+		}
 
 		dev->base_address[i] = dev->bus->self->base_address[n];
 		dev->base_address[i] += regs[i].phys_addr;
@@ -141,8 +183,14 @@
 		       (unsigned long)sparc_alloc_io (dev->base_address[i], 0,
 						      regs[i].reg_size,
 						      dev->prom_name, 0, 0);
+#if 0
+/*
+ * This release_region() screwes those who do sparc_alloc_io().
+ * Change drivers which do check_region(). See drivers/block/floppy.c.
+ */
 		    /* Some drivers call 'check_region', so we release it */
                     release_region(dev->base_address[i] & PAGE_MASK, PAGE_SIZE);
+#endif
 
 		    if (dev->base_address[i] == 0 ) {
 			panic("ebus: unable sparc_alloc_io for dev %s",
@@ -154,12 +202,22 @@
 	len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
 	if ((len == -1) || (len == 0)) {
 		dev->num_irqs = 0;
+		if ((dev->irqs[0] = dev->bus->self->irq) != 0) {
+			 dev->num_irqs = 1;
+/* P3 remove */ printk("EBUS: child %s irq %d from parent\n", dev->prom_name, dev->irqs[0]);
+		}
 	} else {
-		dev->num_irqs = len / sizeof(irqs[0]);
-
-#define IRQ_8042 7
-		if (irqs[0] == 4) dev->irqs[0] = IRQ_8042;
-		printk("FIXME: %s irq(%d)\n", dev->prom_name, irqs[0]);
+		dev->num_irqs = 1;  /* dev->num_irqs = len / sizeof(irqs[0]); */
+		if (irqs[0] == 0 || irqs[0] >= 8) {
+			/* See above for the parent. XXX */
+			printk("EBUS: %s got bad irq %d from PROM\n",
+			    dev->prom_name, irqs[0]);
+			dev->num_irqs = 0;
+			dev->irqs[0] = 0;
+		} else {
+			dev->irqs[0] = pcic_pin_to_irq(irqs[0], dev->prom_name);
+/* P3 remove */ printk("EBUS: child %s irq %d from PROM\n", dev->prom_name, dev->irqs[0]);
+		}
 	}
 
 #ifdef DEBUG_FILL_EBUS_DEV
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc/kernel/entry.S linux.15p9/arch/sparc/kernel/entry.S
--- linux.vanilla/arch/sparc/kernel/entry.S	Tue Jan  4 21:18:41 2000
+++ linux.15p9/arch/sparc/kernel/entry.S	Fri Jan 21 17:50:17 2000
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.159.2.6 1999/10/11 08:24:35 davem Exp $
+/* $Id: entry.S,v 1.159.2.7 2000/01/21 01:05:35 davem Exp $
  * arch/sparc/kernel/entry.S:  Sparc trap low-level entry points.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -1898,5 +1898,53 @@
 	LOAD_CURRENT(g6, o0)
 	retl
 	 nop
+
+#ifdef CONFIG_PCI
+#include <asm/pcic.h>
+
+	.align	4
+	.globl	linux_trap_ipi15_pcic
+linux_trap_ipi15_pcic:
+	rd	%wim, %l3
+	SAVE_ALL
+
+	/*
+	 * First deactivate NMI
+	 * or we cannot drop ET, cannot get window spill traps.
+	 * The busy loop is necessary because the PIO error
+	 * sometimes does not go away quickly and we trap again.
+	 */
+	sethi	%hi(C_LABEL(pcic_regs)), %o1
+	ld	[%o1 + %lo(C_LABEL(pcic_regs))], %o2
+
+	! Get pending status for printouts later.
+	ld	[%o2 + PCI_SYS_INT_PENDING], %o0
+
+	mov	PCI_SYS_INT_PENDING_CLEAR_ALL, %o1
+	stb	%o1, [%o2 + PCI_SYS_INT_PENDING_CLEAR]
+1:
+	ld	[%o2 + PCI_SYS_INT_PENDING], %o1
+	andcc	%o1, ((PCI_SYS_INT_PENDING_PIO|PCI_SYS_INT_PENDING_PCI)>>24), %g0
+	bne	1b
+	 nop
+
+	or	%l0, PSR_PIL, %l4
+	wr	%l4, 0x0, %psr
+	WRITE_PAUSE
+	wr	%l4, PSR_ET, %psr
+	WRITE_PAUSE
+
+	call	C_LABEL(pcic_nmi)
+	 add	%sp, REGWIN_SZ, %o1	! struct pt_regs *regs
+	RESTORE_ALL
+
+	.globl	C_LABEL(pcic_nmi_trap_patch)
+C_LABEL(pcic_nmi_trap_patch):
+	sethi	%hi(linux_trap_ipi15_pcic), %l3
+	jmpl	%l3 + %lo(linux_trap_ipi15_pcic), %g0
+	 rd	%psr, %l0
+	.word	0
+
+#endif /* CONFIG_PCI */
 
 /* End of entry.S */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc/kernel/head.S linux.15p9/arch/sparc/kernel/head.S
--- linux.vanilla/arch/sparc/kernel/head.S	Tue Jan  4 21:18:41 2000
+++ linux.15p9/arch/sparc/kernel/head.S	Fri Jan 21 17:50:17 2000
@@ -1,8 +1,8 @@
-/* $Id: head.S,v 1.95.2.5 1999/12/02 11:51:56 davem Exp $
+/* $Id: head.S,v 1.95.2.6 2000/01/21 01:05:39 davem Exp $
  * head.S: The initial boot code for the Sparc port of Linux.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1995 Peter Zaitcev   (Zaitcev@ipmce.su)
+ * Copyright (C) 1995,1999 Pete Zaitcev   (zaitcev@metabyte.com)
  * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
  * Copyright (C) 1997 Jakub Jelinek   (jj@sunsite.mff.cuni.cz)
  * Copyright (C) 1997 Michael A. Griffith (grif@acm.org)
@@ -116,10 +116,10 @@
 t_irq12:TRAP_ENTRY_INTERRUPT(12)            /* IRQ Zilog serial chip         */
 t_irq13:TRAP_ENTRY_INTERRUPT(13)            /* IRQ Audio Intr.               */
 t_irq14:TRAP_ENTRY_INTERRUPT(14)            /* IRQ Timer #2                  */
+	.globl	t_nmi
 #ifndef __SMP__
 t_nmi:	NMI_TRAP                            /* Level 15 (NMI)                */
 #else
-	.globl	t_nmi
 t_nmi:	TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m)
 #endif
 t_racc:	TRAP_ENTRY(0x20, do_reg_access)     /* General Register Access Error */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc/kernel/irq.c linux.15p9/arch/sparc/kernel/irq.c
--- linux.vanilla/arch/sparc/kernel/irq.c	Sat Aug 14 02:25:55 1999
+++ linux.15p9/arch/sparc/kernel/irq.c	Thu Feb 17 13:50:55 2000
@@ -713,7 +713,7 @@
  *
  */
 
-__initfunc(void init_IRQ(void))
+unsigned long __init init_IRQ(unsigned long memory)
 {
 	extern void sun4c_init_IRQ( void );
 	extern void sun4m_init_IRQ( void );
@@ -751,4 +751,5 @@
 		break;
 	}
 	btfixup();
+	return memory;
 }
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc/kernel/pcic.c linux.15p9/arch/sparc/kernel/pcic.c
--- linux.vanilla/arch/sparc/kernel/pcic.c	Sat Aug 14 02:27:15 1999
+++ linux.15p9/arch/sparc/kernel/pcic.c	Fri Jan 21 17:50:17 2000
@@ -1,10 +1,12 @@
-/* $Id: pcic.c,v 1.5.2.1 1999/08/07 10:42:43 davem Exp $
+/* $Id: pcic.c,v 1.5.2.2 2000/01/21 01:05:41 davem Exp $
  * pcic.c: Sparc/PCI controller support
  *
  * Copyright (C) 1998 V. Roganov and G. Raiko
  *
  * Code is derived from Ultra/PCI PSYCHO controller support, see that
  * for author info.
+ *
+ * Support for diverse IIep based platforms by Pete Zaitcev.
  */
 
 #include <linux/config.h>
@@ -16,20 +18,10 @@
 
 #include <asm/ebus.h>
 #include <asm/sbus.h> /* for sanity check... */
+#include <asm/swift.h> /* for cache flushing. */
 
 #include <asm/io.h>
 
-#undef PROM_DEBUG
-#undef FIXUP_REGS_DEBUG
-#undef FIXUP_IRQ_DEBUG
-#undef FIXUP_VMA_DEBUG
-
-#ifdef PROM_DEBUG
-#define dprintf	prom_printf
-#else
-#define dprintf printk
-#endif
-
 #include <linux/ctype.h>
 #include <linux/pci.h>
 #include <linux/timex.h>
@@ -68,9 +60,101 @@
 
 #else
 
+unsigned int pcic_pin_to_irq(unsigned int pin, char *name);
+
+/*
+ * I studied different documents and many live PROMs both from 2.30
+ * family and 3.xx versions. I came to the amazing conclusion: there is
+ * absolutely no way to route interrupts in IIep systems relying on
+ * information which PROM presents. We must hardcode interrupt routing
+ * schematics. And this actually sucks.   -- zaitcev 1999/05/12
+ *
+ * To find irq for a device we determine which routing map
+ * is in effect or, in other words, on which machine we are running.
+ * We use PROM name for this although other techniques may be used
+ * in special cases (Gleb reports a PROMless IIep based system).
+ * Once we know the map we take device configuration address and
+ * find PCIC pin number where INT line goes. Then we may either program
+ * preferred irq into the PCIC or supply the preexisting irq to the device.
+ *
+ * XXX Entries for JE-1 are completely bogus. Gleb, Vladimir, please fill them.
+ */
+struct pcic_ca2irq {
+	unsigned char busno;		/* PCI bus number */
+	unsigned char devfn;		/* Configuration address */
+	unsigned char pin;		/* PCIC external interrupt pin */
+	unsigned char irq;		/* Preferred IRQ (mappable in PCIC) */
+	unsigned int force;		/* Enforce preferred IRQ */
+};
+
+struct pcic_sn2list {
+	char *sysname;
+	struct pcic_ca2irq *intmap;
+	int mapdim;
+};
+
+/*
+ * XXX JE-1 is a little known beast.
+ * One rumor has the map this way: pin 0 - parallel, audio;
+ * pin 1 - Ethernet; pin 2 - su; pin 3 - PS/2 kbd and mouse.
+ * All other comparable systems tie serial and keyboard together,
+ * so we do not code this rumor just yet.
+ */
+static struct pcic_ca2irq pcic_i_je1[] = {
+	{ 0, 0x01, 1,  6, 1 },		/* Happy Meal */
+};
+
+/* XXX JS-E entry is incomplete - PCI Slot 2 address (pin 7)? */
+static struct pcic_ca2irq pcic_i_jse[] = {
+	{ 0, 0x00, 0, 13, 0 },		/* Ebus - serial and keyboard */
+	{ 0, 0x01, 1,  6, 0 },		/* hme */
+	{ 0, 0x08, 2,  9, 0 },		/* VGA - we hope not used :) */
+	{ 0, 0x18, 6,  8, 0 },		/* PCI INTA# in Slot 1 */
+	{ 0, 0x38, 4,  9, 0 },		/* All ISA devices. Read 8259. */
+	{ 0, 0x80, 5, 11, 0 },		/* EIDE */
+	/* {0,0x88, 0,0,0} - unknown device... PMU? Probably no interrupt. */
+	{ 0, 0xA0, 4,  9, 0 },		/* USB */
+	/*
+	 * Some pins belong to non-PCI devices, we hardcode them in drivers.
+	 * sun4m timers - irq 10, 14
+	 * PC style RTC - pin 7, irq 4 ?
+	 * Smart card, Parallel - pin 4 shared with USB, ISA
+	 * audio - pin 3, irq 5 ?
+	 */
+};
+
+/*
+ * Krups
+ * No documentation available, so we guess it, based on Espresso layout.
+ * Since we always run PROLL on Krups we may put map in there.
+ */
+static struct pcic_ca2irq pcic_i_jk[] = {
+	{ 0, 0x00, 0, 13, 0 },		/* Ebus - serial and keyboard */
+	{ 0, 0x01, 1,  6, 0 },		/* hme */
+};
+
+/*
+ * Several entries in this list may point to the same routing map
+ * as several PROMs may be installed on the same physical board.
+ */
+#define SN2L_INIT(name, map)	\
+  { name, map, sizeof(map)/sizeof(struct pcic_ca2irq) }
+
+static struct pcic_sn2list pcic_known_sysnames[] = {
+	SN2L_INIT("JE-1-name", pcic_i_je1),  /* XXX Gleb, put name here, pls */
+	SN2L_INIT("SUNW,JS-E", pcic_i_jse),	/* PROLL JavaStation-E */
+	SN2L_INIT("SUNW,JS-NC", pcic_i_jk),	/* PROLL JavaStation-NC */
+	SN2L_INIT("SUNW,JSIIep", pcic_i_jk),	/* OBP JavaStation-NC */
+	{ NULL, NULL, 0 }
+};
+
 static struct linux_pcic PCIC;
 static struct linux_pcic *pcic = NULL;
 
+unsigned int pcic_regs;
+volatile int pcic_speculative;
+volatile int pcic_trapped;
+
 static void pci_do_gettimeofday(struct timeval *tv);
 static void pci_do_settimeofday(struct timeval *tv);
 
@@ -100,7 +184,7 @@
 			    "from PROM.\n");
 		prom_halt();
 	}
-	
+
 	pcic = &PCIC;
 
 	pcic->pcic_regs = (unsigned long)sparc_alloc_io(regs[0].phys_addr, NULL,
@@ -146,8 +230,39 @@
 
 	pbm = &pcic->pbm;
 	pbm->prom_node = node;
-	prom_getstring(node, "name", namebuf, sizeof(namebuf));
+	prom_getstring(node, "name", namebuf, 63);  namebuf[63] = 0;
 	strcpy(pbm->prom_name, namebuf);
+
+	{
+		extern volatile int t_nmi[1];
+		extern int pcic_nmi_trap_patch[1];
+
+		t_nmi[0] = pcic_nmi_trap_patch[0];
+		t_nmi[1] = pcic_nmi_trap_patch[1];
+		t_nmi[2] = pcic_nmi_trap_patch[2];
+		t_nmi[3] = pcic_nmi_trap_patch[3];
+		swift_flush_dcache();
+		pcic_regs = pcic->pcic_regs;
+	}
+
+	prom_getstring(prom_root_node, "name", namebuf, 63);  namebuf[63] = 0;
+	{
+		struct pcic_sn2list *p;
+
+		for (p = pcic_known_sysnames; p->sysname != NULL; p++) {
+			if (strcmp(namebuf, p->sysname) == 0)
+				break;
+		}
+		pcic->pcic_imap = p->intmap;
+		pcic->pcic_imdim = p->mapdim;
+	}
+	if (pcic->pcic_imap == NULL) {
+		/*
+		 * We do not panic here for the sake of embedded systems.
+		 */
+		printk("PCIC: System %s is unknown, cannot route interrupts\n",
+		    namebuf);
+	}
 }
 
 __initfunc(void pcibios_init(void))
@@ -165,20 +280,15 @@
 	       pcic->pcic_regs, pcic->pcic_io);
 
 	/*
-	 * FIXME:
 	 *      Switch off IOTLB translation.
-	 *      It'll be great to use IOMMU to handle HME's rings
-	 *      but we couldn't. Thus, we have to flush CPU cache
-	 *      in HME.
 	 */
 	writeb(PCI_DVMA_CONTROL_IOTLB_DISABLE, 
 	       pcic->pcic_regs+PCI_DVMA_CONTROL);
 
 	/*
-	 * FIXME:
 	 *      Increase mapped size for PCI memory space (DMA access).
 	 *      Should be done in that order (size first, address second).
-	 *      Why we couldn't set up 4GB and forget about it ?
+	 *      Why we couldn't set up 4GB and forget about it? XXX
 	 */
 	writel(0xF0000000UL, pcic->pcic_regs+PCI_SIZE_0);
 	writel(0+PCI_BASE_ADDRESS_SPACE_MEMORY, 
@@ -203,7 +313,7 @@
 		if(err != 0 && err != -1) {
 			unsigned long devfn = (regs[0].which_io >> 8) & 0xff;
 			if(devfn == pdev->devfn)
-				return node; /* Match */
+				return node;
 		}
 		node = prom_getsibling(node);
 	}
@@ -215,10 +325,14 @@
 	return kmalloc(sizeof(struct pcidev_cookie), GFP_ATOMIC);
 }
 
-
-static void pcic_map_pci_device (struct pci_dev *dev) {
-	int node, pcinode;
+static void pcic_map_pci_device (struct pci_dev *dev, int node) {
+	char namebuf[64];
+	struct linux_prom_pci_assigned_addresses addrs[6];
+	int addrlen;
+	unsigned long address;
+	int length;
 	int i, j;
+	int nmem = 0, nio = 0;
 
 	/* Is any valid address present ? */
 	i = 0;
@@ -226,103 +340,165 @@
 		if (dev->base_address[j]) i++;
 	if (!i) return; /* nothing to do */
 
+	if (node == 0 || node == -1) {
+		printk("PCIC: no prom node for device (%x,%x)\n",
+		    dev->device, dev->vendor);
+		return;
+	}
+	prom_getstring(node, "name", namebuf, 63);  namebuf[63] = 0;
+
 	/*
 	 * find related address and get it's window length
 	 */
-	pcinode = prom_getchild(prom_root_node);
-	pcinode = prom_searchsiblings(pcinode, "pci");
-	if (!pcinode)
-		panic("PCIC: failed to locate 'pci' node");
-
-
-	for (node = prom_getchild(pcinode); node;
-	     node = prom_getsibling(node)) {
-		struct linux_prom_pci_assigned_addresses addrs[6];
-		int addrlen = prom_getproperty(node,"assigned-addresses",
+	addrlen = prom_getproperty(node,"assigned-addresses",
 					       (char*)addrs, sizeof(addrs));
-		if (addrlen == -1)
-			continue;
-
-		addrlen /= sizeof(struct linux_prom_pci_assigned_addresses);
-		for (i = 0; i < addrlen; i++ )
-		    for (j = 0; j < 6; j++) {
-			if (!dev->base_address[j] || !addrs[i].phys_lo)
-				continue;
-			if (addrs[i].phys_lo == dev->base_address[j]) {
-			    unsigned long address = dev->base_address[j];
-			    int length  = addrs[i].size_lo;
-			    char namebuf[128] = { 0, };
-			    unsigned long mapaddr, addrflags;
-	    
-			    prom_getstring(node, "name",
-					   namebuf,  sizeof(namebuf));
-
-			    /* FIXME:
-			     *      failure in allocation too large space
-			     */
-			    if (length > 0x200000) {
-				length = 0x200000;
-				prom_printf("PCIC: map window for device '%s' "
-					    "reduced to 2MB !\n", namebuf);
-			    }
-
-			    /*
-			     *  Be careful with MEM/IO address flags
-			     */
-			    if ((address & PCI_BASE_ADDRESS_SPACE) ==
-				 PCI_BASE_ADDRESS_SPACE_IO) {
-				mapaddr = address & PCI_BASE_ADDRESS_IO_MASK;
-			    } else {
-				mapaddr = address & PCI_BASE_ADDRESS_MEM_MASK;
-			    }
-			    addrflags = address ^ mapaddr;
-
-			    dev->base_address[j] =
-				(unsigned long)sparc_alloc_io(address, 0, 
-							      length,
-							      namebuf, 0, 0);
-			    if ( dev->base_address[j] == 0 )
-				panic("PCIC: failed make mapping for "
-				      "pci device '%s' with address %lx\n",
-				       namebuf, address);
+	if (addrlen == -1) {
+		/*
+		 * We could live without this property. Address and size
+		 * can be determined from PCI Configuration space registers.
+		 * We use "assigned-addresses" to gather length, which
+		 * is typically less than otherwise would be needed.
+		 */
+		printk("PCIC: no \"assigned-addresses\" for device (%x,%x)\n",
+		    dev->device, dev->vendor);
+		return;
+	}
 
-			    dev->base_address[j] ^= addrflags;
-			    return;
+	addrlen /= sizeof(struct linux_prom_pci_assigned_addresses);
+	for (j = 0; j < 6; j++) {		/* changing data goes first */
+		address = dev->base_address[j];
+		if (address == 0) break;	/* are sequential */
+		if ((address & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) {
+			if (address < 0x10000) {
+				/*
+				 * Under 64K I/O - use fixed map.
+				 * We expect ALL devices to get here.
+				 *
+				 * CheerIO converts PCI memory transactions
+				 * into IOW/IOR transactions for us, forget it.
+				 *
+				 * Note that check_region()/request_region()
+				 * work for these devices.
+				 */
+				dev->base_address[j] += pcic->pcic_io;
+				nio++;
+			} else {
+				/*
+				 * OOPS... PCI Spec allows this. Sun does
+				 * not have any devices getting above 64K
+				 * so it must be user with a weird I/O
+				 * board in a PCI slot. We must remap it
+				 * under 64K but it is not done yet. XXX
+				 */
+				printk("PCIC: Skipping I/O space at 0x%x,"
+				    "this will Oops if a driver attaches;"
+				    "device '%s' (%x,%x)\n", address, namebuf,
+	    			    dev->device, dev->vendor);
+			}
+		} else {
+			/*
+			 * Memory we must map, as Gleb did this originally.
+			 */
+
+			for (i = 0; i < addrlen; i++) {
+				if (addrs[i].phys_lo == 0) continue;
+				if (addrs[i].phys_lo !=
+				   (address & PCI_BASE_ADDRESS_MEM_MASK))
+					continue;
+
+				length  = addrs[i].size_lo;
+
+				/*
+				 *      failure in allocation too large space
+				 */
+				if (length > 0x200000) {
+					length = 0x200000;
+					prom_printf("PCIC: map window for "
+					    "device '%s' reduced to 2MB !\n",
+					    namebuf);
+				}
+
+				dev->base_address[j] =
+				    (unsigned long)sparc_alloc_io(
+				    address & PCI_BASE_ADDRESS_MEM_MASK,
+				    0, length, namebuf, 0, 0);
+
+				if (dev->base_address[j] == 0) {
+					panic("PCIC: failed to map "
+					    "device '%s' (%x,%x) at %lx\n",
+					    namebuf, dev->device, dev->vendor,
+					    address);
+				}
+				dev->base_address[j] |= address & PCI_BASE_ADDRESS_MEM_TYPE_MASK;
+				nmem++;
 			}
 		}
 	}
 
-	panic("PCIC: unable to locate prom node for pci device (%x,%x) \n",
-	      dev->device, dev->vendor);
+	if (nio == 0 && nmem == 0) {
+		printk("PCIC: not mapped device '%s' (%x,%x)\n",
+		    namebuf, dev->device, dev->vendor);
+	}
 }
 
-/*
- * Assign IO space for a device.
- * This is a chance for devices which have the same IO and Mem Space to
- * fork access to IO and Mem.
- *
- * Now, we assume there is one such device only (IGA 1682) but code below
- * should work in cases when space of all such devices is less then 16MB.
- */
-unsigned long pcic_alloc_io( unsigned long* addr )
-{
-	unsigned long paddr = *addr;
-	unsigned long offset;
+static void pcic_fill_irq(struct pci_dev *dev, int node) {
+	struct pcic_ca2irq *p;
+	int i, ivec;
+	char namebuf[64];  /* P3 remove */
 
-	if(pcic->pcic_mapped_io == 0) {
-		pcic->pcic_mapped_io = paddr & ~(PCI_SPACE_SIZE-1) ;
-		writeb((pcic->pcic_mapped_io>>24) & 0xff, 
-		       pcic->pcic_regs+PCI_PIBAR);
-		writeb((pcic->pcic_io_phys>>24) & PCI_SIBAR_ADDRESS_MASK,
-		       pcic->pcic_regs+PCI_SIBAR);
-		writeb(PCI_ISIZE_16M, pcic->pcic_regs+PCI_ISIZE);
-	}
-	if(paddr < pcic->pcic_mapped_io ||
-	   paddr > pcic->pcic_mapped_io + PCI_SPACE_SIZE)
-		return 0;
-	offset = paddr - pcic->pcic_mapped_io;
-	*addr = pcic->pcic_io_phys + offset;
-	return pcic->pcic_io + offset;
+	if (node == -1) {
+		strcpy(namebuf, "???");
+	} else {
+		prom_getstring(node, "name", namebuf, sizeof(namebuf)); /* P3 remove */
+	}
+
+	if ((p = pcic->pcic_imap) == 0) {
+		dev->irq = 0;
+		return;
+	}
+	for (i = 0; i < pcic->pcic_imdim; i++) {
+		if (p->busno == dev->bus->number && p->devfn == dev->devfn)
+			break;
+		p++;
+	}
+	if (i >= pcic->pcic_imdim) {
+		printk("PCIC: device %s devfn %02x:%02x not found in %d\n",
+		    namebuf, dev->bus->number, dev->devfn, pcic->pcic_imdim);
+		dev->irq = 0;
+		return;
+	}
+
+	i = p->pin;
+	if (i >= 0 && i < 4) {
+		ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_LO);
+		dev->irq = ivec >> (i << 2) & 0xF;
+	} else if (i >= 4 && i < 8) {
+		ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_HI);
+		dev->irq = ivec >> ((i-4) << 2) & 0xF;
+	} else {					/* Corrupted map */
+		printk("PCIC: BAD PIN %d\n", i); for (;;) {}
+	}
+/* P3 remove later */ printk("PCIC: device %s pin %d ivec 0x%x irq %x\n", namebuf, i, ivec, dev->irq);
+
+	/*
+	 * dev->irq=0 means PROM did not bothered to program the upper
+	 * half of PCIC. This happens on JS-E with PROM 3.11, for instance.
+	 */
+	if (dev->irq == 0 || p->force) {
+		if (p->irq == 0 || p->irq >= 15) {	/* Corrupted map */
+			printk("PCIC: BAD IRQ %d\n", p->irq); for (;;) {}
+		}
+		printk("PCIC: setting irq %x for device (%x,%x)\n",
+		    p->irq, dev->device, dev->vendor);
+		dev->irq = p->irq;
+
+		ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_HI);
+		ivec &= ~(0xF << ((p->pin - 4) << 2));
+		ivec |= p->irq << ((p->pin - 4) << 2);
+		writew(ivec, pcic->pcic_regs+PCI_INT_SELECT_HI);
+	}
+
+	return;
 }
 
 /*
@@ -333,6 +509,9 @@
   struct pci_dev *dev;
   int i, has_io, has_mem;
   unsigned short cmd;
+	struct linux_pbm_info* pbm = &pcic->pbm;
+	int node;
+	struct pcidev_cookie *pcp;
 
 	if(pcic == NULL) {
 		prom_printf("PCI: Error, PCIC not found.\n");
@@ -358,47 +537,61 @@
 		}
 		pci_read_config_word(dev, PCI_COMMAND, &cmd);
 		if (has_io && !(cmd & PCI_COMMAND_IO)) {
-			printk("PCI: Enabling I/O for device %02x:%02x\n",
+			printk("PCIC: Enabling I/O for device %02x:%02x\n",
 				dev->bus->number, dev->devfn);
 			cmd |= PCI_COMMAND_IO;
 			pci_write_config_word(dev, PCI_COMMAND, cmd);
 		}
 		if (has_mem && !(cmd & PCI_COMMAND_MEMORY)) {
-			printk("PCI: Enabling memory for device %02x:%02x\n",
+			printk("PCIC: Enabling memory for device %02x:%02x\n",
 				dev->bus->number, dev->devfn);
 			cmd |= PCI_COMMAND_MEMORY;
 			pci_write_config_word(dev, PCI_COMMAND, cmd);
 		}    
 
+		node = pdev_to_pnode(pbm, dev);
+		if(node == 0)
+			node = -1;
+
 		/* cookies */
-		{
-			struct pcidev_cookie *pcp;
-			struct linux_pbm_info* pbm = &pcic->pbm;
-			int node = pdev_to_pnode(pbm, dev);
-
-			if(node == 0)
-				node = -1;
-			pcp = pci_devcookie_alloc();
-			pcp->pbm = pbm;
-			pcp->prom_node = node;
-			dev->sysdata = pcp;
-		}
+		pcp = pci_devcookie_alloc();
+		pcp->pbm = pbm;
+		pcp->prom_node = node;
+		dev->sysdata = pcp;
 
 		/* memory mapping */
-		if (!(dev->vendor == PCI_VENDOR_ID_SUN &&
-		      dev->device == PCI_DEVICE_ID_SUN_EBUS)) {
-			pcic_map_pci_device(dev);
-		}
-
-		/* irq */
-#define SETIRQ(vend,devid,irqn) \
-	if (dev->vendor==vend && dev->device==devid) dev->irq = irqn;
+		if ((dev->class>>16) != PCI_BASE_CLASS_BRIDGE)
+			pcic_map_pci_device(dev, node);
 
-		SETIRQ(PCI_VENDOR_ID_SUN,PCI_DEVICE_ID_SUN_HAPPYMEAL,3);
+		pcic_fill_irq(dev, node);
 	}
+
 	ebus_init();
 }
 
+/*
+ * pcic_pin_to_irq() is exported to ebus.c.
+ */
+unsigned int
+pcic_pin_to_irq(unsigned int pin, char *name)
+{
+	unsigned int irq;
+	unsigned int ivec;
+
+	if (pin < 4) {
+		ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_LO);
+		irq = ivec >> (pin << 2) & 0xF;
+	} else if (pin < 8) {
+		ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_HI);
+		irq = ivec >> ((pin-4) << 2) & 0xF;
+	} else {					/* Corrupted map */
+		printk("PCIC: BAD PIN %d FOR %s\n", pin, name);
+		for (;;) {}	/* XXX Cannot panic properly in case of PROLL */
+	}
+/* P3 remove later */ printk("PCIC: dev %s pin %d ivec 0x%x irq %x\n", name, pin, ivec, irq);
+	return irq;
+}
+
 /* Makes compiler happy */
 static volatile int pcic_timer_dummy;
 
@@ -538,26 +731,38 @@
 			       unsigned char where, unsigned int *value)
 {
 	unsigned long flags;
-	if (where&3) return PCIBIOS_BAD_REGISTER_NUMBER;
-	if (bus != 0 || 
-	    (device_fn != 0 && device_fn != 1 && device_fn != 0x80)) {
-		*value = 0xffffffff;
-		return PCIBIOS_SUCCESSFUL;
-	}
 
-	/* FIXME: IGA haven't got high config memory addresses !!! */
-	if (device_fn == 0x80 && where > PCI_INTERRUPT_LINE) {
-		*value = 0xffffffff;
-		return PCIBIOS_SUCCESSFUL;
-	}
+	if (where&3) return PCIBIOS_BAD_REGISTER_NUMBER;
 
 	save_and_cli(flags);
+#if 0
+	pcic_speculative = 1;
+	pcic_trapped = 0;
+#endif
 	writel(CONFIG_CMD(bus,device_fn,where), pcic->pcic_config_space_addr);
+#if 0
+	nop();
+	if (pcic_trapped) {
+		restore_flags(flags);
+		*value = ~0;
+		return PCIBIOS_SUCCESSFUL;
+	}
+#endif
+	pcic_speculative = 2;
+	pcic_trapped = 0;
 	*value = readl(pcic->pcic_config_space_data + (where&4));
+	nop();
+	if (pcic_trapped) {
+		pcic_speculative = 0;
+		restore_flags(flags);
+		*value = ~0;
+		return PCIBIOS_SUCCESSFUL;
+	}
+	pcic_speculative = 0;
 	restore_flags(flags);
 	return PCIBIOS_SUCCESSFUL;
 }
-    
+
 int pcibios_write_config_byte (unsigned char bus, unsigned char devfn,
 			       unsigned char where, unsigned char value)
 {
@@ -585,8 +790,8 @@
 				unsigned char where, unsigned int value)
 {
 	unsigned long flags;
-	if ((where&3) || bus != 0 || (devfn != 0 && devfn != 1 && devfn != 0x80))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	if (where&3) return PCIBIOS_BAD_REGISTER_NUMBER;
 
 	save_and_cli(flags);
 	writel(CONFIG_CMD(bus,devfn,where),pcic->pcic_config_space_addr);
@@ -598,6 +803,29 @@
 __initfunc(char *pcibios_setup(char *str))
 {
 	return str;
+}
+
+/*
+ * NMI
+ */
+void pcic_nmi(unsigned int pend, struct pt_regs *regs)
+{
+
+	pend = flip_dword(pend);
+
+	if (!pcic_speculative || (pend & PCI_SYS_INT_PENDING_PIO) == 0) {
+		/*
+		 * XXX On CP-1200 PCI #SERR may happen, we do not know
+		 * what to do about it yet.
+		 */
+		printk("Aiee, NMI pend 0x%x pc 0x%x spec %d, hanging\n",
+		    pend, (int)regs->pc, pcic_speculative);
+		for (;;) { }
+	}
+	pcic_speculative = 0;
+	pcic_trapped = 1;
+	regs->pc = regs->npc;
+	regs->npc += 4;
 }
 
 /*
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc/kernel/sys_sunos.c linux.15p9/arch/sparc/kernel/sys_sunos.c
--- linux.vanilla/arch/sparc/kernel/sys_sunos.c	Tue Jan  4 21:18:41 2000
+++ linux.15p9/arch/sparc/kernel/sys_sunos.c	Fri Jan 21 17:50:17 2000
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos.c,v 1.94.2.3 1999/10/04 10:36:20 davem Exp $
+/* $Id: sys_sunos.c,v 1.94.2.4 2000/01/17 21:28:27 davem Exp $
  * sys_sunos.c: SunOS specific syscall compatibility support.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -370,6 +370,7 @@
 	spin_lock_irq(&current->sigmask_lock);
 	old = current->blocked.sig[0];
 	current->blocked.sig[0] |= (blk_mask & _BLOCKABLE);
+	recalc_sigpending(current);
 	spin_unlock_irq(&current->sigmask_lock);
 	return old;
 }
@@ -381,6 +382,7 @@
 	spin_lock_irq(&current->sigmask_lock);
 	retval = current->blocked.sig[0];
 	current->blocked.sig[0] = (newmask & _BLOCKABLE);
+	recalc_sigpending(current);
 	spin_unlock_irq(&current->sigmask_lock);
 	return retval;
 }
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc/mm/srmmu.c linux.15p9/arch/sparc/mm/srmmu.c
--- linux.vanilla/arch/sparc/mm/srmmu.c	Tue Jan  4 21:18:42 2000
+++ linux.15p9/arch/sparc/mm/srmmu.c	Fri Jan 14 15:56:16 2000
@@ -1,4 +1,4 @@
-/* $Id: srmmu.c,v 1.187.2.7 1999/11/16 06:29:44 davem Exp $
+/* $Id: srmmu.c,v 1.187.2.8 1999/12/23 01:58:38 davem Exp $
  * srmmu.c:  SRMMU specific routines for memory management.
  *
  * Copyright (C) 1995 David S. Miller  (davem@caip.rutgers.edu)
@@ -1662,7 +1662,8 @@
 	srmmu_map[srmmu_bank].vbase = vbase;
 	srmmu_map[srmmu_bank].pbase = sp_banks[sp_entry].base_addr;
 	srmmu_map[srmmu_bank].size = sp_banks[sp_entry].num_bytes;
-	srmmu_bank++;
+	if (srmmu_map[srmmu_bank].size)
+		srmmu_bank++;
 	map_spbank_last_pa = pstart - SRMMU_PGDIR_SIZE;
 	return vstart;
 }
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc64/config.in linux.15p9/arch/sparc64/config.in
--- linux.vanilla/arch/sparc64/config.in	Tue Jan  4 21:18:42 2000
+++ linux.15p9/arch/sparc64/config.in	Wed Feb 16 18:29:09 2000
@@ -131,6 +131,25 @@
 
 if [ "$CONFIG_NET" = "y" ]; then
 	source net/Config.in
+	mainmenu_option next_comment
+	comment 'Amateur Radio support'
+	bool 'Amateur Radio support' CONFIG_HAMRADIO
+	if [ "$CONFIG_HAMRADIO" != "n" ] ; then
+		comment 'Packet Radio protocols'
+		tristate 'Amateur Radio AX.25 Level 2 protocol' CONFIG_AX25
+		if [ "$CONFIG_AX25" != "n" ]; then
+			bool '   AX.25 DAMA Slave support' CONFIG_AX25_DAMA_SLAVE
+#			bool '   AX.25 DAMA Master support' CONFIG_AX25_DAMA_MASTER
+			dep_tristate '   Amateur Radio NET/ROM protocol' CONFIG_NETROM $CONFIG_AX25
+			dep_tristate '   Amateur Radio X.25 PLP (Rose)' CONFIG_ROSE $CONFIG_AX25
+
+			comment 'AX.25 network device drivers'
+			dep_tristate 'Serial port KISS driver' CONFIG_MKISS $CONFIG_AX25
+			dep_tristate 'Serial port 6PACK driver' CONFIG_6PACK $CONFIG_AX25
+		fi
+	fi
+
+	endmenu
 fi
 
 mainmenu_option next_comment
@@ -158,7 +177,7 @@
 	mainmenu_option next_comment
 	comment 'SCSI low-level drivers'
 
-	bool 'Sparc ESP Scsi Driver' CONFIG_SCSI_SUNESP $CONFIG_SCSI
+	tristate 'Sparc ESP Scsi Driver' CONFIG_SCSI_SUNESP $CONFIG_SCSI
 	tristate 'PTI Qlogic,ISP Driver' CONFIG_SCSI_QLOGICPTI $CONFIG_SCSI
 
 	if [ "$CONFIG_PCI" != "n" ]; then
@@ -198,6 +217,7 @@
 	bool 'Network device support' CONFIG_NETDEVICES
 	if [ "$CONFIG_NETDEVICES" = "y" ]; then
 		tristate 'Dummy net driver support' CONFIG_DUMMY
+		tristate 'Bonding driver support' CONFIG_BONDING
 		tristate 'PPP (point-to-point) support' CONFIG_PPP
 		if [ ! "$CONFIG_PPP" = "n" ]; then
 		   comment 'CCP compressors for PPP are only built as modules.'
@@ -221,6 +241,7 @@
 			tristate 'RealTek 8129/8139 (not 8019/8029!) support' CONFIG_RTL8139
 			tristate 'PCI NE2000 support' CONFIG_NE2K_PCI
 			tristate 'EtherExpressPro/100 support' CONFIG_EEXPRESS_PRO100
+			tristate 'SysKonnect SK-98xx support' CONFIG_SK98LIN
 		fi
 #		bool 'FDDI driver support' CONFIG_FDDI
 #		if [ "$CONFIG_FDDI" = "y" ]; then
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc64/defconfig linux.15p9/arch/sparc64/defconfig
--- linux.vanilla/arch/sparc64/defconfig	Tue Jan  4 21:18:42 2000
+++ linux.15p9/arch/sparc64/defconfig	Thu Feb 17 21:58:23 2000
@@ -176,6 +176,11 @@
 # CONFIG_NET_SCHED is not set
 
 #
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
 # SCSI support
 #
 CONFIG_SCSI=y
@@ -235,6 +240,7 @@
 #
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
+CONFIG_BONDING=m
 CONFIG_PPP=m
 
 #
@@ -254,6 +260,7 @@
 CONFIG_RTL8139=m
 CONFIG_NE2K_PCI=m
 CONFIG_EEXPRESS_PRO100=m
+CONFIG_SK98LIN=m
 
 #
 # Unix 98 PTY support
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc64/kernel/binfmt_elf32.c linux.15p9/arch/sparc64/kernel/binfmt_elf32.c
--- linux.vanilla/arch/sparc64/kernel/binfmt_elf32.c	Sun Oct  4 18:22:43 1998
+++ linux.15p9/arch/sparc64/kernel/binfmt_elf32.c	Mon Feb  7 12:29:22 2000
@@ -1,7 +1,7 @@
 /*
  * binfmt_elf32.c: Support 32-bit Sparc ELF binaries on Ultra.
  *
- * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller	(davem@dm.cobaltmicro.com)
+ * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller	(davem@redhat.com)
  * Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek	(jj@ultra.linux.cz)
  */
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc64/kernel/dtlb_backend.S linux.15p9/arch/sparc64/kernel/dtlb_backend.S
--- linux.vanilla/arch/sparc64/kernel/dtlb_backend.S	Tue Jan  4 21:18:42 2000
+++ linux.15p9/arch/sparc64/kernel/dtlb_backend.S	Mon Feb  7 12:29:22 2000
@@ -1,8 +1,8 @@
-/* $Id: dtlb_backend.S,v 1.7.2.1 1999/12/05 10:41:57 davem Exp $
+/* $Id: dtlb_backend.S,v 1.7.2.2 2000/01/31 05:02:35 davem Exp $
  * dtlb_backend.S: Back end to DTLB miss replacement strategy.
  *                 This is included directly into the trap table.
  *
- * Copyright (C) 1996,1998 David S. Miller (davem@dm.cobaltmicro.com)
+ * Copyright (C) 1996,1998 David S. Miller (davem@redhat.com)
  * Copyright (C) 1997,1998 Jakub Jelinek   (jj@ultra.linux.cz)
  */
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc64/kernel/dtlb_base.S linux.15p9/arch/sparc64/kernel/dtlb_base.S
--- linux.vanilla/arch/sparc64/kernel/dtlb_base.S	Wed Aug  5 00:03:35 1998
+++ linux.15p9/arch/sparc64/kernel/dtlb_base.S	Mon Feb  7 12:29:22 2000
@@ -1,8 +1,8 @@
-/* $Id: dtlb_base.S,v 1.4 1998/06/15 16:59:30 jj Exp $
+/* $Id: dtlb_base.S,v 1.4.2.1 2000/01/31 05:02:35 davem Exp $
  * dtlb_base.S:	Front end to DTLB miss replacement strategy.
  *              This is included directly into the trap table.
  *
- * Copyright (C) 1996,1998 David S. Miller (davem@dm.cobaltmicro.com)
+ * Copyright (C) 1996,1998 David S. Miller (davem@redhat.com)
  * Copyright (C) 1997,1998 Jakub Jelinek   (jj@ultra.linux.cz)
  */
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc64/kernel/dtlb_prot.S linux.15p9/arch/sparc64/kernel/dtlb_prot.S
--- linux.vanilla/arch/sparc64/kernel/dtlb_prot.S	Thu Mar 11 00:53:37 1999
+++ linux.15p9/arch/sparc64/kernel/dtlb_prot.S	Mon Feb  7 12:29:22 2000
@@ -1,8 +1,8 @@
-/* $Id: dtlb_prot.S,v 1.18 1999/03/02 15:42:14 jj Exp $
+/* $Id: dtlb_prot.S,v 1.18.2.1 2000/01/31 05:02:35 davem Exp $
  * dtlb_prot.S: DTLB protection trap strategy.
  *              This is included directly into the trap table.
  *
- * Copyright (C) 1996,1998 David S. Miller (davem@dm.cobaltmicro.com)
+ * Copyright (C) 1996,1998 David S. Miller (davem@redhat.com)
  * Copyright (C) 1997,1998 Jakub Jelinek   (jj@ultra.linux.cz)
  */
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc64/kernel/ioctl32.c linux.15p9/arch/sparc64/kernel/ioctl32.c
--- linux.vanilla/arch/sparc64/kernel/ioctl32.c	Tue Jan  4 21:18:43 2000
+++ linux.15p9/arch/sparc64/kernel/ioctl32.c	Tue Jan 18 00:49:39 2000
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.62.2.8 1999/11/16 23:59:31 davem Exp $
+/* $Id: ioctl32.c,v 1.62.2.9 2000/01/15 04:40:57 davem Exp $
  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  *
  * Copyright (C) 1997  Jakub Jelinek  (jj@sunsite.mff.cuni.cz)
@@ -37,6 +37,7 @@
 #include <linux/ext2_fs.h>
 #include <linux/videodev.h>
 #include <linux/netdevice.h>
+#include <linux/smb_fs.h>
 
 #include <scsi/scsi.h>
 /* Ugly hack. */
@@ -1692,6 +1693,24 @@
 	return 0;
 }
 
+static int do_smb_getmountuid(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	__kernel_uid_t kuid;
+	int err;
+
+	cmd = SMB_IOC_GETMOUNTUID;
+
+	set_fs(KERNEL_DS);
+	err = sys_ioctl(fd, cmd, (unsigned long)&kuid);
+	set_fs(old_fs);
+
+	if (err >= 0)
+		err = put_user(kuid, (__kernel_uid_t32 *)arg);
+
+	return err;
+}
+
 asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	struct file * filp;
@@ -1878,6 +1897,11 @@
 		error = do_video_ioctl(fd, cmd, arg);
 		goto out;
 
+	/* One SMB ioctl needs translations. */
+	case _IOR('u', 1, __kernel_uid_t32): /* SMB_IOC_GETMOUNTUID */
+		error = do_smb_getmountuid(fd, cmd, arg);
+		goto out;
+
 	/* List here exlicitly which ioctl's are known to have
 	 * compatable types passed or none at all...
 	 */
@@ -2393,6 +2417,9 @@
 	/* Raw devices */
 	case _IO(0xac, 0): /* RAW_SETBIND */
 	case _IO(0xac, 1): /* RAW_GETBIND */
+
+	/* SMB ioctls which do not need any translations */
+	case SMB_IOC_NEWCONN:
 
 		error = sys_ioctl (fd, cmd, arg);
 		goto out;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc64/kernel/irq.c linux.15p9/arch/sparc64/kernel/irq.c
--- linux.vanilla/arch/sparc64/kernel/irq.c	Tue Jan  4 21:18:43 2000
+++ linux.15p9/arch/sparc64/kernel/irq.c	Thu Feb 17 21:58:23 2000
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.76.2.1 1999/12/05 07:24:37 davem Exp $
+/* $Id: irq.c,v 1.76.2.2 2000/02/17 18:05:36 davem Exp $
  * irq.c: UltraSparc IRQ handling/init/registry.
  *
  * Copyright (C) 1997  David S. Miller  (davem@caip.rutgers.edu)
@@ -1399,7 +1399,7 @@
 	prom_timers->count0 = 0;
 }
 
-__initfunc(void init_IRQ(void))
+unsigned long __init init_IRQ(unsigned long memory)
 {
 	static int called = 0;
 
@@ -1430,4 +1430,5 @@
 			     : /* No outputs */
 			     : "i" (PSTATE_IE)
 			     : "g1");
+	return memory;
 }
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc64/kernel/itlb_base.S linux.15p9/arch/sparc64/kernel/itlb_base.S
--- linux.vanilla/arch/sparc64/kernel/itlb_base.S	Thu Mar 11 00:53:37 1999
+++ linux.15p9/arch/sparc64/kernel/itlb_base.S	Mon Feb  7 12:29:22 2000
@@ -1,8 +1,8 @@
-/* $Id: itlb_base.S,v 1.7 1999/03/02 15:42:12 jj Exp $
+/* $Id: itlb_base.S,v 1.7.2.1 2000/01/31 05:02:35 davem Exp $
  * itlb_base.S:	Front end to ITLB miss replacement strategy.
  *              This is included directly into the trap table.
  *
- * Copyright (C) 1996,1998 David S. Miller (davem@dm.cobaltmicro.com)
+ * Copyright (C) 1996,1998 David S. Miller (davem@redhat.com)
  * Copyright (C) 1997,1998 Jakub Jelinek   (jj@ultra.linux.cz)
  */
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc64/kernel/signal32.c linux.15p9/arch/sparc64/kernel/signal32.c
--- linux.vanilla/arch/sparc64/kernel/signal32.c	Sat Aug 14 02:26:47 1999
+++ linux.15p9/arch/sparc64/kernel/signal32.c	Fri Jan 14 15:56:16 2000
@@ -1,4 +1,4 @@
-/*  $Id: signal32.c,v 1.47.2.1 1999/06/14 00:36:24 davem Exp $
+/*  $Id: signal32.c,v 1.47.2.3 1999/12/20 01:14:06 davem Exp $
  *  arch/sparc64/kernel/signal32.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
@@ -1033,6 +1033,62 @@
 		err |= __put_user(0, &sf->fpu_save);
 	}
 	
+	/* Update the siginfo structure.  Is this good?  */
+	if (info->si_code == 0) {
+		info->si_signo = signr;
+		info->si_errno = 0;
+
+		switch (signr) {
+		case SIGSEGV:
+		case SIGILL:
+		case SIGFPE:
+		case SIGBUS:
+		case SIGEMT:
+			info->si_code = current->tss.sig_desc;
+			info->si_addr = (void *)current->tss.sig_address;
+			info->si_trapno = 0;
+			break;
+		default:
+			break;
+		}
+	}
+
+	err = __put_user (info->si_signo, &sf->info.si_signo);
+	err |= __put_user (info->si_errno, &sf->info.si_errno);
+	err |= __put_user (info->si_code, &sf->info.si_code);
+	if (info->si_code < 0)
+		err |= __copy_to_user (sf->info._sifields._pad, info->_sifields._pad, SI_PAD_SIZE);
+	else {
+		i = info->si_signo;
+		if (info->si_code == SI_USER)
+			i = SIGRTMIN;
+		switch (i) {
+		case SIGPOLL:
+			err |= __put_user (info->si_band, &sf->info.si_band);
+			err |= __put_user (info->si_fd, &sf->info.si_fd);
+			break;
+		case SIGCHLD:
+			err |= __put_user (info->si_pid, &sf->info.si_pid);
+			err |= __put_user (info->si_uid, &sf->info.si_uid);
+			err |= __put_user (info->si_status, &sf->info.si_status);
+			err |= __put_user (info->si_utime, &sf->info.si_utime);
+			err |= __put_user (info->si_stime, &sf->info.si_stime);
+			break;
+		case SIGSEGV:
+		case SIGILL:
+		case SIGFPE:
+		case SIGBUS:
+		case SIGEMT:
+			err |= __put_user ((long)info->si_addr, &sf->info.si_addr);
+			err |= __put_user (info->si_trapno, &sf->info.si_trapno);
+			break;
+		default:
+			err |= __put_user (info->si_pid, &sf->info.si_pid);
+			err |= __put_user (info->si_uid, &sf->info.si_uid);
+			break;
+		}
+	}
+	
 	/* Setup sigaltstack */
 	err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp);
 	err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags);
@@ -1048,7 +1104,7 @@
 	case 1: seta.sig[1] = (oldset->sig[0] >> 32);
 	        seta.sig[0] = oldset->sig[0];
 	}
-	err |= __copy_to_user(&sf->mask, &seta, sizeof(sigset_t));
+	err |= __copy_to_user(&sf->mask, &seta, sizeof(sigset_t32));
 
 	err |= copy_in_user((u32 *)sf,
 			    (u32 *)(regs->u_regs[UREG_FP]),
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc64/kernel/smp.c linux.15p9/arch/sparc64/kernel/smp.c
--- linux.vanilla/arch/sparc64/kernel/smp.c	Tue Jan  4 21:18:43 2000
+++ linux.15p9/arch/sparc64/kernel/smp.c	Thu Feb 17 21:58:23 2000
@@ -159,7 +159,7 @@
 }
 
 extern int cpu_idle(void *unused);
-extern void init_IRQ(void);
+extern unsigned long init_IRQ(unsigned long);
 
 void initialize_secondary(void)
 {
@@ -168,7 +168,8 @@
 int start_secondary(void *unused)
 {
 	trap_init();
-	init_IRQ();
+	/* No memory allocation allowed on slave IRQ init */
+	init_IRQ(0UL);
 	smp_callin();
 	return cpu_idle(NULL);
 }
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc64/kernel/starfire.c linux.15p9/arch/sparc64/kernel/starfire.c
--- linux.vanilla/arch/sparc64/kernel/starfire.c	Thu Mar 11 00:53:37 1999
+++ linux.15p9/arch/sparc64/kernel/starfire.c	Mon Feb  7 12:29:22 2000
@@ -1,7 +1,7 @@
-/* $Id: starfire.c,v 1.2 1998/12/09 18:53:11 davem Exp $
+/* $Id: starfire.c,v 1.2.2.1 2000/01/31 05:02:35 davem Exp $
  * starfire.c: Starfire/E10000 support.
  *
- * Copyright (C) 1998 David S. Miller (davem@dm.cobaltmicro.com)
+ * Copyright (C) 1998 David S. Miller (davem@redhat.com)
  */
 
 #include <linux/kernel.h>
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc64/kernel/sys32.S linux.15p9/arch/sparc64/kernel/sys32.S
--- linux.vanilla/arch/sparc64/kernel/sys32.S	Mon Nov 16 18:37:28 1998
+++ linux.15p9/arch/sparc64/kernel/sys32.S	Wed Jan 26 23:03:00 2000
@@ -1,4 +1,4 @@
-/* $Id: sys32.S,v 1.8 1998/10/28 08:10:37 jj Exp $
+/* $Id: sys32.S,v 1.8.2.1 2000/01/24 11:36:55 jj Exp $
  * sys32.S: I-cache tricks for 32-bit compatability layer simple
  *          conversions.
  *
@@ -20,7 +20,7 @@
 
 	.align		32
 	.globl		sys32_lseek
-	.globl		sys32_chmod, sys32_chown, sys32_lchown, sys32_mknod
+	.globl		sys32_chmod, sys32_mknod
 sys32_lseek:
 	sra		%o1, 0, %o1
 	sethi		%hi(sys_lseek), %g1
@@ -32,20 +32,6 @@
 	orcc		%g2, %lo(0xffff), %g2
 	jmpl		%g1 + %lo(sys_chmod), %g0
 	 and		%o1, %g2, %o1
-sys32_chown:
-	sethi		%hi(0xffff), %g2
-	sethi		%hi(sys_chown), %g1
-	orcc		%g2, %lo(0xffff), %g2
-	and		%o1, %g2, %o1
-	jmpl		%g1 + %lo(sys_chown), %g0
-	 and		%o2, %g2, %o2
-sys32_lchown:
-	sethi		%hi(0xffff), %g2
-	sethi		%hi(sys_lchown), %g1
-	orcc		%g2, %lo(0xffff), %g2
-	and		%o1, %g2, %o1
-	jmpl		%g1 + %lo(sys_lchown), %g0
-	 and		%o2, %g2, %o2
 sys32_mknod:
 	sethi		%hi(0xffff), %g2
 	sethi		%hi(sys_mknod), %g1
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc64/kernel/sys_sparc32.c linux.15p9/arch/sparc64/kernel/sys_sparc32.c
--- linux.vanilla/arch/sparc64/kernel/sys_sparc32.c	Tue Jan  4 21:18:43 2000
+++ linux.15p9/arch/sparc64/kernel/sys_sparc32.c	Wed Jan 26 23:03:00 2000
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.107.2.5 1999/11/12 11:17:47 davem Exp $
+/* $Id: sys_sparc32.c,v 1.107.2.7 2000/01/24 11:36:50 jj Exp $
  * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -1890,15 +1890,14 @@
 	return ret;
 }
 
+#define low2highuid(uid) ((uid) == (u16)-1) ? (uid_t)-1 : (uid_t)(uid)
+#define low2highgid(gid) ((gid) == (u16)-1) ? (gid_t)-1 : (gid_t)(gid)
+
 extern asmlinkage int sys_setreuid(uid_t ruid, uid_t euid);
 
 asmlinkage int sys32_setreuid(__kernel_uid_t32 ruid, __kernel_uid_t32 euid)
 {
-	uid_t sruid, seuid;
-
-	sruid = (ruid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)ruid);
-	seuid = (euid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)euid);
-	return sys_setreuid(sruid, seuid);
+	return sys_setreuid(low2highuid(ruid), low2highuid(euid));
 }
 
 extern asmlinkage int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid);
@@ -1907,12 +1906,7 @@
 			       __kernel_uid_t32 euid,
 			       __kernel_uid_t32 suid)
 {
-	uid_t sruid, seuid, ssuid;
-
-	sruid = (ruid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)ruid);
-	seuid = (euid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)euid);
-	ssuid = (suid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)suid);
-	return sys_setresuid(sruid, seuid, ssuid);
+	return sys_setresuid(low2highuid(ruid), low2highuid(euid), low2highuid(suid));
 }
 
 extern asmlinkage int sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
@@ -1935,11 +1929,7 @@
 
 asmlinkage int sys32_setregid(__kernel_gid_t32 rgid, __kernel_gid_t32 egid)
 {
-	gid_t srgid, segid;
-
-	srgid = (rgid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)rgid);
-	segid = (egid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)egid);
-	return sys_setregid(srgid, segid);
+	return sys_setregid(low2highgid(rgid), low2highgid(egid));
 }
 
 extern asmlinkage int sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid);
@@ -1948,12 +1938,7 @@
 			       __kernel_gid_t32 egid,
 			       __kernel_gid_t32 sgid)
 {
-	gid_t srgid, segid, ssgid;
-
-	srgid = (rgid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)rgid);
-	segid = (egid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)egid);
-	ssgid = (sgid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)sgid);
-	return sys_setresgid(srgid, segid, ssgid);
+	return sys_setresgid(low2highgid(rgid), low2highgid(egid), low2highgid(sgid));
 }
 
 extern asmlinkage int sys_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);
@@ -1975,6 +1960,25 @@
 	return ret;
 }
 
+extern asmlinkage long sys_chown(const char *, uid_t,gid_t);
+extern asmlinkage long sys_lchown(const char *, uid_t,gid_t);
+extern asmlinkage long sys_fchown(unsigned int, uid_t,gid_t);
+
+asmlinkage long sys32_chown16(const char * filename, u16 user, u16 group)
+{
+	return sys_chown(filename, low2highuid(user), low2highgid(group));
+}
+
+asmlinkage long sys32_lchown16(const char * filename, u16 user, u16 group)
+{
+	return sys_lchown(filename, low2highuid(user), low2highgid(group));
+}
+                
+asmlinkage long sys32_fchown16(unsigned int fd, u16 user, u16 group)
+{
+	return sys_fchown(fd, low2highuid(user), low2highgid(group));
+}
+
 struct tms32 {
 	__kernel_clock_t32 tms_utime;
 	__kernel_clock_t32 tms_stime;
@@ -3150,7 +3154,7 @@
 
 	if (mod->next == NULL)
 		return -EINVAL;
-	if ((mod->flags & (MOD_RUNNING | MOD_DELETED)) != MOD_RUNNING)
+	if (!MOD_CAN_QUERY(mod))
 		if (put_user(0, ret))
 			return -EFAULT;
 		else
@@ -3194,7 +3198,7 @@
 
 	if (mod->next == NULL)
 		return -EINVAL;
-	if ((mod->flags & (MOD_RUNNING | MOD_DELETED)) != MOD_RUNNING)
+	if (!MOD_CAN_QUERY(mod))
 		if (put_user(0, ret))
 			return -EFAULT;
 		else
@@ -3238,7 +3242,7 @@
 	char *strings;
 	unsigned *vals;
 
-	if ((mod->flags & (MOD_RUNNING | MOD_DELETED)) != MOD_RUNNING)
+	if (!MOD_CAN_QUERY(mod))
 		if (put_user(0, ret))
 			return -EFAULT;
 		else
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc64/kernel/sys_sunos32.c linux.15p9/arch/sparc64/kernel/sys_sunos32.c
--- linux.vanilla/arch/sparc64/kernel/sys_sunos32.c	Sat Aug 14 02:27:15 1999
+++ linux.15p9/arch/sparc64/kernel/sys_sunos32.c	Fri Jan 21 17:50:17 2000
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos32.c,v 1.22.2.2 1999/08/07 10:43:02 davem Exp $
+/* $Id: sys_sunos32.c,v 1.22.2.3 2000/01/17 21:28:31 davem Exp $
  * sys_sunos32.c: SunOS binary compatability layer on sparc64.
  *
  * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -327,6 +327,7 @@
 	spin_lock_irq(&current->sigmask_lock);
 	old = (u32) current->blocked.sig[0];
 	current->blocked.sig[0] |= (blk_mask & _BLOCKABLE);
+	recalc_sigpending(current);
 	spin_unlock_irq(&current->sigmask_lock);
 	return old;
 }
@@ -338,6 +339,7 @@
 	spin_lock_irq(&current->sigmask_lock);
 	retval = (u32) current->blocked.sig[0];
 	current->blocked.sig[0] = (newmask & _BLOCKABLE);
+	recalc_sigpending(current);
 	spin_unlock_irq(&current->sigmask_lock);
 	return retval;
 }
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc64/kernel/systbls.S linux.15p9/arch/sparc64/kernel/systbls.S
--- linux.vanilla/arch/sparc64/kernel/systbls.S	Wed Oct 20 01:12:34 1999
+++ linux.15p9/arch/sparc64/kernel/systbls.S	Wed Jan 26 23:03:00 2000
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.53.2.1 1999/09/22 11:37:39 jj Exp $
+/* $Id: systbls.S,v 1.53.2.3 2000/01/24 22:14:40 davem Exp $
  * systbls.S: System call entry point tables for OS compatibility.
  *            The native Linux system call table lives here also.
  *
@@ -21,8 +21,8 @@
 sys_call_table32:
 /*0*/	.word sys_nis_syscall, sparc_exit, sys_fork, sys_read, sys_write
 /*5*/	.word sys_open, sys_close, sys32_wait4, sys_creat, sys_link
-/*10*/  .word sys_unlink, sunos_execv, sys_chdir, sys32_chown, sys32_mknod
-/*15*/	.word sys32_chmod, sys32_lchown, sparc_brk, sys_perfctr, sys32_lseek
+/*10*/  .word sys_unlink, sunos_execv, sys_chdir, sys32_chown16, sys32_mknod
+/*15*/	.word sys32_chmod, sys32_lchown16, sparc_brk, sys_perfctr, sys32_lseek
 /*20*/	.word sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid
 /*25*/	.word sys_time, sys_ptrace, sys_alarm, sys32_sigaltstack, sys32_pause
 /*30*/	.word sys32_utime, sys_nis_syscall, sys_nis_syscall, sys_access, sys_nice
@@ -43,7 +43,7 @@
 	.word sys32_rt_sigtimedwait, sys32_rt_sigqueueinfo, sys32_rt_sigsuspend, sys_nis_syscall, sys_nis_syscall
 /*110*/	.word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 	.word sys_nis_syscall, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd
-/*120*/	.word sys32_readv, sys32_writev, sys32_settimeofday, sys_fchown, sys_fchmod
+/*120*/	.word sys32_readv, sys32_writev, sys32_settimeofday, sys32_fchown16, sys_fchmod
 	.word sys_nis_syscall, sys32_setreuid, sys32_setregid, sys_rename, sys_truncate
 /*130*/	.word sys_ftruncate, sys_flock, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 	.word sys_nis_syscall, sys_mkdir, sys_rmdir, sys32_utimes, sys_nis_syscall
@@ -143,7 +143,7 @@
 	.word sys_close, sunos_wait4, sys_creat
 	.word sys_link, sys_unlink, sunos_execv
 	.word sys_chdir, sunos_nosys, sys32_mknod
-	.word sys32_chmod, sys32_lchown, sunos_brk
+	.word sys32_chmod, sys32_lchown16, sunos_brk
 	.word sunos_nosys, sys32_lseek, sunos_getpid
 	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_getuid, sunos_nosys, sys_ptrace
@@ -179,7 +179,7 @@
 	.word sys32_sigstack, sys32_recvmsg, sys32_sendmsg
 	.word sunos_nosys, sys32_gettimeofday, sys32_getrusage
 	.word sunos_getsockopt, sunos_nosys, sunos_readv
-	.word sunos_writev, sys32_settimeofday, sys_fchown
+	.word sunos_writev, sys32_settimeofday, sys32_fchown16
 	.word sys_fchmod, sys32_recvfrom, sys32_setreuid
 	.word sys_setregid, sys_rename, sys_truncate
 	.word sys_ftruncate, sys_flock, sunos_nosys
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc64/kernel/traps.c linux.15p9/arch/sparc64/kernel/traps.c
--- linux.vanilla/arch/sparc64/kernel/traps.c	Tue Jan  4 21:18:43 2000
+++ linux.15p9/arch/sparc64/kernel/traps.c	Fri Jan 14 15:56:16 2000
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.58.2.2 1999/12/01 23:55:43 davem Exp $
+/* $Id: traps.c,v 1.58.2.3 1999/12/19 23:59:28 davem Exp $
  * arch/sparc64/kernel/traps.c
  *
  * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -516,8 +516,22 @@
 		regs->tpc = regs->tnpc;
 		regs->tnpc += 4;
 	} else {
+		unsigned long fsr = current->tss.xfsr[0];
+
 		current->tss.sig_address = regs->tpc;
 		current->tss.sig_desc = SUBSIG_FPERROR;
+		if ((fsr & 0x1c000) == (1 << 14)) {
+			if (fsr & 0x01)
+				current->tss.sig_desc = SUBSIG_FPINEXACT;
+			else if (fsr & 0x02)
+				current->tss.sig_desc = SUBSIG_FPDIVZERO;
+			else if (fsr & 0x04)
+				current->tss.sig_desc = SUBSIG_FPUNFLOW;
+			else if (fsr & 0x08)
+				current->tss.sig_desc = SUBSIG_FPOVFLOW;
+			else if (fsr & 0x10)
+				current->tss.sig_desc = SUBSIG_FPINTOVFL;
+		}
 		send_sig(SIGFPE, current, 1);
 	}
 }
@@ -561,7 +575,9 @@
 
 void do_div0(struct pt_regs *regs)
 {
-	send_sig(SIGILL, current, 1);
+	current->tss.sig_address = regs->tpc;
+	current->tss.sig_desc = SUBSIG_IDIVZERO;
+	send_sig(SIGFPE, current, 1);
 }
 
 void instruction_dump (unsigned int *pc)
@@ -686,10 +702,12 @@
 	send_sig(SIGILL, current, 1);
 }
 
-void handle_hw_divzero(struct pt_regs *regs, unsigned long pc, unsigned long npc,
-		       unsigned long psr)
+void handle_hw_divzero(struct pt_regs *regs, unsigned long pc,
+		       unsigned long npc, unsigned long psr)
 {
-	send_sig(SIGILL, current, 1);
+	current->tss.sig_address = regs->tpc;
+	current->tss.sig_desc = SUBSIG_IDIVZERO;
+	send_sig(SIGFPE, current, 1);
 }
 
 /* Trap level 1 stuff or other traps we should never see... */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc64/lib/debuglocks.c linux.15p9/arch/sparc64/lib/debuglocks.c
--- linux.vanilla/arch/sparc64/lib/debuglocks.c	Tue Oct 27 17:52:20 1998
+++ linux.15p9/arch/sparc64/lib/debuglocks.c	Mon Feb  7 12:29:21 2000
@@ -1,7 +1,7 @@
-/* $Id: debuglocks.c,v 1.2 1998/10/13 09:07:27 davem Exp $
+/* $Id: debuglocks.c,v 1.2.2.1 2000/01/31 05:02:31 davem Exp $
  * debuglocks.c: Debugging versions of SMP locking primitives.
  *
- * Copyright (C) 1998 David S. Miller (davem@dm.cobaltmicro.com)
+ * Copyright (C) 1998 David S. Miller (davem@redhat.com)
  */
 
 #include <linux/kernel.h>
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc64/lib/memscan.S linux.15p9/arch/sparc64/lib/memscan.S
--- linux.vanilla/arch/sparc64/lib/memscan.S	Wed Aug  5 00:03:35 1998
+++ linux.15p9/arch/sparc64/lib/memscan.S	Mon Feb  7 12:29:21 2000
@@ -1,8 +1,8 @@
-/* $Id: memscan.S,v 1.2 1998/05/21 14:42:22 jj Exp $
+/* $Id: memscan.S,v 1.2.2.1 2000/01/31 05:02:32 davem Exp $
  * memscan.S: Optimized memscan for Sparc64.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1998 David S. Miller (davem@dm.cobaltmicro.com)
+ * Copyright (C) 1998 David S. Miller (davem@redhat.com)
  */
 
 #define HI_MAGIC	0x8080808080808080
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/arch/sparc64/math-emu/sfp-machine.h linux.15p9/arch/sparc64/math-emu/sfp-machine.h
--- linux.vanilla/arch/sparc64/math-emu/sfp-machine.h	Tue Jan  4 21:18:43 2000
+++ linux.15p9/arch/sparc64/math-emu/sfp-machine.h	Fri Jan 14 15:56:16 2000
@@ -37,7 +37,7 @@
   _FP_MUL_MEAT_2_wide_3mul(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
 
 #define _FP_DIV_MEAT_S(R,X,Y)	_FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm)
-#define _FP_DIV_MEAT_D(R,X,Y)	_FP_DIV_MEAT_1_udiv(D,R,X,Y)
+#define _FP_DIV_MEAT_D(R,X,Y)	_FP_DIV_MEAT_1_udiv_norm(D,R,X,Y)
 #define _FP_DIV_MEAT_Q(R,X,Y)	_FP_DIV_MEAT_2_udiv(Q,R,X,Y)
 
 #define _FP_NANFRAC_S		((_FP_QNANBIT_S << 1) - 1)
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/block/Config.in linux.15p9/drivers/block/Config.in
--- linux.vanilla/drivers/block/Config.in	Tue Jan  4 21:18:44 2000
+++ linux.15p9/drivers/block/Config.in	Mon Feb  7 12:19:10 2000
@@ -44,6 +44,7 @@
             bool '     NS87415 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_NS87415
             bool '     VIA82C586 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_VIA82C586
             bool '     CMD646 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_CMD646
+            bool '     Cyrix CS5530 MediaGX chipset support' CONFIG_BLK_DEV_CS5530 
           fi
         fi
       fi
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/block/DAC960.c linux.15p9/drivers/block/DAC960.c
--- linux.vanilla/drivers/block/DAC960.c	Sat Aug 28 20:00:54 1999
+++ linux.15p9/drivers/block/DAC960.c	Sun Jan 23 08:01:00 2000
@@ -19,8 +19,8 @@
 */
 
 
-#define DAC960_DriverVersion			"2.2.4"
-#define DAC960_DriverDate			"23 August 1999"
+#define DAC960_DriverVersion			"2.2.5"
+#define DAC960_DriverDate			"23 January 2000"
 
 
 #include <linux/version.h>
@@ -120,7 +120,7 @@
   DAC960_Announce("***** DAC960 RAID Driver Version "
 		  DAC960_DriverVersion " of "
 		  DAC960_DriverDate " *****\n", Controller);
-  DAC960_Announce("Copyright 1998-1999 by Leonard N. Zubkoff "
+  DAC960_Announce("Copyright 1998-2000 by Leonard N. Zubkoff "
 		  "<lnz@dandelion.com>\n", Controller);
 }
 
@@ -194,6 +194,23 @@
 
 
 /*
+  DAC960_WaitForCommand waits for a wake_up on Controller's Command Wait Queue.
+*/
+
+static void DAC960_WaitForCommand(DAC960_Controller_T *Controller)
+{
+  WaitQueue_T WaitQueueEntry = { current, NULL };
+  add_wait_queue(&Controller->CommandWaitQueue, &WaitQueueEntry);
+  current->state = TASK_UNINTERRUPTIBLE;
+  spin_unlock(&io_request_lock);
+  schedule();
+  current->state = TASK_RUNNING;
+  remove_wait_queue(&Controller->CommandWaitQueue, &WaitQueueEntry);
+  spin_lock_irq(&io_request_lock);
+}
+
+
+/*
   DAC960_QueueCommand queues Command.
 */
 
@@ -317,6 +334,62 @@
 
 
 /*
+  DAC960_ReportErrorStatus reports Controller BIOS Messages passed through
+  the Error Status Register when the driver performs the BIOS handshaking.
+  It returns true for fatal errors and false otherwise.
+*/
+
+static boolean DAC960_ReportErrorStatus(DAC960_Controller_T *Controller,
+					unsigned char ErrorStatus,
+					unsigned char Parameter0,
+					unsigned char Parameter1)
+{
+  switch (ErrorStatus)
+    {
+    case 0x00:
+      DAC960_Notice("Physical Drive %d:%d Not Responding\n",
+		    Controller, Parameter1, Parameter0);
+      break;
+    case 0x08:
+      if (Controller->DriveSpinUpMessageDisplayed) break;
+      DAC960_Notice("Spinning Up Drives\n", Controller);
+      Controller->DriveSpinUpMessageDisplayed = true;
+      break;
+    case 0x30:
+      DAC960_Notice("Configuration Checksum Error\n", Controller);
+      break;
+    case 0x60:
+      DAC960_Notice("Mirror Race Recovery Failed\n", Controller);
+      break;
+    case 0x70:
+      DAC960_Notice("Mirror Race Recovery In Progress\n", Controller);
+      break;
+    case 0x90:
+      DAC960_Notice("Physical Drive %d:%d COD Mismatch\n",
+		    Controller, Parameter1, Parameter0);
+      break;
+    case 0xA0:
+      DAC960_Notice("Logical Drive Installation Aborted\n", Controller);
+      break;
+    case 0xB0:
+      DAC960_Notice("Mirror Race On A Critical Logical Drive\n", Controller);
+      break;
+    case 0xD0:
+      DAC960_Notice("New Controller Configuration Found\n", Controller);
+      break;
+    case 0xF0:
+      DAC960_Error("Fatal Memory Parity Error for Controller at\n", Controller);
+      return true;
+    default:
+      DAC960_Error("Unknown Initialization Error %02X for Controller at\n",
+		   Controller, ErrorStatus);
+      return true;
+    }
+  return false;
+}
+
+
+/*
   DAC960_EnableMemoryMailboxInterface enables the Memory Mailbox Interface.
 */
 
@@ -382,7 +455,7 @@
       case DAC960_V5_Controller:
 	while (--TimeoutCounter >= 0)
 	  {
-	    if (DAC960_V5_HardwareMailboxEmptyP(ControllerBaseAddress))
+	    if (!DAC960_V5_HardwareMailboxFullP(ControllerBaseAddress))
 	      break;
 	    udelay(10);
 	  }
@@ -474,11 +547,13 @@
       unsigned char DeviceFunction = PCI_Device->devfn;
       unsigned char Device = DeviceFunction >> 3;
       unsigned char Function = DeviceFunction & 0x7;
+      unsigned char ErrorStatus, Parameter0, Parameter1;
       unsigned int IRQ_Channel = PCI_Device->irq;
       unsigned long BaseAddress0 = PCI_Device->base_address[0];
       unsigned long BaseAddress1 = PCI_Device->base_address[1];
       unsigned short SubsystemVendorID, SubsystemDeviceID;
       int CommandIdentifier;
+      void *BaseAddress;
       pci_read_config_word(PCI_Device, PCI_SUBSYSTEM_VENDOR_ID,
 			   &SubsystemVendorID);
       pci_read_config_word(PCI_Device, PCI_SUBSYSTEM_ID,
@@ -524,24 +599,6 @@
       Controller->Function = Function;
       sprintf(Controller->ControllerName, "c%d", Controller->ControllerNumber);
       /*
-	Acquire shared access to the IRQ Channel.
-      */
-      if (IRQ_Channel == 0)
-	{
-	  DAC960_Error("IRQ Channel %d illegal for Controller at\n",
-		       Controller, IRQ_Channel);
-	  goto Failure;
-	}
-      strcpy(Controller->FullModelName, "DAC960");
-      if (request_irq(IRQ_Channel, DAC960_InterruptHandler,
-		      SA_SHIRQ, Controller->FullModelName, Controller) < 0)
-	{
-	  DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n",
-		       Controller, IRQ_Channel);
-	  goto Failure;
-	}
-      Controller->IRQ_Channel = IRQ_Channel;
-      /*
 	Map the Controller Register Window.
       */
       if (MemoryWindowSize < PAGE_SIZE)
@@ -556,34 +613,87 @@
 		       "Controller at\n", Controller);
 	  goto Failure;
 	}
+      BaseAddress = Controller->BaseAddress;
       switch (ControllerType)
 	{
 	case DAC960_V5_Controller:
-	  DAC960_V5_DisableInterrupts(Controller->BaseAddress);
+	  DAC960_V5_DisableInterrupts(BaseAddress);
+	  DAC960_V5_AcknowledgeHardwareMailboxStatus(BaseAddress);
+	  udelay(1000);
+	  while (DAC960_V5_InitializationInProgressP(BaseAddress))
+	    {
+	      if (DAC960_V5_ReadErrorStatus(BaseAddress, &ErrorStatus,
+					    &Parameter0, &Parameter1) &&
+		  DAC960_ReportErrorStatus(Controller, ErrorStatus,
+					   Parameter0, Parameter1))
+		goto Failure;
+	      udelay(10);
+	    }
 	  if (!DAC960_EnableMemoryMailboxInterface(Controller))
 	    {
 	      DAC960_Error("Unable to Enable Memory Mailbox Interface "
 			   "for Controller at\n", Controller);
 	      goto Failure;
 	    }
-	  DAC960_V5_EnableInterrupts(Controller->BaseAddress);
+	  DAC960_V5_EnableInterrupts(BaseAddress);
 	  break;
 	case DAC960_V4_Controller:
-	  DAC960_V4_DisableInterrupts(Controller->BaseAddress);
+	  DAC960_V4_DisableInterrupts(BaseAddress);
+	  DAC960_V4_AcknowledgeHardwareMailboxStatus(BaseAddress);
+	  udelay(1000);
+	  while (DAC960_V4_InitializationInProgressP(BaseAddress))
+	    {
+	      if (DAC960_V4_ReadErrorStatus(BaseAddress, &ErrorStatus,
+					    &Parameter0, &Parameter1) &&
+		  DAC960_ReportErrorStatus(Controller, ErrorStatus,
+					   Parameter0, Parameter1))
+		goto Failure;
+	      udelay(10);
+	    }
 	  if (!DAC960_EnableMemoryMailboxInterface(Controller))
 	    {
 	      DAC960_Error("Unable to Enable Memory Mailbox Interface "
 			   "for Controller at\n", Controller);
 	      goto Failure;
 	    }
-	  DAC960_V4_EnableInterrupts(Controller->BaseAddress);
+	  DAC960_V4_EnableInterrupts(BaseAddress);
 	  break;
 	case DAC960_V3_Controller:
 	  request_region(Controller->IO_Address, 0x80,
 			 Controller->FullModelName);
-	  DAC960_V3_EnableInterrupts(Controller->BaseAddress);
+	  DAC960_V3_DisableInterrupts(BaseAddress);
+	  DAC960_V3_AcknowledgeStatus(BaseAddress);
+	  udelay(1000);
+	  while (DAC960_V3_InitializationInProgressP(BaseAddress))
+	    {
+	      if (DAC960_V3_ReadErrorStatus(BaseAddress, &ErrorStatus,
+					    &Parameter0, &Parameter1) &&
+		  DAC960_ReportErrorStatus(Controller, ErrorStatus,
+					   Parameter0, Parameter1))
+		goto Failure;
+	      udelay(10);
+	    }
+	  DAC960_V3_EnableInterrupts(BaseAddress);
 	  break;
 	}
+      /*
+	Acquire shared access to the IRQ Channel.
+      */
+      if (IRQ_Channel == 0)
+	{
+	  DAC960_Error("IRQ Channel %d illegal for Controller at\n",
+		       Controller, IRQ_Channel);
+	  goto Failure;
+	}
+      strcpy(Controller->FullModelName, "DAC960");
+      if (request_irq(IRQ_Channel, DAC960_InterruptHandler,
+		      SA_SHIRQ, Controller->FullModelName, Controller) < 0)
+	{
+	  DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n",
+		       Controller, IRQ_Channel);
+	  goto Failure;
+	}
+      Controller->IRQ_Channel = IRQ_Channel;
       DAC960_ActiveControllerCount++;
       for (CommandIdentifier = 0;
 	   CommandIdentifier < DAC960_MaxChannels;
@@ -604,11 +714,11 @@
 			"0x%X PCI Address 0x%X\n", Controller,
 			Bus, Device, Function, IO_Address, PCI_Address);
       if (Controller == NULL) break;
-      if (Controller->IRQ_Channel > 0)
-	free_irq(IRQ_Channel, Controller);
       if (Controller->MemoryMappedAddress != NULL)
 	iounmap(Controller->MemoryMappedAddress);
       DAC960_Controllers[Controller->ControllerNumber] = NULL;
+      if (Controller->IRQ_Channel > 0)
+	free_irq(IRQ_Channel, Controller);
     Ignore:
       kfree(Controller);
     }
@@ -1282,9 +1392,7 @@
       Command = DAC960_AllocateCommand(Controller);
       if (Command != NULL) break;
       if (!WaitForCommand) return false;
-      spin_unlock(&io_request_lock);
-      sleep_on(&Controller->CommandWaitQueue);
-      spin_lock_irq(&io_request_lock);
+      DAC960_WaitForCommand(Controller);
     }
   DAC960_ClearCommand(Command);
   if (Request->cmd == READ)
@@ -1836,6 +1944,20 @@
 	      }
 	  else if (NewEnquiry->RebuildFlag == DAC960_BackgroundCheckInProgress)
 	    Controller->NeedConsistencyCheckProgress = true;
+	  if (CommandType != DAC960_MonitoringCommand &&
+	      Controller->RebuildFlagPending)
+	    {
+	      DAC960_Enquiry_T *Enquiry = (DAC960_Enquiry_T *)
+		Bus_to_Virtual(Command->CommandMailbox.Type3.BusAddress);
+	      Enquiry->RebuildFlag = Controller->PendingRebuildFlag;
+	      Controller->RebuildFlagPending = false;
+	    }
+	  else if (CommandType == DAC960_MonitoringCommand &&
+		   NewEnquiry->RebuildFlag > DAC960_BackgroundCheckInProgress)
+	    {
+	      Controller->PendingRebuildFlag = NewEnquiry->RebuildFlag;
+	      Controller->RebuildFlagPending = true;
+	    }
 	}
       else if (CommandOpcode == DAC960_PerformEventLogOperation)
 	{
@@ -2019,6 +2141,9 @@
 	    Controller->RebuildProgress.LogicalDriveSize;
 	  unsigned int BlocksCompleted =
 	    LogicalDriveSize - Controller->RebuildProgress.RemainingBlocks;
+	  if (CommandStatus == DAC960_NoRebuildOrCheckInProgress &&
+	      Controller->LastRebuildStatus == DAC960_NormalCompletion)
+	    CommandStatus = DAC960_RebuildSuccessful;
 	  switch (CommandStatus)
 	    {
 	    case DAC960_NormalCompletion:
@@ -2046,13 +2171,28 @@
 			      "Failure of Drive Being Rebuilt\n", Controller);
 	      break;
 	    case DAC960_NoRebuildOrCheckInProgress:
-	      if (Controller->LastRebuildStatus != DAC960_NormalCompletion)
-		break;
+	      break;
 	    case DAC960_RebuildSuccessful:
 	      DAC960_Progress("Rebuild Completed Successfully\n", Controller);
 	      break;
+	    case DAC960_RebuildSuccessfullyTerminated:
+	      DAC960_Progress("Rebuild Successfully Terminated\n", Controller);
+	      break;
 	    }
 	  Controller->LastRebuildStatus = CommandStatus;
+	  if (CommandType != DAC960_MonitoringCommand &&
+	      Controller->RebuildStatusPending)
+	    {
+	      Command->CommandStatus = Controller->PendingRebuildStatus;
+	      Controller->RebuildStatusPending = false;
+	    }
+	  else if (CommandType == DAC960_MonitoringCommand &&
+		   CommandStatus != DAC960_NormalCompletion &&
+		   CommandStatus != DAC960_NoRebuildOrCheckInProgress)
+	    {
+	      Controller->PendingRebuildStatus = CommandStatus;
+	      Controller->RebuildStatusPending = true;
+	    }
 	}
       else if (CommandOpcode == DAC960_RebuildStat)
 	{
@@ -2267,7 +2407,7 @@
   if (CommandType == DAC960_QueuedCommand)
     {
       DAC960_KernelCommand_T *KernelCommand = Command->KernelCommand;
-      KernelCommand->CommandStatus = CommandStatus;
+      KernelCommand->CommandStatus = Command->CommandStatus;
       Command->KernelCommand = NULL;
       if (CommandOpcode == DAC960_DCDB)
 	Controller->DirectCommandActive[KernelCommand->DCDB->Channel]
@@ -2288,9 +2428,12 @@
       return;
     }
   /*
-    Deallocate the Command, and wake up any processes waiting on a free Command.
+    Deallocate the Command.
   */
   DAC960_DeallocateCommand(Command);
+  /*
+    Wake up any processes waiting on a free Command.
+  */
   wake_up(&Controller->CommandWaitQueue);
 }
 
@@ -2696,19 +2839,14 @@
 	  }
 	if (CommandOpcode == DAC960_DCDB)
 	  {
-	    while (true)
-	      {
-		DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
-		if (!Controller->DirectCommandActive[DCDB.Channel]
-						    [DCDB.TargetID])
-		  Command = DAC960_AllocateCommand(Controller);
-		if (Command != NULL)
-		  Controller->DirectCommandActive[DCDB.Channel]
-						 [DCDB.TargetID] = true;
-		DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
-		if (Command != NULL) break;
-		sleep_on(&Controller->CommandWaitQueue);
-	      }
+	    DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+	    while (Controller->DirectCommandActive[DCDB.Channel]
+						  [DCDB.TargetID] ||
+		   (Command = DAC960_AllocateCommand(Controller)) == NULL)
+	      DAC960_WaitForCommand(Controller);
+	    Controller->DirectCommandActive[DCDB.Channel]
+					   [DCDB.TargetID] = true;
+	    DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
 	    DAC960_ClearCommand(Command);
 	    Command->CommandType = DAC960_ImmediateCommand;
 	    memcpy(&Command->CommandMailbox, &UserCommand.CommandMailbox,
@@ -2718,14 +2856,10 @@
 	  }
 	else
 	  {
-	    while (true)
-	      {
-		DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
-		Command = DAC960_AllocateCommand(Controller);
-		DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
-		if (Command != NULL) break;
-		sleep_on(&Controller->CommandWaitQueue);
-	      }
+	    DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+	    while ((Command = DAC960_AllocateCommand(Controller)) == NULL)
+	      DAC960_WaitForCommand(Controller);
+	    DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
 	    DAC960_ClearCommand(Command);
 	    Command->CommandType = DAC960_ImmediateCommand;
 	    memcpy(&Command->CommandMailbox, &UserCommand.CommandMailbox,
@@ -3127,14 +3261,10 @@
   DAC960_CommandMailbox_T *CommandMailbox;
   ProcessorFlags_T ProcessorFlags;
   unsigned char Channel, TargetID, LogicalDriveNumber;
-  while (true)
-    {
-      DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
-      Command = DAC960_AllocateCommand(Controller);
-      DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
-      if (Command != NULL) break;
-      sleep_on(&Controller->CommandWaitQueue);
-    }
+  DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+  while ((Command = DAC960_AllocateCommand(Controller)) == NULL)
+    DAC960_WaitForCommand(Controller);
+  DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
   Controller->UserStatusLength = 0;
   DAC960_ClearCommand(Command);
   Command->CommandType = DAC960_ImmediateCommand;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/block/DAC960.h linux.15p9/drivers/block/DAC960.h
--- linux.vanilla/drivers/block/DAC960.h	Sat Aug 28 20:00:54 1999
+++ linux.15p9/drivers/block/DAC960.h	Sun Jan 23 08:01:00 2000
@@ -55,17 +55,17 @@
 
 
 /*
-  Define a 32 bit I/O Address data type.
+  Define a 32/64 bit I/O Address data type.
 */
 
-typedef unsigned int DAC960_IO_Address_T;
+typedef unsigned long DAC960_IO_Address_T;
 
 
 /*
-  Define a 32 bit PCI Bus Address data type.
+  Define a 32/64 bit PCI Bus Address data type.
 */
 
-typedef unsigned int DAC960_PCI_Address_T;
+typedef unsigned long DAC960_PCI_Address_T;
 
 
 /*
@@ -196,6 +196,7 @@
 #define DAC960_RebuildFailed_BadBlocksOnOther	0x0003	/* Consistency */
 #define DAC960_RebuildFailed_NewDriveFailed	0x0004	/* Consistency */
 #define DAC960_RebuildSuccessful		0x0100	/* Consistency */
+#define DAC960_RebuildSuccessfullyTerminated	0x0107	/* Consistency */
 #define DAC960_AddCapacityInProgress		0x0004	/* Consistency */
 #define DAC960_AddCapacityFailedOrSuspended	0x00F4	/* Consistency */
 #define DAC960_Config2ChecksumError		0x0002	/* Configuration */
@@ -513,7 +514,7 @@
   unsigned char SynchronousMultiplier;			/* Byte 4 */
   unsigned char SynchronousOffset:5;			/* Byte 5 Bits 0-4 */
   unsigned char :3;					/* Byte 5 Bits 5-7 */
-  unsigned long DiskSize __attribute__ ((packed));	/* Bytes 6-9 */
+  unsigned int DiskSize __attribute__ ((packed));	/* Bytes 6-9 */
 }
 DAC960_DeviceState_T;
 
@@ -1212,6 +1213,7 @@
   unsigned char LogicalDriveCount;
   unsigned char GeometryTranslationHeads;
   unsigned char GeometryTranslationSectors;
+  unsigned char PendingRebuildFlag;
   unsigned short ControllerQueueDepth;
   unsigned short DriverQueueDepth;
   unsigned short MaxBlocksPerCommand;
@@ -1247,6 +1249,9 @@
   boolean NeedRebuildProgress;
   boolean NeedConsistencyCheckProgress;
   boolean EphemeralProgressMessage;
+  boolean RebuildFlagPending;
+  boolean RebuildStatusPending;
+  boolean DriveSpinUpMessageDisplayed;
   Timer_T MonitoringTimer;
   GenericDiskInfo_T GenericDiskInfo;
   DAC960_Command_T *FreeCommands;
@@ -1269,6 +1274,7 @@
   DAC960_EventLogEntry_T EventLogEntry;
   DAC960_RebuildProgress_T RebuildProgress;
   DAC960_CommandStatus_T LastRebuildStatus;
+  DAC960_CommandStatus_T PendingRebuildStatus;
   DAC960_LogicalDriveInformation_T
     LogicalDriveInformation[2][DAC960_MaxLogicalDrives];
   DAC960_LogicalDriveState_T LogicalDriveInitialState[DAC960_MaxLogicalDrives];
@@ -1393,7 +1399,8 @@
   DAC960_V5_MailboxRegister11Offset =		0x5B,
   DAC960_V5_MailboxRegister12Offset =		0x5C,
   DAC960_V5_StatusCommandIdentifierRegOffset =	0x5D,
-  DAC960_V5_StatusRegisterOffset =		0x5E
+  DAC960_V5_StatusRegisterOffset =		0x5E,
+  DAC960_V5_ErrorStatusRegisterOffset =		0x63
 }
 DAC960_V5_RegisterOffsets_T;
 
@@ -1415,7 +1422,8 @@
   } Write;
   struct {
     boolean HardwareMailboxEmpty:1;			/* Bit 0 */
-    unsigned char :7;					/* Bits 1-7 */
+    boolean InitializationNotInProgress:1;		/* Bit 1 */
+    unsigned char :6;					/* Bits 2-7 */
   } Read;
 }
 DAC960_V5_InboundDoorBellRegister_T;
@@ -1459,6 +1467,22 @@
 
 
 /*
+  Define the structure of the DAC960 V5 Error Status Register.
+*/
+
+typedef union DAC960_V5_ErrorStatusRegister
+{
+  unsigned char All;
+  struct {
+    unsigned int :2;					/* Bits 0-1 */
+    boolean ErrorStatusPending:1;			/* Bit 2 */
+    unsigned int :5;					/* Bits 3-7 */
+  } Bits;
+}
+DAC960_V5_ErrorStatusRegister_T;
+
+
+/*
   Define inline functions to provide an abstraction for reading and writing the
   DAC960 V5 Controller Interface Registers.
 */
@@ -1514,12 +1538,21 @@
 }
 
 static inline
-boolean DAC960_V5_HardwareMailboxEmptyP(void *ControllerBaseAddress)
+boolean DAC960_V5_HardwareMailboxFullP(void *ControllerBaseAddress)
 {
   DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
     readb(ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
-  return InboundDoorBellRegister.Read.HardwareMailboxEmpty;
+  return !InboundDoorBellRegister.Read.HardwareMailboxEmpty;
+}
+
+static inline
+boolean DAC960_V5_InitializationInProgressP(void *ControllerBaseAddress)
+{
+  DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All =
+    readb(ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
+  return !InboundDoorBellRegister.Read.InitializationNotInProgress;
 }
 
 static inline
@@ -1575,7 +1608,7 @@
 void DAC960_V5_EnableInterrupts(void *ControllerBaseAddress)
 {
   DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister;
-  InterruptMaskRegister.All = 0;
+  InterruptMaskRegister.All = 0xFF;
   InterruptMaskRegister.Bits.DisableInterrupts = false;
   writeb(InterruptMaskRegister.All,
 	 ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset);
@@ -1585,7 +1618,7 @@
 void DAC960_V5_DisableInterrupts(void *ControllerBaseAddress)
 {
   DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister;
-  InterruptMaskRegister.All = 0;
+  InterruptMaskRegister.All = 0xFF;
   InterruptMaskRegister.Bits.DisableInterrupts = true;
   writeb(InterruptMaskRegister.All,
 	 ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset);
@@ -1607,7 +1640,9 @@
   NextCommandMailbox->Words[1] = CommandMailbox->Words[1];
   NextCommandMailbox->Words[2] = CommandMailbox->Words[2];
   NextCommandMailbox->Words[3] = CommandMailbox->Words[3];
+  wmb();
   NextCommandMailbox->Words[0] = CommandMailbox->Words[0];
+  mb();
 }
 
 static inline
@@ -1637,6 +1672,26 @@
   return readw(ControllerBaseAddress + DAC960_V5_StatusRegisterOffset);
 }
 
+static inline boolean
+DAC960_V5_ReadErrorStatus(void *ControllerBaseAddress,
+			  unsigned char *ErrorStatus,
+			  unsigned char *Parameter0,
+			  unsigned char *Parameter1)
+{
+  DAC960_V5_ErrorStatusRegister_T ErrorStatusRegister;
+  ErrorStatusRegister.All =
+    readb(ControllerBaseAddress + DAC960_V5_ErrorStatusRegisterOffset);
+  if (!ErrorStatusRegister.Bits.ErrorStatusPending) return false;
+  ErrorStatusRegister.Bits.ErrorStatusPending = false;
+  *ErrorStatus = ErrorStatusRegister.All;
+  *Parameter0 =
+    readb(ControllerBaseAddress + DAC960_V5_CommandOpcodeRegisterOffset);
+  *Parameter1 =
+    readb(ControllerBaseAddress + DAC960_V5_CommandIdentifierRegisterOffset);
+  writeb(0xFF, ControllerBaseAddress + DAC960_V5_ErrorStatusRegisterOffset);
+  return true;
+}
+
 static inline
 void DAC960_V5_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller)
 {
@@ -1695,7 +1750,8 @@
   DAC960_V4_MailboxRegister11Offset =		0x100B,
   DAC960_V4_MailboxRegister12Offset =		0x100C,
   DAC960_V4_StatusCommandIdentifierRegOffset =	0x1018,
-  DAC960_V4_StatusRegisterOffset =		0x101A
+  DAC960_V4_StatusRegisterOffset =		0x101A,
+  DAC960_V4_ErrorStatusRegisterOffset =		0x103F
 }
 DAC960_V4_RegisterOffsets_T;
 
@@ -1717,7 +1773,8 @@
   } Write;
   struct {
     boolean HardwareMailboxFull:1;			/* Bit 0 */
-    unsigned int :31;					/* Bits 1-31 */
+    boolean InitializationInProgress:1;			/* Bit 1 */
+    unsigned int :30;					/* Bits 2-31 */
   } Read;
 }
 DAC960_V4_InboundDoorBellRegister_T;
@@ -1762,6 +1819,22 @@
 
 
 /*
+  Define the structure of the DAC960 V4 Error Status Register.
+*/
+
+typedef union DAC960_V4_ErrorStatusRegister
+{
+  unsigned char All;
+  struct {
+    unsigned int :2;					/* Bits 0-1 */
+    boolean ErrorStatusPending:1;			/* Bit 2 */
+    unsigned int :5;					/* Bits 3-7 */
+  } Bits;
+}
+DAC960_V4_ErrorStatusRegister_T;
+
+
+/*
   Define inline functions to provide an abstraction for reading and writing the
   DAC960 V4 Controller Interface Registers.
 */
@@ -1826,6 +1899,15 @@
 }
 
 static inline
+boolean DAC960_V4_InitializationInProgressP(void *ControllerBaseAddress)
+{
+  DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All =
+    readl(ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset);
+  return InboundDoorBellRegister.Read.InitializationInProgress;
+}
+
+static inline
 void DAC960_V4_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
 {
   DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister;
@@ -1914,7 +1996,9 @@
   NextCommandMailbox->Words[1] = CommandMailbox->Words[1];
   NextCommandMailbox->Words[2] = CommandMailbox->Words[2];
   NextCommandMailbox->Words[3] = CommandMailbox->Words[3];
+  wmb();
   NextCommandMailbox->Words[0] = CommandMailbox->Words[0];
+  mb();
 }
 
 static inline
@@ -1944,11 +2028,31 @@
   return readw(ControllerBaseAddress + DAC960_V4_StatusRegisterOffset);
 }
 
+static inline boolean
+DAC960_V4_ReadErrorStatus(void *ControllerBaseAddress,
+			  unsigned char *ErrorStatus,
+			  unsigned char *Parameter0,
+			  unsigned char *Parameter1)
+{
+  DAC960_V4_ErrorStatusRegister_T ErrorStatusRegister;
+  ErrorStatusRegister.All =
+    readb(ControllerBaseAddress + DAC960_V4_ErrorStatusRegisterOffset);
+  if (!ErrorStatusRegister.Bits.ErrorStatusPending) return false;
+  ErrorStatusRegister.Bits.ErrorStatusPending = false;
+  *ErrorStatus = ErrorStatusRegister.All;
+  *Parameter0 =
+    readb(ControllerBaseAddress + DAC960_V4_CommandOpcodeRegisterOffset);
+  *Parameter1 =
+    readb(ControllerBaseAddress + DAC960_V4_CommandIdentifierRegisterOffset);
+  writeb(0, ControllerBaseAddress + DAC960_V4_ErrorStatusRegisterOffset);
+  return true;
+}
+
 static inline
 void DAC960_V4_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller)
 {
   void *ControllerBaseAddress = Controller->BaseAddress;
-  writel(0xAABBFFFF,
+  writel(0x743C485E,
 	 ControllerBaseAddress + DAC960_V4_CommandOpcodeRegisterOffset);
   writel((unsigned long) Controller->FirstCommandMailbox,
 	 ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset);
@@ -1966,7 +2070,7 @@
 {
   void *ControllerBaseAddress = Controller->BaseAddress;
   if (readl(ControllerBaseAddress
-	    + DAC960_V4_CommandOpcodeRegisterOffset) != 0xAABBFFFF)
+	    + DAC960_V4_CommandOpcodeRegisterOffset) != 0x743C485E)
     return;
   *MemoryMailboxAddress =
     (void *) readl(ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset);
@@ -2000,6 +2104,7 @@
   DAC960_V3_MailboxRegister12Offset =		0x0C,
   DAC960_V3_StatusCommandIdentifierRegOffset =	0x0D,
   DAC960_V3_StatusRegisterOffset =		0x0E,
+  DAC960_V3_ErrorStatusRegisterOffset =		0x3F,
   DAC960_V3_InboundDoorBellRegisterOffset =	0x40,
   DAC960_V3_OutboundDoorBellRegisterOffset =	0x41,
   DAC960_V3_InterruptEnableRegisterOffset =	0x43
@@ -2023,7 +2128,8 @@
   } Write;
   struct {
     boolean MailboxFull:1;				/* Bit 0 */
-    unsigned char :7;					/* Bits 1-7 */
+    boolean InitializationInProgress:1;			/* Bit 1 */
+    unsigned char :6;					/* Bits 2-7 */
   } Read;
 }
 DAC960_V3_InboundDoorBellRegister_T;
@@ -2064,6 +2170,22 @@
 
 
 /*
+  Define the structure of the DAC960 V3 Error Status Register.
+*/
+
+typedef union DAC960_V3_ErrorStatusRegister
+{
+  unsigned char All;
+  struct {
+    unsigned int :2;					/* Bits 0-1 */
+    boolean ErrorStatusPending:1;			/* Bit 2 */
+    unsigned int :5;					/* Bits 3-7 */
+  } Bits;
+}
+DAC960_V3_ErrorStatusRegister_T;
+
+
+/*
   Define inline functions to provide an abstraction for reading and writing the
   DAC960 V3 Controller Interface Registers.
 */
@@ -2118,6 +2240,15 @@
 }
 
 static inline
+boolean DAC960_V3_InitializationInProgressP(void *ControllerBaseAddress)
+{
+  DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All =
+    readb(ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset);
+  return InboundDoorBellRegister.Read.InitializationInProgress;
+}
+
+static inline
 void DAC960_V3_AcknowledgeInterrupt(void *ControllerBaseAddress)
 {
   DAC960_V3_OutboundDoorBellRegister_T OutboundDoorBellRegister;
@@ -2190,6 +2321,26 @@
 DAC960_V3_ReadStatusRegister(void *ControllerBaseAddress)
 {
   return readw(ControllerBaseAddress + DAC960_V3_StatusRegisterOffset);
+}
+
+static inline boolean
+DAC960_V3_ReadErrorStatus(void *ControllerBaseAddress,
+			  unsigned char *ErrorStatus,
+			  unsigned char *Parameter0,
+			  unsigned char *Parameter1)
+{
+  DAC960_V3_ErrorStatusRegister_T ErrorStatusRegister;
+  ErrorStatusRegister.All =
+    readb(ControllerBaseAddress + DAC960_V3_ErrorStatusRegisterOffset);
+  if (!ErrorStatusRegister.Bits.ErrorStatusPending) return false;
+  ErrorStatusRegister.Bits.ErrorStatusPending = false;
+  *ErrorStatus = ErrorStatusRegister.All;
+  *Parameter0 =
+    readb(ControllerBaseAddress + DAC960_V3_CommandOpcodeRegisterOffset);
+  *Parameter1 =
+    readb(ControllerBaseAddress + DAC960_V3_CommandIdentifierRegisterOffset);
+  writeb(0, ControllerBaseAddress + DAC960_V3_ErrorStatusRegisterOffset);
+  return true;
 }
 
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/block/Makefile linux.15p9/drivers/block/Makefile
--- linux.vanilla/drivers/block/Makefile	Sat Aug 14 02:27:16 1999
+++ linux.15p9/drivers/block/Makefile	Mon Feb  7 12:19:10 2000
@@ -162,6 +162,10 @@
 IDE_OBJS += cmd646.o
 endif
 
+ifeq ($(CONFIG_BLK_DEV_CS5530),y)
+IDE_OBJS += cs5530.o
+endif     
+
 ifeq ($(CONFIG_BLK_DEV_SL82C105),y)
 IDE_OBJS += sl82c105.o
 endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/block/cmd646.c linux.15p9/drivers/block/cmd646.c
--- linux.vanilla/drivers/block/cmd646.c	Tue Mar 16 00:11:29 1999
+++ linux.15p9/drivers/block/cmd646.c	Mon Feb  7 12:29:22 2000
@@ -1,4 +1,4 @@
-/* $Id: cmd646.c,v 1.11 1998/12/13 08:36:54 davem Exp $
+/* $Id: cmd646.c,v 1.11.2.1 2000/01/31 05:02:39 davem Exp $
  * cmd646.c: Enable interrupts at initialization time on Ultra/PCI machines.
  *           Note, this driver is not used at all on other systems because
  *           there the "BIOS" has done all of the following already.
@@ -6,7 +6,7 @@
  *           on the 646U2 and not on the 646U.
  *
  * Copyright (C) 1998       Eddie C. Dost  (ecd@skynet.be)
- * Copyright (C) 1998       David S. Miller (davem@dm.cobaltmicro.com)
+ * Copyright (C) 1998       David S. Miller (davem@redhat.com)
  */
 
 #include <linux/types.h>
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/block/cpqarray.c linux.15p9/drivers/block/cpqarray.c
--- linux.vanilla/drivers/block/cpqarray.c	Sat Aug 14 02:27:16 1999
+++ linux.15p9/drivers/block/cpqarray.c	Mon Feb  7 12:23:16 2000
@@ -41,8 +41,8 @@
 
 #define SMART2_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
 
-#define DRIVER_NAME "Compaq SMART2 Driver (v 1.0.5)"
-#define DRIVER_VERSION SMART2_DRIVER_VERSION(1,0,5)
+#define DRIVER_NAME "Compaq SMART2 Driver (v 1.0.6)"
+#define DRIVER_VERSION SMART2_DRIVER_VERSION(1,0,6)
 #define MAJOR_NR COMPAQ_SMART2_MAJOR
 #include <linux/blk.h>
 #include <linux/blkdev.h>
@@ -84,6 +84,7 @@
 	{ 0x40400E11, "Integrated Array",	&smart4_access },
 	{ 0x40500E11, "Smart Array 4200",	&smart4_access },
 	{ 0x40510E11, "Smart Array 4250ES",	&smart4_access },
+	{ 0x40580E11, "Smart Array 431",	&smart4_access },
 };
 
 static struct hd_struct * ida;
@@ -1223,7 +1224,7 @@
 			return(error);
 		}
 		copy_from_user(p, (void*)io->sg[0].addr, io->sg[0].size);
-		c->req.bp = virt_to_bus(&(io->c));
+		c->req.hdr.blk = virt_to_bus(&(io->c));
 		c->req.sg[0].size = io->sg[0].size;
 		c->req.sg[0].addr = virt_to_bus(p);
 		c->req.hdr.sg_cnt = 1;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/block/cpqarray.h linux.15p9/drivers/block/cpqarray.h
--- linux.vanilla/drivers/block/cpqarray.h	Sat Aug 14 02:27:16 1999
+++ linux.15p9/drivers/block/cpqarray.h	Mon Feb  7 13:48:56 2000
@@ -30,7 +30,6 @@
 #include <linux/locks.h>
 #include <linux/malloc.h>
 #include <linux/proc_fs.h>
-#include <linux/md.h>
 #include <linux/timer.h>
 #endif
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/block/cs5530.c linux.15p9/drivers/block/cs5530.c
--- linux.vanilla/drivers/block/cs5530.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/block/cs5530.c	Mon Feb  7 12:25:34 2000
@@ -0,0 +1,467 @@
+/*
+ * linux/drivers/block/cs5530.c		Version 0.4	Feb 6, 2000
+ *
+ * Copyright (C) 2000			Mark Lord <mlord@pobox.com>
+ * May be copied or modified under the terms of the GNU General Public License
+ *
+ * Development of this chipset driver was funded
+ * by the nice folks at National Semiconductor.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#ifndef SETFEATURES_XFER
+	#define CS5530_2_2_KERNEL
+#endif
+
+#ifdef CS5530_2_2_KERNEL
+	#include "ide.h"
+	#define XFER_UDMA_6	0x46	/* 0100|0110 */
+	#define XFER_UDMA_5	0x45	/* 0100|0101 */
+	#define XFER_UDMA_4	0x44	/* 0100|0100 */
+	#define XFER_UDMA_3	0x43	/* 0100|0011 */
+	#define XFER_UDMA_2	0x42	/* 0100|0010 */
+	#define XFER_UDMA_1	0x41	/* 0100|0001 */
+	#define XFER_UDMA_0	0x40	/* 0100|0000 */
+	#define XFER_MW_DMA_2	0x22	/* 0010|0010 */
+	#define XFER_MW_DMA_1	0x21	/* 0010|0001 */
+	#define XFER_MW_DMA_0	0x20	/* 0010|0000 */
+	#define XFER_SW_DMA_2	0x12	/* 0001|0010 */
+	#define XFER_SW_DMA_1	0x11	/* 0001|0001 */
+	#define XFER_SW_DMA_0	0x10	/* 0001|0000 */
+	#define XFER_PIO_4	0x0C	/* 0000|1100 */
+	#define XFER_PIO_3	0x0B	/* 0000|1011 */
+	#define XFER_PIO_2	0x0A	/* 0000|1010 */
+	#define XFER_PIO_1	0x09	/* 0000|1001 */
+	#define XFER_PIO_0	0x08	/* 0000|1000 */
+	#define XFER_PIO_SLOW	0x00	/* 0000|0000 */
+	#define SETFEATURES_XFER 0x03	/* Set transfer mode */
+	#define pci_for_each_dev(dev) \
+        	for(dev = pci_devices; dev; dev=dev->next)
+#else
+	#include <linux/ide.h>
+#endif	/* CS5530_2_2_KERNEL */
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include "ide_modes.h"
+
+/*
+ * Return the mode name for a drive transfer mode value:
+ */
+static const char *strmode (byte mode)
+{
+	switch (mode) {
+		case XFER_UDMA_4:	return("UDMA4");
+		case XFER_UDMA_3:	return("UDMA3");
+		case XFER_UDMA_2:	return("UDMA2");
+		case XFER_UDMA_1:	return("UDMA1");
+		case XFER_UDMA_0:	return("UDMA0");
+		case XFER_MW_DMA_2:	return("MDMA2");
+		case XFER_MW_DMA_1:	return("MDMA1");
+		case XFER_MW_DMA_0:	return("MDMA0");
+		case XFER_SW_DMA_2:	return("SDMA2");
+		case XFER_SW_DMA_1:	return("SDMA1");
+		case XFER_SW_DMA_0:	return("SDMA0");
+		case XFER_PIO_4:	return("PIO4");
+		case XFER_PIO_3:	return("PIO3");
+		case XFER_PIO_2:	return("PIO2");
+		case XFER_PIO_1:	return("PIO1");
+		case XFER_PIO_0:	return("PIO0");
+		default:		return("???");
+	}
+}
+
+/*
+ * Set a new transfer mode at the drive
+ */
+int cs5530_set_xfer_mode (ide_drive_t *drive, byte mode)
+{
+	int		i, error = 1;
+	byte		stat;
+	ide_hwif_t	*hwif = HWIF(drive);
+
+	printk("%s: cs5530_set_xfer_mode(%s)\n", drive->name, strmode(mode));
+	/*
+	 * If this is a DMA mode setting, then turn off all DMA bits.
+	 * We will set one of them back on afterwards, if all goes well.
+	 *
+	 * Not sure why this is needed (it looks very silly),
+	 * but other IDE chipset drivers also do this fiddling.  ???? -ml
+ 	 */
+	switch (mode) {
+		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:
+			drive->id->dma_ultra &= ~0xFF00;
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+	}
+
+	/*
+	 * Select the drive, and issue the SETFEATURES command
+	 */
+	disable_irq(hwif->irq);
+	udelay(1);
+	SELECT_DRIVE(HWIF(drive), drive);
+	udelay(1);
+	if (IDE_CONTROL_REG)
+		OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG);
+	OUT_BYTE(mode, IDE_NSECTOR_REG);
+	OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG);
+	OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG);
+	udelay(1);	/* spec allows drive 400ns to assert "BUSY" */
+
+	/*
+	 * Wait for drive to become non-BUSY
+	 */
+	if ((stat = GET_STAT()) & BUSY_STAT) {
+		unsigned long flags, timeout;
+		__save_flags(flags);	/* local CPU only */
+		ide__sti();		/* local CPU only -- for jiffies */
+		timeout = jiffies + WAIT_CMD;
+		while ((stat = GET_STAT()) & BUSY_STAT) {
+			if (0 < (signed long)(jiffies - timeout))
+				break;
+		}
+		__restore_flags(flags); /* local CPU only */
+	}
+
+	/*
+	 * Allow status to settle, then read it again.
+	 * A few rare drives vastly violate the 400ns spec here,
+	 * so we'll wait up to 10usec for a "good" status
+	 * rather than expensively fail things immediately.
+	 */
+	for (i = 0; i < 10; i++) {
+		udelay(1);
+		if (OK_STAT((stat = GET_STAT()), DRIVE_READY, BUSY_STAT|DRQ_STAT|ERR_STAT)) {
+			error = 0;
+			break;
+		}
+	}
+	enable_irq(hwif->irq);
+
+	/*
+	 * Turn dma bit on if all is okay
+	 */
+	if (error) {
+		(void) ide_dump_status(drive, "cs5530_set_xfer_mode", stat);
+	} else {
+		switch (mode) {
+			case XFER_UDMA_4:   drive->id->dma_ultra |= 0x1010; break;
+			case XFER_UDMA_3:   drive->id->dma_ultra |= 0x0808; break;
+			case XFER_UDMA_2:   drive->id->dma_ultra |= 0x0404; break;
+			case XFER_UDMA_1:   drive->id->dma_ultra |= 0x0202; break;
+			case XFER_UDMA_0:   drive->id->dma_ultra |= 0x0101; break;
+			case XFER_MW_DMA_2: drive->id->dma_mword |= 0x0404; break;
+			case XFER_MW_DMA_1: drive->id->dma_mword |= 0x0202; break;
+			case XFER_MW_DMA_0: drive->id->dma_mword |= 0x0101; break;
+			case XFER_SW_DMA_2: drive->id->dma_1word |= 0x0404; break;
+			case XFER_SW_DMA_1: drive->id->dma_1word |= 0x0202; break;
+			case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break;
+		}
+	}
+	return error;
+}
+
+/*
+ * Here are the standard PIO mode 0-4 timings for each "format".
+ * Format-0 uses fast data reg timings, with slower command reg timings.
+ * Format-1 uses fast timings for all registers, but won't work with all drives.
+ */
+static unsigned int cs5530_pio_timings[2][5] =
+	{{0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010},
+	 {0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010}};
+
+/*
+ * After chip reset, the PIO timings are set to 0x0000e132, which is not valid.
+ */
+#define CS5530_BAD_PIO(timings) (((timings)&~0x80000000)==0x0000e132)
+#define CS5530_BASEREG(hwif)	(((hwif)->dma_base & ~0xf) + ((hwif)->channel ? 0x30 : 0x20))
+
+/*
+ * cs5530_tuneproc() handles selection/setting of PIO modes
+ * for both the chipset and drive.
+ *
+ * The ide_init_cs5530() routine guarantees that all drives
+ * will have valid default PIO timings set up before we get here.
+ */
+static void cs5530_tuneproc (ide_drive_t *drive, byte pio)	/* pio=255 means "autotune" */
+{
+	ide_hwif_t	*hwif = HWIF(drive);
+	unsigned int	format, basereg = CS5530_BASEREG(hwif);
+	static byte	modes[5] = {XFER_PIO_0, XFER_PIO_1, XFER_PIO_2, XFER_PIO_3, XFER_PIO_4};
+
+	pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
+	if (!cs5530_set_xfer_mode(drive, modes[pio])) {
+		format = (inl(basereg+4) >> 31) & 1;
+		outl(cs5530_pio_timings[format][pio], basereg+(drive->select.b.unit<<3));
+	}
+}
+
+/*
+ * cs5530_config_dma() handles selection/setting of DMA/UDMA modes
+ * for both the chipset and drive.
+ */
+static int cs5530_config_dma (ide_drive_t *drive)
+{
+	int			udma_ok = 1, mode = 0;
+	ide_hwif_t		*hwif = HWIF(drive);
+	int			unit = drive->select.b.unit;
+	ide_drive_t		*mate = &hwif->drives[unit^1];
+	struct hd_driveid	*id = drive->id;
+	unsigned int		basereg, reg, timings;
+
+
+	/*
+	 * Default to DMA-off in case we run into trouble here.
+	 */
+	(void)hwif->dmaproc(ide_dma_off_quietly, drive);	/* turn off DMA while we fiddle */
+	outb(inb(hwif->dma_base+2)&~(unit?0x40:0x20), hwif->dma_base+2); /* clear DMA_capable bit */
+
+	/*
+	 * The CS5530 specifies that two drives sharing a cable cannot
+	 * mix UDMA/MDMA.  It has to be one or the other, for the pair,
+	 * though different timings can still be chosen for each drive.
+	 * We could set the appropriate timing bits on the fly,
+	 * but that might be a bit confusing.  So, for now we statically
+	 * handle this requirement by looking at our mate drive to see
+	 * what it is capable of, before choosing a mode for our own drive.
+	 */
+	if (mate->present) {
+		struct hd_driveid *mateid = mate->id;
+		if (mateid && (mateid->capability & 1)) {
+#ifndef CS5530_2_2_KERNEL
+			if (!hwif->dmaproc(ide_dma_bad_drive, mate))
+#endif /* CS5530_2_2_KERNEL */
+			{
+				if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7))
+					udma_ok = 1;
+				else if ((mateid->field_valid & 2) && (mateid->dma_mword & 7))
+					udma_ok = 0;
+				else
+					udma_ok = 1;
+			}
+		}
+	}
+
+	/*
+	 * Now see what the current drive is capable of,
+	 * selecting UDMA only if the mate said it was ok.
+	 */
+	if (id && (id->capability & 1) && hwif->autodma) {
+#ifndef CS5530_2_2_KERNEL
+		if (!hwif->dmaproc(ide_dma_bad_drive, drive))
+#endif /* CS5530_2_2_KERNEL */
+		{
+			if (udma_ok && (id->field_valid & 4) && (id->dma_ultra & 7)) {
+				if      (id->dma_ultra & 4)
+					mode = XFER_UDMA_2;
+				else if (id->dma_ultra & 2)
+					mode = XFER_UDMA_1;
+				else if (id->dma_ultra & 1)
+					mode = XFER_UDMA_0;
+			}
+			if (!mode && (id->field_valid & 2) && (id->dma_mword & 7)) {
+				if      (id->dma_mword & 4)
+					mode = XFER_MW_DMA_2;
+				else if (id->dma_mword & 2)
+					mode = XFER_MW_DMA_1;
+				else if (id->dma_mword & 1)
+					mode = XFER_MW_DMA_0;
+			}
+		}
+	}
+
+	/*
+	 * Tell the drive to switch to the new mode; abort on failure.
+	 */
+	if (!mode || cs5530_set_xfer_mode(drive, mode))
+		return 1;	/* failure */
+
+	/*
+	 * Now tune the chipset to match the drive:
+	 */
+	switch (mode) {
+		case XFER_UDMA_0:	timings = 0x00921250; break;
+		case XFER_UDMA_1:	timings = 0x00911140; break;
+		case XFER_UDMA_2:	timings = 0x00911030; break;
+		case XFER_MW_DMA_0:	timings = 0x00077771; break;
+		case XFER_MW_DMA_1:	timings = 0x00012121; break;
+		case XFER_MW_DMA_2:	timings = 0x00002020; break;
+		default:
+			printk("%s: cs5530_config_dma: huh? mode=%02x\n", drive->name, mode);
+			return 1;	/* failure */
+	}
+	basereg = CS5530_BASEREG(hwif);
+	reg = inl(basereg+4);			/* get drive0 config register */
+	timings |= reg & 0x80000000;		/* preserve PIO format bit */
+	if (unit == 0) {			/* are we configuring drive0? */
+		outl(timings, basereg+4);	/* write drive0 config register */
+	} else {
+		if (timings & 0x00100000)
+			reg |=  0x00100000;	/* enable UDMA timings for both drives */
+		else
+			reg &= ~0x00100000;	/* disable UDMA timings for both drives */
+		outl(reg,     basereg+4);	/* write drive0 config register */
+		outl(timings, basereg+12);	/* write drive1 config register */
+	}
+	outb(inb(hwif->dma_base+2)|(unit?0x40:0x20), hwif->dma_base+2);	/* set DMA_capable bit */
+
+	/*
+	 * Finally, turn DMA on in software, and exit.
+	 */
+	return hwif->dmaproc(ide_dma_on, drive);	/* success */
+}
+
+/*
+ * This is a CS5530-specific wrapper for the standard ide_dmaproc().
+ * We need it for our custom "ide_dma_check" function.
+ * All other requests are forwarded to the standard ide_dmaproc().
+ */
+int cs5530_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
+{
+	switch (func) {
+		case ide_dma_check:
+			return cs5530_config_dma(drive);
+		default:
+			return ide_dmaproc(func, drive);
+	}
+}
+
+/*
+ * Initialize the cs5530 bridge for reliable IDE DMA operation.
+ */
+unsigned int __init pci_init_cs5530 (struct pci_dev *dev, const char *name)
+{
+	struct pci_dev *master_0 = NULL, *cs5530_0 = NULL;
+	unsigned short pcicmd = 0;
+	unsigned long flags;
+
+	pci_for_each_dev (dev) {
+		if (dev->vendor == PCI_VENDOR_ID_CYRIX) {
+			switch (dev->device) {
+				case PCI_DEVICE_ID_CYRIX_PCI_MASTER:
+					master_0 = dev;
+					break;
+				case PCI_DEVICE_ID_CYRIX_5530_LEGACY:
+					cs5530_0 = dev;
+					break;
+			}
+		}
+	}
+	if (!master_0) {
+		printk("%s: unable to locate PCI MASTER function\n", name);
+		return 0;
+	}
+	if (!cs5530_0) {
+		printk("%s: unable to locate CS5530 LEGACY function\n", name);
+		return 0;
+	}
+
+	save_flags(flags);
+	cli();	/* all CPUs (there should only be one CPU with this chipset) */
+
+	/*
+	 * Enable BusMaster and MemoryWriteAndInvalidate for the cs5530:
+	 * -->  OR 0x14 into 16-bit PCI COMMAND reg of function 0 of the cs5530
+	 */
+	pci_read_config_word (cs5530_0, PCI_COMMAND, &pcicmd);
+	pci_write_config_word(cs5530_0, PCI_COMMAND, pcicmd | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE);
+
+	/*
+	 * Set PCI CacheLineSize to 16-bytes:
+	 * --> Write 0x04 into 8-bit PCI CACHELINESIZE reg of function 0 of the cs5530
+	 */
+	pci_write_config_byte(cs5530_0, PCI_CACHE_LINE_SIZE, 0x04);
+
+	/*
+	 * Disable trapping of UDMA register accesses (Win98 hack):
+	 * --> Write 0x5006 into 16-bit reg at offset 0xd0 of function 0 of the cs5530
+	 */
+	pci_write_config_word(cs5530_0, 0xd0, 0x5006);
+
+	/*
+	 * Bit-1 at 0x40 enables MemoryWriteAndInvalidate on internal X-bus:
+	 * The other settings are what is necessary to get the register
+	 * into a sane state for IDE DMA operation.
+	 */
+	pci_write_config_byte(master_0, 0x40, 0x1e);
+
+	/* 
+	 * Set max PCI burst size (16-bytes seems to work best):
+	 *	   16bytes: set bit-1 at 0x41 (reg value of 0x16)
+	 *	all others: clear bit-1 at 0x41, and do:
+	 *	  128bytes: OR 0x00 at 0x41
+	 *	  256bytes: OR 0x04 at 0x41
+	 *	  512bytes: OR 0x08 at 0x41
+	 *	 1024bytes: OR 0x0c at 0x41
+	 */
+	pci_write_config_byte(master_0, 0x41, 0x14);
+
+	/*
+	 * These settings are necessary to get the chip
+	 * into a sane state for IDE DMA operation.
+	 */
+	pci_write_config_byte(master_0, 0x42, 0x00);
+	pci_write_config_byte(master_0, 0x43, 0xc1);
+
+	restore_flags(flags);
+	return 0;
+}
+
+/*
+ * This gets invoked by the IDE driver once for each channel,
+ * and performs channel-specific pre-initialization before drive probing.
+ */
+void __init ide_init_cs5530 (ide_hwif_t *hwif)
+{
+#ifndef CS5530_2_2_KERNEL
+	static int already_done = 0;
+	if (!already_done) {
+		++already_done;
+		(void) pci_init_cs5530 (hwif->pci_dev, "CS5530");
+	}
+#endif /* CS5530_2_2_KERNEL */
+	if (hwif->mate)
+		hwif->serialized = hwif->mate->serialized = 1;
+	if (!hwif->dma_base) {
+		hwif->autodma = 0;
+	} else {
+		unsigned int basereg, d0_timings;
+
+		hwif->dmaproc  = &cs5530_dmaproc;
+		hwif->tuneproc = &cs5530_tuneproc;
+		basereg = CS5530_BASEREG(hwif);
+		d0_timings = inl(basereg+0);
+		if (CS5530_BAD_PIO(d0_timings)) {	/* PIO timings not initialized? */
+			outl(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+0);
+			if (!hwif->drives[0].autotune)
+				hwif->drives[0].autotune = 1;	/* needs autotuning later */
+		}
+		if (CS5530_BAD_PIO(inl(basereg+8))) {	/* PIO timings not initialized? */
+			outl(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+8);
+			if (!hwif->drives[1].autotune)
+				hwif->drives[1].autotune = 1;	/* needs autotuning later */
+		}
+	}
+}
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/block/ida_cmd.h linux.15p9/drivers/block/ida_cmd.h
--- linux.vanilla/drivers/block/ida_cmd.h	Sat Aug 14 02:27:16 1999
+++ linux.15p9/drivers/block/ida_cmd.h	Mon Feb  7 12:23:16 2000
@@ -191,7 +191,7 @@
 	__u8	expn_fail;
 	__u8	unit_flags;
 	__u16	big_fail_map[8];
-	__u16	big_remap_map[8];
+	__u16	big_remap_map[128];
 	__u16	big_repl_map[8];
 	__u16	big_act_spare_map[8];
 	__u8	big_spar_repl_map[128];
@@ -336,7 +336,7 @@
 	__u32	sense_info;
 	__u8	sense_code;
 	__u8	sense_qual;
-	__u8	residual;
+	__u32	residual;
 	__u8	reserved[4];
 	__u8	cdb[12];	
 } scsi_param_t;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/block/ide-cd.c linux.15p9/drivers/block/ide-cd.c
--- linux.vanilla/drivers/block/ide-cd.c	Tue Jan  4 21:18:44 2000
+++ linux.15p9/drivers/block/ide-cd.c	Thu Feb 17 22:18:17 2000
@@ -313,6 +313,10 @@
 		    failed_command->c[0] == SCMD_READ_SUBCHANNEL)
 			return;
 	}
+
+	if (failed_command && (failed_command->c[0] == TEST_UNIT_READY))
+		return;
+
 	if (reqbuf->error_code == 0x70 && reqbuf->sense_key  == 0x02
 	 && ((reqbuf->asc        == 0x3a && reqbuf->ascq       == 0x00) ||
 	     (reqbuf->asc        == 0x04 && reqbuf->ascq       == 0x01)))
@@ -2567,14 +2571,51 @@
 	return cdrom_lockdoor (drive, lock, NULL);
 }
 
+/*
+ * the buffer struct used by ide_cdrom_get_capabilities()
+ */
+struct get_capabilities_buf {
+	char pad[8];
+	struct atapi_capabilities_page cap;	/* this is 4 bytes short of ATAPI standard */
+	char extra_cap[4];			/* Acer 50X needs the regulation size buffer */
+};
+
+static
+int ide_cdrom_get_capabilities (ide_drive_t *drive, struct get_capabilities_buf *buf)
+{
+	int stat, attempts = 3, buflen = sizeof(*buf);
+
+	/*
+	 * Most drives don't care about the buffer size; they return as much info as there's room for.
+	 * But some older drives (?) had trouble with the standard size, preferring 4 bytes less.
+	 * And the modern Acer 50X rejects anything smaller than the standard size.
+	 */
+	if (!(drive->id && !strcmp(drive->id->model,"ATAPI CD ROM DRIVE 50X MAX")))
+		buflen -= sizeof(buf->extra_cap);	/* for all drives except Acer 50X */
+
+	do { /* we seem to get stat=0x01,err=0x00 the first time (??) */
+		stat = cdrom_mode_sense (drive, PAGE_CAPABILITIES, 0, (char *)buf, buflen, NULL);
+		if (stat == 0) {
+			/*
+			 * The ACER/AOpen 24X cdrom has the speed fields byte-swapped from the standard.
+			 */
+			if (!(drive->id && !drive->id->model[0] && !strncmp(drive->id->fw_rev, "241N", 4))) {
+				buf->cap.curspeed = ntohs(buf->cap.curspeed);
+				buf->cap.maxspeed = ntohs(buf->cap.maxspeed);
+			}
+			CDROM_STATE_FLAGS (drive)->current_speed = (((unsigned int)buf->cap.curspeed) + (176/2)) / 176;
+			CDROM_CONFIG_FLAGS(drive)->max_speed     = (((unsigned int)buf->cap.maxspeed) + (176/2)) / 176;
+			return 0;
+		}
+	} while (--attempts);
+	return stat;
+}
+
 static
 int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed)
 {
-        int stat, attempts = 3;
-        struct {
-                char pad[8];
-                struct atapi_capabilities_page cap;
-        } buf;
+	int stat;
+	struct get_capabilities_buf	buf;
 	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
 	struct atapi_request_sense reqbuf;
 	stat=cdrom_select_speed (drive, speed, &reqbuf);
@@ -2582,25 +2623,9 @@
 		return stat;
 
 	/* Now with that done, update the speed fields */
-        do {    /* we seem to get stat=0x01,err=0x00 the first time (??) */
-                if (attempts-- <= 0)
-                        return 0;
-                stat = cdrom_mode_sense (drive, PAGE_CAPABILITIES, 0,
-                                        (char *)&buf, sizeof (buf), NULL);
-        } while (stat);
-
-        /* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */
-        if (drive->id && !drive->id->model[0] && !strncmp(drive->id->fw_rev, "241N", 4)) {
-                CDROM_STATE_FLAGS (drive)->current_speed  = 
-			(((unsigned int)buf.cap.curspeed) + (176/2)) / 176;
-                CDROM_CONFIG_FLAGS (drive)->max_speed = 
-			(((unsigned int)buf.cap.maxspeed) + (176/2)) / 176;
-        } else {
-                CDROM_STATE_FLAGS (drive)->current_speed  = 
-			(ntohs(buf.cap.curspeed) + (176/2)) / 176;
-                CDROM_CONFIG_FLAGS (drive)->max_speed = 
-			(ntohs(buf.cap.maxspeed) + (176/2)) / 176;
-        }
+	if (ide_cdrom_get_capabilities(drive,&buf))
+		return 0;
+
         cdi->speed = CDROM_STATE_FLAGS (drive)->current_speed;
         return 0;
 }
@@ -2894,11 +2919,8 @@
 static
 int ide_cdrom_probe_capabilities (ide_drive_t *drive)
 {
-	int stat, nslots = 0, attempts = 3;
- 	struct {
-		char pad[8];
-		struct atapi_capabilities_page cap;
-	} buf;
+	int stat, nslots = 0;
+	struct get_capabilities_buf	buf;
 
 	if (CDROM_CONFIG_FLAGS (drive)->nec260) {
 		CDROM_CONFIG_FLAGS (drive)->no_eject = 0;
@@ -2906,13 +2928,8 @@
 		return nslots;
 	}
 
-	do {	/* we seem to get stat=0x01,err=0x00 the first time (??) */
-		if (attempts-- <= 0)
-			return 0;
-		stat = cdrom_mode_sense (drive, PAGE_CAPABILITIES, 0,
-				 	(char *)&buf, sizeof (buf), NULL);
-	} while (stat);
-
+	if (ide_cdrom_get_capabilities(drive,&buf))
+		return 0;
 	if (buf.cap.lock == 0)
 		CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1;
 	if (buf.cap.eject)
@@ -2953,19 +2970,6 @@
 			CDROM_CONFIG_FLAGS (drive)->supp_disc_present = 1;
 			nslots = mechbuf.nslots;
 		}
-	}
-
-	/* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */
-	if (drive->id && !drive->id->model[0] && !strncmp(drive->id->fw_rev, "241N", 4)) {
-		CDROM_STATE_FLAGS (drive)->current_speed  = 
-			(((unsigned int)buf.cap.curspeed) + (176/2)) / 176;
-		CDROM_CONFIG_FLAGS (drive)->max_speed = 
-			(((unsigned int)buf.cap.maxspeed) + (176/2)) / 176;
-	} else {
-		CDROM_STATE_FLAGS (drive)->current_speed  = 
-			(ntohs(buf.cap.curspeed) + (176/2)) / 176;
-		CDROM_CONFIG_FLAGS (drive)->max_speed = 
-			(ntohs(buf.cap.maxspeed) + (176/2)) / 176;
 	}
 
 	printk ("%s: ATAPI %dX %s", 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/block/ide-disk.c linux.15p9/drivers/block/ide-disk.c
--- linux.vanilla/drivers/block/ide-disk.c	Tue Jan  4 21:18:44 2000
+++ linux.15p9/drivers/block/ide-disk.c	Wed Feb 16 18:43:42 2000
@@ -571,7 +571,7 @@
 	drive->special.b.recalibrate  = 1;
 	if (OK_TO_RESET_CONTROLLER)
 		drive->mult_count = 0;
-	if (!drive->keep_settings)
+	if (!drive->keep_settings && !drive->using_dma)
 		drive->mult_req = 0;
 	if (drive->mult_req != drive->mult_count)
 		drive->special.b.set_multmode = 1;
@@ -799,9 +799,6 @@
 	/* Use physical geometry if what we have still makes no sense */
 	if ((!drive->head || drive->head > 16) &&
 	    id->heads && id->heads <= 16) {
-		if ((id->lba_capacity > 16514064) || (id->cyls == 0x3fff)) {
-			id->cyls = ((int)(id->lba_capacity/(id->heads * id->sectors)));
-		}
 		drive->cyl  = id->cyls;
 		drive->head = id->heads;
 		drive->sect = id->sectors;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/block/ide-pci.c linux.15p9/drivers/block/ide-pci.c
--- linux.vanilla/drivers/block/ide-pci.c	Mon Jan 25 05:54:35 1999
+++ linux.15p9/drivers/block/ide-pci.c	Mon Feb  7 12:19:11 2000
@@ -47,6 +47,7 @@
 #define DEVID_UM8886A	((ide_pci_devid_t){PCI_VENDOR_ID_UMC,     PCI_DEVICE_ID_UMC_UM8886A})
 #define DEVID_UM8886BF	((ide_pci_devid_t){PCI_VENDOR_ID_UMC,     PCI_DEVICE_ID_UMC_UM8886BF})
 #define DEVID_HPT343	((ide_pci_devid_t){PCI_VENDOR_ID_TTI,     PCI_DEVICE_ID_TTI_HPT343})
+#define DEVID_CS5530	((ide_pci_devid_t){PCI_VENDOR_ID_CYRIX,   PCI_DEVICE_ID_CYRIX_5530_IDE})
 
 #define IDE_IGNORE	((void *)-1)
 
@@ -103,6 +104,13 @@
 #define	INIT_VIA82C586	NULL
 #endif
 
+#ifdef CONFIG_BLK_DEV_CS5530
+extern void ide_init_cs5530(ide_hwif_t *);
+#define INIT_CS5530     &ide_init_cs5530
+#else
+#define INIT_CS5530     NULL
+#endif
+
 typedef struct ide_pci_enablebit_s {
 	byte	reg;	/* byte pci reg holding the enable-bit */
 	byte	mask;	/* mask to isolate the enable-bit */
@@ -141,6 +149,7 @@
 	{DEVID_UM8886A,	"UM8886A",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
 	{DEVID_UM8886BF,"UM8886BF",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
 	{DEVID_HPT343,	"HPT343",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	NEVER_BOARD,	16 },
+	{DEVID_CS5530,	"CS5530",	INIT_CS5530,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	112 },
 	{IDE_PCI_DEVID_NULL, "PCI_IDE",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 }};
 
 /*
@@ -393,6 +402,7 @@
 		if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) ||
 		    IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210) ||
 		    IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT343) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_CS5530) ||
 		    ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) {
 			unsigned long dma_base = ide_get_or_set_dma_base(hwif, (!mate && d->extra) ? d->extra : 0, d->name);
 			if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) {
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/block/ide-probe.c linux.15p9/drivers/block/ide-probe.c
--- linux.vanilla/drivers/block/ide-probe.c	Tue Jan  4 21:18:44 2000
+++ linux.15p9/drivers/block/ide-probe.c	Wed Jan 26 23:17:13 2000
@@ -279,6 +279,7 @@
 		drive->name, drive->present, drive->media,
 		(cmd == WIN_IDENTIFY) ? "ATA" : "ATAPI");
 #endif
+	delay_50ms();	/* needed for some systems (e.g. crw9624 as drive0 with disk as slave) */
 	SELECT_DRIVE(hwif,drive);
 	delay_50ms();
 	if (IN_BYTE(IDE_SELECT_REG) != drive->select.all && !drive->present) {
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/block/ide.c linux.15p9/drivers/block/ide.c
--- linux.vanilla/drivers/block/ide.c	Tue Jan  4 21:18:44 2000
+++ linux.15p9/drivers/block/ide.c	Mon Feb  7 12:21:10 2000
@@ -598,14 +598,16 @@
 
 static void pre_reset (ide_drive_t *drive)
 {
+	if (drive->driver != NULL)
+		DRIVER(drive)->pre_reset(drive);
 	if (!drive->keep_settings) {
-		drive->unmask = 0;
-		drive->io_32bit = 0;
-		if (drive->using_dma)
+		if (drive->using_dma) {
 			(void) HWIF(drive)->dmaproc(ide_dma_off, drive);
+		} else {
+			drive->unmask = 0;
+			drive->io_32bit = 0;
+		}
 	}
-	if (drive->driver != NULL)
-		DRIVER(drive)->pre_reset(drive);
 }
 
 /*
@@ -830,8 +832,8 @@
 		if ((stat & DRQ_STAT) && rq->cmd != WRITE)
 			try_to_flush_leftover_data(drive);
 	}
-	if (GET_STAT() & (BUSY_STAT|DRQ_STAT))
-		rq->errors |= ERROR_RESET;	/* Mmmm.. timing problem */
+	if (GET_STAT() & (BUSY_STAT|DRQ_STAT))	/* possible timing problem? */
+		OUT_BYTE(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); /* force an abort */
 
 	if (rq->errors >= ERROR_MAX) {
 		if (drive->driver != NULL)
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/block/ide_modes.h linux.15p9/drivers/block/ide_modes.h
--- linux.vanilla/drivers/block/ide_modes.h	Sun Mar 28 19:03:27 1999
+++ linux.15p9/drivers/block/ide_modes.h	Mon Feb  7 13:09:21 2000
@@ -15,7 +15,7 @@
  * breaking the fragile cmd640.c support.
  */
 
-#if defined(CONFIG_BLK_DEV_CMD640) || defined(CONFIG_IDE_CHIPSETS) || defined(CONFIG_BLK_DEV_OPTI621) || defined(CONFIG_BLK_DEV_IDE_PMAC)
+#if defined(CONFIG_BLK_DEV_CMD640) || defined(CONFIG_IDE_CHIPSETS) || defined(CONFIG_BLK_DEV_OPTI621) || defined(CONFIG_BLK_DEV_IDE_PMAC) || defined(CONFIG_BLK_DEV_CS5530)
 
 /*
  * Standard (generic) timings for PIO modes, from ATA2 specification.
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/block/ll_rw_blk.c linux.15p9/drivers/block/ll_rw_blk.c
--- linux.vanilla/drivers/block/ll_rw_blk.c	Tue Jan  4 21:18:44 2000
+++ linux.15p9/drivers/block/ll_rw_blk.c	Mon Feb  7 12:11:33 2000
@@ -847,8 +847,7 @@
 #ifdef CONFIG_BLK_DEV_FD
 	floppy_init();
 #else
-#if !defined (__mc68000__) && !defined(CONFIG_PMAC) && !defined(__sparc__)\
-    && !defined(CONFIG_APUS)
+#if !defined (__mc68000__) && !defined(CONFIG_PPC) && !defined(__sparc__)
 	outb_p(0xc, 0x3f2);
 #endif
 #endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/block/raid1.c linux.15p9/drivers/block/raid1.c
--- linux.vanilla/drivers/block/raid1.c	Tue Dec 22 16:12:38 1998
+++ linux.15p9/drivers/block/raid1.c	Mon Feb  7 12:38:08 2000
@@ -211,7 +211,11 @@
 	while (!( /* FIXME: now we are rather fault tolerant than nice */
 	r1_bh = kmalloc (sizeof (struct raid1_bh), GFP_KERNEL)
 	) )
+	{
 		printk ("raid1_make_request(#1): out of memory\n");
+		current->policy |= SCHED_YIELD;
+		schedule();
+	}
 	memset (r1_bh, 0, sizeof (struct raid1_bh));
 
 /*
@@ -299,7 +303,11 @@
 		while (!( /* FIXME: now we are rather fault tolerant than nice */
 		mirror_bh[i] = kmalloc (sizeof (struct buffer_head), GFP_KERNEL)
 		) )
+		{
 			printk ("raid1_make_request(#2): out of memory\n");
+			current->policy |= SCHED_YIELD;
+			schedule();
+		}
 		memset (mirror_bh[i], 0, sizeof (struct buffer_head));
 
 	/*
@@ -711,7 +719,11 @@
 	while (!( /* FIXME: now we are rather fault tolerant than nice */
 	mddev->private = kmalloc (sizeof (struct raid1_data), GFP_KERNEL)
 	) )
+	{
 		printk ("raid1_run(): out of memory\n");
+		current->policy |= SCHED_YIELD;
+		schedule();
+	}
 	raid_conf = mddev->private;
 	memset(raid_conf, 0, sizeof(*raid_conf));
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/Config.in linux.15p9/drivers/char/Config.in
--- linux.vanilla/drivers/char/Config.in	Tue Jan  4 21:18:45 2000
+++ linux.15p9/drivers/char/Config.in	Mon Feb  7 12:30:39 2000
@@ -44,6 +44,10 @@
      bool 'Specialix DTR/RTS pin is RTS' CONFIG_SPECIALIX_RTSCTS
    fi 
    tristate 'Specialix SX (and SI) card support' CONFIG_SX
+   tristate 'Specialix RIO system support' CONFIG_RIO
+   if [ "$CONFIG_RIO" != "n" ]; then
+     bool 'Support really old RIO/PCI cards' CONFIG_RIO_OLDPCI
+   fi
    bool 'Stallion multiport serial support' CONFIG_STALDRV
    if [ "$CONFIG_STALDRV" = "y" ]; then
      tristate '  Stallion EasyIO or EC8/32 support' CONFIG_STALLION
@@ -137,7 +141,7 @@
   dep_tristate 'Miro PCM20 Radio' CONFIG_RADIO_MIROPCM20 $CONFIG_VIDEO_DEV
   dep_tristate 'GemTek Radio Card support' CONFIG_RADIO_GEMTEK $CONFIG_VIDEO_DEV
   if [ "$CONFIG_RADIO_GEMTEK" = "y" ]; then
-    hex '  GemTek i/o port (0x20c, 0x30c, 0x24c or 0x34c)' CONFIG_RADIO_GEMTEK_PORT 34c
+    hex '  GemTek i/o port (0x20c, 0x24c, 0x248, 0x30c, or 0x34c)' CONFIG_RADIO_GEMTEK_PORT 34c
   fi
   dep_tristate 'Trust FM Radio' CONFIG_RADIO_TRUST $CONFIG_VIDEO_DEV
   if [ "$CONFIG_RADIO_TRUST" = "y" ]; then
@@ -149,6 +153,17 @@
   if [ "$CONFIG_PARPORT" != "n" ]; then
     dep_tristate 'Quickcam BW Video For Linux' CONFIG_VIDEO_BWQCAM $CONFIG_VIDEO_DEV $CONFIG_PARPORT
     dep_tristate 'Colour QuickCam Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_CQCAM $CONFIG_VIDEO_DEV $CONFIG_PARPORT
+  fi
+  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+    dep_tristate 'CPiA Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_CPIA $CONFIG_VIDEO_DEV
+    if [ "$CONFIG_VIDEO_CPIA" != "n" ]; then
+      if [ "$CONFIG_PARPORT" != "n" ]; then
+        dep_tristate 'CPiA Parallel Port Lowlevel Support (EXPERIMENTAL)' CONFIG_VIDEO_CPIA_PP $CONFIG_VIDEO_CPIA $CONFIG_PARPORT
+        if [ "$CONFIG_VIDEO_CPIA_PP" != "n" ]; then
+          bool 'CPiA Parallel Port DMA Support (EXPERIMENTAL)' CONFIG_VIDEO_CPIA_PP_DMA
+        fi
+      fi
+    fi
   fi
   dep_tristate 'Mediavision Pro Movie Studio Video For Linux' CONFIG_VIDEO_PMS $CONFIG_VIDEO_DEV
   if [ "$CONFIG_PMAC" = "y" ]; then
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/Makefile linux.15p9/drivers/char/Makefile
--- linux.vanilla/drivers/char/Makefile	Tue Jan  4 21:18:45 2000
+++ linux.15p9/drivers/char/Makefile	Mon Feb  7 12:30:39 2000
@@ -11,7 +11,7 @@
 
 SUB_DIRS     := 
 MOD_SUB_DIRS := $(SUB_DIRS)
-ALL_SUB_DIRS := $(SUB_DIRS) ftape joystick
+ALL_SUB_DIRS := $(SUB_DIRS) rio ftape joystick
 
 #
 # This file contains the font map for the default (hardware) font
@@ -202,7 +202,18 @@
 L_OBJS += sx.o generic_serial.o
 else
   ifeq ($(CONFIG_SX),m)
-  M_OBJS += sx.o
+  M_OBJS += sx.o  generic_serial.o
+  endif
+endif
+
+ifeq ($(CONFIG_RIO),y)
+L_OBJS += rio/rio.o  generic_serial.o
+SUB_DIRS += rio
+MOD_SUB_DIRS += rio
+else
+  ifeq ($(CONFIG_RIO),m)
+  M_OBJS += generic_serial.o
+  MOD_SUB_DIRS += rio
   endif
 endif
 
@@ -461,6 +472,22 @@
 else
   ifeq ($(CONFIG_VIDEO_VINO),m)
   M_OBJS += vino.o
+  endif
+endif
+
+ifeq ($(CONFIG_VIDEO_CPIA),y)
+LX_OBJS += cpia.o
+else
+  ifeq ($(CONFIG_VIDEO_CPIA),m)
+    MX_OBJS += cpia.o
+  endif
+endif
+
+ifeq ($(CONFIG_VIDEO_CPIA_PP),y)
+L_OBJS += cpia_pp.o
+else
+  ifeq ($(CONFIG_VIDEO_CPIA_PP),m)
+    M_OBJS += cpia_pp.o
   endif
 endif
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/console.c linux.15p9/drivers/char/console.c
--- linux.vanilla/drivers/char/console.c	Tue Jan  4 21:18:45 2000
+++ linux.15p9/drivers/char/console.c	Wed Feb 16 18:35:25 2000
@@ -91,9 +91,6 @@
 #include <linux/config.h>
 #include <linux/version.h>
 #include <linux/tqueue.h>
-#ifdef CONFIG_APM
-#include <linux/apm_bios.h>
-#endif
 
 #include <asm/io.h>
 #include <asm/system.h>
@@ -188,6 +185,12 @@
 static int scrollback_delta = 0;
 
 /*
+ * Hook so that the power management routines can (un)blank
+ * the console on our behalf.
+ */
+int (*console_blank_hook)(int) = NULL;
+
+/*
  *	Low-Level Functions
  */
 
@@ -2539,10 +2542,8 @@
 	if (i)
 		set_origin(currcons);
 
-#ifdef CONFIG_APM
-	if (apm_display_blank())
+	if (console_blank_hook && console_blank_hook(1))
 		return;
-#endif
     	if (vesa_blank_mode)
 		sw->con_blank(vc_cons[currcons].d, vesa_blank_mode + 1);
 }
@@ -2566,9 +2567,8 @@
 
 	currcons = fg_console;
 	console_blanked = 0;
-#ifdef CONFIG_APM
-	apm_display_unblank();
-#endif
+	if (console_blank_hook)
+		console_blank_hook(0);
 	if (sw->con_blank(vc_cons[currcons].d, 0))
 		/* Low-level driver cannot restore -> do it ourselves */
 		update_screen(fg_console);
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/cpia.c linux.15p9/drivers/char/cpia.c
--- linux.vanilla/drivers/char/cpia.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/cpia.c	Mon Feb  7 12:30:39 2000
@@ -0,0 +1,3375 @@
+/*
+ * cpia CPiA driver
+ *
+ * Supports CPiA based Video Camera's.
+ *
+ * (C) 1999 Peter Pregler,
+ *          Scott J. Bertin,
+ *          Johannes Erdfelt
+ *
+ * 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/config.h>
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/wrapper.h>
+#include <linux/fs.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/proc_fs.h>
+#include <linux/ctype.h>
+#include <linux/videodev.h>
+#include <asm/io.h>
+#include <asm/semaphore.h>
+
+#ifdef CONFIG_KMOD
+#include <linux/kmod.h>
+#endif
+
+#undef _CPIA_DEBUG_		/* define for verbose debug output */
+#include <linux/cpia.h>
+
+#ifdef CONFIG_VIDEO_CPIA_PP
+extern int cpia_pp_init(void);
+#endif
+#ifdef CONFIG_VIDEO_CPIA_USB
+extern int cpia_usb_init(void);
+#endif
+
+#ifdef MODULE
+MODULE_AUTHOR("Scott J. Bertin <sbertin@mindspring.com> & Peter Pregler <Peter_Pregler@email.com>");
+MODULE_DESCRIPTION("V4L-driver for Vision CPiA based cameras");
+MODULE_SUPPORTED_DEVICE("video");
+#endif
+
+#define ABOUT "V4L-Driver for Vision CPiA based cameras"
+
+#ifndef VID_HARDWARE_CPIA
+#define VID_HARDWARE_CPIA 24    /* FIXME -> from linux/videodev.h */
+#endif
+
+#define CPIA_MODULE_CPIA			(0<<5)
+#define CPIA_MODULE_SYSTEM			(1<<5)
+#define CPIA_MODULE_VP_CTRL			(5<<5)
+#define CPIA_MODULE_CAPTURE			(6<<5)
+#define CPIA_MODULE_DEBUG			(7<<5)
+
+#define INPUT (DATA_IN << 8)
+#define OUTPUT (DATA_OUT << 8)
+
+#define CPIA_COMMAND_GetCPIAVersion	(INPUT | CPIA_MODULE_CPIA | 1)
+#define CPIA_COMMAND_GetPnPID		(INPUT | CPIA_MODULE_CPIA | 2)
+#define CPIA_COMMAND_GetCameraStatus	(INPUT | CPIA_MODULE_CPIA | 3)
+#define CPIA_COMMAND_GotoHiPower	(OUTPUT | CPIA_MODULE_CPIA | 4)
+#define CPIA_COMMAND_GotoLoPower	(OUTPUT | CPIA_MODULE_CPIA | 5)
+#define CPIA_COMMAND_GotoSuspend	(OUTPUT | CPIA_MODULE_CPIA | 7)
+#define CPIA_COMMAND_GotoPassThrough	(OUTPUT | CPIA_MODULE_CPIA | 8)
+#define CPIA_COMMAND_ModifyCameraStatus	(OUTPUT | CPIA_MODULE_CPIA | 10)
+
+#define CPIA_COMMAND_ReadVCRegs		(INPUT | CPIA_MODULE_SYSTEM | 1)
+#define CPIA_COMMAND_WriteVCReg		(OUTPUT | CPIA_MODULE_SYSTEM | 2)
+#define CPIA_COMMAND_ReadMCPorts	(INPUT | CPIA_MODULE_SYSTEM | 3)
+#define CPIA_COMMAND_WriteMCPort	(OUTPUT | CPIA_MODULE_SYSTEM | 4)
+#define CPIA_COMMAND_SetBaudRate	(OUTPUT | CPIA_MODULE_SYSTEM | 5)
+#define CPIA_COMMAND_SetECPTiming	(OUTPUT | CPIA_MODULE_SYSTEM | 6)
+#define CPIA_COMMAND_ReadIDATA		(INPUT | CPIA_MODULE_SYSTEM | 7)
+#define CPIA_COMMAND_WriteIDATA		(OUTPUT | CPIA_MODULE_SYSTEM | 8)
+#define CPIA_COMMAND_GenericCall	(OUTPUT | CPIA_MODULE_SYSTEM | 9)
+#define CPIA_COMMAND_I2CStart		(OUTPUT | CPIA_MODULE_SYSTEM | 10)
+#define CPIA_COMMAND_I2CStop		(OUTPUT | CPIA_MODULE_SYSTEM | 11)
+#define CPIA_COMMAND_I2CWrite		(OUTPUT | CPIA_MODULE_SYSTEM | 12)
+#define CPIA_COMMAND_I2CRead		(INPUT | CPIA_MODULE_SYSTEM | 13)
+
+#define CPIA_COMMAND_GetVPVersion	(INPUT | CPIA_MODULE_VP_CTRL | 1)
+#define CPIA_COMMAND_SetColourParams	(OUTPUT | CPIA_MODULE_VP_CTRL | 3)
+#define CPIA_COMMAND_SetExposure	(OUTPUT | CPIA_MODULE_VP_CTRL | 4)
+#define CPIA_COMMAND_SetColourBalance	(OUTPUT | CPIA_MODULE_VP_CTRL | 6)
+#define CPIA_COMMAND_SetSensorFPS	(OUTPUT | CPIA_MODULE_VP_CTRL | 7)
+#define CPIA_COMMAND_SetVPDefaults	(OUTPUT | CPIA_MODULE_VP_CTRL | 8)
+#define CPIA_COMMAND_SetApcor		(OUTPUT | CPIA_MODULE_VP_CTRL | 9)
+#define CPIA_COMMAND_SetFlickerCtrl	(OUTPUT | CPIA_MODULE_VP_CTRL | 10)
+#define CPIA_COMMAND_SetVLOffset	(OUTPUT | CPIA_MODULE_VP_CTRL | 11)
+#define CPIA_COMMAND_GetColourParams	(INPUT | CPIA_MODULE_VP_CTRL | 16)
+#define CPIA_COMMAND_GetColourBalance	(INPUT | CPIA_MODULE_VP_CTRL | 17)
+#define CPIA_COMMAND_GetExposure	(INPUT | CPIA_MODULE_VP_CTRL | 18)
+#define CPIA_COMMAND_SetSensorMatrix	(OUTPUT | CPIA_MODULE_VP_CTRL | 19)
+#define CPIA_COMMAND_ColourBars		(OUTPUT | CPIA_MODULE_VP_CTRL | 25)
+#define CPIA_COMMAND_ReadVPRegs		(INPUT | CPIA_MODULE_VP_CTRL | 30)
+#define CPIA_COMMAND_WriteVPReg		(OUTPUT | CPIA_MODULE_VP_CTRL | 31)
+
+#define CPIA_COMMAND_GrabFrame		(OUTPUT | CPIA_MODULE_CAPTURE | 1)
+#define CPIA_COMMAND_UploadFrame	(OUTPUT | CPIA_MODULE_CAPTURE | 2)
+#define CPIA_COMMAND_SetGrabMode	(OUTPUT | CPIA_MODULE_CAPTURE | 3)
+#define CPIA_COMMAND_InitStreamCap	(OUTPUT | CPIA_MODULE_CAPTURE | 4)
+#define CPIA_COMMAND_FiniStreamCap	(OUTPUT | CPIA_MODULE_CAPTURE | 5)
+#define CPIA_COMMAND_StartStreamCap	(OUTPUT | CPIA_MODULE_CAPTURE | 6)
+#define CPIA_COMMAND_EndStreamCap	(OUTPUT | CPIA_MODULE_CAPTURE | 7)
+#define CPIA_COMMAND_SetFormat		(OUTPUT | CPIA_MODULE_CAPTURE | 8)
+#define CPIA_COMMAND_SetROI		(OUTPUT | CPIA_MODULE_CAPTURE | 9)
+#define CPIA_COMMAND_SetCompression	(OUTPUT | CPIA_MODULE_CAPTURE | 10)
+#define CPIA_COMMAND_SetCompressionTarget (OUTPUT | CPIA_MODULE_CAPTURE | 11)
+#define CPIA_COMMAND_SetYUVThresh	(OUTPUT | CPIA_MODULE_CAPTURE | 12)
+#define CPIA_COMMAND_SetCompressionParams (OUTPUT | CPIA_MODULE_CAPTURE | 13)
+#define CPIA_COMMAND_DiscardFrame	(OUTPUT | CPIA_MODULE_CAPTURE | 14)
+
+#define CPIA_COMMAND_OutputRS232	(OUTPUT | CPIA_MODULE_DEBUG | 1)
+#define CPIA_COMMAND_AbortProcess	(OUTPUT | CPIA_MODULE_DEBUG | 4)
+#define CPIA_COMMAND_SetDramPage	(OUTPUT | CPIA_MODULE_DEBUG | 5)
+#define CPIA_COMMAND_StartDramUpload	(OUTPUT | CPIA_MODULE_DEBUG | 6)
+#define CPIA_COMMAND_StartDummyDtream	(OUTPUT | CPIA_MODULE_DEBUG | 8)
+#define CPIA_COMMAND_AbortStream	(OUTPUT | CPIA_MODULE_DEBUG | 9)
+#define CPIA_COMMAND_DownloadDRAM	(OUTPUT | CPIA_MODULE_DEBUG | 10)
+
+struct cam_params {
+	struct {
+		u8 firmwareVersion;
+		u8 firmwareRevision;
+		u8 vcVersion;
+		u8 vcRevision;
+	} version;
+	struct {
+		u16 vendor;
+		u16 product;
+		u16 deviceRevision;
+	} pnpID;
+	struct {
+		u8 vpVersion;
+		u8 vpRevision;
+		u16 cameraHeadID;
+	} vpVersion;
+	struct {
+		u8 systemState;
+		u8 grabState;
+		u8 streamState;
+		u8 fatalError;
+		u8 cmdError;
+		u8 debugFlags;
+		u8 vpStatus;
+		u8 errorCode;
+	} status;
+	struct {
+		u8 brightness;
+		u8 contrast;
+		u8 saturation;
+	} colourParams;
+	struct {
+		u8 gainMode;
+		u8 expMode;
+		u8 compMode;
+		u8 centreWeight;
+		u8 gain;
+		u8 fineExp;
+		u8 coarseExpLo;
+		u8 coarseExpHi;
+		u8 redComp;
+		u8 green1Comp;
+		u8 green2Comp;
+		u8 blueComp;
+	} exposure;
+	struct {
+		u8 balanceMode;
+		u8 redGain;
+		u8 greenGain;
+		u8 blueGain;
+	} colourBalance;
+	struct {
+		u8 divisor;
+		u8 baserate;
+	} sensorFps;
+	struct {
+		u8 gain1;
+		u8 gain2;
+		u8 gain4;
+		u8 gain8;
+	} apcor;
+	struct {
+		u8 flickerMode;
+		u8 coarseJump;
+		u8 allowableOverExposure;
+	} flickerControl;
+	struct {
+		u8 gain1;
+		u8 gain2;
+		u8 gain4;
+		u8 gain8;
+	} vlOffset;
+	struct {
+		u8 mode;
+		u8 decimation;
+	} compression;
+	struct {
+		u8 frTargeting;
+		u8 targetFR;
+		u8 targetQ;
+	} compressionTarget;
+	struct {
+		u8 yThreshold;
+		u8 uvThreshold;
+	} yuvThreshold;
+	struct {
+		u8 hysteresis;
+		u8 threshMax;
+		u8 smallStep;
+		u8 largeStep;
+		u8 decimationHysteresis;
+		u8 frDiffStepThresh;
+		u8 qDiffStepThresh;
+		u8 decimationThreshMod;
+	} compressionParams;
+	struct {
+		u8 videoSize;		/* CIF/QCIF */
+		u8 subSample;
+		u8 yuvOrder;
+	} format;
+	struct {
+		u8 colStart;		/* skip first 8*colStart pixels */
+		u8 colEnd;		/* finish at 8*colEnd pixels */
+		u8 rowStart;		/* skip first 4*rowStart lines */
+		u8 rowEnd;		/* finish at 4*rowEnd lines */
+	} roi;
+	u8 ecpTiming;
+	u8 streamStartLine;
+};
+
+enum {
+	FRAME_READY,		/* Ready to grab into */
+	FRAME_GRABBING,		/* In the process of being grabbed into */
+	FRAME_DONE,		/* Finished grabbing, but not been synced yet */
+	FRAME_UNUSED,		/* Unused (no MCAPTURE) */
+};
+
+#define FRAME_NUM	2	/* double buffering for now */
+struct cpia_frame {
+	u8 *data;
+	int count;
+	int width;
+	int height;
+	volatile int state;
+};
+
+enum v4l_camstates {
+	CPIA_V4L_IDLE = 0,
+	CPIA_V4L_ERROR,
+	CPIA_V4L_COMMAND,
+	CPIA_V4L_GRABBING,
+	CPIA_V4L_STREAMING,
+	CPIA_V4L_STREAMING_PAUSED,
+};
+
+#define COMMAND_NONE			0x0000
+#define COMMAND_SETCOMPRESSION		0x0001
+#define COMMAND_SETCOMPRESSIONTARGET	0x0002
+#define COMMAND_SETCOLOURPARAMS		0x0004
+#define COMMAND_SETFORMAT		0x0008
+#define COMMAND_PAUSE			0x0010
+#define COMMAND_RESUME			0x0020
+#define COMMAND_SETYUVTHRESH		0x0040
+#define COMMAND_SETECPTIMING		0x0080
+#define COMMAND_SETCOMPRESSIONPARAMS	0x0100
+#define COMMAND_SETEXPOSURE		0x0200
+#define COMMAND_SETCOLOURBALANCE	0x0400
+#define COMMAND_SETSENSORFPS		0x0800
+#define COMMAND_SETAPCOR		0x1000
+#define COMMAND_SETFLICKERCTRL		0x2000
+#define COMMAND_SETVLOFFSET		0x4000
+
+struct cam_data {
+	int index;			/* which camera is this */
+        struct semaphore busy_lock;     /* guard against SMP multithreading */
+	struct cpia_camera_ops *ops;	/* lowlevel driver operations */
+	void *lowlevel_data;		/* private data for lowlevel driver */
+	u8 *raw_image;			/* buffer for raw image data */
+	struct cpia_frame decompressed_frame;
+                                        /* buffer to hold decompressed frame */
+	int image_size;		        /* sizeof last decompressed image */
+	int open_count;			/* # of process that have camera open */
+				/* camera status */
+	int fps;			/* actual fps reported by the camera */
+	int transfer_rate;		/* transfer rate from camera in kB/s */
+	u8 mainsFreq;			/* for flicker control */
+
+				/* proc interface */
+	struct semaphore param_lock;	/* params lock for this camera */
+	struct cam_params params;	/* camera settings */
+	struct proc_dir_entry *proc_entry;	/* /proc/cpia/videoX */
+	
+					/* v4l */
+	int video_size;			/* VIDEO_SIZE_ */
+	volatile enum v4l_camstates camstate;	/* v4l layer status */
+	struct video_device vdev;	/* v4l videodev */
+	struct video_picture vp;	/* v4l camera settings */
+	struct video_window vw;		/* v4l capture area */
+
+				/* mmap interface */
+	int curframe;			/* the current frame to grab into */
+	u8 *frame_buf;			/* frame buffer data */
+        struct cpia_frame frame[FRAME_NUM];
+				/* FRAME_NUM-buffering, so we need a array */
+
+        int first_frame;
+	volatile u32 cmd_queue;		/* queued commands */
+};
+
+static struct cam_data *camera[CPIA_MAXCAMS] ={ [0 ... CPIA_MAXCAMS-1] = NULL };
+
+/* Developer's Guide Table 5 p 3-34
+ * indexed by [mains][sensorFps.baserate][sensorFps.divisor]*/
+static u8 flicker_jumps[2][2][4] =
+{ { { 76, 38, 19, 9 }, { 92, 46, 23, 11 } },
+  { { 64, 32, 16, 8 }, { 76, 38, 19, 9} }
+};
+
+/* forward declaration of local function */
+static void reset_camera_struct(struct cam_data *cam);
+
+/**********************************************************************
+ *
+ * Memory management
+ *
+ * This is a shameless copy from the USB-cpia driver (linux kernel
+ * version 2.3.13 or so, I have no idea what this code actually does ;).
+ * Actually it seems to be a copy of a shameless copy of the bttv-driver.
+ * Or that is a copy of a shameless copy of ... (To the powers: is there
+ * no generic kernel-function to do this sort of stuff?)
+ *
+ **********************************************************************/
+
+static inline unsigned long uvirt_to_phys(unsigned long adr)
+{
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *ptep, pte;
+
+	pgd = pgd_offset(current->mm, adr);
+	if (pgd_none(*pgd)) return 0;
+	pmd = pmd_offset(pgd, adr);
+	if (pmd_none(*pmd)) return 0;
+	ptep = pte_offset(pmd, adr/*&(~PGDIR_MASK)*/);
+	pte = *ptep;
+	if(pte_present(pte))
+		return 
+		  virt_to_phys((void *)(pte_page(pte)|(adr&(PAGE_SIZE-1))));
+	return 0;
+}
+
+static inline unsigned long kvirt_to_phys(unsigned long adr) 
+{
+	return uvirt_to_phys(VMALLOC_VMADDR(adr));
+}
+
+static void * rvmalloc(unsigned long size)
+{
+	void * mem;
+	unsigned long adr, page;
+
+	size += (PAGE_SIZE - 1);
+	size &= ~(PAGE_SIZE - 1);
+
+	mem=vmalloc(size);
+	if (mem) {
+		/* Clear the ram out, no junk to the user */
+		memset(mem, 0, size);
+		adr=(unsigned long) mem;
+		while (size > 0) {
+			page = kvirt_to_phys(adr);
+			mem_map_reserve(MAP_NR(phys_to_virt(page)));
+			adr+=PAGE_SIZE;
+			if (size > PAGE_SIZE) size-=PAGE_SIZE;
+			else  size=0;
+		}
+	}
+	return mem;
+}
+
+static void rvfree(void * mem, unsigned long size)
+{
+	unsigned long adr, page;
+        
+	size += (PAGE_SIZE - 1);
+	size &= ~(PAGE_SIZE - 1);
+
+	if (mem) {
+		adr=(unsigned long) mem;
+		while (size > 0) {
+			page = kvirt_to_phys(adr);
+			mem_map_unreserve(MAP_NR(phys_to_virt(page)));
+			adr+=PAGE_SIZE;
+			if (size > PAGE_SIZE) size-=PAGE_SIZE;
+			else size=0;
+		}
+		vfree(mem);
+	}
+}
+
+/**********************************************************************
+ *
+ * /proc interface
+ *
+ **********************************************************************/
+static struct proc_dir_entry *cpia_proc_root=NULL;
+
+static int cpia_read_proc(char *page, char **start, off_t off,
+                          int count, int *eof, void *data)
+{
+	char *out = page;
+	int len, tmp;
+	struct cam_data *cam = data;
+	char tmpstr[20];
+
+	/* IMPORTANT: This output MUST be kept under 4k (FIXME: PAGE_SIZE?)
+	 *            or we need to get more sophisticated. */
+
+	out += sprintf(out, "read-only\n-----------------------\n");
+	out += sprintf(out, "CPIA Version:             %d.%02d (%d.%d)\n",
+	               cam->params.version.firmwareVersion,
+	               cam->params.version.firmwareRevision,
+	               cam->params.version.vcVersion,
+	               cam->params.version.vcRevision);
+	out += sprintf(out, "CPIA PnP-ID:              %04x:%04x:%04x\n",
+	               cam->params.pnpID.vendor, cam->params.pnpID.product,
+	               cam->params.pnpID.deviceRevision);
+	out += sprintf(out, "VP-Version:               %d.%d %04x\n",
+	               cam->params.vpVersion.vpVersion,
+	               cam->params.vpVersion.vpRevision,
+	               cam->params.vpVersion.cameraHeadID);
+	
+	out += sprintf(out, "system_state:             %#04x\n",
+	               cam->params.status.systemState);
+	out += sprintf(out, "grab_state:               %#04x\n",
+	               cam->params.status.grabState);
+	out += sprintf(out, "stream_state:             %#04x\n",
+	               cam->params.status.streamState);
+	out += sprintf(out, "fatal_error:              %#04x\n",
+	               cam->params.status.fatalError);
+	out += sprintf(out, "cmd_error:                %#04x\n",
+	               cam->params.status.cmdError);
+	out += sprintf(out, "debug_flags:              %#04x\n",
+	               cam->params.status.debugFlags);
+	out += sprintf(out, "vp_status:                %#04x\n",
+	               cam->params.status.vpStatus);
+	out += sprintf(out, "error_code:               %#04x\n",
+	               cam->params.status.errorCode);
+	out += sprintf(out, "video_size:               %s\n",
+	               cam->params.format.videoSize == VIDEOSIZE_CIF ?
+		       "CIF " : "QCIF");
+	out += sprintf(out, "sub_sample:               %s\n",
+	               cam->params.format.subSample == SUBSAMPLE_420 ?
+		       "420" : "422");
+	out += sprintf(out, "yuv_order:                %s\n",
+	               cam->params.format.yuvOrder == YUVORDER_YUYV ?
+		       "YUYV" : "UYVY");
+	out += sprintf(out, "roi:                      (%3d, %3d) to (%3d, %3d)\n",
+	               cam->params.roi.colStart*8,
+	               cam->params.roi.rowStart*4,
+	               cam->params.roi.colEnd*8,
+	               cam->params.roi.rowEnd*4);
+	out += sprintf(out, "actual_fps:               %d\n", cam->fps);
+	out += sprintf(out, "transfer_rate:            %dkB/s\n",
+	               cam->transfer_rate);
+	
+	out += sprintf(out, "\nread-write\n");
+	out += sprintf(out, "-----------------------  current       min"
+	               "       max   default  comment\n");
+	out += sprintf(out, "brightness:             %8d  %8d  %8d  %8d\n",
+	               cam->params.colourParams.brightness, 0, 100, 50);
+	if(cam->params.version.firmwareVersion == 1 &&
+	   cam->params.version.firmwareRevision == 2) {
+		/* 1-02 firmware limits contrast to 80 */
+		tmp = 80;
+	} else {
+		tmp = 96;
+	}
+	out += sprintf(out, "contrast:               %8d  %8d  %8d  %8d"
+	               "  steps of 8\n",
+	               cam->params.colourParams.contrast, 0, tmp, 48);
+	out += sprintf(out, "saturation:             %8d  %8d  %8d  %8d\n",
+	               cam->params.colourParams.saturation, 0, 100, 50);
+	tmp = (25000+5000*cam->params.sensorFps.baserate)/
+	      (1<<cam->params.sensorFps.divisor);
+	out += sprintf(out, "sensor_fps:             %4d.%03d  %8d  %8d  %8d\n",
+	               tmp/1000, tmp%1000, 3, 30, 15);
+	out += sprintf(out, "stream_start_line:      %8d  %8d  %8d  %8d\n",
+	               2*cam->params.streamStartLine, 0,
+		       cam->params.format.videoSize == VIDEOSIZE_CIF ? 288:144,
+		       cam->params.format.videoSize == VIDEOSIZE_CIF ? 240:120);
+	out += sprintf(out, "ecp_timing:             %8s  %8s  %8s  %8s\n",
+	               cam->params.ecpTiming ? "slow" : "normal", "slow",
+		       "normal", "normal");
+
+	switch(cam->params.colourBalance.balanceMode) {
+	case 1:
+	  // FIXME case 3:
+		sprintf(tmpstr, "manual");
+		break;
+	case 2:
+		sprintf(tmpstr, "auto");
+		break;
+	default:
+		sprintf(tmpstr, "unknown");
+		break;
+	}
+	out += sprintf(out, "color_balance_mode:     %8s  %8s  %8s"
+		       "  %8s\n",  tmpstr, "manual", "auto", "auto");
+	out += sprintf(out, "red_gain:               %8d  %8d  %8d  %8d\n",
+	               cam->params.colourBalance.redGain, 0, 212, 32);
+	out += sprintf(out, "green_gain:             %8d  %8d  %8d  %8d\n",
+	               cam->params.colourBalance.greenGain, 0, 212, 6);
+	out += sprintf(out, "blue_gain:              %8d  %8d  %8d  %8d\n",
+	               cam->params.colourBalance.blueGain, 0, 212, 92);
+
+	if(cam->params.version.firmwareVersion == 1 &&
+	   cam->params.version.firmwareRevision == 2) {
+		/* 1-02 firmware limits gain to 2 */
+		sprintf(tmpstr, "%8d  %8d", 1, 2);
+	} else {
+		sprintf(tmpstr, "1,2,4,8");
+	}
+	if(cam->params.exposure.gainMode == 0) {
+		out += sprintf(out, "max_gain:                unknown  %18s"
+		               "  %8d\n", tmpstr, 2); 
+	} else {
+		out += sprintf(out, "max_gain:               %8d  %18s  %8d\n", 
+		               1<<(cam->params.exposure.gainMode-1), tmpstr, 2);
+	}
+	switch(cam->params.exposure.expMode) {
+	case 1:
+	case 3:
+		sprintf(tmpstr, "manual");
+		break;
+	case 2:
+		sprintf(tmpstr, "auto");
+		break;
+	default:
+		sprintf(tmpstr, "unknown");
+		break;
+	}
+	out += sprintf(out, "exposure_mode:          %8s  %8s  %8s"
+		       "  %8s\n",  tmpstr, "manual", "auto", "auto");
+	out += sprintf(out, "centre_weight:          %8s  %8s  %8s  %8s\n",
+	               (2-cam->params.exposure.centreWeight) ? "on" : "off",
+	               "off", "on", "on");
+	out += sprintf(out, "gain:                   %8d  %8d  max_gain  %8d  1,2,4,8 possible\n",
+	               1<<cam->params.exposure.gain, 1, 1);
+	if(cam->params.version.firmwareVersion == 1 &&
+	   cam->params.version.firmwareRevision == 2) {
+		/* 1-02 firmware limits fineExp to 127 */
+		tmp = 255;
+	} else {
+		tmp = 511;
+	}
+	out += sprintf(out, "fine_exp:               %8d  %8d  %8d  %8d\n",
+	               cam->params.exposure.fineExp*2, 0, tmp, 0);
+	if(cam->params.version.firmwareVersion == 1 &&
+	   cam->params.version.firmwareRevision == 2) {
+		/* 1-02 firmware limits coarseExpHi to 0 */
+		tmp = 255;
+	} else {
+		tmp = 65535;
+	}
+	out += sprintf(out, "coarse_exp:             %8d  %8d  %8d"
+		       "  %8d\n", cam->params.exposure.coarseExpLo+
+		       256*cam->params.exposure.coarseExpHi, 0, tmp, 185);
+	out += sprintf(out, "red_comp:               %8d  %8d  %8d  %8d\n",
+	               cam->params.exposure.redComp, 220, 255, 220);
+	out += sprintf(out, "green1_comp:            %8d  %8d  %8d  %8d\n",
+	               cam->params.exposure.green1Comp, 214, 255, 214);
+	out += sprintf(out, "green2_comp:            %8d  %8d  %8d  %8d\n",
+	               cam->params.exposure.green2Comp, 214, 255, 214);
+	out += sprintf(out, "blue_comp:              %8d  %8d  %8d  %8d\n",
+	               cam->params.exposure.blueComp, 230, 255, 230);
+	
+	out += sprintf(out, "apcor_gain1:            %#8x  %#8x  %#8x  %#8x\n",
+	               cam->params.apcor.gain1, 0, 0xff, 0x1c);
+	out += sprintf(out, "apcor_gain2:            %#8x  %#8x  %#8x  %#8x\n",
+	               cam->params.apcor.gain2, 0, 0xff, 0x1a);
+	out += sprintf(out, "apcor_gain4:            %#8x  %#8x  %#8x  %#8x\n",
+	               cam->params.apcor.gain4, 0, 0xff, 0x2d);
+	out += sprintf(out, "apcor_gain8:            %#8x  %#8x  %#8x  %#8x\n",
+	               cam->params.apcor.gain8, 0, 0xff, 0x2a);
+	out += sprintf(out, "vl_offset_gain1:        %8d  %8d  %8d  %8d\n",
+	               cam->params.vlOffset.gain1, 0, 255, 24);
+	out += sprintf(out, "vl_offset_gain2:        %8d  %8d  %8d  %8d\n",
+	               cam->params.vlOffset.gain2, 0, 255, 28);
+	out += sprintf(out, "vl_offset_gain4:        %8d  %8d  %8d  %8d\n",
+	               cam->params.vlOffset.gain4, 0, 255, 30);
+	out += sprintf(out, "vl_offset_gain8:        %8d  %8d  %8d  %8d\n",
+	               cam->params.vlOffset.gain8, 0, 255, 30);
+	out += sprintf(out, "flicker_control:        %8s  %8s  %8s  %8s\n",
+	               cam->params.flickerControl.flickerMode ? "on" : "off",
+		       "off", "on", "off");
+	out += sprintf(out, "mains_frequency:        %8d  %8d  %8d  %8d"
+	               " only 50/60\n",
+	               cam->mainsFreq ? 60 : 50, 50, 60, 50);
+	out += sprintf(out, "allowable_overexposure: %8d  %8d  %8d  %8d\n",
+	               cam->params.flickerControl.allowableOverExposure, 0,
+		       255, 0);
+	out += sprintf(out, "compression_mode:       ");
+	switch(cam->params.compression.mode) {
+	case CPIA_COMPRESSION_NONE:
+		out += sprintf(out, "%8s", "none");
+		break;
+	case CPIA_COMPRESSION_AUTO:
+		out += sprintf(out, "%8s", "auto");
+		break;
+	case CPIA_COMPRESSION_MANUAL:
+		out += sprintf(out, "%8s", "manual");
+		break;
+	default:
+		out += sprintf(out, "%8s", "unknown");
+		break;
+	}
+	out += sprintf(out, "    none,auto,manual      auto\n");
+	out += sprintf(out, "decimation:             %8s  %8s  %8s  %8s\n",
+        	       cam->params.compression.decimation == 
+		       DECIMATION_ENAB ? "on":"off", "off", "off",
+		       "off");
+	out += sprintf(out, "compression_target:    %9s %9s %9s %9s\n",
+	               cam->params.compressionTarget.frTargeting  == 
+		       CPIA_COMPRESSION_TARGET_FRAMERATE ?
+		       "framerate":"quality",
+		       "framerate", "quality", "quality");
+	out += sprintf(out, "target_framerate:       %8d  %8d  %8d  %8d\n",
+	               cam->params.compressionTarget.targetFR, 0, 30, 7);
+	out += sprintf(out, "target_quality:         %8d  %8d  %8d  %8d\n",
+	               cam->params.compressionTarget.targetQ, 0, 255, 10);
+	out += sprintf(out, "y_threshold:            %8d  %8d  %8d  %8d\n",
+	               cam->params.yuvThreshold.yThreshold, 0, 31, 15);
+	out += sprintf(out, "uv_threshold:           %8d  %8d  %8d  %8d\n",
+	               cam->params.yuvThreshold.uvThreshold, 0, 31, 15);
+	out += sprintf(out, "hysteresis:             %8d  %8d  %8d  %8d\n",
+	               cam->params.compressionParams.hysteresis, 0, 255, 3);
+	out += sprintf(out, "threshold_max:          %8d  %8d  %8d  %8d\n",
+	               cam->params.compressionParams.threshMax, 0, 255, 11);
+	out += sprintf(out, "small_step:             %8d  %8d  %8d  %8d\n",
+	               cam->params.compressionParams.smallStep, 0, 255, 1);
+	out += sprintf(out, "large_step:             %8d  %8d  %8d  %8d\n",
+	               cam->params.compressionParams.largeStep, 0, 255, 3);
+	out += sprintf(out, "decimation_hysteresis:  %8d  %8d  %8d  %8d\n",
+	               cam->params.compressionParams.decimationHysteresis,
+		       0, 255, 2);
+	out += sprintf(out, "fr_diff_step_thresh:    %8d  %8d  %8d  %8d\n",
+	               cam->params.compressionParams.frDiffStepThresh,
+		       0, 255, 5);
+	out += sprintf(out, "q_diff_step_thresh:     %8d  %8d  %8d  %8d\n",
+	               cam->params.compressionParams.qDiffStepThresh,
+		       0, 255, 3);
+	out += sprintf(out, "decimation_thresh_mod:  %8d  %8d  %8d  %8d\n",
+	               cam->params.compressionParams.decimationThreshMod,
+		       0, 255, 2);
+	
+	len = out - page;
+	len -= off;
+	if (len < count) {
+		*eof = 1;
+		if (len <= 0) return 0;
+	} else {
+		len = count;
+	}
+	*start = page + off;
+	return len;
+}
+
+static int cpia_write_proc(struct file *file, const char *buffer,
+                           unsigned long count, void *data)
+{
+	struct cam_data *cam = data;
+	struct cam_params new_params;
+	int retval, len, colon_found;
+	int size = count;
+	char *p;
+	unsigned long val;
+	u32 command_flags = 0;
+	u8 new_mains;
+	
+	if(down_interruptible(&cam->param_lock)) {
+		return -ERESTARTSYS;
+	}
+	
+	/*
+	 * Skip over leading whitespace
+	 */
+	while (count && isspace(*buffer)) {
+		--count;
+		++buffer;
+	}
+	
+	memcpy(&new_params, &cam->params, sizeof(struct cam_params));
+	new_mains = cam->mainsFreq;
+	
+#define MATCH(x) (len=strlen(x), len <= count && strncmp(buffer, x, len) == 0)
+#define FIRMWARE_VERSION(x,y) (new_params.version.firmwareVersion == (x) && \
+                               new_params.version.firmwareRevision == (y))
+#define VALUE \
+	simple_strtoul(buffer, &p, 0); \
+	if(p == buffer) { \
+		retval = -EINVAL; \
+	} else { \
+		count -= p-buffer; \
+		buffer = p; \
+	}
+#define FIND_VALUE \
+	buffer += len;\
+	count -= len; \
+	colon_found=0; \
+	while(count && (*buffer == ' ' || *buffer == '\t' || \
+	                (!colon_found && *buffer == ':'))) { \
+		if(*buffer == ':') colon_found = 1; \
+		--count; \
+		++buffer; \
+	} \
+	if(!count || !colon_found) { \
+		retval = -EINVAL; \
+	}
+#define FIND_END \
+	if(retval == 0) { \
+		while(count && isspace(*buffer) && *buffer != '\n'){ \
+			--count; \
+			++buffer; \
+		} \
+		if(count) { \
+			if(*buffer != '\n' && *buffer != ';') { \
+				retval = -EINVAL; \
+			} else { \
+				--count; \
+				++buffer; \
+			} \
+		} \
+	}
+	retval = 0;
+	while(count && !retval) {
+		if(MATCH("brightness")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				if(val <= 100)
+					new_params.colourParams.brightness=val;
+				else retval = -EINVAL;
+			}
+			command_flags |= COMMAND_SETCOLOURPARAMS;
+			FIND_END
+		} else if(MATCH("contrast")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				if(val <= 100) {
+					/* contrast is in steps of 8, so round*/
+					val = ((val + 3) / 8) * 8;
+					/* 1-02 firmware limits contrast to 80*/
+					if(FIRMWARE_VERSION(1,2) && val > 80)
+						val = 80;
+					new_params.colourParams.contrast = val;
+				} else retval = -EINVAL;
+			}
+			command_flags |= COMMAND_SETCOLOURPARAMS;
+			FIND_END
+		} else if(MATCH("saturation")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				if(val <= 100)
+					new_params.colourParams.saturation=val;
+				else retval = -EINVAL;
+			}
+			command_flags |= COMMAND_SETCOLOURPARAMS;
+			FIND_END
+		} else if(MATCH("sensor_fps")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				/* find values so that sensorFPS is minimized,
+				 * but >= val */
+				if(val > 30) {
+					retval = -EINVAL;
+				} else if(val > 25) {
+					new_params.sensorFps.divisor = 0;
+					new_params.sensorFps.baserate = 1;
+				} else if(val > 15) {
+					new_params.sensorFps.divisor = 0;
+					new_params.sensorFps.baserate = 0;
+				} else if(val > 12) {
+					new_params.sensorFps.divisor = 1;
+					new_params.sensorFps.baserate = 1;
+				} else if(val > 7) {
+					new_params.sensorFps.divisor = 1;
+					new_params.sensorFps.baserate = 0;
+				} else if(val > 6) {
+					new_params.sensorFps.divisor = 2;
+					new_params.sensorFps.baserate = 1;
+				} else if(val > 3) {
+					new_params.sensorFps.divisor = 2;
+					new_params.sensorFps.baserate = 0;
+				} else {
+					new_params.sensorFps.divisor = 3;
+					/* Either base rate would work here */
+					new_params.sensorFps.baserate = 1;
+				}
+				new_params.flickerControl.coarseJump = 
+					flicker_jumps[new_mains]
+					[new_params.sensorFps.baserate]
+					[new_params.sensorFps.divisor];
+				if(new_params.flickerControl.flickerMode)
+					command_flags |= COMMAND_SETFLICKERCTRL;
+			}
+			command_flags |= COMMAND_SETSENSORFPS;
+			FIND_END
+		} else if(MATCH("stream_start_line")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				int max_line = 288;
+				if(new_params.format.videoSize==VIDEOSIZE_QCIF)
+					max_line = 144;
+				if(val <= max_line)
+					new_params.streamStartLine = val/2;
+				else retval = -EINVAL;
+			}
+			FIND_END
+		} else if(MATCH("ecp_timing")) {
+			FIND_VALUE
+			if(!retval && MATCH("normal")) {
+				buffer += len;
+				count -= len;
+				new_params.ecpTiming = 0;
+			} else if(!retval && MATCH("slow")) {
+				buffer += len;
+				count -= len;
+				new_params.ecpTiming = 1;
+			} else {
+				retval = -EINVAL;
+			}
+			command_flags |= COMMAND_SETECPTIMING;
+			FIND_END
+		} else if(MATCH("color_balance_mode")) {
+			FIND_VALUE
+			if(!retval && MATCH("manual")) {
+				buffer += len;
+				count -= len;
+				new_params.colourBalance.balanceMode=1;
+			} else if(!retval && MATCH("auto")) {
+				buffer += len;
+				count -= len;
+				new_params.colourBalance.balanceMode=2;
+			} else {
+				retval = -EINVAL;
+			}
+			command_flags |= COMMAND_SETCOLOURBALANCE;
+			FIND_END
+		} else if(MATCH("red_gain")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				if(val <= 212)
+					new_params.colourBalance.redGain = val;
+				else retval = -EINVAL;
+			}
+			command_flags |= COMMAND_SETCOLOURBALANCE;
+			FIND_END
+		} else if(MATCH("green_gain")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				if(val <= 212)
+					new_params.colourBalance.greenGain=val;
+				else retval = -EINVAL;
+			}
+			command_flags |= COMMAND_SETCOLOURBALANCE;
+			FIND_END
+		} else if(MATCH("blue_gain")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				if(val <= 212)
+					new_params.colourBalance.blueGain = val;
+				else retval = -EINVAL;
+			}
+			command_flags |= COMMAND_SETCOLOURBALANCE;
+			FIND_END
+		} else if(MATCH("max_gain")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				/* 1-02 firmware limits gain to 2 */
+				if(FIRMWARE_VERSION(1,2) && val > 2)
+					val = 2;
+				switch(val) {
+				case 1:
+					new_params.exposure.gainMode = 1;
+					break;
+				case 2:
+					new_params.exposure.gainMode = 2;
+					break;
+				case 4:
+					new_params.exposure.gainMode = 3;
+					break;
+				case 8:
+					new_params.exposure.gainMode = 4;
+					break;
+				default:
+					retval = -EINVAL;
+					break;
+				}
+			}
+			command_flags |= COMMAND_SETEXPOSURE;
+			FIND_END
+		} else if(MATCH("exposure_mode")) {
+			FIND_VALUE
+			if(!retval && MATCH("auto")) {
+				buffer += len;
+				count -= len;
+				new_params.exposure.expMode = 2;
+			} else if(!retval && MATCH("manual")) {
+				buffer += len;
+				count -= len;
+				if(new_params.exposure.expMode == 2)
+					new_params.exposure.expMode = 3;
+				new_params.flickerControl.flickerMode = 0;
+				command_flags |= COMMAND_SETFLICKERCTRL;
+			} else {
+				retval = -EINVAL;
+			}
+			command_flags |= COMMAND_SETEXPOSURE;
+			FIND_END
+		} else if(MATCH("centre_weight")) {
+			FIND_VALUE
+			if(!retval && MATCH("on")) {
+				buffer += len;
+				count -= len;
+				new_params.exposure.centreWeight = 1;
+			} else if(!retval && MATCH("off")) {
+				buffer += len;
+				count -= len;
+				new_params.exposure.centreWeight = 2;
+			} else {
+				retval = -EINVAL;
+			}
+			command_flags |= COMMAND_SETEXPOSURE;
+			FIND_END
+		} else if(MATCH("gain")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				switch(val) {
+				case 1:
+					new_params.exposure.gain = 0;
+					new_params.exposure.expMode = 1;
+					new_params.flickerControl.flickerMode = 0;
+					command_flags |= COMMAND_SETFLICKERCTRL;
+					break;
+				case 2:
+					new_params.exposure.gain = 1;
+					new_params.exposure.expMode = 1;
+					new_params.flickerControl.flickerMode = 0;
+					command_flags |= COMMAND_SETFLICKERCTRL;
+					break;
+				case 4:
+					new_params.exposure.gain = 2;
+					new_params.exposure.expMode = 1;
+					new_params.flickerControl.flickerMode = 0;
+					command_flags |= COMMAND_SETFLICKERCTRL;
+					break;
+				case 8:
+					new_params.exposure.gain = 3;
+					new_params.exposure.expMode = 1;
+					new_params.flickerControl.flickerMode = 0;
+					command_flags |= COMMAND_SETFLICKERCTRL;
+					break;
+				default:
+					retval = -EINVAL;
+					break;
+				}
+				command_flags |= COMMAND_SETEXPOSURE;
+				if(new_params.exposure.gain >
+				   new_params.exposure.gainMode-1)
+					retval = -EINVAL;
+			}
+			FIND_END
+		} else if(MATCH("fine_exp")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				if(val < 256) {
+					/* 1-02 firmware limits fineExp to 127*/
+					if(FIRMWARE_VERSION(1,2) && val > 127)
+						val = 127;
+					new_params.exposure.fineExp = val;
+					new_params.exposure.expMode = 1;
+					command_flags |= COMMAND_SETEXPOSURE;
+					new_params.flickerControl.flickerMode = 0;
+					command_flags |= COMMAND_SETFLICKERCTRL;
+				} else retval = -EINVAL;
+			}
+			FIND_END
+		} else if(MATCH("coarse_exp")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				if(val < 65536) {
+					/* 1-02 firmware limits
+					 * coarseExp to 255 */
+					if(FIRMWARE_VERSION(1,2) && val > 255)
+						val = 255;
+					new_params.exposure.coarseExpLo =
+						val & 0xff;
+					new_params.exposure.coarseExpHi =
+						val >> 8;
+					new_params.exposure.expMode = 1;
+					command_flags |= COMMAND_SETEXPOSURE;
+					new_params.flickerControl.flickerMode = 0;
+					command_flags |= COMMAND_SETFLICKERCTRL;
+				} else retval = -EINVAL;
+			}
+			FIND_END
+		} else if(MATCH("red_comp")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				if(val >= 220 && val <= 255) {
+					new_params.exposure.redComp = val;
+					command_flags |= COMMAND_SETEXPOSURE;
+				} else retval = -EINVAL;
+			}
+			FIND_END
+		} else if(MATCH("green1_comp")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				if(val >= 214 && val <= 255) {
+					new_params.exposure.green1Comp = val;
+					command_flags |= COMMAND_SETEXPOSURE;
+				} else retval = -EINVAL;
+			}
+			FIND_END
+		} else if(MATCH("green2_comp")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				if(val >= 214 && val <= 255) {
+					new_params.exposure.green2Comp = val;
+					command_flags |= COMMAND_SETEXPOSURE;
+				} else retval = -EINVAL;
+			}
+			FIND_END
+		} else if(MATCH("blue_comp")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				if(val >= 230 && val <= 255) {
+					new_params.exposure.blueComp = val;
+					command_flags |= COMMAND_SETEXPOSURE;
+				} else retval = -EINVAL;
+			}
+			FIND_END
+		} else if(MATCH("apcor_gain1")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				command_flags |= COMMAND_SETAPCOR;
+				if(val <= 0xff) new_params.apcor.gain1 = val;
+				else retval = -EINVAL;
+			}
+			FIND_END
+		} else if(MATCH("apcor_gain2")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				command_flags |= COMMAND_SETAPCOR;
+				if(val <= 0xff) new_params.apcor.gain2 = val;
+				else retval = -EINVAL;
+			}
+			FIND_END
+		} else if(MATCH("apcor_gain4")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				command_flags |= COMMAND_SETAPCOR;
+				if(val <= 0xff) new_params.apcor.gain4 = val;
+				else retval = -EINVAL;
+			}
+			FIND_END
+		} else if(MATCH("apcor_gain8")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				command_flags |= COMMAND_SETAPCOR;
+				if(val <= 0xff) new_params.apcor.gain8 = val;
+				else retval = -EINVAL;
+			}
+			FIND_END
+		} else if(MATCH("vl_offset_gain1")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				if(val <= 0xff) new_params.vlOffset.gain1 = val;
+				else retval = -EINVAL;
+			}
+			FIND_END
+			command_flags |= COMMAND_SETVLOFFSET;
+		} else if(MATCH("vl_offset_gain2")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				if(val <= 0xff) new_params.vlOffset.gain2 = val;
+				else retval = -EINVAL;
+			}
+			FIND_END
+			command_flags |= COMMAND_SETVLOFFSET;
+		} else if(MATCH("vl_offset_gain4")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				if(val <= 0xff) new_params.vlOffset.gain4 = val;
+				else retval = -EINVAL;
+			}
+			FIND_END
+			command_flags |= COMMAND_SETVLOFFSET;
+		} else if(MATCH("vl_offset_gain8")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				if(val <= 0xff) new_params.vlOffset.gain8 = val;
+				else retval = -EINVAL;
+			}
+			FIND_END
+			command_flags |= COMMAND_SETVLOFFSET;
+		} else if(MATCH("flicker_control")) {
+			FIND_VALUE
+			if(!retval && MATCH("on")) {
+				buffer += len;
+				count -= len;
+				new_params.flickerControl.flickerMode = 1;
+				new_params.exposure.expMode = 2;
+				command_flags |= COMMAND_SETEXPOSURE;
+			} else if(!retval && MATCH("off")) {
+				buffer += len;
+				count -= len;
+				new_params.flickerControl.flickerMode = 0;
+			} else {
+				retval = -EINVAL;
+			}
+			command_flags |= COMMAND_SETFLICKERCTRL;
+			FIND_END
+		} else if(MATCH("mains_frequency")) {
+			FIND_VALUE
+			if(!retval && MATCH("50")) {
+				buffer += len;
+				count -= len;
+				new_mains = 0;
+				new_params.flickerControl.coarseJump = 
+					flicker_jumps[new_mains]
+					[new_params.sensorFps.baserate]
+					[new_params.sensorFps.divisor];
+				if(new_params.flickerControl.flickerMode)
+					command_flags |= COMMAND_SETFLICKERCTRL;
+			} else if(!retval && MATCH("60")) {
+				buffer += len;
+				count -= len;
+				new_mains = 1;
+				new_params.flickerControl.coarseJump = 
+					flicker_jumps[new_mains]
+					[new_params.sensorFps.baserate]
+					[new_params.sensorFps.divisor];
+				if(new_params.flickerControl.flickerMode)
+					command_flags |= COMMAND_SETFLICKERCTRL;
+			} else {
+				retval = -EINVAL;
+			}
+			FIND_END
+		} else if(MATCH("allowable_overexposure")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				if(val <= 0xff) {
+					new_params.flickerControl.
+						allowableOverExposure = val;
+					command_flags |= COMMAND_SETFLICKERCTRL;
+				} else retval = -EINVAL;
+			}
+			FIND_END
+		} else if(MATCH("compression_mode")) {
+			FIND_VALUE
+			if(!retval && MATCH("none")) {
+				buffer += len;
+				count -= len;
+				new_params.compression.mode =
+					CPIA_COMPRESSION_NONE;
+			} else if(!retval && MATCH("auto")) {
+				buffer += len;
+				count -= len;
+				new_params.compression.mode =
+					CPIA_COMPRESSION_AUTO;
+			} else if(!retval && MATCH("manual")) {
+				buffer += len;
+				count -= len;
+				new_params.compression.mode =
+					CPIA_COMPRESSION_MANUAL;
+			} else {
+				retval = -EINVAL;
+			}
+			command_flags |= COMMAND_SETCOMPRESSION;
+			FIND_END
+		} else if(MATCH("decimation")) {
+			FIND_VALUE
+			if(!retval && MATCH("off")) {
+				buffer += len;
+				count -= len;
+				new_params.compression.decimation = 0;
+			} else {
+				retval = -EINVAL;
+			}
+			command_flags |= COMMAND_SETCOMPRESSION;
+			FIND_END
+		} else if(MATCH("compression_target")) {
+			FIND_VALUE
+			if(!retval && MATCH("quality")) {
+				buffer += len;
+				count -= len;
+				new_params.compressionTarget.frTargeting = 
+					CPIA_COMPRESSION_TARGET_QUALITY;
+			} else if(!retval && MATCH("framerate")) {
+				buffer += len;
+				count -= len;
+				new_params.compressionTarget.frTargeting = 
+					CPIA_COMPRESSION_TARGET_FRAMERATE;
+			} else {
+				retval = -EINVAL;
+			}
+			command_flags |= COMMAND_SETCOMPRESSIONTARGET;
+			FIND_END
+		} else if(MATCH("target_framerate")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval)
+				new_params.compressionTarget.targetFR = val;
+			command_flags |= COMMAND_SETCOMPRESSIONTARGET;
+			FIND_END
+		} else if(MATCH("target_quality")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) new_params.compressionTarget.targetQ = val;
+			command_flags |= COMMAND_SETCOMPRESSIONTARGET;
+			FIND_END
+		} else if(MATCH("y_threshold")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				if(val < 32)
+					new_params.yuvThreshold.yThreshold=val;
+				else retval = -EINVAL;
+			}
+			command_flags |= COMMAND_SETYUVTHRESH;
+			FIND_END
+		} else if(MATCH("uv_threshold")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				if(val < 32)
+					new_params.yuvThreshold.uvThreshold=val;
+				else retval = -EINVAL;
+			}
+			command_flags |= COMMAND_SETYUVTHRESH;
+			FIND_END
+		} else if(MATCH("hysteresis")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				if(retval <= 0xff)
+				    new_params.compressionParams.hysteresis=val;
+				else retval = -EINVAL;
+			}
+			command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
+			FIND_END
+		} else if(MATCH("threshold_max")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				if(retval <= 0xff)
+				    new_params.compressionParams.threshMax=val;
+				else retval = -EINVAL;
+			}
+			command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
+			FIND_END
+		} else if(MATCH("small_step")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				if(retval <= 0xff)
+				    new_params.compressionParams.smallStep=val;
+				else retval = -EINVAL;
+			}
+			command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
+			FIND_END
+		} else if(MATCH("large_step")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				if(retval <= 0xff)
+				    new_params.compressionParams.largeStep=val;
+				else retval = -EINVAL;
+			}
+			command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
+			FIND_END
+		} else if(MATCH("decimation_hysteresis")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				if(retval <= 0xff)
+				    new_params.compressionParams.
+				        decimationHysteresis = val;
+				else retval = -EINVAL;
+			}
+			command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
+			FIND_END
+		} else if(MATCH("fr_diff_step_thresh")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				if(retval <= 0xff)
+				    new_params.compressionParams.
+				        frDiffStepThresh = val;
+				else retval = -EINVAL;
+			}
+			command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
+			FIND_END
+		} else if(MATCH("q_diff_step_thresh")) {
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				if(retval <= 0xff)
+				    new_params.compressionParams.
+				        qDiffStepThresh = val;
+				else retval = -EINVAL;
+			command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
+			FIND_END
+		} else if(MATCH("decimation_thresh_mod")) {
+			}
+			FIND_VALUE
+			if(!retval) { val = VALUE }
+			if(!retval) {
+				if(retval <= 0xff)
+				    new_params.compressionParams.
+				        decimationThreshMod = val;
+				else retval = -EINVAL;
+			}
+			command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
+			FIND_END
+		} else {
+			retval = -EINVAL;
+		}
+	}
+#undef MATCH	
+#undef FIRMWARE_VERSION
+#undef VALUE
+#undef FIND_VALUE
+#undef FIND_END
+	if(retval == 0) {
+		if(command_flags & COMMAND_SETCOLOURPARAMS) {
+			/* Adjust cam->vp to reflect these changes */
+			cam->vp.brightness =
+				new_params.colourParams.brightness*65535/100;
+			cam->vp.contrast =
+				new_params.colourParams.contrast*65535/100;
+			cam->vp.colour =
+				new_params.colourParams.saturation*65535/100;
+		}
+		
+		memcpy(&cam->params, &new_params, sizeof(struct cam_params));
+		cam->mainsFreq = new_mains;
+		cam->cmd_queue |= command_flags;
+		retval = size;
+	} else {
+		DBG("error: %d\n", retval);
+	}
+	
+	up(&cam->param_lock);
+	
+	return retval;
+}
+
+static void create_proc_cpia_cam(struct cam_data *cam)
+{
+	char name[7];
+	struct proc_dir_entry *ent;
+	
+	if(cpia_proc_root == NULL || cam == NULL) {
+		return;
+	}
+	sprintf(name, "video%d", cam->vdev.minor);
+	
+	ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, cpia_proc_root);
+	if (!ent) return;
+	ent->data = cam;
+	ent->read_proc = cpia_read_proc;
+	ent->write_proc = cpia_write_proc;
+	ent->size = 3623;
+	cam->proc_entry = ent;
+}
+
+static void destroy_proc_cpia_cam(struct cam_data *cam)
+{
+	char name[7];
+	
+	if(cam->proc_entry == NULL) return;
+	
+	sprintf(name, "video%d", cam->vdev.minor);
+	remove_proc_entry(name, cpia_proc_root);
+}
+
+static void proc_cpia_create(void)
+{
+	cpia_proc_root = create_proc_entry("cpia", S_IFDIR, 0);
+}
+
+#ifdef MODULE
+static void proc_cpia_destroy(void)
+{
+	remove_proc_entry("cpia", 0);
+}
+#endif
+
+/* ----------------------- debug functions ---------------------- */
+
+#define printstatus(cam) \
+  DBG("%02x %02x %02x %02x %02x %02x %02x %02x\n",\
+	cam->params.status.systemState, cam->params.status.grabState, \
+	cam->params.status.streamState, cam->params.status.fatalError, \
+	cam->params.status.cmdError, cam->params.status.debugFlags, \
+	cam->params.status.vpStatus, cam->params.status.errorCode);
+
+/* ----------------------- v4l helpers -------------------------- */
+
+/* supported frame palettes and depths */
+static inline int valid_mode(u16 palette, u16 depth)
+{
+	return (palette == VIDEO_PALETTE_GREY && depth == 8) ||
+	       (palette == VIDEO_PALETTE_RGB555 && depth == 16) ||
+	       (palette == VIDEO_PALETTE_RGB565 && depth == 16) ||
+	       (palette == VIDEO_PALETTE_RGB24 && depth == 24) ||
+	       (palette == VIDEO_PALETTE_RGB32 && depth == 32) ||
+	       (palette == VIDEO_PALETTE_YUV422 && depth == 16) ||
+	       (palette == VIDEO_PALETTE_YUYV && depth == 16) ||
+	       (palette == VIDEO_PALETTE_UYVY && depth == 16);
+}
+
+static int match_videosize( int width, int height )
+{
+	/* return the best match, where 'best' is as always
+	 * the largest that is not bigger than what is requested. */
+	if(width>=352 && height>=288) {
+		return VIDEOSIZE_352_288; /* CIF */
+	}
+	if(width>=320 && height>=240) {
+		return VIDEOSIZE_320_240; /* SIF */
+	}
+	if(width>=288 && height>=216) {
+		return VIDEOSIZE_288_216;
+	}
+	if(width>=256 && height>=192) {
+		return VIDEOSIZE_256_192;
+	}
+	if(width>=224 && height>=168) {
+		return VIDEOSIZE_224_168;
+	}
+	if(width>=192 && height>=144) {
+		return VIDEOSIZE_192_144;
+	}
+	if(width>=176 && height>=144) {
+		return VIDEOSIZE_176_144; /* QCIF */
+	}
+	if(width>=160 && height>=120) {
+		return VIDEOSIZE_160_120; /* QSIF */
+	}
+	if(width>=128 && height>=96) {
+		return VIDEOSIZE_128_96;
+	}
+	if(width>=64 && height>=48) {
+		return VIDEOSIZE_64_48;
+	}
+	if(width>=48 && height>=48) {
+		return VIDEOSIZE_48_48;
+	}
+
+	return -1;
+}
+
+/* these are the capture sizes we support */
+static void set_vw_size(struct cam_data *cam)
+{
+	/* the col/row/start/end values are the result of simple math    */
+	/* study the SetROI-command in cpia developers guide p 2-22      */
+	/* streamStartLine is set to the recommended value in the cpia   */
+	/*  developers guide p 3-37                                      */
+	switch(cam->video_size) {
+	case VIDEOSIZE_CIF:
+		cam->vw.width = 352;
+		cam->vw.height = 288;
+		cam->params.format.videoSize=VIDEOSIZE_CIF;
+		cam->params.roi.colStart=0;
+		cam->params.roi.colEnd=44;
+		cam->params.roi.rowStart=0;
+		cam->params.roi.rowEnd=72;
+		cam->params.streamStartLine = 120;
+		break;
+	case VIDEOSIZE_SIF:
+		cam->vw.width = 320;
+		cam->vw.height = 240;
+		cam->params.format.videoSize=VIDEOSIZE_CIF;
+		cam->params.roi.colStart=2;
+		cam->params.roi.colEnd=42;
+		cam->params.roi.rowStart=6;
+		cam->params.roi.rowEnd=66;
+		cam->params.streamStartLine = 120;
+		break;
+	case VIDEOSIZE_288_216:
+		cam->vw.width = 288;
+		cam->vw.height = 216;
+		cam->params.format.videoSize=VIDEOSIZE_CIF;
+		cam->params.roi.colStart=4;
+		cam->params.roi.colEnd=40;
+		cam->params.roi.rowStart=9;
+		cam->params.roi.rowEnd=63;
+		cam->params.streamStartLine = 120;
+		break;
+	case VIDEOSIZE_256_192:
+		cam->vw.width = 256;
+		cam->vw.height = 192;
+		cam->params.format.videoSize=VIDEOSIZE_CIF;
+		cam->params.roi.colStart=6;
+		cam->params.roi.colEnd=38;
+		cam->params.roi.rowStart=12;
+		cam->params.roi.rowEnd=60;
+		cam->params.streamStartLine = 120;
+		break;
+	case VIDEOSIZE_224_168:
+		cam->vw.width = 224;
+		cam->vw.height = 168;
+		cam->params.format.videoSize=VIDEOSIZE_CIF;
+		cam->params.roi.colStart=8;
+		cam->params.roi.colEnd=36;
+		cam->params.roi.rowStart=15;
+		cam->params.roi.rowEnd=57;
+		cam->params.streamStartLine = 120;
+		break;
+	case VIDEOSIZE_192_144:
+		cam->vw.width = 192;
+		cam->vw.height = 144;
+		cam->params.format.videoSize=VIDEOSIZE_CIF;
+		cam->params.roi.colStart=10;
+		cam->params.roi.colEnd=34;
+		cam->params.roi.rowStart=18;
+		cam->params.roi.rowEnd=54;
+		cam->params.streamStartLine = 120;
+		break;
+	case VIDEOSIZE_QCIF:
+		cam->vw.width = 176;
+		cam->vw.height = 144;
+		cam->params.format.videoSize=VIDEOSIZE_QCIF;
+		cam->params.roi.colStart=0;
+		cam->params.roi.colEnd=22;
+		cam->params.roi.rowStart=0;
+		cam->params.roi.rowEnd=36;
+		cam->params.streamStartLine = 60;
+		break;
+	case VIDEOSIZE_QSIF:
+		cam->vw.width = 160;
+		cam->vw.height = 120;
+		cam->params.format.videoSize=VIDEOSIZE_QCIF;
+		cam->params.roi.colStart=1;
+		cam->params.roi.colEnd=21;
+		cam->params.roi.rowStart=3;
+		cam->params.roi.rowEnd=33;
+		cam->params.streamStartLine = 60;
+		break;
+	case VIDEOSIZE_128_96:
+		cam->vw.width = 128;
+		cam->vw.height = 96;
+		cam->params.format.videoSize=VIDEOSIZE_QCIF;
+		cam->params.roi.colStart=3;
+		cam->params.roi.colEnd=19;
+		cam->params.roi.rowStart=6;
+		cam->params.roi.rowEnd=30;
+		cam->params.streamStartLine = 60;
+		break;
+	case VIDEOSIZE_64_48:
+		cam->vw.width = 64;
+		cam->vw.height = 48;
+		cam->params.format.videoSize=VIDEOSIZE_QCIF;
+		cam->params.roi.colStart=7;
+		cam->params.roi.colEnd=15;
+		cam->params.roi.rowStart=12;
+		cam->params.roi.rowEnd=24;
+		cam->params.streamStartLine = 60;
+		break;
+	case VIDEOSIZE_48_48:
+		cam->vw.width = 48;
+		cam->vw.height = 48;
+		cam->params.format.videoSize=VIDEOSIZE_QCIF;
+		cam->params.roi.colStart=8;
+		cam->params.roi.colEnd=14;
+		cam->params.roi.rowStart=6;
+		cam->params.roi.rowEnd=30;
+		cam->params.streamStartLine = 60;
+		break;
+	default:
+		LOG("bad videosize value: %d\n", cam->video_size);
+	}
+
+	return;
+}
+
+static int allocate_frame_buf(struct cam_data *cam) {
+	int i;
+
+	cam->frame_buf = rvmalloc(FRAME_NUM*CPIA_MAX_FRAME_SIZE);
+	if (!cam->frame_buf) {
+		return -ENOBUFS;
+	}
+	for( i=0; i<FRAME_NUM; i++ ) {
+		cam->frame[i].data = cam->frame_buf + i*CPIA_MAX_FRAME_SIZE;
+	}
+	return 0;
+}
+
+static int free_frame_buf(struct cam_data *cam) {
+	int i;
+	
+	rvfree(cam->frame_buf, FRAME_NUM*CPIA_MAX_FRAME_SIZE);
+	cam->frame_buf=0;
+	for( i=0; i<FRAME_NUM; i++ ) {
+		cam->frame[i].data = NULL;
+	}
+	return 0;
+}
+
+
+static void inline free_frames(struct cpia_frame frame[FRAME_NUM])
+{
+	int i;
+	for( i=0; i<FRAME_NUM; i++ ) {
+		frame[i].state=FRAME_UNUSED;
+	}
+	return;
+}
+
+/**********************************************************************
+ *
+ * General functions
+ *
+ **********************************************************************/
+/* send an arbitrary command to the camera */
+static int do_command(struct cam_data *cam, u16 command, u8 a, u8 b, u8 c, u8 d)
+{
+	int retval, datasize;
+	u8 cmd[8], data[8];
+
+	switch(command) {
+	case CPIA_COMMAND_GetCPIAVersion:
+	case CPIA_COMMAND_GetPnPID:
+	case CPIA_COMMAND_GetCameraStatus:
+	case CPIA_COMMAND_GetVPVersion:
+		datasize=8;
+		break;
+	case CPIA_COMMAND_GetColourParams:
+	case CPIA_COMMAND_GetColourBalance:
+	case CPIA_COMMAND_GetExposure:
+		down(&cam->param_lock);
+		datasize=8;
+		break;
+	default:
+		datasize=0;
+		break;
+	}
+
+	cmd[0] = command>>8;
+	cmd[1] = command&0xff;
+	cmd[2] = a;
+	cmd[3] = b;
+	cmd[4] = c;
+	cmd[5] = d;
+	cmd[6] = datasize;
+	cmd[7] = 0;
+
+	retval = cam->ops->transferCmd(cam->lowlevel_data, cmd, data);
+	if(retval) {
+		LOG("%x - failed\n", command);
+	} else {
+		switch(command) {
+		case CPIA_COMMAND_GetCPIAVersion:
+			cam->params.version.firmwareVersion = data[0];
+			cam->params.version.firmwareRevision = data[1];
+			cam->params.version.vcVersion = data[2];
+			cam->params.version.vcRevision = data[3];
+			break;
+		case CPIA_COMMAND_GetPnPID:
+			cam->params.pnpID.vendor = data[0]+(((u16)data[1])<<8);
+			cam->params.pnpID.product = data[2]+(((u16)data[3])<<8);
+			cam->params.pnpID.deviceRevision =
+				data[4]+(((u16)data[5])<<8);
+			break;
+		case CPIA_COMMAND_GetCameraStatus:
+			cam->params.status.systemState = data[0];
+			cam->params.status.grabState = data[1];
+			cam->params.status.streamState = data[2];
+			cam->params.status.fatalError = data[3];
+			cam->params.status.cmdError = data[4];
+			cam->params.status.debugFlags = data[5];
+			cam->params.status.vpStatus = data[6];
+			cam->params.status.errorCode = data[7];
+			break;
+		case CPIA_COMMAND_GetVPVersion:
+			cam->params.vpVersion.vpVersion = data[0];
+			cam->params.vpVersion.vpRevision = data[1];
+			cam->params.vpVersion.cameraHeadID =
+				data[2]+(((u16)data[3])<<8);
+			break;
+		case CPIA_COMMAND_GetColourParams:
+			cam->params.colourParams.brightness = data[0];
+			cam->params.colourParams.contrast = data[1];
+			cam->params.colourParams.saturation = data[2];
+			up(&cam->param_lock);
+			break;
+		case CPIA_COMMAND_GetColourBalance:
+			cam->params.colourBalance.redGain = data[0];
+			cam->params.colourBalance.greenGain = data[1];
+			cam->params.colourBalance.blueGain = data[2];
+			up(&cam->param_lock);
+			break;
+		case CPIA_COMMAND_GetExposure:
+			cam->params.exposure.gain = data[0];
+			cam->params.exposure.fineExp = data[1];
+			cam->params.exposure.coarseExpLo = data[2];
+			cam->params.exposure.coarseExpHi = data[3];
+			cam->params.exposure.redComp = data[4];
+			cam->params.exposure.green1Comp = data[5];
+			cam->params.exposure.green2Comp = data[6];
+			cam->params.exposure.blueComp = data[7];
+			up(&cam->param_lock);
+			break;
+		default:
+			break;
+		}
+	}
+	return retval;
+}
+
+/* send a command  to the camera with an additional data transaction */
+static int do_command_extended(struct cam_data *cam, u16 command,
+                               u8 a, u8 b, u8 c, u8 d,
+                               u8 e, u8 f, u8 g, u8 h,
+                               u8 i, u8 j, u8 k, u8 l)
+{
+	int retval;
+	u8 cmd[8], data[8];
+	cmd[0] = command>>8;
+	cmd[1] = command&0xff;
+	cmd[2] = a;
+	cmd[3] = b;
+	cmd[4] = c;
+	cmd[5] = d;
+	cmd[6] = 8;
+	cmd[7] = 0;
+	data[0] = e;
+	data[1] = f;
+	data[2] = g;
+	data[3] = h;
+	data[4] = i;
+	data[5] = j;
+	data[6] = k;
+	data[7] = l;
+
+	retval = cam->ops->transferCmd(cam->lowlevel_data, cmd, data);
+	if(retval) {
+		LOG("%x - failed\n", command);
+	}
+	return retval;
+}
+
+/**********************************************************************
+ *
+ * Colorspace conversion
+ *
+ **********************************************************************/
+#define LIMIT(x) ((((x)>0xffffff)?0xff0000:(((x)<=0xffff)?0:(x)&0xff0000))>>16)
+
+static int yuvconvert(unsigned char *yuv, unsigned char *rgb, int out_fmt,
+                      int in_uyvy)
+{
+	int y, u, v, r, g, b, y1;
+	switch(out_fmt) {
+	case VIDEO_PALETTE_RGB555:
+	case VIDEO_PALETTE_RGB565:
+	case VIDEO_PALETTE_RGB24:
+	case VIDEO_PALETTE_RGB32:
+		if(in_uyvy) {
+			u = *yuv++ - 128;
+			y = (*yuv++ - 16) * 76310;
+			v = *yuv++ - 128;
+			y1 = (*yuv - 16) * 76310;
+		} else {
+			y = (*yuv++ - 16) * 76310;
+			u = *yuv++ - 128;
+			y1 = (*yuv++ - 16) * 76310;
+			v = *yuv - 128;
+		}
+		r = 104635 * v;
+		g = -25690 * u + -53294 * v;
+		b = 132278 * u;
+		break;
+	default:
+		y = *yuv++;
+		u = *yuv++;
+		y1 = *yuv++;
+		v = *yuv;
+		/* Just to avoid compiler warnings */
+		r = 0;
+		g = 0;
+		b = 0;
+		break;
+	}
+	switch(out_fmt) {
+	case VIDEO_PALETTE_RGB555:
+		*rgb++ = ((LIMIT(g+y) & 0xf8) << 2) | (LIMIT(b+y) >> 3);
+		*rgb++ = ((LIMIT(r+y) & 0xf8) >> 1) | (LIMIT(g+y) >> 6);
+		*rgb++ = ((LIMIT(g+y1) & 0xf8) << 2) | (LIMIT(b+y1) >> 3);
+		*rgb = ((LIMIT(r+y1) & 0xf8) >> 1) | (LIMIT(g+y1) >> 6);
+		return 4;
+	case VIDEO_PALETTE_RGB565:
+		*rgb++ = ((LIMIT(g+y) & 0xfc) << 3) | (LIMIT(b+y) >> 3);
+		*rgb++ = (LIMIT(r+y) & 0xf8) | (LIMIT(g+y) >> 5);
+		*rgb++ = ((LIMIT(g+y1) & 0xfc) << 3) | (LIMIT(b+y1) >> 3);
+		*rgb = (LIMIT(r+y1) & 0xf8) | (LIMIT(g+y1) >> 5);
+		return 4;
+	case VIDEO_PALETTE_RGB24:
+		*rgb++ = LIMIT(b+y);
+		*rgb++ = LIMIT(g+y);
+		*rgb++ = LIMIT(r+y);
+		*rgb++ = LIMIT(b+y1);
+		*rgb++ = LIMIT(g+y1);
+		*rgb = LIMIT(r+y1);
+		return 6;
+	case VIDEO_PALETTE_RGB32:
+		*rgb++ = LIMIT(b+y);
+		*rgb++ = LIMIT(g+y);
+		*rgb++ = LIMIT(r+y);
+		rgb++;
+		*rgb++ = LIMIT(b+y1);
+		*rgb++ = LIMIT(g+y1);
+		*rgb = LIMIT(r+y1);
+		return 8;
+	case VIDEO_PALETTE_GREY:
+		*rgb++ = y;
+		*rgb = y1;
+		return 2;
+	case VIDEO_PALETTE_YUV422:
+	case VIDEO_PALETTE_YUYV:
+		*rgb++ = y;
+		*rgb++ = u;
+		*rgb++ = y1;
+		*rgb = v;
+		return 4;
+	case VIDEO_PALETTE_UYVY:
+		*rgb++ = u;
+		*rgb++ = y;
+		*rgb++ = v;
+		*rgb = y1;
+		return 4;
+	default:
+		return 0;
+	}
+}
+
+static int skipcount(int count, int fmt) {
+	switch(fmt) {
+	case VIDEO_PALETTE_GREY:
+	case VIDEO_PALETTE_RGB555:
+	case VIDEO_PALETTE_RGB565:
+	case VIDEO_PALETTE_YUV422:
+	case VIDEO_PALETTE_YUYV:
+	case VIDEO_PALETTE_UYVY:
+		return 2*count;
+	case VIDEO_PALETTE_RGB24:
+		return 3*count;
+	case VIDEO_PALETTE_RGB32:
+		return 4*count;
+	default:
+		return 0;
+	}
+}
+
+static int parse_picture(struct cam_data *cam, int size)
+{
+	u8 *obuf, *ibuf, *end_obuf;
+	int ll, in_uyvy, compressed, origsize, out_fmt;
+
+	/* make sure params don't change while we are decoding */
+	down(&cam->param_lock);
+	
+	obuf = cam->decompressed_frame.data;
+	end_obuf = obuf+CPIA_MAX_FRAME_SIZE;
+	ibuf = cam->raw_image;
+	origsize = size;
+	out_fmt = cam->vp.palette;
+	
+	if((ibuf[0] != MAGIC_0) || (ibuf[1] != MAGIC_1)) {
+		LOG("header not found\n");
+		up(&cam->param_lock);
+		return -1;
+	}
+
+	if((ibuf[16] != VIDEOSIZE_QCIF) && (ibuf[16] != VIDEOSIZE_CIF)) {
+		LOG("wrong video size\n");
+		up(&cam->param_lock);
+		return -1;
+	}
+	
+	if(ibuf[17] != SUBSAMPLE_422) {
+		LOG("illegal subtype %d\n",ibuf[17]);
+		up(&cam->param_lock);
+		return -1;
+	}
+	
+	if(ibuf[18] != YUVORDER_YUYV && ibuf[18] != YUVORDER_UYVY) {
+		LOG("illegal yuvorder %d\n",ibuf[18]);
+		up(&cam->param_lock);
+		return -1;
+	}
+	in_uyvy = ibuf[18] == YUVORDER_UYVY;
+	
+#if 0
+	/* FIXME: ROI mismatch occurs when switching capture sizes */
+	if((ibuf[24] != cam->params.roi.colStart) ||
+	   (ibuf[25] != cam->params.roi.colEnd) ||
+	   (ibuf[26] != cam->params.roi.rowStart) ||
+	   (ibuf[27] != cam->params.roi.rowEnd)) {
+		LOG("ROI mismatch\n");
+		up(&cam->param_lock);
+		return -1;
+	}
+#endif
+	
+	if((ibuf[28] != NOT_COMPRESSED) && (ibuf[28] != COMPRESSED)) {
+		LOG("illegal compression %d\n",ibuf[28]);
+		up(&cam->param_lock);
+		return -1;
+	}
+	compressed = (ibuf[28] == COMPRESSED);
+	
+	if(ibuf[29] != NO_DECIMATION) {
+		LOG("decimation not supported\n");
+		up(&cam->param_lock);
+		return -1;
+	}
+	
+	cam->params.yuvThreshold.yThreshold = ibuf[30];
+	cam->params.yuvThreshold.uvThreshold = ibuf[31];
+	cam->params.status.systemState = ibuf[32];
+	cam->params.status.grabState = ibuf[33];
+	cam->params.status.streamState = ibuf[34];
+	cam->params.status.fatalError = ibuf[35];
+	cam->params.status.cmdError = ibuf[36];
+	cam->params.status.debugFlags = ibuf[37];
+	cam->params.status.vpStatus = ibuf[38];
+	cam->params.status.errorCode = ibuf[39];
+	cam->fps = ibuf[41];
+	
+	ibuf += 64;
+	size -= 64;
+	ll = ibuf[0] | (ibuf[1] << 8);
+	ibuf += 2;
+	while(size > 0) {
+		size -= (ll+2);
+		if(size < 0) {
+			LOG("Insufficient data in buffer\n");
+			up(&cam->param_lock);
+			return -1;
+		}
+		while(ll > 1) {
+			if(!compressed || (compressed && !(*ibuf & 1))) {
+				obuf += yuvconvert(ibuf,obuf,out_fmt,in_uyvy);
+				ibuf += 4;
+				ll -= 4;
+			} else {
+				/*skip compressed interval from previous frame*/
+				int skipsize = skipcount(*ibuf >> 1, out_fmt);
+				obuf += skipsize;
+				if( obuf > end_obuf ) {
+					LOG("Insufficient data in buffer\n");
+					up(&cam->param_lock);
+					return -1;
+				}
+				++ibuf;
+				ll--;
+			}
+		}
+		if(ll == 1) {
+			if(*ibuf != EOL) {
+				LOG("EOL not found giving up after %d/%d"
+				    " bytes\n", origsize-size, origsize);
+				up(&cam->param_lock);
+				return -1;
+			}
+
+			ibuf++; /* skip over EOL */
+
+			if((size > 3) && (ibuf[0] == EOI) && (ibuf[1] == EOI) &&
+			   (ibuf[2] == EOI) && (ibuf[3] == EOI)) {
+			 	size -= 4;
+				break;
+			}
+
+			if(size > 1) {
+				ll = ibuf[0] | (ibuf[1] << 8);
+				ibuf += 2; /* skip over line length */
+			}
+		} else {
+			LOG("line length was not 1 but %d after %d/%d bytes\n",
+			    ll, origsize-size, origsize);
+			up(&cam->param_lock);
+			return -1;
+		}
+	}
+	
+	cam->decompressed_frame.count = obuf-cam->decompressed_frame.data;
+
+	up(&cam->param_lock);
+	
+	return cam->decompressed_frame.count;
+}
+
+/* InitStreamCap wrapper to select correct start line */
+static inline int init_stream_cap(struct cam_data *cam) {
+	return do_command(cam, CPIA_COMMAND_InitStreamCap,
+	                  0, cam->params.streamStartLine, 0, 0);
+}
+
+/* update various camera modes and settings */
+static void dispatch_commands(struct cam_data *cam ) {
+	down(&cam->param_lock);
+	if( cam->cmd_queue==COMMAND_NONE ) {
+		up(&cam->param_lock);
+		return;
+	}
+	DEB_BYTE(cam->cmd_queue);
+	DEB_BYTE(cam->cmd_queue>>8);
+	if( cam->cmd_queue & COMMAND_SETCOLOURPARAMS ) {
+		do_command(cam, CPIA_COMMAND_SetColourParams,
+		           cam->params.colourParams.brightness,
+		           cam->params.colourParams.contrast,
+		           cam->params.colourParams.saturation, 0);
+	}
+	if( cam->cmd_queue & COMMAND_SETCOMPRESSION ) {
+		do_command(cam, CPIA_COMMAND_SetCompression,
+		           cam->params.compression.mode,
+			   cam->params.compression.decimation, 0, 0);
+	}
+	if( cam->cmd_queue & COMMAND_SETFORMAT ) {
+		do_command(cam, CPIA_COMMAND_SetFormat,
+	        	   cam->params.format.videoSize,
+	        	   cam->params.format.subSample,
+	        	   cam->params.format.yuvOrder, 0);
+		do_command(cam, CPIA_COMMAND_SetROI,
+	        	   cam->params.roi.colStart, cam->params.roi.colEnd,
+	        	   cam->params.roi.rowStart, cam->params.roi.rowEnd);
+		cam->first_frame = 1;
+	}
+	if( cam->cmd_queue & COMMAND_SETCOMPRESSIONTARGET ) {
+		do_command(cam, CPIA_COMMAND_SetCompressionTarget,
+		           cam->params.compressionTarget.frTargeting,
+		           cam->params.compressionTarget.targetFR,
+		           cam->params.compressionTarget.targetQ, 0);
+	}
+	if( cam->cmd_queue & COMMAND_SETYUVTHRESH ) {
+		do_command(cam, CPIA_COMMAND_SetYUVThresh,
+		           cam->params.yuvThreshold.yThreshold,
+		           cam->params.yuvThreshold.uvThreshold, 0, 0);
+	}
+	if( cam->cmd_queue & COMMAND_SETECPTIMING ) {
+		do_command(cam, CPIA_COMMAND_SetECPTiming,
+		           cam->params.ecpTiming, 0, 0, 0);
+	}
+	if( cam->cmd_queue & COMMAND_SETCOMPRESSIONPARAMS ) {
+		do_command_extended(cam, CPIA_COMMAND_SetCompressionParams,
+		            0, 0, 0, 0,
+		            cam->params.compressionParams.hysteresis,
+		            cam->params.compressionParams.threshMax,
+		            cam->params.compressionParams.smallStep,
+		            cam->params.compressionParams.largeStep,
+		            cam->params.compressionParams.decimationHysteresis,
+		            cam->params.compressionParams.frDiffStepThresh,
+		            cam->params.compressionParams.qDiffStepThresh,
+		            cam->params.compressionParams.decimationThreshMod);
+	}
+	if( cam->cmd_queue & COMMAND_SETEXPOSURE ) {
+		do_command_extended(cam, CPIA_COMMAND_SetExposure,
+		                    cam->params.exposure.gainMode,
+		                    cam->params.exposure.expMode,
+		                    cam->params.exposure.compMode,
+		                    cam->params.exposure.centreWeight,
+		                    cam->params.exposure.gain,
+		                    cam->params.exposure.fineExp,
+		                    cam->params.exposure.coarseExpLo,
+		                    cam->params.exposure.coarseExpHi,
+		                    cam->params.exposure.redComp,
+		                    cam->params.exposure.green1Comp,
+		                    cam->params.exposure.green2Comp,
+		                    cam->params.exposure.blueComp);
+	}
+	if( cam->cmd_queue & COMMAND_SETCOLOURBALANCE ) {
+		do_command(cam, CPIA_COMMAND_SetColourBalance,
+		           cam->params.colourBalance.balanceMode,
+		           cam->params.colourBalance.redGain,
+		           cam->params.colourBalance.greenGain,
+		           cam->params.colourBalance.blueGain);
+	}
+	if( cam->cmd_queue & COMMAND_SETSENSORFPS ) {
+		do_command(cam, CPIA_COMMAND_SetSensorFPS,
+		           cam->params.sensorFps.divisor,
+		           cam->params.sensorFps.baserate, 0, 0);
+	}
+	if( cam->cmd_queue & COMMAND_SETAPCOR ) {
+		do_command(cam, CPIA_COMMAND_SetApcor,
+		           cam->params.apcor.gain1,
+		           cam->params.apcor.gain2,
+		           cam->params.apcor.gain4,
+		           cam->params.apcor.gain8);
+	}
+	if( cam->cmd_queue & COMMAND_SETFLICKERCTRL ) {
+		do_command(cam, CPIA_COMMAND_SetFlickerCtrl,
+		           cam->params.flickerControl.flickerMode,
+		           cam->params.flickerControl.coarseJump,
+		           cam->params.flickerControl.allowableOverExposure, 0);
+	}
+	if( cam->cmd_queue & COMMAND_SETVLOFFSET ) {
+		do_command(cam, CPIA_COMMAND_SetVLOffset,
+		           cam->params.vlOffset.gain1,
+		           cam->params.vlOffset.gain2,
+		           cam->params.vlOffset.gain4,
+		           cam->params.vlOffset.gain8);
+	}
+	if( cam->cmd_queue & COMMAND_PAUSE ) {
+		do_command(cam, CPIA_COMMAND_EndStreamCap, 0, 0, 0, 0);
+	}
+	if( cam->cmd_queue & COMMAND_RESUME ) {
+		init_stream_cap( cam );
+	}
+	up(&cam->param_lock);
+	cam->cmd_queue=COMMAND_NONE;
+	return;
+}
+
+/* kernel thread function to read image from camera */
+static void fetch_frame(void *data)
+{
+	int image_size;
+	struct cam_data *cam = (struct cam_data *)data;
+	unsigned long oldjif, rate, diff;
+
+        /* load first frame always uncompressed */
+        if( cam->first_frame &&
+            cam->params.compression.mode != CPIA_COMPRESSION_NONE ) {
+                do_command(cam, CPIA_COMMAND_SetCompression,
+                           CPIA_COMPRESSION_NONE,
+                           NO_DECIMATION, 0, 0);
+        }
+
+        /* init camera upload */
+        if(do_command(cam, CPIA_COMMAND_SetGrabMode, CPIA_GRAB_CONTINUOUS,
+                      0, 0, 0)) goto end;
+        if(do_command(cam, CPIA_COMMAND_GrabFrame, 0,
+                      cam->params.streamStartLine, 0, 0)) goto end;
+
+	/* loop until image ready */
+	do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
+	while(cam->params.status.streamState != STREAM_READY) {
+		if(current->need_resched) {schedule();}
+		current->state=TASK_INTERRUPTIBLE;
+		schedule_timeout(10*HZ/1000); /* 10 ms, hopefully ;) */
+		if(signal_pending(current)) {
+			goto end;
+		}
+		do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
+	}
+
+	/* grab image from camera */
+	if(current->need_resched) {schedule();}
+	oldjif = jiffies;
+	image_size=cam->ops->streamRead(cam->lowlevel_data, cam->raw_image, 0);
+	if(image_size<=0) {
+		DBG("read frame failed\n");
+		goto end;
+	}
+	rate = image_size * HZ / 1024;
+	diff = jiffies-oldjif;
+	rate = diff==0 ? rate : rate/diff; /* unlikely but possible */
+	/* Keep track of transfer_rate as a runnung average over 3 frames
+	 * to smooth out any inconsistencies */
+	cam->transfer_rate = (2*cam->transfer_rate + rate) / 3;
+
+	/* camera idle now so dispatch queued commands */
+	dispatch_commands( cam );
+
+	/* Update our knowledge of the camera state - FIXME: necessary? */
+	do_command(cam, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0);
+	do_command(cam, CPIA_COMMAND_GetExposure, 0, 0, 0, 0);
+	
+	/* decompress and convert image to by copying it from
+	*  raw_image to decompressed_frame
+	*/
+	if(current->need_resched) {schedule();}
+	cam->image_size = parse_picture(cam, image_size);
+	if( cam->image_size <= 0 ) {
+		DBG("parse frame failed\n");
+		goto end;
+	}
+
+	/* FIXME: this only works for double buffering */
+	if( cam->frame[cam->curframe].state == FRAME_READY ) {
+		memcpy(cam->frame[cam->curframe].data,
+		       cam->decompressed_frame.data,
+		       cam->decompressed_frame.count);
+		cam->frame[cam->curframe].state = FRAME_DONE;
+	} else {
+		cam->decompressed_frame.state = FRAME_DONE;
+	}
+
+#if 0
+	if( cam->first_frame &&
+	    cam->params.compression.mode != CPIA_COMPRESSION_NONE ) {
+		cam->first_frame = 0;
+		cam->cmd_queue |= COMMAND_SETCOMPRESSION;
+	}
+#else
+	if( cam->first_frame ) {
+		cam->first_frame = 0;
+		cam->cmd_queue |= COMMAND_SETCOMPRESSION;
+		cam->cmd_queue |= COMMAND_SETEXPOSURE;
+	}
+#endif
+end:
+	return;
+}
+
+static int capture_frame(struct cam_data *cam, struct video_mmap *vm)
+{
+	int retval = 0;
+
+	if( cam->frame_buf == NULL ) { /* we do lazy allocation */
+		if( (retval = allocate_frame_buf(cam)) ) {
+			return retval;
+		}
+	}
+	
+	/* FIXME: the first frame seems to be captured by the camera
+	   without regards to any initial settings, so we throw away
+	   that one, the next one is generated with our settings
+	   (exposure, color balance, ...)
+	*/
+	if(cam->first_frame) {
+	  cam->curframe = vm->frame;
+	  cam->frame[cam->curframe].state = FRAME_READY;
+	  fetch_frame(cam);
+	  if(cam->frame[cam->curframe].state != FRAME_DONE) retval=-EIO;
+	}
+	cam->curframe = vm->frame;
+        cam->frame[cam->curframe].state = FRAME_READY;
+        fetch_frame(cam);
+        if(cam->frame[cam->curframe].state != FRAME_DONE) retval=-EIO;
+
+	return retval;
+}
+  
+static int goto_high_power(struct cam_data *cam)
+{
+	if(do_command(cam, CPIA_COMMAND_GotoHiPower, 0, 0, 0, 0)) return -1;
+	if(do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0)) return -1;
+	if(cam->params.status.systemState == HI_POWER_STATE) {
+		DBG("camera now in HIGH power state\n");
+		return 0;
+	}
+	printstatus(cam);
+	return -1;
+}
+
+static int goto_low_power(struct cam_data *cam)
+{
+	if(do_command(cam, CPIA_COMMAND_GotoLoPower, 0, 0, 0, 0)) return -1;
+	if(do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0)) return -1;
+	if(cam->params.status.systemState == LO_POWER_STATE) {
+		DBG("camera now in LOW power state\n");
+		return 0;
+	}
+	printstatus(cam);
+	return -1;
+}
+
+static void save_camera_state(struct cam_data *cam)
+{
+	do_command(cam, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0);
+	do_command(cam, CPIA_COMMAND_GetExposure, 0, 0, 0, 0);
+
+	DBG("%d/%d/%d/%d/%d/%d/%d/%d\n",
+	     cam->params.exposure.gain,
+	     cam->params.exposure.fineExp,
+	     cam->params.exposure.coarseExpLo,
+	     cam->params.exposure.coarseExpHi,
+	     cam->params.exposure.redComp,
+	     cam->params.exposure.green1Comp,
+	     cam->params.exposure.green2Comp,
+	     cam->params.exposure.blueComp);
+	DBG("%d/%d/%d\n",
+	     cam->params.colourBalance.redGain,
+	     cam->params.colourBalance.greenGain,
+	     cam->params.colourBalance.blueGain);
+
+	return;
+}
+
+static void set_camera_state(struct cam_data *cam)
+{
+	if(cam->params.colourBalance.balanceMode != 1) {
+		do_command(cam, CPIA_COMMAND_SetColourBalance, 
+	        	   1,
+	        	   cam->params.colourBalance.redGain,
+	        	   cam->params.colourBalance.greenGain,
+	        	   cam->params.colourBalance.blueGain);
+	}
+	if(cam->params.colourBalance.balanceMode == 0)
+		cam->params.colourBalance.balanceMode = 2;
+
+	do_command_extended(cam, CPIA_COMMAND_SetExposure,
+			    cam->params.exposure.gainMode, 1, 1,
+			    cam->params.exposure.centreWeight,
+	                    cam->params.exposure.gain,
+	                    cam->params.exposure.fineExp,
+	                    cam->params.exposure.coarseExpLo,
+	                    cam->params.exposure.coarseExpHi,
+	                    cam->params.exposure.redComp,
+	                    cam->params.exposure.green1Comp,
+	                    cam->params.exposure.green2Comp,
+	                    cam->params.exposure.blueComp);
+	do_command_extended(cam, CPIA_COMMAND_SetExposure,
+			    0, 3, 0, 0,
+			    0, 0, 0, 0, 0, 0, 0, 0);
+
+	if(cam->params.exposure.gainMode == 0)
+		cam->params.exposure.gainMode = 2;
+	if(cam->params.exposure.expMode == 0)
+		cam->params.exposure.expMode = 2;
+	if(cam->params.exposure.centreWeight == 0)
+		cam->params.exposure.centreWeight = 1;
+	
+	cam->cmd_queue = COMMAND_SETCOMPRESSION |
+	                 COMMAND_SETCOMPRESSIONTARGET |
+	                 COMMAND_SETCOLOURPARAMS |
+	                 COMMAND_SETFORMAT |
+	                 COMMAND_SETYUVTHRESH |
+	                 COMMAND_SETECPTIMING |
+	                 COMMAND_SETCOMPRESSIONPARAMS |
+#if 0
+	                 COMMAND_SETEXPOSURE |
+#endif
+	                 COMMAND_SETCOLOURBALANCE |
+	                 COMMAND_SETSENSORFPS |
+	                 COMMAND_SETAPCOR |
+	                 COMMAND_SETFLICKERCTRL |
+	                 COMMAND_SETVLOFFSET;
+	dispatch_commands(cam);
+	save_camera_state(cam);
+
+	return;
+}
+
+static void get_version_information(struct cam_data *cam)
+{
+	/* GetCPIAVersion */
+	do_command(cam, CPIA_COMMAND_GetCPIAVersion, 0, 0, 0, 0);
+	printk(KERN_INFO "  CPIA Version: %d.%02d (%d.%d)\n",
+	       cam->params.version.firmwareVersion,
+	       cam->params.version.firmwareRevision,
+	       cam->params.version.vcVersion,
+	       cam->params.version.vcRevision);
+
+	/* GetPnPID */
+	do_command(cam, CPIA_COMMAND_GetPnPID, 0, 0, 0, 0);
+	printk(KERN_INFO "  CPIA PnP-ID: %04x:%04x:%04x\n",
+	       cam->params.pnpID.vendor, cam->params.pnpID.product,
+	       cam->params.pnpID.deviceRevision);
+}
+
+/* initialize camera */
+static int reset_camera(struct cam_data *cam)
+{
+	/* Start the camera in low power mode */
+	if(goto_low_power(cam)) {
+		if( cam->params.status.systemState != 0x4 ) {
+			return -ENODEV;
+		}
+		/* FIXME: this is just dirty trial and error */
+		reset_camera_struct(cam);
+		goto_high_power(cam);
+		do_command(cam, CPIA_COMMAND_DiscardFrame, 0, 0, 0, 0);
+		if(goto_low_power(cam)) return -NODEV;
+	}
+	
+	/* procedure described in developer's guide p3-28 */
+	
+	/* Check the firmware version FIXME: should we check PNPID? */
+	cam->params.version.firmwareVersion = 0;
+	get_version_information(cam);
+	if(cam->params.version.firmwareVersion != 1) {
+		return -ENODEV;
+	}
+
+	/* The fatal error checking should be done after the camera powers up (developer's guide p 3-38) */
+
+	/* Set streamState before transition to high power to avoid bug
+	 * in firmware 1-02 */
+	do_command(cam, CPIA_COMMAND_ModifyCameraStatus, STREAMSTATE, 0,
+	           STREAM_NOT_READY, 0);
+	
+	/* GotoHiPower */
+	if(goto_high_power(cam))
+		return -ENODEV;
+
+	
+	/* Check the camera status */
+	if(do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0))
+		return -EIO;
+	if(cam->params.status.fatalError) {
+		DBG("fatal_error:              %#04x\n",cam->params.status.fatalError);
+		DBG("vp_status:                %#04x\n",cam->params.status.vpStatus);
+		if(cam->params.status.fatalError & ~(COM_FLAG|CPIA_FLAG)) {
+			/* Fatal error in camera */
+			return -EIO;
+		} else if(cam->params.status.fatalError & (COM_FLAG|CPIA_FLAG)){
+			/* Firmware 1-02 may do this for parallel port cameras,
+			 * just clear the flags (developer's guide p 3-38) */
+			do_command(cam, CPIA_COMMAND_ModifyCameraStatus,
+			           FATALERROR, ~(COM_FLAG|CPIA_FLAG), 0, 0);
+		}
+	}
+		
+	/* Check the camera status again */
+	if(cam->params.status.fatalError) {
+		if(cam->params.status.fatalError)
+			return -EIO;
+	}
+	
+	/* VPVersion can't be retrieved before the camera is in HiPower,
+	 * so get it here instead of in get_version_information. */
+	do_command(cam, CPIA_COMMAND_GetVPVersion, 0, 0, 0, 0);
+	printk(KERN_INFO "  VP-Version: %d.%d %04x\n",
+	       cam->params.vpVersion.vpVersion,
+	       cam->params.vpVersion.vpRevision,
+	       cam->params.vpVersion.cameraHeadID);
+
+	/* set camera to a known state */
+	set_camera_state(cam);
+	
+	return 0;
+}
+
+/* ------------------------- V4L interface --------------------- */
+static int cpia_open(struct video_device *dev, int flags)
+{
+	int i;
+	struct cam_data *cam = dev->priv;
+
+	DBG("cpia_open\n");
+
+	if(cam->open_count > 0) {
+		DBG("Camera[%d] already open\n",cam->index);
+		return -EBUSY;
+	}
+	
+	if(cam->raw_image == NULL) {
+		if((cam->raw_image=rvmalloc(CPIA_MAX_IMAGE_SIZE)) == NULL){
+			return -ENOMEM;
+		}
+	}
+	if(cam->decompressed_frame.data == NULL) {
+		cam->decompressed_frame.data=rvmalloc(CPIA_MAX_FRAME_SIZE);
+		if(cam->decompressed_frame.data == NULL){
+			rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE);
+			cam->raw_image=NULL;
+			return -ENOMEM;
+		}
+	}
+	
+	/* open cpia */
+	if (cam->ops->open(cam->index, &cam->lowlevel_data)) {
+		rvfree(cam->decompressed_frame.data, CPIA_MAX_FRAME_SIZE);
+		cam->decompressed_frame.data=NULL;
+		rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE);
+		cam->raw_image=NULL;
+		return -ENODEV;
+	}
+	
+	/* reset the camera */
+	if((i = reset_camera(cam)) != 0) {
+		cam->ops->close(cam->lowlevel_data);
+		rvfree(cam->decompressed_frame.data, CPIA_MAX_FRAME_SIZE);
+		cam->decompressed_frame.data=NULL;
+		rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE);
+		cam->raw_image=NULL;
+		return i;
+	}
+	
+	/* Set ownership of /proc/cpia/videoX to current user */
+	cam->proc_entry->uid = current->uid;
+	
+	/* set mark for loading first frame uncompressed */
+	cam->first_frame = 1;
+	cam->busy_lock = MUTEX;
+        
+	++cam->open_count;
+#ifdef MODULE
+	MOD_INC_USE_COUNT;
+#endif
+	return 0;
+}
+
+/* FIXME */
+static void cpia_close(struct video_device *dev)
+{
+	struct cam_data *cam;
+
+	DBG("cpia_close\n");
+	cam = dev->priv;
+
+	if(cam->ops == NULL) {
+		if(--cam->open_count == 0) {
+			int i;
+			video_unregister_device(dev);
+			/* Need a lock when adding/removing cameras */
+			lock_kernel();
+			if(cam->raw_image) {
+				rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE);
+				cam->raw_image=0;
+			}
+			if(cam->decompressed_frame.data) {
+				rvfree(cam->decompressed_frame.data,
+				       CPIA_MAX_FRAME_SIZE);
+				cam->decompressed_frame.data=0;
+			}
+			if(cam->frame_buf) {
+				free_frame_buf(cam);
+			}
+			for(i=0; i<CPIA_MAXCAMS; ++i) {
+				if(camera[i] == cam) break;
+			}
+			kfree(cam);
+			if(i != CPIA_MAXCAMS) { /* should always be true */
+				camera[i] = NULL;
+			}
+			unlock_kernel();
+		}
+#ifdef MODULE
+		MOD_DEC_USE_COUNT;
+#endif
+		return;
+	}
+	
+	/* Return ownership of /proc/cpia/videoX to root */
+	cam->proc_entry->uid = 0;
+	
+	/* save camera state for later open (developers guide ch 3.5.3) */
+	save_camera_state(cam);
+
+	/* GotoLoPower */
+	goto_low_power(cam);
+
+	/* cleanup internal state stuff */
+	free_frames(cam->frame);
+
+	/* Update the camera ststus */
+	do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
+
+	/* close cpia */
+	cam->ops->close(cam->lowlevel_data);
+
+	if(--cam->open_count == 0) {
+		/* clean up capture-buffers */
+		if(cam->raw_image) {
+			rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE);
+			cam->raw_image = 0;
+		}
+		if(cam->decompressed_frame.data) {
+			rvfree(cam->decompressed_frame.data, CPIA_MAX_FRAME_SIZE);
+			cam->decompressed_frame.data = 0;
+		}
+		if(cam->frame_buf) {
+			free_frame_buf(cam);
+		}
+	}
+	
+
+#ifdef MODULE
+	MOD_DEC_USE_COUNT;
+#endif
+	return;
+}
+
+static long cpia_read(struct video_device *dev, char *buf,
+                     unsigned long count, int noblock)
+{
+	struct cam_data *cam = dev->priv;
+
+	/* make this _really_ smp and multithredi-safe */
+	if( down_interruptible(&cam->busy_lock) ) {
+		return -EINTR;
+	}
+
+	if (!buf) {
+		DBG("buf NULL\n");
+		up(&cam->busy_lock);
+		return -EINVAL;
+	}
+	if(count == 0) {
+		DBG("count 0\n");
+		up(&cam->busy_lock);
+		return 0;
+	}
+	if(!cam->ops) {
+		DBG("ops NULL\n");
+		up(&cam->busy_lock);
+		return -ENODEV;
+	}
+
+	/* upload frame */
+	cam->decompressed_frame.state = FRAME_READY;
+	fetch_frame(cam);
+	if( cam->decompressed_frame.state != FRAME_DONE ) {
+		DBG("upload failed %d/%d\n", cam->decompressed_frame.count,
+		    cam->decompressed_frame.state);
+		up(&cam->busy_lock);
+		return -EIO;
+	}
+	cam->decompressed_frame.state = FRAME_UNUSED;
+
+	/* copy data to user space */
+	if(cam->decompressed_frame.count > count) {
+		DBG("count wrong\n");
+		up(&cam->busy_lock);
+		return -EFAULT;
+	}
+	if(copy_to_user(buf, cam->decompressed_frame.data,
+	                cam->decompressed_frame.count)) {
+		DBG("copy_to_user failed\n");
+		up(&cam->busy_lock);
+		return -EFAULT;
+	}
+
+	up(&cam->busy_lock);
+	return cam->decompressed_frame.count;
+}
+
+static int cpia_ioctl(struct video_device *dev, unsigned int ioctlnr, void *arg)
+{
+	struct cam_data *cam = dev->priv;
+	int retval = 0;
+
+	/* make this _really_ smp-safe */
+	if( down_interruptible(&cam->busy_lock) ) {
+		return -EINTR;
+	}
+	//DBG("cpia_ioctl: %u\n", ioctlnr);
+
+	switch (ioctlnr) {
+
+	/* query capabilites */
+	case VIDIOCGCAP:
+	{
+		struct video_capability b;
+
+		DBG("VIDIOCGCAP\n");
+		strcpy(b.name, "CPiA Parport Camera");
+		b.type = VID_TYPE_CAPTURE;
+		b.channels = 1;
+		b.audios = 0;
+		b.maxwidth = 352;         /* VIDEOSIZE_CIF */
+		b.maxheight = 288;
+		b.minwidth = 48;         /* VIDEOSIZE_48_48 */
+		b.minheight = 48;
+
+		if (copy_to_user(arg, &b, sizeof(b)))
+			retval = -EFAULT;
+		break;
+	}
+
+	/* get/set video source - we are a camera and nothing else */
+	case VIDIOCGCHAN:
+	{
+		struct video_channel v;
+
+		DBG("VIDIOCGCHAN\n");
+		if (copy_from_user(&v, arg, sizeof(v))) {
+			retval = -EFAULT;
+			break;
+		}
+		if (v.channel != 0) {
+			retval = -EINVAL;
+			break;
+		}
+
+		v.channel = 0;
+		strcpy(v.name, "Camera");
+		v.tuners = 0;
+		v.flags = 0;
+		v.type = VIDEO_TYPE_CAMERA;
+		v.norm = 0;
+
+		if (copy_to_user(arg, &v, sizeof(v)))
+			retval = -EFAULT;
+		break;
+	}
+	
+	case VIDIOCSCHAN:
+	{
+		int v;
+
+		DBG("VIDIOCSCHAN\n");
+		if (copy_from_user(&v, arg, sizeof(v)))
+			retval = -EFAULT;
+
+		if (retval == 0 && v != 0)
+			retval = -EINVAL;
+
+		break;
+	}
+
+	/* image properties */
+	case VIDIOCGPICT:
+		DBG("VIDIOCGPICT\n");
+		if (copy_to_user(arg, &cam->vp, sizeof(struct video_picture)))
+			retval = -EFAULT;
+		break;
+	
+	case VIDIOCSPICT:
+	{
+		struct video_picture vp;
+
+		DBG("VIDIOCSPICT\n");
+
+		/* copy_from_user */
+		if (copy_from_user(&vp, arg, sizeof(vp))) {
+			retval = -EFAULT;
+			break;
+		}
+		/* check validity */
+		DBG("palette: %d\n", vp.palette);
+		DBG("depth: %d\n", vp.depth);
+		if ( !valid_mode(vp.palette, vp.depth) ) {
+			retval = -EINVAL;
+			break;
+		}
+		down(&cam->param_lock);
+		/* brightness, colour, contrast need no check 0-65535 */
+		memcpy( &cam->vp, &vp, sizeof(vp) );
+		/* update cam->params.colourParams */
+		cam->params.colourParams.brightness = vp.brightness*100/65535;
+		cam->params.colourParams.contrast = vp.contrast*100/65535;
+		cam->params.colourParams.saturation = vp.colour*100/65535;
+		/* contrast is in steps of 8, so round */
+		cam->params.colourParams.contrast =
+			((cam->params.colourParams.contrast + 3) / 8) * 8;
+		if(cam->params.version.firmwareVersion == 1 &&
+		   cam->params.version.firmwareRevision == 2 &&
+		   cam->params.colourParams.contrast > 80) {
+			/* 1-02 firmware limits contrast to 80 */
+			cam->params.colourParams.contrast = 80;
+		}
+		/* queue command to update camera */
+		cam->cmd_queue |= COMMAND_SETCOLOURPARAMS;
+		up(&cam->param_lock);
+		DBG("VIDIOCSPICT: %d / %d // %d / %d / %d / %d\n",
+		    vp.depth, vp.palette, vp.brightness, vp.hue, vp.colour,
+		    vp.contrast);
+		break;
+	}
+
+	/* get/set capture window */
+	case VIDIOCGWIN:
+		DBG("VIDIOCGWIN\n");
+
+		if (copy_to_user(arg, &cam->vw, sizeof(struct video_window)))
+			retval = -EFAULT;
+		break;
+	
+	case VIDIOCSWIN:
+	{
+		/* copy_from_user, check validity, copy to internal structure */
+		struct video_window vw;
+		DBG("VIDIOCSWIN\n");
+		if (copy_from_user(&vw, arg, sizeof(vw))) {
+			retval = -EFAULT;
+			break;
+		}
+
+		if (vw.clipcount != 0) {    /* clipping not supported */
+			retval = -EINVAL;
+			break;
+		}
+		if (vw.clips != NULL) {     /* clipping not supported */
+			retval = -EINVAL;
+			break;
+		}
+
+		/* we set the video window to something smaller or equal to what
+		* is requested by the user???
+		*/
+		down(&cam->param_lock);
+		if(vw.width!=cam->vw.width || vw.height!=cam->vw.height) {
+			int video_size = match_videosize(vw.width, vw.height);
+			if(video_size < 0) {
+				retval = -EINVAL;
+				up(&cam->param_lock);
+				break;
+			}
+			cam->video_size = video_size;
+			set_vw_size(cam);
+			DBG("%d / %d\n", cam->vw.width, cam->vw.height);
+			cam->cmd_queue |= COMMAND_SETFORMAT;
+		}
+
+		// FIXME needed??? memcpy(&cam->vw, &vw, sizeof(vw));
+		up(&cam->param_lock);
+
+		/* setformat ignored by camera during streaming,
+		 * so stop/dispatch/start */
+		if(cam->cmd_queue & COMMAND_SETFORMAT) {
+			DBG("\n");
+			dispatch_commands(cam);
+		}
+		DBG("%d/%d:%d\n", cam->video_size,
+		    cam->vw.width, cam->vw.height);
+		break;
+	}
+
+	/* mmap interface */
+	case VIDIOCGMBUF:
+	{
+		struct video_mbuf vm;
+		int i;
+
+		DBG("VIDIOCGMBUF\n");
+		memset(&vm, 0, sizeof(vm));
+		vm.size = CPIA_MAX_FRAME_SIZE*FRAME_NUM;
+		vm.frames = FRAME_NUM;
+		for( i=0; i<FRAME_NUM; i++ ) {
+			vm.offsets[i] = CPIA_MAX_FRAME_SIZE*i;
+		}
+		if(copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
+			retval = -EFAULT;
+
+		break;
+	}
+	
+	case VIDIOCMCAPTURE:
+	{
+		struct video_mmap vm;
+		int video_size;
+
+		if (copy_from_user((void *)&vm, (void *)arg, sizeof(vm))) {
+			retval = -EFAULT;
+			break;
+		}
+#if 0
+		DBG("VIDIOCMCAPTURE: %d / %d / %dx%d\n", vm.format, vm.frame,
+		    vm.width, vm.height);
+#endif
+		if (vm.frame<0||vm.frame>FRAME_NUM) {
+			retval = -EINVAL;
+			break;
+		}
+
+		/* set video format */
+		cam->vp.palette = vm.format;
+		switch(vm.format) {
+		case VIDEO_PALETTE_GREY:
+		case VIDEO_PALETTE_RGB555:
+		case VIDEO_PALETTE_RGB565:
+		case VIDEO_PALETTE_YUV422:
+		case VIDEO_PALETTE_YUYV:
+		case VIDEO_PALETTE_UYVY:
+			cam->vp.depth = 16;
+			break;
+		case VIDEO_PALETTE_RGB24:
+			cam->vp.depth = 24;
+			break;
+		case VIDEO_PALETTE_RGB32:
+			cam->vp.depth = 32;
+			break;
+		default:
+			retval = -EINVAL;
+			break;
+		}
+		if(retval != 0) break;
+
+		/* set video size */
+		video_size = match_videosize(vm.width, vm.height);
+		if(cam->video_size<0) {
+			retval = -EINVAL;
+			break;
+		}
+		if( video_size != cam->video_size ) {
+			cam->video_size = video_size;
+			set_vw_size(cam);
+			cam->cmd_queue |= COMMAND_SETFORMAT;
+			dispatch_commands(cam);
+		}
+#if 0
+		DBG("VIDIOCMCAPTURE: %d / %d/%d\n", cam->video_size,
+		    cam->vw.width, cam->vw.height);
+#endif
+		/* according to v4l-spec we must start streaming here */
+		retval = capture_frame(cam, &vm);
+
+		break;
+	}
+	
+	case VIDIOCSYNC:
+	{
+		int frame;
+
+		if (copy_from_user((void *)&frame, arg, sizeof(int))) {
+			retval = -EFAULT;
+			break;
+		}
+		//DBG("VIDIOCSYNC: %d\n", frame);
+
+		if (frame<0||frame>=FRAME_NUM) {
+			retval = -EINVAL;
+			break;
+		}
+
+		switch (cam->frame[frame].state) {
+		case FRAME_UNUSED:
+		case FRAME_READY:
+		case FRAME_GRABBING:
+			DBG("sync to unused frame %d\n", frame);
+			retval = -EINVAL;
+			break;
+
+		case FRAME_DONE:
+			cam->frame[frame].state = FRAME_UNUSED;
+			//DBG("VIDIOCSYNC: %d synced\n", frame);
+			break;
+		}
+		if(retval == -EINTR) {
+			/* FIXME - xawtv does not handle this nice */
+			retval = 0;
+		}
+		break;
+	}
+
+	/* pointless to implement overlay with this camera */
+	case VIDIOCCAPTURE:
+		retval = -EINVAL;
+		break;
+	case VIDIOCGFBUF:
+		retval = -EINVAL;
+		break;
+	case VIDIOCSFBUF:
+		retval = -EINVAL;
+		break;
+	case VIDIOCKEY:
+		retval = -EINVAL;
+		break;
+
+	/* tuner interface - we have none */
+	case VIDIOCGTUNER:
+		retval = -EINVAL;
+		break;
+	case VIDIOCSTUNER:
+		retval = -EINVAL;
+		break;
+	case VIDIOCGFREQ:
+		retval = -EINVAL;
+		break;
+	case VIDIOCSFREQ:
+		retval = -EINVAL;
+		break;
+
+	/* audio interface - we have none */
+	case VIDIOCGAUDIO:
+		retval = -EINVAL;
+		break;
+	case VIDIOCSAUDIO:
+		retval = -EINVAL;
+		break;
+	default:
+		retval = -ENOIOCTLCMD;
+		break;
+	}
+
+	up(&cam->param_lock);
+	up(&cam->busy_lock);
+	return retval;
+} 
+
+/* FIXME */
+static int cpia_mmap(struct video_device *dev, const char *adr,
+                     unsigned long size)
+{
+	unsigned long start = (unsigned long)adr;
+	unsigned long page, pos;
+	struct cam_data *cam;
+	int retval;
+
+	DBG("cpia_mmap: %ld\n", size);
+
+	if(size > FRAME_NUM*CPIA_MAX_FRAME_SIZE){
+		return -EINVAL;
+	}
+
+	cam = dev->priv;
+
+	/* make this _really_ smp-safe */
+	if( down_interruptible(&cam->busy_lock) ) {
+		return -EINTR;
+	}
+
+	if( cam->frame_buf == NULL ) { /* we do lazy allocation */
+		if( (retval = allocate_frame_buf(cam)) ) {
+			up(&cam->busy_lock);
+			return retval;
+		}
+	}
+	pos = (unsigned long)(cam->frame_buf);
+	while (size > 0) {
+		page = kvirt_to_phys(pos);
+		if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) {
+			up(&cam->busy_lock);
+			return -EAGAIN;
+		}
+		start+=PAGE_SIZE;
+		pos+=PAGE_SIZE;
+		if (size > PAGE_SIZE) size-=PAGE_SIZE;
+		else size=0;
+	}
+
+	DBG("cpia_mmap: %ld\n", size);
+	up(&cam->busy_lock);
+	return 0;
+}
+
+int cpia_video_init(struct video_device *vdev)
+{
+	create_proc_cpia_cam(vdev->priv);
+	return 0;
+}
+
+static struct video_device cpia_template = {
+	"CPiA Camera",
+	VID_TYPE_CAPTURE,
+	VID_HARDWARE_CPIA,      /* FIXME */
+	cpia_open,              /* open */
+	cpia_close,             /* close */
+	cpia_read,              /* read */
+	NULL,                   /* no write */
+	NULL,                   /* no poll */
+	cpia_ioctl,             /* ioctl */
+	cpia_mmap,              /* mmap */
+	cpia_video_init,        /* initialize */
+	NULL,                   /* priv */
+	0,                      /* busy */
+	-1                      /* minor - unset */
+};
+
+/* initialise cam_data structure  */
+static void reset_camera_struct(struct cam_data *cam)
+{
+	/* The following parameter values are the defaults from
+	 * "Software Developer's Guide for CPiA Cameras".  Any changes
+	 * to the defaults are noted in comments. */
+	cam->params.colourParams.brightness = 50;
+	cam->params.colourParams.contrast = 48;
+	cam->params.colourParams.saturation = 50;
+	cam->params.exposure.gainMode = 2;
+	cam->params.exposure.expMode = 2;		/* AEC */
+	cam->params.exposure.compMode = 1;
+	cam->params.exposure.centreWeight = 1;
+	cam->params.exposure.gain = 0;
+	cam->params.exposure.fineExp = 0;
+	cam->params.exposure.coarseExpLo = 185;
+	cam->params.exposure.coarseExpHi = 0;
+	cam->params.exposure.redComp = 220;
+	cam->params.exposure.green1Comp = 214;
+	cam->params.exposure.green2Comp = 214;
+	cam->params.exposure.blueComp = 230;
+	cam->params.colourBalance.balanceMode = 2;	/* auto color balance */
+	cam->params.colourBalance.redGain = 32;
+	cam->params.colourBalance.greenGain = 6;
+	cam->params.colourBalance.blueGain = 92;
+	cam->params.apcor.gain1 = 0x1c;
+	cam->params.apcor.gain2 = 0x1a;
+	cam->params.apcor.gain4 = 0x2d;
+	cam->params.apcor.gain8 = 0x2a;
+	cam->params.flickerControl.flickerMode = 0;
+	cam->params.flickerControl.coarseJump = 
+		flicker_jumps[cam->mainsFreq]
+		             [cam->params.sensorFps.baserate]
+		             [cam->params.sensorFps.divisor];
+	cam->params.vlOffset.gain1 = 24;
+	cam->params.vlOffset.gain2 = 28;
+	cam->params.vlOffset.gain4 = 30;
+	cam->params.vlOffset.gain8 = 30;
+	cam->params.compressionParams.hysteresis = 3;
+	cam->params.compressionParams.threshMax = 11;
+	cam->params.compressionParams.smallStep = 1;
+	cam->params.compressionParams.largeStep = 3;
+	cam->params.compressionParams.decimationHysteresis = 2;
+	cam->params.compressionParams.frDiffStepThresh = 5;
+	cam->params.compressionParams.qDiffStepThresh = 3;
+	cam->params.compressionParams.decimationThreshMod = 2;
+	/* End of default values from Software Developer's Guide */
+	
+	/* Start with a reasonable transfer rate */
+	cam->transfer_rate = 500;
+	
+	/* Set Sensor FPS to 15fps. This seems better than 30fps
+	 * for indoor lighting. */
+	cam->params.sensorFps.divisor = 1;
+	cam->params.sensorFps.baserate = 1;
+	
+	cam->params.yuvThreshold.yThreshold = 15; /* FIXME? */
+	cam->params.yuvThreshold.uvThreshold = 15; /* FIXME? */
+	
+	cam->params.format.subSample = SUBSAMPLE_422;
+	cam->params.format.yuvOrder = YUVORDER_YUYV;
+	
+	cam->params.compression.mode = CPIA_COMPRESSION_AUTO;
+	cam->params.compressionTarget.frTargeting =
+		CPIA_COMPRESSION_TARGET_QUALITY;
+	cam->params.compressionTarget.targetFR = 7; /* FIXME? */
+	cam->params.compressionTarget.targetQ = 10; /* FIXME? */
+
+	cam->video_size = VIDEOSIZE_CIF;
+	
+	cam->vp.colour = 32768;      /* 50% */
+	cam->vp.hue = 32768;         /* 50% */
+	cam->vp.brightness = 32768;  /* 50% */
+	cam->vp.contrast = 32768;    /* 50% */
+	cam->vp.whiteness = 0;       /* not used -> grayscale only */
+	cam->vp.depth = 0;           /* FIXME: to be set by user? */
+	cam->vp.palette = 0;         /* FIXME: to be set by user? */
+
+	cam->vw.x = 0;
+	cam->vw.y = 0;
+	set_vw_size(cam);
+	cam->vw.chromakey = 0;
+	/* PP NOTE: my extension to use vw.flags for this, bear it! */
+	cam->vw.flags = 0;
+	cam->vw.clipcount = 0;
+	cam->vw.clips = NULL;
+
+	cam->cmd_queue = COMMAND_NONE;
+	cam->first_frame = 0;
+
+	return;
+}
+
+/* initialize cam_data structure  */
+static void init_camera_struct(struct cam_data *cam,
+                               struct cpia_camera_ops *ops )
+{
+	int i;
+	/* Default everything to 0 */
+	memset(cam, 0, sizeof(struct cam_data));
+
+	cam->ops = ops;
+	cam->param_lock = MUTEX;
+
+	reset_camera_struct(cam);
+
+	cam->proc_entry = NULL;
+
+	memcpy(&cam->vdev, &cpia_template, sizeof(cpia_template));
+	cam->vdev.priv = cam;
+	
+	cam->curframe = 0;
+	for( i=0; i<FRAME_NUM; i++) {
+		cam->frame[i].width = 0;
+		cam->frame[i].height = 0;
+		cam->frame[i].state = FRAME_UNUSED;
+		cam->frame[i].data = NULL;
+	}
+	cam->decompressed_frame.width = 0;
+	cam->decompressed_frame.height = 0;
+	cam->decompressed_frame.state = FRAME_UNUSED;
+	cam->decompressed_frame.data = NULL;
+
+	return;
+}
+
+int cpia_register_camera(struct cpia_camera_ops *ops)
+{
+	int i;
+	struct cam_data *cam;
+	/* Need a lock when adding/removing cameras.  This doesn't happen
+	 * often and doesn't take very long, so grabbing the kernel lock
+	 * should be OK. */
+	lock_kernel();
+	for(i=0; i < CPIA_MAXCAMS && camera[i] != NULL; ++i); /* no loop body */
+	if(i == CPIA_MAXCAMS) {
+		unlock_kernel();
+		return -ENODEV;
+	}
+	
+	if((camera[i] = kmalloc(sizeof(struct cam_data), GFP_KERNEL)) == NULL) {
+		unlock_kernel();
+		return -ENOMEM;
+	}
+	
+	init_camera_struct( camera[i], ops );
+	camera[i]->index = i;
+
+	/* register v4l device */
+	if (video_register_device(&camera[i]->vdev, VFL_TYPE_GRABBER) == -1) {
+		kfree(camera[i]);
+		camera[i] = NULL;
+		unlock_kernel();
+		printk(KERN_DEBUG "video_register_device failed\n");
+		return -ENODEV;
+	}
+
+	unlock_kernel();
+	
+	/* FIXME */
+#if 1
+	cam = camera[i];
+	/* open cpia */
+	if (cam->ops->open(cam->index, &cam->lowlevel_data)) {
+		rvfree(cam->decompressed_frame.data, CPIA_MAX_FRAME_SIZE);
+		cam->decompressed_frame.data=NULL;
+		rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE);
+		cam->raw_image=NULL;
+		return -ENODEV;
+	}
+	
+	/* reset the camera */
+	if((i = reset_camera(cam)) != 0) {
+		cam->ops->close(cam->lowlevel_data);
+		rvfree(cam->decompressed_frame.data, CPIA_MAX_FRAME_SIZE);
+		cam->decompressed_frame.data=NULL;
+		rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE);
+		cam->raw_image=NULL;
+		return i;
+	}
+#endif	
+	return i;
+}
+
+void cpia_unregister_camera(int camnr)
+{
+	struct cam_data *cam;
+	if(camnr >= CPIA_MAXCAMS || camera[camnr] == NULL) return;
+	cam = camera[camnr];
+	
+	DBG("unregistering video\n");
+	/* FIXME: Is this safe if the device is open? */
+	video_unregister_device(&cam->vdev);
+	
+	/* Need a lock when adding/removing cameras.  This doesn't happen
+	 * often and doesn't take very long, so grabbing the kernel lock
+	 * should be OK. */
+	lock_kernel();
+	
+	DBG("destroying /proc/cpia/video%d\n", cam->vdev.minor);
+	destroy_proc_cpia_cam(cam);
+	
+	if(cam->open_count == 0) {
+		DBG("freeing camera\n");
+		kfree(camera[camnr]);
+		camera[camnr] = NULL;
+	} else {
+		DBG("camera open -- setting ops to NULL\n");
+		cam->ops = NULL;
+	}
+	unlock_kernel();
+}
+
+/****************************************************************************
+ *
+ *  Module routines
+ *
+ ***************************************************************************/
+
+#ifdef MODULE
+int init_module(void)
+{
+	printk(KERN_INFO "%s v%d.%d.%d\n", ABOUT,
+	       CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER);
+	proc_cpia_create();
+#ifdef CONFIG_KMOD
+#ifdef CONFIG_VIDEO_CPIA_PP_MODULE
+	request_module("cpia_pp");
+#endif
+#ifdef CONFIG_VIDEO_CPIA_USB_MODULE
+	request_module("cpia_usb");
+#endif
+#endif
+return 0;
+}
+
+void cleanup_module(void)
+{
+	int i;
+	for(i=0; i<CPIA_MAXCAMS; ++i) {
+		if(camera[i]) {
+			video_unregister_device(&camera[i]->vdev);
+		}
+	}
+	
+	proc_cpia_destroy();
+}
+
+#else
+
+int cpia_init(struct video_init *unused)
+{
+	printk(KERN_INFO "%s v%d.%d.%d\n", ABOUT,
+	       CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER);
+	proc_cpia_create();
+
+#ifdef MODULE
+#ifdef CONFIG_KMOD
+#ifdef CONFIG_VIDEO_CPIA_PP_MODULE
+	request_module("cpia_pp");
+#endif
+#ifdef CONFIG_VIDEO_CPIA_USB_MODULE
+	request_module("cpia_usb");
+#endif
+#endif	/* CONFIG_KMOD */
+#else	/* !MODULE */
+#ifdef CONFIG_VIDEO_CPIA_PP
+	cpia_pp_init();
+#endif
+#ifdef CONFIG_VIDEO_CPIA_USB
+	cpia_usb_init();
+#endif
+#endif	/* !MODULE */
+	return 0;
+}
+
+/* Exported symbols for modules. */
+
+EXPORT_SYMBOL(cpia_register_camera);
+EXPORT_SYMBOL(cpia_unregister_camera);
+
+#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/cpia_pp.c linux.15p9/drivers/char/cpia_pp.c
--- linux.vanilla/drivers/char/cpia_pp.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/cpia_pp.c	Mon Feb  7 14:51:33 2000
@@ -0,0 +1,1497 @@
+/*
+ * cpia_pp CPiA Parallel Port driver
+ *
+ * Supports CPiA based parallel port Video Camera's.
+ *
+ * (C) 1999 Bas Huisman <bhuism@cs.utwente.nl>
+ *          Scott J. Bertin <sbertin@mindspring.com>,
+ *          Peter Pregler <Peter_Pregler@email.com>
+ *          Johannes Erdfelt
+ *
+ * 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/config.h>
+
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/kernel.h>
+#include <linux/parport.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#ifdef CONFIG_VIDEO_CPIA_PP_DMA
+#include <asm/dma.h>
+#endif
+
+#ifdef CONFIG_KMOD
+#include <linux/kmod.h>
+#endif
+
+
+/* If this is a module and parport_pc is not, some parport_pc_* functions
+ * are not directly availbale.  parport.h messes this up.
+ * This fixes what we need.
+ */
+#if defined(MODULE) && !defined(CONFIG_PARPORT_PC_MODULE)
+#define PARPORT_NEED_GENERIC_OPS
+#undef parport_enable_irq
+#undef parport_disable_irq
+#undef parport_read_fifo
+#define parport_read_fifo(p)		(p)->ops->read_fifo(p)
+#endif
+
+/* These should be defined in linux/parport.h, but aren't.  The #ifndef
+ * parport_enable_irq is in case they are at some future time.
+ */
+#ifdef PARPORT_NEED_GENERIC_OPS
+#ifndef parport_enable_irq
+#define parport_enable_irq(p) (p)->ops->enable_irq(p)
+#define parport_disable_irq(p) (p)->ops->disable_irq(p)
+#endif				/* parport_enable_irq */
+#else				/* !PARPORT_NEED_GENERIC_OPS */
+#ifndef parport_enable_irq
+#define parport_enable_irq(p) parport_pc_enable_irq(p)
+#define parport_disable_irq(p) parport_pc_disable_irq(p)
+#endif				/* parport_enable_irq */
+#endif				/* !PARPORT_NEED_GENERIC_OPS */
+
+#undef _CPIA_DEBUG_		/* define for verbose debug output */
+#include <linux/cpia.h>
+
+static int cpia_pp_open(int camnr, void **privdata);
+static int cpia_pp_registerCallback(void *privdata, void (*cb) (void *cbdata),
+                                    void *cbdata);
+static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data);
+static int cpia_pp_streamStart(void *privdata);
+static int cpia_pp_streamStop(void *privdata);
+static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock);
+static int cpia_pp_close(void *privdata);
+
+#define ABOUT "Parallel port driver for Vision CPiA based cameras"
+
+/* IEEE 1284 Compatiblity Mode signal names 	*/
+#define nStrobe		PARPORT_CONTROL_STROBE	  /* inverted */
+#define nAutoFd		PARPORT_CONTROL_AUTOFD	  /* inverted */
+#define nInit		PARPORT_CONTROL_INIT
+#define nSelectIn	PARPORT_CONTROL_SELECT
+#define IntrEnable	PARPORT_CONTROL_INTEN	  /* normally zero for no IRQ */
+#define DirBit		PARPORT_CONTROL_DIRECTION /* 0 = Forward, 1 = Reverse	*/
+
+#define nFault		PARPORT_STATUS_ERROR
+#define Select		PARPORT_STATUS_SELECT
+#define PError		PARPORT_STATUS_PAPEROUT
+#define nAck		PARPORT_STATUS_ACK
+#define Busy		PARPORT_STATUS_BUSY	  /* inverted */	
+
+/* some more */
+#define HostClk		nStrobe
+#define HostAck		nAutoFd
+#define nReverseRequest	nInit
+#define Active_1284	nSelectIn
+#define nPeriphRequest	nFault
+#define XFlag		Select
+#define nAckReverse	PError
+#define PeriphClk	nAck
+#define PeriphAck	Busy
+
+/* these can be used to correct for the inversion on some bits */
+#define STATUS_INVERSION_MASK	(Busy)
+#define CONTROL_INVERSION_MASK	(nStrobe|nAutoFd|nSelectIn)
+
+#define ECR_empty	0x01
+#define ECR_full	0x02
+#define ECR_serviceIntr 0x04
+#define ECR_dmaEn	0x08
+#define ECR_nErrIntrEn	0x10
+
+#define ECR_mode_mask	0xE0
+#define ECR_SPP_mode	0x00
+#define ECR_PS2_mode	0x20
+#define ECR_FIFO_mode	0x40
+#define ECR_ECP_mode	0x60
+
+#define ECP_FIFO_SIZE	16
+#define DMA_BUFFER_SIZE               PAGE_SIZE
+	/* for 16bit DMA make sure DMA_BUFFER_SIZE is 16 bit aligned */
+
+#define GetECRMasked(port,mask)	(parport_read_econtrol(port) & (mask))
+#define GetStatus(port)		((parport_read_status(port)^STATUS_INVERSION_MASK)&(0xf8))
+#define SetStatus(port,val)	parport_write_status(port,(val)^STATUS_INVERSION_MASK)
+#define GetControl(port)	((parport_read_control(port)^CONTROL_INVERSION_MASK)&(0x3f))
+#define SetControl(port,val)	parport_write_control(port,(val)^CONTROL_INVERSION_MASK)
+
+#define GetStatusMasked(port,mask)	(GetStatus(port) & (mask))
+#define GetControlMasked(port,mask)	(GetControl(port) & (mask))
+#define SetControlMasked(port,mask)	SetControl(port,GetControl(port) | (mask));
+#define ClearControlMasked(port,mask)	SetControl(port,GetControl(port)&~(mask));
+#define FrobControlBit(port,mask,value)	SetControl(port,(GetControl(port)&~(mask))|((value)&(mask)));
+
+#define PP_MAXCAMS	(PARPORT_MAX<CPIA_MAXCAMS?PARPORT_MAX:CPIA_MAXCAMS)
+#define PACKET_LENGTH 	8
+
+/* Magic numbers for defining port-device mappings */
+#define PPCPIA_PARPORT_UNSPEC -4
+#define PPCPIA_PARPORT_AUTO -3
+#define PPCPIA_PARPORT_OFF -2
+#define PPCPIA_PARPORT_NONE -1
+
+#ifdef MODULE
+static int parport_nr[PP_MAXCAMS] = {[0 ... PP_MAXCAMS - 1] = PPCPIA_PARPORT_UNSPEC};
+static char *parport[PP_MAXCAMS] = {NULL,};
+
+MODULE_DESCRIPTION("Parallel port driver for Vision CPiA based cameras");
+MODULE_PARM(parport, "1-" __MODULE_STRING(PP_MAXCAMS) "s");
+MODULE_PARM_DESC(parport, "'auto' or a list of parallel port numbers. Just like lp.");
+#else
+static int parport_nr[PP_MAXCAMS] __initdata =
+	{[0 ... PP_MAXCAMS - 1] = PPCPIA_PARPORT_UNSPEC};
+static int parport_ptr = 0;
+#endif
+
+enum comstates { CPIA_FORWARD, CPIA_REVERSE };	//fixme
+enum camstates {
+	CPIA_PHASE_idle = 0,
+	CPIA_PHASE_neg2s,
+	CPIA_PHASE_setup,
+	CPIA_PHASE_f2rev,
+	CPIA_PHASE_r2for,
+	CPIA_PHASE_term,
+	CPIA_PHASE_secpread,
+	CPIA_PHASE_ecpread,
+	CPIA_PHASE_secpwrite,
+};
+#ifdef _CPIA_DEBUG_
+static char camstatesstr[12][40] =
+{
+	"CPIA_PHASE_idle",
+	"CPIA_PHASE_neg2s",
+	"CPIA_PHASE_setup",
+	"CPIA_PHASE_f2rev",
+	"CPIA_PHASE_r2for",
+	"CPIA_PHASE_term",
+	"CPIA_PHASE_secpread",
+	"CPIA_PHASE_ecpread",
+	"CPIA_PHASE_secpwrite",
+};
+#endif
+struct pp_cam_entry {
+	struct pardevice *pdev;
+	struct parport *port;
+	enum comstates state;
+	enum camstates camstate;
+	struct tq_struct cb_task;
+	int open_count;
+	int camnr;
+	struct wait_queue *wq_stream;
+	
+	/* image state flags */
+	int image_ready;	/* we got an interrupt */
+	int image_complete;	/* we have seen 4 EOI */
+
+	int streaming; /* we are in streaming mode */
+	int stream_irq;
+	
+#ifdef CONFIG_VIDEO_CPIA_PP_DMA
+	/* dma stuff */
+	int dma_on;
+	int dma_intr;
+	int block_size; /* read block_size bytes per DMA */
+	unsigned char *dma_buf;	/* into dma_buf */
+	struct wait_queue *wq_dma;
+	struct tq_struct dma_task;
+	/* counters used in dma-interrupt handler */
+	unsigned char *buf; /* current position in read buffer */
+	int readbytes; /* # bytes read */
+	int bytes; /* maximum # of bytes to read */
+	int endseen; /* number of EOI read */
+#endif
+};
+
+static struct pp_cam_entry *camera[PP_MAXCAMS] = {[0 ... PP_MAXCAMS - 1] = NULL};
+
+static struct cpia_camera_ops cpia_pp_ops = 
+{
+	cpia_pp_open,
+	cpia_pp_registerCallback,
+	cpia_pp_transferCmd,
+	cpia_pp_streamStart,
+	cpia_pp_streamStop,
+	cpia_pp_streamRead,
+	cpia_pp_close
+};
+
+#ifdef _CPIA_DEBUG_
+#define DEB_PORT(port) { \
+u8 controll = GetControl(port); \
+u8 statusss = GetStatus(port); \
+DBG("nsel %c per %c naut %c nstrob %c nak %c busy %c nfaul %c sel %c init %c dir %c\n",\
+((controll & nSelectIn)	? 'U' : 'D'), \
+((statusss & PError)	? 'U' : 'D'), \
+((controll & nAutoFd)	? 'U' : 'D'), \
+((controll & nStrobe)	? 'U' : 'D'), \
+((statusss & nAck)	? 'U' : 'D'), \
+((statusss & Busy)	? 'U' : 'D'), \
+((statusss & nFault)	? 'U' : 'D'), \
+((statusss & Select)	? 'U' : 'D'), \
+((controll & nInit)	? 'U' : 'D'), \
+((controll & DirBit)	? 'R' : 'F')  \
+); }
+#else
+#define DEB_PORT(port) {}
+#endif
+
+#define WHILE_OUT_TIMEOUT (HZ/10)
+#define DMA_TIMEOUT 10*HZ
+
+/* FIXME */
+static void cpia_parport_enable_irq( struct parport *port ) {
+  parport_enable_irq(port);
+  mdelay(10);
+  return;
+}
+
+static void cpia_parport_disable_irq( struct parport *port ) {
+  parport_disable_irq(port);
+  mdelay(10);
+  return;
+}
+
+static int while_out(struct pp_cam_entry *cam)
+{
+	struct parport *port = cam->port;
+	unsigned long endjif;
+
+	if (GetECRMasked(port, ECR_full)) {
+		return 1;
+	}
+
+	endjif = jiffies + WHILE_OUT_TIMEOUT;
+	while( jiffies<endjif ) {
+		schedule();
+		if (GetECRMasked(port, ECR_full)) {
+			return 1;
+		}
+	}
+	DBG("WhileoutError at line waited %d\n", WHILE_OUT_TIMEOUT);
+	return 0;
+}
+
+static int my_wait_peripheral(struct parport *port, int mask, int result)
+{
+	unsigned long oldjiffies = jiffies;
+
+	result &= mask;
+
+	if (GetStatusMasked(port, mask) == result) {
+		return 0;
+	}
+
+	while (jiffies < oldjiffies + (HZ / 3)) {
+		if (GetStatusMasked(port, mask) == result) {
+			return 0;
+		}
+	}
+
+	DBG("failed 0x%x should be 0x%x waited %ld jiffies\n", GetStatus(port) & mask, result, jiffies - oldjiffies);
+	return 1;
+}
+
+static void EmptyFifo(struct parport *port)
+{
+	while (!GetECRMasked(port, ECR_empty)) {
+		parport_read_fifo(port);
+	}
+}
+
+/****************************************************************************
+ *
+ *  Negotiate2Setup
+ *
+ ***************************************************************************/
+static int Negotiate2SetupPhase(struct pp_cam_entry *cam, int extensibility)
+{
+	struct parport *port = cam->port;
+	u8 status = GetStatus(port);
+	u8 control = GetControl(port);
+
+	cam->camstate = CPIA_PHASE_neg2s;
+
+	if (control & nSelectIn) DBG("nSelIn should be low at beginning\n");
+	if (status & PError) DBG("PError should be low at beginning\n");
+	if (!(control & nAutoFd)) DBG("nAutFb should be high at beginning\n");
+	if (!(control & nStrobe)) DBG("nStrobe should be high at beginning\n");
+
+	/*
+	   a high nack idicates a new image is ready (see the docs)
+	   this line can be used for a ISR.
+	 */
+	//if (!(status & nAck)) DBG("nAck should be high at beginning\n");
+
+	if (!(status & Busy)) DBG("Busy should be high at beginning\n");
+	// FIXME ?if (status & nFault) DBG("nFault should be low at beginning\n");
+	if (!(status & Select)) DBG("Select should be high at beginning\n");
+	if (!(control & nInit)) DBG("nInit should be high at beginning\n");
+
+	if (cam->state != CPIA_FORWARD)
+		DBG("port was not in CPIA_FORWARD direction\n");
+
+	parport_write_data(port, extensibility ? 0x80 : 0x10);
+
+	FrobControlBit(port, nSelectIn | nAutoFd, nSelectIn);	//A nAutoFd low,nSelectin high
+
+	if (my_wait_peripheral(port, PError | nFault | Select | nAck, PError | nFault | Select)) {	//B
+		DBG("B failed\n");
+		return -1;
+	}
+
+	ClearControlMasked(port, nStrobe);
+	ClearControlMasked(port, nStrobe);
+	ClearControlMasked(port, nStrobe);
+	ClearControlMasked(port, nStrobe);
+
+	SetControlMasked(port, nAutoFd | nStrobe);	// C
+
+	if (my_wait_peripheral(port, nAck | Select | PError, nAck | Select)) {	// D niet perror+busy low ? nfault high ?
+		DBG("D failed nAck,nInit should become high, Perror low\n");
+		return -1;
+	}
+
+	if (extensibility) {
+		parport_write_data(port, 8 | 3);
+		ClearControlMasked(port, nStrobe);
+		if (my_wait_peripheral(port, nAck, 0)) {
+			DBG("nAck should go low in asking for extensibility mode\n");
+			DEB_PORT(port);
+			return -1;
+		}
+		SetControlMasked(port, nStrobe);
+		if (my_wait_peripheral(port, nAck | Select, nAck | Select)) {
+			DBG("nAck,Xflag should go high in asking for extensibility mode\n");
+			DEB_PORT(port);
+			return -1;
+		}
+	}
+	return 0;
+}
+
+/****************************************************************************
+ *
+ *  EcpSetupPhase
+ *
+ ***************************************************************************/
+static int ECPSetupPhase(struct pp_cam_entry *cam)
+{
+	cam->camstate = CPIA_PHASE_setup;
+	ClearControlMasked(cam->port, nAutoFd);	// E
+	//if (my_wait_peripheral(cam->port,PError,PError)) //pport style
+
+	if (my_wait_peripheral(cam->port, PError | nAck | Busy, PError | nAck)) {	// F
+		DBG("F failed PError,nAck high Busy Low\n");
+		DEB_PORT(cam->port);
+		return -1;
+	}
+	EmptyFifo(cam->port);
+	return 0;
+}
+
+/****************************************************************************
+ *
+ *  Forward2Reverse
+ *
+ ***************************************************************************/
+static int Forward2Reverse(struct pp_cam_entry *cam)
+{
+	struct parport *port = cam->port;
+
+	cam->camstate = CPIA_PHASE_f2rev;
+
+	SetControlMasked(port, DirBit);		// door ClearControlBit(port,nReverseRequest) komt de eerste byte beter als DirBit hier wordt gezet
+	//mdelay(3);
+
+	ClearControlMasked(port, nReverseRequest);	// G
+	//if (my_wait_peripheral(port,PError,0)) //pportq style
+
+	if (my_wait_peripheral(port, PError | Busy | nFault | Select, Busy | Select)) {	//H 
+		DBG("H failed\n");
+		DEB_PORT(port);
+		ClearControlMasked(port, DirBit);	// DirBit repareren;
+		//mdelay(3);
+
+		return -1;
+	}
+	cam->state = CPIA_REVERSE;
+	return 0;
+}
+
+
+/****************************************************************************
+ *
+ *  Reverse2Forward
+ *
+ ***************************************************************************/
+static void Reverse2Forward(struct pp_cam_entry *cam)
+{
+	struct parport *port = cam->port;
+
+	cam->camstate = CPIA_PHASE_r2for;
+
+	if (cam->state != CPIA_REVERSE)
+		DBG("port was not in CPIA_REVERSE direction\n");
+
+	SetControlMasked(port, nReverseRequest);
+	if (my_wait_peripheral(port, nAckReverse, nAckReverse))
+		DBG("nAckReverse should fo high in Reverse2Forward\n");
+
+	ClearControlMasked(port, DirBit);
+	//mdelay(3);
+
+	cam->state = CPIA_FORWARD;
+}
+
+
+/****************************************************************************
+ *
+ *  Valid1284Termination
+ *
+ ***************************************************************************/
+static void Valid1284Termination(struct pp_cam_entry *cam)
+{
+	struct parport *port = cam->port;
+
+	cam->camstate = CPIA_PHASE_term;
+
+	if (cam->state != CPIA_FORWARD)
+		DBG("port was not in CPIA_FORWARD direction\n");
+
+	FrobControlBit(port, nSelectIn | nAutoFd | nStrobe | nInit, nAutoFd | nStrobe | nInit);		//20
+
+	if (my_wait_peripheral(port, nAck, 0)) {	//21
+		DBG("nAck should go low in Valid1284Termination\n");
+		DEB_PORT(port);
+	}
+
+	ClearControlMasked(port, nAutoFd);	//22
+
+	if (my_wait_peripheral(port, nAck, nAck))	//23
+		DBG("nAck should go high again in Valid1284Termination\n");
+
+	SetControlMasked(port, nAutoFd);	//24
+
+	if (my_wait_peripheral(port, PError | nAck | Busy | nFault | Select,
+	                       nAck | Busy | Select))
+		DBG("status bit did not go to the correct value\n");
+	
+	cam->camstate = CPIA_PHASE_idle;
+}
+
+/****************************************************************************
+ *
+ *  SimECPReadBuffer (does termination)
+ *
+ ***************************************************************************/
+static int SimECPReadBuffer(struct pp_cam_entry *cam, u8 *buf, int bytes)
+{
+	int readbytes = 0;
+	struct parport *port = cam->port;
+
+	cam->camstate = CPIA_PHASE_secpread;
+
+	if (cam->state != CPIA_REVERSE) DBG("cam not in CPIA_REVERSE\n");
+	if (!GetControlMasked(port, DirBit))
+		DBG("parport is in forward mode, "
+		    "guess you won't be reading much\n");
+
+	while (readbytes < bytes) {
+		ClearControlMasked(port, nAutoFd);	//moet hier staan: als de while loop exit moet nAutoFd high blijven ...
+
+		if (my_wait_peripheral(port, nAck, 0)) {
+			DBG("nAck didn't went down after read %d bytes no more data ?\n", readbytes);
+			break;
+		}
+		*buf++ = parport_read_data(port);
+		SetControlMasked(port, nAutoFd);
+
+		readbytes++;
+		if (my_wait_peripheral(port, nAck, nAck)) {
+			DBG("nAck didn't went up after read %d bytes\n", readbytes);
+			break;
+		}
+	}
+	return readbytes;
+}
+
+/****************************************************************************
+ *
+ *  ECPReadBuffer_PIO
+ *
+ ***************************************************************************/
+static int ECPReadBuffer_PIO(struct pp_cam_entry *cam, u8 *buf, int bytes)
+{
+	int readbytes = 0, endseen = 0, j;
+	struct parport *port = cam->port;
+
+	if (my_wait_peripheral(port, nAck, 0)) {
+		DBG("nAck didn't went down after read %d bytes no more data ?\n", readbytes);
+		DEB_PORT(port);
+		goto WhileoutError;
+	}
+
+	*buf = parport_read_data(port);	// we take the first byte manually
+	if (*buf == EOI) {
+		endseen++;
+	} else {
+		endseen = 0;
+	}
+	buf++;
+	readbytes++;
+
+	/* acknowledge for this BYTE */
+	SetControlMasked(port, nAutoFd);
+	if (my_wait_peripheral(port, nAck, nAck)) {
+		DBG("nAck didn't went up after read %d bytes\n", readbytes);
+		goto WhileoutError;
+	}
+
+	parport_frob_econtrol(port,
+		ECR_mode_mask|ECR_serviceIntr|ECR_dmaEn|ECR_nErrIntrEn,
+		ECR_ECP_mode|ECR_serviceIntr|ECR_nErrIntrEn);
+
+	while ((((bytes - readbytes) / ECP_FIFO_SIZE) > 0) && (endseen < 4)) {
+		if( current->need_resched ) {
+			schedule();
+		}
+		if (while_out(cam) <= 0) {
+			goto WhileoutError;
+		}
+		for (j = 0; j < ECP_FIFO_SIZE; j++) {
+			*buf = parport_read_fifo(port);
+			if (*buf == EOI) {
+				endseen++;
+			} else {
+				endseen = 0;
+			}
+			buf++;
+			readbytes++;
+		}
+		if( current->need_resched ) schedule();
+	}
+
+	/* switch off automatic filling of the FIFO */
+	ClearControlMasked(port, nAutoFd);
+
+	while ((!GetECRMasked(port, ECR_empty)) && (readbytes < bytes))	{
+		*buf = parport_read_fifo(port);
+		if (*buf == EOI) {
+			endseen++;
+		} else {
+			endseen = 0;
+		}
+		buf++;
+		readbytes++;
+	}
+
+WhileoutError:
+
+	parport_write_econtrol(port, PARPORT_MODE_PCECR);
+	parport_frob_econtrol(port,
+	                      ECR_serviceIntr|ECR_dmaEn|ECR_nErrIntrEn,
+	                      ECR_serviceIntr|ECR_nErrIntrEn);
+	
+	if( endseen > 3 ) {
+		cam->image_complete=1;
+	}
+	
+	return readbytes;
+}
+
+#ifdef CONFIG_VIDEO_CPIA_PP_DMA
+/****************************************************************************
+ *
+ * ECPReadBuffer_DMA
+ *
+ ****************************************************************************/
+
+int ECPReadBuffer_DMA(struct pp_cam_entry *cam, u8 *buf, int bytes)
+{
+	struct parport *port = cam->port;
+	unsigned long flags;
+	int channel = port->dma;
+	int end_jiffies;
+
+	cam->buf=buf;
+	cam->bytes=bytes;
+	cam->endseen=0;
+	cam->readbytes=0;
+	cam->image_complete=0;
+
+	if (my_wait_peripheral(port,nAck,0)) {
+		DBG("nAck didn't went down after read %d bytes no more data ?\n",cam->readbytes);
+		DEB_PORT(port);
+		return cam->readbytes;
+	}
+
+	*(cam->buf) = parport_read_data(port); // we take the first byte manually
+	if (*(cam->buf) == EOI) {
+		cam->endseen++;
+	} else {
+		cam->endseen = 0;
+	}
+	cam->buf++;
+	cam->readbytes++;
+
+	/* acknowledge for this BYTE */
+	SetControlMasked( port, nAutoFd );	  				
+	if (my_wait_peripheral(port,nAck,nAck)) {
+		DBG("nAck didn't went up after read %d bytes\n",cam->readbytes);
+		return cam->readbytes;
+	}
+
+	/* switch port to EPC mode, disable all interrupts for now */
+	parport_frob_econtrol(port, ECR_mode_mask, ECR_ECP_mode);
+	parport_frob_econtrol(port,
+			      ECR_nErrIntrEn|ECR_serviceIntr|ECR_dmaEn,
+			      ECR_nErrIntrEn|ECR_serviceIntr);
+
+	/* prepare controller for dma - align for 16bit DMA */
+	cam->block_size=
+		bytes<DMA_BUFFER_SIZE?(bytes+(bytes%2)):DMA_BUFFER_SIZE;
+
+	flags=claim_dma_lock();
+	disable_dma(channel);
+	clear_dma_ff(channel);
+	set_dma_mode(channel, DMA_MODE_READ);
+	set_dma_addr(channel, virt_to_bus(cam->dma_buf));
+	set_dma_count(channel, cam->block_size);
+	enable_dma(channel);
+
+	cam->dma_on=1;
+	cam->dma_intr = 0;
+
+	/* switch on dma transfer */
+	parport_frob_econtrol(port, ECR_dmaEn, ECR_dmaEn);
+	parport_frob_econtrol(port,ECR_serviceIntr, 0);
+
+	release_dma_lock(flags);
+
+	end_jiffies = jiffies+DMA_TIMEOUT;
+	while(cam->dma_on && !cam->image_complete &&
+	      jiffies < end_jiffies
+	      /*&& !signal_pending(current)*/) {
+		interruptible_sleep_on(&cam->wq_dma);
+	}
+
+	/* we are done with dma */
+	flags=claim_dma_lock();
+	if(cam->dma_on) {
+		cam->dma_on=0;
+		interruptible_sleep_on(&cam->wq_dma);
+	}
+
+	disable_dma(channel);
+
+	parport_frob_econtrol(port,ECR_mode_mask, ECR_PS2_mode);
+	parport_frob_econtrol(port,ECR_serviceIntr, ECR_serviceIntr);
+	parport_frob_econtrol(port, ECR_dmaEn, 0);
+
+	release_dma_lock(flags);
+	return cam->readbytes;
+}
+#endif
+
+/****************************************************************************
+ *
+ * ECPReadBuffer (does termination) (stops when reading EOI)
+ *
+ ****************************************************************************/
+
+int ECPReadBuffer(struct pp_cam_entry *cam, u8 *buf, int bytes)
+{
+	struct parport *port = cam->port;
+	int readbytes;
+
+	cam->camstate = CPIA_PHASE_ecpread;
+
+	if (cam->state != CPIA_REVERSE) DBG("cam not in CPIA_REVERSE\n");
+	if (!GetControlMasked(port,DirBit)) DBG("parport is in forward mode, guess you won't be reading much\n");
+
+#ifdef CONFIG_VIDEO_CPIA_PP_DMA
+	if(cam->dma_buf) {
+		readbytes = ECPReadBuffer_DMA(cam, buf, bytes);
+	} else {
+#endif
+		readbytes = ECPReadBuffer_PIO(cam, buf, bytes);
+#ifdef CONFIG_VIDEO_CPIA_PP_DMA
+	}
+#endif
+
+	return readbytes;
+};
+
+/****************************************************************************
+ *
+ *  SimECPWriteBuffer (does termination)
+ *
+ ***************************************************************************/
+static int SimECPWriteBuffer(struct pp_cam_entry *cam, const u8 *buf, int size)
+{
+	int written = 0;
+	struct parport *port = cam->port;
+
+	cam->camstate = CPIA_PHASE_secpwrite;
+
+	if (cam->state != CPIA_FORWARD) DBG("cam not in CPIA_FORWARD\n");
+	if (GetControlMasked(port, DirBit))
+		DBG("parport is in reverse mode, "
+		    "guess you won't be writing much\n");
+
+	parport_write_data(port, *buf);
+	SetControlMasked(port, HostAck);
+	for (written = 0; written < size; written++) {
+		parport_write_data(port, *buf++);
+		ClearControlMasked(port, HostClk);
+		if (my_wait_peripheral(port, PeriphAck, PeriphAck)) {
+			DBG("PeriphAck never went up signaling read a byte\n");
+			break;
+		}
+		//DBG("written byte: %02x\n",*(u8*)(buf-1));
+		SetControlMasked(port, HostClk);
+		if (my_wait_peripheral(port, PeriphAck, 0)) {
+			DBG("PeriphAck never went down signaling ready for next byte\n");
+			break;
+		}
+	}
+
+	if (written != size)
+		DBG("failed; written %db should be %db\n", written, size);
+
+	return written;
+}
+
+/****************************************************************************
+ *
+ *  EndTransferMode
+ *
+ ***************************************************************************/
+static void EndTransferMode(struct pp_cam_entry *cam)
+{
+	if (!cam) return;
+	if (cam->state == CPIA_REVERSE)  Reverse2Forward(cam);
+	Valid1284Termination(cam);
+	if(cam->stream_irq) cpia_parport_enable_irq(cam->port);
+}
+
+/****************************************************************************
+ *
+ *  ForwardSetup
+ *
+ ***************************************************************************/
+static int ForwardSetup(struct pp_cam_entry *cam)
+{
+	if(cam->stream_irq) cpia_parport_disable_irq(cam->port);
+	if (!Negotiate2SetupPhase(cam, 0)) {
+		if (!ECPSetupPhase(cam)) {
+			return 0;
+		} else {
+			DBG("could not finish setup phase\n");
+		}
+	} else {
+		DBG("could not negotiate for setup phase\n");
+	}
+	EndTransferMode(cam);
+	return -1;
+}
+
+/****************************************************************************
+ *
+ *  ReverseSetup
+ *
+ ***************************************************************************/
+static int ReverseSetup(struct pp_cam_entry *cam, int extensibility)
+{
+	if(cam->stream_irq) cpia_parport_disable_irq(cam->port);
+	if (!Negotiate2SetupPhase(cam, extensibility)) {
+		if (!ECPSetupPhase(cam)) {
+			if (!Forward2Reverse(cam)) {
+				return 0;	/* don't terminate */
+			} else {
+				DBG("could not forward to reverse the port in order to read anything\n");
+			}
+		} else {
+			DBG("could not finish setup phase\n");
+		}
+	} else {
+		DBG("could not negotiate for setup phase\n");
+	}
+	EndTransferMode(cam);
+	return -1;
+}
+
+#ifdef CONFIG_VIDEO_CPIA_PP_DMA
+/****************************************************************************
+ *
+ *  DMA routines
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ *
+ *  Initiate a DMA read buffer
+ *
+ ****************************************************************************/
+
+static inline void receive_buf_dma(struct pp_cam_entry *cam, int num_bytes)
+{
+	int channel = cam->port->dma;
+
+	disable_dma(channel);
+	clear_dma_ff(channel);
+	set_dma_mode(channel, DMA_MODE_READ);
+	set_dma_addr(channel, virt_to_bus(cam->dma_buf));
+	set_dma_count(channel, num_bytes);
+	enable_dma(channel);
+
+	parport_frob_econtrol(cam->port,ECR_serviceIntr, 0);
+
+	return;
+}
+
+static inline void stop_receive_buf_dma(struct pp_cam_entry *cam)
+{
+	unsigned long flags;
+
+	flags=claim_dma_lock();
+	disable_dma(cam->port->dma);
+	cam->dma_on=0;
+
+	parport_frob_econtrol(cam->port,ECR_mode_mask, ECR_PS2_mode);
+	parport_frob_econtrol(cam->port,ECR_serviceIntr,
+                	      ECR_serviceIntr);
+	parport_frob_econtrol(cam->port, ECR_dmaEn, 0);
+
+	if( waitqueue_active(&cam->wq_dma) ) {
+        	wake_up_interruptible(&cam->wq_dma);
+        }
+	release_dma_lock(flags);
+
+	return;
+}
+
+/****************************************************************************
+ *
+ *  DMA bottom half
+ *
+ ****************************************************************************/
+
+static void dma_handler(void *handle)
+{
+	struct pp_cam_entry *cam = handle;
+	int i;
+	unsigned char *dma_ptr, *buf_ptr;
+	unsigned long flags;
+
+	flags=claim_dma_lock();
+	disable_dma(cam->port->dma);
+	parport_frob_econtrol(cam->port,ECR_serviceIntr,
+                	      ECR_serviceIntr);
+	release_dma_lock(flags);
+
+	cam->dma_intr--;
+	if(cam->dma_intr) {
+        	DBG("extra interrupt: %d\n", cam->dma_intr);
+        	stop_receive_buf_dma(cam);
+        	return;
+        }
+	if(cam->dma_on==0 || cam->image_complete) {
+        	return;
+        }
+	flags=claim_dma_lock();
+	clear_dma_ff(cam->port->dma);
+	if((i=get_dma_residue(cam->port->dma))!=0) {
+        	DBG("dma_residue: %d\n", i);
+        	stop_receive_buf_dma(cam);
+        	release_dma_lock(flags);
+        	return;
+        }
+	release_dma_lock(flags);
+	if((i=cam->readbytes+cam->block_size)>cam->bytes) {
+        	DBG("read too many bytes: %d/%d/%d\n",
+		    i, cam->readbytes, cam->bytes);
+        	stop_receive_buf_dma(cam);
+        	return;
+        }
+	dma_ptr=cam->dma_buf;
+	buf_ptr=cam->buf;
+	i=-1;
+	while(++i<cam->block_size && cam->endseen<4) {
+        	if(*dma_ptr==EOI) {
+                	cam->endseen++;
+                } else {
+                	cam->endseen=0;
+                }
+        	(*buf_ptr++)=(*dma_ptr++);
+        }
+	cam->readbytes+=i;
+	cam->buf+=i;
+	if( cam->endseen==4 ) {
+        	cam->image_complete=1;
+        	stop_receive_buf_dma(cam);
+        	return;
+        }
+
+	if( cam->bytes-cam->readbytes <= DMA_BUFFER_SIZE ) {
+		cam->block_size=cam->bytes-cam->readbytes;
+		cam->block_size=cam->block_size-(cam->block_size%2);
+        	if( cam->block_size==0 ) {
+                	stop_receive_buf_dma(cam);
+                	return;
+                }
+        }
+
+	if( cam->dma_on) {
+        	receive_buf_dma(cam, cam->block_size);
+        } else {
+        	stop_receive_buf_dma(cam);
+        }
+	return;
+}
+#endif
+
+/****************************************************************************
+ *
+ *  IRQ handler
+ *
+ ***************************************************************************/
+
+static void cpia_pp_irq_handler(int irq, void *handle, struct pt_regs *b)
+{
+	struct pp_cam_entry *cam = handle;
+	if (cam==NULL) {
+		return;
+	}
+#ifdef CONFIG_VIDEO_CPIA_PP_DMA
+	if(cam->dma_on) {
+		cam->dma_intr++;
+		if( cam->dma_intr == 1 ) {
+			queue_task(&cam->dma_task, &tq_immediate);
+			mark_bh(IMMEDIATE_BH);
+		} else {
+			DBG("%d\n", cam->dma_intr);
+		}
+		return;
+	}
+#endif
+	if (cam->camstate == CPIA_PHASE_ecpread) return;
+	if( cam->camstate != CPIA_PHASE_idle )
+		DBG("got IRQ(%d) when in %s\n",
+		    irq, camstatesstr[cam->camstate]);
+
+	cam->image_ready++;
+	if(cam->image_ready > 1) {
+		cam->image_ready=0;
+		DBG("image skipped?\n");
+	}
+	if(cam->cb_task.routine!=0) {
+		queue_task(&cam->cb_task, &tq_scheduler);
+	}
+
+	if(waitqueue_active(&cam->wq_stream)) {
+        	wake_up_interruptible(&cam->wq_stream);
+        }
+	return;
+}
+
+/****************************************************************************
+ *
+ *  WritePacket
+ *
+ ***************************************************************************/
+static int WritePacket(struct pp_cam_entry *cam, const u8 *packet, size_t size)
+{
+	int retval=0;
+	if (packet == NULL) {
+		return -EINVAL;
+	}
+	if (ForwardSetup(cam)) {
+		return -EIO;
+	}
+	if (SimECPWriteBuffer(cam, packet, size) != size) {
+		retval = -EIO;
+	}
+	EndTransferMode(cam);
+	return retval;
+}
+
+/****************************************************************************
+ *
+ *  ReadPacket
+ *
+ ***************************************************************************/
+static int ReadPacket(struct pp_cam_entry *cam, u8 *packet, size_t size)
+{
+	int retval=0;
+	if (packet == NULL) {
+		return -EINVAL;
+	}
+	if (ReverseSetup(cam, 0)) {
+		return -EIO;
+	}
+	if (SimECPReadBuffer(cam, packet, size) != size) {
+		retval = -EIO;
+	}
+	EndTransferMode(cam);
+	return retval;
+}
+
+/****************************************************************************
+ *
+ *  cpia_pp_streamStart
+ *
+ ***************************************************************************/
+static int cpia_pp_streamStart(void *privdata)
+{
+	struct pp_cam_entry *cam = privdata;
+	DBG("\n");
+	cam->streaming=1;
+	cam->image_ready=0;
+	//if (ReverseSetup(cam,1)) return -EIO;
+	if(cam->stream_irq) cpia_parport_enable_irq(cam->port);
+
+	return 0;
+}
+
+/****************************************************************************
+ *
+ *  cpia_pp_streamStop
+ *
+ ***************************************************************************/
+static int cpia_pp_streamStop(void *privdata)
+{
+	struct pp_cam_entry *cam = privdata;
+
+	DBG("\n");
+	cam->streaming=0;
+	cpia_parport_disable_irq(cam->port);
+	//EndTransferMode(cam);
+
+	return 0;
+}
+
+/****************************************************************************
+ *
+ *  cpia_pp_streamRead
+ *
+ ***************************************************************************/
+static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock)
+{
+	struct pp_cam_entry *cam = privdata;
+	int read_bytes = 0;
+	if(cam == NULL) {
+		DBG("Internal driver error: cam is NULL\n");
+		return -EINVAL;
+	}
+	if(buffer == NULL) {
+		DBG("Internal driver error: buffer is NULL\n");
+		return -EINVAL;
+	}
+	//if(cam->streaming) DBG("%d / %d\n", cam->image_ready, noblock);
+	if( cam->stream_irq ) {
+		DBG("%d\n", cam->image_ready);
+		cam->image_ready--;
+	}
+	cam->image_complete=0;
+	if (0/*cam->streaming*/) {
+		if(!cam->image_ready) {
+			if(noblock) return -EWOULDBLOCK;
+			interruptible_sleep_on(&cam->wq_stream);
+			if( signal_pending(current) ) return -EINTR;
+			DBG("%d\n", cam->image_ready);
+		}
+	} else {
+		if (ReverseSetup(cam, 1)) return -EIO;
+	}
+	read_bytes = ECPReadBuffer(cam, buffer, CPIA_MAX_IMAGE_SIZE);
+	if( 1/*!cam->streaming*/) {
+		EndTransferMode(cam);
+	}
+	if(!cam->image_complete) {
+		if( !signal_pending(current) )
+			DBG("incomplete image: %ld / %d / %d\n",
+			    jiffies, cam->image_complete, read_bytes);
+	}
+	return cam->image_complete ? read_bytes : -EIO;
+}
+
+/****************************************************************************
+ *
+ *  cpia_pp_transferCmd
+ *
+ ***************************************************************************/
+static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data)
+{
+	int err;
+	int retval=0;
+	int databytes;
+	struct pp_cam_entry *cam = privdata;
+	if(cam == NULL) {
+		DBG("Internal driver error: cam is NULL\n");
+		return -EINVAL;
+	}
+	if(command == NULL) {
+		DBG("Internal driver error: command is NULL\n");
+		return -EINVAL;
+	}
+	databytes = (((int)command[7])<<8) | command[6];
+	if ((err = WritePacket(cam, command, PACKET_LENGTH)) < 0) {
+		return err;
+	}
+	if(command[0] == DATA_IN) {
+		u8 buffer[8];
+		if(data == NULL) {
+			DBG("Internal driver error: data is NULL\n");
+			return -EINVAL;
+		}
+		err = ReadPacket(cam, buffer, 8);
+		if(err < 0) {
+			return err;
+		}
+		memcpy(data, buffer, databytes);
+	} else if(command[0] == DATA_OUT) {
+		if(databytes > 0) {
+			if(data == NULL) {
+				DBG("Internal driver error: data is NULL\n");
+				retval = -EINVAL;
+			} else {
+				WritePacket(cam, data, databytes);
+			}
+		}
+	} else {
+		DBG("Unexpected first byte of command: %x\n", command[0]);
+		retval = -EINVAL;
+	}
+	return retval;
+}
+
+/****************************************************************************
+ *
+ *  cpia_pp_open
+ *
+ ***************************************************************************/
+static int cpia_pp_open(int camnr, void **privdata)
+{
+	struct pp_cam_entry *cam=NULL;
+	int i;
+	for(i=0; i<PP_MAXCAMS; ++i) {
+		cam=camera[i];
+		if(cam == NULL) {
+			DBG("Trying to open non-existent camera[%d]\n", camnr);
+			return -ENXIO;
+		}
+		if(cam->camnr == camnr) {
+			DBG("Found camera[%d]\n", camnr);
+			break;
+		}
+	}
+	
+	*privdata = cam;
+	
+	if(cam->open_count == 0) {
+		if (parport_claim(cam->pdev)) {
+			DBG("failed to claim the port\n");
+			return -EBUSY;
+		}
+		parport_write_econtrol(cam->port, PARPORT_MODE_PCECR);
+		parport_frob_econtrol(cam->port,
+		                      ECR_serviceIntr|ECR_dmaEn|ECR_nErrIntrEn,
+		                      ECR_serviceIntr|ECR_nErrIntrEn);
+#ifdef CONFIG_VIDEO_CPIA_PP_DMA
+		cam->dma_task.routine=dma_handler;
+		cam->dma_task.data=cam;
+#endif
+		cam->stream_irq=0;
+		cpia_parport_disable_irq(cam->port);
+	}
+	
+	++cam->open_count;
+	
+#ifdef MODULE
+	MOD_INC_USE_COUNT;
+#endif
+	return 0;
+}
+
+/****************************************************************************
+ *
+ *  cpia_pp_registerCallback
+ *
+ ***************************************************************************/
+static int cpia_pp_registerCallback(void *privdata, void (*cb)(void *cbdata), void *cbdata)
+{
+	struct pp_cam_entry *cam = privdata;
+	int retval = 0;
+	
+	if(cam->port->irq != PARPORT_IRQ_NONE) {
+		cam->cb_task.routine = cb;
+		cam->cb_task.data = cbdata;
+	} else {
+		retval = -1;
+	}
+	return retval;
+}
+
+/****************************************************************************
+ *
+ *  cpia_pp_close
+ *
+ ***************************************************************************/
+static int cpia_pp_close(void *privdata)
+{
+	struct pp_cam_entry *cam = privdata;
+#ifdef CONFIG_VIDEO_CPIA_PP_DMA
+	unsigned int flags;
+#endif
+#ifdef MODULE
+	MOD_DEC_USE_COUNT;
+#endif
+	if (--cam->open_count == 0) {
+		if (cam->port->irq != PARPORT_IRQ_NONE) {
+			cpia_parport_disable_irq(cam->port);
+		}
+		
+#ifdef CONFIG_VIDEO_CPIA_PP_DMA
+		save_flags(flags);
+		cli();
+		if (cam->dma_on) {
+			cam->dma_on=0;
+			interruptible_sleep_on(&cam->wq_dma);
+		}
+		restore_flags(flags);
+#endif
+		if (waitqueue_active(&cam->wq_stream)) { /* FIXME */
+			wake_up(&cam->wq_stream);
+		}
+		
+		parport_release(cam->pdev);
+	}
+	return 0;
+}
+
+/****************************************************************************
+ *
+ *  cpia_pp_register
+ *
+ ***************************************************************************/
+static int cpia_pp_register(int nr, struct parport *port)
+{
+	struct pardevice *pdev = NULL;
+	int camnr;
+
+	if (!(port->modes & PARPORT_MODE_PCECP)) {
+		LOG("port is not ECP capable\n");
+		return -ENXIO;
+	}
+
+	if((camnr = cpia_register_camera(&cpia_pp_ops)) < 0) {
+		LOG("failed to cpia_register_camera\n");
+		return -ENXIO;
+	}
+	camera[nr] = kmalloc(sizeof(struct pp_cam_entry), GFP_KERNEL);
+	if (camera[nr] == NULL) {
+		LOG("failed to allocate camera structure\n");
+		cpia_unregister_camera(camnr);
+		return -ENOMEM;
+	}
+	memset(camera[nr],0,sizeof(struct pp_cam_entry));
+	
+	pdev = parport_register_device(port, "cpia_pp", NULL, NULL,
+	                               cpia_pp_irq_handler, 0, camera[nr]);
+
+	if (!pdev) {
+		LOG("failed to parport_register_device\n");
+		cpia_unregister_camera(camnr);
+		kfree(camera[nr]);
+		return -ENXIO;
+	}
+
+	camera[nr]->pdev = pdev;
+	camera[nr]->port = port;
+	camera[nr]->state = CPIA_FORWARD;
+	camera[nr]->camstate = CPIA_PHASE_idle;
+	camera[nr]->camnr = camnr;
+	init_waitqueue(&camera[nr]->wq_stream);
+
+	camera[nr]->streaming = 0;
+	camera[nr]->stream_irq = 0;
+
+#ifdef CONFIG_VIDEO_CPIA_PP_DMA
+	if (pdev->port->irq != PARPORT_IRQ_NONE &&
+	    pdev->port->dma != PARPORT_DMA_NONE) {
+		if(request_dma(pdev->port->dma, "cpia_pp")) {
+			LOG("failed to register dma %d\n", pdev->port->dma);
+			parport_unregister_device(pdev);
+			cpia_unregister_camera(camnr);
+			kfree(camera[nr]);
+			return -ENXIO;
+		}
+		camera[nr]->dma_buf=kmalloc(DMA_BUFFER_SIZE, GFP_DMA);
+		if(camera[nr]->dma_buf == NULL) {
+			free_dma(camera[nr]->pdev->port->dma);
+			LOG("failed to allocate dma buffer, using FIFO mode\n");
+		} else {
+			init_waitqueue(&camera[nr]->wq_dma);
+			printk(KERN_INFO "  using DMA mode (irq %d, DMA %d)\n", pdev->port->irq, pdev->port->dma);
+		}
+		memset(camera[nr]->dma_buf, 0, DMA_BUFFER_SIZE);
+	} else {
+		printk(KERN_INFO "  using PIO mode\n");
+	}
+#endif
+
+	return 0;
+}
+
+int cpia_pp_init(void)
+{
+	struct parport *port;
+	int i, count = 0;
+
+	printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT, 
+	       CPIA_PP_MAJ_VER,CPIA_PP_MIN_VER,CPIA_PP_PATCH_VER);
+
+	switch (parport_nr[0]) {
+	case PPCPIA_PARPORT_OFF:
+		printk("  disabled\n");
+		return 0;
+
+	case PPCPIA_PARPORT_UNSPEC:
+	case PPCPIA_PARPORT_AUTO:
+		for (port = parport_enumerate(); port; port = port->next) {
+
+#if defined(CONFIG_PNP_PARPORT) || \
+    (defined(MODULE) && defined(CONFIG_PNP_PARPORT_MODULE))
+			if (port->probe_info.class != PARPORT_CLASS_MEDIA ||
+			    port->probe_info.cmdset == NULL ||
+			    strncmp(port->probe_info.cmdset, "CPIA_1", 6) != 0){
+				continue;
+			}
+#endif
+
+			if (cpia_pp_register(count, port) == 0 &&
+			    ++count == PP_MAXCAMS) {
+				break;
+			}
+		}
+		break;
+
+	default:
+		for (i = 0; i < PP_MAXCAMS; i++) {
+			for (port = parport_enumerate(); port;
+			     port = port->next) {
+				if (port->number == parport_nr[i]) {
+					if (!cpia_pp_register(i, port)) {
+						count++;
+					}
+					break;
+				}
+			}
+		}
+		break;
+	}
+
+	printk("  %d camera(s) found\n", count);
+	if (count == 0) {
+		return -ENODEV;
+	}
+	return 0;
+}
+
+#ifdef MODULE
+int init_module(void)
+{
+	if (parport[0]) {
+		/* The user gave some parameters.  Let's see what they were. */
+		if (!strncmp(parport[0], "auto", 4)) {
+			parport_nr[0] = PPCPIA_PARPORT_AUTO;
+		} else {
+			int n;
+			for (n = 0; n < PP_MAXCAMS && parport[n]; n++) {
+				if (!strncmp(parport[n], "none", 4)) {
+					parport_nr[n] = PPCPIA_PARPORT_NONE;
+				} else {
+					char *ep;
+					unsigned long r = simple_strtoul(parport[n], &ep, 0);
+					if (ep != parport[n]) {
+						parport_nr[n] = r;
+					} else {
+						LOG("bad port specifier `%s'\n", parport[n]);
+						return -ENODEV;
+					}
+				}
+			}
+		}
+	}
+#if defined(CONFIG_KMOD) && defined(CONFIG_PNP_PARPORT_MODULE)
+	request_module("parport_probe");
+#endif
+	return cpia_pp_init();
+}
+
+void cleanup_module(void)
+{
+	int i;
+	for (i = 0; camera[i] != NULL && i < PP_MAXCAMS; i++) {
+		while(camera[i]->open_count > 0) {
+			LOG("You forgot to close camera %d, will do it for you\n", camera[i]->camnr);
+			cpia_pp_close(camera[i]);
+		}
+		
+#ifdef CONFIG_VIDEO_CPIA_PP_DMA
+		if (camera[i]->dma_buf) {
+			free_dma(camera[i]->pdev->port->dma);
+			kfree(camera[i]->dma_buf);
+		}
+#endif
+
+		cpia_unregister_camera(camera[i]->camnr);
+		parport_unregister_device(camera[i]->pdev);
+		kfree(camera[i]);
+	}
+	return;
+}
+
+#else /* !MODULE */
+
+__initfunc(void cpia_pp_setup(char *str, int *ints))
+{
+	if (!str) {
+		if (ints[0] == 0 || ints[1] == 0) {
+			/* disable driver on "cpia_pp=" or "cpia_pp=0" */
+			parport_nr[0] = PPCPIA_PARPORT_OFF;
+		}
+	} else if (!strncmp(str, "parport", 7)) {
+		int n = simple_strtoul(str + 7, NULL, 10);
+		if (parport_ptr < PP_MAXCAMS) {
+			parport_nr[parport_ptr++] = n;
+		} else {
+			LOG("too many ports, %s ignored.\n", str);
+		}
+	} else if (!strcmp(str, "auto")) {
+		parport_nr[0] = PPCPIA_PARPORT_AUTO;
+	} else if (!strcmp(str, "none")) {
+		parport_nr[parport_ptr++] = PPCPIA_PARPORT_NONE;
+	}
+}
+
+#endif /* !MODULE */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/cyclades.c linux.15p9/drivers/char/cyclades.c
--- linux.vanilla/drivers/char/cyclades.c	Wed Oct 20 01:12:35 1999
+++ linux.15p9/drivers/char/cyclades.c	Fri Jan 21 18:26:24 2000
@@ -1,7 +1,7 @@
 #undef	BLOCKMOVE
 #define	Z_WAKE
 static char rcsid[] =
-"$Revision: 2.3.2.2 $$Date: 1999/10/01 11:27:43 $";
+"$Revision: 2.3.2.4 $$Date: 2000/01/17 09:19:40 $";
 
 /*
  *  linux/drivers/char/cyclades.c
@@ -9,8 +9,9 @@
  * This file contains the driver for the Cyclades Cyclom-Y multiport
  * serial boards.
  *
- * Initially written by Randolph Bentson (bentson@grieg.seaslug.org).
- * Maintained by Ivan Passos (ivan@cyclades.com).
+ * Initially written by Randolph Bentson <bentson@grieg.seaslug.org>.
+ * Modified and maintained by Marcio Saito <marcio@cyclades.com>.
+ * Currently maintained by Ivan Passos <ivan@cyclades.com>.
  *
  * For Technical support and installation problems, please send e-mail
  * to support@cyclades.com.
@@ -30,6 +31,17 @@
  *   void cleanup_module(void);
  *
  * $Log: cyclades.c,v $
+ * Revision 2.3.2.4   2000/01/17 09:19:40 ivan
+ * Fixed SMP locking in Cyclom-Y interrupt handler.
+ *
+ * Revision 2.3.2.3   1999/12/28 12:31:39 ivan
+ * Added a new cyclades_card field called nports to allow the driver to 
+ * know the exact number of ports found by the Z firmware after its load;
+ * RX buffer contention prevention logic on interrupt op mode revisited 
+ * (Cyclades-Z only);
+ * Revisited printk's for Z debug;
+ * Driver now makes sure that the constant SERIAL_XMIT_SIZE is defined;
+ *
  * Revision 2.3.2.2   1999/10/01 11:27:43 ivan
  * Fixed bug in cyz_poll that would make all ports but port 0 
  * unable to transmit/receive data (Cyclades-Z only);
@@ -598,25 +610,6 @@
 
 #define cy_min(a,b) (((a)<(b))?(a):(b))
 
-#if 0
-/******** 
- * For the next two macros, it is assumed that the buffer size is a 
- * power of 2 
- ********/
-
-#define CHARS_IN_BUF(buf_ctrl) \
-    ((cy_readl(&buf_ctrl->rx_put) - \
-      cy_readl(&buf_ctrl->rx_get) + \
-      cy_readl(&buf_ctrl->rx_bufsize)) & \
-		  (cy_readl(&buf_ctrl->rx_bufsize) - 1))
-
-#define SPACE_IN_BUF(buf_ctrl) \
-    ((cy_readl(&buf_ctrl->tx_get) - \
-      cy_readl(&buf_ctrl->tx_put) + \
-      cy_readl(&buf_ctrl->tx_bufsize) - 1) & \
-		  (cy_readl(&buf_ctrl->tx_bufsize) - 1))
-#endif
-
 /*
  * Include section 
  */
@@ -700,6 +693,9 @@
 			(ZFIRM_ID==cy_readl(&((struct FIRM_ID *) \
 			((card).base_addr+ID_ADDRESS))->signature)))
 
+#ifndef SERIAL_XMIT_SIZE
+#define	SERIAL_XMIT_SIZE	(MIN(PAGE_SIZE, 4096))
+#endif
 #define WAKEUP_CHARS (SERIAL_XMIT_SIZE-256)
 
 #define STD_COM_FLAGS (0)
@@ -995,10 +991,12 @@
     }
 #ifdef CONFIG_CYZ_INTR
     if (test_and_clear_bit(Cy_EVENT_Z_RX_FULL, &info->event)) {
-	cyz_rx_full_timer[info->line].expires = jiffies + 1;
-	cyz_rx_full_timer[info->line].function = cyz_rx_restart;
-	cyz_rx_full_timer[info->line].data = (unsigned long)info;
-	add_timer(&cyz_rx_full_timer[info->line]);
+	if (cyz_rx_full_timer[info->line].function == NULL) {
+	    cyz_rx_full_timer[info->line].expires = jiffies + 1;
+	    cyz_rx_full_timer[info->line].function = cyz_rx_restart;
+	    cyz_rx_full_timer[info->line].data = (unsigned long)info;
+	    add_timer(&cyz_rx_full_timer[info->line]);
+	}
     }
 #endif
     if (test_and_clear_bit(Cy_EVENT_DELTA_WAKEUP, &info->event)) {
@@ -1170,7 +1168,6 @@
                     info->last_active = jiffies;
                     save_car = cy_readb(base_addr+(CyCAR<<index));
                     cy_writeb((u_long)base_addr+(CyCAR<<index), save_xir);
-		    spin_unlock(&cinfo->card_lock);
 
                     /* if there is nowhere to put the data, discard it */
                     if(info->tty == 0){
@@ -1299,7 +1296,6 @@
                         queue_task(&tty->flip.tqueue, &tq_timer);
                     }
                     /* end of service */
-		    spin_lock(&cinfo->card_lock);
                     cy_writeb((u_long)base_addr+(CyRIR<<index), (save_xir & 0x3f));
                     cy_writeb((u_long)base_addr+(CyCAR<<index), (save_car));
 		    spin_unlock(&cinfo->card_lock);
@@ -1321,23 +1317,18 @@
                     i = channel + chip * 4 + cinfo->first_line;
                     save_car = cy_readb(base_addr+(CyCAR<<index));
                     cy_writeb((u_long)base_addr+(CyCAR<<index), save_xir);
-		    spin_unlock(&cinfo->card_lock);
 
                     /* validate the port# (as configured and open) */
                     if( (i < 0) || (NR_PORTS <= i) ){
-			spin_lock(&cinfo->card_lock);
                         cy_writeb((u_long)base_addr+(CySRER<<index),
                              cy_readb(base_addr+(CySRER<<index)) & ~CyTxMpty);
-			spin_unlock(&cinfo->card_lock);
                         goto txend;
                     }
                     info = &cy_port[i];
                     info->last_active = jiffies;
                     if(info->tty == 0){
-			spin_lock(&cinfo->card_lock);
                         cy_writeb((u_long)base_addr+(CySRER<<index),
                              cy_readb(base_addr+(CySRER<<index)) & ~CyTxMpty);
-			spin_unlock(&cinfo->card_lock);
                         goto txdone;
                     }
 
@@ -1369,27 +1360,21 @@
 
                     while (char_count-- > 0){
 			if (!info->xmit_cnt){
-			    spin_lock(&cinfo->card_lock);
                             cy_writeb((u_long)base_addr+(CySRER<<index),
 				cy_readb(base_addr+(CySRER<<index)) & 
 					~CyTxMpty);
-			    spin_unlock(&cinfo->card_lock);
 			    goto txdone;
 			}
 			if (info->xmit_buf == 0){
-			    spin_lock(&cinfo->card_lock);
                             cy_writeb((u_long)base_addr+(CySRER<<index),
 				cy_readb(base_addr+(CySRER<<index)) & 
 					~CyTxMpty);
-			    spin_unlock(&cinfo->card_lock);
                             goto txdone;
 			}
 			if (info->tty->stopped || info->tty->hw_stopped){
-			    spin_lock(&cinfo->card_lock);
                             cy_writeb((u_long)base_addr+(CySRER<<index),
 				cy_readb(base_addr+(CySRER<<index)) & 
 					~CyTxMpty);
-			    spin_unlock(&cinfo->card_lock);
                             goto txdone;
 			}
                         /* Because the Embedded Transmit Commands have
@@ -1431,7 +1416,6 @@
                     }
         txend:
                     /* end of service */
-		    spin_lock(&cinfo->card_lock);
                     cy_writeb((u_long)base_addr+(CyTIR<<index), 
 			      (save_xir & 0x3f));
                     cy_writeb((u_long)base_addr+(CyCAR<<index), (save_car));
@@ -1452,7 +1436,6 @@
 
                     mdm_change = cy_readb(base_addr+(CyMISR<<index));
                     mdm_status = cy_readb(base_addr+(CyMSVR1<<index));
-		    spin_unlock(&cinfo->card_lock);
 
                     if(info->tty == 0){/* no place for data, ignore it*/
                         ;
@@ -1487,11 +1470,9 @@
                                     /* cy_start isn't used
 				         because... !!! */
                                     info->tty->hw_stopped = 0;
-				  spin_lock(&cinfo->card_lock);
                                   cy_writeb((u_long)base_addr+(CySRER<<index),
                                        cy_readb(base_addr+(CySRER<<index)) | 
                                        CyTxMpty);
-				  spin_unlock(&cinfo->card_lock);
                                     cy_sched_event(info,
 				        Cy_EVENT_WRITE_WAKEUP);
                                 }
@@ -1500,11 +1481,9 @@
                                     /* cy_stop isn't used
 				         because ... !!! */
                                     info->tty->hw_stopped = 1;
-				  spin_lock(&cinfo->card_lock);
                                   cy_writeb((u_long)base_addr+(CySRER<<index),
                                        cy_readb(base_addr+(CySRER<<index)) & 
                                        ~CyTxMpty);
-				  spin_unlock(&cinfo->card_lock);
                                 }
                             }
                         }
@@ -1514,7 +1493,6 @@
                         }
                     }
                     /* end of service */
-		    spin_lock(&cinfo->card_lock);
                     cy_writeb((u_long)base_addr+(CyMIR<<index), 
 			      (save_xir & 0x3f));
                     cy_writeb((u_long)base_addr+(CyCAR<<index), save_car);
@@ -1536,7 +1514,6 @@
 /******** Start of block of Cyclades-Z specific code *********/
 /***********************************************************/
 
-
 static int
 cyz_fetch_msg( struct cyclades_card *cinfo,
 	    uclong *channel, ucchar *cmd, uclong *param)
@@ -1567,7 +1544,6 @@
     return 0;
 } /* cyz_fetch_msg */
 
-
 static int
 cyz_issue_cmd( struct cyclades_card *cinfo,
 	    uclong channel, ucchar cmd, uclong param)
@@ -1591,7 +1567,7 @@
                                (cinfo->ctl_addr))->pci_doorbell);
     while( (cy_readl(pci_doorbell) & 0xff) != 0){
         if (index++ == 1000){
-            return(-1);
+	    return((int)(cy_readl(pci_doorbell) & 0xff));
         }
 	udelay(50L);
     }
@@ -1603,7 +1579,8 @@
 } /* cyz_issue_cmd */
 
 static void
-cyz_handle_rx(struct cyclades_port *info, volatile struct BUF_CTRL *buf_ctrl)
+cyz_handle_rx(struct cyclades_port *info, volatile struct CH_CTRL *ch_ctrl,
+	      volatile struct BUF_CTRL *buf_ctrl)
 {
   struct cyclades_card *cinfo = &cy_card[info->card];
   struct tty_struct *tty = info->tty;
@@ -1613,14 +1590,12 @@
 #else
   char data;
 #endif
-  volatile uclong rx_put, rx_get, rx_bufsize;
-
-/* Removed due to compilation problems in Alpha systems */
-//    if ((char_count = CHARS_IN_BUF(buf_ctrl))){
+  volatile uclong rx_put, rx_get, new_rx_get, rx_bufsize, rx_bufaddr;
 
-    rx_get = cy_readl(&buf_ctrl->rx_get);
+    rx_get = new_rx_get = cy_readl(&buf_ctrl->rx_get);
     rx_put = cy_readl(&buf_ctrl->rx_put);
     rx_bufsize = cy_readl(&buf_ctrl->rx_bufsize);
+    rx_bufaddr = cy_readl(&buf_ctrl->rx_bufaddr);
     if (rx_put >= rx_get)
 	char_count = rx_put - rx_get;
     else
@@ -1639,7 +1614,7 @@
 #endif
 	if(tty == 0){
 	    /* flush received characters */
-	    rx_get = (rx_get + char_count) & (rx_bufsize - 1);
+	    new_rx_get = (new_rx_get + char_count) & (rx_bufsize - 1);
 	    info->rflush_count++;
 	}else{
 #ifdef BLOCKMOVE
@@ -1647,19 +1622,18 @@
 	       for performance, but because of buffer boundaries, there
 	       may be several steps to the operation */
 	    while(0 < (small_count = 
-		       cy_min((rx_bufsize - rx_get),
+		       cy_min((rx_bufsize - new_rx_get),
 		       cy_min((TTY_FLIPBUF_SIZE - tty->flip.count), char_count))
 		 )) {
 		memcpy_fromio(tty->flip.char_buf_ptr,
 			      (char *)(cinfo->base_addr
-				       + cy_readl(&buf_ctrl->rx_bufaddr)
-				       + rx_get),
+				       + rx_bufaddr + new_rx_get),
 			      small_count);
 
 		tty->flip.char_buf_ptr += small_count;
 		memset(tty->flip.flag_buf_ptr, TTY_NORMAL, small_count);
 		tty->flip.flag_buf_ptr += small_count;
-		rx_get = (rx_get + small_count) & (rx_bufsize - 1);
+		new_rx_get = (new_rx_get + small_count) & (rx_bufsize - 1);
 		char_count -= small_count;
 		info->icount.rx += small_count;
 		info->idle_stats.recv_bytes += small_count;
@@ -1668,14 +1642,10 @@
 #else
 	    while(char_count--){
 		if (tty->flip.count >= TTY_FLIPBUF_SIZE){
-#ifdef CONFIG_CYZ_INTR
-		    cy_sched_event(info, Cy_EVENT_Z_RX_FULL);
-#endif
 		    break;
 		}
-		data = cy_readb(cinfo->base_addr +
-			cy_readl(&buf_ctrl->rx_bufaddr) + rx_get);
-		rx_get = (rx_get + 1) & (rx_bufsize - 1);
+		data = cy_readb(cinfo->base_addr + rx_bufaddr + new_rx_get);
+		new_rx_get = (new_rx_get + 1) & (rx_bufsize - 1);
 		tty->flip.count++;
 		*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
 		*tty->flip.char_buf_ptr++ = data;
@@ -1683,16 +1653,29 @@
 		info->icount.rx++;
 	    }
 #endif
+#ifdef CONFIG_CYZ_INTR
+	    /* Recalculate the number of chars in the RX buffer and issue
+	       a cmd in case it's higher than the RX high water mark */
+	    rx_put = cy_readl(&buf_ctrl->rx_put);
+	    if (rx_put >= rx_get)
+		char_count = rx_put - rx_get;
+	    else
+		char_count = rx_put - rx_get + rx_bufsize;
+	    if(char_count >= cy_readl(&buf_ctrl->rx_threshold)) {
+		cy_sched_event(info, Cy_EVENT_Z_RX_FULL);
+	    }
+#endif
 	    info->idle_stats.recv_idle = jiffies;
 	    queue_task(&tty->flip.tqueue, &tq_timer);
 	}
 	/* Update rx_get */
-	cy_writel(&buf_ctrl->rx_get, rx_get);
+	cy_writel(&buf_ctrl->rx_get, new_rx_get);
     }
 }
 
 static void
-cyz_handle_tx(struct cyclades_port *info, volatile struct BUF_CTRL *buf_ctrl)
+cyz_handle_tx(struct cyclades_port *info, volatile struct CH_CTRL *ch_ctrl,
+	      volatile struct BUF_CTRL *buf_ctrl)
 {
   struct cyclades_card *cinfo = &cy_card[info->card];
   struct tty_struct *tty = info->tty;
@@ -1701,14 +1684,15 @@
 #ifdef BLOCKMOVE
   int small_count;
 #endif
-  volatile uclong tx_put, tx_get, tx_bufsize;
+  volatile uclong tx_put, tx_get, tx_bufsize, tx_bufaddr;
 
-/* Removed due to compilation problems in Alpha systems */
-//    if ((char_count = SPACE_IN_BUF(buf_ctrl))){
+    if (info->xmit_cnt <= 0)	/* Nothing to transmit */
+	return;
 
     tx_get = cy_readl(&buf_ctrl->tx_get);
     tx_put = cy_readl(&buf_ctrl->tx_put);
     tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize);
+    tx_bufaddr = cy_readl(&buf_ctrl->tx_bufaddr);
     if (tx_put >= tx_get)
 	char_count = tx_get - tx_put - 1 + tx_bufsize;
     else
@@ -1723,8 +1707,7 @@
 	if(info->x_char) { /* send special char */
 	    data = info->x_char;
 
-	    cy_writeb((cinfo->base_addr + 
-		cy_readl(&buf_ctrl->tx_bufaddr) + tx_put), data);
+	    cy_writeb((cinfo->base_addr + tx_bufaddr + tx_put), data);
 	    tx_put = (tx_put + 1) & (tx_bufsize - 1);
 	    info->x_char = 0;
 	    char_count--;
@@ -1738,8 +1721,7 @@
 		   cy_min ((SERIAL_XMIT_SIZE - info->xmit_tail),
 			cy_min(info->xmit_cnt, char_count))))){
 
-	    memcpy_toio((char *)(cinfo->base_addr
-				 + cy_readl(&buf_ctrl->tx_bufaddr) + tx_put),
+	    memcpy_toio((char *)(cinfo->base_addr + tx_bufaddr + tx_put),
 			&info->xmit_buf[info->xmit_tail],
 			small_count);
 
@@ -1758,8 +1740,7 @@
 	    info->xmit_cnt--;
 	    info->xmit_tail = (info->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1);
 
-	    cy_writeb(cinfo->base_addr + 
-		cy_readl(&buf_ctrl->tx_bufaddr) + tx_put, data);
+	    cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data);
 	    tx_put = (tx_put + 1) & (tx_bufsize - 1);
 	    char_count--;
 	    info->icount.tx++;
@@ -1800,6 +1781,11 @@
     fw_ver = cy_readl(&board_ctrl->fw_version);
     hw_ver = cy_readl(&((struct RUNTIME_9060 *)(cinfo->ctl_addr))->mail_box_0);
 
+#ifdef CONFIG_CYZ_INTR
+    if (!cinfo->nports)
+	cinfo->nports = (int) cy_readl(&board_ctrl->n_channel);
+#endif
+
     while(cyz_fetch_msg(cinfo, &channel, &cmd, &param) == 1) {
 	special_count = 0;
 	delta_count = 0;
@@ -1872,7 +1858,7 @@
 		printk("cyz_interrupt: rcvd intr, card %d, port %ld\n\r", 
 			info->card, channel);
 #endif
-		cyz_handle_rx(info, buf_ctrl);
+		cyz_handle_rx(info, ch_ctrl, buf_ctrl);
 		break;
 	    case C_CM_TXBEMPTY:
 	    case C_CM_TXLOWWM:
@@ -1882,7 +1868,7 @@
 		printk("cyz_interrupt: xmit intr, card %d, port %ld\n\r", 
 			info->card, channel);
 #endif
-		cyz_handle_tx(info, buf_ctrl);
+		cyz_handle_tx(info, ch_ctrl, buf_ctrl);
 		break;
 #endif /* CONFIG_CYZ_INTR */
 	    case C_CM_FATAL:
@@ -1931,12 +1917,16 @@
     int retval;
     int card = info->card;
     uclong channel = (info->line) - (cy_card[card].first_line);
+    unsigned long flags;
 
-    cyz_rx_full_timer[info->card].expires = jiffies + HZ;
+    CY_LOCK(info, flags);
     retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_INTBACK2, 0L);
     if (retval != 0){
-	printk("cyc:cyz_rx_restart retval was %x\n", retval);
+	printk("cyc:cyz_rx_restart retval on ttyC%d was %x\n", 
+	       info->line, retval);
     }
+    cyz_rx_full_timer[info->line].function = NULL;
+    CY_UNLOCK(info, flags);
 }
 
 #else /* CONFIG_CYZ_INTR */
@@ -1961,27 +1951,28 @@
 	if (!IS_CYC_Z(*cinfo)) continue;
 	if (!ISZLOADED(*cinfo)) continue;
 
+	firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS);
+	zfw_ctrl = (struct ZFW_CTRL *)
+		   (cinfo->base_addr + cy_readl(&firm_id->zfwctrl_addr));
+	board_ctrl = &(zfw_ctrl->board_ctrl);
+
 	/* Skip first polling cycle to avoid racing conditions with the FW */
 	if (!cinfo->intr_enabled) {
+	    cinfo->nports = (int) cy_readl(&board_ctrl->n_channel);
 	    cinfo->intr_enabled = 1;
 	    continue;
 	}
 
-	firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS);
-	zfw_ctrl = (struct ZFW_CTRL *)
-		   (cinfo->base_addr + cy_readl(&firm_id->zfwctrl_addr));
-	board_ctrl = &(zfw_ctrl->board_ctrl);
-
 	cyz_handle_cmd(cinfo);
 
-	for (port = 0; port < cy_readl(&board_ctrl->n_channel); port++){
+	for (port = 0 ; port < cinfo->nports ; port++) {
 	    info = &cy_port[ port + cinfo->first_line ];
             tty = info->tty;
 	    ch_ctrl = &(zfw_ctrl->ch_ctrl[port]);
 	    buf_ctrl = &(zfw_ctrl->buf_ctrl[port]);
 
-	    cyz_handle_rx(info, buf_ctrl);
-	    cyz_handle_tx(info, buf_ctrl);
+	    cyz_handle_rx(info, ch_ctrl, buf_ctrl);
+	    cyz_handle_tx(info, ch_ctrl, buf_ctrl);
 	}
 	/* poll every 'cyz_polling_cycle' period */
 	cyz_timerlist.expires = jiffies + cyz_polling_cycle;
@@ -2140,13 +2131,15 @@
 
 	retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTL, 0L);
 	if (retval != 0){
-	    printk("cyc:startup(1) retval was %x\n", retval);
+	    printk("cyc:startup(1) retval on ttyC%d was %x\n", 
+		   info->line, retval);
 	}
 
 	/* Flush RX buffers before raising DTR and RTS */
 	retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_RX, 0L);
 	if (retval != 0){
-	    printk("cyc:startup(2) retval was %x\n", retval);
+	    printk("cyc:startup(2) retval on ttyC%d was %x\n", 
+		   info->line, retval);
 	}
 
 	/* set timeout !!! */
@@ -2156,7 +2149,8 @@
 	retval = cyz_issue_cmd(&cy_card[info->card],
 	    channel, C_CM_IOCTLM, 0L);
 	if (retval != 0){
-	    printk("cyc:startup(3) retval was %x\n", retval);
+	    printk("cyc:startup(3) retval on ttyC%d was %x\n", 
+		   info->line, retval);
 	}
 #ifdef CY_DEBUG_DTR
 	    printk("cyc:startup raising Z DTR\n");
@@ -2218,7 +2212,8 @@
 	CY_LOCK(info, flags);
 	    retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_INTBACK, 0L);
 	    if (retval != 0){
-		printk("cyc:start_xmit retval was %x\n", retval);
+		printk("cyc:start_xmit retval on ttyC%d was %x\n", 
+		       info->line, retval);
 	    }
 	CY_UNLOCK(info, flags);
 #else /* CONFIG_CYZ_INTR */
@@ -2328,7 +2323,8 @@
 		retval = cyz_issue_cmd(&cy_card[info->card],
 			channel, C_CM_IOCTLM, 0L);
 		if (retval != 0){
-		    printk("cyc:shutdown retval was %x\n", retval);
+		    printk("cyc:shutdown retval on ttyC%d was %x\n", 
+			   info->line, retval);
 		}
 #ifdef CY_DEBUG_DTR
 		printk("cyc:shutdown dropping Z DTR\n");
@@ -2512,16 +2508,21 @@
 	ch_ctrl = zfw_ctrl->ch_ctrl;
 
 	while (1) {
-	    cy_writel(&ch_ctrl[channel].rs_control,
-               cy_readl(&ch_ctrl[channel].rs_control) | C_RS_RTS | C_RS_DTR);
-	    retval = cyz_issue_cmd(&cy_card[info->card],
-		    channel, C_CM_IOCTLM, 0L);
-	    if (retval != 0){
-		printk("cyc:block_til_ready retval was %x\n", retval);
-	    }
+	    if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
+		(tty->termios->c_cflag & CBAUD)){
+		cy_writel(&ch_ctrl[channel].rs_control,
+			  cy_readl(&ch_ctrl[channel].rs_control) | 
+			  (C_RS_RTS | C_RS_DTR));
+		retval = cyz_issue_cmd(&cy_card[info->card],
+				       channel, C_CM_IOCTLM, 0L);
+		if (retval != 0){
+		    printk("cyc:block_til_ready retval on ttyC%d was %x\n", 
+			   info->line, retval);
+		}
 #ifdef CY_DEBUG_DTR
-		    printk("cyc:block_til_ready raising Z DTR\n");
+		printk("cyc:block_til_ready raising Z DTR\n");
 #endif
+	    }
 
 	    current->state = TASK_INTERRUPTIBLE;
 	    if (tty_hung_up_p(filp)
@@ -2895,7 +2896,8 @@
 	    retval = cyz_issue_cmd(&cy_card[info->card], channel, 
 				   C_CM_IOCTLW, 0L);
 	    if (retval != 0){
-		printk("cyc:cy_close retval was %x\n", retval);
+		printk("cyc:cy_close retval on ttyC%d was %x\n", 
+		       info->line, retval);
 	    }
 	    CY_UNLOCK(info, flags);
 	    interruptible_sleep_on(&info->shutdown_wait);
@@ -3502,8 +3504,8 @@
 
 	retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTL, 0L);
 	if (retval != 0){
-	    printk("cyc:set_line_char retval at %d was %x\n",
-	        __LINE__, retval);
+	    printk("cyc:set_line_char retval on ttyC%d was %x\n", 
+		   info->line, retval);
 	}
 
 	/* CD sensitivity */
@@ -3529,8 +3531,8 @@
 
 	retval = cyz_issue_cmd( &cy_card[card], channel, C_CM_IOCTLM, 0L);
 	if (retval != 0){
-	    printk("cyc:set_line_char retval at %d was %x\n",
-	        __LINE__, retval);
+	    printk("cyc:set_line_char(2) retval on ttyC%d was %x\n", 
+		   info->line, retval);
 	}
 
 	if (info->tty){
@@ -3906,8 +3908,8 @@
         retval = cyz_issue_cmd(&cy_card[info->card],
 				    channel, C_CM_IOCTLM,0L);
 	if (retval != 0){
-	    printk("cyc:set_modem_info retval at %d was %x\n",
-	        __LINE__, retval);
+	    printk("cyc:set_modem_info retval on ttyC%d was %x\n", 
+		   info->line, retval);
 	}
 	CY_UNLOCK(info, flags);
     }
@@ -3958,16 +3960,16 @@
 		(info->line) - (cy_card[info->card].first_line),
 		C_CM_SET_BREAK, 0L);
 	    if (retval != 0) {
-		printk("cyc:cy_break (set) retval at %d was %x\n",
-		        __LINE__, retval);
+		printk("cyc:cy_break (set) retval on ttyC%d was %x\n", 
+		       info->line, retval);
 	    }
 	} else {
 	    retval = cyz_issue_cmd(&cy_card[info->card],
 		(info->line) - (cy_card[info->card].first_line),
 		C_CM_CLR_BREAK, 0L);
 	    if (retval != 0) {
-		printk("cyc:cy_break (clr) retval at %d was %x\n",
-		        __LINE__, retval);
+		printk("cyc:cy_break (clr) retval on ttyC%d was %x\n", 
+		       info->line, retval);
 	    }
 	}
     }
@@ -4339,7 +4341,7 @@
 
     if ((old_termios->c_cflag & CRTSCTS) &&
         !(tty->termios->c_cflag & CRTSCTS)) {
-            tty->stopped = 0;
+            tty->hw_stopped = 0;
             cy_start(tty);
     }
 #if 0
@@ -4580,7 +4582,8 @@
 	CY_LOCK(info, flags);
 	retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_TX, 0L);
 	if (retval != 0) {
-	    printk("cyc: flush_buffer retval was %x\n", retval);
+	    printk("cyc: flush_buffer retval on ttyC%d was %x\n", 
+		   info->line, retval);
 	}
 	CY_UNLOCK(info, flags);
     }
@@ -5479,6 +5482,8 @@
 			     cy_card[board].ctl_addr)->mail_box_0);
 		nports = (mailbox == ZE_V1) ? ZE_V1_NPORTS : 8;
 		cinfo->intr_enabled = 0;
+		cinfo->nports = 0; /* Will be correctly set later, after 
+				      Z FW is loaded */
 		spin_lock_init(&cinfo->card_lock);
                 for (port = cinfo->first_line ;
                      port < cinfo->first_line + nports;
@@ -5515,9 +5520,6 @@
                     info->x_char = 0;
                     info->event = 0;
                     info->count = 0;
-#ifdef CY_DEBUG_COUNT
-//        printk("cyc:cy_init(1) setting Z count to 0\n");
-#endif
                     info->blocked_open = 0;
                     info->default_threshold = 0;
                     info->default_timeout = 0;
@@ -5540,13 +5542,17 @@
                     info->jiffies[1] = 0;
                     info->jiffies[2] = 0;
                     info->rflush_count = 0;
+#ifdef CONFIG_CYZ_INTR
+		    cyz_rx_full_timer[port].function = NULL;
+#endif
                 }
                 continue;
             }else{ /* Cyclom-Y of some kind*/
                 index = cinfo->bus_index;
 		spin_lock_init(&cinfo->card_lock);
+		cinfo->nports = CyPORTS_PER_CHIP * cinfo->num_chips;
                 for (port = cinfo->first_line ;
-                     port < cinfo->first_line + 4*cinfo->num_chips ;
+                     port < cinfo->first_line + cinfo->nports ;
                      port++)
                 {
                     info = &cy_port[port];
@@ -5591,9 +5597,6 @@
                     info->x_char = 0;
                     info->event = 0;
                     info->count = 0;
-#ifdef CY_DEBUG_COUNT
-//        printk("cyc:cy_init(2) setting Y count to 0\n");
-#endif
                     info->blocked_open = 0;
                     info->default_threshold = 0;
                     info->default_timeout = 0;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/generic_serial.c linux.15p9/drivers/char/generic_serial.c
--- linux.vanilla/drivers/char/generic_serial.c	Sat Aug 28 20:00:55 1999
+++ linux.15p9/drivers/char/generic_serial.c	Tue Jan 18 00:52:10 2000
@@ -19,93 +19,11 @@
 #include <linux/mm.h>
 #include <asm/semaphore.h>
 #include <linux/version.h>
+#include <linux/module.h>
+#include <linux/compatmac.h>
+#include <linux/generic_serial.h>
 
-
-#if LINUX_VERSION_CODE < 0x020100    /* Less than 2.1.0 */
-#define TWO_ZERO
-#else
-#if LINUX_VERSION_CODE < 0x020200   /* less than 2.2.x */
-#warning "Please use a 2.2.x kernel. "
-#else
-#if LINUX_VERSION_CODE < 0x020300   /* less than 2.2.x */
-#define TWO_TWO
-#else
-#define TWO_THREE
-#endif
-#endif
-#endif
-
-#ifdef TWO_ZERO
-
-/* Here is the section that makes the 2.2 compatible driver source 
-   work for 2.0 too! We mostly try to adopt the "new thingies" from 2.2, 
-   and provide for compatibility stuff here if possible. */
-
-/* Some 200 days (on intel) */
-#define MAX_SCHEDULE_TIMEOUT     ((long)(~0UL>>1))
-
-
-#ifndef MODULE
-
-#define copy_to_user(a,b,c)          memcpy_tofs(a,b,c)
-
-static inline int copy_from_user(void *to,const void *from, int c) 
-{
-	memcpy_fromfs(to, from, c);
-	return 0;
-}
-
-
-#define capable(x)                   suser()
-
-#define queue_task                   queue_task_irq_off
-#define tty_flip_buffer_push(tty)    queue_task(&tty->flip.tqueue, &tq_timer)
-#define signal_pending(current)      (current->signal & ~current->blocked)
-#define schedule_timeout(to)         do {current->timeout = jiffies + (to);schedule ();} while (0)
-#define time_after(t1,t2)            (((long)t1-t2) > 0)
-
-#define test_and_set_bit(nr, addr)   set_bit(nr, addr)
-#define test_and_clear_bit(nr, addr) clear_bit(nr, addr)
-
-/* Not yet implemented on 2.0 */
-#define ASYNC_SPD_SHI  -1
-#define ASYNC_SPD_WARP -1
-
-
-
-/* Ugly hack: the driver_name doesn't exist in 2.0.x . So we define it
-   to the "name" field that does exist. As long as the assignments are
-   done in the right order, there is nothing to worry about. */
-#define driver_name           name 
-
-
-/* Should be in a header somewhere. */
-#define TTY_HW_COOK_OUT       14 /* Flag to tell ntty what we can handle */
-#define TTY_HW_COOK_IN        15 /* in hardware - output and input       */
-#endif
-
-#endif
-
-#ifndef TWO_ZERO
-/* This include is new with 2.2  (and required!) */
-#include <asm/uaccess.h>
-#endif
-
-#ifndef TWO_THREE
-/* These are new in 2.3. The source now uses 2.3 syntax, and here is 
-   the compatibility define... */
-#define wait_queue_head_t struct wait_queue *
-#define DECLARE_MUTEX(name) struct semaphore name = MUTEX
-#define DECLARE_WAITQUEUE(wait, current) struct wait_queue wait = { current, NULL }
-
-#endif
-
-#include "generic_serial.h"
-
-
-#ifndef MODULE
-extern void my_hd (unsigned char *ptr, int n);
-#endif
+#define DEBUG 
 
 static char *                  tmp_buf; 
 static DECLARE_MUTEX(tmp_buf_sem);
@@ -119,8 +37,8 @@
 #define gs_dprintk(f, str...) /* nothing */
 #endif
 
-#define func_enter() gs_dprintk (SX_DEBUG_FLOW, "gs: enter " __FUNCTION__ "\n")
-#define func_exit()  gs_dprintk (SX_DEBUG_FLOW, "gs: exit  " __FUNCTION__ "\n")
+#define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter " __FUNCTION__ "\n")
+#define func_exit()  gs_dprintk (GS_DEBUG_FLOW, "gs: exit  " __FUNCTION__ "\n")
 
 
 
@@ -135,6 +53,27 @@
 #endif
 
 
+#ifdef DEBUG
+static void my_hd (unsigned char *addr, int len)
+{
+	int i, j, ch;
+
+	for (i=0;i<len;i+=16) {
+		printk ("%08x ", (int) addr+i);
+		for (j=0;j<16;j++) {
+			printk ("%02x %s", addr[j+i], (j==7)?" ":"");
+		}
+		for (j=0;j<16;j++) {
+			ch = addr[j+i];
+			printk ("%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch));
+		}
+		printk ("\n");
+	}
+}
+#else
+#define my_hd(addr,len) 
+#endif
+
 
 void gs_put_char(struct tty_struct * tty, unsigned char ch)
 {
@@ -397,16 +336,19 @@
 	if (!tty) return 0;
 	port = tty->driver_data;
 
+	if (!port->rd) return 0;
+	if (!port->rd->chars_in_buffer) return 0;
+
 	func_exit ();
 	return port->xmit_cnt + port->rd->chars_in_buffer (port);
 }
 
 
-static void gs_wait_tx_flushed (void * ptr, int timeout) 
+static int gs_wait_tx_flushed (void * ptr, int timeout) 
 {
 	struct gs_port *port = ptr;
 	long end_jiffies;
-	int jiffies_to_transmit, charsleft;
+	int jiffies_to_transmit, charsleft = 0, rv = 0;
 	int to, rcib;
 
 	func_enter();
@@ -420,7 +362,7 @@
 	if (!port || port->xmit_cnt < 0 || !port->xmit_buf) {
 		gs_dprintk (GS_DEBUG_FLUSH, "ERROR: !port, !port->xmit_buf or prot->xmit_cnt < 0.\n");
 	func_exit();
-		return;  /* This is an error which we don't know how to handle. */
+		return -EINVAL;  /* This is an error which we don't know how to handle. */
 	}
 	gs_dprintk (GS_DEBUG_FLUSH, "checkpoint 1\n");
 
@@ -430,8 +372,8 @@
 
 	if(rcib <= 0) {
 		gs_dprintk (GS_DEBUG_FLUSH, "nothing to wait for.\n");
-	func_exit();
-	return;
+		func_exit();
+		return rv;
 	}
 	gs_dprintk (GS_DEBUG_FLUSH, "checkpoint 3\n");
 
@@ -464,14 +406,18 @@
 
 		current->state = TASK_INTERRUPTIBLE;
 		schedule_timeout(jiffies_to_transmit);
-		if (signal_pending (current))
+		if (signal_pending (current)) {
+			gs_dprintk (GS_DEBUG_FLUSH, "Signal pending. Bombing out: "); 
+			rv = -EINTR;
 			break;
+		}
 	}
 
 	gs_dprintk (GS_DEBUG_FLUSH, "charsleft = %d.\n", charsleft); 
 	current->state = TASK_RUNNING;
 
 	func_exit();
+	return rv;
 }
 
 
@@ -750,8 +696,10 @@
 		func_exit();
 		return;
 	}
+
 	if (!port->tty) {
-		printk (KERN_WARNING "gs: Odd: port->tty is NULL\n");
+		/* This seems to happen when this is called from vhangup. */
+		gs_dprintk (GS_DEBUG_CLOSE, "gs: Odd: port->tty is NULL\n");
 		port->tty = tty;
 	}
 
@@ -775,6 +723,7 @@
 		port->count = 0;
 	}
 	if (port->count) {
+		gs_dprintk(GS_DEBUG_CLOSE, "gs_close: count: %d\n", port->count);
 		restore_flags(flags);
 		func_exit ();
 		return;
@@ -806,6 +755,7 @@
 
 	port->rd->disable_rx_interrupts (port);
 
+	/* close has no way of returning "EINTR", so discard return value */
 	if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
 		gs_wait_tx_flushed (port, port->closing_wait); 
 
@@ -816,8 +766,12 @@
 	if (tty->ldisc.flush_buffer)
 		tty->ldisc.flush_buffer(tty);
 	tty->closing = 0;
+
 	port->event = 0;
+	port->rd->close (port);
+	port->rd->shutdown_port (port);
 	port->tty = 0;
+
 	if (port->blocked_open) {
 		if (port->close_delay) {
 			current->state = TASK_INTERRUPTIBLE;
@@ -829,8 +783,6 @@
 	                 ASYNC_CLOSING | ASYNC_INITIALIZED);
 	wake_up_interruptible(&port->close_wait);
 
-	port->rd->close (port);
-	port->rd->shutdown_port (port);
 	restore_flags(flags);
 	func_exit ();
 }
@@ -846,7 +798,7 @@
                      struct termios * old_termios)
 {
 	struct gs_port *port = tty->driver_data;
-	int baudrate, tmp;
+	int baudrate, tmp, rv;
 	struct termios *tiosp;
 
 	func_enter();
@@ -872,7 +824,7 @@
 		   && (tiosp->c_line  == old_termios->c_line)
 		   && (memcmp(tiosp->c_cc, old_termios->c_cc, NCC) == 0)) {
 			gs_dprintk(GS_DEBUG_TERMIOS, "gs_set_termios: optimized away\n");
-			return;
+			return /* 0 */;
 		}
 	} else 
 		gs_dprintk(GS_DEBUG_TERMIOS, "gs_set_termios: no old_termios: "
@@ -928,9 +880,11 @@
 
 	/* We should really wait for the characters to be all sent before
 	   changing the settings. -- CAL */
-	gs_wait_tx_flushed (port, MAX_SCHEDULE_TIMEOUT);
+	rv = gs_wait_tx_flushed (port, MAX_SCHEDULE_TIMEOUT);
+	if (rv < 0) return /* rv */;
 
-	port->rd->set_real_termios(port);
+	rv = port->rd->set_real_termios(port);
+	if (rv < 0) return /* rv */;
 
 	if ((!old_termios || 
 	     (old_termios->c_cflag & CRTSCTS)) &&
@@ -948,7 +902,7 @@
 #endif
 
 	func_exit();
-	return;
+	return /* 0 */;
 }
 
 
@@ -1072,3 +1026,15 @@
 	copy_to_user(sp, &sio, sizeof(struct serial_struct));
 }
 
+
+#ifdef MODULE
+int init_module (void)
+{
+  return 0;
+}
+
+int cleanup_module (void)
+{
+  return 0;
+}
+#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/generic_serial.h linux.15p9/drivers/char/generic_serial.h
--- linux.vanilla/drivers/char/generic_serial.h	Sat Aug 14 02:27:17 1999
+++ linux.15p9/drivers/char/generic_serial.h	Tue Jan 18 00:52:10 2000
@@ -1,101 +0,0 @@
-/*
- *  generic_serial.h
- *
- *  Copyright (C) 1998 R.E.Wolff@BitWizard.nl
- *
- *  written for the SX serial driver.
- *     Contains the code that should be shared over all the serial drivers.
- *
- *  Version 0.1 -- December, 1998.
- */
-
-#ifndef GENERIC_SERIAL_H
-#define GENERIC_SERIAL_H
-
-struct real_driver {
-  void                    (*disable_tx_interrupts) (void *);
-  void                    (*enable_tx_interrupts) (void *);
-  void                    (*disable_rx_interrupts) (void *);
-  void                    (*enable_rx_interrupts) (void *);
-  int                     (*get_CD) (void *);
-  void                    (*shutdown_port) (void*);
-  void                    (*set_real_termios) (void*);
-  int                     (*chars_in_buffer) (void*);
-  void                    (*close) (void*);
-  void                    (*hungup) (void*);
-  void                    (*getserial) (void*, struct serial_struct *sp);
-};
-
-
-
-struct gs_port {
-  int                     magic;
-  unsigned char           *xmit_buf; 
-  int                     xmit_head;
-  int                     xmit_tail;
-  int                     xmit_cnt;
-  /*  struct semaphore        port_write_sem; */
-  int                     flags;
-  struct termios          normal_termios;
-  struct termios          callout_termios;
-  wait_queue_head_t       open_wait;
-  wait_queue_head_t       close_wait;
-  long                    session;
-  long                    pgrp;
-  int                     count;
-  int                     blocked_open;
-  struct tty_struct       *tty;
-  int                     event;
-  unsigned short          closing_wait;
-  int                     close_delay;
-  struct real_driver      *rd;
-  int                     wakeup_chars;
-  int                     baud_base;
-  int                     baud;
-  int                     custom_divisor;
-};
-
-
-/* Flags */
-/* Warning: serial.h defines some ASYNC_ flags, they say they are "only"
-   used in serial.c, but they are also used in all other serial drivers. 
-   Make sure they don't clash with these here... */
-#define GS_TX_INTEN      0x00800000
-#define GS_RX_INTEN      0x00400000
-#define GS_ACTIVE        0x00200000
-
-
-
-#define GS_TYPE_NORMAL   1
-#define GS_TYPE_CALLOUT  2
-
-
-#define GS_DEBUG_FLUSH   0x00000001
-#define GS_DEBUG_BTR     0x00000002
-#define GS_DEBUG_TERMIOS 0x00000004
-#define GS_DEBUG_STUFF   0x00000008
-#define GS_DEBUG_CLOSE   0x00000010
-
-
-void gs_put_char(struct tty_struct *tty, unsigned char ch);
-int  gs_write(struct tty_struct *tty, int from_user, 
-             const unsigned char *buf, int count);
-int  gs_write_room(struct tty_struct *tty);
-int  gs_chars_in_buffer(struct tty_struct *tty);
-void gs_flush_buffer(struct tty_struct *tty);
-void gs_flush_chars(struct tty_struct *tty);
-void gs_stop(struct tty_struct *tty);
-void gs_start(struct tty_struct *tty);
-void gs_hangup(struct tty_struct *tty);
-void gs_do_softint(void *private_);
-int  block_til_ready(void *port, struct file *filp);
-void gs_close(struct tty_struct *tty, struct file *filp);
-void gs_set_termios (struct tty_struct * tty, 
-                     struct termios * old_termios);
-int  gs_init_port(struct gs_port *port);
-int  gs_setserial(struct gs_port *port, struct serial_struct *sp);
-void gs_getserial(struct gs_port *port, struct serial_struct *sp);
-
-extern int gs_debug;
-
-#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/istallion.c linux.15p9/drivers/char/istallion.c
--- linux.vanilla/drivers/char/istallion.c	Sat Aug 14 02:25:39 1999
+++ linux.15p9/drivers/char/istallion.c	Mon Feb  7 12:07:56 2000
@@ -3,8 +3,8 @@
 /*
  *	istallion.c  -- stallion intelligent multiport serial driver.
  *
- *	Copyright (C) 1996-1999  Stallion Technologies (support@stallion.oz.au).
- *	Copyright (C) 1994-1996  Greg Ungerer (gerg@stallion.oz.au).
+ *	Copyright (C) 1996-2000  Stallion Technologies (support@stallion.oz.au)
+ *	Copyright (C) 1994-1996  Greg Ungerer.
  *
  *	This code is loosely based on the Linux serial driver, written by
  *	Linus Torvalds, Theodore T'so and others.
@@ -167,7 +167,7 @@
  */
 static char	*stli_drvtitle = "Stallion Intelligent Multiport Serial Driver";
 static char	*stli_drvname = "istallion";
-static char	*stli_drvversion = "5.5.1";
+static char	*stli_drvversion = "5.6.0";
 static char	*stli_serialname = "ttyE";
 static char	*stli_calloutname = "cue";
 
@@ -383,7 +383,7 @@
 /*
  *	Define the module agruments.
  */
-MODULE_AUTHOR("Greg Ungerer");
+MODULE_AUTHOR("Stallion Technologies (support@stallion.oz.au)");
 MODULE_DESCRIPTION("Stallion Intelligent Multiport Serial Driver");
 
 MODULE_PARM(board0, "1-3s");
@@ -711,6 +711,8 @@
 static int	stli_getportstats(stliport_t *portp, comstats_t *cp);
 static int	stli_portcmdstats(stliport_t *portp);
 static int	stli_clrportstats(stliport_t *portp, comstats_t *cp);
+static int	stli_geticounters(stliport_t *portp,
+				  struct serial_icounter_struct *cp);
 static int	stli_getportstruct(unsigned long arg);
 static int	stli_getbrdstruct(unsigned long arg);
 static void	*stli_memalloc(int len);
@@ -2170,6 +2172,13 @@
 		    sizeof(comstats_t))) == 0)
 			rc = stli_clrportstats(portp, (comstats_t *) arg);
 		break;
+	case TIOCGICOUNT:
+		if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
+		    sizeof(struct serial_icounter_struct *))) == 0)
+			rc = stli_geticounters(portp,
+				      (struct serial_icounter_struct *) arg);
+		break;
+
 	case TIOCSERCONFIG:
 	case TIOCSERGWILD:
 	case TIOCSERSWILD:
@@ -3375,6 +3384,9 @@
 		portp->closing_wait = 30 * HZ;
 		portp->tqhangup.routine = stli_dohangup;
 		portp->tqhangup.data = portp;
+		portp->open_wait = 0;
+		portp->close_wait = 0;
+		portp->raw_wait = 0;
 		portp->normaltermios = stli_deftermios;
 		portp->callouttermios = stli_deftermios;
 		panelport++;
@@ -5138,6 +5150,33 @@
 
 	copy_to_user(cp, &stli_comstats, sizeof(comstats_t));
 	return(0);
+}
+
+static int stli_geticounters(stliport_t *portp,
+			     struct serial_icounter_struct *icp)
+{
+	struct serial_icounter_struct icount;
+	comstats_t *s	= &stli_comstats;
+	int rc;
+	
+	if ((rc = stli_portcmdstats(portp)) < 0)
+		return(rc);
+	
+	memset(&icount, 0, sizeof(icount));
+	
+	/*
+	 * we only support a subset of the icounters - the others are handled
+	 * by the uart and we don't get interrupted for them
+	 */
+	icount.dcd	= s->modem;
+	icount.rx	= s->rxtotal;
+	icount.tx	= s->txtotal;
+	icount.frame	= s->rxframing;
+	icount.overrun	= s->rxoverrun;
+	icount.parity	= s->rxparity;
+	icount.brk	= s->rxbreaks;
+	
+	return (copy_to_user(icp, &icount, sizeof(icount)));
 }
 
 /*****************************************************************************/
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/joystick/joy-creative.c linux.15p9/drivers/char/joystick/joy-creative.c
--- linux.vanilla/drivers/char/joystick/joy-creative.c	Tue Jan  4 21:18:45 2000
+++ linux.15p9/drivers/char/joystick/joy-creative.c	Mon Feb  7 12:24:45 2000
@@ -66,7 +66,7 @@
 	int r[2], t[2], p[2];
 	int i, j, ret;
 
-	for (i = 0; i < 2; i++); {
+	for (i = 0; i < 2; i++) {
 		r[i] = buf[i] = 0;
 		p[i] = t[i] = JS_CR_MAX_STROBE;
 		p[i] += JS_CR_MAX_STROBE;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/misc.c linux.15p9/drivers/char/misc.c
--- linux.vanilla/drivers/char/misc.c	Sat Aug 14 02:27:17 1999
+++ linux.15p9/drivers/char/misc.c	Wed Feb 16 18:35:25 2000
@@ -236,7 +236,7 @@
 	dtlk_init();
 #endif
 #ifdef CONFIG_APM
-	apm_bios_init();
+	apm_init();
 #endif
 #ifdef CONFIG_H8
 	h8_init();
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/n_tty.c linux.15p9/drivers/char/n_tty.c
--- linux.vanilla/drivers/char/n_tty.c	Wed Oct 20 01:12:35 1999
+++ linux.15p9/drivers/char/n_tty.c	Wed Feb 16 20:19:24 2000
@@ -17,6 +17,10 @@
  * 
  * This file may be redistributed under the terms of the GNU Public
  * License.
+ *
+ * 2000/01/20   Fixed SMP locking on put_tty_queue using bits of 
+ *		the patch by Andrew J. Kroll <ag784@freenet.buffalo.edu>
+ *		who actually finally proved there really was a race.
  */
 
 #include <linux/types.h>
@@ -38,6 +42,7 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
+#include <asm/spinlock.h>
 
 #define CONSOLE_DEV MKDEV(TTY_MAJOR,0)
 #define SYSCONS_DEV  MKDEV(TTYAUX_MAJOR,1)
@@ -57,13 +62,22 @@
 #define TTY_THRESHOLD_THROTTLE		128 /* now based on remaining room */
 #define TTY_THRESHOLD_UNTHROTTLE 	128
 
+static spinlock_t __attribute((unused)) tty_put_lock = SPIN_LOCK_UNLOCKED;
+
 static inline void put_tty_queue(unsigned char c, struct tty_struct *tty)
 {
+	unsigned long flags;
+	/*
+	 *	The problem of stomping on the buffers ends here.
+	 *	Why didn't anyone see this one comming? --AJK
+	*/
+	spin_lock_irqsave(&tty_put_lock, flags);
 	if (tty->read_cnt < N_TTY_BUF_SIZE) {
 		tty->read_buf[tty->read_head] = c;
 		tty->read_head = (tty->read_head + 1) & (N_TTY_BUF_SIZE-1);
 		tty->read_cnt++;
 	}
+	spin_unlock_irqrestore(&tty_put_lock, flags);
 }
 
 /* 
@@ -1094,7 +1108,9 @@
 				nr -= num;
 				if (nr == 0)
 					break;
+				current->state = TASK_RUNNING;
 				get_user(c, b);
+				current->state = TASK_INTERRUPTIBLE;
 				if (opost(c, tty) < 0)
 					break;
 				b++; nr--;
@@ -1102,7 +1118,9 @@
 			if (tty->driver.flush_chars)
 				tty->driver.flush_chars(tty);
 		} else {
+			current->state = TASK_RUNNING;
 			c = tty->driver.write(tty, 1, b, nr);
+			current->state = TASK_INTERRUPTIBLE;
 			if (c < 0) {
 				retval = c;
 				goto break_out;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/radio-gemtek.c linux.15p9/drivers/char/radio-gemtek.c
--- linux.vanilla/drivers/char/radio-gemtek.c	Sat Aug 14 02:27:17 1999
+++ linux.15p9/drivers/char/radio-gemtek.c	Wed Jan 26 23:00:52 2000
@@ -282,7 +282,7 @@
 MODULE_AUTHOR("Jonas Munsin");
 MODULE_DESCRIPTION("A driver for the GemTek Radio Card");
 MODULE_PARM(io, "i");
-MODULE_PARM_DESC(io, "I/O address of the GemTek card (0x20c, 0x30c, 0x24c or 0x34c (or 0x248 for the combined sound/radiocard))");
+MODULE_PARM_DESC(io, "I/O address of the GemTek card (0x20c, 0x30c, 0x24c or 0x34c (0x20c or 0x248 have been reported to work for the combined sound/radiocard)).");
 
 EXPORT_NO_SYMBOLS;
 
@@ -290,7 +290,7 @@
 {
 	if(io==-1)
 	{
-		printk(KERN_ERR "You must set an I/O address with io=0x20c, io=0x30c, io=0x24c or io=0x34c (or io=0x248 for the combined sound/radiocard)\n");
+		printk(KERN_ERR "You must set an I/O address with io=0x20c, io=0x30c, io=0x24c or io=0x34c (io=0x20c or io=0x248 for the combined sound/radiocard)\n");
 		return -EINVAL;
 	}
 	return gemtek_init(NULL);
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/random.c linux.15p9/drivers/char/random.c
--- linux.vanilla/drivers/char/random.c	Wed Oct 20 01:12:35 1999
+++ linux.15p9/drivers/char/random.c	Wed Jan 12 01:14:43 2000
@@ -1328,6 +1328,7 @@
 			schedule();
 			continue;
 		}
+		current->state = TASK_RUNNING;
 		n = extract_entropy(&random_state, buf, n, 1);
 		if (n < 0) {
 			retval = n;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/Makefile linux.15p9/drivers/char/rio/Makefile
--- linux.vanilla/drivers/char/rio/Makefile	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/Makefile	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,22 @@
+#
+# Makefile for the linux rio-subsystem.
+#
+# (C) R.E.Wolff@BitWizard.nl 
+# 
+# This file is GPL. See other files for the full Blurb. I'm lazy today. 
+#
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+O_TARGET := rio.o
+O_OBJS   := rio_linux.o rioinit.o rioboot.o riocmd.o rioctrl.o riointr.o \
+            rioparam.o riopcicopy.o rioroute.o riotable.o riotty.o
+M_OBJS   := $(O_TARGET)
+
+include $(TOPDIR)/Rules.make
+
+rio.o: $(O_OBJS)
\ No newline at end of file
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/board.h linux.15p9/drivers/char/rio/board.h
--- linux.vanilla/drivers/char/rio/board.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/board.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,143 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources. 
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: board.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:07
+**	Retrieved	: 11/6/98 11:34:20
+**
+**  ident @(#)board.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef	__rio_board_h__
+#define	__rio_board_h__
+
+#ifdef SCCS_LABELS
+static char *_board_h_sccs_ = "@(#)board.h	1.2";
+#endif
+
+/*
+** board.h contains the definitions for the *hardware* of the host cards.
+** It describes the memory overlay for the dual port RAM area.
+*/
+
+#define	DP_SRAM1_SIZE	0x7C00
+#define	DP_SRAM2_SIZE	0x0200
+#define	DP_SRAM3_SIZE	0x7000
+#define	DP_SCRATCH_SIZE	0x1000
+#define	DP_PARMMAP_ADDR	0x01FE	/* offset into SRAM2 */
+#define	DP_STARTUP_ADDR	0x01F8	/* offset into SRAM2 */
+
+/*
+**	The shape of the Host Control area, at offset 0x7C00, Write Only
+*/
+struct s_Ctrl
+{
+	BYTE	DpCtl;				/* 7C00 */
+	BYTE	Dp_Unused2_[127];
+	BYTE	DpIntSet;			/* 7C80 */
+	BYTE	Dp_Unused3_[127];
+	BYTE	DpTpuReset;			/* 7D00 */
+	BYTE	Dp_Unused4_[127];
+	BYTE	DpIntReset;			/* 7D80 */
+	BYTE	Dp_Unused5_[127];
+};
+
+/*
+** The PROM data area on the host (0x7C00), Read Only
+*/
+struct s_Prom
+{
+	WORD	DpSlxCode[2];
+	WORD	DpRev;
+	WORD	Dp_Unused6_;
+	WORD	DpUniq[4];
+	WORD	DpJahre;
+	WORD	DpWoche;
+	WORD	DpHwFeature[5];
+	WORD	DpOemId;
+	WORD	DpSiggy[16];
+};
+
+/*
+** Union of the Ctrl and Prom areas
+*/
+union u_CtrlProm	/* This is the control/PROM area (0x7C00) */
+{
+	struct s_Ctrl	DpCtrl;
+	struct s_Prom	DpProm;
+};
+
+/*
+** The top end of memory!
+*/
+struct s_ParmMapS		/* Area containing Parm Map Pointer */
+{
+	BYTE	Dp_Unused8_[DP_PARMMAP_ADDR];
+	WORD	DpParmMapAd;
+};
+
+struct s_StartUpS
+{
+	BYTE    Dp_Unused9_[DP_STARTUP_ADDR];
+	BYTE	Dp_LongJump[0x4];
+	BYTE	Dp_Unused10_[2];
+	BYTE	Dp_ShortJump[0x2];
+};
+
+union u_Sram2ParmMap	/* This is the top of memory (0x7E00-0x7FFF) */
+{
+	BYTE	DpSramMem[DP_SRAM2_SIZE];
+	struct s_ParmMapS DpParmMapS;
+	struct s_StartUpS DpStartUpS;
+};
+
+/*
+**	This is the DP RAM overlay.
+*/
+struct DpRam
+{
+    BYTE 		 DpSram1[DP_SRAM1_SIZE];     /* 0000 - 7BFF */
+    union u_CtrlProm     DpCtrlProm;                 /* 7C00 - 7DFF */
+    union u_Sram2ParmMap DpSram2ParmMap;             /* 7E00 - 7FFF */
+    BYTE		 DpScratch[DP_SCRATCH_SIZE]; /* 8000 - 8FFF */
+    BYTE		 DpSram3[DP_SRAM3_SIZE];     /* 9000 - FFFF */
+};
+
+#define	DpControl	DpCtrlProm.DpCtrl.DpCtl
+#define	DpSetInt	DpCtrlProm.DpCtrl.DpIntSet
+#define	DpResetTpu	DpCtrlProm.DpCtrl.DpTpuReset
+#define	DpResetInt	DpCtrlProm.DpCtrl.DpIntReset
+
+#define	DpSlx		DpCtrlProm.DpProm.DpSlxCode
+#define	DpRevision	DpCtrlProm.DpProm.DpRev
+#define	DpUnique	DpCtrlProm.DpProm.DpUniq
+#define	DpYear		DpCtrlProm.DpProm.DpJahre
+#define	DpWeek		DpCtrlProm.DpProm.DpWoche
+#define	DpSignature	DpCtrlProm.DpProm.DpSiggy
+
+#define	DpParmMapR	DpSram2ParmMap.DpParmMapS.DpParmMapAd
+#define	DpSram2		DpSram2ParmMap.DpSramMem
+
+#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/bootpkt.h linux.15p9/drivers/char/rio/bootpkt.h
--- linux.vanilla/drivers/char/rio/bootpkt.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/bootpkt.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,62 @@
+
+
+/****************************************************************************
+ *******                                                              *******
+ *******        B O O T    P A C K E T   H E A D E R   F I L E
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _pkt_h
+#define _pkt_h 1
+
+#ifndef lint
+#ifdef SCCS
+static char *_rio_bootpkt_h_sccs = "@(#)bootpkt.h	1.1" ;
+#endif
+#endif
+
+    /*************************************************
+     * Overlayed onto the Data fields of a regular
+     * Packet
+     ************************************************/
+typedef struct BOOT_PKT BOOT_PKT ;
+struct BOOT_PKT {
+                    short     seq_num ;
+                    char      data[10] ;
+                } ;
+
+
+#endif
+
+/*********** end of file ***********/
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/brates.h linux.15p9/drivers/char/rio/brates.h
--- linux.vanilla/drivers/char/rio/brates.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/brates.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,107 @@
+/****************************************************************************
+ *******                                                              *******
+ *******		BRATES.H				      *******
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Jeremy Rolls
+ Date    : 1 Nov 1990
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _brates_h
+#ifndef lint
+/* static char * _brates_h_sccs = "@(#)brates.h	1.4"; */
+#endif
+#define _brates_h 1
+/* List of baud rate defines. Most are borrowed from /usr/include/sys/termio.h
+*/
+#ifndef INKERNEL
+
+#define	B0	0x00
+#define	B50	0x01
+#define	B75	0x02
+#define	B110	0x03
+#define	B134	0x04
+#define	B150	0x05
+#define	B200	0x06
+#define	B300	0x07
+#define	B600	0x08
+#define	B1200	0x09
+#define	B1800	0x0a
+#define	B2400	0x0b
+#define	B4800	0x0c
+#define	B9600	0x0d
+#define	B19200	0x0e
+#define	B38400	0x0f
+
+#endif
+
+/*
+** The following baudrates may or may not be defined
+** on various UNIX systems.
+** If they are not then we define them.
+** If they are then we do not define them ;-)
+**
+** This is appalling that we use same definitions as UNIX
+** for our own download code as there is no garuntee that
+** B57600 will be defined as 0x11 by a UNIX system....
+** Arghhhhh!!!!!!!!!!!!!!
+*/
+#if !defined(B56000)
+#define	B56000	0x10
+#endif
+
+#if !defined(B57600)
+#define	B57600	0x11
+#endif
+
+#if !defined(B64000)
+#define	B64000	0x12
+#endif
+
+#if !defined(B115200)
+#define	B115200	0x13
+#endif
+
+
+#if !defined(B2000)
+#define B2000	0x14
+#endif
+
+
+#define MAX_RATE B2000
+
+struct    baud_rate            /* Tag for baud rates */
+{
+     /* short    host_rate,*/        /* As passed by the driver */
+     short    divisor,          /* The divisor */
+              prescaler;        /* The pre-scaler */
+};
+
+#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/cdproto.h linux.15p9/drivers/char/rio/cdproto.h
--- linux.vanilla/drivers/char/rio/cdproto.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/cdproto.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,55 @@
+/* 
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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 _cirrusprots_h
+#define _cirrusprots_h
+
+#ifdef RTA
+extern void cd1400_reset ( int uart) ;
+extern void cd1400_init ( int uart ) ;
+extern void ccr_wait ( int priority, int port) ;
+extern void cd1400_txstart( int port) ;
+extern void cd1400_rxstart ( int port) ;
+extern void command_acknowledge ( PHB *port_header ) ;
+extern int close_port ( ushort port, PHB *port_header, ushort preemptive, int pseudo) ;
+extern void command_preemptive ( PKT *packet) ;
+extern void rup_service ( void ) ;
+extern ushort GetModemLines(struct PHB *, register short *);
+extern void cd1400_intr (Process *cirrus_p, ushort *RtaType) ;
+extern void cd1400_mdint ( short port) ;
+extern void cd1400_rxint ( short port) ;
+extern void cd1400_rxexcept ( short port) ;
+extern void cd1400_txdata ( short port, PHB *port_header, PKT *packet) ;
+extern void cd1400_fast_clock(void);
+extern void cd1400_map_baud ( ushort host_rate, ushort *prescaler, ushort *divisor) ;
+extern void cd1400_modem ( ushort port, ushort way) ;
+extern void cd1400_txcommand ( short port, PHB *port_header, PKT *packet) ;
+extern void cd1400_txint ( int port) ;
+void Rprintf( char *RIOPrBuf, char *Str, ... );
+#if defined(DCIRRUS)
+void debug_packet(PKT *pkt, int option, char *string, int channel);
+#endif	/* defined(DCIRRUS) */
+#endif
+
+#ifdef HOST
+extern void wflush (PHB *);
+extern void command_preemptive (PKT *);
+#endif
+
+#endif /* _cirrusprots_h */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/chan.h linux.15p9/drivers/char/rio/chan.h
--- linux.vanilla/drivers/char/rio/chan.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/chan.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,33 @@
+/*
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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 _chan_h
+#define _chan_h
+
+#ifndef lint
+#ifdef SCCS
+static char *_rio_chan_h_sccs = "@(#)chan.h	1.1" ;
+#endif
+#endif
+
+#define Link0   0
+#define Link1   1
+#define Link2   2
+#define Link3   3
+
+#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/cirrus.h linux.15p9/drivers/char/rio/cirrus.h
--- linux.vanilla/drivers/char/rio/cirrus.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/cirrus.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,463 @@
+/****************************************************************************
+ *******                                                              *******
+ *******		CIRRUS.H				      *******
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Jeremy Rolls
+ Date    : 3 Aug 1990
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _cirrus_h
+#ifndef lint
+/* static char* _cirrus_h_sccs = "@(#)cirrus.h	1.16"; */
+#endif
+#define _cirrus_h 1
+
+#ifdef RTA
+#define	TO_UART	RX
+#define TO_DRIVER TX
+#endif
+
+#ifdef HOST
+#define	TO_UART	TX
+#define TO_DRIVER RX
+#endif
+#ifdef RTA
+/* Miscellaneous defines for CIRRUS addresses and related logic for
+   interrupts etc.
+*/
+#define	MAP(a)		((short *)(cirrus_base + (a)))
+#define outp(a,b)	(*MAP (a) =(b))
+#define inp(a)		((*MAP (a)) & 0xff)
+#define	CIRRUS_FIRST	(short*)0x7300
+#define	CIRRUS_SECOND	(short*)0x7200
+#define	CIRRUS_THIRD	(short*)0x7100
+#define	CIRRUS_FOURTH	(short*)0x7000
+#define	PORTS_ON_CIRRUS	4
+#define	CIRRUS_FIFO_SIZE	12
+#define	SPACE		0x20
+#define	TAB		0x09
+#define	LINE_FEED	0x0a
+#define	CARRIAGE_RETURN	0x0d
+#define	BACKSPACE	0x08
+#define	SPACES_IN_TABS	8
+#define	SEND_ESCAPE	0x00
+#define START_BREAK	0x81
+#define	TIMER_TICK	0x82
+#define STOP_BREAK	0x83
+#define BASE(a) ((a) < 4 ? (short*)CIRRUS_FIRST : ((a) < 8 ? (short *)CIRRUS_SECOND : ((a) < 12 ? (short*)CIRRUS_THIRD : (short *)CIRRUS_FOURTH)))
+#define txack1	((short *)0x7104) 
+#define rxack1	((short *)0x7102) 
+#define mdack1  ((short *)0x7106)
+#define txack2  ((short *)0x7006) 
+#define rxack2	((short *)0x7004) 
+#define mdack2  ((short *)0x7100) 
+#define int_latch       ((short *) 0x7800)
+#define int_status      ((short *) 0x7c00) 
+#define tx1_pending     0x20 
+#define rx1_pending     0x10 
+#define md1_pending     0x40 
+#define tx2_pending     0x02 
+#define rx2_pending     0x01 
+#define md2_pending     0x40 
+#define module1_bits	0x07
+#define module1_modern	0x08
+#define module2_bits	0x70
+#define module2_modern	0x80
+#define module_blank	0xf
+#define rs232_d25	0x0
+#define	rs232_rj45	0x1
+#define rs422_d25	0x3
+#define parallel	0x5
+
+#define	CLK0	0x00
+#define CLK1	0x01
+#define CLK2	0x02
+#define CLK3	0x03
+#define CLK4	0x04
+
+#define CIRRUS_REVC    0x42
+#define CIRRUS_REVE    0x44
+
+#define	TURNON	1
+#define TURNOFF 0
+
+/* The list of CIRRUS registers. 
+   NB. These registers are relative values on 8 bit boundaries whereas
+   on the RTA's the CIRRUS registers are on word boundaries. Use pointer
+   arithmetic (short *) to obtain the real addresses required */
+#define ccr	0x05	/* Channel Command Register     */
+#define ier	0x06	/* Interrupt Enable Register    */
+#define cor1	0x08	/* Channel Option Register 1    */
+#define cor2	0x09	/* Channel Option Register 2    */
+#define cor3	0x0a	/* Channel Option Register 3    */
+#define cor4	0x1e	/* Channel Option Register 4    */
+#define	cor5	0x1f	/* Channel Option Register 5	*/
+
+#define ccsr	0x0b	/* Channel Control Status Register */
+#define rdcr	0x0e	/* Receive Data Count Register  */
+#define tdcr	0x12	/* Transmit Data Count Register */
+#define mcor1	0x15	/* Modem Change Option Register 1 */
+#define mcor2	0x16	/* Modem Change Option Regsiter 2 */
+
+#define livr	0x18	/* Local Interrupt Vector Register */
+#define schr1	0x1a	/* Special Character Register 1 */
+#define schr2	0x1b	/* Special Character Register 2 */
+#define schr3	0x1c	/* Special Character Register 3 */
+#define schr4	0x1d	/* Special Character Register 4 */
+
+#define rtr	0x20    /* Receive Timer Register */
+#define rtpr	0x21	/* Receive Timeout Period Register */
+#define lnc	0x24	/* Lnext character */
+
+#define rivr	0x43	/* Receive Interrupt Vector Register    */
+#define tivr	0x42	/* Transmit Interrupt Vector Register   */
+#define mivr	0x41	/* Modem Interrupt Vector Register      */
+#define gfrcr	0x40	/* Global Firmware Revision code Reg    */
+#define ricr	0x44	/* Receive Interrupting Channel Reg     */
+#define ticr	0x45	/* Transmit Interrupting Channel Reg    */
+#define micr	0x46	/* Modem Interrupting Channel Register  */
+
+#define gcr	0x4b	/* Global configuration register*/
+#define misr    0x4c    /* Modem interrupt status register */
+
+#define rbusr	0x59
+#define tbusr	0x5a
+#define mbusr	0x5b
+
+#define eoir	0x60	/* End Of Interrupt Register */
+#define rdsr	0x62	/* Receive Data / Status Register */
+#define tdr	0x63	/* Transmit Data Register */
+#define svrr	0x67	/* Service Request Register */
+
+#define car	0x68	/* Channel Access Register */
+#define mir	0x69	/* Modem Interrupt Register */
+#define tir	0x6a	/* Transmit Interrupt Register */
+#define rir	0x6b	/* Receive Interrupt Register */
+#define msvr1	0x6c	/* Modem Signal Value Register 1 */
+#define msvr2	0x6d	/* Modem Signal Value Register 2*/
+#define psvr	0x6f	/* Printer Signal Value Register*/
+
+#define tbpr	0x72	/* Transmit Baud Rate Period Register */
+#define tcor	0x76	/* Transmit Clock Option Register */
+
+#define rbpr	0x78	/* Receive Baud Rate Period Register */
+#define rber	0x7a	/* Receive Baud Rate Extension Register */
+#define rcor	0x7c	/* Receive Clock Option Register*/
+#define ppr	0x7e	/* Prescalar Period Register    */
+
+/* Misc registers used for forcing the 1400 out of its reset woes */
+#define airl	0x6d
+#define airm	0x6e
+#define airh	0x6f
+#define btcr	0x66
+#define mtcr	0x6c
+#define tber	0x74
+
+#endif				/* #ifdef RTA */
+
+
+/* Bit fields for particular registers */
+
+/* GCR */
+#define GCR_SERIAL	0x00	/* Configure as serial channel */
+#define GCR_PARALLEL	0x80	/* Configure as parallel channel */
+
+/* RDSR - when status read from FIFO */
+#define	RDSR_BREAK		0x08	/* Break received */
+#define RDSR_TIMEOUT    	0x80    /* No new data timeout */
+#define RDSR_SC1  	  	0x10    /* Special char 1 (tx XON) matched */
+#define RDSR_SC2  	  	0x20    /* Special char 2 (tx XOFF) matched */
+#define RDSR_SC12_MASK	  	0x30    /* Mask for special chars 1 and 2 */
+
+/* PPR */
+#define PPR_DEFAULT	0x31	/* Default value - for a 25Mhz clock gives
+				   a timeout period of 1ms */
+
+/* LIVR */
+#define	LIVR_EXCEPTION	0x07	/* Receive exception interrupt */
+
+/* CCR */
+#define	CCR_RESET	0x80	/* Reset channel */
+#define	CCR_CHANGE	0x4e	/* COR's have changed - NB always change all
+				   COR's */
+#define	CCR_WFLUSH	0x82	/* Flush transmit FIFO and TSR / THR */
+
+#define	CCR_SENDSC1	0x21	/* Send special character one */
+#define CCR_SENDSC2	0x22	/* Send special character two */
+#define CCR_SENDSC3	0x23	/* Send special character three */
+#define CCR_SENDSC4	0x24	/* Send special character four */
+
+#define CCR_TENABLE	0x18	/* Enable transmitter */
+#define	CCR_TDISABLE	0x14	/* Disable transmitter */
+#define CCR_RENABLE	0x12	/* Enable receiver */
+#define CCR_RDISABLE	0x11	/* Disable receiver */
+
+#define	CCR_READY	0x00	/* CCR is ready for another command */
+
+/* CCSR */
+#define CCSR_TXENABLE	0x08	/* Transmitter enable */
+#define CCSR_RXENABLE	0x80	/* Receiver enable */
+#define CCSR_TXFLOWOFF	0x04	/* Transmit flow off */
+#define CCSR_TXFLOWON	0x02	/* Transmit flow on */
+
+/* SVRR */
+#define	SVRR_RECEIVE	0x01	/* Receive interrupt pending */
+#define	SVRR_TRANSMIT	0x02	/* Transmit interrupt pending */
+#define	SVRR_MODEM	0x04	/* Modem interrupt pending */
+
+/* CAR */
+#define CAR_PORTS	0x03	/* Bit fields for ports */
+
+/* IER */
+#define	IER_MODEM	0x80	/* Change in modem status */
+#define	IER_RECEIVE	0x10	/* Good data / data exception */
+#define IER_TRANSMITR	0x04	/* Transmit ready (FIFO empty) */
+#define	IER_TRANSMITE	0x02	/* Transmit empty */
+#define IER_TIMEOUT	0x01	/* Timeout on no data */
+
+#define	IER_DEFAULT	0x94	/* Default values */
+#define IER_PARALLEL    0x84    /* Default for Parallel */
+#define	IER_EMPTY	0x92	/* Transmitter empty rather than ready */
+
+/* COR1 - Driver only */
+#define	COR1_INPCK	0x10	/* Check parity of received characters */
+
+/* COR1 - driver and RTA */
+#define	COR1_ODD	0x80	/* Odd parity */
+#define COR1_EVEN	0x00	/* Even parity */
+#define	COR1_NOP	0x00	/* No parity */
+#define	COR1_FORCE	0x20	/* Force parity */
+#define	COR1_NORMAL	0x40	/* With parity */
+#define	COR1_1STOP	0x00	/* 1 stop bit */
+#define	COR1_15STOP	0x04	/* 1.5 stop bits */
+#define	COR1_2STOP	0x08	/* 2 stop bits */
+#define	COR1_5BITS	0x00	/* 5 data bits */
+#define	COR1_6BITS	0x01	/* 6 data bits */
+#define	COR1_7BITS	0x02	/* 7 data bits */
+#define	COR1_8BITS	0x03	/* 8 data bits */
+
+#define COR1_HOST       0xef    /* Safe host bits */
+
+/* RTA only */
+#define COR1_CINPCK     0x00    /* Check parity of received characters */
+#define COR1_CNINPCK    0x10    /* Don't check parity */
+
+/* COR2 bits for both RTA and driver use */
+#define	COR2_IXANY	0x80	/* IXANY - any character is XON */
+#define	COR2_IXON	0x40	/* IXON - enable tx soft flowcontrol */
+#define	COR2_RTSFLOW	0x02	/* Enable tx hardware flow control */
+
+/* Additional driver bits */
+#define	COR2_HUPCL	0x20	/* Hang up on close */
+#define	COR2_CTSFLOW	0x04	/* Enable rx hardware flow control */
+#define	COR2_IXOFF	0x01	/* Enable rx software flow control */
+#define COR2_DTRFLOW	0x08	/* Enable tx hardware flow control */
+
+/* RTA use only */
+#define COR2_ETC	0x20	/* Embedded transmit options */
+#define	COR2_LOCAL	0x10	/* Local loopback mode */
+#define	COR2_REMOTE	0x08	/* Remote loopback mode */
+#define	COR2_HOST	0xc2	/* Safe host bits */
+
+/* COR3 - RTA use only */
+#define	COR3_SCDRNG	0x80	/* Enable special char detect for range */
+#define	COR3_SCD34	0x40	/* Special character detect for SCHR's 3 + 4 */
+#define	COR3_FCT	0x20	/* Flow control transparency */
+#define	COR3_SCD12	0x10	/* Special character detect for SCHR's 1 + 2 */
+#define	COR3_FIFO12	0x0c	/* 12 chars for receive FIFO threshold */
+#define COR3_FIFO10     0x0a    /* 10 chars for receive FIFO threshold */
+#define COR3_FIFO8      0x08    /* 8 chars for receive FIFO threshold */
+#define COR3_FIFO6      0x06    /* 6 chars for receive FIFO threshold */
+
+#define COR3_THRESHOLD  COR3_FIFO8	/* MUST BE LESS THAN MCOR_THRESHOLD */
+
+#define	COR3_DEFAULT	(COR3_FCT | COR3_THRESHOLD)
+				/* Default bits for COR3 */
+
+/* COR4 driver and RTA use */
+#define	COR4_IGNCR	0x80	/* Throw away CR's on input */
+#define	COR4_ICRNL	0x40	/* Map CR -> NL on input */
+#define	COR4_INLCR	0x20	/* Map NL -> CR on input */
+#define	COR4_IGNBRK	0x10	/* Ignore Break */
+#define	COR4_NBRKINT	0x08	/* No interrupt on break (-BRKINT) */
+#define COR4_RAISEMOD	0x01	/* Raise modem output lines on non-zero baud */
+
+
+/* COR4 driver only */
+#define COR4_IGNPAR	0x04	/* IGNPAR (ignore characters with errors) */
+#define COR4_PARMRK	0x02	/* PARMRK */
+
+#define COR4_HOST	0xf8	/* Safe host bits */
+
+/* COR4 RTA only */
+#define COR4_CIGNPAR	0x02	/* Thrown away bad characters */
+#define COR4_CPARMRK	0x04	/* PARMRK characters */
+#define COR4_CNPARMRK	0x03	/* Don't PARMRK */
+
+/* COR5 driver and RTA use */
+#define	COR5_ISTRIP	0x80	/* Strip input chars to 7 bits */
+#define	COR5_LNE	0x40	/* Enable LNEXT processing */
+#define	COR5_CMOE	0x20	/* Match good and errored characters */
+#define	COR5_ONLCR	0x02	/* NL -> CR NL on output */
+#define	COR5_OCRNL	0x01	/* CR -> NL on output */
+
+/*
+** Spare bits - these are not used in the CIRRUS registers, so we use
+** them to set various other features.
+*/
+/*
+** tstop and tbusy indication
+*/
+#define	COR5_TSTATE_ON	0x08	/* Turn on monitoring of tbusy and tstop */
+#define	COR5_TSTATE_OFF	0x04	/* Turn off monitoring of tbusy and tstop */
+/*
+** TAB3
+*/
+#define	COR5_TAB3	0x10	/* TAB3 mode */
+
+#define	COR5_HOST	0xc3	/* Safe host bits */
+
+/* CCSR */
+#define	CCSR_TXFLOFF	0x04	/* Tx is xoffed */
+
+/* MSVR1 */
+/* NB. DTR / CD swapped from Cirrus spec as the pins are also reversed on the
+   RTA. This is because otherwise DCD would get lost on the 1 parallel / 3
+   serial option.
+*/
+#define	MSVR1_CD	0x80	/* CD (DSR on Cirrus) */
+#define	MSVR1_RTS	0x40	/* RTS (CTS on Cirrus) */
+#define	MSVR1_RI	0x20	/* RI */
+#define	MSVR1_DTR	0x10	/* DTR (CD on Cirrus) */
+#define	MSVR1_CTS	0x01	/* CTS output pin (RTS on Cirrus) */
+/* Next two used to indicate state of tbusy and tstop to driver */
+#define	MSVR1_TSTOP	0x08	/* Set if port flow controlled */
+#define	MSVR1_TEMPTY	0x04	/* Set if port tx buffer empty */
+
+#define	MSVR1_HOST	0xf3	/* The bits the host wants */
+
+/* MSVR2 */
+#define	MSVR2_DSR	0x02	/* DSR output pin (DTR on Cirrus) */
+
+/* MCOR */
+#define	MCOR_CD	        0x80	/* CD (DSR on Cirrus) */
+#define	MCOR_RTS	0x40	/* RTS (CTS on Cirrus) */
+#define	MCOR_RI	        0x20	/* RI */
+#define	MCOR_DTR	0x10	/* DTR (CD on Cirrus) */
+
+#define MCOR_DEFAULT    (MCOR_CD | MCOR_RTS | MCOR_RI | MCOR_DTR)
+#define MCOR_FULLMODEM  MCOR_DEFAULT
+#define MCOR_RJ45       (MCOR_CD | MCOR_RTS | MCOR_DTR)
+#define MCOR_RESTRICTED (MCOR_CD | MCOR_RTS)
+
+/* More MCOR - H/W Handshake (flowcontrol) stuff */
+#define	MCOR_THRESH8	0x08	/* eight characters then we stop */
+#define	MCOR_THRESH9	0x09	/* nine characters then we stop */
+#define	MCOR_THRESH10	0x0A	/* ten characters then we stop */
+#define	MCOR_THRESH11	0x0B	/* eleven characters then we stop */
+
+#define	MCOR_THRESHBITS 0x0F	/* mask for ANDing out the above */
+
+#define	MCOR_THRESHOLD	MCOR_THRESH9 /* MUST BE GREATER THAN COR3_THRESHOLD */
+
+
+/* RTPR */
+#define RTPR_DEFAULT	0x02	/* Default */
+
+
+/* Defines for the subscripts of a CONFIG packet */
+#define	CONFIG_COR1	1	/* Option register 1 */
+#define	CONFIG_COR2	2	/* Option register 2 */
+#define	CONFIG_COR4	3	/* Option register 4 */
+#define	CONFIG_COR5	4	/* Option register 5 */
+#define	CONFIG_TXXON	5	/* Tx XON character */
+#define	CONFIG_TXXOFF	6	/* Tx XOFF character */
+#define	CONFIG_RXXON	7	/* Rx XON character */
+#define	CONFIG_RXXOFF	8	/* Rx XOFF character */
+#define CONFIG_LNEXT	9	/* LNEXT character */
+#define	CONFIG_TXBAUD	10	/* Tx baud rate */
+#define	CONFIG_RXBAUD	11	/* Rx baud rate */
+
+/* Port status stuff */
+#define	IDLE_CLOSED	0	/* Closed */
+#define IDLE_OPEN	1	/* Idle open */
+#define IDLE_BREAK	2	/* Idle on break */
+
+/* Subscript of MODEM STATUS packet */
+#define	MODEM_VALUE	3	/* Current values of handshake pins */
+/* Subscript of SBREAK packet */
+#define BREAK_LENGTH	1	/* Length of a break in slices of 0.01 seconds
+				   0 = stay on break until an EBREAK command
+				   is sent */
+
+
+#define	PRE_EMPTIVE	0x80	/* Pre-emptive bit in command field */
+
+/* Packet types going from Host to remote - with the exception of OPEN, MOPEN,
+   CONFIG, SBREAK and MEMDUMP the remaining bytes of the data array will not
+   be used 
+*/
+#define	OPEN		0x00	/* Open a port */
+#define CONFIG		0x01	/* Configure a port */
+#define	MOPEN		0x02	/* Modem open (block for DCD) */
+#define	CLOSE		0x03	/* Close a port */
+#define	WFLUSH		(0x04 | PRE_EMPTIVE) /* Write flush */
+#define	RFLUSH		(0x05 | PRE_EMPTIVE) /* Read flush */
+#define	RESUME		(0x06 | PRE_EMPTIVE) /* Resume if xoffed */
+#define	SBREAK		0x07 	/* Start break */
+#define	EBREAK		0x08	/* End break */
+#define	SUSPEND		(0x09 | PRE_EMPTIVE) /* Susp op (behave as tho xoffed) */
+#define FCLOSE          (0x0a | PRE_EMPTIVE) /* Force close */
+#define XPRINT          0x0b    /* Xprint packet */
+#define MBIS		(0x0c | PRE_EMPTIVE) /* Set modem lines */
+#define MBIC		(0x0d | PRE_EMPTIVE) /* Clear modem lines */
+#define MSET		(0x0e | PRE_EMPTIVE) /* Set modem lines */
+#define PCLOSE		0x0f	/* Pseudo close - Leaves rx/tx enabled */
+#define MGET		(0x10 | PRE_EMPTIVE) /* Force update of modem status */
+#define MEMDUMP		(0x11 | PRE_EMPTIVE) /* Send back mem from addr supplied */
+#define	READ_REGISTER	(0x12 | PRE_EMPTIVE) /* Read CD1400 register (debug) */
+
+/* "Command" packets going from remote to host COMPLETE and MODEM_STATUS
+   use data[4] / data[3] to indicate current state and modem status respectively
+*/ 
+
+#define	COMPLETE	(0x20 | PRE_EMPTIVE)
+				/* Command complete */
+#define BREAK_RECEIVED	(0x21 | PRE_EMPTIVE)
+				/* Break received */
+#define MODEM_STATUS	(0x22 | PRE_EMPTIVE)
+				/* Change in modem status */
+
+/* "Command" packet that could go either way - handshake wake-up */
+#define HANDSHAKE	(0x23 | PRE_EMPTIVE)
+				/* Wake-up to HOST / RTA */
+
+#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/cmd.h linux.15p9/drivers/char/rio/cmd.h
--- linux.vanilla/drivers/char/rio/cmd.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/cmd.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,84 @@
+
+
+/****************************************************************************
+ *******                                                              *******
+ *******           C O M M A N D   P A C K E T   H E A D E R S
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+
+#ifndef _cmd_h
+#define _cmd_h
+
+#ifndef lint
+#ifdef SCCS
+static char *_rio_cmd_h_sccs = "@(#)cmd.h	1.1" ;
+#endif
+#endif
+
+
+#define PRE_EMPTIVE_CMD         0x80
+#define INLINE_CMD              ~PRE_EMPTIVE_CMD
+
+#define CMD_IGNORE_PKT          ( (ushort) 0)
+#define CMD_STATUS_REQ          ( (ushort) 1)
+#define CMD_UNIT_STATUS_REQ     ( (ushort) 2)     /* Is this needed ??? */
+#define CMD_CONF_PORT           ( (ushort) 3)
+#define CMD_CONF_UNIT           ( (ushort) 4)
+#define CMD_ROUTE_MAP_REQ       ( (ushort) 5)
+#define CMD_FLUSH_TX            ( (ushort) 6)
+#define CMD_FLUSH_RX            ( (ushort) 7)
+#define CMD_PARTION_PORT        ( (ushort) 8)
+#define CMD_RESET_PORT          ( (ushort) 0x0a)
+#define CMD_BOOT_UNIT           ( (ushort) 0x0b)
+#define CMD_FOUND_UNIT          ( (ushort) 0x0c)
+#define CMD_ATTACHED_RTA_2      ( (ushort) 0x0d)
+#define CMD_PROVIDE_BOOT        ( (ushort) 0x0e)
+#define CMD_CIRRUS              ( (ushort) 0x0f)
+
+#define FORM_STATUS_PKT         ( (ushort) 1 )
+#define FORM_POLL_PKT           ( (ushort) 2 )
+#define FORM_LINK_STATUS_PKT    ( (ushort) 3 )
+
+
+#define CMD_DATA_PORT           ( (ushort) 1 )
+#define CMD_DATA                ( (ushort) 2 )
+
+#define CMD_TX_PART             ( (ushort) 2 )
+#define CMD_RX_PART             ( (ushort) 3 )
+#define CMD_RX_LIMIT            ( (ushort) 4 )
+
+#endif
+
+/*********** end of file ***********/
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/cmdblk.h linux.15p9/drivers/char/rio/cmdblk.h
--- linux.vanilla/drivers/char/rio/cmdblk.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/cmdblk.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,60 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: cmdblk.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:09
+**	Retrieved	: 11/6/98 11:34:20
+**
+**  ident @(#)cmdblk.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_cmdblk_h__
+#define __rio_cmdblk_h__
+
+#ifdef SCCS_LABELS
+#ifndef lint
+static char *_cmdblk_h_sccs_ = "@(#)cmdblk.h	1.2";
+#endif
+#endif
+
+/*
+** the structure of a command block, used to queue commands destined for
+** a rup.
+*/
+
+struct CmdBlk
+{
+ struct CmdBlk *NextP;          /* Pointer to next command block */
+ struct	PKT     Packet;         /* A packet, to copy to the rup */
+    	                        /* The func to call to check if OK */
+    	int     (*PreFuncP)(int, struct CmdBlk *);
+    	int     PreArg;         /* The arg for the func */
+    	                        /* The func to call when completed */
+    	int     (*PostFuncP)(int, struct CmdBlk *);
+    	int     PostArg;        /* The arg for the func */
+};
+
+#define NUM_RIO_CMD_BLKS (3 * (MAX_RUP * 4 + LINKS_PER_UNIT * 4))
+#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/cmdpkt.h linux.15p9/drivers/char/rio/cmdpkt.h
--- linux.vanilla/drivers/char/rio/cmdpkt.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/cmdpkt.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,206 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: cmdpkt.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:09
+**	Retrieved	: 11/6/98 11:34:20
+**
+**  ident @(#)cmdpkt.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+#ifndef __rio_cmdpkt_h__
+#define __rio_cmdpkt_h__
+
+#ifdef SCCS_LABELS
+#ifndef lint
+static char *_cmdpkt_h_sccs_ = "@(#)cmdpkt.h	1.2";
+#endif
+#endif
+
+/*
+** overlays for the data area of a packet. Used in both directions
+** (to build a packet to send, and to interpret a packet that arrives)
+** and is very inconvenient for MIPS, so they appear as two seperate
+** structures - those used for modifying/reading packets on the card
+** and those for modifying/reading packets in real memory, which have an _M
+** suffix.
+*/
+
+#define	RTA_BOOT_DATA_SIZE (PKT_MAX_DATA_LEN-2)
+
+/*
+** The boot information packet looks like this:
+** This structure overlays a PktCmd->CmdData structure, and so starts
+** at Data[2] in the actual pkt!
+*/
+struct BootSequence
+{
+    WORD	NumPackets;
+    WORD	LoadBase;
+    WORD	CodeSize;
+};
+
+#define	BOOT_SEQUENCE_LEN	8
+
+struct SamTop
+{
+    BYTE Unit;
+    BYTE Link;
+};
+
+struct CmdHdr
+{
+    BYTE PcCommand;
+    union
+    {
+    BYTE PcPhbNum;
+    BYTE PcLinkNum;
+    BYTE PcIDNum;
+    } U0;
+};
+
+
+struct PktCmd
+{
+    union
+    {
+	struct 
+	{
+	    struct CmdHdr CmdHdr;
+	    struct BootSequence PcBootSequence;
+	} S1;
+	struct
+	{
+	    WORD PcSequence;
+	    BYTE PcBootData[RTA_BOOT_DATA_SIZE];
+	} S2;
+	struct
+	{
+	    WORD  __crud__;
+	    BYTE  PcUniqNum[4];	        /* this is really a uint. */
+	    BYTE  PcModuleTypes;  	/* what modules are fitted */
+	} S3;
+	struct
+	{
+	    struct CmdHdr CmdHdr;
+	    BYTE   __undefined__;
+	    BYTE   PcModemStatus;
+	    BYTE   PcPortStatus;
+	    BYTE   PcSubCommand;	/* commands like mem or register dump */
+	    WORD   PcSubAddr;		/* Address for command */
+	    BYTE   PcSubData[64];	/* Date area for command */
+	} S4;
+	struct
+	{
+	    struct CmdHdr CmdHdr;
+	    BYTE   PcCommandText[1];
+	    BYTE   __crud__[20];
+	    BYTE   PcIDNum2;		/* It had to go somewhere! */
+	} S5;
+	struct
+	{
+	    struct CmdHdr CmdHdr;
+	    struct SamTop    Topology[LINKS_PER_UNIT];
+	} S6;
+    } U1;
+};
+
+struct PktCmd_M
+{
+    union
+    {
+	struct 
+	{
+	    struct
+	    {
+    		uchar PcCommand;
+    		union
+    		{
+    		    uchar PcPhbNum;
+    		    uchar PcLinkNum;
+    		    uchar PcIDNum;
+    		} U0;
+	    } CmdHdr;
+	    struct
+	    {
+                ushort	NumPackets;
+                ushort	LoadBase;
+                ushort	CodeSize;
+            } PcBootSequence;
+	} S1;
+	struct
+	{
+	    ushort PcSequence;
+	    uchar PcBootData[RTA_BOOT_DATA_SIZE];
+	} S2;
+	struct
+	{
+	    ushort  __crud__;
+	    uchar  PcUniqNum[4];	        /* this is really a uint. */
+	    uchar  PcModuleTypes;  	/* what modules are fitted */
+	} S3;
+	struct
+	{
+	    ushort  __cmd_hdr__;
+	    uchar   __undefined__;
+	    uchar   PcModemStatus;
+	    uchar   PcPortStatus;
+	    uchar   PcSubCommand;
+	    ushort  PcSubAddr;
+	    uchar   PcSubData[64];
+	} S4;
+	struct
+	{
+	    ushort  __cmd_hdr__;
+	    uchar   PcCommandText[1];
+	    uchar   __crud__[20];
+	    uchar   PcIDNum2;		/* Tacked on end */
+	} S5;
+	struct
+	{
+	    ushort  __cmd_hdr__;
+	    struct Top Topology[LINKS_PER_UNIT];
+	} S6;
+    } U1;
+};
+
+#define Command		U1.S1.CmdHdr.PcCommand
+#define PhbNum		U1.S1.CmdHdr.U0.PcPhbNum
+#define IDNum		U1.S1.CmdHdr.U0.PcIDNum
+#define IDNum2		U1.S5.PcIDNum2
+#define LinkNum		U1.S1.CmdHdr.U0.PcLinkNum
+#define Sequence	U1.S2.PcSequence
+#define BootData	U1.S2.PcBootData
+#define BootSequence	U1.S1.PcBootSequence
+#define UniqNum		U1.S3.PcUniqNum
+#define ModemStatus	U1.S4.PcModemStatus
+#define PortStatus	U1.S4.PcPortStatus
+#define SubCommand	U1.S4.PcSubCommand
+#define SubAddr		U1.S4.PcSubAddr
+#define SubData		U1.S4.PcSubData
+#define CommandText	U1.S5.PcCommandText
+#define RouteTopology	U1.S6.Topology
+#define ModuleTypes	U1.S3.PcModuleTypes
+
+#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/control.h linux.15p9/drivers/char/rio/control.h
--- linux.vanilla/drivers/char/rio/control.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/control.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,62 @@
+
+
+/****************************************************************************
+ *******                                                              *******
+ *******           C O N T R O L   P A C K E T   H E A D E R S
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Jon Brawn
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+
+#ifndef _control_h
+#define _control_h
+
+#ifndef lint
+/* static char *_rio_control_h_sccs = "@(#)control.h	1.4"; */
+#endif
+
+#define	CONTROL		'^'
+#define IFOAD		( CONTROL + 1 )
+#define	IDENTIFY	( CONTROL + 2 )
+#define	ZOMBIE		( CONTROL + 3 )
+#define	UFOAD		( CONTROL + 4 )
+#define IWAIT		( CONTROL + 5 )
+
+#define	IFOAD_MAGIC	0xF0AD		/* of course */
+#define	ZOMBIE_MAGIC	(~0xDEAD)	/* not dead -> zombie */
+#define	UFOAD_MAGIC	0xD1E		/* kill-your-neighbour */
+#define	IWAIT_MAGIC	0xB1DE		/* Bide your time */
+
+#endif
+
+/*********** end of file ***********/
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/daemon.h linux.15p9/drivers/char/rio/daemon.h
--- linux.vanilla/drivers/char/rio/daemon.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/daemon.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,334 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: daemon.h
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 11:34:09
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)daemon.h	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef	__rio_daemon_h__
+#define	__rio_daemon_h__
+
+#ifdef SCCS_LABELS
+#ifndef lint
+static char *_daemon_h_sccs_ = "@(#)daemon.h	1.3";
+#endif
+#endif
+
+
+/*
+** structures used on /dev/rio
+*/
+
+struct Error
+{
+	uint	Error;
+	uint	Entry;
+	uint	Other;
+};
+
+struct DownLoad
+{
+	char	*DataP;
+	uint	Count;
+	uint	ProductCode;
+};
+
+/*
+** A few constants....
+*/
+#ifndef MAX_VERSION_LEN
+#define	MAX_VERSION_LEN	256
+#endif
+
+#ifndef MAX_XP_CTRL_LEN
+#define	MAX_XP_CTRL_LEN 16		/* ALSO IN PORT.H */
+#endif
+
+struct	PortSetup
+{
+	uint	From;	/* Set/Clear XP & IXANY Control from this port.... */
+	uint	To;	/* .... to this port */
+	uint	XpCps;			/* at this speed */
+	char	XpOn[MAX_XP_CTRL_LEN];	/* this is the start string */
+	char	XpOff[MAX_XP_CTRL_LEN];	/* this is the stop string */
+	uchar	IxAny;			/* enable/disable IXANY */
+	uchar	IxOn;			/* enable/disable IXON */
+	uchar	Lock;			/* lock port params */
+	uchar	Store;			/* store params across closes */
+	uchar	Drain;			/* close only when drained */
+};
+
+struct	LpbReq
+{
+	uint	Host;
+	uint	Link;
+	struct  LPB     *LpbP;
+};
+
+struct	RupReq
+{
+	uint	HostNum;
+	uint	RupNum;
+	struct  RUP 	*RupP;
+};
+
+struct	PortReq
+{
+	uint	SysPort;
+	struct  Port 	*PortP;
+};
+
+struct  StreamInfo
+{
+	uint	SysPort;
+#if 0
+	queue_t RQueue;
+	queue_t WQueue;
+#else
+	int RQueue;
+	int WQueue;
+#endif
+};
+
+struct	HostReq
+{
+	uint	HostNum;
+	struct  Host 	*HostP;
+};
+
+struct	HostDpRam
+{
+	uint	HostNum;
+	struct	DpRam	*DpRamP;
+};
+
+struct	DebugCtrl
+{
+	uint	SysPort;
+	uint	Debug;
+	uint	Wait;
+};
+
+struct	MapInfo
+{
+	uint	FirstPort;	/* 8 ports, starting from this (tty) number */
+	uint	RtaUnique;	/* reside on this RTA (unique number) */
+};
+
+struct	MapIn
+{
+	uint	NumEntries;		/* How many port sets are we mapping? */
+	struct  MapInfo	*MapInfoP;	/* Pointer to (user space) info */
+};
+
+struct  SendPack
+{
+        unsigned int	PortNum;
+	unsigned char	Len;
+	unsigned char	Data[PKT_MAX_DATA_LEN];
+};
+
+struct SpecialRupCmd
+{
+	struct	PKT		Packet;
+	unsigned short	Host;
+	unsigned short	RupNum;
+};
+
+struct	IdentifyRta
+{
+	ulong	RtaUnique;
+	uchar	ID;
+};
+
+struct	KillNeighbour
+{
+	ulong	UniqueNum;
+	uchar	Link;
+};
+
+struct rioVersion {
+    char        version[MAX_VERSION_LEN];
+    char        relid[MAX_VERSION_LEN];
+    int         buildLevel;
+    char        buildDate[MAX_VERSION_LEN];
+};
+
+
+/*
+**	RIOC commands are for the daemon type operations
+**
+** 09.12.1998 ARG - ESIL 0776 part fix
+** Definition for 'RIOC' also appears in rioioctl.h, so we'd better do a
+** #ifndef here first.
+** rioioctl.h also now has #define 'RIO_QUICK_CHECK' as this ioctl is now
+** allowed to be used by customers.
+*/
+#ifndef RIOC
+#define	RIOC	('R'<<8)|('i'<<16)|('o'<<24)
+#endif
+
+/*
+** Boot stuff
+*/
+#define	RIO_GET_TABLE     (RIOC | 100)
+#define RIO_PUT_TABLE     (RIOC | 101)
+#define RIO_ASSIGN_RTA    (RIOC | 102)
+#define RIO_DELETE_RTA    (RIOC | 103)
+#define	RIO_HOST_FOAD	  (RIOC | 104)
+#define	RIO_QUICK_CHECK	  (RIOC | 105)
+#define RIO_SIGNALS_ON    (RIOC | 106)
+#define RIO_SIGNALS_OFF   (RIOC | 107)
+#define	RIO_CHANGE_NAME   (RIOC | 108)
+#define RIO_DOWNLOAD      (RIOC | 109)
+#define	RIO_GET_LOG	  (RIOC | 110)
+#define	RIO_SETUP_PORTS   (RIOC | 111)
+#define RIO_ALL_MODEM     (RIOC | 112)
+
+/*
+** card state, debug stuff
+*/
+#define	RIO_NUM_HOSTS	  (RIOC | 120)
+#define	RIO_HOST_LPB	  (RIOC | 121)
+#define	RIO_HOST_RUP	  (RIOC | 122)
+#define	RIO_HOST_PORT	  (RIOC | 123)
+#define	RIO_PARMS 	  (RIOC | 124)
+#define RIO_HOST_REQ	  (RIOC | 125)
+#define	RIO_READ_CONFIG	  (RIOC | 126)
+#define	RIO_SET_CONFIG	  (RIOC | 127)
+#define	RIO_VERSID	  (RIOC | 128)
+#define	RIO_FLAGS	  (RIOC | 129)
+#define	RIO_SETDEBUG	  (RIOC | 130)
+#define	RIO_GETDEBUG	  (RIOC | 131)
+#define	RIO_READ_LEVELS   (RIOC | 132)
+#define	RIO_SET_FAST_BUS  (RIOC | 133)
+#define	RIO_SET_SLOW_BUS  (RIOC | 134)
+#define	RIO_SET_BYTE_MODE (RIOC | 135)
+#define	RIO_SET_WORD_MODE (RIOC | 136)
+#define RIO_STREAM_INFO   (RIOC | 137)
+#define	RIO_START_POLLER  (RIOC | 138)
+#define	RIO_STOP_POLLER   (RIOC | 139)
+#define	RIO_LAST_ERROR    (RIOC | 140)
+#define	RIO_TICK	  (RIOC | 141)
+#define	RIO_TOCK	  (RIOC | 241)	/* I did this on purpose, you know. */
+#define	RIO_SEND_PACKET   (RIOC | 142)
+#define	RIO_SET_BUSY	  (RIOC | 143)
+#define	SPECIAL_RUP_CMD   (RIOC | 144)
+#define	RIO_FOAD_RTA      (RIOC | 145)
+#define	RIO_ZOMBIE_RTA    (RIOC | 146)
+#define RIO_IDENTIFY_RTA  (RIOC | 147)
+#define RIO_KILL_NEIGHBOUR (RIOC | 148)
+#define RIO_DEBUG_MEM     (RIOC | 149)
+/*
+** 150 - 167 used.....   See below
+*/
+#define RIO_GET_PORT_SETUP (RIOC | 168)
+#define RIO_RESUME        (RIOC | 169)
+#define	RIO_MESG	(RIOC | 170)
+#define	RIO_NO_MESG	(RIOC | 171)
+#define	RIO_WHAT_MESG	(RIOC | 172)
+#define RIO_HOST_DPRAM	(RIOC | 173)
+#define RIO_MAP_B50_TO_50	(RIOC | 174)
+#define RIO_MAP_B50_TO_57600	(RIOC | 175)
+#define RIO_MAP_B110_TO_110	(RIOC | 176)
+#define RIO_MAP_B110_TO_115200	(RIOC | 177)
+#define RIO_GET_PORT_PARAMS	(RIOC | 178)
+#define RIO_SET_PORT_PARAMS	(RIOC | 179)
+#define RIO_GET_PORT_TTY	(RIOC | 180)
+#define RIO_SET_PORT_TTY	(RIOC | 181)
+#define RIO_SYSLOG_ONLY	(RIOC | 182)
+#define RIO_SYSLOG_CONS	(RIOC | 183)
+#define RIO_CONS_ONLY	(RIOC | 184)
+#define RIO_BLOCK_OPENS	(RIOC | 185)
+
+/*
+** 02.03.1999 ARG - ESIL 0820 fix :
+** RIOBootMode is no longer use by the driver, so these ioctls
+** are now obsolete :
+**
+#define RIO_GET_BOOT_MODE	(RIOC | 186)
+#define RIO_SET_BOOT_MODE	(RIOC | 187)
+**
+*/
+
+#define RIO_MEM_DUMP	(RIOC | 189)
+#define RIO_READ_REGISTER	(RIOC | 190)
+#define RIO_GET_MODTYPE	(RIOC | 191)
+#define RIO_SET_TIMER	(RIOC | 192)
+#define RIO_READ_CHECK	(RIOC | 196)
+#define RIO_WAITING_FOR_RESTART	(RIOC | 197)
+#define RIO_BIND_RTA	(RIOC | 198)
+#define RIO_GET_BINDINGS	(RIOC | 199)
+#define RIO_PUT_BINDINGS	(RIOC | 200)
+
+#define	RIO_MAKE_DEV		(RIOC | 201)
+#define	RIO_MINOR		(RIOC | 202)
+
+#define	RIO_IDENTIFY_DRIVER	(RIOC | 203)
+#define	RIO_DISPLAY_HOST_CFG	(RIOC | 204)
+
+
+/*
+** MAKE_DEV / MINOR stuff
+*/
+#define	RIO_DEV_DIRECT		0x0000
+#define	RIO_DEV_MODEM		0x0200
+#define	RIO_DEV_XPRINT		0x0400
+#define	RIO_DEV_MASK		0x0600
+
+/*
+** port management, xprint stuff
+*/
+#define	rIOCN(N)	(RIOC|(N))
+#define	rIOCR(N,T)	(RIOC|(N))
+#define	rIOCW(N,T)	(RIOC|(N))
+
+#define	RIO_GET_XP_ON     rIOCR(150,char[16])	/* start xprint string */
+#define	RIO_SET_XP_ON     rIOCW(151,char[16])
+#define	RIO_GET_XP_OFF    rIOCR(152,char[16])	/* finish xprint string */
+#define	RIO_SET_XP_OFF    rIOCW(153,char[16])
+#define	RIO_GET_XP_CPS    rIOCR(154,int)	/* xprint CPS */
+#define	RIO_SET_XP_CPS    rIOCW(155,int)
+#define RIO_GET_IXANY     rIOCR(156,int)	/* ixany allowed? */
+#define RIO_SET_IXANY     rIOCW(157,int)
+#define RIO_SET_IXANY_ON  rIOCN(158)		/* allow ixany */
+#define RIO_SET_IXANY_OFF rIOCN(159)		/* disallow ixany */
+#define RIO_GET_MODEM     rIOCR(160,int)	/* port is modem/direct line? */
+#define RIO_SET_MODEM     rIOCW(161,int)
+#define RIO_SET_MODEM_ON  rIOCN(162)		/* port is a modem */
+#define RIO_SET_MODEM_OFF rIOCN(163)		/* port is direct */
+#define RIO_GET_IXON      rIOCR(164,int)	/* ixon allowed? */
+#define RIO_SET_IXON      rIOCW(165,int)
+#define RIO_SET_IXON_ON   rIOCN(166)		/* allow ixon */
+#define RIO_SET_IXON_OFF  rIOCN(167)		/* disallow ixon */
+
+#define RIO_GET_SIVIEW	  ((('s')<<8) | 106)	/* backwards compatible with SI */
+
+#define	RIO_IOCTL_UNKNOWN	-2
+
+#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/data.h linux.15p9/drivers/char/rio/data.h
--- linux.vanilla/drivers/char/rio/data.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/data.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,40 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: data.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:09
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)data.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_datadex__
+#define __rio_datadex__
+
+#ifndef lint
+static char *_data_h_sccs_ = "@(#)data.h	1.2";
+#endif
+
+#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/debug.h linux.15p9/drivers/char/rio/debug.h
--- linux.vanilla/drivers/char/rio/debug.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/debug.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,39 @@
+/*
+** File:		debug.h
+**
+** Author:		David Dix
+**
+** Created:		12th March 1993
+**
+** Last modified:	93/04/27
+**
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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 _debug_h_
+#define _debug_h_
+
+
+#if defined(DCIRRUS)
+#define	DBPACKET(pkt, opt, str, chn) 	debug_packet((pkt), (opt), (str), (chn))
+#else
+#define	DBPACKET(pkt, opt, str, c)
+#endif	/* DCIRRUS */
+
+
+#endif	/* _debug_h_ */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/defaults.h linux.15p9/drivers/char/rio/defaults.h
--- linux.vanilla/drivers/char/rio/defaults.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/defaults.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,59 @@
+
+/****************************************************************************
+ *******                                                              *******
+ *******                     D E F A U L T S
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef lint
+#ifdef SCCS
+static char *_rio_defaults_h_sccs = "@(#)defaults.h	1.1" ;
+#endif
+#endif
+
+
+#define MILLISECOND           (int) (1000/64)   /* 15.625 low ticks */
+#define SECOND                (int) 15625       /* Low priority ticks */
+
+#ifdef RTA
+#define RX_LIMIT       (ushort) 3
+#endif
+#ifdef HOST
+#define RX_LIMIT       (ushort) 1
+#endif
+
+#define LINK_TIMEOUT          (int) (POLL_PERIOD / 2)
+
+
+/*********** end of file ***********/
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/eisa.h linux.15p9/drivers/char/rio/eisa.h
--- linux.vanilla/drivers/char/rio/eisa.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/eisa.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,104 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: eisa.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:10
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)eisa.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_eisa_h__
+#define __rio_eisa_h__
+
+#ifdef SCCS_LABELS
+#ifndef lint
+static char *_eisa_h_sccs_ = "@(#)eisa.h	1.2";
+#endif
+#endif
+
+/*
+** things to do with the EISA bus
+*/
+
+#define RIO_EISA_STRING_ADDRESS 	0xfffd9	/* where EISA is stored */
+
+#define	RIO_MAX_EISA_SLOTS		16	/* how many EISA slots? */
+
+#define	RIO_EISA_IDENT			0x984D	/* Specialix */
+#define	RIO_EISA_PRODUCT_CODE		0x14	/* Code 14 */
+#define	RIO_EISA_ENABLE_BIT		0x01	/* To enable card */
+
+#define	EISA_MEMORY_BASE_LO		0xC00	/* A16-A23 */
+#define	EISA_MEMORY_BASE_HI		0xC01	/* A24-A31 */
+#define	EISA_INTERRUPT_VEC		0xC02	/* see below */
+#define	EISA_CONTROL_PORT		0xC02	/* see below */
+#define	EISA_INTERRUPT_RESET		0xC03	/* read to clear IRQ */
+
+#define	EISA_PRODUCT_IDENT_LO		0xC80	/* where RIO_EISA_IDENT is */
+#define	EISA_PRODUCT_IDENT_HI		0xC81
+#define	EISA_PRODUCT_NUMBER		0xC82   /* where PROD_CODE is */
+#define	EISA_REVISION_NUMBER		0xC83	/* revision (1dp) */
+#define	EISA_ENABLE			0xC84	/* set LSB to enable card */
+#define	EISA_UNIQUE_NUM_0		0xC88	/* vomit */
+#define	EISA_UNIQUE_NUM_1		0xC8A
+#define	EISA_UNIQUE_NUM_2		0xC90	/* bit strangely arranged */
+#define	EISA_UNIQUE_NUM_3		0xC92
+#define	EISA_MANUF_YEAR			0xC98	/* when */
+#define	EISA_MANUF_WEEK			0xC9A	/* more when */
+
+#define	EISA_TP_BOOT_FROM_RAM	0x01
+#define	EISA_TP_BOOT_FROM_LINK	0x00
+#define	EISA_TP_FAST_LINKS	0x02
+#define	EISA_TP_SLOW_LINKS	0x00
+#define	EISA_TP_BUS_ENABLE	0x04
+#define	EISA_TP_BUS_DISABLE	0x00
+#define	EISA_TP_RUN		0x08
+#define	EISA_TP_RESET		0x00
+#define	EISA_POLLED		0x00
+#define	EISA_IRQ_3		0x30
+#define	EISA_IRQ_4		0x40
+#define	EISA_IRQ_5		0x50
+#define	EISA_IRQ_6		0x60
+#define	EISA_IRQ_7		0x70
+#define	EISA_IRQ_9		0x90
+#define	EISA_IRQ_10		0xA0
+#define	EISA_IRQ_11		0xB0
+#define	EISA_IRQ_12		0xC0
+#define	EISA_IRQ_14		0xE0
+#define	EISA_IRQ_15		0xF0
+
+#define	EISA_INTERRUPT_MASK	0xF0
+#define	EISA_CONTROL_MASK	0x0F
+
+#define	RIO_EISA_DEFAULT_MODE	EISA_TP_SLOW_LINKS
+
+#define	RIOEisaToIvec(X)	(uchar )((uchar)((X) & EISA_INTERRUPT_MASK)>>4)
+
+#define	INBZ(z,x)	inb(((z)<<12) | (x))
+#define	OUTBZ(z,x,y)	outb((((z)<<12) | (x)), y)
+
+#endif /* __rio_eisa_h__ */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/enable.h linux.15p9/drivers/char/rio/enable.h
--- linux.vanilla/drivers/char/rio/enable.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/enable.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,50 @@
+/****************************************************************************
+ *******                                                              *******
+ *******               E N A B L E   H E A D E R S
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef lint
+#ifdef SCCS
+static char *_rio_enable_h_sccs = "@(#)enable.h	1.1" ;
+#endif
+#endif
+
+
+#define ENABLE_LTT  TRUE
+#define ENABLE_LRT  TRUE
+
+
+/*********** end of file ***********/
+
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/error.h linux.15p9/drivers/char/rio/error.h
--- linux.vanilla/drivers/char/rio/error.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/error.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,85 @@
+
+/****************************************************************************
+ *******                                                              *******
+ *******     E R R O R  H E A D E R   F I L E
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef lint
+/* static char *_rio_error_h_sccs = "@(#)error.h	1.3"; */
+#endif
+
+#define E_NO_ERROR                       ((ushort) 0)
+#define E_PROCESS_NOT_INIT               ((ushort) 1)
+#define E_LINK_TIMEOUT                   ((ushort) 2)
+#define E_NO_ROUTE                       ((ushort) 3)
+#define E_CONFUSED                       ((ushort) 4)
+#define E_HOME                           ((ushort) 5)
+#define E_CSUM_FAIL                      ((ushort) 6)
+#define E_DISCONNECTED                   ((ushort) 7)
+#define E_BAD_RUP                        ((ushort) 8)
+#define E_NO_VIRGIN                      ((ushort) 9)
+#define E_BOOT_RUP_BUSY                  ((ushort) 10)
+
+
+
+    /*************************************************
+     * Parsed to mem_halt()
+     ************************************************/
+#define E_CHANALLOC                      ((ushort) 0x80)
+#define E_POLL_ALLOC                     ((ushort) 0x81)
+#define E_LTTWAKE                        ((ushort) 0x82)
+#define E_LTT_ALLOC                      ((ushort) 0x83)
+#define E_LRT_ALLOC                      ((ushort) 0x84)
+#define E_CIRRUS                         ((ushort) 0x85)
+#define E_MONITOR                        ((ushort) 0x86)
+#define E_PHB_ALLOC                      ((ushort) 0x87)
+#define E_ARRAY_ALLOC                    ((ushort) 0x88)
+#define E_QBUF_ALLOC                     ((ushort) 0x89)
+#define E_PKT_ALLOC                      ((ushort) 0x8a)
+#define E_GET_TX_Q_BUF                   ((ushort) 0x8b)
+#define E_GET_RX_Q_BUF                   ((ushort) 0x8c)
+#define E_MEM_OUT                        ((ushort) 0x8d)
+#define E_MMU_INIT                       ((ushort) 0x8e)
+#define E_LTT_INIT                       ((ushort) 0x8f)
+#define E_LRT_INIT                       ((ushort) 0x90)
+#define E_LINK_RUN                       ((ushort) 0x91)
+#define E_MONITOR_ALLOC                  ((ushort) 0x92)
+#define E_MONITOR_INIT                   ((ushort) 0x93)
+#define E_POLL_INIT                      ((ushort) 0x94)
+
+
+/*********** end of file ***********/
+
+
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/errors.h linux.15p9/drivers/char/rio/errors.h
--- linux.vanilla/drivers/char/rio/errors.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/errors.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,104 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: errors.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:10
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)errors.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef	__rio_errors_h__
+#define	__rio_errors_h__
+
+#ifdef SCCS_LABELS
+#ifndef lint
+static char *_errors_h_sccs_ = "@(#)errors.h	1.2";
+#endif
+#endif
+
+/*
+** error codes
+*/
+
+#define	NOTHING_WRONG_AT_ALL		0
+#define	BAD_CHARACTER_IN_NAME		1
+#define	TABLE_ENTRY_ISNT_PROPERLY_NULL	2
+#define	UNKNOWN_HOST_NUMBER		3
+#define	ZERO_RTA_ID			4
+#define	BAD_RTA_ID			5
+#define	DUPLICATED_RTA_ID		6
+#define	DUPLICATE_UNIQUE_NUMBER		7
+#define	BAD_TTY_NUMBER			8
+#define	TTY_NUMBER_IN_USE		9
+#define	NAME_USED_TWICE			10
+#define	HOST_ID_NOT_ZERO		11
+#define	BOOT_IN_PROGRESS		12
+#define	COPYIN_FAILED			13
+#define	HOST_FILE_TOO_LARGE		14
+#define	COPYOUT_FAILED			15
+#define	NOT_SUPER_USER			16
+#define	RIO_ALREADY_POLLING		17
+
+#define	ID_NUMBER_OUT_OF_RANGE		18
+#define PORT_NUMBER_OUT_OF_RANGE	19
+#define	HOST_NUMBER_OUT_OF_RANGE	20
+#define	RUP_NUMBER_OUT_OF_RANGE		21
+#define	TTY_NUMBER_OUT_OF_RANGE		22
+#define	LINK_NUMBER_OUT_OF_RANGE	23
+
+#define	HOST_NOT_RUNNING		24
+#define	IOCTL_COMMAND_UNKNOWN		25
+#define	RIO_SYSTEM_HALTED		26
+#define	WAIT_FOR_DRAIN_BROKEN		27
+#define	PORT_NOT_MAPPED_INTO_SYSTEM	28
+#define	EXCLUSIVE_USE_SET		29
+#define	WAIT_FOR_NOT_CLOSING_BROKEN	30
+#define	WAIT_FOR_PORT_TO_OPEN_BROKEN	31
+#define	WAIT_FOR_CARRIER_BROKEN		32
+#define	WAIT_FOR_NOT_IN_USE_BROKEN	33
+#define	WAIT_FOR_CAN_ADD_COMMAND_BROKEN	34
+#define	WAIT_FOR_ADD_COMMAND_BROKEN	35
+#define	WAIT_FOR_NOT_PARAM_BROKEN	36
+#define	WAIT_FOR_RETRY_BROKEN		37
+#define	HOST_HAS_ALREADY_BEEN_BOOTED	38
+#define	UNIT_IS_IN_USE			39
+#define	COULDNT_FIND_ENTRY		40
+#define	RTA_UNIQUE_NUMBER_ZERO		41
+#define	CLOSE_COMMAND_FAILED		42
+#define	WAIT_FOR_CLOSE_BROKEN		43
+#define	CPS_VALUE_OUT_OF_RANGE		44
+#define	ID_ALREADY_IN_USE		45
+#define	SIGNALS_ALREADY_SET		46
+#define	NOT_RECEIVING_PROCESS		47
+#define	RTA_NUMBER_WRONG		48
+#define NO_SUCH_PRODUCT			49
+#define	HOST_SYSPORT_BAD		50
+#define	ID_NOT_TENTATIVE		51
+#define XPRINT_CPS_OUT_OF_RANGE		52
+#define	NOT_ENOUGH_CORE_FOR_PCI_COPY	53
+
+
+#endif /* __rio_errors_h__ */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/formpkt.h linux.15p9/drivers/char/rio/formpkt.h
--- linux.vanilla/drivers/char/rio/formpkt.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/formpkt.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,154 @@
+
+
+/****************************************************************************
+ *******                                                              *******
+ *******         F O R M   P A C K E T   H E A D E R   F I L E
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _formpkt_h
+#define _formpkt_h 1
+
+#ifndef lint
+#ifdef SCCS
+static char *_rio_formpkt_h_sccs = "@(#)formpkt.h	1.1" ;
+#endif
+#endif
+
+typedef struct FORM_BOOT_PKT_1 FORM_BOOT_PKT_1 ;
+struct FORM_BOOT_PKT_1 {
+                           ushort pkt_number ;
+                           ushort pkt_total ;
+                           ushort boot_top ;
+                       } ;
+
+typedef struct FORM_BOOT_PKT_2 FORM_BOOT_PKT_2 ;
+struct FORM_BOOT_PKT_2 {
+                           ushort pkt_number ;
+                           char   boot_data[10] ;
+                       } ;
+
+
+typedef struct FORM_ATTACH_RTA   FORM_ATTACH_RTA ;
+struct FORM_ATTACH_RTA  {
+                       char    cmd_code ;
+                       char    booter_serial[4] ;
+                       char    booter_link ;
+                       char    bootee_serial[4] ;
+                       char    bootee_link ;
+                   } ;
+
+
+typedef struct FORM_BOOT_ID   FORM_BOOT_ID ;
+struct FORM_BOOT_ID  {
+                       char    cmd_code ;
+                       char    bootee_serial[4] ;
+                       char    bootee_prod_id ;
+                       char    bootee_link ;
+                   } ;
+
+
+
+typedef struct FORM_ROUTE_1   FORM_ROUTE_1 ;
+struct FORM_ROUTE_1 {
+                        char     cmd_code ;
+                        char     pkt_number ;
+                        char     total_in_sequence ;
+                        char     unit_id ;
+                        char     host_unit_id ;
+                    } ;
+
+typedef struct FORM_ROUTE_2   FORM_ROUTE_2 ;
+struct FORM_ROUTE_2 {
+                        char   cmd_code ;
+                        char   pkt_number ;
+                        char   total_in_sequence ;
+                        char   route_data[9] ;
+                    } ;
+
+typedef struct FORM_ROUTE_REQ   FORM_ROUTE_REQ ;
+struct FORM_ROUTE_REQ {
+                          char   cmd_code ;
+                          char   pkt_number ;
+                          char   total_in_sequence ;
+                          char   route_data[10] ;
+                      } ;
+
+
+typedef struct FORM_ERROR   FORM_ERROR ;
+struct FORM_ERROR {
+                        char   cmd_code ;
+                        char   error_code ;
+
+                    } ;
+
+typedef struct FORM_STATUS   FORM_STATUS ;
+struct FORM_STATUS {
+                        char   cmd_code ;
+                        char   status_code ;
+                        char   last_packet_valid ;
+                        char   tx_buffer ;
+                        char   rx_buffer ;
+                        char   port_status ;
+                        char   phb_status ;
+                    } ;
+
+
+typedef struct FORM_LINK_STATUS   FORM_LINK_STATUS ;
+struct FORM_LINK_STATUS {
+                        char    cmd_code ;
+                        char    status_code ;
+                        char    link_number ;
+                        ushort  rx_errors ;
+                        ushort  tx_errors ;
+                        ushort  csum_errors ;
+                        ushort  disconnects ;
+                    } ;
+
+
+
+typedef struct FORM_PARTITION FORM_PARTITION ;
+struct FORM_PARTITION {
+                        char    cmd_code ;
+                        char    status_code ;
+                        char    port_number ;
+                        char    tx_max ;
+                        char    rx_max ;
+                        char    rx_limit ;
+                      } ;
+
+
+#endif
+
+/*********** end of file ***********/
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/func.h linux.15p9/drivers/char/rio/func.h
--- linux.vanilla/drivers/char/rio/func.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/func.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,171 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: func.h
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 11:34:10
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)func.h	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __func_h_def
+#define __func_h_def
+
+#ifdef SCCS_LABELS
+#ifndef lint
+static char *_func_h_sccs_ = "@(#)func.h	1.3";
+#endif
+#endif
+
+/* rioboot.c */
+int RIOBootCodeRTA(struct rio_info *, struct DownLoad *);
+int RIOBootCodeHOST(struct rio_info *, register struct DownLoad *);
+int RIOBootCodeUNKNOWN(struct rio_info *, struct DownLoad *);
+void msec_timeout(struct Host *);
+int RIOBootRup(struct rio_info *, uint, struct Host *, struct PKT *);
+int RIOBootComplete(struct rio_info *, struct Host *, uint, struct PktCmd *);
+int RIOBootOk(struct rio_info *,struct Host *, ulong);
+int RIORtaBound(struct rio_info *, uint); 
+void FillSlot(int, int, uint, struct Host *);
+
+/* riocmd.c */
+int RIOFoadRta(struct Host *, struct Map *);
+int RIOZombieRta(struct Host *, struct Map *);
+int RIOCommandRta(struct rio_info *, uint, int (* func)( struct Host *, 
+								struct Map *));
+int RIOIdentifyRta(struct rio_info *, caddr_t); 
+int RIOKillNeighbour(struct rio_info *, caddr_t);
+int RIOSuspendBootRta(struct Host *, int, int);
+int RIOFoadWakeup(struct rio_info *);
+int RIOCommandRup(struct rio_info *, uint, struct Host *, struct PKT *);
+struct CmdBlk * RIOGetCmdBlk(void);
+void RIOFreeCmdBlk(struct CmdBlk *);
+int RIOQueueCmdBlk(struct Host *, uint, struct CmdBlk *);
+void RIOPollHostCommands(struct rio_info *, struct Host *);
+int RIOStrlen(register char *);
+int RIOStrCmp(register char *, register char *);
+int RIOStrnCmp(register char *, register char *, int);
+void  RIOStrNCpy(char *, char *, int);
+int RIOWFlushMark(int, struct CmdBlk *);
+int RIORFlushEnable(int, struct CmdBlk *);
+int RIOUnUse(int, struct CmdBlk *);
+void ShowPacket(uint, struct PKT *);
+
+/* rioctrl.c */
+int copyin(int, caddr_t, int);
+int copyout(caddr_t, int, int);
+int riocontrol(struct rio_info *, dev_t,int,caddr_t,int); 
+int RIOPreemptiveCmd(struct rio_info *,struct Port *,uchar);
+
+/* rioinit.c */
+void rioinit(struct rio_info *, struct RioHostInfo *);
+void RIOInitHosts(struct rio_info *, struct RioHostInfo *);
+void RIOISAinit(struct rio_info *,int);
+int RIODoAT(struct rio_info *, int, int);
+caddr_t RIOCheckForATCard(int);
+int RIOAssignAT(struct rio_info *, int, caddr_t, int);
+int RIOBoardTest(paddr_t, caddr_t, uchar, int);
+int RIOScrub(int, BYTE *, int);
+void RIOAllocateInterrupts(struct rio_info *);
+void RIOStopInterrupts(struct rio_info *, int, int);
+void RIOAllocDataStructs(struct rio_info *);
+void RIOSetupDataStructs(struct rio_info *);
+int RIODefaultName(struct rio_info *, struct Host *, uint);
+int RIOReport(struct rio_info *);
+struct rioVersion * RIOVersid(void);
+int RIOMapin(paddr_t, int, caddr_t *);
+void RIOMapout(paddr_t, long, caddr_t);
+void RIOHostReset(uint, volatile struct DpRam *, uint);
+
+/* riointr.c */
+void riopoll(struct rio_info *);
+void riointr(struct rio_info *);
+void RIOTxEnable(char *);
+void RIOServiceHost(struct rio_info *, struct Host *, int);
+void RIOReceive(struct rio_info *, struct Port *);
+int riotproc(struct rio_info *, register struct ttystatics *, int, int);
+
+/* rioparam.c */
+int RIOParam(struct Port *, int, int, int);
+int RIODelay(struct Port *PortP, int);
+int RIODelay_ni(struct Port *PortP, int);
+void ms_timeout(struct Port *);
+int can_add_transmit(struct PKT **, struct Port *);
+void add_transmit(struct Port *);
+void put_free_end(struct Host *, struct PKT *);
+int can_remove_receive(struct PKT **, struct Port *);
+void remove_receive(struct Port *);
+
+/* rioroute.c */
+int RIORouteRup(struct rio_info *, uint, struct Host *, struct PKT *);
+void RIOFixPhbs(struct rio_info *, struct Host *, uint); 
+int RIOCheckIsolated(struct rio_info *, struct Host *, uint);
+int RIOIsolate(struct rio_info *, struct Host *, uint);
+int RIOCheck(struct Host *, uint);
+uint GetUnitType(uint);
+int RIOSetChange(struct rio_info *);
+void RIOConCon(struct rio_info *, struct Host *, uint, uint, uint, uint, int);
+int RIOFindFreeID(struct rio_info *, struct Host *, uint *, uint *);
+int RIOFreeDisconnected(struct rio_info *, struct Host *, int );
+int RIORemoveFromSavedTable(struct rio_info *, struct Map *);
+
+
+/* riotty.c */
+
+int riotopen(struct tty_struct * tty, struct file * filp);
+int riotclose(void  *ptr);
+int RIOCookMode(struct ttystatics *);
+int riotioctl(struct rio_info *, dev_t, register int, register caddr_t); 
+void ttyseth(struct Port *, struct ttystatics *, struct old_sgttyb *sg);
+
+/* riotable.c */
+int RIONewTable(struct rio_info *);
+int RIOApel(struct rio_info *);
+int RIODeleteRta(struct rio_info *, struct Map *);
+int RIOAssignRta(struct rio_info *, struct Map *);
+int RIOReMapPorts(struct rio_info *, struct Host *, struct Map *);
+int RIOChangeName(struct rio_info *, struct Map*);
+
+#if 0
+/* riodrvr.c */
+struct rio_info * rio_install(struct RioHostInfo *);
+int rio_uninstall(register struct rio_info *);
+int rio_open(struct rio_info *, int, struct file *);
+int rio_close(struct rio_info *, struct file *);
+int rio_read(struct rio_info *, struct file *, char *, int);
+int rio_write(struct rio_info *, struct file *	f, char *, int);
+int rio_ioctl(struct rio_info *, struct file *, int, char *);
+int rio_select(struct rio_info *, struct file *	f, int, struct sel *);
+int	rio_intr(char *);
+int rio_isr_thread(char  *);
+struct rio_info * rio_info_store( int cmd, struct rio_info * p);
+#endif
+
+extern int    rio_pcicopy(char *src, char *dst, int n);
+extern int rio_minor (kdev_t device);
+extern int rio_ismodem (kdev_t device);
+extern void rio_udelay (int usecs);
+
+#endif	/* __func_h_def */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/host.h linux.15p9/drivers/char/rio/host.h
--- linux.vanilla/drivers/char/rio/host.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/host.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,134 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: host.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:10
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)host.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_host_h__
+#define __rio_host_h__
+
+#ifdef SCCS_LABELS
+#ifndef lint
+static char *_host_h_sccs_ = "@(#)host.h	1.2";
+#endif
+#endif
+
+/*
+** the host structure - one per host card in the system.
+*/
+
+#define	MAX_EXTRA_UNITS	64
+
+/*
+**    Host data structure. This is used for the software equiv. of
+**    the host.
+*/
+struct    Host
+{
+    uchar             	    Type;      /* RIO_EISA, RIO_MCA, ... */
+    uchar             	    Ivec;      /* POLLED or ivec number */
+    uchar             	    Mode;      /* Control stuff */
+    uchar                   Slot;      /* Slot */
+    volatile caddr_t        Caddr;     /* KV address of DPRAM */
+    volatile struct DpRam   *CardP;    /* KV address of DPRAM, with overlay */
+    paddr_t          	    PaddrP;    /* Phys. address of DPRAM */
+    char                    Name[MAX_NAME_LEN];  /* The name of the host */
+    uint            	    UniqueNum; /* host unique number */
+    semtype	    HostLock;  /* Lock structure for MPX */
+    /*struct pci_devinfo	    PciDevInfo; *//* PCI Bus/Device/Function stuff */
+    /*struct lockb	    HostLock;  *//* Lock structure for MPX */
+    uint                    WorkToBeDone; /* set to true each interrupt */
+    uint                    InIntr;    /* Being serviced? */
+    uint                    IntSrvDone;	/* host's interrupt has been serviced */
+    int			    (*Copy)( caddr_t, caddr_t, int ); /* copy func */
+    struct timer_list timer;
+    /*
+    **               I M P O R T A N T !
+    **
+    ** The rest of this data structure is cleared to zero after
+    ** a RIO_HOST_FOAD command.
+    */
+    
+    ulong                   Flags;     /* Whats going down */
+#define RC_WAITING            0
+#define RC_STARTUP            1
+#define RC_RUNNING            2
+#define RC_STUFFED            3
+#define RC_SOMETHING          4
+#define RC_SOMETHING_NEW      5
+#define RC_SOMETHING_ELSE     6
+#define RC_READY              7
+#define RUN_STATE             7
+/*
+** Boot mode applies to the way in which hosts in this system will
+** boot RTAs
+*/
+#define RC_BOOT_ALL           0x8	/* Boot all RTAs attached */
+#define RC_BOOT_OWN           0x10	/* Only boot RTAs bound to this system */
+#define RC_BOOT_NONE          0x20	/* Don't boot any RTAs (slave mode) */
+
+    struct Top		    Topology[LINKS_PER_UNIT]; /* one per link */
+    struct Map              Mapping[MAX_RUP];     /* Mappings for host */
+    struct PHB		    *PhbP;                /* Pointer to the PHB array */
+    ushort           	    *PhbNumP;             /* Ptr to Number of PHB's */
+    struct LPB 	            *LinkStrP ;           /* Link Structure Array */
+    struct RUP       	    *RupP;                /* Sixteen real rups here */
+    struct PARM_MAP  	    *ParmMapP;            /* points to the parmmap */
+    uint                    ExtraUnits[MAX_EXTRA_UNITS]; /* unknown things */
+    uint                    NumExtraBooted;       /* how many of the above */
+    /*
+    ** Twenty logical rups.
+    ** The first sixteen are the real Rup entries (above), the last four
+    ** are the link RUPs.
+    */
+    struct UnixRup	    UnixRups[MAX_RUP+LINKS_PER_UNIT];
+	int				timeout_id;	/* For calling 100 ms delays */
+	int				timeout_sem;/* For calling 100 ms delays */
+    int locks;
+    char             	    ____end_marker____;
+};
+#define Control      CardP->DpControl
+#define SetInt       CardP->DpSetInt
+#define ResetTpu     CardP->DpResetTpu
+#define ResetInt     CardP->DpResetInt
+#define Signature    CardP->DpSignature
+#define Sram1        CardP->DpSram1
+#define Sram2        CardP->DpSram2
+#define Sram3        CardP->DpSram3
+#define Scratch      CardP->DpScratch
+#define __ParmMapR   CardP->DpParmMapR
+#define SLX          CardP->DpSlx
+#define Revision     CardP->DpRevision
+#define Unique       CardP->DpUnique
+#define Year         CardP->DpYear
+#define Week         CardP->DpWeek
+
+#define RIO_DUMBPARM 0x0860    /* what not to expect */
+
+#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/hosthw.h linux.15p9/drivers/char/rio/hosthw.h
--- linux.vanilla/drivers/char/rio/hosthw.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/hosthw.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,57 @@
+/****************************************************************************
+ *******                                                              *******
+ *******                H O S T      H A R D W A R E
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra / Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+
+#ifndef lint
+#ifdef SCCS_LABELS
+static char *_rio_hosthw_h_sccs = "@(#)hosthw.h	1.2" ;
+#endif
+#endif
+
+#define SET_OTHER_INTERRUPT  ( (volatile u_short *) 0x7c80 )
+#define SET_EISA_INTERRUPT  ( (volatile u_short *) 0x7ef0 )
+
+#define EISA_HOST    0x30
+#define AT_HOST      0xa0
+#define MCA_HOST     0xb0
+#define PCI_HOST     0xd0
+
+#define PRODUCT_MASK 0xf0
+
+
+/*********** end of file ***********/
+
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/link.h linux.15p9/drivers/char/rio/link.h
--- linux.vanilla/drivers/char/rio/link.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/link.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,188 @@
+/****************************************************************************
+ *******                                                              *******
+ *******                      L I N K
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra / Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _link_h
+#define _link_h 1
+
+#ifndef lint
+#ifdef SCCS_LABELS
+/* static char *_rio_link_h_sccs = "@(#)link.h	1.15"; */
+#endif
+#endif
+
+
+
+/*************************************************
+ * Define the Link Status stuff
+ ************************************************/
+#define LRT_ACTIVE         ((ushort) 0x01)
+#define LRT_SPARE1         ((ushort) 0x02)
+#define INTRO_RCVD         ((ushort) 0x04)
+#define FORCED_DISCONNECT  ((ushort) 0x08)
+#define LRT_SPARE2	   ((ushort) 0x80)
+
+#define TOP_OF_RTA_RAM     ((ushort) 0x7000)
+#define HOST_SERIAL_POINTER (unsigned char **) (TOP_OF_RTA_RAM - 2 * sizeof (ushort))
+
+/* Flags for ltt_status */
+#define  WAITING_ACK		(ushort) 0x0001
+#define  DATA_SENT		(ushort) 0x0002
+#define  WAITING_RUP		(ushort) 0x0004
+#define  WAITING_RETRY		(ushort) 0x0008
+#define  WAITING_TOPOLOGY	(ushort) 0x0010
+#define  SEND_SYNC		(ushort) 0x0020
+#define  FOAD_THIS_LINK		(ushort) 0x0040
+#define  REQUEST_SYNC		(ushort) 0x0080
+#define  REMOTE_DYING		(ushort) 0x0100
+#define  DIE_NOW		(ushort) 0x0200
+
+/* Boot request stuff */
+#define BOOT_REQUEST       ((ushort) 0)    /* Request for a boot */
+#define BOOT_ABORT         ((ushort) 1)    /* Abort a boot */
+#define BOOT_SEQUENCE      ((ushort) 2)    /* Packet with the number of packets
+                                              and load address */
+#define BOOT_COMPLETED     ((ushort) 3)    /* Boot completed */
+
+/* States that a link can be in */
+#define	LINK_DISCONNECTED  ((ushort) 0)    /* Disconnected */
+#define LINK_BOOT1         ((ushort) 1)    /* Trying to send 1st stage boot */
+#define LINK_BOOT2         ((ushort) 2)    /* Trying to send 2nd stage boot */
+#define LINK_BOOT2WAIT     ((ushort) 3)    /* Waiting for selftest results */
+#define LINK_BOOT3         ((ushort) 4)    /* Trying to send 3rd stage boots */
+#define LINK_SYNC          ((ushort) 5)    /* Syncing */
+
+#define LINK_INTRO         ((ushort) 10)    /* Introductory packet */
+#define LINK_SUPPLYID      ((ushort) 11)    /* Trying to supply an ID */
+#define LINK_TOPOLOGY      ((ushort) 12)    /* Send a topology update */
+#define LINK_REQUESTID     ((ushort) 13)    /* Waiting for an ID */
+#define LINK_CONNECTED     ((ushort) 14)    /* Connected */
+
+#define LINK_INTERCONNECT  ((ushort) 20)   /* Subnets interconnected */
+
+#define LINK_SPARE	   ((ushort) 40)
+
+/*
+** Set the default timeout for link communications.
+*/
+#define	LINKTIMEOUT		(400 * MILLISECOND)
+
+/*
+** LED stuff
+*/
+#if defined(RTA)
+#define LED_OFF            ((ushort) 0)    /* LED off */
+#define LED_RED            ((ushort) 1)    /* LED Red */
+#define LED_GREEN          ((ushort) 2)    /* LED Green */
+#define LED_ORANGE         ((ushort) 4)    /* LED Orange */
+#define LED_1TO8_OPEN      ((ushort) 1)    /* Port 1->8 LED on */
+#define LED_9TO16_OPEN     ((ushort) 2)    /* Port 9->16 LED on */
+#define LED_SET_COLOUR(colour)	(link->led = (colour))
+#define LED_OR_COLOUR(colour)	(link->led |= (colour))
+#define LED_TIMEOUT(time)    (link->led_timeout = RioTimePlus(RioTime(),(time)))
+#else
+#define LED_SET_COLOUR(colour)
+#define LED_OR_COLOUR(colour)
+#define LED_TIMEOUT(time)
+#endif /* RTA */
+
+struct LPB {
+               WORD          link_number ;       /* Link Number */
+               Channel_ptr   in_ch ;             /* Link In Channel */
+               Channel_ptr   out_ch ;            /* Link Out Channel */
+#ifdef RTA
+               uchar        stat_led ;          /* Port open leds */
+               uchar        led ;               /* True, light led! */
+#endif
+               BYTE attached_serial[4]; /* Attached serial number */
+               BYTE attached_host_serial[4];
+                                                 /* Serial number of Host who
+                                                    booted the other end */
+               WORD          descheduled ;       /* Currently Descheduled */
+               WORD          state;              /* Current state */
+               WORD          send_poll ;         /* Send a Poll Packet */
+               Process_ptr   ltt_p ;             /* Process Descriptor */
+               Process_ptr   lrt_p ;             /* Process Descriptor */
+               WORD          lrt_status ;        /* Current lrt status */
+               WORD          ltt_status ;        /* Current ltt status */
+               WORD          timeout ;           /* Timeout value */
+               WORD          topology;           /* Topology bits */
+               WORD          mon_ltt ;
+               WORD          mon_lrt ;
+               WORD          WaitNoBoot ;	 /* Secs to hold off booting */
+               PKT_ptr       add_packet_list;    /* Add packets to here */
+               PKT_ptr       remove_packet_list; /* Send packets from here */
+#ifdef RTA
+#ifdef DCIRRUS
+#define    QBUFS_PER_REDIRECT (4 / PKTS_PER_BUFFER + 1) 
+#else
+#define    QBUFS_PER_REDIRECT (8 / PKTS_PER_BUFFER + 1) 
+#endif
+               PKT_ptr_ptr   rd_add ;            /* Add a new Packet here */
+               Q_BUF_ptr     rd_add_qb;          /* Pointer to the add Q buf */
+               PKT_ptr_ptr   rd_add_st_qbb ;     /* Pointer to start of the Q's buf */
+               PKT_ptr_ptr   rd_add_end_qbb ;    /* Pointer to the end of the Q's buf */
+               PKT_ptr_ptr   rd_remove ;         /* Remove a Packet here */
+               Q_BUF_ptr     rd_remove_qb ;      /* Pointer to the remove Q buf */
+               PKT_ptr_ptr   rd_remove_st_qbb ;  /* Pointer to the start of the Q buf */
+               PKT_ptr_ptr   rd_remove_end_qbb ; /* Pointer to the end of the Q buf */
+               ushort        pkts_in_q ;         /* Packets in queue */
+#endif
+
+               Channel_ptr   lrt_fail_chan ;     /* Lrt's failure channel */
+               Channel_ptr   ltt_fail_chan ;     /* Ltt's failure channel */
+
+#if defined (HOST) || defined (INKERNEL)
+ /* RUP structure for HOST to driver communications */
+               struct RUP           rup ;              
+#endif
+               struct RUP           link_rup;           /* RUP for the link (POLL,
+                                                    topology etc.) */
+               WORD          attached_link ;     /* Number of attached link */
+               WORD          csum_errors ;       /* csum errors */
+               WORD          num_disconnects ;   /* number of disconnects */
+               WORD          num_sync_rcvd ;     /* # sync's received */
+               WORD          num_sync_rqst ;     /* # sync requests */
+               WORD          num_tx ;            /* Num pkts sent */
+               WORD          num_rx ;            /* Num pkts received */
+               WORD          module_attached;    /* Module tpyes of attached */
+               WORD          led_timeout;        /* LED timeout */
+               WORD          first_port;         /* First port to service */
+               WORD          last_port;          /* Last port to service */
+           } ;
+
+#endif
+
+/*********** end of file ***********/
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/linux_compat.h linux.15p9/drivers/char/rio/linux_compat.h
--- linux.vanilla/drivers/char/rio/linux_compat.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/linux_compat.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,128 @@
+/*
+ * (C) 2000 R.E.Wolff@BitWizard.nl
+ *
+ *      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.
+ */
+
+
+#define disable(oldspl) save_flags (oldspl)
+#define restore(oldspl) restore_flags (oldspl)
+
+#define sysbrk(x) kmalloc ((x), GFP_KERNEL)
+#define sysfree(p,size) kfree ((p))
+
+#define WBYTE(p,v) writeb(v, &p)
+#define RBYTE(p)   readb (&p)
+#define WWORD(p,v) writew(v, &p)
+#define RWORD(p)   readw(&p)
+#define WINDW(p,v) writew(v, p)
+#define RINDW(p)   readw(p)
+
+#define DEBUG_ALL
+
+#define cprintf printk
+
+#ifdef __KERNEL__
+#define INKERNEL
+#endif
+
+struct ttystatics {
+  struct termios tm;
+};
+
+#define bzero(d, n)         memset((d), 0, (n))
+#define bcopy(src, dest, n) memcpy ((dest), (src), (n))
+
+#define SEM_SIGIGNORE 0x1234
+
+typedef struct semaphore semtype;
+
+
+#ifdef DEBUG_SEM
+#define swait(a,b)      printk ("waiting:    " __FILE__ " line %d\n", __LINE__)
+#define ssignal(sem)    printk ("signalling: " __FILE__ " line %d\n", __LINE__)
+
+#define sreset(sem)     printk ("sreset:     " __FILE__ "\n")
+#define sem_init(sem,v) printk ("sreset:     " __FILE__ "\n")
+#endif
+
+
+#define getpid()    (current->pid)
+
+#define major(dev) MAJOR(dev)
+#define minor(dev) MINOR(dev)
+
+#define QSIZE SERIAL_XMIT_SIZE
+
+#define pseterr(errno) return (- errno)
+
+#define V_CBAUD CBAUD
+
+/* For one reason or another rioboot.c uses delay instead of RIODelay. */
+#define delay(x,y) RIODelay(NULL, y)
+
+extern int rio_debug;
+
+#define rio_dprint(f, p) do {if (rio_debug & f) printk p;} while (0)
+
+#define RIO_DEBUG_INIT         0x000001
+#define RIO_DEBUG_BOOT         0x000002
+#define RIO_DEBUG_CMD          0x000004
+#define RIO_DEBUG_CTRL         0x000008
+#define RIO_DEBUG_INTR         0x000010
+#define RIO_DEBUG_PARAM        0x000020
+#define RIO_DEBUG_ROUTE        0x000040
+#define RIO_DEBUG_TABLE        0x000080
+#define RIO_DEBUG_TTY          0x000100
+#define RIO_DEBUG_FLOW         0x000200
+#define RIO_DEBUG_MODEMSIGNALS 0x000400
+#define RIO_DEBUG_PROBE        0x000800
+#define RIO_DEBUG_CLEANUP      0x001000
+#define RIO_DEBUG_IFLOW        0x002000
+#define RIO_DEBUG_PFE          0x004000
+#define RIO_DEBUG_REC          0x008000
+#define RIO_DEBUG_SPINLOCK     0x010000
+#define RIO_DEBUG_DELAY        0x020000
+
+
+/* Copied over from riowinif.h . This is ugly. The winif file declares
+also much other stuff which is incompatible with the headers from
+the older driver. The older driver includes "brates.h" which shadows
+the definitions from Linux, and is incompatible... */
+
+/* RxBaud and TxBaud definitions... */
+#define	RIO_B0			0x00			/* RTS / DTR signals dropped */
+#define	RIO_B50			0x01			/* 50 baud */
+#define	RIO_B75			0x02			/* 75 baud */
+#define	RIO_B110		0x03			/* 110 baud */
+#define	RIO_B134		0x04			/* 134.5 baud */
+#define	RIO_B150		0x05			/* 150 baud */
+#define	RIO_B200		0x06			/* 200 baud */
+#define	RIO_B300		0x07			/* 300 baud */
+#define	RIO_B600		0x08			/* 600 baud */
+#define	RIO_B1200		0x09			/* 1200 baud */
+#define	RIO_B1800		0x0A			/* 1800 baud */
+#define	RIO_B2400		0x0B			/* 2400 baud */
+#define	RIO_B4800		0x0C			/* 4800 baud */
+#define	RIO_B9600		0x0D			/* 9600 baud */
+#define	RIO_B19200		0x0E			/* 19200 baud */
+#define	RIO_B38400		0x0F			/* 38400 baud */
+#define	RIO_B56000		0x10			/* 56000 baud */
+#define	RIO_B57600		0x11			/* 57600 baud */
+#define	RIO_B64000		0x12			/* 64000 baud */
+#define	RIO_B115200		0x13			/* 115200 baud */
+#define	RIO_B2000		0x14			/* 2000 baud */
+
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/list.h linux.15p9/drivers/char/rio/list.h
--- linux.vanilla/drivers/char/rio/list.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/list.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,196 @@
+/****************************************************************************
+ *******                                                              *******
+ *******                      L I S T                                 *******
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Jeremy Rolls.
+ Date    : 04-Nov-1990
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+ ***************************************************************************/
+
+#ifndef _list_h
+#define _list_h 1
+
+#ifdef SCCS_LABELS
+#ifndef lint
+static char *_rio_list_h_sccs = "@(#)list.h	1.9" ;
+#endif
+#endif
+
+#define PKT_IN_USE    0x1
+
+#ifdef INKERNEL
+
+#define ZERO_PTR (ushort) 0x8000
+#define	CaD	PortP->Caddr
+
+/*
+** We can add another packet to a transmit queue if the packet pointer pointed
+** to by the TxAdd pointer has PKT_IN_USE clear in its address.
+*/
+
+#ifndef linux
+#if defined( MIPS ) && !defined( MIPSEISA )
+/* May the shoes of the Devil dance on your grave for creating this */
+#define   can_add_transmit(PacketP,PortP) \
+          (!((uint)(PacketP = (struct PKT *)RIO_PTR(CaD,RINDW(PortP->TxAdd))) \
+          & (PKT_IN_USE<<2)))
+
+#elif  defined(MIPSEISA) || defined(nx6000) || \
+       defined(drs6000)  || defined(UWsparc)
+
+#define   can_add_transmit(PacketP,PortP) \
+          (!((uint)(PacketP = (struct PKT *)RIO_PTR(CaD,RINDW(PortP->TxAdd))) \
+	  & PKT_IN_USE))
+
+#else
+#define   can_add_transmit(PacketP,PortP) \
+          (!((uint)(PacketP = (struct PKT *)RIO_PTR(CaD,*PortP->TxAdd)) \
+	  & PKT_IN_USE))
+#endif
+
+/*
+** To add a packet to the queue, you set the PKT_IN_USE bit in the address,
+** and then move the TxAdd pointer along one position to point to the next
+** packet pointer. You must wrap the pointer from the end back to the start.
+*/
+#if defined(MIPS) || defined(nx6000) || defined(drs6000) || defined(UWsparc)
+#   define add_transmit(PortP)  \
+	WINDW(PortP->TxAdd,RINDW(PortP->TxAdd) | PKT_IN_USE);\
+	if (PortP->TxAdd == PortP->TxEnd)\
+	    PortP->TxAdd = PortP->TxStart;\
+	else\
+	    PortP->TxAdd++;\
+	WWORD(PortP->PhbP->tx_add , RIO_OFF(CaD,PortP->TxAdd));
+#elif defined(AIX)
+#   define add_transmit(PortP)  \
+	{\
+	    register ushort *TxAddP = (ushort *)RIO_PTR(Cad,PortP->TxAddO);\
+	    WINDW( TxAddP, RINDW( TxAddP ) | PKT_IN_USE );\
+	    if (PortP->TxAddO == PortP->TxEndO )\
+		PortP->TxAddO = PortP->TxStartO;\
+	    else\
+		PortP->TxAddO += sizeof(ushort);\
+	    WWORD(((PHB *)RIO_PTR(Cad,PortP->PhbO))->tx_add , PortP->TxAddO );\
+	}
+#else
+#   define add_transmit(PortP)  \
+	*PortP->TxAdd |= PKT_IN_USE;\
+	if (PortP->TxAdd == PortP->TxEnd)\
+	    PortP->TxAdd = PortP->TxStart;\
+	else\
+	    PortP->TxAdd++;\
+	PortP->PhbP->tx_add = RIO_OFF(CaD,PortP->TxAdd);
+#endif
+
+/*
+** can_remove_receive( PacketP, PortP ) returns non-zero if PKT_IN_USE is set
+** for the next packet on the queue. It will also set PacketP to point to the
+** relevent packet, [having cleared the PKT_IN_USE bit]. If PKT_IN_USE is clear,
+** then can_remove_receive() returns 0.
+*/
+#if defined(MIPS) || defined(nx6000) || defined(drs6000) || defined(UWsparc)
+#   define can_remove_receive(PacketP,PortP) \
+	((RINDW(PortP->RxRemove) & PKT_IN_USE) ? \
+	(PacketP=(struct PKT *)RIO_PTR(CaD,(RINDW(PortP->RxRemove) & ~PKT_IN_USE))):0)
+#elif defined(AIX)
+#   define can_remove_receive(PacketP,PortP) \
+	((RINDW((ushort *)RIO_PTR(Cad,PortP->RxRemoveO)) & PKT_IN_USE) ? \
+	(PacketP=(struct PKT *)RIO_PTR(Cad,RINDW((ushort *)RIO_PTR(Cad,PortP->RxRemoveO)) & ~PKT_IN_USE)):0)
+#else
+#   define can_remove_receive(PacketP,PortP) \
+	((*PortP->RxRemove & PKT_IN_USE) ? \
+	(PacketP=(struct PKT *)RIO_PTR(CaD,(*PortP->RxRemove & ~PKT_IN_USE))):0)
+#endif
+
+
+/*
+** Will God see it within his heart to forgive us for this thing that
+** we have created? To remove a packet from the receive queue you clear
+** its PKT_IN_USE bit, and then bump the pointers. Once the pointers
+** get to the end, they must be wrapped back to the start.
+*/
+#if defined(MIPS) || defined(nx6000) || defined(drs6000) || defined(UWsparc)
+#   define remove_receive(PortP) \
+	WINDW(PortP->RxRemove, (RINDW(PortP->RxRemove) & ~PKT_IN_USE));\
+	if (PortP->RxRemove == PortP->RxEnd)\
+	    PortP->RxRemove = PortP->RxStart;\
+	else\
+	    PortP->RxRemove++;\
+	WWORD(PortP->PhbP->rx_remove , RIO_OFF(CaD,PortP->RxRemove));
+#elif defined(AIX)
+#   define remove_receive(PortP) \
+    {\
+        register ushort *RxRemoveP = (ushort *)RIO_PTR(Cad,PortP->RxRemoveO);\
+        WINDW( RxRemoveP, RINDW( RxRemoveP ) & ~PKT_IN_USE );\
+        if (PortP->RxRemoveO == PortP->RxEndO)\
+            PortP->RxRemoveO = PortP->RxStartO;\
+        else\
+            PortP->RxRemoveO += sizeof(ushort);\
+        WWORD(((PHB *)RIO_PTR(Cad,PortP->PhbO))->rx_remove, PortP->RxRemoveO );\
+    }
+#else
+#   define remove_receive(PortP) \
+	*PortP->RxRemove &= ~PKT_IN_USE;\
+	if (PortP->RxRemove == PortP->RxEnd)\
+	    PortP->RxRemove = PortP->RxStart;\
+	else\
+	    PortP->RxRemove++;\
+	PortP->PhbP->rx_remove = RIO_OFF(CaD,PortP->RxRemove);
+#endif
+#endif
+
+
+#else /* !IN_KERNEL */
+
+#define ZERO_PTR NULL
+
+
+#ifdef HOST
+/* #define can_remove_transmit(pkt,phb) ((((char*)pkt = (*(char**)(phb->tx_remove))-1) || 1)) && (*phb->u3.s2.tx_remove_ptr & PKT_IN_USE))   */
+#define remove_transmit(phb) *phb->u3.s2.tx_remove_ptr &= ~(ushort)PKT_IN_USE;\
+                             if (phb->tx_remove == phb->tx_end)\
+                                phb->tx_remove = phb->tx_start;\
+                             else\
+                                phb->tx_remove++;
+#define can_add_receive(phb) !(*phb->u4.s2.rx_add_ptr & PKT_IN_USE)
+#define add_receive(pkt,phb) *phb->rx_add = pkt;\
+                             *phb->u4.s2.rx_add_ptr |= PKT_IN_USE;\
+                             if (phb->rx_add == phb->rx_end)\
+                                phb->rx_add = phb->rx_start;\
+                             else\
+                                phb->rx_add++;
+#endif
+#endif
+
+#ifdef RTA
+#define splx(oldspl)    if ((oldspl) == 0) spl0()
+#endif
+
+#endif /* ifndef _list.h */
+/*********** end of file ***********/
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/lrt.h linux.15p9/drivers/char/rio/lrt.h
--- linux.vanilla/drivers/char/rio/lrt.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/lrt.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,55 @@
+/****************************************************************************
+ *******                                                              *******
+ *******                      L R T
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra / Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef lint
+#ifdef SCCS_LABELS
+static char *_rio_lrt_h_sccs = "@(#)lrt.h	1.1" ;
+#endif
+#endif
+
+
+#ifdef DCIRRUS
+#define LRT_STACK       (unsigned short) 600
+#else
+#define LRT_STACK        (ushort) 200
+#endif
+
+
+
+/*********** end of file ***********/
+
+
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/ltt.h linux.15p9/drivers/char/rio/ltt.h
--- linux.vanilla/drivers/char/rio/ltt.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/ltt.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,55 @@
+/****************************************************************************
+ *******                                                              *******
+ *******                      L T T
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra / Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef lint
+#ifdef SCCS_LABELS
+static char *_rio_ltt_h_sccs = "@(#)ltt.h	1.1" ;
+#endif
+#endif
+
+#ifdef DCIRRUS
+#define LTT_STACK       (unsigned short)  600
+#else
+#define LTT_STACK       (ushort) 200
+#endif
+ 
+
+
+
+/*********** end of file ***********/
+
+
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/lttwake.h linux.15p9/drivers/char/rio/lttwake.h
--- linux.vanilla/drivers/char/rio/lttwake.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/lttwake.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,53 @@
+
+
+
+/****************************************************************************
+ *******                                                              *******
+ *******            L T T    W A K E U P    H E A D E R
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef lint
+#ifdef SCCS_LABELS
+static char *_rio_lttwake_h_sccs = "@(#)lttwake.h	1.1" ;
+#endif
+#endif
+
+#define LTT_WAKEUP_STACK          500
+#define LTT_WAKEUP_INTERVAL       (int) (500 * MILLISECOND)
+
+
+/*********** end of file ***********/
+
+
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/map.h linux.15p9/drivers/char/rio/map.h
--- linux.vanilla/drivers/char/rio/map.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/map.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,103 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: map.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:11
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)map.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_map_h__
+#define __rio_map_h__
+
+#ifdef SCCS_LABELS
+static char *_map_h_sccs_ = "@(#)map.h	1.2";
+#endif
+
+/*
+** mapping structure passed to and from the config.rio program to
+** determine the current topology of the world
+*/
+
+#define MAX_MAP_ENTRY 17
+#define	TOTAL_MAP_ENTRIES (MAX_MAP_ENTRY*RIO_SLOTS)
+#define	MAX_NAME_LEN 32
+
+struct Map
+{
+	uint	HostUniqueNum;	        /* Supporting hosts unique number */
+	uint	RtaUniqueNum;	        /* Unique number */
+	/*
+	** The next two IDs must be swapped on big-endian architectures
+	** when using a v2.04 /etc/rio/config with a v3.00 driver (when
+	** upgrading for example).
+	*/
+	ushort	ID;			/* ID used in the subnet */
+	ushort	ID2;			/* ID of 2nd block of 8 for 16 port */
+	ulong	Flags;			/* Booted, ID Given, Disconnected */
+	ulong	SysPort;		/* First tty mapped to this port */
+	struct Top   Topology[LINKS_PER_UNIT];	/* ID connected to each link */
+	char	Name[MAX_NAME_LEN];        /* Cute name by which RTA is known */
+};
+
+/*
+** Flag values:
+*/
+#define	RTA_BOOTED		0x00000001
+#define RTA_NEWBOOT		0x00000010
+#define	MSG_DONE		0x00000020
+#define	RTA_INTERCONNECT	0x00000040
+#define	RTA16_SECOND_SLOT	0x00000080
+#define	BEEN_HERE		0x00000100
+#define SLOT_TENTATIVE		0x40000000
+#define SLOT_IN_USE		0x80000000
+
+/*
+** HostUniqueNum is the unique number from the host card that this RTA
+** is to be connected to.
+** RtaUniqueNum is the unique number of the RTA concerned. It will be ZERO
+** if the slot in the table is unused. If it is the same as the HostUniqueNum
+** then this slot represents a host card.
+** Flags contains current boot/route state info
+** SysPort is a value in the range 0-504, being the number of the first tty
+** on this RTA. Each RTA supports 8 ports. The SysPort value must be modulo 8.
+** SysPort 0-127 correspond to /dev/ttyr001 to /dev/ttyr128, with minor
+** numbers 0-127. SysPort 128-255 correspond to /dev/ttyr129 to /dev/ttyr256,
+** again with minor numbers 0-127, and so on for SysPorts 256-383 and 384-511
+** ID will be in the range 0-16 for a `known' RTA. ID will be 0xFFFF for an
+** unused slot/unknown ID etc.
+** The Topology array contains the ID of the unit connected to each of the
+** four links on this unit. The entry will be 0xFFFF if NOTHING is connected
+** to the link, or will be 0xFF00 if an UNKNOWN unit is connected to the link.
+** The Name field is a null-terminated string, upto 31 characters, containing
+** the 'cute' name that the sysadmin/users know the RTA by. It is permissible
+** for this string to contain any character in the range \040 to \176 inclusive.
+** In particular, ctrl sequences and DEL (0x7F, \177) are not allowed. The
+** special character '%' IS allowable, and needs no special action.
+**
+*/
+
+#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/mca.h linux.15p9/drivers/char/rio/mca.h
--- linux.vanilla/drivers/char/rio/mca.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/mca.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,73 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: mca.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:11
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)mca.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_mca_h__
+#define	__rio_mca_h__
+
+#ifdef SCCS_LABELS
+static char *_mca_h_sccs_ = "@(#)mca.h	1.2";
+#endif
+
+/*
+** Micro Channel stuff
+*/
+
+#define	McaMaxSlots	8
+#define McaSlotSelect	0x96
+#define	McaSlotEnable	0x08
+#define	McaIdLow	0x100
+#define	McaIdHigh	0x101
+#define	McaIrqEnable	0x102
+#define	McaMemory	0x103
+#define McaRIOId	0x6a5c
+#define	McaIrq9		0x00
+#define	McaIrq3		0x02
+#define	McaIrq4		0x04
+#define	McaIrq7		0x06
+#define	McaIrq10	0x08
+#define	McaIrq11	0x0A
+#define	McaIrq12	0x0C
+#define	McaIrq15	0x0E
+#define McaIrqMask	0x0E
+#define	McaCardEnable	0x01
+#define	McaAddress(X)	(((X)&0xFF)<<16)
+
+#define	McaTpFastLinks	        0x40
+#define	McaTpSlowLinks	        0x00
+#define	McaTpBootFromRam	0x01
+#define	McaTpBootFromLink	0x00
+#define	McaTpBusEnable		0x02
+#define	McaTpBusDisable		0x00
+
+#define	RIO_MCA_DEFAULT_MODE	SLOW_LINKS
+
+#endif	/* __rio_mca_h__ */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/mesg.h linux.15p9/drivers/char/rio/mesg.h
--- linux.vanilla/drivers/char/rio/mesg.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/mesg.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,41 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: mesg.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:12
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)mesg.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_mesg_h__
+#define	__rio_mesg_h__
+
+#ifdef SCCS_LABELS
+static char *_mesg_h_sccs_ = "@(#)mesg.h	1.2";
+#endif
+
+
+#endif /* __rio_mesg_h__ */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/param.h linux.15p9/drivers/char/rio/param.h
--- linux.vanilla/drivers/char/rio/param.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/param.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,61 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: param.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:12
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)param.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_param_h__
+#define __rio_param_h__
+
+#ifdef SCCS_LABELS
+static char *_param_h_sccs_ = "@(#)param.h	1.2";
+#endif
+
+
+/*
+** the param command block, as used in OPEN and PARAM calls.
+*/
+
+struct phb_param
+{
+    BYTE    Cmd;        /* It is very important that these line up */
+    BYTE    Cor1;       /* with what is expected at the other end. */
+    BYTE    Cor2;       /* to confirm that you've got it right,    */
+    BYTE    Cor4;       /* check with cirrus/cirrus.h              */
+    BYTE    Cor5;
+    BYTE    TxXon;	/* Transmit X-On character */
+    BYTE    TxXoff;	/* Transmit X-Off character */
+    BYTE    RxXon;	/* Receive X-On character */
+    BYTE    RxXoff;	/* Receive X-Off character */
+    BYTE    LNext;	/* Literal-next character */
+    BYTE    TxBaud;	/* Transmit baudrate */
+    BYTE    RxBaud;	/* Receive baudrate */
+};
+
+#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/parmmap.h linux.15p9/drivers/char/rio/parmmap.h
--- linux.vanilla/drivers/char/rio/parmmap.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/parmmap.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,96 @@
+/****************************************************************************
+ *******                                                              *******
+ *******               H O S T   M E M O R Y  M A P
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra / Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+6/4/1991   jonb		     Made changes to accomodate Mips R3230 bus
+ ***************************************************************************/
+
+#ifndef _parmap_h
+#define _parmap_h
+
+
+#ifdef SCCS_LABELS
+#ifndef lint
+/* static char *_rio_parmmap_h_sccs = "@(#)parmmap.h	1.4"; */
+#endif
+#endif
+
+typedef struct PARM_MAP PARM_MAP ;
+
+struct PARM_MAP
+{
+PHB_ptr           phb_ptr ;              /* Pointer to the PHB array */
+WORD_ptr          phb_num_ptr ;          /* Ptr to Number of PHB's */
+FREE_LIST_ptr     free_list;             /* Free List pointer */
+FREE_LIST_ptr     free_list_end;         /* Free List End pointer */
+Q_BUF_ptr_ptr     q_free_list_ptr ;      /* Ptr to Q_BUF variable */
+BYTE_ptr          unit_id_ptr ;          /* Unit Id */
+LPB_ptr           link_str_ptr ;         /* Link Structure Array */
+BYTE_ptr          bootloader_1 ;         /* 1st Stage Boot Loader */
+BYTE_ptr          bootloader_2 ;         /* 2nd Stage Boot Loader */
+WORD_ptr          port_route_map_ptr ;   /* Port Route Map */
+ROUTE_STR_ptr     route_ptr ;            /* Unit Route Map */
+NUMBER_ptr        map_present ;          /* Route Map present */
+NUMBER            pkt_num ;               /* Total number of packets */
+NUMBER            q_num ;                 /* Total number of Q packets */
+WORD              buffers_per_port ;      /* Number of buffers per port */
+WORD              heap_size ;             /* Initial size of heap */
+WORD              heap_left ;             /* Current Heap left */
+WORD              error ;                 /* Error code */
+WORD              tx_max;                 /* Max number of tx pkts per phb */
+WORD              rx_max;                 /* Max number of rx pkts per phb */
+WORD              rx_limit;               /* For high / low watermarks */
+NUMBER            links ;                 /* Links to use */
+NUMBER            timer ;                 /* Interrupts per second */
+RUP_ptr           rups ;                 /* Pointer to the RUPs */
+WORD              max_phb ;              /* Mostly for debugging */
+WORD              living ;               /* Just increments!! */
+WORD              init_done ;            /* Initialisation over */
+WORD              booting_link ;
+WORD              idle_count ;           /* Idle time counter */
+WORD              busy_count ;           /* Busy counter */
+WORD              idle_control ;         /* Control Idle Process */
+#if defined(HOST) || defined(INKERNEL)
+WORD              tx_intr;               /* TX interrupt pending */
+WORD              rx_intr;               /* RX interrupt pending */
+WORD              rup_intr;              /* RUP interrupt pending */
+#endif
+#if defined(RTA)
+WORD		  dying_count;		/* Count of processes dead */
+#endif
+} ;
+
+#endif
+
+/*********** end of file ***********/
+
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/pci.h linux.15p9/drivers/char/rio/pci.h
--- linux.vanilla/drivers/char/rio/pci.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/pci.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,76 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: pci.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:12
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)pci.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_pci_h__
+#define	__rio_pci_h__
+
+#ifdef SCCS_LABELS
+static char *_pci_h_sccs_ = "@(#)pci.h	1.2";
+#endif
+
+/*
+** PCI stuff
+*/
+
+#define	PCITpFastClock		0x80
+#define	PCITpSlowClock		0x00
+#define	PCITpFastLinks	        0x40
+#define	PCITpSlowLinks	        0x00
+#define	PCITpIntEnable		0x04
+#define	PCITpIntDisable		0x00
+#define	PCITpBusEnable		0x02
+#define	PCITpBusDisable		0x00
+#define	PCITpBootFromRam	0x01
+#define	PCITpBootFromLink	0x00
+
+#define	RIO_PCI_VENDOR		0x11CB
+#define	RIO_PCI_DEVICE		0x8000
+#define	RIO_PCI_BASE_CLASS	0x02
+#define	RIO_PCI_SUB_CLASS	0x80
+#define	RIO_PCI_PROG_IFACE	0x00
+
+#define RIO_PCI_RID		0x0008
+#define RIO_PCI_BADR0		0x0010
+#define RIO_PCI_INTLN		0x003C
+#define RIO_PCI_INTPIN		0x003D
+
+#define	RIO_PCI_MEM_SIZE	65536
+
+#define	RIO_PCI_TURBO_TP	0x80
+#define	RIO_PCI_FAST_LINKS	0x40
+#define	RIO_PCI_INT_ENABLE	0x04
+#define	RIO_PCI_TP_BUS_ENABLE	0x02
+#define	RIO_PCI_BOOT_FROM_RAM	0x01
+
+#define	RIO_PCI_DEFAULT_MODE	0x05
+
+#endif	/* __rio_pci_h__ */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/phb.h linux.15p9/drivers/char/rio/phb.h
--- linux.vanilla/drivers/char/rio/phb.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/phb.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,293 @@
+/****************************************************************************
+ *******                                                              *******
+ *******                 P H B     H E A D E R                        *******
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra, Jeremy Rolls
+ Date    : 
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _phb_h
+#define _phb_h 1
+
+#ifdef SCCS_LABELS
+#ifndef lint
+/* static char *_rio_phb_h_sccs = "@(#)phb.h	1.12"; */
+#endif
+#endif
+
+
+ /*************************************************
+  * Set the LIMIT values.
+  ************************************************/
+#ifdef RTA
+#define RX_LIMIT       (ushort) 3
+#endif
+#ifdef HOST
+#define RX_LIMIT       (ushort) 1
+#endif
+
+
+/*************************************************
+ * Handshake asserted. Deasserted by the LTT(s)
+ ************************************************/
+#define PHB_HANDSHAKE_SET      ((ushort) 0x001) /* Set by LRT */
+
+#define PHB_HANDSHAKE_RESET     ((ushort) 0x002) /* Set by ISR / driver */
+
+#define PHB_HANDSHAKE_FLAGS     (PHB_HANDSHAKE_RESET | PHB_HANDSHAKE_SET)
+                                                /* Reset by ltt */
+
+
+/*************************************************
+ * Maximum number of PHB's
+ ************************************************/
+#if defined (HOST) || defined (INKERNEL)
+#define MAX_PHB               ((ushort) 128)  /* range 0-127 */
+#else
+#define MAX_PHB               ((ushort) 8)    /* range 0-7 */
+#endif
+
+/*************************************************
+ * Defines for the mode fields
+ ************************************************/
+#define TXPKT_INCOMPLETE        0x0001  /* Previous tx packet not completed */
+#define TXINTR_ENABLED          0x0002  /* Tx interrupt is enabled */
+#define TX_TAB3                 0x0004  /* TAB3 mode */
+#define TX_OCRNL                0x0008  /* OCRNL mode */
+#define TX_ONLCR                0x0010  /* ONLCR mode */
+#define TX_SENDSPACES           0x0020  /* Send n spaces command needs 
+                                           completing */
+#define TX_SENDNULL             0x0040  /* Escaping NULL needs completing */
+#define TX_SENDLF               0x0080  /* LF -> CR LF needs completing */
+#define TX_PARALLELBUG          0x0100  /* CD1400 LF -> CR LF bug on parallel
+                                           port */
+#define TX_HANGOVER             (TX_SENDSPACES | TX_SENDLF | TX_SENDNULL)
+#define TX_DTRFLOW		0x0200	/* DTR tx flow control */
+#define	TX_DTRFLOWED		0x0400	/* DTR is low - don't allow more data
+					   into the FIFO */
+#define	TX_DATAINFIFO		0x0800	/* There is data in the FIFO */
+#define	TX_BUSY			0x1000	/* Data in FIFO, shift or holding regs */
+
+#define RX_SPARE	        0x0001   /* SPARE */
+#define RXINTR_ENABLED          0x0002   /* Rx interrupt enabled */
+#define RX_ICRNL                0x0008   /* ICRNL mode */
+#define RX_INLCR                0x0010   /* INLCR mode */
+#define RX_IGNCR                0x0020   /* IGNCR mode */
+#define RX_CTSFLOW              0x0040   /* CTSFLOW enabled */
+#define RX_IXOFF                0x0080   /* IXOFF enabled */
+#define RX_CTSFLOWED            0x0100   /* CTSFLOW and CTS dropped */
+#define RX_IXOFFED              0x0200   /* IXOFF and xoff sent */
+#define RX_BUFFERED		0x0400	 /* Try and pass on complete packets */
+
+#define PORT_ISOPEN             0x0001  /* Port open? */
+#define PORT_HUPCL              0x0002  /* Hangup on close? */
+#define PORT_MOPENPEND          0x0004  /* Modem open pending */
+#define PORT_ISPARALLEL         0x0008  /* Parallel port */
+#define PORT_BREAK              0x0010  /* Port on break */
+#define PORT_STATUSPEND		0x0020  /* Status packet pending */
+#define PORT_BREAKPEND          0x0040  /* Break packet pending */
+#define PORT_MODEMPEND          0x0080  /* Modem status packet pending */
+#define PORT_PARALLELBUG        0x0100  /* CD1400 LF -> CR LF bug on parallel
+                                           port */
+#define PORT_FULLMODEM          0x0200  /* Full modem signals */
+#define PORT_RJ45               0x0400  /* RJ45 connector - no RI signal */
+#define PORT_RESTRICTED         0x0600  /* Restricted connector - no RI / DTR */
+
+#define PORT_MODEMBITS          0x0600  /* Mask for modem fields */
+
+#define PORT_WCLOSE             0x0800  /* Waiting for close */
+#define	PORT_HANDSHAKEFIX	0x1000	/* Port has H/W flow control fix */
+#define	PORT_WASPCLOSED		0x2000	/* Port closed with PCLOSE */
+#define	DUMPMODE		0x4000	/* Dump RTA mem */
+#define	READ_REG		0x8000	/* Read CD1400 register */
+
+
+
+/**************************************************************************
+ * PHB Structure
+ * A  few words.
+ *
+ * Normally Packets are added to the end of the list and removed from
+ * the start. The pointer tx_add points to a SPACE to put a Packet.
+ * The pointer tx_remove points to the next Packet to remove
+ *************************************************************************/
+#ifndef INKERNEL
+#define src_unit     u2.s2.unit
+#define src_port     u2.s2.port
+#define dest_unit    u1.s1.unit
+#define dest_port    u1.s1.port
+#endif
+#ifdef HOST
+#define tx_start     u3.s1.tx_start_ptr_ptr
+#define tx_add       u3.s1.tx_add_ptr_ptr
+#define tx_end       u3.s1.tx_end_ptr_ptr
+#define tx_remove    u3.s1.tx_remove_ptr_ptr
+#define rx_start     u4.s1.rx_start_ptr_ptr
+#define rx_add       u4.s1.rx_add_ptr_ptr
+#define rx_end       u4.s1.rx_end_ptr_ptr
+#define rx_remove    u4.s1.rx_remove_ptr_ptr
+#endif
+typedef struct PHB PHB ;
+struct PHB {
+#ifdef RTA
+        ushort      port;
+#endif
+#ifdef INKERNEL
+        WORD      source;
+#else
+        union       
+        {
+            ushort source;              /* Complete source */
+            struct
+            {
+                unsigned char unit;     /* Source unit */
+                unsigned char port;     /* Source port */
+            } s2;
+        } u2;
+#endif
+        WORD      handshake ;
+        WORD      status ;
+        NUMBER       timeout ;           /* Maximum of 1.9 seconds */
+        WORD      link ;              /* Send down this link */
+#ifdef INKERNEL
+        WORD      destination;
+#else
+        union       
+        {
+            ushort destination;         /* Complete destination */
+            struct
+            {
+                unsigned char unit;     /* Destination unit */
+                unsigned char port;     /* Destination port */
+            } s1;
+        } u1;
+#endif
+#ifdef RTA
+        ushort      tx_pkts_added;
+        ushort      tx_pkts_removed;
+        Q_BUF_ptr   tx_q_start ;        /* Start of the Q list chain */
+        short       num_tx_q_bufs ;     /* Number of Q buffers in the chain */
+        PKT_ptr_ptr tx_add ;            /* Add a new Packet here */
+        Q_BUF_ptr   tx_add_qb;          /* Pointer to the add Q buf */
+        PKT_ptr_ptr tx_add_st_qbb ;     /* Pointer to start of the Q's buf */
+        PKT_ptr_ptr tx_add_end_qbb ;    /* Pointer to the end of the Q's buf */
+        PKT_ptr_ptr tx_remove ;         /* Remove a Packet here */
+        Q_BUF_ptr   tx_remove_qb ;      /* Pointer to the remove Q buf */
+        PKT_ptr_ptr tx_remove_st_qbb ;  /* Pointer to the start of the Q buf */
+        PKT_ptr_ptr tx_remove_end_qbb ; /* Pointer to the end of the Q buf */
+#endif
+#ifdef INKERNEL
+        PKT_ptr_ptr tx_start ;
+        PKT_ptr_ptr tx_end ;
+        PKT_ptr_ptr tx_add ;
+        PKT_ptr_ptr tx_remove ;
+#endif
+#ifdef HOST
+        union
+        {
+            struct
+            {
+                PKT_ptr_ptr tx_start_ptr_ptr;
+                PKT_ptr_ptr tx_end_ptr_ptr;
+                PKT_ptr_ptr tx_add_ptr_ptr;
+                PKT_ptr_ptr tx_remove_ptr_ptr;
+            } s1;
+            struct
+            {
+                ushort * tx_start_ptr;
+                ushort * tx_end_ptr;
+                ushort * tx_add_ptr;
+                ushort * tx_remove_ptr;
+            } s2;
+        } u3;
+#endif
+
+#ifdef  RTA
+        ushort      rx_pkts_added;
+        ushort      rx_pkts_removed;
+        Q_BUF_ptr   rx_q_start ;        /* Start of the Q list chain */
+        short       num_rx_q_bufs ;     /* Number of Q buffers in the chain */
+        PKT_ptr_ptr rx_add ;            /* Add a new Packet here */
+        Q_BUF_ptr   rx_add_qb ;         /* Pointer to the add Q buf */
+        PKT_ptr_ptr rx_add_st_qbb ;     /* Pointer to start of the Q's buf */
+        PKT_ptr_ptr rx_add_end_qbb ;    /* Pointer to the end of the Q's buf */
+        PKT_ptr_ptr rx_remove ;         /* Remove a Packet here */
+        Q_BUF_ptr   rx_remove_qb ;      /* Pointer to the remove Q buf */
+        PKT_ptr_ptr rx_remove_st_qbb ;  /* Pointer to the start of the Q buf */
+        PKT_ptr_ptr rx_remove_end_qbb ; /* Pointer to the end of the Q buf */
+#endif
+#ifdef INKERNEL
+        PKT_ptr_ptr rx_start ;
+        PKT_ptr_ptr rx_end ;
+        PKT_ptr_ptr rx_add ;
+        PKT_ptr_ptr rx_remove ;
+#endif
+#ifdef HOST
+        union
+        {
+            struct
+            {
+                PKT_ptr_ptr rx_start_ptr_ptr;
+                PKT_ptr_ptr rx_end_ptr_ptr;
+                PKT_ptr_ptr rx_add_ptr_ptr;
+                PKT_ptr_ptr rx_remove_ptr_ptr;
+            } s1;
+            struct
+            {
+                ushort * rx_start_ptr;
+                ushort * rx_end_ptr;
+                ushort * rx_add_ptr;
+                ushort * rx_remove_ptr;
+            } s2;
+        } u4;
+#endif
+
+#ifdef RTA                              /* some fields for the remotes */
+        ushort     flush_count;		/* Count of write flushes */
+        ushort     txmode;		/* Modes for tx */
+        ushort     rxmode;		/* Modes for rx */
+        ushort     portmode;		/* Generic modes */
+        ushort     column;		/* TAB3 column count */
+        ushort     tx_subscript;	/* (TX) Subscript into data field */
+        ushort     rx_subscript;	/* (RX) Subscript into data field */
+        PKT_ptr    rx_incomplete;	/* Hold an incomplete packet here */
+        ushort     modem_bits;		/* Modem bits to mask */
+	ushort	   lastModem;		/* Modem control lines. */
+        ushort     addr;		/* Address for sub commands */
+        ushort     MonitorTstate;	/* TRUE if monitoring tstop */
+#endif
+
+        } ;
+
+#endif
+
+/*********** end of file ***********/
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/pkt.h linux.15p9/drivers/char/rio/pkt.h
--- linux.vanilla/drivers/char/rio/pkt.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/pkt.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,120 @@
+/****************************************************************************
+ *******                                                              *******
+ *******            P A C K E T   H E A D E R   F I L E
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra / Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _pkt_h
+#define _pkt_h 1
+
+
+#ifdef SCCS_LABELS
+#ifndef lint
+/* static char *_rio_pkt_h_sccs = "@(#)pkt.h	1.8"; */
+#endif
+#endif
+
+#define MAX_TTL         0xf
+#define PKT_CMD_BIT     ((ushort) 0x080)
+#define PKT_CMD_DATA    ((ushort) 0x080)
+
+#define PKT_ACK         ((ushort) 0x040)
+
+#define PKT_TGL         ((ushort) 0x020)
+
+#define PKT_LEN_MASK    ((ushort) 0x07f)
+
+#define DATA_WNDW       ((ushort) 0x10)
+#define PKT_TTL_MASK    ((ushort) 0x0f)
+
+#define PKT_MAX_DATA_LEN   72
+
+#define PKT_LENGTH         sizeof(struct PKT)
+#define SYNC_PKT_LENGTH    (PKT_LENGTH + 4)
+
+#define CONTROL_PKT_LEN_MASK PKT_LEN_MASK
+#define CONTROL_PKT_CMD_BIT  PKT_CMD_BIT
+#define CONTROL_PKT_ACK (PKT_ACK << 8)
+#define CONTROL_PKT_TGL (PKT_TGL << 8)
+#define CONTROL_PKT_TTL_MASK (PKT_TTL_MASK << 8)
+#define CONTROL_DATA_WNDW  (DATA_WNDW << 8)
+
+struct PKT    {
+#ifdef INKERNEL
+                   BYTE    dest_unit ;    /* Destination Unit Id */
+                   BYTE    dest_port ;    /* Destination POrt */
+                   BYTE    src_unit ;     /* Source Unit Id */
+                   BYTE    src_port ;     /* Source POrt */
+#else
+                   union       
+                   {
+                       ushort destination;         /* Complete destination */
+                       struct
+                       {
+                           unsigned char unit;     /* Destination unit */
+                           unsigned char port;     /* Destination port */
+                       } s1;
+                   } u1;
+                   union       
+                   {
+                       ushort source;              /* Complete source */
+                       struct
+                       {
+                           unsigned char unit;     /* Source unit */
+                           unsigned char port;     /* Source port */
+                       } s2;
+                   } u2;
+#endif
+#ifdef INKERNEL
+                   BYTE len ;
+                   BYTE control;
+#else
+                   union
+                   {
+                        ushort      control;
+                        struct
+                        {
+                            unsigned char len;
+                            unsigned char control;
+                        } s3;
+                    } u3;
+#endif
+                   BYTE    data[PKT_MAX_DATA_LEN] ;     
+                                                   /* Actual data :-) */
+                   WORD  csum ;                  /* C-SUM */
+               } ;
+#endif
+
+/*********** end of file ***********/
+
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/poll.h linux.15p9/drivers/char/rio/poll.h
--- linux.vanilla/drivers/char/rio/poll.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/poll.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,76 @@
+/****************************************************************************
+ *******                                                              *******
+ *******                      P O L L
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra / Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _poll_h
+#define _poll_h
+
+#ifndef lint
+#ifdef SCCS_LABELS
+static char *_rio_poll_h_sccs = "@(#)poll.h	1.2" ;
+#endif
+#endif
+
+
+#ifdef HOST
+#define POLL_STACK            100
+#endif
+#ifdef RTA
+#define POLL_STACK            200
+#endif
+
+#define POLL_PERIOD           (int) SECOND
+
+/* The various poll commands */
+#define POLL_POLL             0            /* We are connected and happy.. */
+#define POLL_INTRO            1            /* Introduction packet */
+#define POLL_TOPOLOGY         2            /* Topology update */
+#define POLL_ASSIGN           3            /* ID assign */
+#define POLL_FOAD             4            /* F*** Off And Die */
+#define POLL_LMD	      5		   /* Let Me Die */
+#define POLL_DYB	      6		   /* Die You Ba***** */
+
+/* The way data fields are split up for POLL packets */
+#define POLL_HOST_SERIAL      2            /* Host who booted me */
+#define POLL_MY_SERIAL        6            /* My serial number */
+#define POLL_YOUR_ID          1            /* Your ID number */
+#define POLL_TOPOLOGY_FIELDS  2            /* Topology maps */
+
+#endif
+
+/*********** end of file ***********/
+
+
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/port.h linux.15p9/drivers/char/rio/port.h
--- linux.vanilla/drivers/char/rio/port.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/port.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,245 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: port.h
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 11:34:12
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)port.h	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef	__rio_port_h__
+#define	__rio_port_h__
+
+#ifdef SCCS_LABELS
+static char *_port_h_sccs_ = "@(#)port.h	1.3";
+#endif
+
+
+#undef VPIX
+
+
+/*
+** the port data structure - one per port in the system
+*/
+
+#ifdef STATS
+struct RIOStats
+{
+	/*
+	** interrupt statistics
+	*/
+	uint	BreakIntCnt;
+	uint	ModemOffCnt;
+	uint	ModemOnCnt;
+	uint	RxIntCnt;
+	uint	TxIntCnt;
+	/*
+	** throughput statistics
+	*/
+	uint	RxCharCnt;
+	uint	RxPktCnt;
+	uint	RxSaveCnt;
+	uint	TxCharCnt;
+	uint	TxPktCnt;
+	/*
+	** driver entry statistics
+	*/
+	uint	CloseCnt;
+	uint	IoctlCnt;
+	uint	OpenCnt;
+	uint	ReadCnt;
+	uint	WriteCnt;
+	/*
+	** proc statistics
+	*/
+	uint	BlockCnt;
+	uint	OutputCnt;
+	uint	ResumeCnt;
+	uint	RflushCnt;
+	uint	SuspendCnt;
+	uint	TbreakCnt;
+	uint	TimeoutCnt;
+	uint	UnblockCnt;
+	uint	WflushCnt;
+	uint	WFBodgeCnt;
+};
+#endif
+
+/*
+**	Port data structure
+*/
+struct	Port
+{
+  struct gs_port gs; 
+  int				PortNum;	/* RIO port no., 0-511 */
+  struct Host	*HostP;
+  volatile caddr_t		Caddr;
+  ushort			HostPort;  /* Port number on host card */
+  uchar			RupNum;	/* Number of RUP for port */
+  uchar			ID2;	/* Second ID of RTA for port */
+  ulong			State;	/* FLAGS for open & xopen */
+#define	RIO_LOPEN	0x00001		/* Local open */
+#define	RIO_MOPEN	0x00002		/* Modem open */
+#define	RIO_WOPEN	0x00004		/* Waiting for open */
+#define	RIO_CLOSING	0x00008		/* The port is being close */
+#define	RIO_XPBUSY	0x00010		/* Transparent printer busy */
+#define	RIO_BREAKING	0x00020		/* Break in progress */
+#define	RIO_DIRECT	0x00040		/* Doing Direct output */
+#define	RIO_EXCLUSIVE	0x00080		/* Stream open for exclusive use */
+#define	RIO_NDELAY	0x00100		/* Stream is open FNDELAY */
+#define	RIO_CARR_ON	0x00200		/* Stream has carrier present */
+#define	RIO_XPWANTR	0x00400		/* Stream wanted by Xprint */
+#define	RIO_RBLK	0x00800		/* Stream is read-blocked */
+#define	RIO_BUSY	0x01000		/* Stream is BUSY for write */
+#define	RIO_TIMEOUT	0x02000		/* Stream timeout in progress */
+#define	RIO_TXSTOP	0x04000		/* Stream output is stopped */
+#define	RIO_WAITFLUSH	0x08000		/* Stream waiting for flush */
+#define	RIO_DYNOROD	0x10000		/* Drain failed */
+#define	RIO_DELETED	0x20000		/* RTA has been deleted */
+#define RIO_ISSCANCODE	0x40000		/* This line is in scancode mode */
+#define	RIO_USING_EUC	0x100000	/* Using extended Unix chars */
+#define	RIO_CAN_COOK	0x200000	/* This line can do cooking */
+#define RIO_TRIAD_MODE  0x400000        /* Enable TRIAD special ops. */
+#define RIO_TRIAD_BLOCK 0x800000        /* Next read will block */
+#define RIO_TRIAD_FUNC  0x1000000       /* Seen a function key coming in */
+#define RIO_THROTTLE_RX 0x2000000       /* RX needs to be throttled. */
+
+    ulong			Config;	/* FLAGS for NOREAD.... */
+#define	RIO_NOREAD	0x0001		/* Are not allowed to read port */
+#define	RIO_NOWRITE	0x0002		/* Are not allowed to write port */
+#define	RIO_NOXPRINT	0x0004		/* Are not allowed to xprint port */
+#define	RIO_NOMASK	0x0007		/* All not allowed things */
+#define RIO_IXANY	0x0008          /* Port is allowed ixany */
+#define	RIO_MODEM	0x0010		/* Stream is a modem device */
+#define	RIO_IXON	0x0020		/* Port is allowed ixon */
+#define RIO_WAITDRAIN	0x0040		/* Wait for port to completely drain */
+#define RIO_MAP_50_TO_50	0x0080	/* Map 50 baud to 50 baud */
+#define RIO_MAP_110_TO_110	0x0100	/* Map 110 baud to 110 baud */
+
+/*
+** 15.10.1998 ARG - ESIL 0761 prt fix
+** As LynxOS does not appear to support Hardware Flow Control .....
+** Define our own flow control flags in 'Config'.
+*/
+#define RIO_CTSFLOW	0x0200		/* RIO's own CTSFLOW flag */
+#define RIO_RTSFLOW	0x0400		/* RIO's own RTSFLOW flag */
+
+
+    struct PHB			*PhbP;	  /* pointer to PHB for port */
+    WORD                        *TxAdd;   /* Add packets here */
+    WORD                        *TxStart; /* Start of add array */
+    WORD                        *TxEnd;         /* End of add array */
+    WORD                        *RxRemove;      /* Remove packets here */
+    WORD                        *RxStart;       /* Start of remove array */
+    WORD                        *RxEnd;         /* End of remove array */
+    uint			RtaUniqueNum;	/* Unique number of RTA */
+    ushort			PortState;	/* status of port */
+    ushort			ModemState;	/* status of modem lines */
+    ulong			ModemLines;	/* Modem bits sent to RTA */
+    uchar			CookMode;	/* who expands CR/LF? */
+    uchar			ParamSem;	/* Prevent write during param */
+    uchar			Mapped;		/* if port mapped onto host */
+    uchar			SecondBlock;	/* if port belongs to 2nd block
+						   of 16 port RTA */
+    uchar			InUse;		/* how many pre-emptive cmds */
+    uchar			Lock;		/* if params locked */
+    uchar			Store;	/* if params stored across closes */
+    uchar			FirstOpen; /* TRUE if first time port opened */
+    uchar			FlushCmdBodge;	/* if doing a (non)flush */
+    uchar			MagicFlags;	/* require intr processing */
+#define	MAGIC_FLUSH	0x01	/* mirror of WflushFlag */
+#define	MAGIC_REBOOT	0x02	/* RTA re-booted, re-open ports */
+#define	MORE_OUTPUT_EYGOR 0x04	/* riotproc failed to empty clists */
+    uchar			WflushFlag;	/* 1 How many WFLUSHs active */
+/*
+** Transparent print stuff
+*/
+    struct Xprint
+    {
+#ifndef MAX_XP_CTRL_LEN
+#define MAX_XP_CTRL_LEN		16		/* ALSO IN DAEMON.H */
+#endif
+	uint			XpCps;
+	char			XpOn[MAX_XP_CTRL_LEN];
+	char			XpOff[MAX_XP_CTRL_LEN];
+	ushort			XpLen;		/* strlen(XpOn)+strlen(XpOff) */
+	uchar			XpActive;
+	uchar			XpLastTickOk;	/* TRUE if we can process */
+#define	XP_OPEN		00001
+#define	XP_RUNABLE	00002
+	struct ttystatics 		*XttyP;
+    } Xprint;
+#ifdef VPIX
+    v86_t			*StashP;
+    uint			IntMask;
+    struct termss 		VpixSs;
+    uchar			ModemStatusReg;	/* Modem status register */
+#endif
+    uchar			RxDataStart;
+    uchar			Cor2Copy;	/* copy of COR2 */
+    char			*Name;		/* points to the Rta's name */
+#ifdef STATS
+    struct RIOStats 		Stat;		/* ports statistics */
+#endif
+    char			*TxRingBuffer;
+    ushort			TxBufferIn;	/* New data arrives here */
+    ushort			TxBufferOut;	/* Intr removes data here */
+    ushort			OldTxBufferOut;	/* Indicates if draining */
+    int				TimeoutId;	/* Timeout ID */
+    uint			Debug;
+    uchar			WaitUntilBooted; /* True if open should block */
+    uint			statsGather;	/* True if gathering stats */
+    ulong			txchars;	/* Chars transmitted */
+    ulong			rxchars;	/* Chars received */
+    ulong			opens;		/* port open count */
+    ulong			closes;		/* port close count */
+    ulong			ioctls;		/* ioctl count */
+    uchar			LastRxTgl;	/* Last state of rx toggle bit */
+  spinlock_t				portSem;	/* Lock using this sem */
+	int				MonitorTstate;	/* Monitoring ? */
+	int				timeout_id;	/* For calling 100 ms delays */
+	int				timeout_sem;/* For calling 100 ms delays */
+	int				firstOpen;	/* First time open ? */
+	char *			p;			/* save the global struc here .. */
+};
+
+struct ModuleInfo
+{
+	char	*Name;
+	uint	Flags[4];	/* one per port on a module */
+};
+#endif
+
+/*
+** This struct is required because trying to grab an entire Port structure
+** runs into problems with differing struct sizes between driver and config.
+*/
+struct PortParams {
+	uint	Port;
+	ulong	Config;
+	ulong	State;
+	struct ttystatics	*TtyP;
+};
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/proto.h linux.15p9/drivers/char/rio/proto.h
--- linux.vanilla/drivers/char/rio/proto.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/proto.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,244 @@
+/*
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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	_prototypes_h
+#define _prototypes_h
+
+
+/*
+** boot.c
+*/
+void init_boot( char *p, short stage);
+
+/*
+** disconct.c
+*/
+void kill_boot ( LPB *link );
+void disconnected( LPB *link );
+short boot_3( LPB *link, PKT *pkt );
+short send_3_pkt( LPB *link, PKT *pkt);
+
+/*
+** error.c
+*/
+void du_error(void);
+
+/*
+** formpkt.c
+*/
+ushort sum_it( PKT *pkt ) ;
+void form_rup_pkt( RUP *form_rup, PKT *pkt );
+void form_poll_pkt ( int type, LPB *link, int node );
+void form_route_pkt ( int type, PKT *pkt, LPB *link );
+
+/*
+** idle.c
+*/
+void idle( Process *idle_p );
+
+/*
+** init.c
+*/
+void general_init(void);
+void mem_halt( int error);
+
+/*
+** linkinit.c
+*/
+void initlink( u_short number, LPB *link);
+void runlink( LPB *link);
+
+/*
+** list.c
+*/
+PKT *get_free_start(void);
+void put_free_start( PKT *pkt);
+
+#ifdef HOST
+int can_remove_transmit ( PKT **pkt, PKT *pointer );
+#endif
+
+#ifdef RTA
+int spl7 ( void );
+int spl0 ( void );
+Q_BUF *get_free_q( void );
+PKT *get_free_end(void);
+int add_end( PKT *pkt, PHB *phb, int type);
+unsigned short free_packets( PHB *phb, int type);
+int can_remove_start( PKT **pkt, PHB *phb, int type);
+int can_add_start( PHB *phb, int type);
+int can_add_end( PHB *phb, int type);
+void put_free_end( PKT *pkt);
+int remove_start( PKT **pkt, PHB *phb, int type);
+#endif
+
+/*
+** Lrt.c
+*/
+void lrt( Process *lrt_p, LPB *link );
+
+#ifdef RTA
+void set_led_red ( LPB *link );
+#endif
+
+/*
+** ltt.c
+*/
+void ltt( Process *ltt_p, LPB *link, PHB *phb_ptr[] );
+void send_poll ( LPB *link );
+void request_id ( LPB *link );
+void send_topology_update ( LPB *link );
+void send_topology ( LPB *link );
+void supply_id ( LPB *link );
+
+#ifdef RTA
+void redirect_queue ( LPB *link, ushort flush );
+int obtain_rup ( int rup_number, PKT **pkt_address, LPB *link );
+#endif
+
+#ifdef TESTING_PERF
+int consume_cpu( void );
+#endif
+
+/*
+** lttwake.c
+*/
+#ifdef HOST
+void ltt_wakeup( Process *ltt_wakeup_p );
+#endif
+
+/*
+** mapgen.c
+*/
+void generate_id_map( short mapping, ROUTE_STR route[] );
+void gen_map( int mapping, int looking_at, int come_from, ROUTE_STR route[], int link, int *ttl );
+void adjust_ttl( int mapping, int looking_at, int come_from, ROUTE_STR route[], int link, int *ttl);
+void init_sys_map(void);
+
+/*
+** mmu.c
+*/
+char *rio_malloc( unsigned int amount);
+char *rio_calloc( unsigned int num, unsigned int size);
+ERROR rio_mmu_init( uint total_mem );
+
+/*
+** partn.c
+*/
+void partition_tx( struct PHB *phb, u_short tx_size, u_short rx_size, u_short rx_limit);
+
+/*
+** poll.c
+*/
+void tx_poll( Process *tx_poll_p);
+
+/*
+** process.c
+*/
+int  get_proc_space( Process **pd, int **pws, int wssize);
+
+/*
+** readrom.c
+*/
+void read_serial_number(char *buf);
+
+/*
+** rio.c
+*/
+int main( void );
+
+/*
+** route.c
+*/
+void route_update ( PKT *pkt, LPB *link);
+
+/*
+** rtainit.c
+*/
+#if defined(RTA)
+void rta_init(ushort RtaType);
+#endif /* defined(RTA) */
+
+/*
+** rupboot.c
+*/
+void rup_boot( PKT *pkt, RUP *this_rup, LPB *link);
+
+#ifdef RTA
+void kill_your_neighbour( int link_to_kill );
+#endif
+
+/*
+** rupcmd.c
+*/
+void rup_command( PKT *pkt, struct RUP *this_rup, LPB *link);
+
+/*
+** ruperr.c
+*/
+void rup_error( PKT *pkt, RUP *this_rup, LPB *link );
+void illegal_cmd( PKT *src_pkt );
+
+/*
+** ruppoll.c
+*/
+void rup_poll( PKT *pkt, RUP *this_rup, LPB *link );
+
+/*
+** ruppower.c
+*/
+void rup_power( PKT *pkt, RUP *this_rup, LPB *link );
+
+/*
+** ruprm.c
+*/
+void rup_route_map( PKT *pkt, RUP *this_rup, LPB *link);
+
+/*
+** rupstat.c
+*/
+void rup_status( PKT *pkt, RUP *this_rup, LPB *link);
+
+/*
+** rupsync.c
+*/
+void rup_sync( PKT *pkt);
+
+/*
+** rxpkt.c
+*/
+ERROR  rx_pkt( PKT_ptr_ptr pkt_address, LPB *link);
+
+/*
+** sendsts.c
+*/
+void send_status( PKT *requesting_pkt, RUP *this_rup);
+
+/*
+** serial.c
+*/
+void assign_serial ( char *ser_in, char *ser_out);
+int cmp_serial ( char *ser_1, char *ser_2);
+
+/*
+** txpkt.c
+*/
+ERROR  tx_pkt( PKT *pkt, LPB *link);
+short send_sync( LPB *link);
+
+#endif	/* _prototypes_h */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/protsts.h linux.15p9/drivers/char/rio/protsts.h
--- linux.vanilla/drivers/char/rio/protsts.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/protsts.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,119 @@
+/****************************************************************************
+ *******                                                              *******
+ *******      P R O T O C O L    S T A T U S   S T R U C T U R E      *******
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra / Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _protsts_h
+#define _protsts_h 1
+
+
+#ifdef SCCS_LABELS
+#ifndef lint
+/* static char *_rio_protsts_h_sccs = "@(#)protsts.h	1.4"; */
+#endif
+#endif
+
+/*************************************************
+ * ACK bit. Last Packet received OK. Set by
+ * rxpkt to indicate that the Packet has been
+ * received OK and that the LTT must set the ACK
+ * bit in the next outward bound Packet
+ * and re-set by LTT's after xmit.
+ *
+ * Gets shoved into rx_status
+ ************************************************/
+#define PHB_RX_LAST_PKT_ACKED    ((ushort) 0x080)
+
+/*******************************************************
+ * The Rx TOGGLE bit.
+ * Stuffed into rx_status by RXPKT
+ ******************************************************/
+#define PHB_RX_DATA_WNDW         ((ushort) 0x040)
+
+/*******************************************************
+ * The Rx TOGGLE bit. Matches the setting in PKT.H
+ * Stuffed into rx_status
+ ******************************************************/
+#define PHB_RX_TGL               ((ushort) 0x2000)
+
+
+/*************************************************
+ * This bit is set by the LRT to indicate that
+ * an ACK (packet) must be returned.
+ *
+ * Gets shoved into tx_status
+ ************************************************/
+#define PHB_TX_SEND_PKT_ACK      ((ushort) 0x08)
+
+/*************************************************
+ * Set by LTT to indicate that an ACK is required
+ *************************************************/
+#define PHB_TX_ACK_RQRD         ((ushort) 0x01)
+
+
+/*******************************************************
+ * The Tx TOGGLE bit.
+ * Stuffed into tx_status by RXPKT from the PKT WndW
+ * field. Looked by the LTT when the NEXT Packet
+ * is going to be sent.
+ ******************************************************/
+#define PHB_TX_DATA_WNDW         ((ushort) 0x04)
+
+
+/*******************************************************
+ * The Tx TOGGLE bit. Matches the setting in PKT.H
+ * Stuffed into tx_status
+ ******************************************************/
+#define PHB_TX_TGL               ((ushort) 0x02)
+
+/*******************************************************
+ * Request intr bit. Set when the queue has gone quiet
+ * and the PHB has requested an interrupt.
+ ******************************************************/
+#define PHB_TX_INTR             ((ushort) 0x100)
+
+/*******************************************************
+ * SET if the PHB cannot send any more data down the
+ * Link
+ ******************************************************/
+#define PHB_TX_HANDSHAKE         ((ushort) 0x010)
+
+
+#define RUP_SEND_WNDW		 ((ushort) 0x08) ;
+
+#endif
+
+/*********** end of file ***********/
+
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/qbuf.h linux.15p9/drivers/char/rio/qbuf.h
--- linux.vanilla/drivers/char/rio/qbuf.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/qbuf.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,67 @@
+
+/****************************************************************************
+ *******                                                              *******
+ *******       Q U E U E    B U F F E R   S T R U C T U R E S
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra / Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _qbuf_h
+#define _qbuf_h 1
+
+#ifndef lint
+#ifdef SCCS_LABELS
+static char *_rio_qbuf_h_sccs = "@(#)qbuf.h	1.1" ;
+#endif
+#endif
+
+
+
+#ifdef HOST
+#define PKTS_PER_BUFFER    1
+#else
+#define PKTS_PER_BUFFER    (220 / PKT_LENGTH)
+#endif
+
+typedef struct Q_BUF Q_BUF ;
+struct Q_BUF  {
+                  Q_BUF_ptr next ;
+                  Q_BUF_ptr prev ;
+                  PKT_ptr buf[PKTS_PER_BUFFER] ;
+              } ;
+
+
+#endif
+
+
+/*********** end of file ***********/
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/rio.h linux.15p9/drivers/char/rio/rio.h
--- linux.vanilla/drivers/char/rio/rio.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/rio.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,304 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 1998 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: rio.h
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 11:34:13
+**	Retrieved	: 11/6/98 11:34:22
+**
+**  ident @(#)rio.h	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef	__rio_rio_h__
+#define	__rio_rio_h__
+
+#ifdef SCCS_LABELS
+static char *_rio_h_sccs_ = "@(#)rio.h	1.3";
+#endif
+
+/*
+** 30.09.1998 ARG -
+** Introduced driver version and host card type strings
+*/
+#define RIO_DRV_STR "Specialix RIO Driver"
+#define RIO_AT_HOST_STR "ISA"
+#define RIO_PCI_HOST_STR "PCI"
+
+
+/*
+** rio_info_store() commands (arbitary values) :
+*/
+#define RIO_INFO_PUT	0xA4B3C2D1
+#define RIO_INFO_GET	0xF1E2D3C4
+
+
+/*
+** anything that I couldn't cram in somewhere else
+*/
+/*
+#ifndef RIODEBUG
+#define debug
+#else
+#define debug rioprint
+#endif
+*/
+
+
+/*
+**	Maximum numbers of things
+*/
+#define	RIO_SLOTS	4	/* number of configuration slots */
+#define	RIO_HOSTS	4	/* number of hosts that can be found */
+#define	PORTS_PER_HOST	128	/* number of ports per host */
+#define	LINKS_PER_UNIT	4	/* number of links from a host */
+#define	RIO_PORTS	(PORTS_PER_HOST * RIO_HOSTS) /* max. no. of ports */
+#define	RTAS_PER_HOST	(MAX_RUP) /* number of RTAs per host */
+#define	PORTS_PER_RTA	(PORTS_PER_HOST/RTAS_PER_HOST)	/* ports on a rta */
+#define	PORTS_PER_MODULE 4	/* number of ports on a plug-in module */
+				/* number of modules on an RTA */
+#define	MODULES_PER_RTA	 (PORTS_PER_RTA/PORTS_PER_MODULE)
+#define MAX_PRODUCT	16	/* numbr of different product codes */
+#define MAX_MODULE_TYPES 16	/* number of different types of module */
+
+#define RIO_CONTROL_DEV	128	/* minor number of host/control device */
+#define RIO_INVALID_MAJOR 0	/* test first host card's major no for validity */
+
+/*
+** number of RTAs that can be bound to a master
+*/
+#define MAX_RTA_BINDINGS (MAX_RUP * RIO_HOSTS)
+
+/*
+**	Unit types
+*/
+#define PC_RTA16	0x90000000
+#define PC_RTA8		0xe0000000
+#define TYPE_HOST	0
+#define TYPE_RTA8	1
+#define TYPE_RTA16	2
+
+/*
+**	Flag values returned by functions
+*/
+#define	RIO_FAIL	-1
+#define	RIO_SUCCESS	0
+#define	COPYFAIL	-1	/* copy[in|out] failed */
+
+/*
+** SysPort value for something that hasn't any ports
+*/
+#define	NO_PORT	0xFFFFFFFF
+
+/*
+** Unit ID Of all hosts
+*/
+#define	HOST_ID	0
+
+/*
+** Break bytes into nybles
+*/
+#define	LONYBLE(X)	((X) & 0xF)
+#define	HINYBLE(X)	(((X)>>4) & 0xF)
+
+/*
+** Flag values passed into some functions
+*/
+#define	DONT_SLEEP	0
+#define	OK_TO_SLEEP	1
+
+#define	DONT_PRINT	1
+#define	DO_PRINT	0
+
+#define PRINT_TO_LOG_CONS	0
+#define PRINT_TO_CONS	1
+#define PRINT_TO_LOG	2
+
+/*
+** Timeout has trouble with times of less than 3 ticks...
+*/
+#define	MIN_TIMEOUT	3
+
+/*
+**	Generally useful constants
+*/
+#define	HALF_A_SECOND		((HZ)>>1)
+#define	A_SECOND		(HZ)
+#define	HUNDRED_HZ		((HZ/100)?(HZ/100):1)
+#define	FIFTY_HZ		((HZ/50)?(HZ/50):1)
+#define	TWENTY_HZ		((HZ/20)?(HZ/20):1)
+#define	TEN_HZ			((HZ/10)?(HZ/10):1)
+#define	FIVE_HZ			((HZ/5)?(HZ/5):1)
+#define	HUNDRED_MS		TEN_HZ
+#define	FIFTY_MS		TWENTY_HZ
+#define	TWENTY_MS		FIFTY_HZ
+#define	TEN_MS			HUNDRED_HZ
+#define	TWO_SECONDS		((A_SECOND)*2)
+#define	FIVE_SECONDS		((A_SECOND)*5)
+#define	TEN_SECONDS		((A_SECOND)*10)
+#define	FIFTEEN_SECONDS		((A_SECOND)*15)
+#define	TWENTY_SECONDS		((A_SECOND)*20)
+#define	HALF_A_MINUTE		(A_MINUTE>>1)
+#define	A_MINUTE		(A_SECOND*60)
+#define	FIVE_MINUTES		(A_MINUTE*5)
+#define	QUARTER_HOUR		(A_MINUTE*15)
+#define	HALF_HOUR		(A_MINUTE*30)
+#define	HOUR			(A_MINUTE*60)
+
+#define	SIXTEEN_MEG		0x1000000
+#define	ONE_MEG			0x100000
+#define	SIXTY_FOUR_K		0x10000
+
+#define	RIO_AT_MEM_SIZE		SIXTY_FOUR_K
+#define	RIO_EISA_MEM_SIZE	SIXTY_FOUR_K
+#define	RIO_MCA_MEM_SIZE	SIXTY_FOUR_K
+
+#define	POLL_VECTOR		0x100
+
+#define	COOK_WELL		0
+#define	COOK_MEDIUM		1
+#define	COOK_RAW		2
+
+/*
+**	Pointer manipulation stuff
+**	RIO_PTR takes hostp->Caddr and the offset into the DP RAM area
+**	and produces a UNIX caddr_t (pointer) to the object
+**	RIO_OBJ takes hostp->Caddr and a UNIX pointer to an object and
+**	returns the offset into the DP RAM area.
+*/
+#define	RIO_PTR(C,O) (((caddr_t)(C))+(0xFFFF&(O)))
+#define	RIO_OFF(C,O) ((int)(O)-(int)(C))
+
+/*
+**	How to convert from various different device number formats:
+**	DEV is a dev number, as passed to open, close etc - NOT a minor
+**	number!
+**
+**	Note:	LynxOS only gives us 8 bits for the device minor number,
+**		so all this crap here to deal with 'modem' bits etc. is
+**		just a load of irrelevant old bunkum!
+**		This however does not stop us needing to define a value
+**		for RIO_MODEMOFFSET which is required by the 'riomkdev'
+**		utility in the New Config Utilities suite.
+*/
+/* 0-511: direct 512-1023: modem */
+#define	RIO_MODEMOFFSET		0x200	/* doesn't mean anything */
+#define	RIO_MODEM_MASK		0x1FF
+#define	RIO_MODEM_BIT		0x200
+#define	RIO_UNMODEM(DEV)	(minor(DEV) & RIO_MODEM_MASK)
+#define	RIO_ISMODEM(DEV)	(minor(DEV) & RIO_MODEM_BIT)
+#define RIO_PORT(DEV,FIRST_MAJ)	( (major(DEV) - FIRST_MAJ) * PORTS_PER_HOST) \
+					+ minor(DEV)
+
+/*
+**	Min and Max
+*/
+#ifndef min
+#define	min(A,B)	((A)<(B)?(A):(B))
+#endif
+#ifndef max
+#define	max(A,B)	((A)>(B)?(A):(B))
+#endif
+
+#define	splrio	spltty
+
+#define	RIO_IPL	5
+#define	RIO_PRI	(PZERO+10)
+#define RIO_CLOSE_PRI	PZERO-1	/* uninteruptible sleeps for close */
+
+typedef struct DbInf
+{
+	uint	Flag;
+	char	Name[8];
+} DbInf;
+
+#ifndef TRUE
+#define	TRUE (1==1)
+#endif
+#ifndef FALSE
+#define	FALSE	(!TRUE)
+#endif
+
+#define CSUM(pkt_ptr)  (((ushort *)(pkt_ptr))[0] + ((ushort *)(pkt_ptr))[1] + \
+			((ushort *)(pkt_ptr))[2] + ((ushort *)(pkt_ptr))[3] + \
+			((ushort *)(pkt_ptr))[4] + ((ushort *)(pkt_ptr))[5] + \
+			((ushort *)(pkt_ptr))[6] + ((ushort *)(pkt_ptr))[7] + \
+			((ushort *)(pkt_ptr))[8] + ((ushort *)(pkt_ptr))[9] )
+
+/*
+** This happy little macro copies SIZE bytes of data from FROM to TO
+** quite well. SIZE must be a constant.
+*/
+#define CCOPY( FROM, TO, SIZE ) { *(struct s { char data[SIZE]; } *)(TO) = *(struct s *)(FROM); }
+
+/*
+** increment a buffer pointer modulo the size of the buffer...
+*/
+#define	BUMP( P, I )	((P) = (((P)+(I)) & RIOBufferMask))
+
+#define INIT_PACKET( PK, PP ) \
+{ \
+	*((uint *)PK)    = PP->PacketInfo; \
+}
+
+#define	RIO_LINK_ENABLE	0x80FF /* FF is a hack, mainly for Mips, to        */
+			       /* prevent a really stupid race condition.  */
+
+#define	NOT_INITIALISED	0
+#define	INITIALISED	1
+
+#define	NOT_POLLING	0
+#define	POLLING		1
+
+#define	NOT_CHANGED	0
+#define	CHANGED		1
+
+#define	NOT_INUSE	0
+
+#define	DISCONNECT	0
+#define	CONNECT		1
+
+
+/*
+** Machine types - these must NOT overlap with product codes 0-15
+*/
+#define	RIO_MIPS_R3230	31
+#define	RIO_MIPS_R4030	32
+
+#define	RIO_IO_UNKNOWN	-2
+
+#undef	MODERN
+#define	ERROR( E )	do { u.u_error = E; return OPENFAIL } while ( 0 )
+
+/* Defines for MPX line discipline routines */
+
+#define DIST_LINESW_OPEN	0x01
+#define DIST_LINESW_CLOSE	0x02
+#define DIST_LINESW_READ	0x04
+#define DIST_LINESW_WRITE	0x08
+#define DIST_LINESW_IOCTL	0x10
+#define DIST_LINESW_INPUT	0x20
+#define DIST_LINESW_OUTPUT	0x40
+#define DIST_LINESW_MDMINT	0x80
+
+#endif /* __rio_h__ */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/rio_linux.c linux.15p9/drivers/char/rio/rio_linux.c
--- linux.vanilla/drivers/char/rio/rio_linux.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/rio_linux.c	Fri Jan 21 18:58:25 2000
@@ -0,0 +1,1555 @@
+
+/* rio_linux.c -- Linux driver for the Specialix RIO series cards. 
+ *
+ *
+ *   (C) 1999 R.E.Wolff@BitWizard.nl
+ *
+ * Specialix pays for the development and support of this driver.
+ * Please DO contact support@specialix.co.uk if you require
+ * support. But please read the documentation (rio.txt) first.
+ *
+ *
+ *
+ *      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.
+ *
+ * Revision history:
+ * $Log: rio.c,v $
+ * Revision 1.1  1999/07/11 10:13:54  wolff
+ * Initial revision
+ *
+ * */
+
+
+#define RCS_ID "$Id: rio.c,v 1.1 1999/07/11 10:13:54 wolff Exp wolff $"
+#define RCS_REV "$Revision: 1.1 $"
+
+
+#include <linux/module.h>
+#include <linux/config.h> 
+#include <linux/kdev_t.h>
+#include <asm/io.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/mm.h>
+#include <linux/serial.h>
+#include <linux/fcntl.h>
+#include <linux/major.h>
+#include <linux/delay.h>
+#include <linux/tqueue.h>
+#include <linux/version.h>
+#include <linux/pci.h>
+#include <linux/malloc.h>
+#include <linux/miscdevice.h>
+
+#include <linux/compatmac.h>
+#include <linux/generic_serial.h>
+
+
+#include "linux_compat.h"
+#include "typdef.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "top.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "riotypes.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "error.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+#include "control.h"
+#include "cirrus.h"
+#include "rioioctl.h"
+#include "param.h"
+#include "list.h"
+#include "sam.h"
+#include "protsts.h"
+#include "rioboard.h"
+
+
+#include "rio_linux.h"
+
+/* I don't think that this driver can handle more than 512 ports on
+one machine.  Specialix specifies max 4 boards in one machine. I don't
+know why. If you want to try anyway you'll have to increase the number
+of boards in rio.h.  You'll have to allocate more majors if you need
+more than 512 ports.... */
+
+
+/* ************************************************************** */
+/* * This section can be removed when 2.0 becomes outdated....  * */
+/* ************************************************************** */
+
+#if LINUX_VERSION_CODE < 0x020100    /* Less than 2.1.0 */
+#define TWO_ZERO
+#else
+#if LINUX_VERSION_CODE < 0x020209   /* less than 2.2.x */
+#warning "Please use a recent 2.2.x kernel. "
+#endif
+#endif
+
+
+#ifdef TWO_ZERO
+
+/* Here is the section that makes the 2.2 compatible driver source 
+   work for 2.0 too! We mostly try to adopt the "new thingies" from 2.2, 
+   and provide for compatibility stuff here if possible. */
+
+#include <linux/bios32.h>
+
+#define Get_user(a,b)                a = get_user(b)
+#define Put_user(a,b)                0,put_user(a,b)
+#define copy_to_user(a,b,c)          memcpy_tofs(a,b,c)
+
+static inline int copy_from_user(void *to,const void *from, int c) 
+{
+  memcpy_fromfs(to, from, c);
+  return 0;
+}
+
+#define pci_present                  pcibios_present
+#define pci_read_config_word         pcibios_read_config_word
+#define pci_read_config_dword        pcibios_read_config_dword
+
+static inline unsigned char get_irq (unsigned char bus, unsigned char fn)
+{
+  unsigned char t; 
+  pcibios_read_config_byte (bus, fn, PCI_INTERRUPT_LINE, &t);
+  return t;
+}
+
+static inline void *ioremap(unsigned long base, long length)
+{
+  if (base < 0x100000) return (void *)base;
+  return vremap (base, length);
+}
+
+#define my_iounmap(x, b)             (((long)x<0x100000)?0:vfree ((void*)x))
+
+#define capable(x)                   suser()
+
+#define queue_task                   queue_task_irq_off
+#define tty_flip_buffer_push(tty)    queue_task(&tty->flip.tqueue, &tq_timer)
+#define signal_pending(current)      (current->signal & ~current->blocked)
+#define schedule_timeout(to)         do {current->timeout = jiffies + (to);schedule ();} while (0)
+#define time_after(t1,t2)            (((long)t1-t2) > 0)
+
+
+#define test_and_set_bit(nr, addr)   set_bit(nr, addr)
+#define test_and_clear_bit(nr, addr) clear_bit(nr, addr)
+
+/* Not yet implemented on 2.0 */
+#define ASYNC_SPD_SHI  -1
+#define ASYNC_SPD_WARP -1
+
+
+/* Ugly hack: the driver_name doesn't exist in 2.0.x . So we define it
+   to the "name" field that does exist. As long as the assignments are
+   done in the right order, there is nothing to worry about. */
+#define driver_name           name 
+
+/* Should be in a header somewhere. They are in tty.h on 2.2 */
+#define TTY_HW_COOK_OUT       14 /* Flag to tell ntty what we can handle */
+#define TTY_HW_COOK_IN        15 /* in hardware - output and input       */
+
+/* The return type of a "close" routine. */
+#define INT                   void
+#define NO_ERROR              /* Nothing */
+
+#else
+
+/* The 2.2.x compatibility section. */
+#include <asm/uaccess.h>
+
+#define Get_user(a,b)         get_user(a,b)
+#define Put_user(a,b)         put_user(a,b)
+#define get_irq(pdev)         pdev->irq
+
+#define INT                   int
+#define NO_ERROR              0              
+
+#define my_iounmap(x,b)       (iounmap((char *)(b)))
+
+#endif
+
+/* ************************************************************** */
+/* *                End of compatibility section..              * */
+/* ************************************************************** */
+
+
+
+/* Why the hell am I defining these here? */
+#define RIO_TYPE_NORMAL 1
+#define RIO_TYPE_CALLOUT 2
+
+#ifndef RIO_NORMAL_MAJOR0
+/* This allows overriding on the compiler commandline, or in a "major.h" 
+   include or something like that */
+#define RIO_NORMAL_MAJOR0  154
+#define RIO_CALLOUT_MAJOR0 155
+#define RIO_NORMAL_MAJOR1  156
+#define RIO_CALLOUT_MAJOR1 157
+#endif
+
+#ifndef PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8
+#define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000
+#endif
+
+#ifndef RIO_WINDOW_LEN 
+#define RIO_WINDOW_LEN 0x10000
+#endif
+
+
+/* Configurable options: 
+   (Don't be too sure that it'll work if you toggle them) */
+
+/* Am I paranoid or not ? ;-) */
+#undef RIO_PARANOIA_CHECK
+
+
+/* 20 -> 2000 per second. The card should rate-limit interrupts at 1000
+   Hz, but it is user configurable. I don't recommend going above 1000
+   Hz. The interrupt ratelimit might trigger if the interrupt is
+   shared with a very active other device. 
+   undef this if you want to disable the check....
+*/
+#define IRQ_RATE_LIMIT 200
+
+#if 0
+/* Not implemented */
+/* 
+ * The following defines are mostly for testing purposes. But if you need
+ * some nice reporting in your syslog, you can define them also.
+ */
+#define RIO_REPORT_FIFO
+#define RIO_REPORT_OVERRUN
+#endif 
+
+
+/* These constants are derived from SCO Source */
+static struct Conf
+RIOConf =
+{
+  /* locator */         "RIO Config here",
+  /* startuptime */     HZ*2,           /* how long to wait for card to run */
+  /* slowcook */        0,              /* TRUE -> always use line disc. */
+  /* intrpolltime */    1,              /* The frequency of OUR polls */
+  /* breakinterval */   25,             /* x10 mS */
+  /* timer */           10,             /* mS */
+  /* RtaLoadBase */     0x7000,
+  /* HostLoadBase */    0x7C00,
+  /* XpHz */            5,              /* number of Xprint hits per second */
+  /* XpCps */           120,            /* Xprint characters per second */
+  /* XpOn */            "\033d#",       /* start Xprint for a wyse 60 */
+  /* XpOff */           "\024",         /* end Xprint for a wyse 60 */
+  /* MaxXpCps */        2000,           /* highest Xprint speed */
+  /* MinXpCps */        10,             /* slowest Xprint speed */
+  /* SpinCmds */        1,              /* non-zero for mega fast boots */
+  /* First Addr */      0x0A0000,       /* First address to look at */
+  /* Last Addr */       0xFF0000,       /* Last address looked at */
+  /* BufferSize */      1024,           /* Bytes per port of buffering */
+  /* LowWater */        256,            /* how much data left before wakeup */
+  /* LineLength */      80,             /* how wide is the console? */
+  /* CmdTimeout */      HZ,             /* how long a close command may take */
+};
+
+
+
+
+/* Function prototypes */
+
+static void rio_disable_tx_interrupts (void * ptr); 
+static void rio_enable_tx_interrupts (void * ptr); 
+static void rio_disable_rx_interrupts (void * ptr); 
+static void rio_enable_rx_interrupts (void * ptr); 
+static int  rio_get_CD (void * ptr); 
+static void rio_shutdown_port (void * ptr);
+static int  rio_set_real_termios (void  *ptr);
+static void rio_hungup (void  *ptr);
+static void rio_close (void  *ptr);
+static int rio_chars_in_buffer (void * ptr);
+static int rio_fw_ioctl (struct inode *inode, struct file *filp,
+		         unsigned int cmd, unsigned long arg);
+static int rio_fw_open(struct inode *inode, struct file *filp);
+static INT rio_fw_release(struct inode *inode, struct file *filp);
+static int rio_init_drivers(void);
+
+
+void my_hd (void *addr, int len);
+
+
+
+static struct tty_driver rio_driver, rio_callout_driver;
+static struct tty_driver rio_driver2, rio_callout_driver2;
+
+static struct tty_struct * rio_table[RIO_NPORTS] = { NULL, };
+static struct termios ** rio_termios;
+static struct termios ** rio_termios_locked;
+
+/* The name "p" is a bit non-descript. But that's what the rio-lynxos
+sources use all over the place. */
+struct rio_info *p;
+
+/* struct rio_board boards[RIO_HOSTS]; */
+struct rio_port *rio_ports;
+
+int rio_refcount;
+int rio_initialized = 0;
+int rio_nports = 0;
+int rio_debug = 0;
+
+
+/* You can have the driver poll your card. 
+    - Set rio_poll to 1 to poll every timer tick (10ms on Intel). 
+      This is used when the card cannot use an interrupt for some reason.
+*/
+int rio_poll = 1;
+
+
+/* These are the only open spaces in my computer. Yours may have more
+   or less.... */
+int rio_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000};
+
+#define NR_RIO_ADDRS (sizeof(rio_probe_addrs)/sizeof (int))
+
+
+/* Set the mask to all-ones. This alas, only supports 32 interrupts. 
+   Some architectures may need more. -- Changed to LONG to
+   support up to 64 bits on 64bit architectures. -- REW 20/06/99 */
+long rio_irqmask = -1;
+
+#ifndef TWO_ZERO
+#ifdef MODULE
+MODULE_PARM(rio_poll, "i");
+MODULE_PARM(rio_debug, "i");
+MODULE_PARM(rio_irqmask, "i");
+#endif
+#endif
+
+static struct real_driver rio_real_driver = {
+  rio_disable_tx_interrupts,
+  rio_enable_tx_interrupts,
+  rio_disable_rx_interrupts,
+  rio_enable_rx_interrupts,
+  rio_get_CD,
+  rio_shutdown_port, 
+  rio_set_real_termios, 
+  rio_chars_in_buffer,
+  rio_close,
+  rio_hungup,
+  NULL
+};
+
+
+/* 
+   This driver can spew a whole lot of debugging output at you. If you
+   need maximum performance, you should disable the DEBUG define. To
+   aid in debugging in the field, I'm leaving the compile-time debug
+   features enabled, and disable them "runtime". That allows me to
+   instruct people with problems to enable debugging without requiring
+   them to recompile... 
+*/
+#define DEBUG
+
+#ifdef DEBUG
+#define rio_dprintk(f, str...) if (rio_debug & f) printk (str)
+#else
+#define rio_dprintk(f, str...) /* nothing */
+#endif
+
+
+#define func_enter() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter " __FUNCTION__ "\n")
+#define func_exit()  rio_dprintk (RIO_DEBUG_FLOW, "rio: exit  " __FUNCTION__ "\n")
+
+#define func_enter2() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter " __FUNCTION__ \
+                                  "(port %d)\n", port->line)
+
+
+
+
+/* 
+ *  Firmware loader driver specific routines
+ *
+ */
+
+static struct file_operations rio_fw_fops = {
+	NULL,	/*	lseek	*/
+	NULL,	/*	read	*/
+	NULL,	/*	write	*/
+	NULL,	/*	readdir	*/
+	NULL,	/*	select	*/
+	rio_fw_ioctl,
+	NULL,	/*	mmap	*/
+	rio_fw_open,
+#ifndef TWO_ZERO
+	NULL,	/*	flush	*/
+#endif
+	rio_fw_release,
+	NULL,	/*	fsync	*/
+	NULL,	/*	fasync	*/
+	NULL,	/*	check_media_change	*/
+	NULL,	/*	revalidate	*/
+};
+
+struct miscdevice rio_fw_device = {
+	RIOCTL_MISC_MINOR, "rioctl", &rio_fw_fops
+};
+
+
+
+
+
+#ifdef RIO_PARANOIA_CHECK
+
+/* This doesn't work. Who's paranoid around here? Not me! */
+
+static inline int rio_paranoia_check(struct rio_port const * port,
+				    kdev_t device, const char *routine)
+{
+
+  static const char *badmagic =
+    KERN_ERR "rio: Warning: bad rio port magic number for device %s in %s\n";
+  static const char *badinfo =
+    KERN_ERR "rio: Warning: null rio port for device %s in %s\n";
+ 
+  if (!port) {
+    printk(badinfo, kdevname(device), routine);
+    return 1;
+  }
+  if (port->magic != RIO_MAGIC) {
+    printk(badmagic, kdevname(device), routine);
+    return 1;
+  }
+
+  return 0;
+}
+#else
+#define rio_paranoia_check(a,b,c) 0
+#endif
+
+
+#ifdef DEBUG
+void my_hd (void *ad, int len)
+{
+  int i, j, ch;
+  unsigned char *addr = ad;
+  
+  for (i=0;i<len;i+=16) {
+    printk ("%08x ", (int) addr+i);
+    for (j=0;j<16;j++) {
+      printk ("%02x %s", addr[j+i], (j==7)?" ":"");
+    }
+    for (j=0;j<16;j++) {
+      ch = addr[j+i];
+      printk ("%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch));
+    }
+    printk ("\n");
+  }
+}
+#else
+#define my_hd(ad,len) do{/* nothing*/ } while (0)
+#endif
+
+
+/* Delay a number of jiffies, allowing a signal to interrupt */ 
+int RIODelay (struct Port *PortP, int njiffies)
+{
+  func_enter ();
+
+  rio_dprintk (RIO_DEBUG_DELAY, "delaying %d jiffies\n", njiffies);  
+  current->state = TASK_INTERRUPTIBLE;
+  schedule_timeout(njiffies);
+  current->state = TASK_RUNNING;
+  func_exit();
+
+  if (signal_pending(current))
+    return RIO_FAIL;
+  else
+    return !RIO_FAIL;
+}
+
+
+/* Delay a number of jiffies, disallowing a signal to interrupt */ 
+int RIODelay_ni (struct Port *PortP, int njiffies)
+{
+  func_enter ();
+
+  rio_dprintk (RIO_DEBUG_DELAY, "delaying %d jiffies (ni)\n", njiffies);  
+  current->state = TASK_UNINTERRUPTIBLE;
+  schedule_timeout(njiffies);
+  current->state = TASK_RUNNING;
+  func_exit();
+  return !RIO_FAIL;
+}
+
+
+int rio_minor (kdev_t device)
+{
+  return MINOR (device) + 
+    256 * ((MAJOR (device) == RIO_NORMAL_MAJOR1) ||
+	   (MAJOR (device) == RIO_CALLOUT_MAJOR1));
+}
+
+
+int rio_ismodem (kdev_t device)
+{
+  return (MAJOR (device) != RIO_NORMAL_MAJOR0) &&
+         (MAJOR (device) != RIO_NORMAL_MAJOR1);
+}
+
+
+void rio_udelay (int usecs)
+{
+  udelay (usecs);
+}
+
+
+void rio_inc_mod_count (void)
+{
+  func_enter ();
+  MOD_INC_USE_COUNT; 
+  func_exit ();
+}
+
+
+void rio_dec_mod_count (void)
+{
+  func_enter ();
+  MOD_DEC_USE_COUNT; 
+  func_exit ();
+}
+
+
+static int rio_set_real_termios (void *ptr)
+{
+  int rv;
+  func_enter();
+
+  rv = RIOParam( (struct Port *) ptr, CONFIG, 0, 1);
+
+  func_exit ();
+
+  return rv;
+}
+
+
+void rio_reset_interrupt (struct Host *HostP)
+{
+  switch( HostP->Type ) {
+  case RIO_AT:
+  case RIO_MCA:
+  case RIO_PCI:
+    WBYTE(HostP->ResetInt , 0xff);
+  }
+}
+
+
+static void rio_interrupt (int irq, void *ptr, struct pt_regs *regs)
+{
+  struct Host *HostP;
+
+  HostP = &p->RIOHosts[(long)ptr];
+  /*   func_enter ();  */
+  rio_dprintk (RIO_DEBUG_IFLOW, "rio: enter rio_interrupt (%d/%d)\n", 
+               irq, HostP->Ivec); 
+
+  /* AAargh! The order in which to do these things is essential and
+     not trivial. 
+     
+     - Rate limit goes before "recursive". Otherwise a series of
+       recursive calls will hang the machine in the interrupt routine. 
+
+     - hardware twiddling goes before "recursive". Otherwise when we
+       poll the card, and a recursive interrupt happens, we wont
+       ack the card, so it might keep on interrupting us. (especially
+       level sensitive interrupt systems like PCI).
+
+     - Rate limit goes before hardware twiddling. Otherwise we won't
+       catch a card that has gone bonkers.
+
+     - The "initialized" test goes after the hardware twiddling. Otherwise
+       the card will stick us in the interrupt routine again.
+
+     - The initialized test goes before recursive. 
+  */
+
+
+
+#ifdef IRQ_RATE_LIMIT
+  /* Aaargh! I'm ashamed. This costs more lines-of-code than the
+     actual interrupt routine!. (Well, used to when I wrote that comment) */
+  {
+    static int lastjif;
+    static int nintr=0;
+
+    if (lastjif == jiffies) {
+      if (++nintr > IRQ_RATE_LIMIT) {
+        free_irq (HostP->Ivec, ptr);
+        printk (KERN_ERR "rio: Too many interrupts. Turning off interrupt %d.\n", 
+                HostP->Ivec);
+      }
+    } else {
+      lastjif = jiffies;
+      nintr = 0;
+    }
+  }
+#endif
+
+  if (HostP->Ivec == irq) {
+    /* Tell the card we've noticed the interrupt. */
+    rio_reset_interrupt (HostP);
+  }
+
+  if ((HostP->Flags & RUN_STATE) != RC_RUNNING) return;
+
+  if (test_and_set_bit (RIO_BOARD_INTR_LOCK, &HostP->locks)) {
+    printk (KERN_ERR "Recursive interrupt! (host %d/irq%d)\n", 
+            (int) ptr, HostP->Ivec);
+    return;
+  }
+
+  RIOServiceHost(p, HostP, irq);
+
+  rio_dprintk ( RIO_DEBUG_IFLOW, "riointr() doing host %d type %d\n", 
+                (int) ptr, HostP->Type);
+
+  clear_bit (RIO_BOARD_INTR_LOCK, &HostP->locks);
+  rio_dprintk (RIO_DEBUG_IFLOW, "rio: exit rio_interrupt (%d/%d)\n", 
+               irq, HostP->Ivec); 
+  /*  func_exit ();  */
+}
+
+
+static void rio_pollfunc (unsigned long data)
+{
+  func_enter ();
+
+  rio_interrupt (0, (void *)data, NULL);
+  p->RIOHosts[data].timer.expires = jiffies + rio_poll;
+  add_timer (&p->RIOHosts[data].timer);
+
+  func_exit ();
+}
+
+
+/* ********************************************************************** *
+ *                Here are the routines that actually                     *
+ *              interface with the generic_serial driver                  *
+ * ********************************************************************** */
+
+/* Ehhm. I don't know how to fiddle with interrupts on the Specialix 
+   cards. ....   Hmm. Ok I figured it out. You don't.  -- REW */
+
+static void rio_disable_tx_interrupts (void * ptr) 
+{
+  func_enter();
+
+  /*  port->gs.flags &= ~GS_TX_INTEN; */
+
+  func_exit();
+}
+
+
+static void rio_enable_tx_interrupts (void * ptr) 
+{
+  struct Port *PortP = ptr;
+  /* int hn; */
+
+  func_enter();
+
+  /* hn = PortP->HostP - p->RIOHosts;
+
+     rio_dprintk (RIO_DEBUG_TTY, "Pushing host %d\n", hn);
+     rio_interrupt (-1,(void *) hn, NULL); */
+
+  RIOTxEnable((char *) PortP);
+
+  /* 
+   * In general we cannot count on "tx empty" interrupts, although
+   * the interrupt routine seems to be able to tell the difference. 
+   */
+  PortP->gs.flags &= ~GS_TX_INTEN;
+
+  func_exit();
+}
+
+
+static void rio_disable_rx_interrupts (void * ptr) 
+{
+  func_enter();
+  func_exit();
+}
+
+static void rio_enable_rx_interrupts (void * ptr) 
+{
+  /*  struct rio_port *port = ptr; */
+  func_enter();
+  func_exit();
+}
+
+
+/* Jeez. Isn't this simple?  */
+static int rio_get_CD (void * ptr) 
+{
+  struct Port *PortP = ptr;
+  int rv;
+
+  func_enter();
+  rv = (PortP->ModemState & MSVR1_CD) != 0;
+
+  rio_dprintk (RIO_DEBUG_INIT, "Getting CD status: %d\n", rv);
+  
+  func_exit();  
+  return rv;
+}
+
+
+/* Jeez. Isn't this simple? Actually, we can sync with the actual port
+   by just pushing stuff into the queue going to the port... */
+static int rio_chars_in_buffer (void * ptr) 
+{
+  func_enter();
+
+  func_exit();  
+  return 0;
+}
+
+
+/* Nothing special here... */
+static void rio_shutdown_port (void * ptr) 
+{
+  func_enter();
+
+#if 0
+  port->gs.flags &= ~ GS_ACTIVE;
+  if (!port->gs.tty) {
+    printk ("No tty.\n");
+    return;
+  }
+  if (!port->gs.tty->termios) {
+    printk ("No termios.\n");
+    return;
+  }
+  if (port->gs.tty->termios->c_cflag & HUPCL) {
+    rio_setsignals (port, 0, 0);
+  }
+#endif
+
+  func_exit();
+}
+
+
+
+/* ********************************************************************** *
+ *                Here are the routines that actually                     *
+ *               interface with the rest of the system                    *
+ * ********************************************************************** */
+
+
+static int rio_fw_open(struct inode *inode, struct file *filp)
+{
+  func_enter ();
+  rio_inc_mod_count ();
+  func_exit ();
+  return 0;
+}
+
+
+static INT rio_fw_release(struct inode *inode, struct file *filp)
+{
+  func_enter ();
+  rio_dec_mod_count ();
+  func_exit ();
+  return NO_ERROR;
+}
+
+
+/* I haven't the foggiest why the decrement use count has to happen
+   here. The whole linux serial drivers stuff needs to be redesigned.
+   My guess is that this is a hack to minimize the impact of a bug
+   elsewhere. Thinking about it some more. (try it sometime) Try
+   running minicom on a serial port that is driven by a modularized
+   driver. Have the modem hangup. Then remove the driver module. Then
+   exit minicom.  I expect an "oops".  -- REW */
+static void rio_hungup (void *ptr)
+{
+  func_enter ();
+  /* rio_dec_mod_count (); */
+  func_exit ();
+}
+
+
+/* The standard serial_close would become shorter if you'd wrap it like
+   this. 
+   rs_close (...){save_flags;cli;real_close();dec_use_count;restore_flags;}
+ */
+static void rio_close (void *ptr)
+{
+  func_enter ();
+  riotclose (ptr);
+  rio_dec_mod_count ();
+  func_exit ();
+}
+
+
+
+static int rio_fw_ioctl (struct inode *inode, struct file *filp,
+		         unsigned int cmd, unsigned long arg)
+{
+  int rc = 0;
+  func_enter();
+
+  /* The "dev" argument isn't used. */
+  rc = -riocontrol (p, 0, cmd, (void *)arg, suser ());
+
+  func_exit ();
+  return rc;
+}
+
+
+static int rio_ioctl (struct tty_struct * tty, struct file * filp, 
+                     unsigned int cmd, unsigned long arg)
+{
+#if 0
+  int rc;
+  struct rio_port *port = tty->driver_data;
+  int ival;
+
+  /* func_enter2(); */
+
+
+  rc  = 0;
+  switch (cmd) {
+  case TIOCGSOFTCAR:
+    rc = Put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
+                  (unsigned int *) arg);
+    break;
+  case TIOCSSOFTCAR:
+    if ((rc = verify_area(VERIFY_READ, (void *) arg,
+                          sizeof(int))) == 0) {
+      Get_user(ival, (unsigned int *) arg);
+      tty->termios->c_cflag =
+        (tty->termios->c_cflag & ~CLOCAL) |
+        (ival ? CLOCAL : 0);
+    }
+    break;
+  case TIOCGSERIAL:
+    if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
+                          sizeof(struct serial_struct))) == 0)
+      gs_getserial(&port->gs, (struct serial_struct *) arg);
+    break;
+  case TIOCSSERIAL:
+    if ((rc = verify_area(VERIFY_READ, (void *) arg,
+                          sizeof(struct serial_struct))) == 0)
+      rc = gs_setserial(&port->gs, (struct serial_struct *) arg);
+    break;
+  case TIOCMGET:
+    if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
+                          sizeof(unsigned int))) == 0) {
+      ival = rio_getsignals(port);
+      put_user(ival, (unsigned int *) arg);
+    }
+    break;
+  case TIOCMBIS:
+    if ((rc = verify_area(VERIFY_READ, (void *) arg,
+                          sizeof(unsigned int))) == 0) {
+      Get_user(ival, (unsigned int *) arg);
+      rio_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1),
+                           ((ival & TIOCM_RTS) ? 1 : -1));
+    }
+    break;
+  case TIOCMBIC:
+    if ((rc = verify_area(VERIFY_READ, (void *) arg,
+                          sizeof(unsigned int))) == 0) {
+      Get_user(ival, (unsigned int *) arg);
+      rio_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1),
+                           ((ival & TIOCM_RTS) ? 0 : -1));
+    }
+    break;
+  case TIOCMSET:
+    if ((rc = verify_area(VERIFY_READ, (void *) arg,
+                          sizeof(unsigned int))) == 0) {
+      Get_user(ival, (unsigned int *) arg);
+      rio_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0),
+                           ((ival & TIOCM_RTS) ? 1 : 0));
+    }
+    break;
+
+  default:
+    rc = -ENOIOCTLCMD;
+    break;
+  }
+  /* func_exit(); */
+  return rc;
+#else
+  return -ENOIOCTLCMD;
+#endif
+
+}
+
+
+/* The throttle/unthrottle scheme for the Specialix card is different
+ * from other drivers and deserves some explanation. 
+ * The Specialix hardware takes care of XON/XOFF
+ * and CTS/RTS flow control itself.  This means that all we have to
+ * do when signalled by the upper tty layer to throttle/unthrottle is
+ * to make a note of it here.  When we come to read characters from the
+ * rx buffers on the card (rio_receive_chars()) we look to see if the
+ * upper layer can accept more (as noted here in rio_rx_throt[]). 
+ * If it can't we simply don't remove chars from the cards buffer. 
+ * When the tty layer can accept chars, we again note that here and when
+ * rio_receive_chars() is called it will remove them from the cards buffer.
+ * The card will notice that a ports buffer has drained below some low
+ * water mark and will unflow control the line itself, using whatever
+ * flow control scheme is in use for that port. -- Simon Allen
+ */
+
+static void rio_throttle (struct tty_struct * tty)
+{
+  struct Port *port = (struct Port *)tty->driver_data;
+  
+  func_enter();
+  /* If the port is using any type of input flow
+   * control then throttle the port.
+   */
+
+  if((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty)) ) {
+    port->State |= RIO_THROTTLE_RX;
+  }
+
+  func_exit();
+}
+
+
+static void rio_unthrottle (struct tty_struct * tty)
+{
+  struct Port *port = (struct Port *)tty->driver_data;
+
+  func_enter();
+  /* Always unthrottle even if flow control is not enabled on
+   * this port in case we disabled flow control while the port
+   * was throttled
+   */
+
+  port->State &= ~RIO_THROTTLE_RX;
+
+  func_exit();
+  return;
+}
+
+
+
+
+
+/* ********************************************************************** *
+ *                    Here are the initialization routines.               *
+ * ********************************************************************** */
+
+
+struct vpd_prom *get_VPD_PROM (struct Host *hp)
+{
+  static struct vpd_prom vpdp;
+  char *p;
+  int i;
+
+  func_enter();
+  rio_dprintk (RIO_DEBUG_PROBE, "Going to verify vpd prom at %p.\n", 
+              hp->Caddr + RIO_VPD_ROM);
+
+  p = (char *) &vpdp;
+  for (i=0;i< sizeof (struct vpd_prom);i++)
+    *p++ = readb (hp->Caddr+RIO_VPD_ROM + i*2);
+      /* read_rio_byte (hp, RIO_VPD_ROM + i*2); */
+
+  /* Terminate the identifier string. 
+     *** requires one extra byte in struct vpd_prom *** */
+  *p++=0; 
+
+  if (rio_debug & RIO_DEBUG_PROBE)
+    my_hd ((char *)&vpdp, 0x20);
+
+  return &vpdp;
+}
+
+
+
+static int rio_init_drivers(void)
+{
+  int error;
+  
+  func_enter();
+
+  memset(&rio_driver, 0, sizeof(rio_driver));
+  rio_driver.magic = TTY_DRIVER_MAGIC;
+  rio_driver.driver_name = "specialix_rio";
+  rio_driver.name = "ttySR";
+  rio_driver.major = RIO_NORMAL_MAJOR0;
+  rio_driver.num = 256;
+  rio_driver.type = TTY_DRIVER_TYPE_SERIAL;
+  rio_driver.subtype = RIO_TYPE_NORMAL;
+  rio_driver.init_termios = tty_std_termios;
+  rio_driver.init_termios.c_cflag =
+    B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+  rio_driver.flags = TTY_DRIVER_REAL_RAW;
+  rio_driver.refcount = &rio_refcount;
+  rio_driver.table = rio_table;
+  rio_driver.termios = rio_termios;
+  rio_driver.termios_locked = rio_termios_locked;
+
+  rio_driver.open  = riotopen;
+  rio_driver.close = gs_close;
+  rio_driver.write = gs_write;
+  rio_driver.put_char = gs_put_char;
+  rio_driver.flush_chars = gs_flush_chars;
+  rio_driver.write_room = gs_write_room;
+  rio_driver.chars_in_buffer = gs_chars_in_buffer;
+  rio_driver.flush_buffer = gs_flush_buffer;
+  rio_driver.ioctl = rio_ioctl;
+  rio_driver.throttle = rio_throttle;
+  rio_driver.unthrottle = rio_unthrottle;
+  rio_driver.set_termios = gs_set_termios;
+  rio_driver.stop = gs_stop;
+  rio_driver.start = gs_start;
+  rio_driver.hangup = gs_hangup;
+
+  rio_driver2 = rio_driver;
+  rio_driver.major = RIO_NORMAL_MAJOR1;
+
+  rio_callout_driver = rio_driver;
+  rio_callout_driver.name = "cusr";
+  rio_callout_driver.major = RIO_CALLOUT_MAJOR0;
+  rio_callout_driver.subtype = RIO_TYPE_CALLOUT;
+
+  rio_callout_driver2 = rio_callout_driver;
+  rio_callout_driver2.major = RIO_CALLOUT_MAJOR1;
+
+  rio_dprintk (RIO_DEBUG_INIT, "set_termios = %p\n", gs_set_termios);
+
+  if ((error = tty_register_driver(&rio_driver))) goto bad1;
+  if ((error = tty_register_driver(&rio_driver2))) goto bad2;
+  if ((error = tty_register_driver(&rio_callout_driver))) goto bad3;
+  if ((error = tty_register_driver(&rio_callout_driver2))) goto bad4;
+
+  func_exit();
+  return 0;
+  /* 
+ bad5:tty_unregister_driver (&rio_callout_driver2); */
+ bad4:tty_unregister_driver (&rio_callout_driver);
+ bad3:tty_unregister_driver (&rio_driver2);
+ bad2:tty_unregister_driver (&rio_driver);
+ bad1:printk(KERN_ERR "rio: Couldn't register a rio driver, error = %d\n",
+             error);
+  return 1;
+}
+
+
+static void * ckmalloc (int size)
+{
+  void *p;
+
+  p = kmalloc(size, GFP_KERNEL);
+  if (p) 
+    memset(p, 0, size);
+  return p;
+}
+
+
+
+static int rio_init_datastructures (void)
+{
+  int i;
+  struct Port *port;
+  func_enter();
+
+  /* Many drivers statically allocate the maximum number of ports
+     There is no reason not to allocate them dynamically. Is there? -- REW */
+  /* However, the RIO driver allows users to configure their first
+     RTA as the ports numbered 504-511. We therefore need to allocate 
+     the whole range. :-(   -- REW */
+
+#define RI_SZ   sizeof(struct rio_info)
+#define HOST_SZ sizeof(struct Host)
+#define PORT_SZ sizeof(struct Port *)
+#define TMIO_SZ sizeof(struct termios *)
+  rio_dprintk (RIO_DEBUG_INIT, "getting : %d %d %d %d %d bytes\n", 
+               RI_SZ, 
+               RIO_HOSTS * HOST_SZ,
+               RIO_PORTS * PORT_SZ,
+               RIO_PORTS * TMIO_SZ,
+               RIO_PORTS * TMIO_SZ);
+  
+  if (!(p                  = ckmalloc (              RI_SZ))) goto free0;
+  if (!(p->RIOHosts        = ckmalloc (RIO_HOSTS * HOST_SZ))) goto free1;
+  if (!(p->RIOPortp        = ckmalloc (RIO_PORTS * PORT_SZ))) goto free2;
+  if (!(rio_termios        = ckmalloc (RIO_PORTS * TMIO_SZ))) goto free3;
+  if (!(rio_termios_locked = ckmalloc (RIO_PORTS * TMIO_SZ))) goto free4;
+  p->RIOConf = RIOConf;
+  rio_dprintk (RIO_DEBUG_INIT, "Got : %p %p %p %p %p\n", 
+               p, p->RIOHosts, p->RIOPortp, rio_termios, rio_termios);
+
+  /* Adjust the values in the "driver" */
+  rio_driver.termios = rio_termios;
+  rio_driver.termios_locked = rio_termios_locked;
+  
+#if 1
+  for (i = 0; i < RIO_PORTS; i++) {
+    port = p->RIOPortp[i] = ckmalloc (sizeof (struct Port));
+    if (!port) {
+      goto free6;
+    }
+    rio_dprintk (RIO_DEBUG_INIT, "initing port %d (%d)\n", i, port->Mapped);
+    port->PortNum = i;
+    port->gs.callout_termios = tty_std_termios;
+    port->gs.normal_termios  = tty_std_termios;
+    port->gs.magic = RIO_MAGIC;
+    port->gs.close_delay = HZ/2;
+    port->gs.closing_wait = 30 * HZ;
+    port->gs.rd = &rio_real_driver;
+  }
+#else
+  /* We could postpone initializing them to when they are configured. */
+#endif
+
+  if (rio_debug & RIO_DEBUG_INIT) {
+    my_hd (&rio_real_driver, sizeof (rio_real_driver));
+  }
+
+  
+  func_exit();
+  return 0;
+
+ free6:for (i--;i>=0;i--)
+        kfree (p->RIOPortp[i]);
+/*free5: */
+       kfree (rio_termios_locked); 
+ free4:kfree (rio_termios);
+ free3:kfree (p->RIOPortp);
+ free2:kfree (p->RIOHosts);
+ free1:kfree (p);
+ free0:
+  rio_dprintk (RIO_DEBUG_INIT, "Not enough memory! %p %p %p %p %p\n", 
+               p, p->RIOHosts, p->RIOPortp, rio_termios, rio_termios);
+  return -ENOMEM;
+}
+
+
+static void rio_release_drivers(void)
+{
+  func_enter();
+  tty_unregister_driver (&rio_callout_driver2);
+  tty_unregister_driver (&rio_callout_driver);
+  tty_unregister_driver (&rio_driver2);
+  tty_unregister_driver (&rio_driver);
+  func_exit();
+}
+
+#ifdef TWO_ZERO
+#define PDEV unsigned char pci_bus, unsigned pci_fun
+#define pdev pci_bus, pci_fun
+#else
+#define PDEV   struct pci_dev *pdev
+#endif
+
+
+#ifdef CONFIG_PCI
+ /* This was written for SX, but applies to RIO too...
+    (including bugs....)
+
+    There is another bit besides Bit 17. Turning that bit off
+    (on boards shipped with the fix in the eeprom) results in a 
+    hang on the next access to the card. 
+ */
+
+ /******************************************************** 
+ * Setting bit 17 in the CNTRL register of the PLX 9050  * 
+ * chip forces a retry on writes while a read is pending.*
+ * This is to prevent the card locking up on Intel Xeon  *
+ * multiprocessor systems with the NX chipset.    -- NV  *
+ ********************************************************/
+
+/* Newer cards are produced with this bit set from the configuration
+   EEprom.  As the bit is read/write for the CPU, we can fix it here,
+   if we detect that it isn't set correctly. -- REW */
+
+void fix_rio_pci (PDEV)
+{
+  unsigned int hwbase;
+  unsigned long rebase;
+  unsigned int t;
+
+#define CNTRL_REG_OFFSET        0x50
+#define CNTRL_REG_GOODVALUE     0x00260000
+
+  pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase);
+  hwbase &= PCI_BASE_ADDRESS_MEM_MASK;
+  rebase =  (ulong) ioremap(hwbase, 0x80);
+  t = readl (rebase + CNTRL_REG_OFFSET);
+  if (t != CNTRL_REG_GOODVALUE) {
+    printk (KERN_DEBUG "rio: performing cntrl reg fix: %08x -> %08x\n", 
+            t, CNTRL_REG_GOODVALUE); 
+    writel (CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET);  
+  }
+  my_iounmap (hwbase, rebase);
+}
+#endif
+
+
+#ifdef MODULE
+#define rio_init init_module
+#endif
+
+extern int gs_debug;
+
+int rio_init(void) 
+{
+  int found = 0;
+  int i;
+  struct Host *hp;
+  int retval;
+  struct vpd_prom *vpdp;
+  int okboard;
+
+
+#ifdef CONFIG_PCI
+#ifndef TWO_ZERO
+  struct pci_dev *pdev = NULL;
+#else
+  unsigned char pci_bus, pci_fun;
+  /* in 2.2.x pdev is a pointer defining a PCI device. In 2.0 its the bus/fn */
+#endif
+  unsigned int tint;
+  unsigned short tshort;
+#endif
+
+  func_enter();
+  rio_dprintk (RIO_DEBUG_INIT, "Initing rio module... (rio_debug=%d)\n", 
+	       rio_debug);
+  gs_debug = rio_debug >> 24;
+
+  if (abs ((long) (&rio_debug) - rio_debug) < 0x10000) {
+    printk (KERN_WARNING "rio: rio_debug is an address, instead of a value. "
+            "Assuming -1. Was %x/%p.\n", rio_debug, &rio_debug);
+    rio_debug=-1;
+  }
+
+  retval = rio_init_datastructures ();
+  if (retval < 0) return retval;
+
+#ifdef CONFIG_PCI
+  if (pci_present ()) {
+    /* First look for the JET devices: */
+#ifndef TWO_ZERO
+    while ((pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, 
+                                    PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, 
+                                    pdev))) {
+#else
+    for (i=0;i< RIO_NBOARDS;i++) {
+      if (pcibios_find_device (PCI_VENDOR_ID_SPECIALIX, 
+			       PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, i,
+			       &pci_bus, &pci_fun)) break;
+#endif
+      /* Specialix has a whole bunch of cards with
+         0x2000 as the device ID. They say its because
+         the standard requires it. Stupid standard. */
+      /* It seems that reading a word doesn't work reliably on 2.0.
+         Also, reading a non-aligned dword doesn't work. So we read the
+         whole dword at 0x2c and extract the word at 0x2e (SUBSYSTEM_ID)
+         ourselves */
+      /* I don't know why the define doesn't work, constant 0x2c does --REW */ 
+      pci_read_config_dword (pdev, 0x2c, &tint);
+      tshort = (tint >> 16) & 0xffff;
+      rio_dprintk (RIO_DEBUG_PROBE, "Got a specialix card: %x.\n", tint);
+      /* rio_dprintk (RIO_DEBUG_PROBE, "pdev = %d/%d  (%x)\n", pdev, tint); */ 
+      if (tshort != 0x0100) {
+        rio_dprintk (RIO_DEBUG_PROBE, "But it's not a RIO card (%d)...\n", 
+                    tshort);
+        continue;
+      }
+      rio_dprintk (RIO_DEBUG_PROBE, "cp1\n");
+
+      pci_read_config_dword(pdev, PCI_BASE_ADDRESS_2, &tint);
+
+      hp = &p->RIOHosts[p->RIONumHosts];
+      hp->PaddrP =  tint & PCI_BASE_ADDRESS_MEM_MASK;
+      hp->Ivec = get_irq (pdev);
+      if (((1 << hp->Ivec) & rio_irqmask) == 0) hp->Ivec = 0;
+      hp->CardP	= (struct DpRam *)
+      hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
+      hp->Type  = RIO_PCI;
+      hp->Copy  = rio_pcicopy; 
+      hp->Mode  = RIO_PCI_DEFAULT_MODE;
+ 
+      rio_dprintk (RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n",
+                   (void *)p->RIOHosts[p->RIONumHosts].PaddrP,
+                   p->RIOHosts[p->RIONumHosts].Caddr);
+      if (RIOBoardTest( p->RIOHosts[p->RIONumHosts].PaddrP,
+                        p->RIOHosts[p->RIONumHosts].Caddr, 
+                        RIO_PCI, 0 ) == RIO_SUCCESS) {
+        WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff);
+        p->RIOHosts[p->RIONumHosts].UniqueNum  =
+          ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0]) &0xFF)<< 0)|
+          ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1]) &0xFF)<< 8)|
+          ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2]) &0xFF)<<16)|
+          ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3]) &0xFF)<<24);
+        rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n",
+                   p->RIOHosts[p->RIONumHosts].UniqueNum);
+
+#if 1
+        fix_rio_pci (pdev);
+#endif
+        p->RIOLastPCISearch = RIO_SUCCESS;
+        p->RIONumHosts++;
+        found++;
+      } else {
+        my_iounmap (p->RIOHosts[p->RIONumHosts].PaddrP, 
+                    p->RIOHosts[p->RIONumHosts].Caddr);
+      }
+
+#ifdef TWO_ZERO
+    }  /* We have two variants with the opening brace, so to prevent */
+#else
+    }  /* Emacs from getting confused we have two closing braces too. */
+#endif
+    
+
+    /* Then look for the older PCI card.... : */
+#ifndef TWO_ZERO
+
+  /* These older PCI cards have problems (only byte-mode access is
+     supported), which makes them a bit awkward to support. 
+     They also have problems sharing interrupts. Be careful. 
+     (The driver now refuses to share interrupts for these
+     cards. This should be sufficient).
+  */
+
+    /* Then look for the older RIO/PCI devices: */
+    while ((pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, 
+                                    PCI_DEVICE_ID_SPECIALIX_RIO, 
+                                    pdev))) {
+#else
+    for (i=0;i< RIO_NBOARDS;i++) {
+      if (pcibios_find_device (PCI_VENDOR_ID_SPECIALIX, 
+			       PCI_DEVICE_ID_SPECIALIX_RIO, i,
+			       &pci_bus, &pci_fun)) break;
+#endif
+
+#ifdef CONFIG_RIO_OLDPCI
+      pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &tint);
+
+      hp = &p->RIOHosts[p->RIONumHosts];
+      hp->PaddrP =  tint & PCI_BASE_ADDRESS_MEM_MASK;
+      hp->Ivec = get_irq (pdev);
+      if (((1 << hp->Ivec) & rio_irqmask) == 0) hp->Ivec = 0;
+      hp->Ivec |= 0x8000; /* Mark as non-sharable */
+      hp->CardP	= (struct DpRam *)
+      hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
+      hp->Type  = RIO_PCI;
+      hp->Copy  = rio_pcicopy;
+      hp->Mode  = RIO_PCI_DEFAULT_MODE;
+ 
+      rio_dprintk (RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n",
+                   (void *)p->RIOHosts[p->RIONumHosts].PaddrP,
+                   p->RIOHosts[p->RIONumHosts].Caddr);
+      if (RIOBoardTest( p->RIOHosts[p->RIONumHosts].PaddrP,
+                        p->RIOHosts[p->RIONumHosts].Caddr, 
+                        RIO_PCI, 0 ) == RIO_SUCCESS) {
+        WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff);
+        p->RIOHosts[p->RIONumHosts].UniqueNum  =
+          ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0]) &0xFF)<< 0)|
+          ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1]) &0xFF)<< 8)|
+          ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2]) &0xFF)<<16)|
+          ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3]) &0xFF)<<24);
+        rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n",
+                   p->RIOHosts[p->RIONumHosts].UniqueNum);
+
+        p->RIOLastPCISearch = RIO_SUCCESS;
+        p->RIONumHosts++;
+        found++;
+      } else {
+        my_iounmap (p->RIOHosts[p->RIONumHosts].PaddrP, 
+                    p->RIOHosts[p->RIONumHosts].Caddr);
+      }
+#else
+      printk (KERN_ERR "Found an older RIO PCI card, but the driver is not "
+              "compiled to support it.\n");
+#endif
+#ifdef TWO_ZERO
+    }  /* We have two variants with the opening brace, so to prevent */
+#else
+    }  /* Emacs from getting confused we have two closing braces too. */
+#endif
+  }
+#endif /* PCI */
+
+  /* Now probe for ISA cards... */
+  for (i=0;i<NR_RIO_ADDRS;i++) {
+    hp = &p->RIOHosts[p->RIONumHosts];
+    hp->PaddrP = rio_probe_addrs[i];
+    /* There was something about the IRQs of these cards. 'Forget what.--REW */
+    hp->Ivec = 0;
+    hp->CardP = (struct DpRam *)
+    hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
+    hp->Type = RIO_AT;
+    hp->Copy = rio_pcicopy;
+    hp->Mode = 0;
+
+    vpdp = get_VPD_PROM (hp);
+
+    okboard = 0;
+    if ((strncmp (vpdp->identifier, RIO_ISA_IDENT, 16) == 0) ||
+        (strncmp (vpdp->identifier, RIO_ISA2_IDENT, 16) == 0) ||
+        (strncmp (vpdp->identifier, RIO_ISA3_IDENT, 16) == 0)) {
+      /* Board is present... */
+      if (RIOBoardTest (hp->PaddrP, 
+                        hp->Caddr, RIO_AT, 0) == RIO_SUCCESS) {
+        /* ... and feeling fine!!!! */
+        rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n",
+                   p->RIOHosts[p->RIONumHosts].UniqueNum);
+        if (RIOAssignAT(p, hp->PaddrP, hp->Caddr, 0)) {        
+          rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, host%d uniqid = %x.\n",
+                       p->RIONumHosts, 
+                       p->RIOHosts[p->RIONumHosts-1].UniqueNum);
+          okboard++;
+          found++;
+        }
+      }
+
+    if (!okboard)
+      my_iounmap (hp->PaddrP, hp->Caddr);
+    }
+  }
+
+
+  for (i=0;i<p->RIONumHosts;i++) {
+    hp = &p->RIOHosts[i];
+    if (hp->Ivec) {
+      int mode = SA_SHIRQ;
+      if (hp->Ivec & 0x8000) {mode = 0; hp->Ivec &= 0x7fff;}
+      if (request_irq (hp->Ivec, rio_interrupt, mode, "rio", (void *)i)) {
+        printk(KERN_ERR "rio: Cannot allocate irq %d.\n", hp->Ivec);
+        hp->Ivec = 0;
+      }
+      rio_dprintk (RIO_DEBUG_INIT, "Got irq %d.\n", hp->Ivec);
+    }
+    /* Init the timer "always" to make sure that it can safely be 
+       deleted when we unload... */
+
+    init_timer (&hp->timer);
+    if (!hp->Ivec) {
+      rio_dprintk (RIO_DEBUG_INIT, "Starting polling at %dj intervals.\n", 
+                   rio_poll);
+      hp->timer.data = i;
+      hp->timer.function = rio_pollfunc;
+      hp->timer.expires = jiffies + rio_poll;
+      add_timer (&hp->timer);
+    }
+  }
+
+  if (found) {
+    printk (KERN_INFO "rio: total of %d boards detected.\n", found);
+
+    if (misc_register(&rio_fw_device) < 0) {
+      printk(KERN_ERR "RIO: Unable to register firmware loader driver.\n");
+      return -EIO;
+    }
+    rio_init_drivers ();
+  }
+
+  func_exit();
+  return found?0:-EIO;
+}
+
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+  int i; 
+  struct Host *hp;
+  
+  func_enter();
+
+  for (i=0,hp=p->RIOHosts;i<p->RIONumHosts;i++, hp++) {
+    RIOHostReset (hp->Type, hp->CardP, hp->Slot);
+    if (hp->Ivec) {
+      free_irq (hp->Ivec, (void *)i);
+      rio_dprintk (RIO_DEBUG_INIT, "freed irq %d.\n", hp->Ivec);
+    }
+    /* It is safe/allowed to del_timer a non-active timer */
+    del_timer (&hp->timer);
+  }
+
+  if (misc_deregister(&rio_fw_device) < 0) {
+    printk (KERN_INFO "rio: couldn't deregister control-device\n");
+  }
+
+
+  rio_dprintk (RIO_DEBUG_CLEANUP, "Cleaning up drivers\n");
+
+  rio_release_drivers ();
+
+  /* Release dynamically allocated memory */
+  kfree (rio_termios_locked); 
+  kfree (rio_termios);
+  kfree (p->RIOPortp);
+  kfree (p->RIOHosts);
+  kfree (p);
+
+  func_exit();
+}
+#endif
+
+
+
+/*
+ * Anybody who knows why this doesn't work for me, please tell me -- REW.
+ * Snatched from scsi.c (fixed one spelling error):
+ * Overrides for Emacs so that we follow Linus' tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local Variables:
+ * c-indent-level: 4
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/rio_linux.h linux.15p9/drivers/char/rio/rio_linux.h
--- linux.vanilla/drivers/char/rio/rio_linux.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/rio_linux.h	Sat Jan 22 00:23:24 2000
@@ -0,0 +1,161 @@
+
+/*
+ *  rio_linux.h
+ *
+ *  Copyright (C) 1998,1999,2000 R.E.Wolff@BitWizard.nl
+ *
+ *      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.
+ *
+ *  RIO serial driver.
+ *
+ *  Version 1.0 -- July, 1999. 
+ * 
+ */
+
+#define RIO_NBOARDS        4
+#define RIO_PORTSPERBOARD 128
+#define RIO_NPORTS        (RIO_NBOARDS * RIO_PORTSPERBOARD)
+
+#ifdef __KERNEL__
+
+#define RIO_MAGIC 0x12345678
+
+
+struct vpd_prom {
+  unsigned short id;
+  char hwrev;
+  char hwass;
+  int uniqid;
+  char myear;
+  char mweek;
+  char hw_feature[5];
+  char oem_id;
+  char identifier[16];
+};
+
+
+#define RIO_DEBUG_ALL           0xffffffff
+
+#define O_OTHER(tty)    \
+      ((O_OLCUC(tty))  ||\
+      (O_ONLCR(tty))   ||\
+      (O_OCRNL(tty))   ||\
+      (O_ONOCR(tty))   ||\
+      (O_ONLRET(tty))  ||\
+      (O_OFILL(tty))   ||\
+      (O_OFDEL(tty))   ||\
+      (O_NLDLY(tty))   ||\
+      (O_CRDLY(tty))   ||\
+      (O_TABDLY(tty))  ||\
+      (O_BSDLY(tty))   ||\
+      (O_VTDLY(tty))   ||\
+      (O_FFDLY(tty)))
+
+/* Same for input. */
+#define I_OTHER(tty)    \
+      ((I_INLCR(tty))  ||\
+      (I_IGNCR(tty))   ||\
+      (I_ICRNL(tty))   ||\
+      (I_IUCLC(tty))   ||\
+      (L_ISIG(tty)))
+
+
+#endif /* __KERNEL__ */
+
+
+#define RIO_BOARD_INTR_LOCK  1
+
+
+#ifndef RIOCTL_MISC_MINOR 
+/* Allow others to gather this into "major.h" or something like that */
+#define RIOCTL_MISC_MINOR    169
+#endif
+
+
+/* Allow us to debug "in the field" without requiring clients to
+   recompile.... */
+#if 1
+#define rio_spin_lock_irqsave(sem, flags) do { \
+	rio_dprint(RIO_DEBUG_SPINLOCK, ("spinlockirqsave: %p %s:%d\n", \
+					sem, __FILE__, __LINE__));\
+        spin_lock_irqsave(sem, flags);\
+        } while (0)
+
+#define rio_spin_unlock_irqrestore(sem, flags) do { \
+	rio_dprint(RIO_DEBUG_SPINLOCK, ("spinunlockirqrestore: %p %s:%d\n",\
+					sem, __FILE__, __LINE__));\
+        spin_unlock_irqrestore(sem, flags);\
+        } while (0)
+
+
+#define rio_spin_lock(sem) do { \
+	rio_dprint(RIO_DEBUG_SPINLOCK, ("spinlock: %p %s:%d\n",\
+					sem, __FILE__, __LINE__));\
+        spin_lock(sem);\
+        } while (0)
+
+#define rio_spin_unlock(sem) do { \
+	rio_dprint(RIO_DEBUG_SPINLOCK, ("spinunlock: %p %s:%d\n",\
+					sem, __FILE__, __LINE__));\
+        spin_unlock(sem);\
+        } while (0)
+#else
+#define rio_spin_lock_irqsave(sem, flags) \
+            spin_lock_irqsave(sem, flags)
+
+#define rio_spin_unlock_irqrestore(sem, flags) \
+            spin_unlock_irqrestore(sem, flags)
+
+#define rio_spin_lock(sem) \
+            spin_lock(sem) 
+
+#define rio_spin_unlock(sem) \
+            spin_unlock(sem) 
+
+#endif
+
+
+
+#ifdef CONFIG_RIO_OLDPCI
+static inline void *rio_memcpy_toio (void *dummy, void *dest, void *source, int n)
+{
+  char *dst = dest;
+  char *src = source;
+
+  while (n--) {
+    writeb (*src++, dst++);
+    (void) readb (dummy);
+  }
+
+  return dest;
+}
+
+
+static inline void *rio_memcpy_fromio (void *dest, void *source, int n)
+{
+  char *dst = dest;
+  char *src = source;
+
+  while (n--) 
+    *dst++ = readb (src++);
+
+  return dest;
+}
+
+#else
+#define rio_memcpy_toio(dummy,dest,source,n)   memcpy_toio(dest, source, n)
+#define rio_memcpy_fromio                      memcpy_fromio
+#endif
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/rioboard.h linux.15p9/drivers/char/rio/rioboard.h
--- linux.vanilla/drivers/char/rio/rioboard.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/rioboard.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,281 @@
+/************************************************************************/
+/*									*/
+/*	Title		:	RIO Host Card Hardware Definitions	*/
+/*									*/
+/*	Author		:	N.P.Vassallo				*/
+/*									*/
+/*	Creation	:	26th April 1999				*/
+/*									*/
+/*	Version		:	1.0.0					*/
+/*									*/
+/*	Copyright	:	(c) Specialix International Ltd. 1999	*
+ *
+ *      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.
+ *									*/
+/*	Description	:	Prototypes, structures and definitions	*/
+/*				describing the RIO board hardware	*/
+/*									*/
+/************************************************************************/
+
+/* History...
+
+1.0.0	26/04/99 NPV	Creation.
+
+*/
+
+#ifndef	_rioboard_h				/* If RIOBOARD.H not already defined */
+#define	_rioboard_h    1
+
+/*****************************************************************************
+***********************                                ***********************
+***********************   Hardware Control Registers   ***********************
+***********************                                ***********************
+*****************************************************************************/
+
+/* Hardware Registers... */
+
+#define	RIO_REG_BASE	0x7C00			/* Base of control registers */
+
+#define	RIO_CONFIG	RIO_REG_BASE + 0x0000	/* WRITE: Configuration Register */
+#define	RIO_INTSET	RIO_REG_BASE + 0x0080	/* WRITE: Interrupt Set */
+#define	RIO_RESET	RIO_REG_BASE + 0x0100	/* WRITE: Host Reset */
+#define	RIO_INTRESET	RIO_REG_BASE + 0x0180	/* WRITE: Interrupt Reset */
+
+#define	RIO_VPD_ROM	RIO_REG_BASE + 0x0000	/* READ: Vital Product Data ROM */
+#define	RIO_INTSTAT	RIO_REG_BASE + 0x0080	/* READ: Interrupt Status (Jet boards only) */
+#define	RIO_RESETSTAT	RIO_REG_BASE + 0x0100	/* READ: Reset Status (Jet boards only) */
+
+/* RIO_VPD_ROM definitions... */
+#define	VPD_SLX_ID1	0x00			/* READ: Specialix Identifier #1 */
+#define	VPD_SLX_ID2	0x01			/* READ: Specialix Identifier #2 */
+#define	VPD_HW_REV	0x02			/* READ: Hardware Revision */
+#define	VPD_HW_ASSEM	0x03			/* READ: Hardware Assembly Level */
+#define	VPD_UNIQUEID4	0x04			/* READ: Unique Identifier #4 */
+#define	VPD_UNIQUEID3	0x05			/* READ: Unique Identifier #3 */
+#define	VPD_UNIQUEID2	0x06			/* READ: Unique Identifier #2 */
+#define	VPD_UNIQUEID1	0x07			/* READ: Unique Identifier #1 */
+#define	VPD_MANU_YEAR	0x08			/* READ: Year Of Manufacture (0 = 1970) */
+#define	VPD_MANU_WEEK	0x09			/* READ: Week Of Manufacture (0 = week 1 Jan) */
+#define	VPD_HWFEATURE1	0x0A			/* READ: Hardware Feature Byte 1 */
+#define	VPD_HWFEATURE2	0x0B			/* READ: Hardware Feature Byte 2 */
+#define	VPD_HWFEATURE3	0x0C			/* READ: Hardware Feature Byte 3 */
+#define	VPD_HWFEATURE4	0x0D			/* READ: Hardware Feature Byte 4 */
+#define	VPD_HWFEATURE5	0x0E			/* READ: Hardware Feature Byte 5 */
+#define	VPD_OEMID	0x0F			/* READ: OEM Identifier */
+#define	VPD_IDENT	0x10			/* READ: Identifier string (16 bytes) */
+#define	VPD_IDENT_LEN	0x10
+
+/* VPD ROM Definitions... */
+#define	SLX_ID1		0x4D
+#define	SLX_ID2		0x98
+
+#define	PRODUCT_ID(a)	((a>>4)&0xF)		/* Use to obtain Product ID from VPD_UNIQUEID1 */
+
+#define	ID_SX_ISA	0x2
+#define	ID_RIO_EISA	0x3
+#define	ID_SX_PCI	0x5
+#define	ID_SX_EISA	0x7
+#define	ID_RIO_RTA16	0x9
+#define	ID_RIO_ISA	0xA
+#define	ID_RIO_MCA	0xB
+#define	ID_RIO_SBUS	0xC
+#define	ID_RIO_PCI	0xD
+#define	ID_RIO_RTA8	0xE
+
+/* Transputer bootstrap definitions... */
+
+#define	BOOTLOADADDR		(0x8000 - 6)
+#define	BOOTINDICATE		(0x8000 - 2)
+
+/* Firmware load position... */
+
+#define	FIRMWARELOADADDR	0x7C00		/* Firmware is loaded _before_ this address */
+
+/*****************************************************************************
+*****************************                    *****************************
+*****************************   RIO (Rev1) ISA   *****************************
+*****************************                    *****************************
+*****************************************************************************/
+
+/* Control Register Definitions... */
+#define	RIO_ISA_IDENT	"JBJGPGGHINSMJPJR"
+
+#define	RIO_ISA_CFG_BOOTRAM	0x01		/* Boot from RAM, else Link */
+#define	RIO_ISA_CFG_BUSENABLE	0x02		/* Enable processor bus */
+#define	RIO_ISA_CFG_IRQMASK	0x30		/* Interrupt mask */
+#define	  RIO_ISA_CFG_IRQ12	0x10		/* Interrupt Level 12 */
+#define	  RIO_ISA_CFG_IRQ11	0x20		/* Interrupt Level 11 */
+#define	  RIO_ISA_CFG_IRQ9	0x30		/* Interrupt Level 9 */
+#define	RIO_ISA_CFG_LINK20	0x40		/* 20Mbps link, else 10Mbps */
+#define	RIO_ISA_CFG_WAITSTATE0	0x80		/* 0 waitstates, else 1 */
+
+/*****************************************************************************
+*****************************                    *****************************
+*****************************   RIO (Rev2) ISA   *****************************
+*****************************                    *****************************
+*****************************************************************************/
+
+/* Control Register Definitions... */
+#define	RIO_ISA2_IDENT	"JBJGPGGHINSMJPJR"
+
+#define	RIO_ISA2_CFG_BOOTRAM	0x01		/* Boot from RAM, else Link */
+#define	RIO_ISA2_CFG_BUSENABLE	0x02		/* Enable processor bus */
+#define	RIO_ISA2_CFG_INTENABLE	0x04		/* Interrupt enable, else disable */
+#define	RIO_ISA2_CFG_16BIT	0x08		/* 16bit mode, else 8bit */
+#define	RIO_ISA2_CFG_IRQMASK	0x30		/* Interrupt mask */
+#define	  RIO_ISA2_CFG_IRQ15	0x00		/* Interrupt Level 15 */
+#define	  RIO_ISA2_CFG_IRQ12	0x10		/* Interrupt Level 12 */
+#define	  RIO_ISA2_CFG_IRQ11	0x20		/* Interrupt Level 11 */
+#define	  RIO_ISA2_CFG_IRQ9	0x30		/* Interrupt Level 9 */
+#define	RIO_ISA2_CFG_LINK20	0x40		/* 20Mbps link, else 10Mbps */
+#define	RIO_ISA2_CFG_WAITSTATE0	0x80		/* 0 waitstates, else 1 */
+
+/*****************************************************************************
+*****************************                   ******************************
+*****************************   RIO (Jet) ISA   ******************************
+*****************************                   ******************************
+*****************************************************************************/
+
+/* Control Register Definitions... */
+#define	RIO_ISA3_IDENT	"JET HOST BY KEV#"
+
+#define	RIO_ISA3_CFG_BUSENABLE	0x02		/* Enable processor bus */
+#define	RIO_ISA3_CFG_INTENABLE	0x04		/* Interrupt enable, else disable */
+#define	RIO_ISA32_CFG_IRQMASK	0xF30		/* Interrupt mask */
+#define	  RIO_ISA3_CFG_IRQ15	0xF0		/* Interrupt Level 15 */
+#define	  RIO_ISA3_CFG_IRQ12	0xC0		/* Interrupt Level 12 */
+#define	  RIO_ISA3_CFG_IRQ11	0xB0		/* Interrupt Level 11 */
+#define	  RIO_ISA3_CFG_IRQ10	0xA0		/* Interrupt Level 10 */
+#define	  RIO_ISA3_CFG_IRQ9	0x90		/* Interrupt Level 9 */
+
+/*****************************************************************************
+*********************************             ********************************
+*********************************   RIO MCA   ********************************
+*********************************             ********************************
+*****************************************************************************/
+
+/* Control Register Definitions... */
+#define	RIO_MCA_IDENT	"JBJGPGGHINSMJPJR"
+
+#define	RIO_MCA_CFG_BOOTRAM	0x01		/* Boot from RAM, else Link */
+#define	RIO_MCA_CFG_BUSENABLE	0x02		/* Enable processor bus */
+#define	RIO_MCA_CFG_LINK20	0x40		/* 20Mbps link, else 10Mbps */
+
+/*****************************************************************************
+********************************              ********************************
+********************************   RIO EISA   ********************************
+********************************              ********************************
+*****************************************************************************/
+
+/* EISA Configuration Space Definitions... */
+#define	EISA_PRODUCT_ID1	0xC80
+#define	EISA_PRODUCT_ID2	0xC81
+#define	EISA_PRODUCT_NUMBER	0xC82
+#define	EISA_REVISION_NUMBER	0xC83
+#define	EISA_CARD_ENABLE	0xC84
+#define	EISA_VPD_UNIQUEID4	0xC88		/* READ: Unique Identifier #4 */
+#define	EISA_VPD_UNIQUEID3	0xC8A		/* READ: Unique Identifier #3 */
+#define	EISA_VPD_UNIQUEID2	0xC90		/* READ: Unique Identifier #2 */
+#define	EISA_VPD_UNIQUEID1	0xC92		/* READ: Unique Identifier #1 */
+#define	EISA_VPD_MANU_YEAR	0xC98		/* READ: Year Of Manufacture (0 = 1970) */
+#define	EISA_VPD_MANU_WEEK	0xC9A		/* READ: Week Of Manufacture (0 = week 1 Jan) */
+#define	EISA_MEM_ADDR_23_16	0xC00
+#define	EISA_MEM_ADDR_31_24	0xC01
+#define	EISA_RIO_CONFIG		0xC02		/* WRITE: Configuration Register */
+#define	EISA_RIO_INTSET		0xC03		/* WRITE: Interrupt Set */
+#define	EISA_RIO_INTRESET	0xC03		/* READ:  Interrupt Reset */
+
+/* Control Register Definitions... */
+#define	RIO_EISA_CFG_BOOTRAM	0x01		/* Boot from RAM, else Link */
+#define	RIO_EISA_CFG_LINK20	0x02		/* 20Mbps link, else 10Mbps */
+#define	RIO_EISA_CFG_BUSENABLE	0x04		/* Enable processor bus */
+#define	RIO_EISA_CFG_PROCRUN	0x08		/* Processor running, else reset */
+#define	RIO_EISA_CFG_IRQMASK	0xF0		/* Interrupt mask */
+#define	  RIO_EISA_CFG_IRQ15	0xF0		/* Interrupt Level 15 */
+#define	  RIO_EISA_CFG_IRQ14	0xE0		/* Interrupt Level 14 */
+#define	  RIO_EISA_CFG_IRQ12	0xC0		/* Interrupt Level 12 */
+#define	  RIO_EISA_CFG_IRQ11	0xB0		/* Interrupt Level 11 */
+#define	  RIO_EISA_CFG_IRQ10	0xA0		/* Interrupt Level 10 */
+#define	  RIO_EISA_CFG_IRQ9	0x90		/* Interrupt Level 9 */
+#define	  RIO_EISA_CFG_IRQ7	0x70		/* Interrupt Level 7 */
+#define	  RIO_EISA_CFG_IRQ6	0x60		/* Interrupt Level 6 */
+#define	  RIO_EISA_CFG_IRQ5	0x50		/* Interrupt Level 5 */
+#define	  RIO_EISA_CFG_IRQ4	0x40		/* Interrupt Level 4 */
+#define	  RIO_EISA_CFG_IRQ3	0x30		/* Interrupt Level 3 */
+
+/*****************************************************************************
+********************************              ********************************
+********************************   RIO SBus   ********************************
+********************************              ********************************
+*****************************************************************************/
+
+/* Control Register Definitions... */
+#define	RIO_SBUS_IDENT	"JBPGK#\0\0\0\0\0\0\0\0\0\0"
+
+#define	RIO_SBUS_CFG_BOOTRAM	0x01		/* Boot from RAM, else Link */
+#define	RIO_SBUS_CFG_BUSENABLE	0x02		/* Enable processor bus */
+#define	RIO_SBUS_CFG_INTENABLE	0x04		/* Interrupt enable, else disable */
+#define	RIO_SBUS_CFG_IRQMASK	0x38		/* Interrupt mask */
+#define	  RIO_SBUS_CFG_IRQNONE	0x00		/* No Interrupt */
+#define	  RIO_SBUS_CFG_IRQ7	0x38		/* Interrupt Level 7 */
+#define	  RIO_SBUS_CFG_IRQ6	0x30		/* Interrupt Level 6 */
+#define	  RIO_SBUS_CFG_IRQ5	0x28		/* Interrupt Level 5 */
+#define	  RIO_SBUS_CFG_IRQ4	0x20		/* Interrupt Level 4 */
+#define	  RIO_SBUS_CFG_IRQ3	0x18		/* Interrupt Level 3 */
+#define	  RIO_SBUS_CFG_IRQ2	0x10		/* Interrupt Level 2 */
+#define	  RIO_SBUS_CFG_IRQ1	0x08		/* Interrupt Level 1 */
+#define	RIO_SBUS_CFG_LINK20	0x40		/* 20Mbps link, else 10Mbps */
+#define	RIO_SBUS_CFG_PROC25	0x80		/* 25Mhz processor clock, else 20Mhz */
+
+/*****************************************************************************
+*********************************             ********************************
+*********************************   RIO PCI   ********************************
+*********************************             ********************************
+*****************************************************************************/
+
+/* Control Register Definitions... */
+#define	RIO_PCI_IDENT	"ECDDPGJGJHJRGSK#"
+
+#define	RIO_PCI_CFG_BOOTRAM	0x01		/* Boot from RAM, else Link */
+#define	RIO_PCI_CFG_BUSENABLE	0x02		/* Enable processor bus */
+#define	RIO_PCI_CFG_INTENABLE	0x04		/* Interrupt enable, else disable */
+#define	RIO_PCI_CFG_LINK20	0x40		/* 20Mbps link, else 10Mbps */
+#define	RIO_PCI_CFG_PROC25	0x80		/* 25Mhz processor clock, else 20Mhz */
+
+/* PCI Definitions... */
+#define	SPX_VENDOR_ID		0x11CB		/* Assigned by the PCI SIG */
+#define	SPX_DEVICE_ID		0x8000		/* RIO bridge boards */
+#define	SPX_PLXDEVICE_ID	0x2000		/* PLX bridge boards */
+#define	SPX_SUB_VENDOR_ID	SPX_VENDOR_ID	/* Same as vendor id */
+#define	RIO_SUB_SYS_ID		0x0800		/* RIO PCI board */
+
+/*****************************************************************************
+*****************************                   ******************************
+*****************************   RIO (Jet) PCI   ******************************
+*****************************                   ******************************
+*****************************************************************************/
+
+/* Control Register Definitions... */
+#define	RIO_PCI2_IDENT	"JET HOST BY KEV#"
+
+#define	RIO_PCI2_CFG_BUSENABLE	0x02		/* Enable processor bus */
+#define	RIO_PCI2_CFG_INTENABLE	0x04		/* Interrupt enable, else disable */
+
+/* PCI Definitions... */
+#define	RIO2_SUB_SYS_ID		0x0100		/* RIO (Jet) PCI board */
+
+#endif						/*_rioboard_h */
+
+/* End of RIOBOARD.H */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/rioboot.c linux.15p9/drivers/char/rio/rioboot.c
--- linux.vanilla/drivers/char/rio/rioboot.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/rioboot.c	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,1330 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: rioboot.c
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 10:33:36
+**	Retrieved	: 11/6/98 10:33:48
+**
+**  ident @(#)rioboot.c	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifdef SCCS_LABELS
+static char *_rioboot_c_sccs_ = "@(#)rioboot.c	1.3";
+#endif
+
+#define __NO_VERSION__
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/malloc.h>
+#include <linux/errno.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/string.h>
+#include <asm/semaphore.h>
+
+
+#include <linux/termios.h>
+#include <linux/serial.h>
+
+#include <linux/compatmac.h>
+#include <linux/generic_serial.h>
+
+
+
+#include "linux_compat.h"
+#include "rio_linux.h"
+#include "typdef.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "top.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "riotypes.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "error.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+
+
+static uchar
+RIOAtVec2Ctrl[] =
+{
+	/* 0 */  INTERRUPT_DISABLE,
+	/* 1 */  INTERRUPT_DISABLE,
+	/* 2 */  INTERRUPT_DISABLE,
+	/* 3 */  INTERRUPT_DISABLE,
+	/* 4 */  INTERRUPT_DISABLE,
+	/* 5 */  INTERRUPT_DISABLE,
+	/* 6 */  INTERRUPT_DISABLE,
+	/* 7 */  INTERRUPT_DISABLE,
+	/* 8 */  INTERRUPT_DISABLE,
+	/* 9 */  IRQ_9|INTERRUPT_ENABLE,
+	/* 10 */ INTERRUPT_DISABLE,
+	/* 11 */ IRQ_11|INTERRUPT_ENABLE,
+	/* 12 */ IRQ_12|INTERRUPT_ENABLE,
+	/* 13 */ INTERRUPT_DISABLE,
+	/* 14 */ INTERRUPT_DISABLE,
+	/* 15 */ IRQ_15|INTERRUPT_ENABLE
+};
+
+/*
+** Load in the RTA boot code.
+*/
+int
+RIOBootCodeRTA(p, rbp)
+struct rio_info *	p;
+struct DownLoad *	rbp; 
+{
+	int offset;
+
+	/* Linux doesn't allow you to disable interrupts during a
+	   "copyin". (Crash when a pagefault occurs). */
+	/* disable(oldspl); */
+	
+	rio_dprint(RIO_DEBUG_BOOT, ("Data at user address 0x%x\n",(int)rbp->DataP));
+
+	/*
+	** Check that we have set asside enough memory for this
+	*/
+	if ( rbp->Count > SIXTY_FOUR_K ) {
+		rio_dprint(RIO_DEBUG_BOOT, ("RTA Boot Code Too Large!\n"));
+		p->RIOError.Error = HOST_FILE_TOO_LARGE;
+		/* restore(oldspl); */
+		return ENOMEM;
+	}
+
+	if ( p->RIOBooting ) {
+		rio_dprint(RIO_DEBUG_BOOT, ("RTA Boot Code : BUSY BUSY BUSY!\n"));
+		p->RIOError.Error = BOOT_IN_PROGRESS;
+		/* restore(oldspl); */
+		return EBUSY;
+	}
+
+	/*
+	** The data we load in must end on a (RTA_BOOT_DATA_SIZE) byte boundary,
+	** so calculate how far we have to move the data up the buffer
+	** to achieve this.
+	*/
+	offset = (RTA_BOOT_DATA_SIZE - (rbp->Count % RTA_BOOT_DATA_SIZE)) % 
+							RTA_BOOT_DATA_SIZE;
+
+	/*
+	** Be clean, and clear the 'unused' portion of the boot buffer,
+	** because it will (eventually) be part of the Rta run time environment
+	** and so should be zeroed.
+	*/
+	bzero( (caddr_t)p->RIOBootPackets, offset );
+
+	/*
+	** Copy the data from user space.
+	*/
+
+	if ( copyin((int)rbp->DataP,((caddr_t)(p->RIOBootPackets))+offset,
+				rbp->Count) ==COPYFAIL ) {
+		rio_dprint(RIO_DEBUG_BOOT, ("Bad data copy from user space\n"));
+		p->RIOError.Error = COPYIN_FAILED;
+		/* restore(oldspl); */
+		return EFAULT;
+	}
+
+	/*
+	** Make sure that our copy of the size includes that offset we discussed
+	** earlier.
+	*/
+	p->RIONumBootPkts = (rbp->Count+offset)/RTA_BOOT_DATA_SIZE;
+	p->RIOBootCount   = rbp->Count;
+
+	/* restore(oldspl); */
+	return 0;
+}
+
+
+/*
+** Load in the host boot code - load it directly onto all halted hosts
+** of the correct type.
+**
+** Put your rubber pants on before messing with this code - even the magic
+** numbers have trouble understanding what they are doing here.
+*/
+int
+RIOBootCodeHOST(p, rbp)
+struct rio_info *	p;
+register struct DownLoad *rbp;
+{
+	register struct Host *HostP;
+	register caddr_t Cad;
+	register PARM_MAP *ParmMapP;
+	register int RupN;
+	int PortN;
+	uint host;
+	caddr_t StartP;
+	BYTE *DestP;
+	int wait_count;
+	ushort OldParmMap;
+	ushort offset;	/* It is very important that this is a ushort */
+	/* uint byte; */
+	caddr_t DownCode = NULL;
+	unsigned long flags;
+
+	HostP = NULL; /* Assure the compiler we've initialized it */
+	for ( host=0; host<p->RIONumHosts; host++ ) {
+		rio_dprint(RIO_DEBUG_BOOT, ("Attempt to boot host %d\n",host));
+		HostP = &p->RIOHosts[host];
+
+		if ( (HostP->Flags & RUN_STATE) != RC_WAITING ) {
+			rio_dprint(RIO_DEBUG_BOOT, ("%s %d already running\n","Host",host));
+			continue;
+		}
+
+		/*
+		** Grab a 32 bit pointer to the card.
+		*/
+		Cad = HostP->Caddr;
+
+		/*
+		** We are going to (try) and load in rbp->Count bytes.
+		** The last byte will reside at p->RIOConf.HostLoadBase-1;
+		** Therefore, we need to start copying at address
+		** (caddr+p->RIOConf.HostLoadBase-rbp->Count)
+		*/
+		StartP = (caddr_t)&Cad[p->RIOConf.HostLoadBase-rbp->Count];
+
+		rio_dprint(RIO_DEBUG_BOOT,  ("kernel virtual address for host is 0x%x\n", (int)Cad ) );
+		rio_dprint(RIO_DEBUG_BOOT,  ("kernel virtual address for download is 0x%x\n", (int)StartP ) );
+		rio_dprint(RIO_DEBUG_BOOT, ("host loadbase is 0x%x\n",p->RIOConf.HostLoadBase));
+		rio_dprint(RIO_DEBUG_BOOT,  ("size of download is 0x%x\n", rbp->Count ) );
+
+		if ( p->RIOConf.HostLoadBase < rbp->Count ) {
+			rio_dprint(RIO_DEBUG_BOOT, ("Bin too large\n"));
+			p->RIOError.Error = HOST_FILE_TOO_LARGE;
+			return EFBIG;
+		}
+		/*
+		** Ensure that the host really is stopped.
+		** Disable it's external bus & twang its reset line.
+		*/
+		RIOHostReset( HostP->Type, (struct DpRam *)HostP->CardP, HostP->Slot );
+
+		/*
+		** Copy the data directly from user space to the SRAM.
+		** This ain't going to be none too clever if the download
+		** code is bigger than this segment.
+		*/
+		rio_dprint(RIO_DEBUG_BOOT, ("Copy in code\n"));
+
+		/*
+		** PCI hostcard can't cope with 32 bit accesses and so need to copy 
+		** data to a local buffer, and then dripfeed the card.
+		*/
+		if ( HostP->Type == RIO_PCI ) {
+		  /* int offset; */
+
+			DownCode = sysbrk(rbp->Count);
+			if ( !DownCode ) {
+				rio_dprint(RIO_DEBUG_BOOT, ("No system memory available\n"));
+				p->RIOError.Error = NOT_ENOUGH_CORE_FOR_PCI_COPY;
+				return ENOMEM;
+			}
+			bzero(DownCode, rbp->Count);
+
+			if ( copyin((int)rbp->DataP,DownCode,rbp->Count)==COPYFAIL ) {
+				rio_dprint(RIO_DEBUG_BOOT, ("Bad copyin of host data\n"));
+				p->RIOError.Error = COPYIN_FAILED;
+				return EFAULT;
+			}
+
+			HostP->Copy( DownCode, StartP, rbp->Count );
+
+			sysfree( DownCode, rbp->Count );
+		}
+		else if ( copyin((int)rbp->DataP,StartP,rbp->Count)==COPYFAIL ) {
+			rio_dprint(RIO_DEBUG_BOOT, ("Bad copyin of host data\n"));
+			p->RIOError.Error = COPYIN_FAILED;
+			return EFAULT;
+		}
+
+		rio_dprint(RIO_DEBUG_BOOT, ("Copy completed\n"));
+
+		/*
+		**			S T O P !
+		**
+		** Upto this point the code has been fairly rational, and possibly
+		** even straight forward. What follows is a pile of crud that will
+		** magically turn into six bytes of transputer assembler. Normally
+		** you would expect an array or something, but, being me, I have
+		** chosen [been told] to use a technique whereby the startup code
+		** will be correct if we change the loadbase for the code. Which
+		** brings us onto another issue - the loadbase is the *end* of the
+		** code, not the start.
+		**
+		** If I were you I wouldn't start from here.
+		*/
+
+		/*
+		** We now need to insert a short boot section into
+		** the memory at the end of Sram2. This is normally (de)composed
+		** of the last eight bytes of the download code. The
+		** download has been assembled/compiled to expect to be
+		** loaded from 0x7FFF downwards. We have loaded it
+		** at some other address. The startup code goes into the small
+		** ram window at Sram2, in the last 8 bytes, which are really
+		** at addresses 0x7FF8-0x7FFF.
+		**
+		** If the loadbase is, say, 0x7C00, then we need to branch to
+		** address 0x7BFE to run the host.bin startup code. We assemble
+		** this jump manually.
+		**
+		** The two byte sequence 60 08 is loaded into memory at address
+		** 0x7FFE,F. This is a local branch to location 0x7FF8 (60 is nfix 0,
+		** which adds '0' to the .O register, complements .O, and then shifts
+		** it left by 4 bit positions, 08 is a jump .O+8 instruction. This will
+		** add 8 to .O (which was 0xFFF0), and will branch RELATIVE to the new
+		** location. Now, the branch starts from the value of .PC (or .IP or
+		** whatever the bloody register is called on this chip), and the .PC
+		** will be pointing to the location AFTER the branch, in this case
+		** .PC == 0x8000, so the branch will be to 0x8000+0xFFF8 = 0x7FF8.
+		**
+		** A long branch is coded at 0x7FF8. This consists of loading a four
+		** byte offset into .O using nfix (as above) and pfix operators. The
+		** pfix operates in exactly the same way as the nfix operator, but
+		** without the complement operation. The offset, of course, must be
+		** relative to the address of the byte AFTER the branch instruction,
+		** which will be (urm) 0x7FFC, so, our final destination of the branch
+		** (loadbase-2), has to be reached from here. Imagine that the loadbase
+		** is 0x7C00 (which it is), then we will need to branch to 0x7BFE (which
+		** is the first byte of the initial two byte short local branch of the
+		** download code).
+		**
+		** To code a jump from 0x7FFC (which is where the branch will start
+		** from) to 0x7BFE, we will need to branch 0xFC02 bytes (0x7FFC+0xFC02)=
+		** 0x7BFE.
+		** This will be coded as four bytes:
+		** 60 2C 20 02
+		** being nfix .O+0
+		**	   pfix .O+C
+		**	   pfix .O+0
+		**	   jump .O+2
+		**
+		** The nfix operator is used, so that the startup code will be
+		** compatible with the whole Tp family. (lies, damn lies, it'll never
+		** work in a month of Sundays).
+		**
+		** The nfix nyble is the 1s compliment of the nyble value you
+		** want to load - in this case we wanted 'F' so we nfix loaded '0'.
+		*/
+
+
+		/*
+		** Dest points to the top 8 bytes of Sram2. The Tp jumps
+		** to 0x7FFE at reset time, and starts executing. This is
+		** a short branch to 0x7FF8, where a long branch is coded.
+		*/
+
+		DestP = (BYTE *)&Cad[0x7FF8];	/* <<<---- READ THE ABOVE COMMENTS */
+
+#define	NFIX(N)	(0x60 | (N))	/* .O  = (~(.O + N))<<4 */
+#define	PFIX(N)	(0x20 | (N))	/* .O  =   (.O + N)<<4  */
+#define	JUMP(N)	(0x00 | (N))	/* .PC =   .PC + .O	 */
+
+		/*
+		** 0x7FFC is the address of the location following the last byte of
+		** the four byte jump instruction.
+		** READ THE ABOVE COMMENTS
+		**
+		** offset is (TO-FROM) % MEMSIZE, but with compound buggering about.
+		** Memsize is 64K for this range of Tp, so offset is a short (unsigned,
+		** cos I don't understand 2's complement).
+		*/
+		offset = (p->RIOConf.HostLoadBase-2)-0x7FFC;
+		WBYTE( DestP[0] , NFIX(((ushort)(~offset) >> (ushort)12) & 0xF) );
+		WBYTE( DestP[1] , PFIX(( offset >> 8) & 0xF) );
+		WBYTE( DestP[2] , PFIX(( offset >> 4) & 0xF) );
+		WBYTE( DestP[3] , JUMP( offset & 0xF) );
+
+		WBYTE( DestP[6] , NFIX(0) );
+		WBYTE( DestP[7] , JUMP(8) );
+
+		rio_dprint(RIO_DEBUG_BOOT, ("host loadbase is 0x%x\n",p->RIOConf.HostLoadBase));
+		rio_dprint(RIO_DEBUG_BOOT, ("startup offset is 0x%x\n",offset));
+
+		/*
+		** Flag what is going on
+		*/
+		HostP->Flags &= ~RUN_STATE;
+		HostP->Flags |= RC_STARTUP;
+
+		/*
+		** Grab a copy of the current ParmMap pointer, so we
+		** can tell when it has changed.
+		*/
+		OldParmMap = RWORD(HostP->__ParmMapR);
+
+		rio_dprint(RIO_DEBUG_BOOT, ("Original parmmap is 0x%x\n",OldParmMap));
+
+		/*
+		** And start it running (I hope).
+		** As there is nothing dodgy or obscure about the
+		** above code, this is guaranteed to work every time.
+		*/
+		rio_dprint(RIO_DEBUG_BOOT,  ("Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n",
+		    HostP->Type, HostP->Mode, HostP->Ivec ) );
+
+		switch ( HostP->Type ) {
+			case RIO_AT:
+				rio_dprint(RIO_DEBUG_BOOT, ("Start ISA card running\n"));
+				WBYTE(HostP->Control, 
+					BOOT_FROM_RAM | EXTERNAL_BUS_ON
+					| HostP->Mode
+					| RIOAtVec2Ctrl[HostP->Ivec & 0xF] );
+				break;
+
+#ifdef FUTURE_RELEASE
+			case RIO_MCA:
+				/*
+				** MCA handles IRQ vectors differently, so we don't write 
+				** them to this register.
+				*/
+				rio_dprint(RIO_DEBUG_BOOT, ("Start MCA card running\n"));
+				WBYTE(HostP->Control, McaTpBootFromRam | McaTpBusEnable | HostP->Mode);
+				break;
+
+			case RIO_EISA:
+				/*
+				** EISA is totally different and expects OUTBZs to turn it on.
+				*/
+				rio_dprint(RIO_DEBUG_BOOT, NULL,DBG_DAEMON,"Start EISA card running\n");
+				OUTBZ( HostP->Slot, EISA_CONTROL_PORT, HostP->Mode | RIOEisaVec2Ctrl[HostP->Ivec] | EISA_TP_RUN | EISA_TP_BUS_ENABLE | EISA_TP_BOOT_FROM_RAM );
+				break;
+#endif
+
+			case RIO_PCI:
+				/*
+				** PCI is much the same as MCA. Everything is once again memory
+				** mapped, so we are writing to memory registers instead of io
+				** ports.
+				*/
+				rio_dprint(RIO_DEBUG_BOOT, ("Start PCI card running\n"));
+				WBYTE(HostP->Control, PCITpBootFromRam | PCITpBusEnable | HostP->Mode);
+				break;
+			default:
+				rio_dprint(RIO_DEBUG_BOOT, ("Unknown host type %d\n",HostP->Type));
+				break;
+		}
+		rio_dprint(RIO_DEBUG_BOOT, ("Set control port\n"));
+
+		/*
+		** Now, wait for upto five seconds for the Tp to setup the parmmap
+		** pointer:
+		*/
+		for ( wait_count=0; (wait_count<p->RIOConf.StartupTime)&&
+				(RWORD(HostP->__ParmMapR)==OldParmMap); wait_count++ ) {
+			rio_dprint(RIO_DEBUG_BOOT, ("Checkout %d, 0x%x\n",wait_count,RWORD(HostP->__ParmMapR)));
+			delay(HostP, HUNDRED_MS);
+		}
+
+		/*
+		** If the parmmap pointer is unchanged, then the host code
+		** has crashed & burned in a really spectacular way
+		*/
+		if ( RWORD(HostP->__ParmMapR) == OldParmMap ) {
+			rio_dprint(RIO_DEBUG_BOOT, ("parmmap 0x%x\n", RWORD(HostP->__ParmMapR)));
+			rio_dprint(RIO_DEBUG_BOOT, ("RIO Mesg Run Fail\n"));
+
+#define	HOST_DISABLE \
+		HostP->Flags &= ~RUN_STATE; \
+		HostP->Flags |= RC_STUFFED; \
+		RIOHostReset( HostP->Type, (struct DpRam *)HostP->CardP, HostP->Slot );\
+		continue
+
+			HOST_DISABLE;
+		}
+
+		rio_dprint(RIO_DEBUG_BOOT, ("Running 0x%x\n",RWORD(HostP->__ParmMapR)));
+
+		/*
+		** Well, the board thought it was OK, and setup its parmmap
+		** pointer. For the time being, we will pretend that this
+		** board is running, and check out what the error flag says.
+		*/
+
+		/*
+		** Grab a 32 bit pointer to the parmmap structure
+		*/
+		ParmMapP = (PARM_MAP *)RIO_PTR(Cad,RWORD(HostP->__ParmMapR));
+		rio_dprint(RIO_DEBUG_BOOT, ("ParmMapP : %x\n", (int)ParmMapP));
+		ParmMapP = (PARM_MAP *)((unsigned long)Cad + 
+						(unsigned long)((RWORD((HostP->__ParmMapR))) & 0xFFFF)); 
+		rio_dprint(RIO_DEBUG_BOOT, ("ParmMapP : %x\n", (int)ParmMapP));
+
+		/*
+		** The links entry should be 0xFFFF; we set it up
+		** with a mask to say how many PHBs to use, and 
+		** which links to use.
+		*/
+		if ( (RWORD(ParmMapP->links) & 0xFFFF) != 0xFFFF ) {
+			rio_dprint(RIO_DEBUG_BOOT, ("RIO Mesg Run Fail %s\n", HostP->Name));
+			rio_dprint(RIO_DEBUG_BOOT, ("Links = 0x%x\n",RWORD(ParmMapP->links)));
+			HOST_DISABLE;
+		}
+
+		WWORD(ParmMapP->links , RIO_LINK_ENABLE);
+
+		/*
+		** now wait for the card to set all the parmmap->XXX stuff
+		** this is a wait of upto two seconds....
+		*/
+		rio_dprint(RIO_DEBUG_BOOT, ("Looking for init_done - %d ticks\n",p->RIOConf.StartupTime));
+		HostP->timeout_id = 0;
+		for ( wait_count=0; (wait_count<p->RIOConf.StartupTime) && 
+						!RWORD(ParmMapP->init_done); wait_count++ ) {
+			rio_dprint(RIO_DEBUG_BOOT, ("Waiting for init_done\n"));
+			delay(HostP, HUNDRED_MS);
+		}
+		rio_dprint(RIO_DEBUG_BOOT, ("OK! init_done!\n"));
+
+		if (RWORD(ParmMapP->error) != E_NO_ERROR || 
+							!RWORD(ParmMapP->init_done) ) {
+			rio_dprint(RIO_DEBUG_BOOT, ("RIO Mesg Run Fail %s\n", HostP->Name));
+			rio_dprint(RIO_DEBUG_BOOT, ("Timedout waiting for init_done\n"));
+			HOST_DISABLE;
+		}
+
+		rio_dprint(RIO_DEBUG_BOOT, ("Got init_done\n"));
+
+		/*
+		** It runs! It runs!
+		*/
+		rio_dprint(RIO_DEBUG_BOOT, ("Host ID %x Running\n",HostP->UniqueNum));
+
+		/*
+		** set the time period between interrupts.
+		*/
+		WWORD(ParmMapP->timer, (short)p->RIOConf.Timer );
+
+		/*
+		** Translate all the 16 bit pointers in the __ParmMapR into
+		** 32 bit pointers for the driver.
+		*/
+		HostP->ParmMapP	 =	ParmMapP;
+		HostP->PhbP		 =	(PHB*)RIO_PTR(Cad,RWORD(ParmMapP->phb_ptr));
+		HostP->RupP		 =	(RUP*)RIO_PTR(Cad,RWORD(ParmMapP->rups));
+		HostP->PhbNumP	  = (ushort*)RIO_PTR(Cad,RWORD(ParmMapP->phb_num_ptr));
+		HostP->LinkStrP	 =	(LPB*)RIO_PTR(Cad,RWORD(ParmMapP->link_str_ptr));
+
+		/*
+		** point the UnixRups at the real Rups
+		*/
+		for ( RupN = 0; RupN<MAX_RUP; RupN++ ) {
+			HostP->UnixRups[RupN].RupP		= &HostP->RupP[RupN];
+			HostP->UnixRups[RupN].Id		  = RupN+1;
+			HostP->UnixRups[RupN].BaseSysPort = NO_PORT;
+		}
+
+		for ( RupN = 0; RupN<LINKS_PER_UNIT; RupN++ ) {
+			HostP->UnixRups[RupN+MAX_RUP].RupP	= &HostP->LinkStrP[RupN].rup;
+			HostP->UnixRups[RupN+MAX_RUP].Id  = 0;
+			HostP->UnixRups[RupN+MAX_RUP].BaseSysPort = NO_PORT;
+		}
+
+		/*
+		** point the PortP->Phbs at the real Phbs
+		*/
+		for ( PortN=p->RIOFirstPortsMapped; 
+				PortN<p->RIOLastPortsMapped+PORTS_PER_RTA; PortN++ ) {
+			if ( p->RIOPortp[PortN]->HostP == HostP ) {
+				struct Port *PortP = p->RIOPortp[PortN];
+				struct PHB *PhbP;
+				/* int oldspl; */
+
+				if ( !PortP->Mapped )
+					continue;
+
+				PhbP = &HostP->PhbP[PortP->HostPort];
+				rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+				PortP->PhbP = PhbP;
+
+				PortP->TxAdd	= (WORD *)RIO_PTR(Cad,RWORD(PhbP->tx_add));
+				PortP->TxStart  = (WORD *)RIO_PTR(Cad,RWORD(PhbP->tx_start));
+				PortP->TxEnd	= (WORD *)RIO_PTR(Cad,RWORD(PhbP->tx_end));
+				PortP->RxRemove = (WORD *)RIO_PTR(Cad,RWORD(PhbP->rx_remove));
+				PortP->RxStart  = (WORD *)RIO_PTR(Cad,RWORD(PhbP->rx_start));
+				PortP->RxEnd	= (WORD *)RIO_PTR(Cad,RWORD(PhbP->rx_end));
+
+				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+				/*
+				** point the UnixRup at the base SysPort
+				*/
+				if ( !(PortN % PORTS_PER_RTA) )
+					HostP->UnixRups[PortP->RupNum].BaseSysPort = PortN;
+			}
+		}
+
+		rio_dprint(RIO_DEBUG_BOOT, ("Set the card running... \n"));
+		/*
+		** last thing - show the world that everything is in place
+		*/
+		HostP->Flags &= ~RUN_STATE;
+		HostP->Flags |= RC_RUNNING;
+	}
+	/*
+	** MPX always uses a poller. This is actually patched into the system
+	** configuration and called directly from each clock tick.
+	**
+	*/
+	p->RIOPolling = 1;
+
+	p->RIOSystemUp++;
+	
+	rio_dprint(RIO_DEBUG_BOOT, ("Done everything %x\n", HostP->Ivec));
+	return 0;
+}
+
+
+
+/*
+** Boot an RTA. If we have successfully processed this boot, then
+** return 1. If we havent, then return 0.
+*/
+int
+RIOBootRup( p, Rup, HostP, PacketP)
+struct rio_info *	p;
+uint Rup;
+struct Host *HostP;
+struct PKT *PacketP; 
+{
+	struct PktCmd *PktCmdP = (struct PktCmd *)PacketP->data;
+	struct PktCmd_M *PktReplyP;
+	struct CmdBlk *CmdBlkP;
+	uint sequence;
+
+#ifdef CHECK
+	CheckHost(Host);
+	CheckRup(Rup);
+	CheckHostP(HostP);
+	CheckPacketP(PacketP);
+#endif
+
+	/*
+	** If we haven't been told what to boot, we can't boot it.
+	*/
+	if ( p->RIONumBootPkts == 0 ) {
+		rio_dprint(RIO_DEBUG_BOOT, ("No RTA code to download yet\n"));
+		return 0;
+	}
+
+	/* rio_dprint(RIO_DEBUG_BOOT, NULL,DBG_BOOT,"Incoming command packet\n"); */
+	/* ShowPacket( DBG_BOOT, PacketP ); */
+
+	/*
+	** Special case of boot completed - if we get one of these then we
+	** don't need a command block. For all other cases we do, so handle
+	** this first and then get a command block, then handle every other
+	** case, relinquishing the command block if disaster strikes!
+	*/
+	if ( (RBYTE(PacketP->len) & PKT_CMD_BIT) && 
+			(RBYTE(PktCmdP->Command)==BOOT_COMPLETED) )
+		return RIOBootComplete(p, HostP, Rup, PktCmdP );
+
+	/*
+	** try to unhook a command block from the command free list.
+	*/
+	if ( !(CmdBlkP = RIOGetCmdBlk()) ) {
+		rio_dprint(RIO_DEBUG_BOOT, ("No command blocks to boot RTA! come back later.\n"));
+		return 0;
+	}
+
+	/*
+	** Fill in the default info on the command block
+	*/
+	CmdBlkP->Packet.dest_unit = Rup < (ushort)MAX_RUP ? Rup : 0;
+	CmdBlkP->Packet.dest_port = BOOT_RUP;
+	CmdBlkP->Packet.src_unit  = 0;
+	CmdBlkP->Packet.src_port  = BOOT_RUP;
+
+	CmdBlkP->PreFuncP = CmdBlkP->PostFuncP = NULL;
+	PktReplyP = (struct PktCmd_M *)CmdBlkP->Packet.data;
+
+	/*
+	** process COMMANDS on the boot rup!
+	*/
+	if ( RBYTE(PacketP->len) & PKT_CMD_BIT ) {
+		/*
+		** We only expect one type of command - a BOOT_REQUEST!
+		*/
+		if ( RBYTE(PktCmdP->Command) != BOOT_REQUEST ) {
+			rio_dprint(RIO_DEBUG_BOOT, ("Unexpected command %d on BOOT RUP %d of host %d\n", 
+						PktCmdP->Command,Rup,HostP-p->RIOHosts));
+			ShowPacket( DBG_BOOT, PacketP );
+			RIOFreeCmdBlk( CmdBlkP );
+			return 1;
+		}
+
+		/*
+		** Build a Boot Sequence command block
+		**
+		** 02.03.1999 ARG - ESIL 0820 fix
+		** We no longer need to use "Boot Mode", we'll always allow
+		** boot requests - the boot will not complete if the device
+		** appears in the bindings table.
+		** So, this conditional is not required ...
+		**
+		if (p->RIOBootMode == RC_BOOT_NONE)
+			**
+			** If the system is in slave mode, and a boot request is
+			** received, set command to BOOT_ABORT so that the boot
+			** will not complete.
+			**
+			PktReplyP->Command			 = BOOT_ABORT;
+		else
+		**
+		** We'll just (always) set the command field in packet reply
+		** to allow an attempted boot sequence :
+		*/
+		PktReplyP->Command = BOOT_SEQUENCE;
+
+		PktReplyP->BootSequence.NumPackets = p->RIONumBootPkts;
+		PktReplyP->BootSequence.LoadBase   = p->RIOConf.RtaLoadBase;
+		PktReplyP->BootSequence.CodeSize   = p->RIOBootCount;
+
+		CmdBlkP->Packet.len				= BOOT_SEQUENCE_LEN | PKT_CMD_BIT;
+
+		bcopy("BOOT",(void *)&CmdBlkP->Packet.data[BOOT_SEQUENCE_LEN],4);
+
+		rio_dprint(RIO_DEBUG_BOOT, ("Boot RTA on Host %d Rup %d - %d (0x%x) packets to 0x%x\n",
+			HostP-p->RIOHosts, Rup, p->RIONumBootPkts, p->RIONumBootPkts, 
+								p->RIOConf.RtaLoadBase));
+
+		/*
+		** If this host is in slave mode, send the RTA an invalid boot
+		** sequence command block to force it to kill the boot. We wait
+		** for half a second before sending this packet to prevent the RTA
+		** attempting to boot too often. The master host should then grab
+		** the RTA and make it its own.
+		*/
+		p->RIOBooting++;
+		RIOQueueCmdBlk( HostP, Rup, CmdBlkP );
+		return 1;
+	}
+
+	/*
+	** It is a request for boot data.
+	*/
+	sequence = RWORD(PktCmdP->Sequence);
+
+	rio_dprint(RIO_DEBUG_BOOT, ("Boot block %d on Host %d Rup%d\n",sequence,HostP-p->RIOHosts,Rup));
+
+	if ( sequence >= p->RIONumBootPkts ) {
+		rio_dprint(RIO_DEBUG_BOOT, ("Got a request for packet %d, max is %d\n", sequence, 
+					p->RIONumBootPkts));
+		ShowPacket( DBG_BOOT, PacketP );
+	}
+
+	PktReplyP->Sequence = sequence;
+
+	bcopy( p->RIOBootPackets[ p->RIONumBootPkts - sequence - 1 ], 
+				PktReplyP->BootData, RTA_BOOT_DATA_SIZE );
+
+	CmdBlkP->Packet.len = PKT_MAX_DATA_LEN;
+	ShowPacket( DBG_BOOT, &CmdBlkP->Packet );
+	RIOQueueCmdBlk( HostP, Rup, CmdBlkP );
+	return 1;
+}
+
+/*
+** This function is called when an RTA been booted.
+** If booted by a host, HostP->HostUniqueNum is the booting host.
+** If booted by an RTA, HostP->Mapping[Rup].RtaUniqueNum is the booting RTA.
+** RtaUniq is the booted RTA.
+*/
+int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, struct PktCmd *PktCmdP )
+{
+	struct Map	*MapP = NULL;
+	struct Map	*MapP2 = NULL;
+	int	Flag;
+	int	found;
+	int	host, rta;
+	int	EmptySlot = -1;
+	int	entry, entry2;
+	char	*MyType, *MyName;
+	uint	MyLink;
+	ushort	RtaType;
+	uint	RtaUniq = (RBYTE(PktCmdP->UniqNum[0])) +
+			  (RBYTE(PktCmdP->UniqNum[1]) << 8) +
+			  (RBYTE(PktCmdP->UniqNum[2]) << 16) +
+			  (RBYTE(PktCmdP->UniqNum[3]) << 24);
+
+	/* Was RIOBooting-- . That's bad. If an RTA sends two of them, the
+	   driver will never think that the RTA has booted... -- REW */
+	p->RIOBooting = 0;
+
+	rio_dprint(RIO_DEBUG_BOOT, ("RTA Boot completed - BootInProgress now %d\n", p->RIOBooting));
+
+	/*
+	** Determine type of unit (16/8 port RTA).
+	*/
+	RtaType = GetUnitType(RtaUniq);
+        if ( Rup >= (ushort)MAX_RUP ) {
+	    rio_dprint(RIO_DEBUG_BOOT, ("RIO: Host %s has booted an RTA(%d) on link %c\n",
+	     HostP->Name, 8 * RtaType, RBYTE(PktCmdP->LinkNum)+'A' ));
+	} else {
+	    rio_dprint(RIO_DEBUG_BOOT, ("RIO: RTA %s has booted an RTA(%d) on link %c\n",
+	     HostP->Mapping[Rup].Name, 8 * RtaType,
+	     RBYTE(PktCmdP->LinkNum)+'A'));
+	}
+
+	rio_dprint(RIO_DEBUG_BOOT, ("UniqNum is 0x%x\n",RtaUniq));
+
+        if ( ( RtaUniq == 0x00000000 ) || ( RtaUniq == 0xffffffff ) )
+	{
+	    rio_dprint(RIO_DEBUG_BOOT, ( "Illegal RTA Uniq Number\n"));
+	    return TRUE;
+	}
+
+	/*
+	** If this RTA has just booted an RTA which doesn't belong to this
+	** system, or the system is in slave mode, do not attempt to create
+	** a new table entry for it.
+	*/
+	if (!RIOBootOk(p, HostP, RtaUniq))
+	{
+	    MyLink = RBYTE(PktCmdP->LinkNum);
+	    if (Rup < (ushort) MAX_RUP)
+	    {
+		/*
+		** RtaUniq was clone booted (by this RTA). Instruct this RTA
+		** to hold off further attempts to boot on this link for 30
+		** seconds.
+		*/
+		if (RIOSuspendBootRta(HostP, HostP->Mapping[Rup].ID, MyLink))
+		{
+		    rio_dprint(RIO_DEBUG_BOOT, ("RTA failed to suspend booting on link %c\n",
+		     'A' + MyLink));
+		}
+	    }
+	    else
+	    {
+		/*
+		** RtaUniq was booted by this host. Set the booting link
+		** to hold off for 30 seconds to give another unit a
+		** chance to boot it.
+		*/
+		WWORD(HostP->LinkStrP[MyLink].WaitNoBoot, 30);
+	    }
+	    rio_dprint(RIO_DEBUG_BOOT, ("RTA %x not owned - suspend booting down link %c on unit %x\n",
+	      RtaUniq, 'A' + MyLink, HostP->Mapping[Rup].RtaUniqueNum));
+	    return TRUE;
+	}
+
+	/*
+	** Check for a SLOT_IN_USE entry for this RTA attached to the
+	** current host card in the driver table.
+	**
+	** If it exists, make a note that we have booted it. Other parts of
+	** the driver are interested in this information at a later date,
+	** in particular when the booting RTA asks for an ID for this unit,
+	** we must have set the BOOTED flag, and the NEWBOOT flag is used
+	** to force an open on any ports that where previously open on this
+	** unit.
+	*/
+        for ( entry=0; entry<MAX_RUP; entry++ )
+	{
+	    uint sysport;
+
+	    if ((HostP->Mapping[entry].Flags & SLOT_IN_USE) && 
+	       (HostP->Mapping[entry].RtaUniqueNum==RtaUniq))
+	    {
+	        HostP->Mapping[entry].Flags |= RTA_BOOTED|RTA_NEWBOOT;
+#if NEED_TO_FIX
+		RIO_SV_BROADCAST(HostP->svFlags[entry]);
+#endif
+		if ( (sysport=HostP->Mapping[entry].SysPort) != NO_PORT )
+		{
+		   if ( sysport < p->RIOFirstPortsBooted )
+			p->RIOFirstPortsBooted = sysport;
+		   if ( sysport > p->RIOLastPortsBooted )
+			p->RIOLastPortsBooted = sysport;
+		   /*
+		   ** For a 16 port RTA, check the second bank of 8 ports
+		   */
+		   if (RtaType == TYPE_RTA16)
+		   {
+			entry2 = HostP->Mapping[entry].ID2 - 1;
+			HostP->Mapping[entry2].Flags |= RTA_BOOTED|RTA_NEWBOOT;
+#if NEED_TO_FIX
+			RIO_SV_BROADCAST(HostP->svFlags[entry2]);
+#endif
+			sysport = HostP->Mapping[entry2].SysPort;
+			if ( sysport < p->RIOFirstPortsBooted )
+			    p->RIOFirstPortsBooted = sysport;
+			if ( sysport > p->RIOLastPortsBooted )
+			    p->RIOLastPortsBooted = sysport;
+		   }
+		}
+		if (RtaType == TYPE_RTA16) {
+		   rio_dprint(RIO_DEBUG_BOOT, ("RTA will be given IDs %d+%d\n",
+		    entry+1, entry2+1));
+		} else {
+		   rio_dprint(RIO_DEBUG_BOOT, ("RTA will be given ID %d\n",entry+1));
+		}
+		return TRUE;
+	    }
+	}
+
+	rio_dprint(RIO_DEBUG_BOOT, ("RTA not configured for this host\n"));
+
+	if ( Rup >= (ushort)MAX_RUP )
+	{
+	    /*
+	    ** It was a host that did the booting
+	    */
+	    MyType = "Host";
+	    MyName = HostP->Name;
+	}
+	else
+	{
+	    /*
+	    ** It was an RTA that did the booting
+	    */
+	    MyType = "RTA";
+	    MyName = HostP->Mapping[Rup].Name;
+	}
+#ifdef CHECK
+	CheckString(MyType);
+	CheckString(MyName);
+#endif
+
+	MyLink = RBYTE(PktCmdP->LinkNum);
+
+	/*
+	** There is no SLOT_IN_USE entry for this RTA attached to the current
+	** host card in the driver table.
+	**
+	** Check for a SLOT_TENTATIVE entry for this RTA attached to the
+	** current host card in the driver table.
+	**
+	** If we find one, then we re-use that slot.
+	*/
+	for ( entry=0; entry<MAX_RUP; entry++ )
+	{
+	    if ( (HostP->Mapping[entry].Flags & SLOT_TENTATIVE) &&
+		 (HostP->Mapping[entry].RtaUniqueNum == RtaUniq) )
+	    {
+		if (RtaType == TYPE_RTA16)
+		{
+		    entry2 = HostP->Mapping[entry].ID2 - 1;
+		    if ( (HostP->Mapping[entry2].Flags & SLOT_TENTATIVE) &&
+			 (HostP->Mapping[entry2].RtaUniqueNum == RtaUniq) )
+			rio_dprint(RIO_DEBUG_BOOT, ("Found previous tentative slots (%d+%d)\n",
+			 entry, entry2));
+		    else
+			continue;
+		}
+		else
+			rio_dprint(RIO_DEBUG_BOOT, ("Found previous tentative slot (%d)\n",entry));
+		if (! p->RIONoMessage)
+		    cprintf("RTA connected to %s '%s' (%c) not configured.\n",MyType,MyName,MyLink+'A');
+		return TRUE;
+	    }
+	}
+
+	/*
+	** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
+	** attached to the current host card in the driver table.
+	**
+	** Check if there is a SLOT_IN_USE or SLOT_TENTATIVE entry on another
+	** host for this RTA in the driver table.
+	**
+	** For a SLOT_IN_USE entry on another host, we need to delete the RTA
+	** entry from the other host and add it to this host (using some of
+	** the functions from table.c which do this).
+	** For a SLOT_TENTATIVE entry on another host, we must cope with the
+	** following scenario:
+	**
+	** + Plug 8 port RTA into host A. (This creates SLOT_TENTATIVE entry
+	**   in table)
+	** + Unplug RTA and plug into host B. (We now have 2 SLOT_TENTATIVE
+	**   entries)
+	** + Configure RTA on host B. (This slot now becomes SLOT_IN_USE)
+	** + Unplug RTA and plug back into host A.
+	** + Configure RTA on host A. We now have the same RTA configured
+	**   with different ports on two different hosts.
+	*/
+	rio_dprint(RIO_DEBUG_BOOT, ("Have we seen RTA %x before?\n", RtaUniq ));
+	found = 0;
+	Flag = 0; /* Convince the compiler this variable is initialized */
+	for ( host = 0; !found && (host < p->RIONumHosts); host++ )
+	{
+	    for ( rta=0; rta<MAX_RUP; rta++ )
+	    {
+		if ((p->RIOHosts[host].Mapping[rta].Flags &
+		 (SLOT_IN_USE | SLOT_TENTATIVE)) &&
+		 (p->RIOHosts[host].Mapping[rta].RtaUniqueNum==RtaUniq))
+		{
+		    Flag = p->RIOHosts[host].Mapping[rta].Flags;
+		    MapP = &p->RIOHosts[host].Mapping[rta];
+		    if (RtaType == TYPE_RTA16)
+		    {
+			MapP2 = &p->RIOHosts[host].Mapping[MapP->ID2 - 1];
+			rio_dprint(RIO_DEBUG_BOOT, ("This RTA is units %d+%d from host %s\n",
+			 rta+1, MapP->ID2, p->RIOHosts[host].Name ));
+		    }
+		    else
+			rio_dprint(RIO_DEBUG_BOOT, ("This RTA is unit %d from host %s\n",
+			 rta+1, p->RIOHosts[host].Name ));
+		    found = 1;
+		    break;
+		}
+	    }
+	}
+
+	/*
+	** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
+	** attached to the current host card in the driver table.
+	**
+	** If we have not found a SLOT_IN_USE or SLOT_TENTATIVE entry on
+	** another host for this RTA in the driver table...
+	**
+	** Check for a SLOT_IN_USE entry for this RTA in the config table.
+	*/
+	if ( !MapP )
+	{
+	    rio_dprint(RIO_DEBUG_BOOT, ("Look for RTA %x in RIOSavedTable\n",RtaUniq));
+	    for ( rta=0; rta < TOTAL_MAP_ENTRIES; rta++ )
+	    {
+		rio_dprint(RIO_DEBUG_BOOT, ("Check table entry %d (%x)",
+		      rta,
+		      p->RIOSavedTable[rta].RtaUniqueNum ));
+
+		if ( (p->RIOSavedTable[rta].Flags & SLOT_IN_USE) &&
+		 (p->RIOSavedTable[rta].RtaUniqueNum == RtaUniq) )
+		{
+		    MapP = &p->RIOSavedTable[rta];
+		    Flag = p->RIOSavedTable[rta].Flags;
+		    if (RtaType == TYPE_RTA16)
+		    {
+                        for (entry2 = rta + 1; entry2 < TOTAL_MAP_ENTRIES;
+                         entry2++)
+                        {
+                            if (p->RIOSavedTable[entry2].RtaUniqueNum == RtaUniq)
+                                break;
+                        }
+                        MapP2 = &p->RIOSavedTable[entry2];
+                        rio_dprint(RIO_DEBUG_BOOT, ("This RTA is from table entries %d+%d\n",
+                              rta, entry2));
+		    }
+		    else
+			rio_dprint(RIO_DEBUG_BOOT, ("This RTA is from table entry %d\n", rta));
+		    break;
+		}
+	    }
+	}
+
+	/*
+	** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
+	** attached to the current host card in the driver table.
+	**
+	** We may have found a SLOT_IN_USE entry on another host for this
+	** RTA in the config table, or a SLOT_IN_USE or SLOT_TENTATIVE entry
+	** on another host for this RTA in the driver table.
+	**
+	** Check the driver table for room to fit this newly discovered RTA.
+	** RIOFindFreeID() first looks for free slots and if it does not
+	** find any free slots it will then attempt to oust any
+	** tentative entry in the table.
+	*/
+	EmptySlot = 1;
+	if (RtaType == TYPE_RTA16)
+	{
+	    if (RIOFindFreeID(p, HostP, &entry, &entry2) == 0)
+	    {
+		RIODefaultName(p, HostP, entry);
+		FillSlot(entry, entry2, RtaUniq, HostP);
+		EmptySlot = 0;
+	    }
+	}
+	else
+	{
+	    if (RIOFindFreeID(p, HostP, &entry, NULL) == 0)
+	    {
+		RIODefaultName(p, HostP, entry);
+		FillSlot(entry, 0, RtaUniq, HostP);
+		EmptySlot = 0;
+	    }
+	}
+
+	/*
+	** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
+	** attached to the current host card in the driver table.
+	**
+	** If we found a SLOT_IN_USE entry on another host for this
+	** RTA in the config or driver table, and there are enough free
+	** slots in the driver table, then we need to move it over and
+	** delete it from the other host.
+	** If we found a SLOT_TENTATIVE entry on another host for this
+	** RTA in the driver table, just delete the other host entry.
+	*/
+	if (EmptySlot == 0)
+	{
+	    if ( MapP )
+	    {
+		if (Flag & SLOT_IN_USE)
+		{
+		    rio_dprint(RIO_DEBUG_BOOT, (
+    "This RTA configured on another host - move entry to current host (1)\n"));
+		    HostP->Mapping[entry].SysPort = MapP->SysPort;
+		    CCOPY( MapP->Name, HostP->Mapping[entry].Name, MAX_NAME_LEN );
+		    HostP->Mapping[entry].Flags =
+		     SLOT_IN_USE | RTA_BOOTED | RTA_NEWBOOT;
+#if NEED_TO_FIX
+		    RIO_SV_BROADCAST(HostP->svFlags[entry]);
+#endif
+		    RIOReMapPorts( p, HostP, &HostP->Mapping[entry] );
+		    if ( HostP->Mapping[entry].SysPort < p->RIOFirstPortsBooted )
+			p->RIOFirstPortsBooted = HostP->Mapping[entry].SysPort;
+		    if ( HostP->Mapping[entry].SysPort > p->RIOLastPortsBooted )
+			p->RIOLastPortsBooted = HostP->Mapping[entry].SysPort;
+		    rio_dprint(RIO_DEBUG_BOOT, ("SysPort %d, Name %s\n",(int)MapP->SysPort,MapP->Name));
+		}
+		else
+		{
+		    rio_dprint(RIO_DEBUG_BOOT, (
+   "This RTA has a tentative entry on another host - delete that entry (1)\n"));
+		    HostP->Mapping[entry].Flags =
+		     SLOT_TENTATIVE | RTA_BOOTED | RTA_NEWBOOT;
+#if NEED_TO_FIX
+		    RIO_SV_BROADCAST(HostP->svFlags[entry]);
+#endif
+		}
+		if (RtaType == TYPE_RTA16)
+		{
+		    if (Flag & SLOT_IN_USE)
+		    {
+			HostP->Mapping[entry2].Flags = SLOT_IN_USE |
+			 RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT;
+#if NEED_TO_FIX
+			RIO_SV_BROADCAST(HostP->svFlags[entry2]);
+#endif
+			HostP->Mapping[entry2].SysPort = MapP2->SysPort;
+			/*
+			** Map second block of ttys for 16 port RTA
+			*/
+			RIOReMapPorts( p, HostP, &HostP->Mapping[entry2] );
+		       if (HostP->Mapping[entry2].SysPort < p->RIOFirstPortsBooted)
+			 p->RIOFirstPortsBooted = HostP->Mapping[entry2].SysPort;
+		       if (HostP->Mapping[entry2].SysPort > p->RIOLastPortsBooted)
+			 p->RIOLastPortsBooted = HostP->Mapping[entry2].SysPort;
+			rio_dprint(RIO_DEBUG_BOOT, ("SysPort %d, Name %s\n",
+			       (int)HostP->Mapping[entry2].SysPort,
+			       HostP->Mapping[entry].Name));
+		    }
+		    else
+			HostP->Mapping[entry2].Flags = SLOT_TENTATIVE |
+			 RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT;
+#if NEED_TO_FIX
+			RIO_SV_BROADCAST(HostP->svFlags[entry2]);
+#endif
+		    bzero( (caddr_t)MapP2, sizeof(struct Map) );
+		}
+		bzero( (caddr_t)MapP, sizeof(struct Map) );
+		if (! p->RIONoMessage)
+		    cprintf("An orphaned RTA has been adopted by %s '%s' (%c).\n",MyType,MyName,MyLink+'A');
+	    }
+	    else if (! p->RIONoMessage)
+		cprintf("RTA connected to %s '%s' (%c) not configured.\n",MyType,MyName,MyLink+'A');
+	    RIOSetChange(p);
+	    return TRUE;
+	}
+
+	/*
+	** There is no room in the driver table to make an entry for the
+	** booted RTA. Keep a note of its Uniq Num in the overflow table,
+	** so we can ignore it's ID requests.
+	*/
+	if (! p->RIONoMessage)
+	    cprintf("The RTA connected to %s '%s' (%c) cannot be configured.  You cannot configure more than 128 ports to one host card.\n",MyType,MyName,MyLink+'A');
+	for ( entry=0; entry<HostP->NumExtraBooted; entry++ )
+	{
+	    if ( HostP->ExtraUnits[entry] == RtaUniq )
+	    {
+		/*
+		** already got it!
+		*/
+		return TRUE;
+	    }
+	}
+	/*
+	** If there is room, add the unit to the list of extras
+	*/
+	if ( HostP->NumExtraBooted < MAX_EXTRA_UNITS )
+	    HostP->ExtraUnits[HostP->NumExtraBooted++] = RtaUniq;
+	return TRUE;
+}
+
+
+/*
+** If the RTA or its host appears in the RIOBindTab[] structure then
+** we mustn't boot the RTA and should return FALSE.
+** This operation is slightly different from the other drivers for RIO
+** in that this is designed to work with the new utilities
+** not config.rio and is FAR SIMPLER.
+** We no longer support the RIOBootMode variable. It is all done from the
+** "boot/noboot" field in the rio.cf file.
+*/
+int
+RIOBootOk(p, HostP, RtaUniq)
+struct rio_info *	p;
+struct Host *		HostP;
+ulong RtaUniq;
+{
+    int		Entry;
+    uint HostUniq = HostP->UniqueNum;
+
+	/*
+	** Search bindings table for RTA or its parent.
+	** If it exists, return 0, else 1.
+	*/
+	for (Entry = 0;
+	    ( Entry < MAX_RTA_BINDINGS ) && ( p->RIOBindTab[Entry] != 0 );
+	    Entry++)
+	{
+		if ( (p->RIOBindTab[Entry] == HostUniq) ||
+		     (p->RIOBindTab[Entry] == RtaUniq) )
+			return 0;
+	}
+	return 1;
+}
+
+/*
+** Make an empty slot tentative. If this is a 16 port RTA, make both
+** slots tentative, and the second one RTA_SECOND_SLOT as well.
+*/
+
+void
+FillSlot(entry, entry2, RtaUniq, HostP)
+int entry;
+int entry2;
+uint RtaUniq;
+struct Host *HostP;
+{
+	int		link;
+
+	rio_dprint(RIO_DEBUG_BOOT, ("FillSlot(%d, %d, 0x%x...)\n", entry, entry2, RtaUniq));
+
+	HostP->Mapping[entry].Flags = (RTA_BOOTED | RTA_NEWBOOT | SLOT_TENTATIVE);
+	HostP->Mapping[entry].SysPort = NO_PORT;
+	HostP->Mapping[entry].RtaUniqueNum = RtaUniq;
+	HostP->Mapping[entry].HostUniqueNum = HostP->UniqueNum;
+	HostP->Mapping[entry].ID = entry + 1;
+	HostP->Mapping[entry].ID2 = 0;
+	if (entry2) {
+		HostP->Mapping[entry2].Flags = (RTA_BOOTED | RTA_NEWBOOT | 
+								SLOT_TENTATIVE | RTA16_SECOND_SLOT);
+		HostP->Mapping[entry2].SysPort = NO_PORT;
+		HostP->Mapping[entry2].RtaUniqueNum = RtaUniq;
+		HostP->Mapping[entry2].HostUniqueNum = HostP->UniqueNum;
+		HostP->Mapping[entry2].Name[0] = '\0';
+		HostP->Mapping[entry2].ID = entry2 + 1;
+		HostP->Mapping[entry2].ID2 = entry + 1;
+		HostP->Mapping[entry].ID2 = entry2 + 1;
+	}
+	/*
+	** Must set these up, so that utilities show
+	** topology of 16 port RTAs correctly
+	*/
+	for ( link=0; link<LINKS_PER_UNIT; link++ ) {
+		HostP->Mapping[entry].Topology[link].Unit = ROUTE_DISCONNECT;
+		HostP->Mapping[entry].Topology[link].Link = NO_LINK;
+		if (entry2) {
+			HostP->Mapping[entry2].Topology[link].Unit = ROUTE_DISCONNECT;
+			HostP->Mapping[entry2].Topology[link].Link = NO_LINK;
+		}
+	}
+}
+
+#if 0
+/*
+	Function:	This function is to disable the disk interrupt 
+    Returns :   Nothing
+*/
+void
+disable_interrupt(vector)
+int	vector;
+{
+	int	ps;
+	int	val;
+
+	disable(ps);
+	if (vector > 40)  {
+		val = 1 << (vector - 40);
+		__outb(S8259+1, __inb(S8259+1) | val);
+	}
+	else {
+		val = 1 << (vector - 32);
+		__outb(M8259+1, __inb(M8259+1) | val);
+	}
+	restore(ps);
+}
+
+/*
+	Function:	This function is to enable the disk interrupt 
+    Returns :   Nothing
+*/
+void
+enable_interrupt(vector)
+int	vector;
+{
+	int	ps;
+	int	val;
+
+	disable(ps);
+	if (vector > 40)  {
+		val = 1 << (vector - 40);
+		val = ~val;
+		__outb(S8259+1, __inb(S8259+1) & val);
+	}
+	else {
+		val = 1 << (vector - 32);
+		val = ~val;
+		__outb(M8259+1, __inb(M8259+1) & val);
+	}
+	restore(ps);
+}
+#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/riocmd.c linux.15p9/drivers/char/rio/riocmd.c
--- linux.vanilla/drivers/char/rio/riocmd.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/riocmd.c	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,1146 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  ported from the existing SCO driver source
+**
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: riocmd.c
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 10:33:41
+**	Retrieved	: 11/6/98 10:33:49
+**
+**  ident @(#)riocmd.c	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+#ifdef SCCS_LABELS
+static char *_riocmd_c_sccs_ = "@(#)riocmd.c	1.2";
+#endif
+
+#define __NO_VERSION__
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/malloc.h>
+#include <linux/errno.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/string.h>
+#include <asm/semaphore.h>
+#include <asm/spinlock.h>
+
+
+#include <linux/termios.h>
+#include <linux/serial.h>
+
+#include <linux/compatmac.h>
+#include <linux/generic_serial.h>
+
+#include "linux_compat.h"
+#include "rio_linux.h"
+#include "typdef.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "top.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "riotypes.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "error.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+#include "control.h"
+#include "cirrus.h"
+
+
+static struct IdentifyRta IdRta;
+static struct KillNeighbour KillUnit;
+
+int
+RIOFoadRta(HostP, MapP)
+struct Host *	HostP;
+struct Map *	MapP;
+{
+	struct CmdBlk *CmdBlkP;
+
+	rio_dprint(RIO_DEBUG_CMD, ("FOAD RTA\n"));
+
+	CmdBlkP = RIOGetCmdBlk();
+
+	if ( !CmdBlkP ) {
+		rio_dprint(RIO_DEBUG_CMD, ("FOAD RTA: GetCmdBlk failed\n"));
+		return ENXIO;
+	}
+
+	CmdBlkP->Packet.dest_unit = MapP->ID;
+	CmdBlkP->Packet.dest_port = BOOT_RUP;
+	CmdBlkP->Packet.src_unit  = 0;
+	CmdBlkP->Packet.src_port  = BOOT_RUP;
+	CmdBlkP->Packet.len	   = 0x84;
+	CmdBlkP->Packet.data[0]   = IFOAD;
+	CmdBlkP->Packet.data[1]   = 0;
+	CmdBlkP->Packet.data[2]   = IFOAD_MAGIC & 0xFF;
+	CmdBlkP->Packet.data[3]   = (IFOAD_MAGIC >> 8) & 0xFF;
+
+	if ( RIOQueueCmdBlk( HostP, MapP->ID-1, CmdBlkP) == RIO_FAIL ) {
+		rio_dprint(RIO_DEBUG_CMD, ("FOAD RTA: Failed to queue foad command\n"));
+		return EIO;
+	}
+	return 0;
+}
+
+int
+RIOZombieRta(HostP, MapP)
+struct Host *	HostP;
+struct Map *	MapP;
+{
+	struct CmdBlk *CmdBlkP;
+
+	rio_dprint(RIO_DEBUG_CMD, ("ZOMBIE RTA\n"));
+
+	CmdBlkP = RIOGetCmdBlk();
+
+	if ( !CmdBlkP ) {
+		rio_dprint(RIO_DEBUG_CMD, ("ZOMBIE RTA: GetCmdBlk failed\n"));
+		return ENXIO;
+	}
+
+	CmdBlkP->Packet.dest_unit = MapP->ID;
+	CmdBlkP->Packet.dest_port = BOOT_RUP;
+	CmdBlkP->Packet.src_unit  = 0;
+	CmdBlkP->Packet.src_port  = BOOT_RUP;
+	CmdBlkP->Packet.len	   = 0x84;
+	CmdBlkP->Packet.data[0]   = ZOMBIE;
+	CmdBlkP->Packet.data[1]   = 0;
+	CmdBlkP->Packet.data[2]   = ZOMBIE_MAGIC & 0xFF;
+	CmdBlkP->Packet.data[3]   = (ZOMBIE_MAGIC >> 8) & 0xFF;
+
+	if ( RIOQueueCmdBlk( HostP, MapP->ID-1, CmdBlkP) == RIO_FAIL ) {
+		rio_dprint(RIO_DEBUG_CMD, ("ZOMBIE RTA: Failed to queue zombie command\n"));
+		return EIO;
+	}
+	return 0;
+}
+
+int
+RIOCommandRta(p, RtaUnique, func)
+struct rio_info *	p;
+uint RtaUnique;
+int (* func)( struct Host *HostP, struct Map *MapP );
+{
+	uint Host;
+
+	rio_dprint(RIO_DEBUG_CMD, ("Command RTA 0x%x func 0x%x\n", RtaUnique, (int)func ));
+
+	if ( !RtaUnique )
+		return(0);
+
+	for ( Host = 0; Host < p->RIONumHosts; Host++ ) {
+		uint Rta;
+		struct Host *HostP = &p->RIOHosts[Host];
+
+		for ( Rta = 0; Rta < RTAS_PER_HOST; Rta++ ) {
+			struct Map *MapP = &HostP->Mapping[Rta];
+
+			if ( MapP->RtaUniqueNum == RtaUnique ) {
+				uint Link;
+
+				/*
+				** now, lets just check we have a route to it...
+				** IF the routing stuff is working, then one of the
+				** topology entries for this unit will have a legit
+				** route *somewhere*. We care not where - if its got
+				** any connections, we can get to it.
+				*/
+				for ( Link = 0; Link < LINKS_PER_UNIT; Link++ ) {
+					if ( MapP->Topology[Link].Unit <= (uchar)MAX_RUP ) {
+						/*
+						** Its worth trying the operation...
+						*/
+						return (*func)( HostP, MapP );
+					}
+				}
+			}
+		}
+	}
+	return ENXIO;
+}
+
+
+int
+RIOIdentifyRta(p, arg)
+struct rio_info *	p;
+caddr_t arg;
+{
+	uint Host;
+
+	if ( copyin( (int)arg, (caddr_t)&IdRta, sizeof(IdRta) ) == COPYFAIL ) {
+		rio_dprint(RIO_DEBUG_CMD, ("RIO_IDENTIFY_RTA copy failed\n"));
+		p->RIOError.Error = COPYIN_FAILED;
+		return EFAULT;
+	}
+
+	for ( Host = 0 ; Host < p->RIONumHosts; Host++ ) {
+		uint Rta;
+		struct Host *HostP = &p->RIOHosts[Host];
+
+		for ( Rta = 0; Rta < RTAS_PER_HOST; Rta++ ) {
+			struct Map *MapP = &HostP->Mapping[Rta];
+
+			if ( MapP->RtaUniqueNum == IdRta.RtaUnique ) {
+				uint Link;
+				/*
+				** now, lets just check we have a route to it...
+				** IF the routing stuff is working, then one of the
+				** topology entries for this unit will have a legit
+				** route *somewhere*. We care not where - if its got
+				** any connections, we can get to it.
+				*/
+				for ( Link = 0; Link < LINKS_PER_UNIT; Link++ ) {
+					if ( MapP->Topology[Link].Unit <= (uchar)MAX_RUP ) {
+						/*
+						** Its worth trying the operation...
+						*/
+						struct CmdBlk *CmdBlkP;
+
+						rio_dprint(RIO_DEBUG_CMD, ("IDENTIFY RTA\n"));
+
+						CmdBlkP = RIOGetCmdBlk();
+
+						if ( !CmdBlkP ) {
+							rio_dprint(RIO_DEBUG_CMD, ("IDENTIFY RTA: GetCmdBlk failed\n"));
+							return ENXIO;
+						}
+		
+						CmdBlkP->Packet.dest_unit = MapP->ID;
+						CmdBlkP->Packet.dest_port = BOOT_RUP;
+						CmdBlkP->Packet.src_unit  = 0;
+						CmdBlkP->Packet.src_port  = BOOT_RUP;
+						CmdBlkP->Packet.len	   = 0x84;
+						CmdBlkP->Packet.data[0]   = IDENTIFY;
+						CmdBlkP->Packet.data[1]   = 0;
+						CmdBlkP->Packet.data[2]   = IdRta.ID;
+		
+						if ( RIOQueueCmdBlk( HostP, MapP->ID-1, CmdBlkP) 
+										== RIO_FAIL ) {
+							rio_dprint(RIO_DEBUG_CMD, ("IDENTIFY RTA: Failed to queue command\n"));
+							return EIO;
+						}
+						return 0;
+					}
+				}
+			}
+		}
+	} 
+	return ENOENT;
+}
+
+
+int
+RIOKillNeighbour(p, arg)
+struct rio_info *	p;
+caddr_t arg;
+{
+	uint Host;
+	uint ID;
+	struct Host *HostP;
+	struct CmdBlk *CmdBlkP;
+
+	rio_dprint(RIO_DEBUG_CMD, ("KILL HOST NEIGHBOUR\n"));
+
+	if ( copyin( (int)arg, (caddr_t)&KillUnit, 
+					sizeof(KillUnit) ) == COPYFAIL ) {
+		rio_dprint(RIO_DEBUG_CMD, ("RIO_KILL_NEIGHBOUR copy failed\n"));
+		p->RIOError.Error = COPYIN_FAILED;
+		return EFAULT;
+	}
+
+	if ( KillUnit.Link > 3 )
+		return ENXIO;
+ 
+	CmdBlkP = RIOGetCmdBlk();
+
+	if ( !CmdBlkP ) {
+		rio_dprint(RIO_DEBUG_CMD, ("UFOAD: GetCmdBlk failed\n"));
+		return ENXIO;
+	}
+
+	CmdBlkP->Packet.dest_unit = 0;
+	CmdBlkP->Packet.src_unit  = 0;
+	CmdBlkP->Packet.dest_port = BOOT_RUP;
+	CmdBlkP->Packet.src_port  = BOOT_RUP;
+	CmdBlkP->Packet.len	   = 0x84;
+	CmdBlkP->Packet.data[0]   = UFOAD;
+	CmdBlkP->Packet.data[1]   = KillUnit.Link;
+	CmdBlkP->Packet.data[2]   = UFOAD_MAGIC & 0xFF;
+	CmdBlkP->Packet.data[3]   = (UFOAD_MAGIC >> 8) & 0xFF;
+
+	for ( Host = 0; Host < p->RIONumHosts; Host++ ) {
+		ID = 0;
+		HostP = &p->RIOHosts[Host];
+
+		if ( HostP->UniqueNum == KillUnit.UniqueNum ) {
+			if ( RIOQueueCmdBlk( HostP, RTAS_PER_HOST+KillUnit.Link,
+							CmdBlkP) == RIO_FAIL ) {
+				rio_dprint(RIO_DEBUG_CMD, ("UFOAD: Failed queue command\n"));
+				return EIO;
+			}
+			return 0;
+		}
+
+		for ( ID=0; ID < RTAS_PER_HOST; ID++ ) {
+			if ( HostP->Mapping[ID].RtaUniqueNum == KillUnit.UniqueNum ) {
+				CmdBlkP->Packet.dest_unit = ID+1;
+				if ( RIOQueueCmdBlk( HostP, ID, CmdBlkP) == RIO_FAIL ) {
+					rio_dprint(RIO_DEBUG_CMD, ("UFOAD: Failed queue command\n"));
+					return EIO;
+				}
+				return 0;
+			}
+		}
+	}
+	RIOFreeCmdBlk( CmdBlkP );
+	return ENXIO;
+}
+
+int
+RIOSuspendBootRta(HostP, ID, Link)
+struct Host *HostP;
+int ID;
+int Link; 
+{
+	struct CmdBlk *CmdBlkP;
+
+	rio_dprint(RIO_DEBUG_CMD, ("SUSPEND BOOT ON RTA ID %d, link %c\n", ID, 'A' + Link));
+
+	CmdBlkP = RIOGetCmdBlk();
+
+	if ( !CmdBlkP ) {
+		rio_dprint(RIO_DEBUG_CMD, ("SUSPEND BOOT ON RTA: GetCmdBlk failed\n"));
+		return ENXIO;
+	}
+
+	CmdBlkP->Packet.dest_unit = ID;
+	CmdBlkP->Packet.dest_port = BOOT_RUP;
+	CmdBlkP->Packet.src_unit  = 0;
+	CmdBlkP->Packet.src_port  = BOOT_RUP;
+	CmdBlkP->Packet.len	   = 0x84;
+	CmdBlkP->Packet.data[0]   = IWAIT;
+	CmdBlkP->Packet.data[1]   = Link;
+	CmdBlkP->Packet.data[2]   = IWAIT_MAGIC & 0xFF;
+	CmdBlkP->Packet.data[3]   = (IWAIT_MAGIC >> 8) & 0xFF;
+
+	if ( RIOQueueCmdBlk( HostP, ID - 1, CmdBlkP) == RIO_FAIL ) {
+		rio_dprint(RIO_DEBUG_CMD, ("SUSPEND BOOT ON RTA: Failed to queue iwait command\n"));
+		return EIO;
+	}
+	return 0;
+}
+
+int
+RIOFoadWakeup(p)
+struct rio_info *	p;
+{
+	int port;
+	register struct Port *PortP;
+	unsigned long flags;
+
+	for ( port=0; port<RIO_PORTS; port++) {
+		PortP = p->RIOPortp[port];
+
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+		PortP->Config = 0;
+		PortP->State = 0;
+		PortP->InUse = NOT_INUSE;
+		PortP->PortState = 0;
+		PortP->FlushCmdBodge = 0;
+		PortP->ModemLines = 0;
+		PortP->ModemState = 0;
+		PortP->CookMode = 0;
+		PortP->ParamSem = 0;
+		PortP->Mapped = 0;
+		PortP->WflushFlag = 0;
+		PortP->MagicFlags = 0;
+		PortP->RxDataStart = 0;
+		PortP->TxBufferIn = 0;
+		PortP->TxBufferOut = 0;
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	}
+	return(0);
+}
+
+/*
+** Incoming command on the COMMAND_RUP to be processed.
+*/
+int
+RIOCommandRup(p, Rup, HostP, PacketP)
+struct rio_info *	p;
+uint Rup;
+struct Host *HostP;
+PKT *PacketP; 
+{
+	struct PktCmd *PktCmdP = (struct PktCmd *)PacketP->data;
+	struct Port *PortP;
+	struct UnixRup *UnixRupP;
+	ushort SysPort;
+	ushort ReportedModemStatus;
+	ushort rup;
+	ushort subCommand;
+	unsigned long flags;
+
+
+#ifdef CHECK
+	CheckHost( Host );
+	CheckHostP( HostP );
+	CheckPacketP( PacketP );
+#endif
+
+	/*
+	** 16 port RTA note:
+	** Command rup packets coming from the RTA will have pkt->data[1] (which
+	** translates to PktCmdP->PhbNum) set to the host port number for the
+	** particular unit. To access the correct BaseSysPort for a 16 port RTA,
+	** we can use PhbNum to get the rup number for the appropriate 8 port
+	** block (for the first block, this should be equal to 'Rup').
+	*/
+	rup = RBYTE(PktCmdP->PhbNum) / (ushort)PORTS_PER_RTA;
+	UnixRupP = &HostP->UnixRups[rup];
+	SysPort = UnixRupP->BaseSysPort + 
+			(RBYTE(PktCmdP->PhbNum) % (ushort)PORTS_PER_RTA);
+	rio_dprint(RIO_DEBUG_CMD, ("Command on rup %d, port %d\n", rup, SysPort));
+
+#ifdef CHECK
+	CheckRup( rup );
+	CheckUnixRupP( UnixRupP );
+#endif
+	if ( UnixRupP->BaseSysPort == NO_PORT ) {
+		rio_dprint(RIO_DEBUG_CMD, ("OBSCURE ERROR!\n"));
+		rio_dprint(RIO_DEBUG_CMD, ("Diagnostics follow. Please WRITE THESE DOWN and report them to Specialix Technical Support\n"));
+		rio_dprint(RIO_DEBUG_CMD, ("CONTROL information: Host number %d, name ``%s''\n", 
+					HostP-p->RIOHosts, HostP->Name ));
+		rio_dprint(RIO_DEBUG_CMD, ("CONTROL information: Rup number  0x%x\n", rup));
+
+		if ( Rup >= (ushort)MAX_RUP )
+			rio_dprint(RIO_DEBUG_CMD, ("CONTROL information: This is the RUP for RTA ``%s''\n",
+						HostP->Mapping[Rup].Name ));
+		else
+			rio_dprint(RIO_DEBUG_CMD, ("CONTROL information: This is the RUP for link ``%c'' of host ``%s''\n", 'A' + Rup - MAX_RUP, HostP->Name ));
+
+		rio_dprint(RIO_DEBUG_CMD, ("PACKET information: Destination 0x%x:0x%x\n",
+					PacketP->dest_unit, PacketP->dest_port ));
+		rio_dprint(RIO_DEBUG_CMD, ("PACKET information: Source	  0x%x:0x%x\n",
+					PacketP->src_unit, PacketP->src_port ));
+		rio_dprint(RIO_DEBUG_CMD, ("PACKET information: Length	  0x%x (%d)\n", PacketP->len,PacketP->len ));
+		rio_dprint(RIO_DEBUG_CMD, ("PACKET information: Control	 0x%x (%d)\n", PacketP->control, PacketP->control));
+		rio_dprint(RIO_DEBUG_CMD, ("PACKET information: Check	   0x%x (%d)\n", PacketP->csum, PacketP->csum ));
+		rio_dprint(RIO_DEBUG_CMD, ("COMMAND information: Host Port Number 0x%x, 
+					Command Code 0x%x\n", PktCmdP->PhbNum, PktCmdP->Command ));
+		return TRUE;
+	}
+
+#ifdef CHECK
+	CheckSysPort( SysPort );
+#endif
+	PortP = p->RIOPortp[ SysPort ];
+#if 0
+	ttyP = PortP->TtyP;
+#endif
+	rio_spin_lock_irqsave(&PortP->portSem, flags);
+	switch( RBYTE(PktCmdP->Command) ) {
+		case BREAK_RECEIVED:
+			rio_dprint(RIO_DEBUG_CMD, ("Received a break!\n"));
+			/* If the current line disc. is not multi-threading and
+	   			the current processor is not the default, reset rup_intr
+	   			and return FALSE to ensure that the command packet is
+	   			not freed. */
+			/* Call tmgr HANGUP HERE */
+			/* Fix this later when every thing works !!!! RAMRAJ */
+			break;
+
+		case COMPLETE:
+			rio_dprint(RIO_DEBUG_CMD, ("Command complete on phb %d host %d\n",
+							RBYTE(PktCmdP->PhbNum), HostP-p->RIOHosts));
+			subCommand = 1;
+			switch (RBYTE(PktCmdP->SubCommand)) {
+				case MEMDUMP :
+					rio_dprint(RIO_DEBUG_CMD, ("Memory dump cmd (0x%x) from addr 0x%x\n",
+		 				RBYTE(PktCmdP->SubCommand), RWORD(PktCmdP->SubAddr)));
+					break;
+				case READ_REGISTER :
+					rio_dprint(RIO_DEBUG_CMD, ("Read register (0x%x)\n", RWORD(PktCmdP->SubAddr)));
+					p->CdRegister = (RBYTE(PktCmdP->ModemStatus) & MSVR1_HOST);
+					break;
+				default :
+					subCommand = 0;
+				break;
+			}
+			if (subCommand)
+				break;
+			rio_dprint(RIO_DEBUG_CMD, ("New status is 0x%x was 0x%x\n",
+					 RBYTE(PktCmdP->PortStatus),PortP->PortState));
+			if (PortP->PortState != RBYTE(PktCmdP->PortStatus)) {
+				rio_dprint(RIO_DEBUG_CMD, ("Mark status & wakeup\n"));
+				PortP->PortState = RBYTE(PktCmdP->PortStatus);
+				/* What should we do here ...
+				wakeup( &PortP->PortState );
+				*/
+			}
+			else {
+				rio_dprint(RIO_DEBUG_CMD, ("No change\n"));
+			}
+
+			/* FALLTHROUGH */
+		case MODEM_STATUS:
+			/*
+			** Knock out the tbusy and tstop bits, as these are not relevant
+			** to the check for modem status change (they're just there because
+			** it's a convenient place to put them!).
+			*/
+			ReportedModemStatus = RBYTE(PktCmdP->ModemStatus);
+			if ((PortP->ModemState & MSVR1_HOST) ==
+					(ReportedModemStatus & MSVR1_HOST)) {
+				rio_dprint(RIO_DEBUG_CMD, ("Modem status unchanged 0x%x\n", PortP->ModemState));
+				/*
+				** Update ModemState just in case tbusy or tstop states have
+				** changed.
+				*/
+				PortP->ModemState = ReportedModemStatus;
+			}
+			else {
+				rio_dprint(RIO_DEBUG_CMD, ("Modem status change from 0x%x to 0x%x\n",
+							 PortP->ModemState, ReportedModemStatus));
+				PortP->ModemState = ReportedModemStatus;
+#ifdef MODEM_SUPPORT
+				if ( PortP->Mapped ) {
+				/***********************************************************\
+				*************************************************************
+				***													   ***
+				***		  M O D E M   S T A T E   C H A N G E		  ***
+				***													   ***
+				*************************************************************
+				\***********************************************************/
+				/*
+				** If the device is a modem, then check the modem
+				** carrier.
+				*/
+				if(!(ttyP->t_cflag & CLOCAL) && 
+					((PortP->State & (RIO_MOPEN|RIO_WOPEN))))
+				{
+			/*
+			** Is there a carrier?
+			*/
+			if ( PortP->ModemState & MSVR1_CD )
+			{
+			/*
+			** Has carrier just appeared?
+			*/
+			if (!(ttyP->t_state & CARR_ON))
+			{
+				rio_dprint(RIO_DEBUG_CMD, PortP,DBG_MODEM,"Carrier just came up.\n");
+				ttyP->t_state |=CARR_ON;
+				/*
+				** wakeup anyone in WOPEN
+				*/
+				if ( ttyP->t_state & (ISOPEN|WOPEN) )
+				wakeup((caddr_t)&ttyP->t_canq);
+#ifdef STATS
+				PortP->Stat.ModemOnCnt++;
+#endif
+			}
+			}
+			else
+			{
+			/*
+			** Has carrier just dropped?
+			*/
+			if (ttyP->t_state & CARR_ON)
+			{
+				/*
+				** send SIGHUP to the process group
+				*/
+				if ( ttyP->t_state & (ISOPEN|WOPEN) )
+				{
+				signal(ttyP->t_pgrp,SIGHUP);
+				ttyflush(ttyP,(FREAD|FWRITE));
+				}
+				ttyP->t_state &= ~CARR_ON;
+				wakeup( (caddr_t)&PortP->TxBufferOut );
+				wakeup( (caddr_t)&PortP->TxBufferIn );
+				rio_dprint(RIO_DEBUG_CMD, PortP,DBG_MODEM,"Carrier just went down.\n");
+#ifdef STATS
+				PortP->Stat.ModemOffCnt++;
+#endif
+			}
+			}
+		}
+		}
+#endif
+			}
+			break;
+
+		default:
+			rio_dprint(RIO_DEBUG_CMD, ("Unknown command %d on CMD_RUP of host %d\n",
+				RBYTE(PktCmdP->Command),HostP-p->RIOHosts));
+			break;
+	}
+	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	return TRUE;
+}
+/*
+** The command mechanism:
+**	Each rup has a chain of commands associated with it.
+**	This chain is maintained by routines in this file.
+**	Periodically we are called and we run a quick check of all the
+**	active chains to determine if there is a command to be executed,
+**	and if the rup is ready to accept it.
+**
+*/
+
+/*
+** Allocate an empty command block.
+*/
+struct CmdBlk *
+RIOGetCmdBlk()
+{
+	struct CmdBlk *CmdBlkP;
+
+	CmdBlkP = (struct CmdBlk *)sysbrk(sizeof(struct CmdBlk));
+	bzero(CmdBlkP, sizeof(struct CmdBlk));
+
+	return CmdBlkP;
+}
+
+/*
+** Return a block to the head of the free list.
+*/
+void
+RIOFreeCmdBlk(CmdBlkP)
+struct CmdBlk *CmdBlkP;
+{
+	sysfree((void *)CmdBlkP, sizeof(struct CmdBlk));
+}
+
+/*
+** attach a command block to the list of commands to be performed for
+** a given rup.
+*/
+int
+RIOQueueCmdBlk(HostP, Rup, CmdBlkP)
+struct Host *HostP;
+uint Rup;
+struct CmdBlk *CmdBlkP;
+{
+	struct CmdBlk **Base;
+	struct UnixRup *UnixRupP;
+	unsigned long flags;
+
+#ifdef CHECK
+	CheckHostP( HostP );
+	CheckRup( Rup );
+	CheckCmdBlkP( CmdBlkP );
+#endif
+
+	rio_dprint(RIO_DEBUG_CMD, ("RIOQueueCmdBlk(Host, Rup %d, 0x%x)\n", Rup, (int)CmdBlkP ));
+
+	if ( Rup >= (ushort)(MAX_RUP+LINKS_PER_UNIT) ) {
+		rio_dprint(RIO_DEBUG_CMD, ("Illegal rup number %d in RIOQueueCmdBlk\n",Rup));
+		RIOFreeCmdBlk( CmdBlkP );
+		return RIO_FAIL;
+	}
+
+	UnixRupP = &HostP->UnixRups[Rup];
+
+	rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
+
+	/*
+	** If the RUP is currently inactive, then put the request
+	** straight on the RUP....
+	*/
+	if ( (UnixRupP->CmdsWaitingP == NULL) && (UnixRupP->CmdPendingP == NULL) && 
+		(RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE) &&
+		(CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP)(CmdBlkP->PreArg,CmdBlkP)
+							:TRUE)) {
+		rio_dprint(RIO_DEBUG_CMD, ("RUP inactive-placing command straight on. Cmd byte is 0x%x\n",
+					CmdBlkP->Packet.data[0]));
+
+		/*
+		** Whammy! blat that pack!
+		*/
+		HostP->Copy( (caddr_t)&CmdBlkP->Packet, 
+			RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt ), sizeof(PKT) );
+
+		/*
+		** place command packet on the pending position.
+		*/
+		UnixRupP->CmdPendingP = CmdBlkP;
+
+		/*
+		** set the command register
+		*/
+		WWORD(UnixRupP->RupP->txcontrol , TX_PACKET_READY);
+
+		rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
+
+		return RIO_SUCCESS;
+	}
+
+	rio_dprint(RIO_DEBUG_CMD, ("RUP active - en-queing\n"));
+
+	if ( UnixRupP->CmdsWaitingP != NULL)
+		rio_dprint(RIO_DEBUG_CMD, ("Rup active - command waiting\n"));
+	if ( UnixRupP->CmdPendingP != NULL )
+		rio_dprint(RIO_DEBUG_CMD, ("Rup active - command pending\n"));
+	if ( RWORD(UnixRupP->RupP->txcontrol) != TX_RUP_INACTIVE )
+		rio_dprint(RIO_DEBUG_CMD, ("Rup active - command rup not ready\n"));
+
+	Base = &UnixRupP->CmdsWaitingP;
+
+	rio_dprint(RIO_DEBUG_CMD, ("First try to queue cmdblk 0x%x at 0x%x\n",(int)CmdBlkP,(int)Base));
+
+	while ( *Base ) {
+		rio_dprint(RIO_DEBUG_CMD, ("Command cmdblk 0x%x here\n",(int)(*Base)));
+		Base = &((*Base)->NextP);
+		rio_dprint(RIO_DEBUG_CMD, ("Now try to queue cmd cmdblk 0x%x at 0x%x\n",
+		       (int)CmdBlkP,(int)Base));
+	}
+
+	rio_dprint(RIO_DEBUG_CMD, ("Will queue cmdblk 0x%x at 0x%x\n",(int)CmdBlkP,(int)Base));
+
+	*Base = CmdBlkP;
+
+	CmdBlkP->NextP = NULL;
+
+	rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
+
+	return RIO_SUCCESS;
+}
+
+/*
+** Here we go - if there is an empty rup, fill it!
+** must be called at splrio() or higher.
+*/
+void
+RIOPollHostCommands(p, HostP)
+struct rio_info *	p;
+struct Host *		HostP;
+{
+	register struct CmdBlk *CmdBlkP;
+	register struct UnixRup *UnixRupP;
+	struct PKT *PacketP;
+	ushort Rup;
+	unsigned long flags;
+
+
+	Rup = MAX_RUP+LINKS_PER_UNIT;
+
+	do {	/* do this loop for each RUP */
+		/*
+		** locate the rup we are processing & lock it
+		*/
+		UnixRupP = &HostP->UnixRups[--Rup];
+
+		spin_lock_irqsave(&UnixRupP->RupLock, flags);
+
+		/*
+		** First check for incoming commands:
+		*/
+		if ( RWORD(UnixRupP->RupP->rxcontrol) != RX_RUP_INACTIVE ) {
+			int FreeMe;
+
+			/* rio_dprint(RIO_DEBUG_CMD, ("RIORupCmd( %d, %d )\n", HostP-p->RIOHosts, Rup )); */
+
+			PacketP =(PKT *)RIO_PTR(HostP->Caddr,RWORD(UnixRupP->RupP->rxpkt));
+
+			ShowPacket( DBG_CMD, PacketP );
+
+			switch ( RBYTE(PacketP->dest_port) ) {
+				case BOOT_RUP:
+					rio_dprint(RIO_DEBUG_CMD, ("Incoming Boot %s packet '%x'\n", 
+						RBYTE(PacketP->len) & 0x80 ? "Command":"Data", 
+						RBYTE(PacketP->data[0]) )); 
+					rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
+					FreeMe= RIOBootRup(p, Rup,HostP,PacketP);
+					rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
+					break;
+
+				case COMMAND_RUP:
+					/*
+					** Free the RUP lock as loss of carrier causes a
+					** ttyflush which will (eventually) call another
+					** routine that uses the RUP lock.
+					*/
+					rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
+					FreeMe= RIOCommandRup(p, Rup,HostP,PacketP);
+					if (PacketP->data[5] == MEMDUMP) {
+						rio_dprint(RIO_DEBUG_CMD, ("Memdump from 0x%x complete\n",
+			 				*(ushort *) &(PacketP->data[6])));
+						HostP->Copy( (caddr_t)&(PacketP->data[8]), 
+								(caddr_t)p->RIOMemDump, 32 );
+					}
+					rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
+					break;
+
+				case ROUTE_RUP:
+					rio_spin_unlock_irqrestore( &UnixRupP->RupLock, flags);
+					FreeMe = RIORouteRup(p, Rup, HostP, PacketP );
+					rio_spin_lock_irqsave( &UnixRupP->RupLock, flags );
+					break;
+
+				default:
+					rio_dprint(RIO_DEBUG_CMD, ("Unknown RUP %d\n", RBYTE(PacketP->dest_port)));
+					FreeMe = 1;
+					break;
+			}
+
+			if ( FreeMe ) {
+				rio_dprint(RIO_DEBUG_CMD, ("Free processed incoming command packet\n"));
+				put_free_end(HostP,PacketP);
+
+				WWORD(UnixRupP->RupP->rxcontrol , RX_RUP_INACTIVE);
+
+				if ( RWORD(UnixRupP->RupP->handshake)==PHB_HANDSHAKE_SET ) {
+					rio_dprint(RIO_DEBUG_CMD, ("Handshake rup %d\n",Rup));
+					WWORD(UnixRupP->RupP->handshake,
+						PHB_HANDSHAKE_SET|PHB_HANDSHAKE_RESET);
+				}
+			}
+		}
+
+		/*
+		** IF a command was running on the port, 
+		** and it has completed, then tidy it up.
+		*/
+		if ( (CmdBlkP = UnixRupP->CmdPendingP) && /* ASSIGN! */
+			(RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE) ) {
+			/*
+			** we are idle.
+			** there is a command in pending.
+			** Therefore, this command has finished.
+			** So, wakeup whoever is waiting for it (and tell them
+			** what happened).
+			*/
+			if ( CmdBlkP->Packet.dest_port == BOOT_RUP )
+				rio_dprint(RIO_DEBUG_CMD, ("Free Boot %s Command Block '%x'\n", 
+						CmdBlkP->Packet.len & 0x80 ? "Command":"Data", 
+							CmdBlkP->Packet.data[0] ));
+
+			rio_dprint(RIO_DEBUG_CMD, ("Command 0x%x completed\n",(int)CmdBlkP));
+
+			/*
+			** Clear the Rup lock to prevent mutual exclusion.
+			*/
+			if ( CmdBlkP->PostFuncP ) {
+				rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
+				(*CmdBlkP->PostFuncP) (CmdBlkP->PostArg,CmdBlkP);
+				rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
+			}
+
+			/*
+			** ....clear the pending flag....
+			*/
+			UnixRupP->CmdPendingP = NULL;
+
+			/*
+			** ....and return the command block to the freelist.
+			*/
+			RIOFreeCmdBlk( CmdBlkP );
+		}
+
+		/*
+		** If there is a command for this rup, and the rup
+		** is idle, then process the command
+		*/
+		if ( (CmdBlkP = UnixRupP->CmdsWaitingP) && /* ASSIGN! */
+			(UnixRupP->CmdPendingP == NULL) &&
+				(RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE) ) {
+			/*
+			** if the pre-function is non-zero, call it.
+			** If it returns RIO_FAIL then don't
+			** send this command yet!
+			*/
+#ifdef CHECK
+CheckCmdBlkP( CmdBlkP );
+#endif
+			if ( !(CmdBlkP->PreFuncP ?
+				(*CmdBlkP->PreFuncP)(CmdBlkP->PreArg, CmdBlkP) : TRUE)) {
+				rio_dprint(RIO_DEBUG_CMD, ("Not ready to start command 0x%x\n",(int)CmdBlkP));
+			}
+			else {
+				rio_dprint(RIO_DEBUG_CMD, ("Start new command 0x%x Cmd byte is 0x%x\n",
+						(int)CmdBlkP, CmdBlkP->Packet.data[0]));
+				/*
+				** Whammy! blat that pack!
+				*/
+#ifdef CHECK
+CheckPacketP( (PKT *)RIO_PTR(HostP->Caddr,UnixRupP->RupP->txpkt) );
+#endif
+				HostP->Copy( (caddr_t)&CmdBlkP->Packet, 
+					RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt), sizeof(PKT));
+
+				/*
+				** remove the command from the rup command queue...
+				*/
+				UnixRupP->CmdsWaitingP = CmdBlkP->NextP;
+
+				/*
+				** ...and place it on the pending position.
+				*/
+				UnixRupP->CmdPendingP = CmdBlkP;
+
+				/*
+				** set the command register
+				*/
+				WWORD(UnixRupP->RupP->txcontrol,TX_PACKET_READY);
+
+				/*
+				** the command block will be freed
+				** when the command has been processed.
+				*/
+			}
+		}
+		spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
+	} while ( Rup );
+}
+
+
+/*
+** Return the length of the named string
+*/
+int
+RIOStrlen(Str)
+register char *Str;
+{
+	register int len = 0;
+
+	while ( *Str++ )
+		len++;
+	return len;
+}
+
+/*
+** compares s1 to s2 and return 0 if they match.
+*/
+int
+RIOStrCmp(s1, s2)
+register char *s1;
+register char *s2;
+{
+	while ( *s1 && *s2 && *s1==*s2 )
+		s1++, s2++;
+	return *s1-*s2;
+}
+
+/*
+** compares s1 to s2 for upto n bytes and return 0 if they match.
+*/
+int
+RIOStrnCmp(s1, s2, n)
+register char *s1;
+register char *s2;
+int n;
+{
+	while ( n && *s1 && *s2 && *s1==*s2 )
+		n--, s1++, s2++;
+	return n ? *s1!=*s2 : 0;
+}
+
+/*
+** copy up to 'len' bytes from 'from' to 'to'.
+*/
+void
+RIOStrNCpy(to, from, len)
+char *to;
+char *from;
+int len; 
+{
+	while ( len-- && (*to++ = *from++) )
+		;
+	to[-1]='\0';
+}
+
+int
+RIOWFlushMark(iPortP, CmdBlkP)
+int iPortP;
+struct CmdBlk *CmdBlkP;
+{
+	struct Port *	PortP = (struct Port *)iPortP;
+	unsigned long flags;
+
+	rio_spin_lock_irqsave(&PortP->portSem, flags);
+#ifdef CHECK
+	CheckPortP( PortP );
+#endif
+	PortP->WflushFlag++;
+	PortP->MagicFlags |= MAGIC_FLUSH;
+	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	return RIOUnUse( iPortP, CmdBlkP );
+}
+
+int
+RIORFlushEnable(iPortP, CmdBlkP)
+int iPortP;
+struct CmdBlk *CmdBlkP; 
+{
+	struct Port *	PortP = (struct Port *)iPortP;
+	PKT *PacketP;
+	unsigned long flags;
+
+	rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+	while ( can_remove_receive(&PacketP, PortP) ) {
+		remove_receive(PortP);
+		ShowPacket(DBG_PROC, PacketP );
+		put_free_end( PortP->HostP, PacketP );
+	}
+
+	if ( RWORD(PortP->PhbP->handshake)==PHB_HANDSHAKE_SET ) {
+		/*
+		** MAGIC! (Basically, handshake the RX buffer, so that
+		** the RTAs upstream can be re-enabled.)
+		*/
+		rio_dprint(RIO_DEBUG_CMD, ("Util: Set RX handshake bit\n"));
+		WWORD(PortP->PhbP->handshake, PHB_HANDSHAKE_SET|PHB_HANDSHAKE_RESET);
+	}
+	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	return RIOUnUse( iPortP, CmdBlkP );
+}
+
+int
+RIOUnUse(iPortP, CmdBlkP)
+int iPortP;
+struct CmdBlk *CmdBlkP; 
+{
+	struct Port *	PortP = (struct Port *)iPortP;
+	unsigned long flags;
+
+	rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+#ifdef CHECK
+	CheckPortP( PortP );
+#endif
+	rio_dprint(RIO_DEBUG_CMD, ("Decrement in use count for port\n"));
+
+	if (PortP->InUse) {
+		if ( --PortP->InUse != NOT_INUSE ) {
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return 0;
+		}
+	}
+	/*
+	** While PortP->InUse is set (i.e. a preemptive command has been sent to
+	** the RTA and is awaiting completion), any transmit data is prevented from
+	** being transferred from the write queue into the transmit packets
+	** (add_transmit) and no furthur transmit interrupt will be sent for that
+	** data. The next interrupt will occur up to 500ms later (RIOIntr is called
+	** twice a second as a saftey measure). This was the case when kermit was
+	** used to send data into a RIO port. After each packet was sent, TCFLSH
+	** was called to flush the read queue preemptively. PortP->InUse was
+	** incremented, thereby blocking the 6 byte acknowledgement packet
+	** transmitted back. This acknowledgment hung around for 500ms before
+	** being sent, thus reducing input performance substantially!.
+	** When PortP->InUse becomes NOT_INUSE, we must ensure that any data
+	** hanging around in the transmit buffer is sent immediately.
+	*/
+	WWORD(PortP->HostP->ParmMapP->tx_intr, 1);
+	/* What to do here ..
+	wakeup( (caddr_t)&(PortP->InUse) );
+	*/
+	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	return 0;
+}
+
+void
+ShowPacket(Flags, PacketP)
+uint Flags;
+struct PKT *PacketP; 
+{
+}
+
+/*
+** 
+** How to use this file:
+** 
+** To send a command down a rup, you need to allocate a command block, fill
+** in the packet information, fill in the command number, fill in the pre-
+** and post- functions and arguments, and then add the command block to the
+** queue of command blocks for the port in question. When the port is idle,
+** then the pre-function will be called. If this returns RIO_FAIL then the
+** command will be re-queued and tried again at a later date (probably in one
+** clock tick). If the pre-function returns NOT RIO_FAIL, then the command
+** packet will be queued on the RUP, and the txcontrol field set to the
+** command number. When the txcontrol field has changed from being the
+** command number, then the post-function will be called, with the argument
+** specified earlier, a pointer to the command block, and the value of
+** txcontrol.
+** 
+** To allocate a command block, call RIOGetCmdBlk(). This returns a pointer
+** to the command block structure allocated, or NULL if there aren't any.
+** The block will have been zeroed for you.
+** 
+** The structure has the following fields:
+** 
+** struct CmdBlk
+** {
+**	 struct CmdBlk *NextP;		  ** Pointer to next command block   **
+**	 struct PKT	 Packet;		** A packet, to copy to the rup	**
+**			int	 (*PreFuncP)();  ** The func to call to check if OK **
+**			int	 PreArg;		** The arg for the func			**
+**			int	 (*PostFuncP)(); ** The func to call when completed **
+**			int	 PostArg;	   ** The arg for the func			**
+** };
+** 
+** You need to fill in ALL fields EXCEPT NextP, which is used to link the
+** blocks together either on the free list or on the Rup list.
+** 
+** Packet is an actual packet structure to be filled in with the packet
+** information associated with the command. You need to fill in everything,
+** as the command processore doesn't process the command packet in any way.
+** 
+** The PreFuncP is called before the packet is enqueued on the host rup.
+** PreFuncP is called as (*PreFuncP)(PreArg, CmdBlkP);. PreFuncP must
+** return !RIO_FAIL to have the packet queued on the rup, and RIO_FAIL
+** if the packet is NOT to be queued.
+** 
+** The PostFuncP is called when the command has completed. It is called
+** as (*PostFuncP)(PostArg, CmdBlkP, txcontrol);. PostFuncP is not expected
+** to return a value. PostFuncP does NOT need to free the command block,
+** as this happens automatically after PostFuncP returns.
+** 
+** Once the command block has been filled in, it is attached to the correct
+** queue by calling RIOQueueCmdBlk( HostP, Rup, CmdBlkP ) where HostP is
+** a pointer to the struct Host, Rup is the NUMBER of the rup (NOT a pointer
+** to it!), and CmdBlkP is the pointer to the command block allocated using
+** RIOGetCmdBlk().
+** 
+*/
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/rioctrl.c linux.15p9/drivers/char/rio/rioctrl.c
--- linux.vanilla/drivers/char/rio/rioctrl.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/rioctrl.c	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,1899 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: rioctrl.c
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 10:33:42
+**	Retrieved	: 11/6/98 10:33:49
+**
+**  ident @(#)rioctrl.c	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+#ifdef SCCS_LABELS
+static char *_rioctrl_c_sccs_ = "@(#)rioctrl.c	1.3";
+#endif
+
+
+#define __NO_VERSION__
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/malloc.h>
+#include <linux/errno.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/string.h>
+#include <asm/semaphore.h>
+#include <asm/uaccess.h>
+
+#include <linux/termios.h>
+#include <linux/serial.h>
+
+#include <linux/compatmac.h>
+#include <linux/generic_serial.h>
+
+
+#include "linux_compat.h"
+#include "rio_linux.h"
+#include "typdef.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "top.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "riotypes.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "error.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+#include "control.h"
+#include "cirrus.h"
+#include "rioioctl.h"
+
+
+static struct LpbReq	 LpbReq;
+static struct RupReq	 RupReq;
+static struct PortReq	PortReq;
+static struct HostReq	HostReq;
+static struct HostDpRam HostDpRam;
+static struct DebugCtrl DebugCtrl;
+static struct Map		 MapEnt;
+static struct PortSetup PortSetup;
+static struct DownLoad	DownLoad;
+static struct SendPack  SendPack;
+/* static struct StreamInfo	StreamInfo; */
+/* static char modemtable[RIO_PORTS]; */
+static struct SpecialRupCmd SpecialRupCmd;
+static struct PortParams PortParams;
+static struct portStats portStats;
+
+static struct SubCmdStruct {
+	ushort	Host;
+	ushort	Rup;
+	ushort	Port;
+	ushort	Addr;
+} SubCmd;
+
+struct PortTty {
+	uint		port;
+	struct ttystatics	Tty;
+};
+
+static struct PortTty	PortTty;
+typedef struct ttystatics TERMIO;
+
+/*
+** This table is used when the config.rio downloads bin code to the
+** driver. We index the table using the product code, 0-F, and call
+** the function pointed to by the entry, passing the information
+** about the boot.
+** The RIOBootCodeUNKNOWN entry is there to politely tell the calling
+** process to bog off.
+*/
+static int 
+(*RIOBootTable[MAX_PRODUCT])(struct rio_info *, struct DownLoad *) =
+{
+/* 0 */	RIOBootCodeHOST,	/* Host Card */
+/* 1 */	RIOBootCodeRTA,		/* RTA */
+};
+
+#define drv_makedev(maj, min) ((((uint) maj & 0xff) << 8) | ((uint) min & 0xff))
+
+#ifdef linux
+int copyin (int arg, caddr_t dp, int siz)
+{
+  int rv;
+
+  rio_dprint (RIO_DEBUG_CTRL, ("Copying %d bytes from user %p to %p.\n", siz, (void *) arg, dp));
+  rv = copy_from_user (dp, (void *)arg, siz);
+  if (rv < 0) return COPYFAIL;
+  else return rv;
+}
+
+
+int copyout (caddr_t dp, int arg, int siz)
+{
+  int rv;
+
+  rio_dprint (RIO_DEBUG_CTRL, ("Copying %d bytes to user %p from %p.\n", siz, (void *) arg, dp));
+  rv = copy_to_user ((void *)arg, dp, siz);
+  if (rv < 0) return COPYFAIL;
+  else return rv;
+}
+
+#else
+
+int
+copyin(arg, dp, siz)
+int arg;
+caddr_t dp;
+int siz; 
+{
+	if (rbounds ((unsigned long) arg) >= siz) {
+		bcopy ( arg, dp, siz );
+		return OK;
+	} else
+		return ( COPYFAIL );
+}
+
+int
+copyout (dp, arg, siz)
+caddr_t dp;
+int arg;
+int siz;
+{
+	if (wbounds ((unsigned long) arg) >=  siz ) {
+		bcopy ( dp, arg, siz );
+		return OK;
+	} else
+		return ( COPYFAIL );
+}
+#endif
+
+int
+riocontrol(p, dev, cmd, arg, su)
+struct rio_info	* p;
+dev_t		dev;
+int		cmd;
+caddr_t		arg;
+int		su;
+{
+	uint	Host;	/* leave me unsigned! */
+	uint	port;	/* and me! */
+	struct Host	*HostP;
+	ushort	loop;
+	int		Entry;
+	struct Port	*PortP;
+	PKT	*PacketP;
+	int		retval = 0;
+	unsigned long flags;
+	
+	/* Confuse teh compiler to think that we've initialized these */
+	Host=0;
+	PortP = NULL;
+
+	rio_dprint(RIO_DEBUG_CTRL, ("control ioctl cmd: 0x%x arg: 0x%x\n", cmd, (int)arg));
+
+	switch (cmd) {
+		/*
+		** RIO_SET_TIMER
+		**
+		** Change the value of the host card interrupt timer.
+		** If the host card number is -1 then all host cards are changed
+		** otherwise just the specified host card will be changed.
+		*/
+		case RIO_SET_TIMER:
+			rio_dprint(RIO_DEBUG_CTRL, ("RIO_SET_TIMER to %dms\n", (uint)arg));
+			{
+				int host, value;
+				host = (uint)arg >> 16;
+				value = (uint)arg & 0x0000ffff;
+				if (host == -1) {
+					for (host = 0; host < p->RIONumHosts; host++) {
+						if (p->RIOHosts[host].Flags == RC_RUNNING) {
+							WWORD(p->RIOHosts[host].ParmMapP->timer , value);
+						}
+					}
+				} else if (host >= p->RIONumHosts) {
+					return EINVAL;
+				} else {
+					if ( p->RIOHosts[host].Flags == RC_RUNNING ) {
+						WWORD(p->RIOHosts[host].ParmMapP->timer , value);
+					}
+				}
+			}
+			return 0;
+
+		case RIO_IDENTIFY_DRIVER:
+			/*
+			** 15.10.1998 ARG - ESIL 0760 part fix
+			** Added driver ident string output.
+			**
+#ifndef __THIS_RELEASE__
+#warning Driver Version string not defined !
+#endif
+			cprintf("%s %s %s %s\n",
+				RIO_DRV_STR,
+				__THIS_RELEASE__,
+				__DATE__, __TIME__ );
+
+			return 0;
+
+		case RIO_DISPLAY_HOST_CFG:
+			**
+			** 15.10.1998 ARG - ESIL 0760 part fix
+			** Added driver host card ident string output.
+			**
+			** Note that the only types currently supported
+			** are ISA and PCI. Also this driver does not
+			** (yet) distinguish between the Old PCI card
+			** and the Jet PCI card. In fact I think this
+			** driver only supports JET PCI !
+			**
+
+			for (Host = 0; Host < p->RIONumHosts; Host++)
+			{
+				HostP = &(p->RIOHosts[Host]);
+
+				switch ( HostP->Type )
+				{
+				    case RIO_AT :
+					strcpy( host_type, RIO_AT_HOST_STR );
+					break;
+
+				    case RIO_PCI :
+					strcpy( host_type, RIO_PCI_HOST_STR );
+					break;
+
+				    default :
+					strcpy( host_type, "Unknown" );
+					break;
+				}
+
+				cprintf(
+				  "RIO Host %d - Type:%s Addr:%X IRQ:%d\n",
+					Host, host_type,
+					(uint)HostP->PaddrP,
+					(int)HostP->Ivec - 32  );
+			}
+			return 0;
+			**
+			*/
+
+		case RIO_FOAD_RTA:
+			rio_dprint(RIO_DEBUG_CTRL, ("RIO_FOAD_RTA\n"));
+			return RIOCommandRta(p, (uint)arg, RIOFoadRta);
+
+		case RIO_ZOMBIE_RTA:
+			rio_dprint(RIO_DEBUG_CTRL, ("RIO_ZOMBIE_RTA\n"));
+			return RIOCommandRta(p, (uint)arg, RIOZombieRta);
+
+		case RIO_IDENTIFY_RTA:
+			rio_dprint(RIO_DEBUG_CTRL, ("RIO_IDENTIFY_RTA\n"));
+			return RIOIdentifyRta(p, arg);
+
+		case RIO_KILL_NEIGHBOUR:
+			rio_dprint(RIO_DEBUG_CTRL, ("RIO_KILL_NEIGHBOUR\n"));
+			return RIOKillNeighbour(p, arg);
+
+		case SPECIAL_RUP_CMD:
+			{
+				struct CmdBlk *CmdBlkP;
+
+				rio_dprint(RIO_DEBUG_CTRL, ("SPECIAL_RUP_CMD\n"));
+				if (copyin((int)arg, (caddr_t)&SpecialRupCmd, 
+							sizeof(SpecialRupCmd)) == COPYFAIL ) {
+					rio_dprint(RIO_DEBUG_CTRL, ("SPECIAL_RUP_CMD copy failed\n"));
+					p->RIOError.Error = COPYIN_FAILED;
+		 			return EFAULT;
+				}
+				CmdBlkP = RIOGetCmdBlk();
+				if ( !CmdBlkP ) {
+					rio_dprint(RIO_DEBUG_CTRL, ("SPECIAL_RUP_CMD GetCmdBlk failed\n"));
+					return ENXIO;
+				}
+				CmdBlkP->Packet = SpecialRupCmd.Packet;
+				if ( SpecialRupCmd.Host >= p->RIONumHosts )
+					SpecialRupCmd.Host = 0;
+					rio_dprint(RIO_DEBUG_CTRL, ("Queue special rup command for host %d rup %d\n",
+						SpecialRupCmd.Host, SpecialRupCmd.RupNum));
+					if (RIOQueueCmdBlk(&p->RIOHosts[SpecialRupCmd.Host], 
+							SpecialRupCmd.RupNum, CmdBlkP) == RIO_FAIL) {
+						cprintf("FAILED TO QUEUE SPECIAL RUP COMMAND\n");
+					}
+					return 0;
+				}
+
+			case RIO_DEBUG_MEM:
+#ifdef DEBUG_MEM_SUPPORT
+RIO_DEBUG_CTRL, 				if (su)
+					return rio_RIODebugMemory(RIO_DEBUG_CTRL, arg);
+				else
+#endif
+					return EPERM;
+
+			case RIO_ALL_MODEM:
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_ALL_MODEM\n"));
+				p->RIOError.Error = IOCTL_COMMAND_UNKNOWN;
+				return EINVAL;
+
+			case RIO_GET_TABLE:
+				/*
+				** Read the routing table from the device driver to user space
+				*/
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_GET_TABLE\n"));
+
+				if ((retval = RIOApel(p)) != 0)
+		 			return retval;
+
+				if (copyout((caddr_t)p->RIOConnectTable, (int)arg,
+						TOTAL_MAP_ENTRIES*sizeof(struct Map)) == COPYFAIL) {
+		 			rio_dprint(RIO_DEBUG_CTRL, ("RIO_GET_TABLE copy failed\n"));
+		 			p->RIOError.Error = COPYOUT_FAILED;
+		 			return EFAULT;
+				}
+
+				{
+					int entry;
+					rio_dprint(RIO_DEBUG_CTRL,  ("*****\nMAP ENTRIES\n") );
+					for ( entry=0; entry<TOTAL_MAP_ENTRIES; entry++ )
+					{
+					  if ((p->RIOConnectTable[entry].ID == 0) &&
+					      (p->RIOConnectTable[entry].HostUniqueNum == 0) &&
+					      (p->RIOConnectTable[entry].RtaUniqueNum == 0)) continue;
+					      
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.HostUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].HostUniqueNum ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.RtaUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].RtaUniqueNum ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.ID = 0x%x\n", entry, p->RIOConnectTable[entry].ID ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.ID2 = 0x%x\n", entry, p->RIOConnectTable[entry].ID2 ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Flags = 0x%x\n", entry, (int)p->RIOConnectTable[entry].Flags ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.SysPort = 0x%x\n", entry, (int)p->RIOConnectTable[entry].SysPort ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[0].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Unit ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[0].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Link ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[1].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Unit ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[1].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Link ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[2].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Unit ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[2].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Link ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[3].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Unit ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[4].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Link ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Name = %s\n", entry, p->RIOConnectTable[entry].Name ) );
+					}
+					rio_dprint(RIO_DEBUG_CTRL,  ("*****\nEND MAP ENTRIES\n") );
+				}
+				p->RIOQuickCheck = NOT_CHANGED;	/* a table has been gotten */
+				return 0;
+
+			case RIO_PUT_TABLE:
+				/*
+				** Write the routing table to the device driver from user space
+				*/
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_PUT_TABLE\n"));
+
+				if ( !su ) {
+		 			rio_dprint(RIO_DEBUG_CTRL, ("RIO_PUT_TABLE !Root\n"));
+		 			p->RIOError.Error = NOT_SUPER_USER;
+		 			return EPERM;
+				}
+				if ( copyin((int)arg, (caddr_t)&p->RIOConnectTable[0], 
+					TOTAL_MAP_ENTRIES*sizeof(struct Map) ) == COPYFAIL ) {
+		 			rio_dprint(RIO_DEBUG_CTRL, ("RIO_PUT_TABLE copy failed\n"));
+		 			p->RIOError.Error = COPYIN_FAILED;
+		 			return EFAULT;
+				}
+/*
+***********************************
+				{
+					int entry;
+					rio_dprint(RIO_DEBUG_CTRL,  ("*****\nMAP ENTRIES\n") );
+					for ( entry=0; entry<TOTAL_MAP_ENTRIES; entry++ )
+					{
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.HostUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].HostUniqueNum ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.RtaUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].RtaUniqueNum ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.ID = 0x%x\n", entry, p->RIOConnectTable[entry].ID ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.ID2 = 0x%x\n", entry, p->RIOConnectTable[entry].ID2 ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Flags = 0x%x\n", entry, p->RIOConnectTable[entry].Flags ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.SysPort = 0x%x\n", entry, p->RIOConnectTable[entry].SysPort ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[0].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[0].Unit ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[0].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[0].Link ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[1].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[1].Unit ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[1].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[1].Link ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[2].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[2].Unit ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[2].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[2].Link ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[3].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[3].Unit ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[4].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[3].Link ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Name = %s\n", entry, p->RIOConnectTable[entry].Name ) );
+					}
+					rio_dprint(RIO_DEBUG_CTRL,  ("*****\nEND MAP ENTRIES\n") );
+				}
+***********************************
+*/
+				return RIONewTable(p);
+
+	 		case RIO_GET_BINDINGS :
+				/*
+				** Send bindings table, containing unique numbers of RTAs owned
+				** by this system to user space
+				*/
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_GET_BINDINGS\n"));
+
+				if ( !su )
+				{
+		 			rio_dprint(RIO_DEBUG_CTRL, ("RIO_GET_BINDINGS !Root\n"));
+		 			p->RIOError.Error = NOT_SUPER_USER;
+		 			return EPERM;
+				}
+				if (copyout((caddr_t) p->RIOBindTab, (int)arg, 
+						(sizeof(ulong) * MAX_RTA_BINDINGS)) == COPYFAIL ) {
+		 			rio_dprint(RIO_DEBUG_CTRL, ("RIO_GET_BINDINGS copy failed\n"));
+		 			p->RIOError.Error = COPYOUT_FAILED;
+		 			return EFAULT;
+				}
+				return 0;
+
+	 		case RIO_PUT_BINDINGS :
+			/*
+			** Receive a bindings table, containing unique numbers of RTAs owned
+			** by this system
+			*/
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_PUT_BINDINGS\n"));
+
+				if ( !su )
+				{
+		 			rio_dprint(RIO_DEBUG_CTRL, ("RIO_PUT_BINDINGS !Root\n"));
+		 			p->RIOError.Error = NOT_SUPER_USER;
+		 			return EPERM;
+				}
+				if (copyin((int)arg, (caddr_t)&p->RIOBindTab[0], 
+						(sizeof(ulong) * MAX_RTA_BINDINGS))==COPYFAIL ) {
+		 			rio_dprint(RIO_DEBUG_CTRL, ("RIO_PUT_BINDINGS copy failed\n"));
+		 			p->RIOError.Error = COPYIN_FAILED;
+		 			return EFAULT;
+				}
+				return 0;
+
+			case RIO_BIND_RTA :
+				{
+					int	EmptySlot = -1;
+					/*
+					** Bind this RTA to host, so that it will be booted by 
+					** host in 'boot owned RTAs' mode.
+					*/
+					rio_dprint(RIO_DEBUG_CTRL, ("RIO_BIND_RTA\n"));
+
+					if ( !su ) {
+		 				rio_dprint(RIO_DEBUG_CTRL, ("RIO_BIND_RTA !Root\n"));
+		 				p->RIOError.Error = NOT_SUPER_USER;
+		 				return EPERM;
+					}
+					for (Entry = 0; Entry < MAX_RTA_BINDINGS; Entry++) {
+		 				if ((EmptySlot == -1) && (p->RIOBindTab[Entry] == 0L))
+							EmptySlot = Entry;
+		 				else if (p->RIOBindTab[Entry] == (int) arg) {
+							/*
+							** Already exists - delete
+							*/
+							p->RIOBindTab[Entry] = 0L;
+							rio_dprint(RIO_DEBUG_CTRL, ("Removing Rta %x from p->RIOBindTab\n",
+		 												(int) arg));
+							return 0;
+		 				}
+					}
+					/*
+					** Dosen't exist - add
+					*/
+					if (EmptySlot != -1) {
+		 				p->RIOBindTab[EmptySlot] = (int) arg;
+		 				rio_dprint(RIO_DEBUG_CTRL, ("Adding Rta %x to p->RIOBindTab\n",
+		  					(int) arg));
+					}
+					else {
+		 				rio_dprint(RIO_DEBUG_CTRL, ("p->RIOBindTab full! - Rta %x not added\n",
+		  					(int) arg));
+		 				return 1;
+					}
+					return 0;
+				}
+
+			case RIO_RESUME :
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_RESUME\n"));
+				port = (uint) arg;
+				if ((port < 0) || (port > 511)) {
+		 			rio_dprint(RIO_DEBUG_CTRL, ("RIO_RESUME: Bad port number %d\n", port));
+		 			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+		 			return EINVAL;
+				}
+				PortP = p->RIOPortp[port];
+				if (!PortP->Mapped) {
+		 			rio_dprint(RIO_DEBUG_CTRL, ("RIO_RESUME: Port %d not mapped\n", port));
+		 			p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM;
+		 			return EINVAL;
+				}
+				if (!(PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
+					rio_dprint(RIO_DEBUG_CTRL, ("RIO_RESUME: Port %d not open\n", port));
+		 			return EINVAL;
+				}
+
+				rio_spin_lock_irqsave(&PortP->portSem, flags);
+				if (RIOPreemptiveCmd(p, (p->RIOPortp[port]), RESUME) == 
+										RIO_FAIL) {
+					rio_dprint(RIO_DEBUG_CTRL, ("RIO_RESUME failed\n"));
+					rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+					return EBUSY;
+				}
+				else {
+					rio_dprint(RIO_DEBUG_CTRL, ("RIO_RESUME: Port %d resumed\n", port));
+					PortP->State |= RIO_BUSY;
+				}
+				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+				return retval;
+
+			case RIO_ASSIGN_RTA:
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_ASSIGN_RTA\n"));
+				if ( !su ) {
+					rio_dprint(RIO_DEBUG_CTRL, ("RIO_ASSIGN_RTA !Root\n"));
+					p->RIOError.Error = NOT_SUPER_USER;
+					return EPERM;
+				}
+				if (copyin((int)arg, (caddr_t)&MapEnt, sizeof(MapEnt))
+									== COPYFAIL) {
+					rio_dprint(RIO_DEBUG_CTRL, ("Copy from user space failed\n"));
+					p->RIOError.Error = COPYIN_FAILED;
+					return EFAULT;
+				}
+				return RIOAssignRta(p, &MapEnt);
+
+			case RIO_CHANGE_NAME:
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_CHANGE_NAME\n"));
+				if ( !su ) {
+					rio_dprint(RIO_DEBUG_CTRL, ("RIO_CHANGE_NAME !Root\n"));
+					p->RIOError.Error = NOT_SUPER_USER;
+					return EPERM;
+				}
+				if (copyin((int)arg, (caddr_t)&MapEnt, sizeof(MapEnt))
+						== COPYFAIL) {
+					rio_dprint(RIO_DEBUG_CTRL, ("Copy from user space failed\n"));
+					p->RIOError.Error = COPYIN_FAILED;
+					return EFAULT;
+				}
+				return RIOChangeName(p, &MapEnt);
+
+			case RIO_DELETE_RTA:
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_DELETE_RTA\n"));
+				if ( !su ) {
+		 			rio_dprint(RIO_DEBUG_CTRL, ("RIO_DELETE_RTA !Root\n"));
+		 			p->RIOError.Error = NOT_SUPER_USER;
+		 			return EPERM;
+				}
+				if (copyin((int)arg, (caddr_t)&MapEnt, sizeof(MapEnt))
+							== COPYFAIL ) {
+		 			rio_dprint(RIO_DEBUG_CTRL, ("Copy from data space failed\n"));
+		 			p->RIOError.Error = COPYIN_FAILED;
+		 			return EFAULT;
+				}
+				return RIODeleteRta(p, &MapEnt);
+
+			case RIO_QUICK_CHECK:
+				/*
+				** 09.12.1998 ARG - ESIL 0776 part fix
+				** A customer was using this to get the RTAs
+				** connect/disconnect status.
+				** RIOConCon() had been botched use RIOHalted
+				** to keep track of RTA connections and
+				** disconnections. That has been changed and
+				** RIORtaDisCons in the rio_info struct now
+				** does the job. So we need to return the value
+				** of RIORtaCons instead of RIOHalted.
+				**
+				if (copyout((caddr_t)&p->RIOHalted,(int)arg,
+							sizeof(uint))==COPYFAIL) {
+				**
+				*/
+
+				if (copyout((caddr_t)&p->RIORtaDisCons,(int)arg,
+							sizeof(uint))==COPYFAIL) {
+					p->RIOError.Error = COPYOUT_FAILED;
+					return EFAULT;
+				}
+				return 0;
+
+			case RIO_LAST_ERROR:
+				if (copyout((caddr_t)&p->RIOError, (int)arg, 
+						sizeof(struct Error)) ==COPYFAIL )
+					return EFAULT;
+				return 0;
+
+			case RIO_GET_LOG:
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_GET_LOG\n"));
+#ifdef LOGGING
+				RIOGetLog(arg);
+				return 0;
+#else
+				return EINVAL;
+#endif
+
+			case RIO_GET_MODTYPE:
+				if ( copyin( (int)arg, (caddr_t)&port, 
+									sizeof(uint)) == COPYFAIL )
+				{
+		 			p->RIOError.Error = COPYIN_FAILED;
+		 			return EFAULT;
+				}
+				rio_dprint(RIO_DEBUG_CTRL, ("Get module type for port %d\n", port));
+				if ( port < 0 || port > 511 )
+				{
+		 			rio_dprint(RIO_DEBUG_CTRL, ("RIO_GET_MODTYPE: Bad port number %d\n", port));
+		 			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+		 			return EINVAL;
+				}
+				PortP = (p->RIOPortp[port]);
+				if (!PortP->Mapped)
+				{
+		 			rio_dprint(RIO_DEBUG_CTRL, ("RIO_GET_MODTYPE: Port %d not mapped\n", port));
+		 			p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM;
+		 			return EINVAL;
+				}
+				/*
+				** Return module type of port
+				*/
+				port = PortP->HostP->UnixRups[PortP->RupNum].ModTypes;
+				if (copyout((caddr_t)&port, (int)arg, 
+							sizeof(uint)) == COPYFAIL) {
+		 			p->RIOError.Error = COPYOUT_FAILED;
+		 			return EFAULT;
+				}
+				return(0);
+			/*
+			** 02.03.1999 ARG - ESIL 0820 fix
+			** We are no longer using "Boot Mode", so these ioctls
+			** are not required :
+			**
+	 		case RIO_GET_BOOT_MODE :
+				rio_dprint(RIO_DEBUG_CTRL, ("Get boot mode - %x\n", p->RIOBootMode));
+				**
+				** Return boot state of system - BOOT_ALL, BOOT_OWN or BOOT_NONE
+				**
+				if (copyout((caddr_t)&p->RIOBootMode, (int)arg, 
+						sizeof(p->RIOBootMode)) == COPYFAIL) {
+		 			p->RIOError.Error = COPYOUT_FAILED;
+		 			return EFAULT;
+				}
+				return(0);
+			
+ 			case RIO_SET_BOOT_MODE :
+				p->RIOBootMode = (uint) arg;
+				rio_dprint(RIO_DEBUG_CTRL, ("Set boot mode to 0x%x\n", p->RIOBootMode));
+				return(0);
+			**
+			** End ESIL 0820 fix
+			*/
+
+	 		case RIO_BLOCK_OPENS:
+				rio_dprint(RIO_DEBUG_CTRL, ("Opens block until booted\n"));
+				for ( Entry=0; Entry < RIO_PORTS; Entry++ ) {
+		 			rio_spin_lock_irqsave(&PortP->portSem, flags);
+		 			p->RIOPortp[Entry]->WaitUntilBooted = 1;
+		 			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+				}
+				return 0;
+			
+	 		case RIO_SETUP_PORTS:
+				rio_dprint(RIO_DEBUG_CTRL, ("Setup ports\n"));
+				if (copyin((int)arg, (caddr_t)&PortSetup, sizeof(PortSetup)) 
+						== COPYFAIL ) {
+					 p->RIOError.Error = COPYIN_FAILED;
+					 rio_dprint(RIO_DEBUG_CTRL, ("EFAULT"));
+					 return EFAULT;
+				}
+				if ( PortSetup.From > PortSetup.To || 
+								PortSetup.To >= RIO_PORTS ) {
+					 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					 rio_dprint(RIO_DEBUG_CTRL, ("ENXIO"));
+					 return ENXIO;
+				}
+				if ( PortSetup.XpCps > p->RIOConf.MaxXpCps ||
+					 PortSetup.XpCps < p->RIOConf.MinXpCps ) {
+					 p->RIOError.Error = XPRINT_CPS_OUT_OF_RANGE;
+					 rio_dprint(RIO_DEBUG_CTRL, ("EINVAL"));
+					 return EINVAL;
+				}
+				if ( !p->RIOPortp ) {
+					 cprintf("No p->RIOPortp array!\n");
+					 rio_dprint(RIO_DEBUG_CTRL, ("No p->RIOPortp array!\n"));
+					 return EIO;
+				}
+				rio_dprint(RIO_DEBUG_CTRL, ("entering loop (%d %d)!\n", PortSetup.From, PortSetup.To));
+				for (loop=PortSetup.From; loop<=PortSetup.To; loop++) {
+				rio_dprint(RIO_DEBUG_CTRL, ("in loop (%d)!\n", loop));
+#if 0
+					PortP = p->RIOPortp[loop];
+					if ( !PortP->TtyP )
+						PortP->TtyP = &p->channel[loop];
+
+		 				rio_spin_lock_irqsave(&PortP->portSem, flags);
+						if ( PortSetup.IxAny )
+							PortP->Config |= RIO_IXANY;
+						else
+							PortP->Config &= ~RIO_IXANY;
+						if ( PortSetup.IxOn )
+							PortP->Config |= RIO_IXON;
+						else
+							PortP->Config &= ~RIO_IXON;
+					 
+					 /*
+					 ** If the port needs to wait for all a processes output
+					 ** to drain before closing then this flag will be set.
+					 */
+					 	if (PortSetup.Drain) {
+							PortP->Config |= RIO_WAITDRAIN;
+					 	} else {
+							PortP->Config &= ~RIO_WAITDRAIN;
+					 	}
+					 /*
+					 ** Store setings if locking or unlocking port or if the
+					 ** port is not locked, when setting the store option.
+					 */
+					 if (PortP->Mapped &&
+						 ((PortSetup.Lock && !PortP->Lock) ||
+							(!PortP->Lock &&
+							(PortSetup.Store && !PortP->Store)))) {
+						PortP->StoredTty.iflag = PortP->TtyP->tm.c_iflag;
+						PortP->StoredTty.oflag = PortP->TtyP->tm.c_oflag;
+						PortP->StoredTty.cflag = PortP->TtyP->tm.c_cflag;
+						PortP->StoredTty.lflag = PortP->TtyP->tm.c_lflag;
+						PortP->StoredTty.line = PortP->TtyP->tm.c_line;
+						bcopy(PortP->TtyP->tm.c_cc, PortP->StoredTty.cc,
+					 		NCC + 5);
+					 }
+					 PortP->Lock = PortSetup.Lock;
+					 PortP->Store = PortSetup.Store;
+					 PortP->Xprint.XpCps = PortSetup.XpCps;
+					 bcopy(PortSetup.XpOn,PortP->Xprint.XpOn,MAX_XP_CTRL_LEN);
+					 bcopy(PortSetup.XpOff,PortP->Xprint.XpOff,MAX_XP_CTRL_LEN);
+					 PortP->Xprint.XpOn[MAX_XP_CTRL_LEN-1] = '\0';
+					 PortP->Xprint.XpOff[MAX_XP_CTRL_LEN-1] = '\0';
+					 PortP->Xprint.XpLen = RIOStrlen(PortP->Xprint.XpOn)+
+								RIOStrlen(PortP->Xprint.XpOff);
+					 rio_spin_unlock_irqrestore( &PortP->portSem , flags);
+#endif
+				}
+				rio_dprint(RIO_DEBUG_CTRL, ("after loop (%d)!\n", loop));
+				rio_dprint(RIO_DEBUG_CTRL,  ("Retval:%x\n", retval ) );
+				return retval;
+
+			case RIO_GET_PORT_SETUP :
+				rio_dprint(RIO_DEBUG_CTRL, ("Get port setup\n"));
+				if (copyin((int)arg, (caddr_t)&PortSetup, sizeof(PortSetup)) 
+							== COPYFAIL ) {
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return EFAULT;
+				}
+				if ( PortSetup.From >= RIO_PORTS ) {
+					 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					 return ENXIO;
+				}
+
+				port = PortSetup.To = PortSetup.From;
+				PortSetup.IxAny = (p->RIOPortp[port]->Config & RIO_IXANY) ? 
+													1 : 0;
+				PortSetup.IxOn = (p->RIOPortp[port]->Config & RIO_IXON) ? 
+													1 : 0;
+				PortSetup.Drain = (p->RIOPortp[port]->Config & RIO_WAITDRAIN) ?
+												 	1 : 0;
+				PortSetup.Store = p->RIOPortp[port]->Store;
+				PortSetup.Lock = p->RIOPortp[port]->Lock;
+				PortSetup.XpCps = p->RIOPortp[port]->Xprint.XpCps;
+				bcopy(p->RIOPortp[port]->Xprint.XpOn, PortSetup.XpOn,
+													MAX_XP_CTRL_LEN);
+				bcopy(p->RIOPortp[port]->Xprint.XpOff, PortSetup.XpOff,
+													MAX_XP_CTRL_LEN);
+				PortSetup.XpOn[MAX_XP_CTRL_LEN-1] = '\0';
+				PortSetup.XpOff[MAX_XP_CTRL_LEN-1] = '\0';
+
+				if ( copyout((caddr_t)&PortSetup,(int)arg,sizeof(PortSetup))
+														==COPYFAIL ) {
+					 p->RIOError.Error = COPYOUT_FAILED;
+					 return EFAULT;
+				}
+				return retval;
+
+			case RIO_GET_PORT_PARAMS :
+				rio_dprint(RIO_DEBUG_CTRL, ("Get port params\n"));
+				if (copyin( (int)arg, (caddr_t)&PortParams,
+					sizeof(struct PortParams)) == COPYFAIL) {
+					p->RIOError.Error = COPYIN_FAILED;
+					return EFAULT;
+				}
+				if (PortParams.Port >= RIO_PORTS) {
+					p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					return ENXIO;
+				}
+				PortP = (p->RIOPortp[PortParams.Port]);
+				PortParams.Config = PortP->Config;
+				PortParams.State = PortP->State;
+				rio_dprint(RIO_DEBUG_CTRL, ("Port %d\n", PortParams.Port));
+
+				if (copyout((caddr_t)&PortParams, (int)arg, 
+						sizeof(struct PortParams)) == COPYFAIL ) {
+					 p->RIOError.Error = COPYOUT_FAILED;
+					 return EFAULT;
+				}
+				return retval;
+
+			case RIO_GET_PORT_TTY :
+				rio_dprint(RIO_DEBUG_CTRL, ("Get port tty\n"));
+				if (copyin((int)arg, (caddr_t)&PortTty, sizeof(struct PortTty)) 
+						== COPYFAIL) {
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return EFAULT;
+				}
+				if ( PortTty.port >= RIO_PORTS ) {
+					 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					 return ENXIO;
+				}
+
+				rio_dprint(RIO_DEBUG_CTRL, ("Port %d\n", PortTty.port));
+				PortP = (p->RIOPortp[PortTty.port]);
+#if 0
+				PortTty.Tty.tm.c_iflag = PortP->TtyP->tm.c_iflag;
+				PortTty.Tty.tm.c_oflag = PortP->TtyP->tm.c_oflag;
+				PortTty.Tty.tm.c_cflag = PortP->TtyP->tm.c_cflag;
+				PortTty.Tty.tm.c_lflag = PortP->TtyP->tm.c_lflag;
+#endif
+				if (copyout((caddr_t)&PortTty, (int)arg, 
+							sizeof(struct PortTty)) == COPYFAIL) {
+					p->RIOError.Error = COPYOUT_FAILED;
+					return EFAULT;
+				}
+				return retval;
+
+			case RIO_SET_PORT_TTY :
+				if (copyin((int)arg, (caddr_t)&PortTty, 
+						sizeof(struct PortTty)) == COPYFAIL) {
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return EFAULT;
+				}
+				rio_dprint(RIO_DEBUG_CTRL, ("Set port %d tty\n", PortTty.port));
+				if (PortTty.port >= (ushort) RIO_PORTS) {
+					 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					 return ENXIO;
+				}
+				PortP = (p->RIOPortp[PortTty.port]);
+#if 0
+		 		rio_spin_lock_irqsave(&PortP->portSem, flags);
+				PortP->TtyP->tm.c_iflag = PortTty.Tty.tm.c_iflag;
+				PortP->TtyP->tm.c_oflag = PortTty.Tty.tm.c_oflag;
+				PortP->TtyP->tm.c_cflag = PortTty.Tty.tm.c_cflag;
+				PortP->TtyP->tm.c_lflag = PortTty.Tty.tm.c_lflag;
+				rio_spin_unlock_irqrestore( &PortP->portSem , flags);
+#endif
+
+				RIOParam(PortP, CONFIG, PortP->State & RIO_MODEM, OK_TO_SLEEP);
+				return retval;
+
+			case RIO_SET_PORT_PARAMS :
+				rio_dprint(RIO_DEBUG_CTRL, ("Set port params\n"));
+				if ( copyin((int)arg, (caddr_t)&PortParams, sizeof(PortParams))
+					== COPYFAIL ) {
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return EFAULT;
+				}
+				if (PortParams.Port >= (ushort) RIO_PORTS) {
+					 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					 return ENXIO;
+				}
+				PortP = (p->RIOPortp[PortParams.Port]);
+		 		rio_spin_lock_irqsave(&PortP->portSem, flags);
+				PortP->Config = PortParams.Config;
+				rio_spin_unlock_irqrestore( &PortP->portSem , flags);
+				return retval;
+
+			case RIO_GET_PORT_STATS :
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_GET_PORT_STATS\n"));
+				if ( copyin((int)arg, (caddr_t)&portStats, 
+						sizeof(struct portStats)) == COPYFAIL ) {
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return EFAULT;
+				}
+				if ( portStats.port >= RIO_PORTS ) {
+					 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					 return ENXIO;
+				}
+				PortP = (p->RIOPortp[portStats.port]);
+				portStats.gather = PortP->statsGather;
+				portStats.txchars = PortP->txchars;
+				portStats.rxchars = PortP->rxchars;
+				portStats.opens = PortP->opens;
+				portStats.closes = PortP->closes;
+				portStats.ioctls = PortP->ioctls;
+				if ( copyout((caddr_t)&portStats, (int)arg, 
+							sizeof(struct portStats)) == COPYFAIL ) {
+					 p->RIOError.Error = COPYOUT_FAILED;
+					 return EFAULT;
+				}
+				return retval;
+
+			case RIO_RESET_PORT_STATS :
+				port = (uint) arg;
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_RESET_PORT_STATS\n"));
+				if ( port >= RIO_PORTS ) {
+					 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					 return ENXIO;
+				}
+				PortP = (p->RIOPortp[port]);
+				rio_spin_lock_irqsave(&PortP->portSem, flags);
+				PortP->txchars	= 0;
+				PortP->rxchars	= 0;
+				PortP->opens	= 0;
+				PortP->closes	= 0;
+				PortP->ioctls	= 0;
+				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+				return retval;
+
+			case RIO_GATHER_PORT_STATS :
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_GATHER_PORT_STATS\n"));
+				if ( copyin( (int)arg, (caddr_t)&portStats, 
+						sizeof(struct portStats)) == COPYFAIL ) {
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return EFAULT;
+				}
+				if ( portStats.port >= RIO_PORTS ) {
+					 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					 return ENXIO;
+				}
+				PortP = (p->RIOPortp[portStats.port]);
+				rio_spin_lock_irqsave(&PortP->portSem, flags);
+				PortP->statsGather = portStats.gather;
+				rio_spin_unlock_irqrestore( &PortP->portSem , flags);
+				return retval;
+
+#ifdef DEBUG_SUPPORTED
+			case RIO_READ_LEVELS:
+				{
+					 int num;
+					 rio_dprint(RIO_DEBUG_CTRL, ("RIO_READ_LEVELS\n"));
+					 for ( num=0; RIODbInf[num].Flag; num++ ) ;
+					 rio_dprint(RIO_DEBUG_CTRL, ("%d levels to copy\n",num));
+					 if (copyout((caddr_t)RIODbInf,(int)arg,
+						sizeof(struct DbInf)*(num+1))==COPYFAIL) {
+						rio_dprint(RIO_DEBUG_CTRL, ("ReadLevels Copy failed\n"));
+						p->RIOError.Error = COPYOUT_FAILED;
+						return EFAULT;
+					 }
+					 rio_dprint(RIO_DEBUG_CTRL, ("%d levels to copied\n",num));
+					 return retval;
+				}
+#endif
+
+			 case RIO_READ_CONFIG:
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_READ_CONFIG\n"));
+				if (copyout((caddr_t)&p->RIOConf, (int)arg, 
+							sizeof(struct Conf)) ==COPYFAIL ) {
+					 p->RIOError.Error = COPYOUT_FAILED;
+					 return EFAULT;
+				}
+				return retval;
+
+			case RIO_SET_CONFIG:
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_SET_CONFIG\n"));
+				if ( !su ) {
+					 p->RIOError.Error = NOT_SUPER_USER;
+					 return EPERM;
+				}
+				if ( copyin((int)arg, (caddr_t)&p->RIOConf, sizeof(struct Conf) )
+						==COPYFAIL ) {
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return EFAULT;
+				}
+				/*
+				** move a few value around
+				*/
+				for (Host=0; Host < p->RIONumHosts; Host++)
+					 if ( (p->RIOHosts[Host].Flags & RUN_STATE) == RC_RUNNING )
+					 	WWORD(p->RIOHosts[Host].ParmMapP->timer , 
+								p->RIOConf.Timer);
+				return retval;
+
+			case RIO_START_POLLER:
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_START_POLLER\n"));
+				return EINVAL;
+
+			case RIO_STOP_POLLER:
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_STOP_POLLER\n"));
+				if ( !su ) {
+					 p->RIOError.Error = NOT_SUPER_USER;
+					 return EPERM;
+				}
+				p->RIOPolling = NOT_POLLING;
+				return retval;
+
+			case RIO_SETDEBUG:
+			case RIO_GETDEBUG:
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_SETDEBUG/RIO_GETDEBUG\n"));
+				if ( copyin( (int)arg, (caddr_t)&DebugCtrl, sizeof(DebugCtrl) )
+							==COPYFAIL ) {
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return EFAULT;
+				}
+				if ( DebugCtrl.SysPort == NO_PORT ) {
+					if ( cmd == RIO_SETDEBUG ) {
+						if ( !su ) {
+							p->RIOError.Error = NOT_SUPER_USER;
+							return EPERM;
+						}
+						p->rio_debug = DebugCtrl.Debug;
+						p->RIODebugWait = DebugCtrl.Wait;
+						rio_dprint(RIO_DEBUG_CTRL, ("Set global debug to 0x%x set wait to 0x%x\n",
+							p->rio_debug,p->RIODebugWait));
+					}
+				 	else {
+						rio_dprint(RIO_DEBUG_CTRL, ("Get global debug 0x%x wait 0x%x\n",
+										p->rio_debug,p->RIODebugWait));
+						DebugCtrl.Debug = p->rio_debug;
+						DebugCtrl.Wait  = p->RIODebugWait;
+						if ( copyout((caddr_t)&DebugCtrl,(int)arg,
+								sizeof(DebugCtrl)) == COPYFAIL ) {
+							rio_dprint(RIO_DEBUG_CTRL, ("RIO_SET/GET DEBUG: bad port number %d\n",
+									DebugCtrl.SysPort));
+						 	p->RIOError.Error = COPYOUT_FAILED;
+						 	return EFAULT;
+						}
+					}
+				}
+				else if ( DebugCtrl.SysPort >= RIO_PORTS && 
+							DebugCtrl.SysPort != NO_PORT ) {
+					 rio_dprint(RIO_DEBUG_CTRL, ("RIO_SET/GET DEBUG: bad port number %d\n",
+									DebugCtrl.SysPort));
+					 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					 return ENXIO;
+				}
+				else if ( cmd == RIO_SETDEBUG ) {
+					if ( !su ) {
+						p->RIOError.Error = NOT_SUPER_USER;
+						return EPERM;
+					}
+					rio_spin_lock_irqsave(&PortP->portSem, flags);
+					p->RIOPortp[DebugCtrl.SysPort]->Debug = DebugCtrl.Debug;
+					rio_spin_unlock_irqrestore( &PortP->portSem , flags);
+					rio_dprint(RIO_DEBUG_CTRL, ("RIO_SETDEBUG 0x%x\n",
+								p->RIOPortp[DebugCtrl.SysPort]->Debug));
+				}
+				else {
+					rio_dprint(RIO_DEBUG_CTRL, ("RIO_GETDEBUG 0x%x\n",
+									 p->RIOPortp[DebugCtrl.SysPort]->Debug));
+					DebugCtrl.Debug = p->RIOPortp[DebugCtrl.SysPort]->Debug;
+					if ( copyout((caddr_t)&DebugCtrl,(int)arg,
+								sizeof(DebugCtrl))==COPYFAIL ) {
+						rio_dprint(RIO_DEBUG_CTRL, ("RIO_GETDEBUG: Bad copy to user space\n"));
+						p->RIOError.Error = COPYOUT_FAILED;
+						return EFAULT;
+					}
+				}
+				return retval;
+
+			case RIO_VERSID:
+				/*
+				** Enquire about the release and version.
+				** We return MAX_VERSION_LEN bytes, being a
+				** textual null terminated string.
+				*/
+				rio_dprint(RIO_DEBUG_CTRL,  ("RIO_VERSID\n") );
+				if ( copyout(	(caddr_t)RIOVersid(),
+						(int)arg,
+						sizeof(struct rioVersion) ) == COPYFAIL )
+				{
+					 rio_dprint(RIO_DEBUG_CTRL,  ("RIO_VERSID: Bad copy to user space (host=%d)\n",Host) );
+					 p->RIOError.Error = COPYOUT_FAILED;
+					 return EFAULT;
+				}
+				return retval;
+
+			/*
+			** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+			** !! commented out previous 'RIO_VERSID' functionality !!
+			** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+			**
+			case RIO_VERSID:
+				**
+				** Enquire about the release and version.
+				** We return MAX_VERSION_LEN bytes, being a textual null
+				** terminated string.
+				**
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_VERSID\n"));
+				if (copyout((caddr_t)RIOVersid(), 
+						(int)arg, MAX_VERSION_LEN ) == COPYFAIL ) {
+					 rio_dprint(RIO_DEBUG_CTRL, ("RIO_VERSID: Bad copy to user space\n",Host));
+					 p->RIOError.Error = COPYOUT_FAILED;
+					 return EFAULT;
+				}
+				return retval;
+			**
+			** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+			*/
+
+			case RIO_NUM_HOSTS:
+				/*
+				** Enquire as to the number of hosts located
+				** at init time.
+				*/
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_NUM_HOSTS\n"));
+				if (copyout((caddr_t)&p->RIONumHosts, (int)arg, 
+							sizeof(p->RIONumHosts) )==COPYFAIL ) {
+					 rio_dprint(RIO_DEBUG_CTRL, ("RIO_NUM_HOSTS: Bad copy to user space\n"));
+					 p->RIOError.Error = COPYOUT_FAILED;
+					 return EFAULT;
+				}
+				return retval;
+
+			case RIO_HOST_FOAD:
+				/*
+				** Kill host. This may not be in the final version...
+				*/
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_FOAD %d\n", (int)arg));
+				if ( !su ) {
+					 rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_FOAD: Not super user\n"));
+					 p->RIOError.Error = NOT_SUPER_USER;
+					 return EPERM;
+				}
+				p->RIOHalted = 1;
+				p->RIOSystemUp = 0;
+
+				for ( Host=0; Host<p->RIONumHosts; Host++ ) {
+					 (void)RIOBoardTest( p->RIOHosts[Host].PaddrP, 
+						p->RIOHosts[Host].Caddr, p->RIOHosts[Host].Type, 
+								p->RIOHosts[Host].Slot );
+					 bzero( (caddr_t)&p->RIOHosts[Host].Flags, 
+							((int)&p->RIOHosts[Host].____end_marker____) -
+								 ((int)&p->RIOHosts[Host].Flags) );
+					 p->RIOHosts[Host].Flags  = RC_WAITING;
+#if 0
+					 RIOSetupDataStructs(p);
+#endif
+				}
+				RIOFoadWakeup(p);
+				p->RIONumBootPkts = 0;
+				p->RIOBooting = 0;
+
+#ifdef RINGBUFFER_SUPPORT
+				for( loop=0; loop<RIO_PORTS; loop++ )
+					if ( p->RIOPortp[loop]->TxRingBuffer )
+						sysfree((void *)p->RIOPortp[loop]->TxRingBuffer, 
+							RIOBufferSize );
+#endif
+#if 0
+				bzero((caddr_t)&p->RIOPortp[0],RIO_PORTS*sizeof(struct Port));
+#else
+				printk ("HEEEEELP!\n");
+#endif
+
+				for( loop=0; loop<RIO_PORTS; loop++ ) {
+#if 0
+					p->RIOPortp[loop]->TtyP = &p->channel[loop];
+#endif
+					
+					p->RIOPortp[loop]->portSem = SPIN_LOCK_UNLOCKED;
+					p->RIOPortp[loop]->InUse = NOT_INUSE;
+				}
+
+				p->RIOSystemUp = 0;
+				return retval;
+
+			case RIO_DOWNLOAD:
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_DOWNLOAD\n"));
+				if ( !su ) {
+					 rio_dprint(RIO_DEBUG_CTRL, ("RIO_DOWNLOAD: Not super user\n"));
+					 p->RIOError.Error = NOT_SUPER_USER;
+					 return EPERM;
+				}
+				if ( copyin((int)arg, (caddr_t)&DownLoad, 
+							sizeof(DownLoad) )==COPYFAIL ) {
+					 rio_dprint(RIO_DEBUG_CTRL, ("RIO_DOWNLOAD: Copy in from user space failed\n"));
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return EFAULT;
+				}
+				rio_dprint(RIO_DEBUG_CTRL,  ("Copied in download code for product code 0x%x\n",
+				    DownLoad.ProductCode ) );
+
+				/*
+				** It is important that the product code is an unsigned object!
+				*/
+				if ( DownLoad.ProductCode > MAX_PRODUCT ) {
+					 rio_dprint(RIO_DEBUG_CTRL, ("RIO_DOWNLOAD: Bad product code %d passed\n",
+							DownLoad.ProductCode));
+					 p->RIOError.Error = NO_SUCH_PRODUCT;
+					 return ENXIO;
+				}
+				/*
+				** do something!
+				*/
+				retval = (*(RIOBootTable[DownLoad.ProductCode]))(p, &DownLoad);
+										/* <-- Panic */
+				p->RIOHalted = 0;
+				/*
+				** and go back, content with a job well completed.
+				*/
+				return retval;
+
+			case RIO_PARMS:
+				{
+					uint host;
+
+					if (copyin((int)arg, (caddr_t)&host, 
+							sizeof(host) ) == COPYFAIL ) {
+						rio_dprint(RIO_DEBUG_CTRL, (
+							"RIO_HOST_REQ: Copy in from user space failed\n"));
+						p->RIOError.Error = COPYIN_FAILED;
+						return EFAULT;
+					}
+					/*
+					** Fetch the parmmap
+					*/
+					rio_dprint(RIO_DEBUG_CTRL, ("RIO_PARMS\n"));
+					if ( copyout( (caddr_t)p->RIOHosts[host].ParmMapP, 
+								(int)arg, sizeof(PARM_MAP) )==COPYFAIL ) {
+						p->RIOError.Error = COPYOUT_FAILED;
+						rio_dprint(RIO_DEBUG_CTRL, ("RIO_PARMS: Copy out to user space failed\n"));
+						return EFAULT;
+					}
+				}
+				return retval;
+
+			case RIO_HOST_REQ:
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_REQ\n"));
+				if (copyin((int)arg, (caddr_t)&HostReq, 
+							sizeof(HostReq) )==COPYFAIL ) {
+					 rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_REQ: Copy in from user space failed\n"));
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return EFAULT;
+				}
+				if ( HostReq.HostNum >= p->RIONumHosts ) {
+					 p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+					 rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_REQ: Illegal host number %d\n",
+							HostReq.HostNum));
+					 return ENXIO;
+				}
+				rio_dprint(RIO_DEBUG_CTRL, ("Request for host %d\n", HostReq.HostNum));
+
+				if (copyout((caddr_t)&p->RIOHosts[HostReq.HostNum], 
+					(int)HostReq.HostP,sizeof(struct Host) ) == COPYFAIL) {
+					p->RIOError.Error = COPYOUT_FAILED;
+					rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_REQ: Bad copy to user space\n"));
+					return EFAULT;
+				}
+				return retval;
+
+			 case RIO_HOST_DPRAM:
+				rio_dprint(RIO_DEBUG_CTRL, ("Request for DPRAM\n"));
+				if ( copyin( (int)arg, (caddr_t)&HostDpRam, 
+								sizeof(HostDpRam) )==COPYFAIL ) {
+					rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_DPRAM: Copy in from user space failed\n"));
+					p->RIOError.Error = COPYIN_FAILED;
+					return EFAULT;
+				}
+				if ( HostDpRam.HostNum >= p->RIONumHosts ) {
+					p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+					rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_DPRAM: Illegal host number %d\n",
+										HostDpRam.HostNum));
+					return ENXIO;
+				}
+				rio_dprint(RIO_DEBUG_CTRL, ("Request for host %d\n", HostDpRam.HostNum));
+
+				if (p->RIOHosts[HostDpRam.HostNum].Type == RIO_PCI) {
+					 int off;
+					 /* It's hardware like this that really gets on my tits. */
+					 static unsigned char copy[sizeof(struct DpRam)];
+					for ( off=0; off<sizeof(struct DpRam); off++ )
+						copy[off] = p->RIOHosts[HostDpRam.HostNum].Caddr[off];
+					if ( copyout( (caddr_t)copy, (int)HostDpRam.DpRamP, 
+							sizeof(struct DpRam) ) == COPYFAIL ) {
+						p->RIOError.Error = COPYOUT_FAILED;
+						rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_DPRAM: Bad copy to user space\n"));
+						return EFAULT;
+					}
+				}
+				else if (copyout((caddr_t)p->RIOHosts[HostDpRam.HostNum].Caddr,
+					(int)HostDpRam.DpRamP, 
+						sizeof(struct DpRam) ) == COPYFAIL ) {
+					 p->RIOError.Error = COPYOUT_FAILED;
+					 rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_DPRAM: Bad copy to user space\n"));
+					 return EFAULT;
+				}
+				return retval;
+
+			 case RIO_SET_BUSY:
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_SET_BUSY\n"));
+				if ( (int)arg < 0 || (int)arg > 511 ) {
+					 rio_dprint(RIO_DEBUG_CTRL, ("RIO_SET_BUSY: Bad port number %d\n",(int)arg));
+					 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					 return EINVAL;
+				}
+				rio_spin_lock_irqsave(&PortP->portSem, flags);
+				p->RIOPortp[(int)arg]->State |= RIO_BUSY;
+				rio_spin_unlock_irqrestore( &PortP->portSem , flags);
+				return retval;
+
+			 case RIO_HOST_PORT:
+				/*
+				** The daemon want port information
+				** (probably for debug reasons)
+				*/
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_PORT\n"));
+				if ( copyin((int)arg, (caddr_t)&PortReq, 
+					sizeof(PortReq) )==COPYFAIL ) {
+					rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_PORT: Copy in from user space failed\n"));
+					p->RIOError.Error = COPYIN_FAILED;
+					return EFAULT;
+				}
+
+				if (PortReq.SysPort >= RIO_PORTS) { /* SysPort is unsigned */
+					 rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_PORT: Illegal port number %d\n",
+											PortReq.SysPort));
+					 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					 return ENXIO;
+				}
+				rio_dprint(RIO_DEBUG_CTRL, ("Request for port %d\n", PortReq.SysPort));
+				if (copyout((caddr_t)p->RIOPortp[PortReq.SysPort], 
+							 (int)PortReq.PortP,
+								sizeof(struct Port) ) == COPYFAIL) {
+					 p->RIOError.Error = COPYOUT_FAILED;
+					 rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_PORT: Bad copy to user space\n"));
+					 return EFAULT;
+				}
+				return retval;
+
+			case RIO_HOST_RUP:
+				/*
+				** The daemon want rup information
+				** (probably for debug reasons)
+				*/
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_RUP\n"));
+				if (copyin((int)arg, (caddr_t)&RupReq, 
+						sizeof(RupReq) )==COPYFAIL ) {
+					 rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_RUP: Copy in from user space failed\n"));
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return EFAULT;
+				}
+				if (RupReq.HostNum >= p->RIONumHosts) { /* host is unsigned */
+					 rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_RUP: Illegal host number %d\n",
+								RupReq.HostNum));
+					 p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+					 return ENXIO;
+				}
+				if ( RupReq.RupNum >= MAX_RUP+LINKS_PER_UNIT ) { /* eek! */
+					 rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_RUP: Illegal rup number %d\n",
+							RupReq.RupNum));
+					 p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
+					 return EINVAL;
+				}
+				HostP = &p->RIOHosts[RupReq.HostNum];
+
+				if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
+					 rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_RUP: Host %d not running\n",
+							RupReq.HostNum));
+					 p->RIOError.Error = HOST_NOT_RUNNING;
+					 return EIO;
+				}
+				rio_dprint(RIO_DEBUG_CTRL, ("Request for rup %d from host %d\n",
+						RupReq.RupNum,RupReq.HostNum));
+
+				if (copyout((caddr_t)HostP->UnixRups[RupReq.RupNum].RupP,
+					(int)RupReq.RupP,sizeof(struct RUP) ) == COPYFAIL) {
+					p->RIOError.Error = COPYOUT_FAILED;
+					rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_RUP: Bad copy to user space\n"));
+					return EFAULT;
+				}
+				return retval;
+
+			case RIO_HOST_LPB:
+				/*
+				** The daemon want lpb information
+				** (probably for debug reasons)
+				*/
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_LPB\n"));
+				if (copyin((int)arg, (caddr_t)&LpbReq, 
+					sizeof(LpbReq) )==COPYFAIL ) {
+					 rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_LPB: Bad copy from user space\n"));
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return EFAULT;
+				}
+				if (LpbReq.Host >= p->RIONumHosts) { /* host is unsigned */
+					rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_LPB: Illegal host number %d\n",
+							LpbReq.Host));
+					p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+					return ENXIO;
+				}
+				if ( LpbReq.Link >= LINKS_PER_UNIT ) { /* eek! */
+					 rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_LPB: Illegal link number %d\n",
+							LpbReq.Link));
+					 p->RIOError.Error = LINK_NUMBER_OUT_OF_RANGE;
+					 return EINVAL;
+				}
+				HostP = &p->RIOHosts[LpbReq.Host];
+
+				if ( (HostP->Flags & RUN_STATE) != RC_RUNNING ) {
+					 rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_LPB: Host %d not running\n",
+						LpbReq.Host));
+					 p->RIOError.Error = HOST_NOT_RUNNING;
+					 return EIO;
+				}
+				rio_dprint(RIO_DEBUG_CTRL, ("Request for lpb %d from host %d\n",
+					LpbReq.Link, LpbReq.Host));
+
+				if (copyout((caddr_t)&HostP->LinkStrP[LpbReq.Link],
+					(int)LpbReq.LpbP,sizeof(struct LPB) ) == COPYFAIL) {
+					rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_LPB: Bad copy to user space\n"));
+					p->RIOError.Error = COPYOUT_FAILED;
+					return EFAULT;
+				}
+				return retval;
+
+				/*
+				** Here 3 IOCTL's that allow us to change the way in which
+				** rio logs errors. send them just to syslog or send them
+				** to both syslog and console or send them to just the console.
+				**
+				** See RioStrBuf() in util.c for the other half.
+				*/
+			case RIO_SYSLOG_ONLY:
+				p->RIOPrintLogState = PRINT_TO_LOG;	/* Just syslog */
+				return 0;
+
+			case RIO_SYSLOG_CONS:
+				p->RIOPrintLogState = PRINT_TO_LOG_CONS;/* syslog and console */
+				return 0;
+
+			case RIO_CONS_ONLY:
+				p->RIOPrintLogState = PRINT_TO_CONS;	/* Just console */
+				return 0;
+
+			case RIO_SIGNALS_ON:
+				if ( p->RIOSignalProcess ) {
+					 p->RIOError.Error = SIGNALS_ALREADY_SET;
+					 return EBUSY;
+				}
+				p->RIOSignalProcess = getpid();
+				p->RIOPrintDisabled = DONT_PRINT;
+				return retval;
+
+			case RIO_SIGNALS_OFF:
+				if ( p->RIOSignalProcess != getpid() ) {
+					 p->RIOError.Error = NOT_RECEIVING_PROCESS;
+					 return EPERM;
+				}
+				rio_dprint(RIO_DEBUG_CTRL, ("Clear signal process to zero\n"));
+				p->RIOSignalProcess = 0;
+				return retval;
+
+			case RIO_SET_BYTE_MODE:
+				for ( Host=0; Host<p->RIONumHosts; Host++ )
+					 if ( p->RIOHosts[Host].Type == RIO_AT )
+						 p->RIOHosts[Host].Mode &= ~WORD_OPERATION;
+				return retval;
+
+			case RIO_SET_WORD_MODE:
+				for ( Host=0; Host<p->RIONumHosts; Host++ )
+					 if ( p->RIOHosts[Host].Type == RIO_AT )
+						 p->RIOHosts[Host].Mode |= WORD_OPERATION;
+				return retval;
+
+			case RIO_SET_FAST_BUS:
+				for ( Host=0; Host<p->RIONumHosts; Host++ )
+					 if ( p->RIOHosts[Host].Type == RIO_AT )
+						 p->RIOHosts[Host].Mode |= FAST_AT_BUS;
+				return retval;
+
+			case RIO_SET_SLOW_BUS:
+				for ( Host=0; Host<p->RIONumHosts; Host++ )
+					 if ( p->RIOHosts[Host].Type == RIO_AT )
+						 p->RIOHosts[Host].Mode &= ~FAST_AT_BUS;
+				return retval;
+
+			case RIO_MAP_B50_TO_50:
+			case RIO_MAP_B50_TO_57600:
+			case RIO_MAP_B110_TO_110:
+			case RIO_MAP_B110_TO_115200:
+				rio_dprint(RIO_DEBUG_CTRL, ("Baud rate mapping\n"));
+				port = (uint) arg;
+				if ( port < 0 || port > 511 ) {
+					 rio_dprint(RIO_DEBUG_CTRL, ("Baud rate mapping: Bad port number %d\n", port));
+					 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					 return EINVAL;
+				}
+				rio_spin_lock_irqsave(&PortP->portSem, flags);
+				switch( cmd )
+				{
+					case RIO_MAP_B50_TO_50 :
+						p->RIOPortp[port]->Config |= RIO_MAP_50_TO_50;
+						break;
+					case RIO_MAP_B50_TO_57600 :
+						p->RIOPortp[port]->Config &= ~RIO_MAP_50_TO_50;
+						break;
+					case RIO_MAP_B110_TO_110 :
+						p->RIOPortp[port]->Config |= RIO_MAP_110_TO_110;
+						break;
+					case RIO_MAP_B110_TO_115200 :
+						p->RIOPortp[port]->Config &= ~RIO_MAP_110_TO_110;
+						break;
+				}
+				rio_spin_unlock_irqrestore( &PortP->portSem , flags);
+				return retval;
+
+			case RIO_STREAM_INFO:
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_STREAM_INFO\n"));
+				return EINVAL;
+
+			case RIO_SEND_PACKET:
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_SEND_PACKET\n"));
+				if ( copyin( (int)arg, (caddr_t)&SendPack,
+									sizeof(SendPack) )==COPYFAIL ) {
+					 rio_dprint(RIO_DEBUG_CTRL, ("RIO_SEND_PACKET: Bad copy from user space\n"));
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return EFAULT;
+				}
+				if ( SendPack.PortNum >= 128 ) {
+					 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					 return ENXIO;
+				}
+
+				PortP = p->RIOPortp[SendPack.PortNum];
+				rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+				if ( !can_add_transmit(&PacketP,PortP) ) {
+					 p->RIOError.Error = UNIT_IS_IN_USE;
+					 rio_spin_unlock_irqrestore( &PortP->portSem , flags);
+					 return ENOSPC;
+				}
+
+				for ( loop=0; loop<(ushort)(SendPack.Len & 127); loop++ )
+					 WBYTE(PacketP->data[loop], SendPack.Data[loop] );
+
+				WBYTE(PacketP->len, SendPack.Len);
+
+				add_transmit( PortP );
+				/*
+				** Count characters transmitted for port statistics reporting
+				*/
+				if (PortP->statsGather)
+					 PortP->txchars += (SendPack.Len & 127);
+				rio_spin_unlock_irqrestore( &PortP->portSem , flags);
+				return retval;
+
+			case RIO_NO_MESG:
+				if ( su )
+					 p->RIONoMessage = 1;
+				return su ? 0 : EPERM;
+
+			case RIO_MESG:
+				if ( su )
+					p->RIONoMessage = 0;
+				return su ? 0 : EPERM;
+
+			case RIO_WHAT_MESG:
+				if ( copyout( (caddr_t)&p->RIONoMessage, (int)arg, 
+					sizeof(p->RIONoMessage) )==COPYFAIL ) {
+					rio_dprint(RIO_DEBUG_CTRL, ("RIO_WHAT_MESG: Bad copy to user space\n"));
+					p->RIOError.Error = COPYOUT_FAILED;
+					return EFAULT;
+				}
+				return 0;
+
+			case RIO_MEM_DUMP :
+				if (copyin((int)arg, (caddr_t)&SubCmd, 
+						sizeof(struct SubCmdStruct)) == COPYFAIL) {
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return EFAULT;
+				}
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_MEM_DUMP host %d rup %d addr %x\n", 
+						SubCmd.Host, SubCmd.Rup, SubCmd.Addr));
+
+				if (SubCmd.Rup >= MAX_RUP+LINKS_PER_UNIT ) {
+					 p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
+					 return EINVAL;
+				}
+
+				if (SubCmd.Host >= p->RIONumHosts ) {
+					 p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+					 return EINVAL;
+				}
+
+				port = p->RIOHosts[SubCmd.Host].
+								UnixRups[SubCmd.Rup].BaseSysPort;
+
+				PortP = p->RIOPortp[port];
+
+				rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+				if ( RIOPreemptiveCmd(p,  PortP, MEMDUMP ) == RIO_FAIL ) {
+					 rio_dprint(RIO_DEBUG_CTRL, ("RIO_MEM_DUMP failed\n"));
+					 rio_spin_unlock_irqrestore( &PortP->portSem , flags);
+					 return EBUSY;
+				}
+				else
+					 PortP->State |= RIO_BUSY;
+
+				rio_spin_unlock_irqrestore( &PortP->portSem , flags);
+				if ( copyout( (caddr_t)p->RIOMemDump, (int)arg, 
+							MEMDUMP_SIZE) == COPYFAIL ) {
+					 rio_dprint(RIO_DEBUG_CTRL, ("RIO_MEM_DUMP copy failed\n"));
+					 p->RIOError.Error = COPYOUT_FAILED;
+					 return EFAULT;
+				}
+				return 0;
+
+			case RIO_TICK:
+				if ((int)arg < 0 || (int)arg >= p->RIONumHosts)
+					 return EINVAL;
+				rio_dprint(RIO_DEBUG_CTRL, ("Set interrupt for host %d\n", (int)arg ));
+				WBYTE(p->RIOHosts[(int)arg].SetInt , 0xff);
+				return 0;
+
+			case RIO_TOCK:
+				if ((int)arg < 0 || (int)arg >= p->RIONumHosts)
+					 return EINVAL;
+				rio_dprint(RIO_DEBUG_CTRL, ("Clear interrupt for host %d\n", (int)arg ));
+				WBYTE((p->RIOHosts[(int)arg].ResetInt) , 0xff);
+				return 0;
+
+			case RIO_READ_CHECK:
+				/* Check reads for pkts with data[0] the same */
+				p->RIOReadCheck = !p->RIOReadCheck;
+				if (copyout((caddr_t)&p->RIOReadCheck,(int)arg,
+							sizeof(uint))== COPYFAIL) {
+					 p->RIOError.Error = COPYOUT_FAILED;
+					 return EFAULT;
+				}
+				return 0;
+
+			case RIO_READ_REGISTER :
+				if (copyin((int)arg, (caddr_t)&SubCmd, 
+							sizeof(struct SubCmdStruct)) == COPYFAIL) {
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return EFAULT;
+				}
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_READ_REGISTER host %d rup %d port %d reg %x\n", 
+						SubCmd.Host, SubCmd.Rup, SubCmd.Port, SubCmd.Addr));
+
+				if (SubCmd.Port > 511) {
+					 rio_dprint(RIO_DEBUG_CTRL, ("Baud rate mapping: Bad port number %d\n", 
+								SubCmd.Port));
+					 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					 return EINVAL;
+				}
+
+				if (SubCmd.Rup >= MAX_RUP+LINKS_PER_UNIT ) {
+					 p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
+					 return EINVAL;
+				}
+
+				if (SubCmd.Host >= p->RIONumHosts ) {
+					 p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+					 return EINVAL;
+				}
+
+				port = p->RIOHosts[SubCmd.Host].
+						UnixRups[SubCmd.Rup].BaseSysPort + SubCmd.Port;
+				PortP = p->RIOPortp[port];
+
+				rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+				if (RIOPreemptiveCmd(p, PortP, READ_REGISTER) == RIO_FAIL) {
+					 rio_dprint(RIO_DEBUG_CTRL, ("RIO_READ_REGISTER failed\n"));
+					 rio_spin_unlock_irqrestore( &PortP->portSem , flags);
+					 return EBUSY;
+				}
+				else
+					 PortP->State |= RIO_BUSY;
+
+				rio_spin_unlock_irqrestore( &PortP->portSem , flags);
+				if (copyout((caddr_t)&p->CdRegister, (int)arg, 
+							sizeof(uint)) == COPYFAIL ) {
+					 rio_dprint(RIO_DEBUG_CTRL, ("RIO_READ_REGISTER copy failed\n"));
+					 p->RIOError.Error = COPYOUT_FAILED;
+					 return EFAULT;
+				}
+				return 0;
+				/*
+				** rio_make_dev: given port number (0-511) ORed with port type
+				** (RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT) return dev_t
+				** value to pass to mknod to create the correct device node.
+				*/
+			case RIO_MAKE_DEV:
+				{
+					uint port = (uint)arg & RIO_MODEM_MASK;
+
+					switch ( (uint)arg & RIO_DEV_MASK ) {
+						case RIO_DEV_DIRECT:
+							arg = (caddr_t)drv_makedev(major(dev), port);
+							rio_dprint(RIO_DEBUG_CTRL, ("Makedev direct 0x%x is 0x%x\n",port, (int)arg ));
+							return (int)arg;
+					 	case RIO_DEV_MODEM:
+							arg =  (caddr_t)drv_makedev(major(dev), (port|RIO_MODEM_BIT) );
+							rio_dprint(RIO_DEBUG_CTRL, ("Makedev modem 0x%x is 0x%x\n",port, (int)arg ));
+							return (int)arg;
+						case RIO_DEV_XPRINT:
+							arg = (caddr_t)drv_makedev(major(dev), port);
+							rio_dprint(RIO_DEBUG_CTRL, ("Makedev printer 0x%x is 0x%x\n",port, (int)arg ));
+							return (int)arg;
+					}
+					rio_dprint(RIO_DEBUG_CTRL, ("MAKE Device is called\n"));
+					return EINVAL;
+				}
+				/*
+				** rio_minor: given a dev_t from a stat() call, return
+				** the port number (0-511) ORed with the port type
+				** ( RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT )
+				*/
+			case RIO_MINOR:
+				{
+					dev_t dv;
+					int mino;
+
+					dv = (dev_t)((int)arg);
+					mino = RIO_UNMODEM(dv);
+
+					if ( RIO_ISMODEM(dv) ) {
+						rio_dprint(RIO_DEBUG_CTRL, ("Minor for device 0x%x: modem %d\n", dv, mino));
+						arg = (caddr_t)(mino | RIO_DEV_MODEM);
+					}
+					else {
+						rio_dprint(RIO_DEBUG_CTRL, ("Minor for device 0x%x: direct %d\n", dv, mino));
+						arg = (caddr_t)(mino | RIO_DEV_DIRECT);
+					}
+					return (int)arg;
+				}
+	}
+	rio_dprint(RIO_DEBUG_CTRL, ("INVALID DAEMON IOCTL 0x%x\n",cmd));
+	p->RIOError.Error = IOCTL_COMMAND_UNKNOWN;
+	return EINVAL;
+}
+
+/*
+** Pre-emptive commands go on RUPs and are only one byte long.
+*/
+int
+RIOPreemptiveCmd(p, PortP, Cmd)
+struct rio_info *	p;
+struct Port *PortP;
+uchar Cmd;
+{
+	struct CmdBlk *CmdBlkP;
+	struct PktCmd_M *PktCmdP;
+	int Ret;
+	ushort rup;
+	int port;
+
+#ifdef CHECK
+	CheckPortP( PortP );
+#endif
+
+	if ( PortP->State & RIO_DELETED ) {
+		rio_dprint(RIO_DEBUG_CTRL, ("Preemptive command to deleted RTA ignored\n"));
+		return RIO_FAIL;
+	}
+
+	if (((int)((char)PortP->InUse) == -1) || ! (CmdBlkP = RIOGetCmdBlk()) ) {
+		rio_dprint(RIO_DEBUG_CTRL, ("Cannot allocate command block for command %d on port %d\n",
+		       Cmd, PortP->PortNum));
+		return RIO_FAIL;
+	}
+
+	rio_dprint(RIO_DEBUG_CTRL, ("Command blk 0x%x - InUse now %d\n", 
+	       (int)CmdBlkP,PortP->InUse));
+
+	PktCmdP = (struct PktCmd_M *)&CmdBlkP->Packet.data[0];
+
+	CmdBlkP->Packet.src_unit  = 0;
+	if (PortP->SecondBlock)
+		rup = PortP->ID2;
+	else
+		rup = PortP->RupNum;
+	CmdBlkP->Packet.dest_unit = rup;
+	CmdBlkP->Packet.src_port  = COMMAND_RUP;
+	CmdBlkP->Packet.dest_port = COMMAND_RUP;
+	CmdBlkP->Packet.len	  = PKT_CMD_BIT | 2;
+	CmdBlkP->PostFuncP	= RIOUnUse;
+	CmdBlkP->PostArg	= (int)PortP;
+	PktCmdP->Command	= Cmd;
+	port				= PortP->HostPort % (ushort)PORTS_PER_RTA;
+	/*
+	** Index ports 8-15 for 2nd block of 16 port RTA.
+	*/
+	if (PortP->SecondBlock)
+		port += (ushort) PORTS_PER_RTA;
+	PktCmdP->PhbNum	   = port;
+
+	switch ( Cmd ) {
+		case MEMDUMP:
+			rio_dprint(RIO_DEBUG_CTRL, ("Queue MEMDUMP command blk 0x%x (addr 0x%x)\n",
+			       (int)CmdBlkP, (int)SubCmd.Addr));
+			PktCmdP->SubCommand		= MEMDUMP;
+			PktCmdP->SubAddr		= SubCmd.Addr;
+			break;
+		case FCLOSE:
+			rio_dprint(RIO_DEBUG_CTRL, ("Queue FCLOSE command blk 0x%x\n",(int)CmdBlkP));
+			break;
+		case READ_REGISTER:
+			rio_dprint(RIO_DEBUG_CTRL, ("Queue READ_REGISTER (0x%x) command blk 0x%x\n",
+		 		(int)SubCmd.Addr, (int)CmdBlkP));
+			PktCmdP->SubCommand		= READ_REGISTER;
+			PktCmdP->SubAddr		= SubCmd.Addr;
+			break;
+		case RESUME:
+			rio_dprint(RIO_DEBUG_CTRL, ("Queue RESUME command blk 0x%x\n",(int)CmdBlkP));
+			break;
+		case RFLUSH:
+			rio_dprint(RIO_DEBUG_CTRL, ("Queue RFLUSH command blk 0x%x\n",(int)CmdBlkP));
+			CmdBlkP->PostFuncP = RIORFlushEnable;
+			break;
+		case SUSPEND:
+			rio_dprint(RIO_DEBUG_CTRL, ("Queue SUSPEND command blk 0x%x\n",(int)CmdBlkP));
+			break;
+
+		case MGET :
+			rio_dprint(RIO_DEBUG_CTRL, ("Queue MGET command blk 0x%x\n", (int)CmdBlkP));
+			break;
+
+		case MSET :
+		case MBIC :
+		case MBIS :
+			CmdBlkP->Packet.data[4] = (char) PortP->ModemLines;
+			rio_dprint(RIO_DEBUG_CTRL, ("Queue MSET/MBIC/MBIS command blk 0x%x\n", (int)CmdBlkP));
+			break;
+
+		case WFLUSH:
+			/*
+			** If we have queued up the maximum number of Write flushes
+			** allowed then we should not bother sending any more to the
+			** RTA.
+			*/
+			if ((int)((char)PortP->WflushFlag) == (int)-1) {
+				rio_dprint(RIO_DEBUG_CTRL, ("Trashed WFLUSH, WflushFlag about to wrap!"));
+				RIOFreeCmdBlk(CmdBlkP);
+				return(RIO_FAIL);
+			} else {
+				rio_dprint(RIO_DEBUG_CTRL, ("Queue WFLUSH command blk 0x%x\n",
+				       (int)CmdBlkP));
+				CmdBlkP->PostFuncP = RIOWFlushMark;
+			}
+			break;
+	}
+
+	PortP->InUse++;
+
+	Ret = RIOQueueCmdBlk( PortP->HostP, rup, CmdBlkP );
+
+	return Ret;
+}
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/riodrvr.h linux.15p9/drivers/char/rio/riodrvr.h
--- linux.vanilla/drivers/char/rio/riodrvr.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/riodrvr.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,143 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: riodrvr.h
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 09:22:46
+**	Retrieved	: 11/6/98 09:22:46
+**
+**  ident @(#)riodrvr.h	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __riodrvr_h
+#define __riodrvr_h
+
+#ifdef SCCS_LABELS
+static char *_riodrvr_h_sccs_ = "@(#)riodrvr.h	1.3";
+#endif
+
+#define MEMDUMP_SIZE	32
+#define HZ				100
+#define	MOD_DISABLE	(RIO_NOREAD|RIO_NOWRITE|RIO_NOXPRINT)
+
+
+struct rio_info {
+	int			mode;			/* Intr or polled, word/byte */
+	semtype			RIOIntrSem;		/* Interrupt thread sem */
+	int			current_chan;		/* current channel */
+	int			RIOFailed;		/* Not initialised ? */
+	int			RIOInstallAttempts;	/* no. of rio-install() calls */
+	int			RIOLastPCISearch;	/* status of last search */
+	int			RIONumHosts;		/* Number of RIO Hosts */
+	struct Host		* RIOHosts;		/* RIO Host values */
+	struct Port		**RIOPortp;		/* RIO port values */
+/*
+** 02.03.1999 ARG - ESIL 0820 fix
+** We no longer use RIOBootMode
+**
+	int			RIOBootMode;		* RIO boot mode *
+**
+*/
+	int			RIOPrintDisabled;	/* RIO printing disabled ? */
+	int			RIOPrintLogState;	/* RIO printing state ? */
+	int			RIOPolling;		/* Polling ? */
+/*
+** 09.12.1998 ARG - ESIL 0776 part fix
+** The 'RIO_QUICK_CHECK' ioctl was using RIOHalted.
+** The fix for this ESIL introduces another member (RIORtaDisCons) here to be
+** updated in RIOConCon() - to keep track of RTA connections/disconnections.
+** 'RIO_QUICK_CHECK' now returns the value of RIORtaDisCons.
+*/
+	int			RIOHalted;		/* halted ? */
+	int			RIORtaDisCons;		/* RTA connections/disconnections */
+	uint			RIOReadCheck;		/* Rio read check */
+	uint			RIONoMessage;		/* To display message or not */
+	uint			RIONumBootPkts;		/* how many packets for an RTA */
+	uint			RIOBootCount; 		/* size of RTA code */
+	uint			RIOBooting;		/* count of outstanding boots */
+	uint			RIOSystemUp;		/* Booted ?? */
+	uint			RIOCounting;		/* for counting interrupts */
+	uint			RIOIntCount;		/* # of intr since last check */
+	uint			RIOTxCount;		/* number of xmit intrs  */
+	uint			RIORxCount;		/* number of rx intrs */
+	uint			RIORupCount;		/* number of rup intrs */
+	int			RIXTimer; 
+	int			RIOBufferSize;		/* Buffersize */
+	int			RIOBufferMask;		/* Buffersize */
+
+	int			RIOFirstMajor;		/* First host card's major no */
+
+	uint			RIOLastPortsMapped;	/* highest port number known */
+	uint			RIOFirstPortsMapped;	/* lowest port number known */
+
+	uint			RIOLastPortsBooted;	/* highest port number running */
+	uint			RIOFirstPortsBooted;	/* lowest port number running */
+
+	uint			RIOLastPortsOpened;	/* highest port number running */
+	uint			RIOFirstPortsOpened;	/* lowest port number running */
+
+	/* Flag to say that the topology information has been changed. */
+	uint			RIOQuickCheck; 
+	uint			CdRegister;		/* ??? */
+	int			RIOSignalProcess;	/* Signalling process */
+	int			rio_debug;		/* To debug ... */
+	int			RIODebugWait;		/* For what ??? */
+	int			tpri;			/* Thread prio */
+	int			tid;			/* Thread id */
+	uint			_RIO_Polled;		/* Counter for polling */
+	uint			_RIO_Interrupted;	/* Counter for interrupt */
+	int			intr_tid;		/* iointset return value */
+	int			TxEnSem;		/* TxEnable Semaphore */
+
+
+	struct Error		RIOError;		/* to Identify what went wrong */ 
+	struct Conf		RIOConf;		/* Configuration ??? */
+	struct ttystatics	channel[RIO_PORTS];	/* channel information */
+	char			RIOBootPackets[1+(SIXTY_FOUR_K/RTA_BOOT_DATA_SIZE)]
+								[RTA_BOOT_DATA_SIZE];
+	struct Map		RIOConnectTable[TOTAL_MAP_ENTRIES];
+	struct Map		RIOSavedTable[TOTAL_MAP_ENTRIES];
+
+	/* RTA to host binding table for master/slave operation */
+	ulong			RIOBindTab[MAX_RTA_BINDINGS];
+	/* RTA memory dump variable */
+	uchar			RIOMemDump[MEMDUMP_SIZE]; 
+	struct ModuleInfo 	RIOModuleTypes[MAX_MODULE_TYPES];
+
+};
+
+
+#ifdef linux
+#define debug(x)        printk x
+#else
+#define debug(x)	kkprintf x
+#endif
+
+
+
+#define RIO_RESET_INT	0x7d80
+#define WRBYTE(x,y)		*(volatile unsigned char *)((x)) = \
+					(unsigned char)(y)
+
+#endif	/* __riodrvr.h */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/rioinfo.h linux.15p9/drivers/char/rio/rioinfo.h
--- linux.vanilla/drivers/char/rio/rioinfo.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/rioinfo.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,96 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: rioinfo.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 14:07:49
+**	Retrieved	: 11/6/98 14:07:50
+**
+**  ident @(#)rioinfo.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rioinfo_h
+#define __rioinfo_h
+
+#ifdef SCCS_LABELS
+static char *_rioinfo_h_sccs_ = "@(#)rioinfo.h	1.2";
+#endif
+
+/*
+** Host card data structure
+*/
+struct RioHostInfo {
+	long	location;	/* RIO Card Base I/O address */
+	long	vector;		/* RIO Card IRQ vector */
+	int	bus;		/* ISA/EISA/MCA/PCI */
+	int	mode;		/* pointer to host mode - INTERUPT / POLLED */
+	struct old_sgttyb
+		* Sg;		/* pointer to default term characteristics */
+};
+
+
+/* Mode in rio device info */
+#define INTERRUPTED_MODE	0x01		/* Interrupt is generated */
+#define POLLED_MODE		0x02		/* No interrupt */
+#define AUTO_MODE		0x03		/* Auto mode */
+
+#define WORD_ACCESS_MODE	0x10		/* Word Access Mode */
+#define BYTE_ACCESS_MODE	0x20		/* Byte Access Mode */
+
+
+/* Bus type that RIO supports */
+#define ISA_BUS			0x01		/* The card is ISA */
+#define EISA_BUS		0x02		/* The card is EISA */
+#define MCA_BUS			0x04		/* The card is MCA */
+#define PCI_BUS			0x08		/* The card is PCI */
+
+/*
+** 11.11.1998 ARG - ESIL ???? part fix
+** Moved definition for 'CHAN' here from rioinfo.c (it is now
+** called 'DEF_TERM_CHARACTERISTICS').
+*/
+
+#define DEF_TERM_CHARACTERISTICS \
+{ \
+	B19200, B19200,				/* input and output speed */ \
+	'H' - '@',				/* erase char */ \
+	-1,					/* 2nd erase char */ \
+	'U' - '@',				/* kill char */ \
+	ECHO | CRMOD,				/* mode */ \
+	'C' - '@',				/* interrupt character */ \
+	'\\' - '@',				/* quit char */ \
+	'Q' - '@',				/* start char */ \
+	'S' - '@',				/* stop char */ \
+	'D' - '@',				/* EOF */ \
+	-1,					/* brk */ \
+	(LCRTBS | LCRTERA | LCRTKIL | LCTLECH),	/* local mode word */ \
+	'Z' - '@',				/* process stop */ \
+	'Y' - '@',				/* delayed stop */ \
+	'R' - '@',				/* reprint line */ \
+	'O' - '@',				/* flush output */ \
+	'W' - '@',				/* word erase */ \
+	'V' - '@'				/* literal next char */ \
+}
+
+#endif /* __rioinfo_h */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/rioinit.c linux.15p9/drivers/char/rio/rioinit.c
--- linux.vanilla/drivers/char/rio/rioinit.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/rioinit.c	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,1652 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: rioinit.c
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 10:33:43
+**	Retrieved	: 11/6/98 10:33:49
+**
+**  ident @(#)rioinit.c	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+#ifdef SCCS_LABELS
+static char *_rioinit_c_sccs_ = "@(#)rioinit.c	1.3";
+#endif
+
+#define __NO_VERSION__
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/malloc.h>
+#include <linux/errno.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/string.h>
+#include <asm/semaphore.h>
+#include <asm/uaccess.h>
+
+#include <linux/termios.h>
+#include <linux/serial.h>
+
+#include <linux/compatmac.h>
+#include <linux/generic_serial.h>
+
+
+#include "linux_compat.h"
+#include "typdef.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "top.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "riotypes.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "error.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+#include "control.h"
+#include "cirrus.h"
+#include "rioioctl.h"
+
+
+#undef bcopy
+#define bcopy rio_pcicopy
+
+int
+RIOPCIinit(struct rio_info *p, int Mode);
+
+
+#if 0
+extern int	rio_intr();
+
+/*
+**	Init time code.
+*/
+void
+rioinit( p, info )
+struct rio_info		* p;
+struct RioHostInfo	* info;
+{
+	/*
+	** Multi-Host card support - taking the easy way out - sorry !
+	** We allocate and set up the Host and Port structs when the
+	** driver is called to 'install' the first host.
+	** We check for this first 'call' by testing the RIOPortp pointer.
+	*/
+	if ( !p->RIOPortp )
+	{
+		rio_dprint(RIO_DEBUG_INIT,  ("Allocating and setting up driver data structures\n") );
+
+		RIOAllocDataStructs(p);		/* allocate host/port structs */
+		RIOSetupDataStructs(p);		/* setup topology structs */
+	}
+
+	RIOInitHosts( p, info );	/* hunt down the hardware */
+
+	RIOAllocateInterrupts(p);	/* allocate interrupts */
+	RIOReport(p);			/* show what we found */
+}
+
+/*
+** Initialise the Cards 
+*/ 
+void
+RIOInitHosts(p, info)
+struct rio_info		* p;
+struct RioHostInfo	* info;
+{
+/*
+** 15.10.1998 ARG - ESIL 0762 part fix
+** If there is no ISA card definition - we always look for PCI cards.
+** As we currently only support one host card this lets an ISA card
+** definition take precedence over PLUG and PLAY.
+** No ISA card - we are PLUG and PLAY with PCI.
+*/
+
+	/*
+	** Note - for PCI both these will be zero, that's okay because
+	** RIOPCIInit() fills them in if a card is found.
+	*/
+	p->RIOHosts[p->RIONumHosts].Ivec	= info->vector;
+	p->RIOHosts[p->RIONumHosts].PaddrP	= info->location;
+
+	/*
+	** Check that we are able to accomodate another host
+	*/
+	if ( p->RIONumHosts >= RIO_HOSTS )
+	{
+		p->RIOFailed++;
+		return;
+	}
+
+	if ( info->bus & ISA_BUS )
+	{
+		rio_dprint(RIO_DEBUG_INIT,  ("initialising card %d (ISA)\n", p->RIONumHosts) );
+		RIOISAinit(p, p->mode);
+	}
+	else
+	{
+		rio_dprint(RIO_DEBUG_INIT,  ("initialising card %d (PCI)\n", p->RIONumHosts) );
+		RIOPCIinit(p, RIO_PCI_DEFAULT_MODE);
+	}
+
+	rio_dprint(RIO_DEBUG_INIT,  ("Total hosts initialised so far : %d\n", p->RIONumHosts) );
+
+
+#ifdef FUTURE_RELEASE
+	if (p->bus & EISA_BUS)
+		/* EISA card */
+		RIOEISAinit(p, RIO_EISA_DEFAULT_MODE);
+
+	if (p->bus & MCA_BUS)
+		/* MCA card */
+		RIOMCAinit(p, RIO_MCA_DEFAULT_MODE);
+#endif
+}
+
+/*
+** go through memory for an AT host that we pass in the device info
+** structure and initialise
+*/
+void
+RIOISAinit(p, mode)
+struct rio_info *	p;
+int					mode;
+{
+
+  /* XXX Need to implement this. */
+#if 0
+	p->intr_tid = iointset(p->RIOHosts[p->RIONumHosts].Ivec,
+					(int (*)())rio_intr, (char*)p->RIONumHosts);
+
+	rio_dprint(RIO_DEBUG_INIT,  ("Set interrupt handler, intr_tid = 0x%x\n", p->intr_tid ) );
+
+	if (RIODoAT(p, p->RIOHosts[p->RIONumHosts].PaddrP, mode)) {
+		return;
+	}
+	else {
+		rio_dprint(RIO_DEBUG_INIT, ("RIODoAT failed\n"));
+		p->RIOFailed++;
+	}
+#endif
+
+}
+
+/*
+** RIODoAT :
+**
+** Map in a boards physical address, check that the board is there,
+** test the board and if everything is okay assign the board an entry
+** in the Rio Hosts structure.
+*/
+int
+RIODoAT(p, Base, mode)
+struct rio_info *	p;
+int		Base;
+int		mode;
+{
+#define	FOUND		1
+#define NOT_FOUND	0
+
+	caddr_t		cardAddr;
+
+	/*
+	** Check to see if we actually have a board at this physical address.
+	*/
+	if ((cardAddr = RIOCheckForATCard(Base)) != 0) {
+		/*
+		** Now test the board to see if it is working.
+		*/
+		if (RIOBoardTest(Base, cardAddr, RIO_AT, 0) == RIO_SUCCESS) {
+			/*
+			** Fill out a slot in the Rio host structure.
+			*/
+			if (RIOAssignAT(p, Base, cardAddr, mode)) {
+				return(FOUND);
+			}
+		}
+		RIOMapout(Base, RIO_AT_MEM_SIZE, cardAddr);
+	}
+	return(NOT_FOUND);
+}
+
+caddr_t
+RIOCheckForATCard(Base)
+int		Base;
+{
+	int				off;
+	struct DpRam	*cardp;		/* (Points at the host) */
+	caddr_t			virtAddr;
+	unsigned char			RIOSigTab[24];
+/*
+** Table of values to search for as prom signature of a host card
+*/
+	strcpy(RIOSigTab, "JBJGPGGHINSMJPJR");
+
+	/*
+	** Hey! Yes, You reading this code! Yo, grab a load a this:
+	**
+	** IF the card is using WORD MODE rather than BYTE MODE
+	** then it will occupy 128K of PHYSICAL memory area. So,
+	** you might think that the following Mapin is wrong. Well,
+	** it isn't, because the SECOND 64K of occupied space is an
+	** EXACT COPY of the FIRST 64K. (good?), so, we need only
+	** map it in in one 64K block.
+	*/
+	if (RIOMapin(Base, RIO_AT_MEM_SIZE, &virtAddr) == -1) {
+		rio_dprint(RIO_DEBUG_INIT, ("RIO-init: Couldn't map the board in!\n"));
+		return((caddr_t)0);
+	}
+
+	/*
+	** virtAddr points to the DP ram of the system.
+	** We now cast this to a pointer to a RIO Host,
+	** and have a rummage about in the PROM.
+	*/
+	cardp = (struct DpRam *)virtAddr;
+
+	for (off=0; RIOSigTab[off]; off++) {
+		if ((RBYTE(cardp->DpSignature[off]) & 0xFF) != RIOSigTab[off]) {
+			/*
+			** Signature mismatch - card not at this address
+			*/
+			RIOMapout(Base, RIO_AT_MEM_SIZE, virtAddr);
+			rio_dprint(RIO_DEBUG_INIT, ("RIO-init: Couldn't match the signature 0x%x 0x%x!\n",
+						(int)cardp, off));
+			return((caddr_t)0);
+		}
+	}
+
+	/*
+	** If we get here then we must have found a valid board so return
+	** its virtual address.
+	*/
+	return(virtAddr);
+}
+#endif
+
+/**
+** RIOAssignAT :
+**
+** Fill out the fields in the p->RIOHosts structure now we know we know
+** we have a board present.
+**
+** bits < 0 indicates 8 bit operation requested,
+** bits > 0 indicates 16 bit operation.
+*/
+int
+RIOAssignAT(p, Base, virtAddr, mode)
+struct rio_info *	p;
+int		Base;
+caddr_t	virtAddr;
+int		mode;
+{
+	int		bits;
+	struct DpRam *cardp = (struct DpRam *)virtAddr;
+
+	if ((Base < ONE_MEG) || (mode & BYTE_ACCESS_MODE))
+		bits = BYTE_OPERATION;
+	else
+		bits = WORD_OPERATION;
+
+	/*
+	** Board has passed its scrub test. Fill in all the
+	** transient stuff.
+	*/
+	p->RIOHosts[p->RIONumHosts].Caddr	= virtAddr;
+	p->RIOHosts[p->RIONumHosts].CardP	= (struct DpRam *)virtAddr;
+
+	/*
+	** Revision 01 AT host cards don't support WORD operations,
+	*/
+	if ( RBYTE(cardp->DpRevision) == 01 )
+		bits = BYTE_OPERATION;
+
+	p->RIOHosts[p->RIONumHosts].Type = RIO_AT;
+	p->RIOHosts[p->RIONumHosts].Copy = bcopy;
+											/* set this later */
+	p->RIOHosts[p->RIONumHosts].Slot = -1;
+	p->RIOHosts[p->RIONumHosts].Mode = SLOW_LINKS | SLOW_AT_BUS | bits;
+	WBYTE(p->RIOHosts[p->RIONumHosts].Control, 
+			BOOT_FROM_RAM | EXTERNAL_BUS_OFF | 
+			p->RIOHosts[p->RIONumHosts].Mode | 
+			INTERRUPT_DISABLE );
+	WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt,0xff);
+	WBYTE(p->RIOHosts[p->RIONumHosts].Control,
+			BOOT_FROM_RAM | EXTERNAL_BUS_OFF | 
+			p->RIOHosts[p->RIONumHosts].Mode |
+			INTERRUPT_DISABLE );
+	WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt,0xff);
+	p->RIOHosts[p->RIONumHosts].UniqueNum =
+		((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0])&0xFF)<<0)|
+		((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1])&0xFF)<<8)|
+		((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2])&0xFF)<<16)|
+		((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3])&0xFF)<<24);
+	rio_dprint(RIO_DEBUG_INIT, ("RIO-init: Uniquenum 0x%x\n",p->RIOHosts[p->RIONumHosts].UniqueNum));
+
+	p->RIONumHosts++;
+	rio_dprint(RIO_DEBUG_INIT, ("RIO-init: Tests Passed at 0x%x\n", Base));
+	return(1);
+}
+#if 0
+#ifdef FUTURE_RELEASE
+int RIOMCAinit(int Mode)
+{
+	uchar SlotNumber;
+	caddr_t Caddr;
+	uint	Paddr;
+	uint	Ivec;
+	int	 Handle;
+	int	 ret = 0;
+
+	/*
+	** Valid mode information for MCA cards
+	** is only FAST LINKS
+	*/
+	Mode = (Mode & FAST_LINKS) ? McaTpFastLinks : McaTpSlowLinks;
+	rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"RIOMCAinit(%d)\n",Mode);
+
+
+	/*
+	** Check out each of the slots
+	*/
+	for (SlotNumber = 0; SlotNumber < McaMaxSlots; SlotNumber++) {
+	/*
+	** Enable the slot we want to talk to
+	*/
+	outb( McaSlotSelect, SlotNumber | McaSlotEnable );
+
+	/*
+	** Read the ID word from the slot
+	*/
+	if (((inb(McaIdHigh)<< 8)|inb(McaIdLow)) == McaRIOId)
+	{
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"Potential MCA card in slot %d\n",SlotNumber);
+
+		/*
+		** Card appears to be a RIO MCA card!
+		*/
+		RIOMachineType |= (1<<RIO_MCA);
+
+		/*
+		** Just check we haven't found too many wonderful objects
+		*/
+		if ( RIONumHosts >= RIO_HOSTS )
+		{
+		Rprintf(RIOMesgTooManyCards);
+		return(ret);
+		}
+
+		/*
+		** McaIrqEnable contains the interrupt vector, and a card
+		** enable bit.
+		*/
+		Ivec = inb(McaIrqEnable);
+
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"Ivec is %x\n",Ivec);
+
+		switch ( Ivec & McaIrqMask )
+		{
+		case McaIrq9:
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"IRQ9\n");
+		break;
+		case McaIrq3:
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"IRQ3\n");
+		break;
+		case McaIrq4:
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"IRQ4\n");
+		break;
+		case McaIrq7:
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"IRQ7\n");
+		break;
+		case McaIrq10:
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"IRQ10\n");
+		break;
+		case McaIrq11:
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"IRQ11\n");
+		break;
+		case McaIrq12:
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"IRQ12\n");
+		break;
+		case McaIrq15:
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"IRQ15\n");
+		break;
+		}
+
+		/*
+		** If the card enable bit isn't set, then set it!
+		*/
+		if ((Ivec & McaCardEnable) != McaCardEnable )
+		{
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"McaCardEnable not set - setting!\n");
+		outb(McaIrqEnable,Ivec|McaCardEnable);
+		}
+		else
+		{
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"McaCardEnable already set\n");
+		}
+
+		/*
+		** Convert the IRQ enable mask into something useful
+		*/
+		Ivec = RIOMcaToIvec[Ivec & McaIrqMask];
+
+		/*
+		** Find the physical address
+		*/
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"inb(McaMemory) is %x\n",inb(McaMemory));
+		Paddr = McaAddress(inb(McaMemory));
+
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"MCA card has Ivec %d Addr %x\n",Ivec,Paddr);
+
+		if ( Paddr != 0 )
+		{
+
+		/*
+		** Tell the memory mapper that we want to talk to it
+		*/
+		Handle = RIOMapin( Paddr, RIO_MCA_MEM_SIZE, &Caddr );
+
+		if ( Handle == -1 ) {
+			rio_dprint(RIO_DEBUG_INIT, ("Couldn't map %d bytes at %x\n", RIO_MCA_MEM_SIZE,Paddr);
+			continue;
+		}
+
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"Board mapped to vaddr 0x%x\n",Caddr);
+
+		/*
+		** And check that it is actually there!
+		*/
+		if ( RIOBoardTest( Paddr,Caddr,RIO_MCA,SlotNumber ) == RIO_SUCCESS )
+		{
+			rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"Board has passed test\n");
+			rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,
+	"Slot %d. Type %d. Paddr 0x%x. Caddr 0x%x. Mode 0x%x.\n",
+			SlotNumber,RIO_MCA,Paddr,Caddr,Mode);
+
+			/*
+			** Board has passed its scrub test. Fill in all the
+			** transient stuff.
+			*/
+			p->RIOHosts[RIONumHosts].Slot	 = SlotNumber;
+			p->RIOHosts[RIONumHosts].Ivec	 = Ivec;
+			p->RIOHosts[RIONumHosts].Type	 = RIO_MCA;
+			p->RIOHosts[RIONumHosts].Copy	 = bcopy;
+			p->RIOHosts[RIONumHosts].PaddrP   = Paddr;
+			p->RIOHosts[RIONumHosts].Caddr	= Caddr;
+			p->RIOHosts[RIONumHosts].CardP	= (struct DpRam *)Caddr;
+			p->RIOHosts[RIONumHosts].Mode	 = Mode;
+			WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt , 0xff);
+			p->RIOHosts[RIONumHosts].UniqueNum =
+			((RBYTE(p->RIOHosts[RIONumHosts].Unique[0])&0xFF)<<0)|
+						((RBYTE(p->RIOHosts[RIONumHosts].Unique[1])&0xFF)<<8)|
+			((RBYTE(p->RIOHosts[RIONumHosts].Unique[2])&0xFF)<<16)|
+			((RBYTE(p->RIOHosts[RIONumHosts].Unique[3])&0xFF)<<24);
+			RIONumHosts++;
+			ret++;
+		}
+		else
+		{
+			/*
+			** It failed the test, so ignore it.
+			*/
+			rio_dprint(RIO_DEBUG_INIT, NULL,DBG_FAIL,"TEST FAILED\n");
+			RIOMapout(Paddr, RIO_MCA_MEM_SIZE, Caddr );
+		}
+		}
+		else
+		{
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"Slot %d - Paddr zero!\n",SlotNumber);
+		}
+	}
+	else
+	{
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"Slot %d NOT RIO\n",SlotNumber);
+	}
+	}
+	/*
+	** Now we have checked all the slots, turn off the MCA slot selector
+	*/
+	outb(McaSlotSelect,0);
+	rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"Slot %d NOT RIO\n",SlotNumber);
+	return ret;
+}
+
+int RIOEISAinit( int Mode )
+{
+	static int EISADone = 0;
+	uint Paddr;
+	int PollIntMixMsgDone = 0;
+	caddr_t Caddr;
+	ushort Ident;
+	uchar EisaSlot;
+	uchar Ivec;
+	int ret = 0;
+
+	/*
+	** The only valid mode information for EISA hosts is fast or slow
+	** links.
+	*/
+	Mode = (Mode & FAST_LINKS) ? EISA_TP_FAST_LINKS : EISA_TP_SLOW_LINKS;
+
+	if ( EISADone )
+	{
+	rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"RIOEISAinit() - already done, return.\n");
+		return(0);
+	}
+
+	EISADone++;
+
+	rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"RIOEISAinit()\n");
+
+
+	/*
+	** First check all cards to see if ANY are set for polled mode operation.
+	** If so, set ALL to polled.
+	*/
+
+	for ( EisaSlot=1; EisaSlot<=RIO_MAX_EISA_SLOTS; EisaSlot++ )
+	{
+	Ident = (INBZ(EisaSlot,EISA_PRODUCT_IDENT_HI)<<8) |
+		 INBZ(EisaSlot,EISA_PRODUCT_IDENT_LO);
+
+	/* rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT, "Check EISA slot %d, ID=%x\n",EisaSlot,Ident); */
+
+	if ( Ident == RIO_EISA_IDENT )
+	{
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"Found Specialix product\n");
+
+		if ( INBZ(EisaSlot,EISA_PRODUCT_NUMBER) != RIO_EISA_PRODUCT_CODE )
+		{
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"Not Specialix RIO - Product number %x\n",
+						INBZ(EisaSlot,EISA_PRODUCT_NUMBER));
+		continue;  /* next slot */
+		}
+		/*
+		** Its a Specialix RIO!
+		*/
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"RIO Revision %d\n",
+					INBZ(EisaSlot,EISA_REVISION_NUMBER));
+		
+		RIOMachineType |= (1<<RIO_EISA);
+
+		/*
+		** Just check we haven't found too many wonderful objects
+		*/
+		if ( RIONumHosts >= RIO_HOSTS )
+		{
+		Rprintf(RIOMesgTooManyCards);
+		return 0;
+		}
+
+		/*
+		** Ensure that the enable bit is set!
+		*/
+		OUTBZ( EisaSlot, EISA_ENABLE, RIO_EISA_ENABLE_BIT );
+
+		/*
+		** EISA_INTERRUPT_VEC contains the interrupt vector.
+		*/
+		Ivec = INBZ(EisaSlot,EISA_INTERRUPT_VEC);
+
+#ifdef RIODEBUG
+		switch ( Ivec & EISA_INTERRUPT_MASK )
+		{
+		case EISA_IRQ_3:
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"EISA IRQ 3\n");
+		break;
+		case EISA_IRQ_4:
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"EISA IRQ 4\n");
+		break;
+		case EISA_IRQ_5:
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"EISA IRQ 5\n");
+		break;
+		case EISA_IRQ_6:
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"EISA IRQ 6\n");
+		break;
+		case EISA_IRQ_7:
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"EISA IRQ 7\n");
+		break;
+		case EISA_IRQ_9:
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"EISA IRQ 9\n");
+		break;
+		case EISA_IRQ_10:
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"EISA IRQ 10\n");
+		break;
+		case EISA_IRQ_11:
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"EISA IRQ 11\n");
+		break;
+		case EISA_IRQ_12:
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"EISA IRQ 12\n");
+		break;
+		case EISA_IRQ_14:
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"EISA IRQ 14\n");
+		break;
+		case EISA_IRQ_15:
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"EISA IRQ 15\n");
+		break;
+		case EISA_POLLED:
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"EISA POLLED\n");
+		break;
+		default:
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT|DBG_FAIL,"Shagged interrupt number!\n");
+		Ivec &= EISA_CONTROL_MASK;
+		}
+#endif
+
+		if ( (Ivec & EISA_INTERRUPT_MASK) ==
+		 EISA_POLLED )
+		{
+		RIOWillPoll = 1;
+		break;		/* From EisaSlot loop */
+		}
+	}
+	}
+
+	/*
+	** Do it all again now we know whether to change all cards to polled
+	** mode or not
+	*/
+
+	for ( EisaSlot=1; EisaSlot<=RIO_MAX_EISA_SLOTS; EisaSlot++ )
+	{
+	Ident = (INBZ(EisaSlot,EISA_PRODUCT_IDENT_HI)<<8) |
+		 INBZ(EisaSlot,EISA_PRODUCT_IDENT_LO);
+
+	if ( Ident == RIO_EISA_IDENT )
+	{
+		if ( INBZ(EisaSlot,EISA_PRODUCT_NUMBER) != RIO_EISA_PRODUCT_CODE )
+		continue;  /* next slot */
+
+		/*
+		** Its a Specialix RIO!
+		*/
+		
+		/*
+		** Ensure that the enable bit is set!
+		*/
+		OUTBZ( EisaSlot, EISA_ENABLE, RIO_EISA_ENABLE_BIT );
+
+		/*
+		** EISA_INTERRUPT_VEC contains the interrupt vector.
+		*/
+		Ivec = INBZ(EisaSlot,EISA_INTERRUPT_VEC);
+
+		if ( RIOWillPoll )
+		{
+			/*
+			** If we are going to operate in polled mode, but this
+			** board is configured to be interrupt driven, display
+			** the message explaining the situation to the punter,
+			** assuming we haven't already done so.
+			*/
+
+			if ( !PollIntMixMsgDone &&
+			 (Ivec & EISA_INTERRUPT_MASK) != EISA_POLLED )
+			{
+			Rprintf(RIOMesgAllPolled);
+			PollIntMixMsgDone = 1;
+			}
+
+			/*
+			** Ungraciously ignore whatever the board reports as its
+			** interrupt vector...
+			*/
+
+			Ivec &= ~EISA_INTERRUPT_MASK;
+
+			/*
+			** ...and force it to dance to the poll tune.
+			*/
+
+			Ivec |= EISA_POLLED;
+		}
+
+		/*
+		** Convert the IRQ enable mask into something useful (0-15)
+		*/
+		Ivec = RIOEisaToIvec(Ivec);
+
+		rio_dprint(RIO_DEBUG_INIT, NULL, DBG_INIT, "EISA host in slot %d has Ivec 0x%x\n",
+		 EisaSlot, Ivec);
+
+		/*
+		** Find the physical address
+		*/
+		Paddr = (INBZ(EisaSlot,EISA_MEMORY_BASE_HI)<<24) |
+				(INBZ(EisaSlot,EISA_MEMORY_BASE_LO)<<16);
+
+		rio_dprint(RIO_DEBUG_INIT, NULL, DBG_INIT,"EISA card has Ivec %d Addr %x\n",Ivec,Paddr);
+
+		if ( Paddr == 0 )
+		{
+		rio_dprint(RIO_DEBUG_INIT, NULL, DBG_INIT | DBG_FAIL,
+		 "Board in slot %d configured for address zero!\n", EisaSlot);
+		continue;
+		}
+
+		/*
+		** Tell the memory mapper that we want to talk to it
+		*/
+		rio_dprint(RIO_DEBUG_INIT, NULL, DBG_INIT,"About to map EISA card \n");
+
+		if (RIOMapin( Paddr, RIO_EISA_MEM_SIZE, &Caddr) == -1) {
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_FAIL,"Couldn't map %d bytes at %x\n",
+							RIO_EISA_MEM_SIZE,Paddr);
+		continue;
+		}
+
+		rio_dprint(RIO_DEBUG_INIT, NULL, DBG_INIT,"Board mapped to vaddr 0x%x\n",Caddr);
+
+		/*
+		** And check that it is actually there!
+		*/
+		if ( RIOBoardTest( Paddr,Caddr,RIO_EISA,EisaSlot) == RIO_SUCCESS )
+			{
+		rio_dprint(RIO_DEBUG_INIT, NULL, DBG_INIT,"Board has passed test\n");
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,
+		"Slot %d. Ivec %d. Type %d. Paddr 0x%x. Caddr 0x%x. Mode 0x%x.\n",
+			EisaSlot,Ivec,RIO_EISA,Paddr,Caddr,Mode);
+
+		/*
+		** Board has passed its scrub test. Fill in all the
+		** transient stuff.
+		*/
+		p->RIOHosts[RIONumHosts].Slot	 = EisaSlot;
+		p->RIOHosts[RIONumHosts].Ivec	 = Ivec;
+		p->RIOHosts[RIONumHosts].Type	 = RIO_EISA;
+		p->RIOHosts[RIONumHosts].Copy	 = bcopy;
+				p->RIOHosts[RIONumHosts].PaddrP   = Paddr;
+				p->RIOHosts[RIONumHosts].Caddr	= Caddr;
+		p->RIOHosts[RIONumHosts].CardP	= (struct DpRam *)Caddr;
+				p->RIOHosts[RIONumHosts].Mode	 = Mode;
+		/*
+		** because the EISA prom is mapped into IO space, we
+		** need to copy the unqiue number into the memory area
+		** that it would have occupied, so that the download
+		** code can determine its ID and card type.
+		*/
+	 WBYTE(p->RIOHosts[RIONumHosts].Unique[0],INBZ(EisaSlot,EISA_UNIQUE_NUM_0));
+	 WBYTE(p->RIOHosts[RIONumHosts].Unique[1],INBZ(EisaSlot,EISA_UNIQUE_NUM_1));
+	 WBYTE(p->RIOHosts[RIONumHosts].Unique[2],INBZ(EisaSlot,EISA_UNIQUE_NUM_2));
+	 WBYTE(p->RIOHosts[RIONumHosts].Unique[3],INBZ(EisaSlot,EISA_UNIQUE_NUM_3));
+		p->RIOHosts[RIONumHosts].UniqueNum =
+			((RBYTE(p->RIOHosts[RIONumHosts].Unique[0])&0xFF)<<0)|
+						((RBYTE(p->RIOHosts[RIONumHosts].Unique[1])&0xFF)<<8)|
+			((RBYTE(p->RIOHosts[RIONumHosts].Unique[2])&0xFF)<<16)|
+			((RBYTE(p->RIOHosts[RIONumHosts].Unique[3])&0xFF)<<24);
+		INBZ(EisaSlot,EISA_INTERRUPT_RESET);
+				RIONumHosts++;
+		ret++;
+			}
+		else
+		{
+		/*
+		** It failed the test, so ignore it.
+		*/
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_FAIL,"TEST FAILED\n");
+
+		RIOMapout(Paddr, RIO_EISA_MEM_SIZE, Caddr );
+		}
+	}
+	}
+	if (RIOMachineType & RIO_EISA)
+	return ret+1;
+	return ret;
+}
+#endif
+
+
+#ifndef linux
+
+#define CONFIG_ADDRESS	0xcf8
+#define CONFIG_DATA		0xcfc
+#define FORWARD_REG		0xcfa
+
+
+static int
+read_config(int bus_number, int device_num, int r_number) 
+{
+	unsigned int cav;
+	unsigned int val;
+
+/*
+   Build config_address_value:
+
+      31        24 23        16 15      11 10  8 7        0 
+      ------------------------------------------------------
+      |1| 0000000 | bus_number | device # | 000 | register |
+      ------------------------------------------------------
+*/
+
+	cav = r_number & 0xff;
+	cav |= ((device_num & 0x1f) << 11);
+	cav |= ((bus_number & 0xff) << 16);
+	cav |= 0x80000000; /* Enable bit */
+	outpd(CONFIG_ADDRESS,cav);
+	val = inpd(CONFIG_DATA);
+	outpd(CONFIG_ADDRESS,0);
+	return val;
+}
+
+static
+write_config(bus_number,device_num,r_number,val) 
+{
+	unsigned int cav;
+
+/*
+   Build config_address_value:
+
+      31        24 23        16 15      11 10  8 7        0 
+      ------------------------------------------------------
+      |1| 0000000 | bus_number | device # | 000 | register |
+      ------------------------------------------------------
+*/
+
+	cav = r_number & 0xff;
+	cav |= ((device_num & 0x1f) << 11);
+	cav |= ((bus_number & 0xff) << 16);
+	cav |= 0x80000000; /* Enable bit */
+	outpd(CONFIG_ADDRESS, cav);
+	outpd(CONFIG_DATA, val);
+	outpd(CONFIG_ADDRESS, 0);
+	return val;
+}
+#else
+/* XXX Implement these... */
+static int
+read_config(int bus_number, int device_num, int r_number) 
+{
+  return 0;
+}
+
+static int
+write_config(int bus_number, int device_num, int r_number) 
+{
+  return 0;
+}
+
+#endif
+
+int
+RIOPCIinit(p, Mode)
+struct rio_info	*p;
+int 		Mode;
+{
+	#define MAX_PCI_SLOT		32
+	#define RIO_PCI_JET_CARD	0x200011CB
+
+	static int	slot;	/* count of machine's PCI slots searched so far */
+	caddr_t		Caddr;	/* Virtual address of the current PCI host card. */
+	unsigned char	Ivec;	/* interrupt vector for the current PCI host */
+	unsigned long	Paddr;	/* Physical address for the current PCI host */
+	int		Handle;	/* Handle to Virtual memory allocated for current PCI host */
+
+
+	rio_dprint(RIO_DEBUG_INIT,  ("Search for a RIO PCI card - start at slot %d\n", slot ) );
+
+	/*
+	** Initialise the search status
+	*/
+	p->RIOLastPCISearch	= RIO_FAIL;
+
+	while ( (slot < MAX_PCI_SLOT) & (p->RIOLastPCISearch != RIO_SUCCESS) )
+	{
+		rio_dprint(RIO_DEBUG_INIT,  ("Currently testing slot %d\n", slot ) );
+
+		if (read_config(0,slot,0) == RIO_PCI_JET_CARD) {
+			p->RIOHosts[p->RIONumHosts].Ivec = 0;
+			Paddr = read_config(0,slot,0x18);
+			Paddr = Paddr - (Paddr & 0x1); /* Mask off the io bit */
+
+			if ( (Paddr == 0) || ((Paddr & 0xffff0000) == 0xffff0000) ) {
+				rio_dprint(RIO_DEBUG_INIT,  ("Goofed up slot\n") );	/* what! */
+				slot++;
+				continue;
+			}
+
+			p->RIOHosts[p->RIONumHosts].PaddrP = Paddr;
+			Ivec = (read_config(0,slot,0x3c) & 0xff);
+
+			rio_dprint(RIO_DEBUG_INIT,  ("PCI Host at 0x%x, Intr %d\n", (int)Paddr, Ivec ) );
+
+			Handle = RIOMapin( Paddr, RIO_PCI_MEM_SIZE, &Caddr );
+			if (Handle == -1) {
+				rio_dprint(RIO_DEBUG_INIT,  ("Couldn't map %d bytes at 0x%x\n", RIO_PCI_MEM_SIZE, (int)Paddr ) );
+				slot++;
+				continue;
+			}
+			p->RIOHosts[p->RIONumHosts].Ivec = Ivec + 32;
+			p->intr_tid = iointset(p->RIOHosts[p->RIONumHosts].Ivec,
+						(int (*)())rio_intr, (char *)p->RIONumHosts);
+			if (RIOBoardTest( Paddr, Caddr, RIO_PCI, 0 ) == RIO_SUCCESS) {
+				rio_dprint(RIO_DEBUG_INIT, ("Board has passed test\n"));
+				rio_dprint(RIO_DEBUG_INIT, ("Paddr 0x%x. Caddr 0x%x. Mode 0x%x.\n", Paddr, Caddr, 
+																Mode));
+
+				/*
+				** Board has passed its scrub test. Fill in all the
+				** transient stuff.
+				*/
+				p->RIOHosts[p->RIONumHosts].Slot	   = 0;
+				p->RIOHosts[p->RIONumHosts].Ivec	   = Ivec + 32;
+				p->RIOHosts[p->RIONumHosts].Type	   = RIO_PCI;
+				p->RIOHosts[p->RIONumHosts].Copy	   = rio_pcicopy; 
+				p->RIOHosts[p->RIONumHosts].PaddrP	   = Paddr;
+				p->RIOHosts[p->RIONumHosts].Caddr	   = Caddr;
+				p->RIOHosts[p->RIONumHosts].CardP	   = (struct DpRam *)Caddr;
+				p->RIOHosts[p->RIONumHosts].Mode	   = Mode;
+
+#if 0
+				WBYTE(p->RIOHosts[p->RIONumHosts].Control, 
+						BOOT_FROM_RAM | EXTERNAL_BUS_OFF | 
+						p->RIOHosts[p->RIONumHosts].Mode | 
+						INTERRUPT_DISABLE );
+				WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt,0xff);
+				WBYTE(p->RIOHosts[p->RIONumHosts].Control,
+						BOOT_FROM_RAM | EXTERNAL_BUS_OFF | 
+						p->RIOHosts[p->RIONumHosts].Mode |
+						INTERRUPT_DISABLE );
+				WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt,0xff);
+#else
+				WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff);
+#endif
+				p->RIOHosts[p->RIONumHosts].UniqueNum  =
+					((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0])&0xFF)<<0)|
+					((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1])&0xFF)<<8)|
+					((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2])&0xFF)<<16)|
+					((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3])&0xFF)<<24);
+
+				rio_dprint(RIO_DEBUG_INIT,  ("Unique no 0x%x.\n", 
+				    p->RIOHosts[p->RIONumHosts].UniqueNum ) );
+
+				p->RIOLastPCISearch = RIO_SUCCESS;
+				p->RIONumHosts++;
+			}
+		}
+		slot++;
+	}
+
+	if ( slot >= MAX_PCI_SLOT ) {
+		rio_dprint(RIO_DEBUG_INIT,  ("All %d PCI slots have tested for RIO cards !!!\n",
+		    MAX_PCI_SLOT ) );
+	}
+
+
+	/*
+	** I don't think we want to do this anymore
+	**
+
+	if (!p->RIOLastPCISearch == RIO_FAIL ) {
+		p->RIOFailed++;
+	}
+
+	**
+	*/
+}
+
+#ifdef FUTURE_RELEASE
+void riohalt( void )
+{
+	int host;
+	for ( host=0; host<p->RIONumHosts; host++ )
+	{
+		rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"Stop host %d\n",host);
+		(void)RIOBoardTest( p->RIOHosts[host].PaddrP, p->RIOHosts[host].Caddr, p->RIOHosts[host].Type,p->RIOHosts[host].Slot );
+	}
+}
+#endif
+#endif
+
+static	uchar	val[] = {
+#ifdef VERY_LONG_TEST
+	  0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
+	  0xa5, 0xff, 0x5a, 0x00, 0xff, 0xc9, 0x36, 
+#endif
+	  0xff, 0x00, 0x00 };
+
+#define	TEST_END sizeof(val)
+
+/*
+** RAM test a board. 
+** Nothing too complicated, just enough to check it out.
+*/
+int
+RIOBoardTest(paddr, caddr, type, slot)
+paddr_t	paddr;
+caddr_t	caddr;
+uchar	type;
+int		slot;
+{
+	struct DpRam *DpRam = (struct DpRam *)caddr;
+	char *ram[4];
+	int  size[4];
+	int  op, bank;
+	int  nbanks;
+
+	rio_dprint(RIO_DEBUG_INIT, ("RIO-init: Reset host type=%d, DpRam=0x%x, slot=%d\n",
+			type,(int)DpRam,slot));
+
+	RIOHostReset(type, DpRam, slot);
+
+	/*
+	** Scrub the memory. This comes in several banks:
+	** DPsram1	- 7000h bytes
+	** DPsram2	- 200h  bytes
+	** DPsram3	- 7000h bytes
+	** scratch	- 1000h bytes
+	*/
+
+	rio_dprint(RIO_DEBUG_INIT, ("RIO-init: Setup ram/size arrays\n"));
+
+	size[0] = DP_SRAM1_SIZE;
+	size[1] = DP_SRAM2_SIZE;
+	size[2] = DP_SRAM3_SIZE;
+	size[3] = DP_SCRATCH_SIZE;
+
+	ram[0] = (char *)&DpRam->DpSram1[0];
+	ram[1] = (char *)&DpRam->DpSram2[0];
+	ram[2] = (char *)&DpRam->DpSram3[0];
+	nbanks = (type == RIO_PCI) ? 3 : 4;
+	if (nbanks == 4)
+		ram[3] = (char *)&DpRam->DpScratch[0];
+
+
+	if (nbanks == 3) {
+		rio_dprint(RIO_DEBUG_INIT, ("RIO-init: Memory: 0x%x(0x%x), 0x%x(0x%x), 0x%x(0x%x)\n",
+				(int)ram[0], size[0], (int)ram[1], size[1], (int)ram[2], size[2]));
+	} else {
+		rio_dprint(RIO_DEBUG_INIT, ("RIO-init: 0x%x(0x%x), 0x%x(0x%x), 0x%x(0x%x), 0x%x(0x%x)\n",
+			(int)ram[0], size[0], (int)ram[1], size[1], (int)ram[2], size[2], (int)ram[3], 
+					size[3]));
+	}
+
+	/*
+	** This scrub operation will test for crosstalk between
+	** banks. TEST_END is a magic number, and relates to the offset
+	** within the 'val' array used by Scrub.
+	*/
+	for (op=0; op<TEST_END; op++) {
+		for (bank=0; bank<nbanks; bank++) {
+			if (RIOScrub(op, (BYTE *)ram[bank], size[bank]) == RIO_FAIL) {
+				rio_dprint(RIO_DEBUG_INIT, ("RIO-init: RIOScrub band %d, op %d failed\n", 
+							bank, op));
+				return RIO_FAIL;
+			}
+		}
+	}
+
+	rio_dprint(RIO_DEBUG_INIT, ("Test completed\n"));
+	return RIO_SUCCESS;
+}
+
+
+/*
+** Scrub an area of RAM.
+** Define PRETEST and POSTTEST for a more thorough checking of the
+** state of the memory.
+** Call with op set to an index into the above 'val' array to determine
+** which value will be written into memory.
+** Call with op set to zero means that the RAM will not be read and checked
+** before it is written.
+** Call with op not zero, and the RAM will be read and compated with val[op-1]
+** to check that the data from the previous phase was retained.
+*/
+int
+RIOScrub(op, ram, size)
+int		op;
+BYTE *	ram;
+int		size; 
+{
+	int				off;
+	unsigned char	oldbyte;
+	unsigned char	newbyte;
+	unsigned char	invbyte;
+	unsigned short	oldword;
+	unsigned short	newword;
+	unsigned short	invword;
+	unsigned short	swapword;
+
+	if (op) {
+		oldbyte = val[op-1];
+		oldword = oldbyte | (oldbyte<<8);
+	} else
+	  oldbyte = oldword = 0; /* Tell the compiler we've initilalized them. */
+	newbyte = val[op];
+	newword = newbyte | (newbyte<<8);
+	invbyte = ~newbyte;
+	invword = invbyte | (invbyte<<8);
+
+	/*
+	** Check that the RAM contains the value that should have been left there
+	** by the previous test (not applicable for pass zero)
+	*/
+	if (op) {
+		for (off=0; off<size; off++) {
+			if (RBYTE(ram[off]) != oldbyte) {
+				rio_dprint(RIO_DEBUG_INIT, ("RIO-init: Byte Pre Check 1: BYTE at offset 0x%x should have been=%x, was=%x\n", off, oldbyte, RBYTE(ram[off])));
+				return RIO_FAIL;
+			}
+		}
+		for (off=0; off<size; off+=2) {
+			if (*(ushort *)&ram[off] != oldword) {
+				rio_dprint(RIO_DEBUG_INIT, ("RIO-init: Word Pre Check: WORD at offset 0x%x should have been=%x, was=%x\n",off,oldword,*(ushort *)&ram[off]));
+				rio_dprint(RIO_DEBUG_INIT, ("RIO-init: Word Pre Check: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n",off,RBYTE(ram[off]),off+1,RBYTE(ram[off+1])));
+				return RIO_FAIL;
+			}
+		}
+	}
+
+	/*
+	** Now write the INVERSE of the test data into every location, using
+	** BYTE write operations, first checking before each byte is written
+	** that the location contains the old value still, and checking after
+	** the write that the location contains the data specified - this is
+	** the BYTE read/write test.
+	*/
+	for (off=0; off<size; off++) {
+		if (op && (RBYTE(ram[off]) != oldbyte)) {
+			rio_dprint(RIO_DEBUG_INIT, ("RIO-init: Byte Pre Check 2: BYTE at offset 0x%x should have been=%x, was=%x\n",off,oldbyte,RBYTE(ram[off])));
+			return RIO_FAIL;
+		}
+		WBYTE(ram[off],invbyte);
+		if (RBYTE(ram[off]) != invbyte) {
+			rio_dprint(RIO_DEBUG_INIT, ("RIO-init: Byte Inv Check: BYTE at offset 0x%x should have been=%x, was=%x\n",off,invbyte,RBYTE(ram[off])));
+			return RIO_FAIL;
+		}
+	}
+
+	/*
+	** now, use WORD operations to write the test value into every location,
+	** check as before that the location contains the previous test value
+	** before overwriting, and that it contains the data value written
+	** afterwards.
+	** This is the WORD operation test.
+	*/
+	for (off=0; off<size; off+=2) {
+		if (*(ushort *)&ram[off] != invword) {
+			rio_dprint(RIO_DEBUG_INIT, ("RIO-init: Word Inv Check: WORD at offset 0x%x should have been=%x, was=%x\n",off,invword,*(ushort *)&ram[off]));
+		rio_dprint(RIO_DEBUG_INIT, ("RIO-init: Word Inv Check: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n",off,RBYTE(ram[off]),off+1,RBYTE(ram[off+1])));
+			return RIO_FAIL;
+		}
+
+		*(ushort *)&ram[off] = newword;
+		if ( *(ushort *)&ram[off] != newword ) {
+			rio_dprint(RIO_DEBUG_INIT, ("RIO-init: Post Word Check 1: WORD at offset 0x%x should have been=%x, was=%x\n",off,newword,*(ushort *)&ram[off]));
+			rio_dprint(RIO_DEBUG_INIT, ("RIO-init: Post Word Check 1: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n",off,RBYTE(ram[off]),off+1,RBYTE(ram[off+1])));
+			return RIO_FAIL;
+		}
+	}
+
+	/*
+	** now run through the block of memory again, first in byte mode
+	** then in word mode, and check that all the locations contain the
+	** required test data.
+	*/
+	for (off=0; off<size; off++) {
+		if (RBYTE(ram[off]) != newbyte) {
+			rio_dprint(RIO_DEBUG_INIT, ("RIO-init: Post Byte Check: BYTE at offset 0x%x should have been=%x, was=%x\n",off,newbyte,RBYTE(ram[off])));
+			return RIO_FAIL;
+		}
+	}
+
+	for (off=0; off<size; off+=2) {
+		if ( *(ushort *)&ram[off] != newword ) {
+			rio_dprint(RIO_DEBUG_INIT, ("RIO-init: Post Word Check 2: WORD at offset 0x%x should have been=%x, was=%x\n",off,newword,*(ushort *)&ram[off]));
+			rio_dprint(RIO_DEBUG_INIT, ("RIO-init: Post Word Check 2: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n",off,RBYTE(ram[off]),off+1,RBYTE(ram[off+1])));
+			return RIO_FAIL;
+		}
+	}
+
+	/*
+	** time to check out byte swapping errors
+	*/
+	swapword = invbyte | (newbyte << 8);
+
+	for (off=0; off<size; off+=2) {
+		WBYTE(ram[off],invbyte);
+		WBYTE(ram[off+1],newbyte);
+	}
+
+	for ( off=0; off<size; off+=2 ) {
+		if (*(ushort *)&ram[off] != swapword) {
+			rio_dprint(RIO_DEBUG_INIT, ("RIO-init: SwapWord Check 1: WORD at offset 0x%x should have been=%x, was=%x\n",off,swapword,*((ushort *)&ram[off])));
+			rio_dprint(RIO_DEBUG_INIT, ("RIO-init: SwapWord Check 1: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n",off,RBYTE(ram[off]),off+1,RBYTE(ram[off+1])));
+			return RIO_FAIL;
+		}
+		*((ushort *)&ram[off]) = ~swapword;
+	}
+
+	for (off=0; off<size; off+=2) {
+		if (RBYTE(ram[off]) != newbyte) {
+			rio_dprint(RIO_DEBUG_INIT, ("RIO-init: SwapWord Check 2: BYTE at offset 0x%x should have been=%x, was=%x\n",off,newbyte,RBYTE(ram[off])));
+			return RIO_FAIL;
+		}
+		if (RBYTE(ram[off+1]) != invbyte) {
+			rio_dprint(RIO_DEBUG_INIT, ("RIO-init: SwapWord Check 2: BYTE at offset 0x%x should have been=%x, was=%x\n",off+1,invbyte,RBYTE(ram[off+1])));
+			return RIO_FAIL;
+		}
+		*((ushort *)&ram[off]) = newword;
+	}
+	return RIO_SUCCESS;
+}
+
+/*
+** try to ensure that every host is either in polled mode
+** or is in interrupt mode. Only allow interrupt mode if
+** all hosts can interrupt (why?)
+** and force into polled mode if told to. Patch up the
+** interrupt vector & salute The Queen when you've done.
+*/
+void
+RIOAllocateInterrupts(p)
+struct rio_info *	p;
+{
+	int Host;
+
+	/*
+	** Easy case - if we have been told to poll, then we poll.
+	*/
+	if (p->mode & POLLED_MODE) {
+		RIOStopInterrupts(p, 0, 0);
+		return;
+	}
+
+	/*
+	** check - if any host has been set to polled mode, then all must be.
+	*/
+	for (Host=0; Host<p->RIONumHosts; Host++) {
+		if ( (p->RIOHosts[Host].Type != RIO_AT) &&
+				(p->RIOHosts[Host].Ivec == POLLED) ) {
+			RIOStopInterrupts(p, 1, Host );
+			return;
+		}
+	}
+	for (Host=0; Host<p->RIONumHosts; Host++) {
+		if (p->RIOHosts[Host].Type == RIO_AT) {
+			if ( (p->RIOHosts[Host].Ivec - 32) == 0) {
+				RIOStopInterrupts(p, 2, Host );
+				return;
+			}
+		}
+	}
+}
+
+/*
+** something has decided that we can't be doing with these
+** new-fangled interrupt thingies. Set everything up to just
+** poll.
+*/
+void
+RIOStopInterrupts(p, Reason, Host)
+struct rio_info *	p;
+int	Reason;
+int	Host; 
+{
+#ifdef FUTURE_RELEASE
+	switch (Reason) {
+		case 0:	/* forced into polling by rio_polled */
+			break;
+		case 1:	/* SCU has set 'Host' into polled mode */
+			break;
+		case 2:	/* there aren't enough interrupt vectors for 'Host' */
+			break;
+	}
+#endif
+
+	for (Host=0; Host<p->RIONumHosts; Host++ ) {
+		struct Host *HostP = &p->RIOHosts[Host];
+
+		switch (HostP->Type) {
+			case RIO_AT:
+				/*
+				** The AT host has it's interrupts disabled by clearing the
+				** int_enable bit.
+				*/
+				HostP->Mode &= ~INTERRUPT_ENABLE;
+				HostP->Ivec = POLLED;
+				break;
+#ifdef FUTURE_RELEASE
+			case RIO_EISA:
+				/*
+				** The EISA host has it's interrupts disabled by setting the
+				** Ivec to zero
+				*/
+				HostP->Ivec = POLLED;
+				break;
+#endif
+			case RIO_PCI:
+				/*
+				** The PCI host has it's interrupts disabled by clearing the
+				** int_enable bit, like a regular host card.
+				*/
+				HostP->Mode &= ~RIO_PCI_INT_ENABLE;
+				HostP->Ivec = POLLED;
+				break;
+#ifdef FUTURE_RELEASE
+			case RIO_MCA:
+				/*
+				** There's always one, isn't there?
+				** The MCA host card cannot have it's interrupts disabled.
+				*/
+				RIOPatchVec(HostP);
+				break;
+#endif
+		}
+	}
+}
+
+#if 0
+/*
+** This function is called at init time to setup the data structures.
+*/
+void
+RIOAllocDataStructs(p)
+struct rio_info *	p;
+{
+	int	port,
+		host,
+		tm;
+
+	p->RIOPortp = (struct Port *)sysbrk(RIO_PORTS * sizeof(struct Port));
+	if (!p->RIOPortp) {
+		rio_dprint(RIO_DEBUG_INIT, ("RIO-init: No memory for port structures\n"));
+		p->RIOFailed++;
+		return;
+	} 
+	bzero( p->RIOPortp, sizeof(struct Port) * RIO_PORTS );
+	rio_dprint(RIO_DEBUG_INIT,  ("RIO-init: allocated and cleared memory for port structs\n") );
+	rio_dprint(RIO_DEBUG_INIT,  ("First RIO port struct @0x%x, size=0x%x bytes\n",
+	    (int)p->RIOPortp, sizeof(struct Port) ) );
+
+	for( port=0; port<RIO_PORTS; port++ ) {
+		p->RIOPortp[port].PortNum = port;
+		p->RIOPortp[port].TtyP = &p->channel[port];
+		sreset (p->RIOPortp[port].InUse);	/* Let the first guy uses it */
+		p->RIOPortp[port].portSem = -1;	/* Let the first guy takes it */
+		p->RIOPortp[port].ParamSem = -1;	/* Let the first guy takes it */
+		p->RIOPortp[port].timeout_id = 0;	/* Let the first guy takes it */
+	}
+
+	p->RIOHosts = (struct Host *)sysbrk(RIO_HOSTS * sizeof(struct Host));
+	if (!p->RIOHosts) {
+		rio_dprint(RIO_DEBUG_INIT, ("RIO-init: No memory for host structures\n"));
+		p->RIOFailed++;
+		return;
+	}
+	bzero(p->RIOHosts, sizeof(struct Host)*RIO_HOSTS);
+	rio_dprint(RIO_DEBUG_INIT,  ("RIO-init: allocated and cleared memory for host structs\n"));
+	rio_dprint(RIO_DEBUG_INIT,  ("First RIO host struct @0x%x, size=0x%x bytes\n",
+	    (int)p->RIOHosts, sizeof(struct Host) ) );
+
+	for( host=0; host<RIO_HOSTS; host++ ) {
+		p->RIOHosts[host].HostLock = -1; /* Let the first guy takes it */
+		p->RIOHosts[host].timeout_id = 0; /* Let the first guy takes it */
+	}
+	/*
+	** check that the buffer size is valid, round down to the next power of
+	** two if necessary; if the result is zero, then, hey, no double buffers.
+	*/
+	for ( tm = 1; tm && tm <= p->RIOConf.BufferSize; tm <<= 1 )
+		;
+	tm >>= 1;
+	p->RIOBufferSize = tm;
+	p->RIOBufferMask = tm ? tm - 1 : 0;
+}
+
+/*
+** this function gets called whenever the data structures need to be
+** re-setup, for example, after a riohalt (why did I ever invent it?)
+*/
+void
+RIOSetupDataStructs(p)
+struct rio_info	* p;
+{
+	int host, entry, rup;
+
+	for ( host=0; host<RIO_HOSTS; host++ ) {
+		struct Host *HostP = &p->RIOHosts[host];
+		for ( entry=0; entry<LINKS_PER_UNIT; entry++ ) {
+			HostP->Topology[entry].Unit = ROUTE_DISCONNECT;
+			HostP->Topology[entry].Link = NO_LINK;
+		}
+		bcopy("HOST X", HostP->Name, 7);
+		HostP->Name[5] = '1'+host;
+		for (rup=0; rup<(MAX_RUP + LINKS_PER_UNIT); rup++) {
+			if (rup < MAX_RUP) {
+				for (entry=0; entry<LINKS_PER_UNIT; entry++ ) {
+					HostP->Mapping[rup].Topology[entry].Unit = ROUTE_DISCONNECT;
+					HostP->Mapping[rup].Topology[entry].Link = NO_LINK;
+				}
+				RIODefaultName(p, HostP, rup);
+			}
+			HostP->UnixRups[rup].RupLock = -1;
+		}
+	}
+}
+#endif
+
+int
+RIODefaultName(p, HostP, UnitId)
+struct rio_info *	p;
+struct Host *	HostP;
+uint			UnitId;
+{
+#ifdef CHECK
+	CheckHost( Host );
+	CheckUnitId( UnitId );
+#endif
+	bcopy("UNKNOWN RTA X-XX",HostP->Mapping[UnitId].Name,17);
+	HostP->Mapping[UnitId].Name[12]='1'+(HostP-p->RIOHosts);
+	if ((UnitId+1) > 9) {
+		HostP->Mapping[UnitId].Name[14]='0'+((UnitId+1)/10);
+		HostP->Mapping[UnitId].Name[15]='0'+((UnitId+1)%10);
+	}
+	else {
+		HostP->Mapping[UnitId].Name[14]='1'+UnitId;
+		HostP->Mapping[UnitId].Name[15]=0;
+	}
+	return 0;
+}
+
+#define RIO_RELEASE	"Linux"
+#define RELEASE_ID	"1.0"
+
+int
+RIOReport(p)
+struct rio_info *	p;
+{
+	char *	RIORelease = RIO_RELEASE;
+	char *	RIORelID = RELEASE_ID;
+	int		host;
+
+	rio_dprint(RIO_DEBUG_INIT, ("RIO : Release: %s ID: %s\n", RIORelease, RIORelID));
+
+	if ( p->RIONumHosts==0 ) {
+		rio_dprint(RIO_DEBUG_INIT, ("\nNo Hosts configured\n"));
+		return(0);
+	}
+
+	for ( host=0; host < p->RIONumHosts; host++ ) {
+		struct Host *HostP = &p->RIOHosts[host];
+		switch ( HostP->Type ) {
+			case RIO_AT:
+				rio_dprint(RIO_DEBUG_INIT, ("AT BUS : found the card at 0x%x\n", HostP->PaddrP));
+		}
+	}
+	return 0;
+}
+
+/*
+** This function returns release/version information as used by ioctl() calls
+** It returns a MAX_VERSION_LEN byte string, null terminated.
+*/
+char *
+OLD_RIOVersid( void )
+{
+	static char	Info[MAX_VERSION_LEN];
+	char *	RIORelease = RIO_RELEASE;
+	char *	cp;
+	int		ct = 0;
+
+	for ( ct=0; RIORelease[ct] && ct<MAX_VERSION_LEN; ct++ )
+		Info[ct] = RIORelease[ct];
+	if ( ct>=MAX_VERSION_LEN ) {
+		Info[MAX_VERSION_LEN-1] = '\0';
+		return Info;
+	}
+	Info[ct++]=' ';
+	if ( ct>=MAX_VERSION_LEN ) {
+		Info[MAX_VERSION_LEN-1] = '\0';
+		return Info;
+	}
+
+	cp="";	/* Fill the RCS Id here */
+
+	while ( *cp && ct<MAX_VERSION_LEN )
+		Info[ct++] = *cp++;
+	if ( ct<MAX_VERSION_LEN-1 )
+		Info[ct] = '\0';
+	Info[MAX_VERSION_LEN-1] = '\0';
+	return Info;
+}
+
+
+static struct rioVersion	stVersion;
+
+struct rioVersion *
+RIOVersid(void)
+{
+    strncpy(stVersion.version, "RIO driver for linux V1.0", 255);
+    strncpy(stVersion.buildDate, __DATE__, 255);
+
+    return &stVersion;
+}
+
+#if 0
+int
+RIOMapin(paddr, size, vaddr)
+paddr_t		paddr;
+int			size;
+caddr_t *	vaddr;
+{
+	*vaddr = (caddr_t)permap( (long)paddr, size);
+	return ((int)*vaddr);
+}
+
+void
+RIOMapout(paddr, size, vaddr)
+paddr_t		paddr;
+long		size;
+caddr_t 	vaddr;
+{
+}
+#endif
+
+
+void
+RIOHostReset(Type, DpRamP, Slot)
+uint Type;
+volatile struct DpRam *DpRamP;
+uint Slot; 
+{
+	/*
+	** Reset the Tpu
+	*/
+	rio_dprint(RIO_DEBUG_INIT,  ("RIOHostReset: type 0x%x", Type ) );
+	switch ( Type ) {
+		case RIO_AT:
+			rio_dprint(RIO_DEBUG_INIT, (" (RIO_AT)\n"));
+			WBYTE(DpRamP->DpControl,  BOOT_FROM_RAM | EXTERNAL_BUS_OFF | 
+					  INTERRUPT_DISABLE | BYTE_OPERATION |
+					  SLOW_LINKS | SLOW_AT_BUS);
+			WBYTE(DpRamP->DpResetTpu, 0xFF);
+			rio_udelay (3);
+
+			rio_dprint(RIO_DEBUG_INIT,  ("RIOHostReset: Don't know if it worked. Try reset again\n") );
+			WBYTE(DpRamP->DpControl,  BOOT_FROM_RAM | EXTERNAL_BUS_OFF |
+					  INTERRUPT_DISABLE | BYTE_OPERATION |
+					  SLOW_LINKS | SLOW_AT_BUS);
+			WBYTE(DpRamP->DpResetTpu, 0xFF);
+			rio_udelay (3);
+			break;
+#ifdef FUTURE_RELEASE
+	case RIO_EISA:
+	/*
+	** Bet this doesn't work!
+	*/
+	OUTBZ( Slot, EISA_CONTROL_PORT,
+		EISA_TP_RUN		| EISA_TP_BUS_DISABLE   |
+		EISA_TP_SLOW_LINKS | EISA_TP_BOOT_FROM_RAM );
+	OUTBZ( Slot, EISA_CONTROL_PORT,
+		EISA_TP_RESET	  | EISA_TP_BUS_DISABLE   | 
+		EISA_TP_SLOW_LINKS | EISA_TP_BOOT_FROM_RAM );
+	suspend( 3 );
+	OUTBZ( Slot, EISA_CONTROL_PORT,
+		EISA_TP_RUN		| EISA_TP_BUS_DISABLE   | 
+		EISA_TP_SLOW_LINKS | EISA_TP_BOOT_FROM_RAM );
+	break;
+	case RIO_MCA:
+	WBYTE(DpRamP->DpControl  , McaTpBootFromRam | McaTpBusDisable );
+	WBYTE(DpRamP->DpResetTpu , 0xFF );
+	suspend( 3 );
+	WBYTE(DpRamP->DpControl  , McaTpBootFromRam | McaTpBusDisable );
+	WBYTE(DpRamP->DpResetTpu , 0xFF );
+	suspend( 3 );
+		break;
+#endif
+	case RIO_PCI:
+		rio_dprint(RIO_DEBUG_INIT,  (" (RIO_PCI)\n") );
+		DpRamP->DpControl  = RIO_PCI_BOOT_FROM_RAM;
+		DpRamP->DpResetInt = 0xFF;
+		DpRamP->DpResetTpu = 0xFF;
+		rio_udelay (100);
+		/* for (i=0; i<6000; i++);  */
+		/* suspend( 3 ); */
+		break;
+#ifdef FUTURE_RELEASE
+	default:
+	Rprintf(RIOMesgNoSupport,Type,DpRamP,Slot);
+	return;
+#endif
+
+	default:
+		rio_dprint(RIO_DEBUG_INIT,  (" (UNKNOWN)\n") );
+		break;
+	}
+	return;
+}
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/riointr.c linux.15p9/drivers/char/rio/riointr.c
--- linux.vanilla/drivers/char/rio/riointr.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/riointr.c	Fri Jan 21 18:58:25 2000
@@ -0,0 +1,1113 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: riointr.c
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 10:33:44
+**	Retrieved	: 11/6/98 10:33:49
+**
+**  ident @(#)riointr.c	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+#ifdef SCCS_LABELS
+static char *_riointr_c_sccs_ = "@(#)riointr.c	1.2";
+#endif
+
+
+#define __NO_VERSION__
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/malloc.h>
+#include <linux/errno.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/string.h>
+#include <asm/semaphore.h>
+#include <asm/uaccess.h>
+
+#include <linux/termios.h>
+#include <linux/serial.h>
+
+#include <linux/compatmac.h>
+#include <linux/generic_serial.h>
+
+#include <linux/delay.h>
+
+#include "linux_compat.h"
+#include "rio_linux.h"
+#include "typdef.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "top.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "riotypes.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "error.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+#include "control.h"
+#include "cirrus.h"
+#include "rioioctl.h"
+
+
+
+
+/*
+** riopoll is called every clock tick. Once the /dev/rio device has been
+** opened, and polldistributed( ) has been called, this routine is called
+** every clock tick *by every cpu*. The 'interesting' piece of code that
+** manipulates 'RIONumCpus' and 'RIOCpuCountdown' is used to fair-share
+** the work between the CPUs. If there are 'N' cpus, then each poll time
+** we increment a counter, modulo 'N-1'. When this counter is 0, we call
+** the interrupt handler. This has the effect that polls are serviced
+** by processor 'N', 'N-1', 'N-2', ... '0', round and round. Neat.
+*/
+void
+riopoll(p)
+struct rio_info *	p;
+{
+	int   host;
+
+	/*
+	** Here's the deal. We try to fair share as much as possible amongst
+	** all the processors that are available. Since each processor 
+	** should generate HZ ticks per second and since we only need HZ ticks
+	** in total for proper operation we simply attempt to cycle round each
+	** processor in turn, using RIOCpuCountdown to decide whether to call
+	** the interrupt routine. ( In fact the count zeroes when it reaches
+	** one less than the total number of processors - so e.g. on a two
+	** processor system RIOService will get called 2*HZ times per second. )
+	** this_cpu (cur_cpu()) tells us the number of the current processor
+	** as follows:
+	**
+	**		0 - default CPU
+	**		1 - first extra CPU
+	**		2 - second extra CPU
+	**		etc.
+	*/
+
+	/*
+	** okay, we've got a cpu that hasn't had a go recently 
+	** - lets check to see what needs doing.
+	*/
+	for ( host=0; host<p->RIONumHosts; host++ ) {
+		struct Host *HostP = &p->RIOHosts[host];
+
+		rio_spin_lock( &HostP->HostLock );
+
+		if ( ( (HostP->Flags & RUN_STATE) != RC_RUNNING ) ||
+		     HostP->InIntr ) {
+			rio_spin_unlock (&HostP->HostLock); 
+			continue;
+		}
+
+		if ( RWORD( HostP->ParmMapP->rup_intr ) ||
+			 RWORD( HostP->ParmMapP->rx_intr  ) ||
+			 RWORD( HostP->ParmMapP->tx_intr  ) ) {
+			HostP->InIntr = 1;
+
+#ifdef FUTURE_RELEASE
+			if( HostP->Type == RIO_EISA )
+				INBZ( HostP->Slot, EISA_INTERRUPT_RESET );
+			else
+#endif
+				WBYTE( HostP->ResetInt , 0xff );
+
+			rio_spin_lock(&HostP->HostLock); 
+
+			p->_RIO_Polled++;
+			RIOServiceHost(p, HostP, 'p' );
+			rio_spin_lock( &HostP->HostLock); 
+			HostP->InIntr = 0;
+			rio_spin_unlock (&HostP->HostLock);
+		}
+	}
+	rio_spin_unlock (&p->RIOIntrSem); 
+}
+
+
+char *firstchars (char *p, int nch)
+{
+  static char buf[2][128];
+  static int t=0;
+  t = ! t;
+  memcpy (buf[t], p, nch);
+  buf[t][nch] = 0;
+  return buf[t];
+}
+
+
+#define	INCR( P, I )	((P) = (((P)+(I)) & p->RIOBufferMask))
+/* Enable and start the transmission of packets */
+void
+RIOTxEnable(en)
+char *		en;
+{
+  struct Port *	PortP;
+  struct rio_info *p;
+  struct tty_struct* tty;
+  int c;
+  struct PKT *	PacketP;
+  unsigned long flags;
+
+  PortP = (struct Port *)en; 
+  p = (struct rio_info *)PortP->p;
+  tty = PortP->gs.tty;
+
+
+  rio_dprint (RIO_DEBUG_INTR, ("tx port %d: %d chars queued.\n", 
+	      PortP->PortNum, PortP->gs.xmit_cnt));
+
+  if (!PortP->gs.xmit_cnt) return;
+  
+
+  /* This routine is an order of magnitude simpler than the specialix
+     version. One of the disadvantages is that this version will send
+     an incomplete packet (usually 64 bytes instead of 72) once for
+     every 4k worth of data. Let's just say that this won't influence
+     performance significantly..... */
+
+  rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+  while (can_add_transmit( &PacketP, PortP )) {
+    c = PortP->gs.xmit_cnt;
+    if (c > PKT_MAX_DATA_LEN) c = PKT_MAX_DATA_LEN;
+
+    /* Don't copy past the end of the source buffer */
+    if (c > SERIAL_XMIT_SIZE - PortP->gs.xmit_tail) 
+      c = SERIAL_XMIT_SIZE - PortP->gs.xmit_tail;
+
+    { int t;
+    t = (c > 10)?10:c;
+    
+    rio_dprint (RIO_DEBUG_INTR, ("tx port %d: copying %d chars: %s - %s\n", 
+				 PortP->PortNum, c, 
+	 firstchars (PortP->gs.xmit_buf + PortP->gs.xmit_tail      , t),
+	 firstchars (PortP->gs.xmit_buf + PortP->gs.xmit_tail + c-t, t)));
+    }
+    /* If for one reason or another, we can't copy more data, 
+       we're done! */
+    if (c == 0) break;
+
+    rio_memcpy_toio (PortP->HostP->Caddr, (caddr_t)PacketP->data, 
+		 PortP->gs.xmit_buf + PortP->gs.xmit_tail, c);
+    /*    udelay (1); */
+
+    writeb (c, &(PacketP->len));
+    if (!( PortP->State & RIO_DELETED ) ) {
+      add_transmit ( PortP );
+      /*
+      ** Count chars tx'd for port statistics reporting
+      */
+      if ( PortP->statsGather )
+	PortP->txchars += c;
+    }
+    PortP->gs.xmit_tail = (PortP->gs.xmit_tail + c) & (SERIAL_XMIT_SIZE-1);
+    PortP->gs.xmit_cnt -= c;
+  }
+
+  rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+
+  if (PortP->gs.xmit_cnt <= (PortP->gs.wakeup_chars + 2*PKT_MAX_DATA_LEN)) {
+    rio_dprint (RIO_DEBUG_INTR, ("Waking up.... ldisc:%d (%d/%d)....",
+		 (int)(PortP->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)),
+		 PortP->gs.wakeup_chars, PortP->gs.xmit_cnt)); 
+    if ((PortP->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+	PortP->gs.tty->ldisc.write_wakeup)
+      (PortP->gs.tty->ldisc.write_wakeup)(PortP->gs.tty);
+    rio_dprint (RIO_DEBUG_INTR, ("(%d/%d)\n",
+		PortP->gs.wakeup_chars, PortP->gs.xmit_cnt)); 
+    wake_up_interruptible(&PortP->gs.tty->write_wait);
+  }
+
+}
+
+
+/*
+** When a real-life interrupt comes in here, we try to find out
+** which host card it belongs to, and then service only that host
+** Notice the cunning way that, once we've found a candidate, we
+** continue just in case we are sharing interrupts.
+*/
+void
+riointr(p)
+struct rio_info *	p;
+{
+	int host;
+
+	for ( host=0; host<p->RIONumHosts; host++ ) {
+		struct Host *HostP = &p->RIOHosts[host];
+
+		rio_dprint(RIO_DEBUG_INTR,  ("riointr() doing host %d type %d\n", host, HostP->Type ) );
+
+		switch( HostP->Type ) {
+			case RIO_AT:
+			case RIO_MCA:
+			case RIO_PCI:
+			  	rio_spin_lock(&HostP->HostLock);
+				WBYTE(HostP->ResetInt , 0xff);
+				if ( !HostP->InIntr ) {
+					HostP->InIntr = 1;
+					rio_spin_unlock (&HostP->HostLock);
+					p->_RIO_Interrupted++;
+					RIOServiceHost(p, HostP, 'i');
+					rio_spin_lock(&HostP->HostLock);
+					HostP->InIntr = 0;
+				}
+				rio_spin_unlock(&HostP->HostLock); 
+				break;
+#ifdef FUTURE_RELEASE
+		case RIO_EISA:
+			if ( ivec == HostP->Ivec )
+			{
+				OldSpl = LOCKB( &HostP->HostLock );
+				INBZ( HostP->Slot, EISA_INTERRUPT_RESET );
+				if ( !HostP->InIntr )
+				{
+					HostP->InIntr = 1;
+					UNLOCKB( &HostP->HostLock, OldSpl );
+					if ( this_cpu < RIO_CPU_LIMIT )
+					{
+						int intrSpl = LOCKB( &RIOIntrLock );
+						UNLOCKB( &RIOIntrLock, intrSpl );
+					}
+						p->_RIO_Interrupted++;
+					RIOServiceHost( HostP, 'i' );
+					OldSpl = LOCKB( &HostP->HostLock );
+					HostP->InIntr = 0;
+				}
+				UNLOCKB( &HostP->HostLock, OldSpl );
+				done++;
+			}
+			break;
+#endif
+		}
+
+		HostP->IntSrvDone++;
+	}
+
+#ifdef FUTURE_RELEASE
+	if ( !done )
+	{
+		cmn_err( CE_WARN, "RIO: Interrupt received with vector 0x%x\n", ivec );
+		cmn_err( CE_CONT, "	 Valid vectors are:\n");
+		for ( host=0; host<RIONumHosts; host++ )
+		{
+			switch( RIOHosts[host].Type )
+			{
+				case RIO_AT:
+				case RIO_MCA:
+				case RIO_EISA:
+						cmn_err( CE_CONT, "0x%x ", RIOHosts[host].Ivec );
+						break;
+				case RIO_PCI:
+						cmn_err( CE_CONT, "0x%x ", get_intr_arg( RIOHosts[host].PciDevInfo.busnum, IDIST_PCI_IRQ( RIOHosts[host].PciDevInfo.slotnum, RIOHosts[host].PciDevInfo.funcnum ) ));
+						break;
+			}
+		}
+		cmn_err( CE_CONT, "\n" );
+	}
+#endif
+}
+
+/*
+** RIO Host Service routine. Does all the work traditionally associated with an
+** interrupt.
+*/
+static int	RupIntr;
+static int	RxIntr;
+static int	TxIntr;
+void
+RIOServiceHost(p, HostP, From)
+struct rio_info *	p;
+struct Host *HostP;
+int From; 
+{
+  rio_spin_lock (&HostP->HostLock);
+  if ( (HostP->Flags & RUN_STATE) != RC_RUNNING ) { 
+    static int t =0;
+    rio_spin_unlock (&HostP->HostLock); 
+    if ((t++ % 200) == 0)
+      rio_dprint(RIO_DEBUG_INTR, ("Interrupt but host not running. flags=%x.\n", (int)HostP->Flags));
+    return;
+  }
+  rio_spin_unlock (&HostP->HostLock); 
+
+  if ( RWORD( HostP->ParmMapP->rup_intr ) ) {
+    WWORD( HostP->ParmMapP->rup_intr , 0 );
+    p->RIORupCount++;
+    RupIntr++;
+    rio_dprint(RIO_DEBUG_INTR, ("RUP interrupt on host %d\n", HostP-p->RIOHosts ));
+    RIOPollHostCommands(p, HostP );
+  }
+
+  if ( RWORD( HostP->ParmMapP->rx_intr ) ) {
+    int port;
+
+    WWORD( HostP->ParmMapP->rx_intr , 0 );
+    p->RIORxCount++;
+    RxIntr++;
+
+    rio_dprint(RIO_DEBUG_INTR, ("RX interrupt on host %d\n", HostP-p->RIOHosts));
+    /*
+    ** Loop through every port. If the port is mapped into
+    ** the system ( i.e. has /dev/ttyXXXX associated ) then it is
+    ** worth checking. If the port isn't open, grab any packets
+    ** hanging on its receive queue and stuff them on the free
+    ** list; check for commands on the way.
+    */
+    for ( port=p->RIOFirstPortsBooted; 
+	  port<p->RIOLastPortsBooted+PORTS_PER_RTA; port++ ) {
+      struct Port *PortP = p->RIOPortp[port];
+      struct tty_struct *ttyP;
+      struct PKT *PacketP;
+		
+      /*
+      ** not mapped in - most of the RIOPortp[] information
+      ** has not been set up!
+      ** Optimise: ports come in bundles of eight.
+      */
+      if ( !PortP->Mapped ) {
+	port += 7;
+	continue; /* with the next port */
+      }
+
+      /*
+      ** If the host board isn't THIS host board, check the next one.
+      ** optimise: ports come in bundles of eight.
+      */
+      if ( PortP->HostP != HostP ) {
+	port += 7;
+	continue;
+      }
+
+      /*
+      ** Let us see - is the port open? If not, then don't service it.
+      */
+      if ( !( PortP->PortState & PORT_ISOPEN ) ) {
+	continue;
+      }
+
+      /*
+      ** find corresponding tty structure. The process of mapping
+      ** the ports puts these here.
+      */
+      ttyP = PortP->gs.tty;
+
+      /*
+      ** Lock the port before we begin working on it.
+      */
+      rio_spin_lock(&PortP->portSem);
+
+      /*
+      ** Process received data if there is any.
+      */
+      if ( can_remove_receive( &PacketP, PortP ) )
+	RIOReceive(p, PortP);
+
+      /*
+      ** If there is no data left to be read from the port, and
+      ** it's handshake bit is set, then we must clear the handshake,
+      ** so that that downstream RTA is re-enabled.
+      */
+      if ( !can_remove_receive( &PacketP, PortP ) && 
+	   ( RWORD( PortP->PhbP->handshake )==PHB_HANDSHAKE_SET ) ) {
+				/*
+				** MAGIC! ( Basically, handshake the RX buffer, so that
+				** the RTAs upstream can be re-enabled. )
+				*/
+	rio_dprint(RIO_DEBUG_INTR, ("Set RX handshake bit\n" ));
+	WWORD( PortP->PhbP->handshake, 
+	       PHB_HANDSHAKE_SET|PHB_HANDSHAKE_RESET );
+      }
+      rio_spin_unlock(&PortP->portSem);
+    }
+  }
+
+  if ( RWORD( HostP->ParmMapP->tx_intr ) ) {
+    int port;
+
+    WWORD( HostP->ParmMapP->tx_intr , 0);
+
+    p->RIOTxCount++;
+    TxIntr++;
+    rio_dprint(RIO_DEBUG_INTR, ("TX interrupt on host %d\n", HostP-p->RIOHosts));
+
+    /*
+    ** Loop through every port.
+    ** If the port is mapped into the system ( i.e. has /dev/ttyXXXX
+    ** associated ) then it is worth checking.
+    */
+    for ( port=p->RIOFirstPortsBooted; 
+	  port<p->RIOLastPortsBooted+PORTS_PER_RTA; port++ ) {
+      struct Port *PortP = p->RIOPortp[port];
+      struct tty_struct *ttyP;
+      struct PKT *PacketP;
+
+      /*
+      ** not mapped in - most of the RIOPortp[] information
+      ** has not been set up!
+      */
+      if ( !PortP->Mapped ) {
+	port += 7;
+	continue; /* with the next port */
+      }
+
+      /*
+      ** If the host board isn't running, then its data structures
+      ** are no use to us - continue quietly.
+      */
+      if ( PortP->HostP != HostP ) {
+	port += 7;
+	continue; /* with the next port */
+      }
+
+      /*
+      ** Let us see - is the port open? If not, then don't service it.
+      */
+      if ( !( PortP->PortState & PORT_ISOPEN ) ) {
+	continue;
+      }
+
+      rio_dprint (RIO_DEBUG_INTR, ("Looking into port %d.\n", port));
+      /*
+      ** Lock the port before we begin working on it.
+      */
+      rio_spin_lock(&PortP->portSem);
+
+      /*
+      ** If we can't add anything to the transmit queue, then
+      ** we need do none of this processing.
+      */
+      if ( !can_add_transmit( &PacketP, PortP ) ) {
+	rio_dprint (RIO_DEBUG_INTR, ("Can't add to port, so skipping.\n"));
+	rio_spin_unlock(&PortP->portSem);
+	continue;
+      }
+
+      /*
+      ** find corresponding tty structure. The process of mapping
+      ** the ports puts these here.
+      */
+      ttyP = PortP->gs.tty;
+      /* If ttyP is NULL, the port is getting closed. Forget about it. */
+      if (!ttyP) {
+	rio_dprint (RIO_DEBUG_INTR, ("no tty, so skipping.\n"));
+	rio_spin_unlock(&PortP->portSem);
+	continue;
+      }
+      /*
+      ** If there is more room available we start up the transmit
+      ** data process again. This can be direct I/O, if the cookmode
+      ** is set to COOK_RAW or COOK_MEDIUM, or will be a call to the
+      ** riotproc( T_OUTPUT ) if we are in COOK_WELL mode, to fetch
+      ** characters via the line discipline. We must always call
+      ** the line discipline,
+      ** so that user input characters can be echoed correctly.
+      **
+      ** ++++ Update +++++
+      ** With the advent of double buffering, we now see if
+      ** TxBufferOut-In is non-zero. If so, then we copy a packet
+      ** to the output place, and set it going. If this empties
+      ** the buffer, then we must issue a wakeup( ) on OUT.
+      ** If it frees space in the buffer then we must issue
+      ** a wakeup( ) on IN.
+      **
+      ** ++++ Extra! Extra! If PortP->WflushFlag is set, then we
+      ** have to send a WFLUSH command down the PHB, to mark the
+      ** end point of a WFLUSH. We also need to clear out any
+      ** data from the double buffer! ( note that WflushFlag is a
+      ** *count* of the number of WFLUSH commands outstanding! )
+      **
+      ** ++++ And there's more!
+      ** If an RTA is powered off, then on again, and rebooted,
+      ** whilst it has ports open, then we need to re-open the ports.
+      ** ( reasonable enough ). We can't do this when we spot the
+      ** re-boot, in interrupt time, because the queue is probably
+      ** full. So, when we come in here, we need to test if any
+      ** ports are in this condition, and re-open the port before
+      ** we try to send any more data to it. Now, the re-booted
+      ** RTA will be discarding packets from the PHB until it
+      ** receives this open packet, but don't worry tooo much
+      ** about that. The one thing that is interesting is the
+      ** combination of this effect and the WFLUSH effect!
+      */
+      /* For now don't handle RTA reboots. -- REW. 
+	 Reenabled. Otherwise RTA reboots didn't work. Duh. -- REW */
+      if ( PortP->MagicFlags ) {
+#if 1
+	if ( PortP->MagicFlags & MAGIC_REBOOT ) {
+	  /*
+	  ** well, the RTA has been rebooted, and there is room
+	  ** on its queue to add the open packet that is required.
+	  **
+	  ** The messy part of this line is trying to decide if
+	  ** we need to call the Param function as a tty or as
+	  ** a modem.
+	  ** DONT USE CLOCAL AS A TEST FOR THIS!
+	  **
+	  ** If we can't param the port, then move on to the
+	  ** next port.
+	  */
+	  PortP->InUse = NOT_INUSE;
+
+	  rio_spin_unlock(&PortP->portSem);
+	  if ( RIOParam(PortP, OPEN, ((PortP->Cor2Copy & 
+				       (COR2_RTSFLOW|COR2_CTSFLOW ) )== 
+				      (COR2_RTSFLOW|COR2_CTSFLOW ) ) ? 
+			TRUE : FALSE, DONT_SLEEP ) == RIO_FAIL ) {
+	    continue; /* with next port */
+	  }
+	  rio_spin_lock(&PortP->portSem);
+	  PortP->MagicFlags &= ~MAGIC_REBOOT;
+	}
+#endif
+
+	/*
+	** As mentioned above, this is a tacky hack to cope
+	** with WFLUSH
+	*/
+	if ( PortP->WflushFlag ) {
+	  rio_dprint(RIO_DEBUG_INTR, ("Want to WFLUSH mark this port\n"));
+
+	  if ( PortP->InUse )
+	    rio_dprint(RIO_DEBUG_INTR, ("FAILS - PORT IS IN USE\n"));
+	}
+				
+	while ( PortP->WflushFlag &&
+		can_add_transmit( &PacketP, PortP ) && 
+		( PortP->InUse == NOT_INUSE ) ) {
+	  int p;
+	  struct PktCmd *PktCmdP;
+
+	  rio_dprint(RIO_DEBUG_INTR, ("Add WFLUSH marker to data queue\n"));
+	  /*
+	  ** make it look just like a WFLUSH command
+	  */
+	  PktCmdP = ( struct PktCmd * )&PacketP->data[0];
+
+	  WBYTE( PktCmdP->Command , WFLUSH );
+
+	  p =  PortP->HostPort % ( ushort )PORTS_PER_RTA;
+
+	  /*
+	  ** If second block of ports for 16 port RTA, add 8
+	  ** to index 8-15.
+	  */
+	  if ( PortP->SecondBlock )
+	    p += PORTS_PER_RTA;
+
+	  WBYTE( PktCmdP->PhbNum, p );
+
+	  /*
+	  ** to make debuggery easier
+	  */
+	  WBYTE( PacketP->data[ 2], 'W'  );
+	  WBYTE( PacketP->data[ 3], 'F'  );
+	  WBYTE( PacketP->data[ 4], 'L'  );
+	  WBYTE( PacketP->data[ 5], 'U'  );
+	  WBYTE( PacketP->data[ 6], 'S'  );
+	  WBYTE( PacketP->data[ 7], 'H'  );
+	  WBYTE( PacketP->data[ 8], ' '  );
+	  WBYTE( PacketP->data[ 9], '0'+PortP->WflushFlag );
+	  WBYTE( PacketP->data[10], ' '  );
+	  WBYTE( PacketP->data[11], ' '  );
+	  WBYTE( PacketP->data[12], '\0' );
+
+	  /*
+	  ** its two bytes long!
+	  */
+	  WBYTE( PacketP->len , PKT_CMD_BIT | 2 );
+
+	  /*
+	  ** queue it!
+	  */
+	  if ( !( PortP->State & RIO_DELETED ) ) {
+	    add_transmit( PortP );
+	    /*
+	    ** Count chars tx'd for port statistics reporting
+	    */
+	    if ( PortP->statsGather )
+	      PortP->txchars += 2;
+	  }
+
+	  if ( --( PortP->WflushFlag ) == 0 ) {
+	    PortP->MagicFlags &= ~MAGIC_FLUSH;
+	  }
+
+	  rio_dprint(RIO_DEBUG_INTR, ("Wflush count now stands at %d\n", 
+		 PortP->WflushFlag));
+	}
+	if ( PortP->MagicFlags & MORE_OUTPUT_EYGOR ) {
+	  if ( PortP->MagicFlags & MAGIC_FLUSH ) {
+	    PortP->MagicFlags |= MORE_OUTPUT_EYGOR;
+	  }
+	  else {
+	    if ( !can_add_transmit( &PacketP, PortP ) ) {
+	      rio_spin_unlock(&PortP->portSem);
+	      continue;
+	    }
+	    rio_spin_unlock(&PortP->portSem);
+	    RIOTxEnable((char *)PortP);
+	    rio_spin_lock(&PortP->portSem);
+	    PortP->MagicFlags &= ~MORE_OUTPUT_EYGOR;
+	  }
+	}
+      }
+
+
+      /*
+      ** If we can't add anything to the transmit queue, then
+      ** we need do none of the remaining processing.
+      */
+      if (!can_add_transmit( &PacketP, PortP ) ) {
+	rio_spin_unlock(&PortP->portSem);
+	continue;
+      }
+
+      rio_spin_unlock(&PortP->portSem);
+      RIOTxEnable((char *)PortP);
+    }
+  }
+}
+
+/*
+** Routine for handling received data for clist drivers.
+** NB: Called with the tty locked. The spl from the lockb( ) is passed.
+** we return the ttySpl level that we re-locked at.
+*/
+void
+RIOReceive(p, PortP)
+struct rio_info *	p;
+struct Port *		PortP;
+{
+  struct tty_struct *TtyP;
+  register ushort transCount;
+  struct PKT *PacketP;
+  register uint	DataCnt;
+  uchar *	ptr;
+  int copied =0;
+
+  static int intCount, RxIntCnt;
+
+  /*
+  ** The receive data process is to remove packets from the
+  ** PHB until there aren't any more or the current cblock
+  ** is full. When this occurs, there will be some left over
+  ** data in the packet, that we must do something with.
+  ** As we haven't unhooked the packet from the read list
+  ** yet, we can just leave the packet there, having first
+  ** made a note of how far we got. This means that we need
+  ** a pointer per port saying where we start taking the
+  ** data from - this will normally be zero, but when we
+  ** run out of space it will be set to the offset of the
+  ** next byte to copy from the packet data area. The packet
+  ** length field is decremented by the number of bytes that
+  ** we succesfully removed from the packet. When this reaches
+  ** zero, we reset the offset pointer to be zero, and free
+  ** the packet from the front of the queue.
+  */
+
+  intCount++;
+
+  TtyP = PortP->gs.tty;
+  if (!TtyP) {
+    rio_dprint (RIO_DEBUG_INTR, ("RIOReceive: tty is null. \n"));
+    return;
+  }
+
+  if (PortP->State & RIO_THROTTLE_RX) {
+    rio_dprint (RIO_DEBUG_INTR, ("RIOReceive: Throttled. Can't handle more input.\n"));
+    return;
+  }
+
+  if ( PortP->State & RIO_DELETED )
+    {
+      while ( can_remove_receive( &PacketP, PortP ) )
+	{
+	  remove_receive( PortP );
+	  put_free_end( PortP->HostP, PacketP );
+	}
+    }
+  else
+    {
+      /*
+      ** loop, just so long as:
+      **   i ) there's some data ( i.e. can_remove_receive )
+      **  ii ) we haven't been blocked
+      ** iii ) there's somewhere to put the data
+      **  iv ) we haven't outstayed our welcome
+      */
+      transCount = 1;
+      while ( can_remove_receive(&PacketP, PortP)
+	      && transCount)
+	{
+#ifdef STATS
+	  PortP->Stat.RxIntCnt++;
+#endif /* STATS */
+	  RxIntCnt++;
+
+	  /*
+	  ** check that it is not a command!
+	  */
+	  if ( PacketP->len & PKT_CMD_BIT ) {
+	    rio_dprint(RIO_DEBUG_INTR, ("RIO: unexpected command packet received on PHB\n"));
+	    /*	    rio_dprint(RIO_DEBUG_INTR, (" sysport   = %d\n", p->RIOPortp->PortNum)); */
+	    rio_dprint(RIO_DEBUG_INTR, (" dest_unit = %d\n", PacketP->dest_unit));
+	    rio_dprint(RIO_DEBUG_INTR, (" dest_port = %d\n", PacketP->dest_port));
+	    rio_dprint(RIO_DEBUG_INTR, (" src_unit  = %d\n", PacketP->src_unit));
+	    rio_dprint(RIO_DEBUG_INTR, (" src_port  = %d\n", PacketP->src_port));
+	    rio_dprint(RIO_DEBUG_INTR, (" len	   = %d\n", PacketP->len));
+	    rio_dprint(RIO_DEBUG_INTR, (" control   = %d\n", PacketP->control));
+	    rio_dprint(RIO_DEBUG_INTR, (" csum	   = %d\n", PacketP->csum));
+	    rio_dprint(RIO_DEBUG_INTR, ("	 data bytes: "));
+	    for ( DataCnt=0; DataCnt<PKT_MAX_DATA_LEN; DataCnt++ )
+	      rio_dprint(RIO_DEBUG_INTR, ("%d\n", PacketP->data[DataCnt]));
+	    remove_receive( PortP );
+	    put_free_end( PortP->HostP, PacketP );
+	    continue; /* with next packet */
+	  }
+
+	  /*
+	  ** How many characters can we move 'upstream' ?
+	  **
+	  ** Determine the minimum of the amount of data
+	  ** available and the amount of space in which to
+	  ** put it.
+	  **
+	  ** 1.	Get the packet length by masking 'len'
+	  **	for only the length bits.
+	  ** 2.	Available space is [buffer size] - [space used]
+	  **
+	  ** Transfer count is the minimum of packet length
+	  ** and available space.
+	  */
+			
+	  transCount = min(PacketP->len & PKT_LEN_MASK,
+			   TTY_FLIPBUF_SIZE - TtyP->flip.count);
+	  rio_dprint(RIO_DEBUG_REC,  ("port %d: Copy %d bytes\n", 
+				      PortP->PortNum, transCount ) );
+	  /*
+	  ** To use the following 'kkprintfs' for debugging - change the '#undef'
+	  ** to '#define', (this is the only place ___DEBUG_IT___ occurs in the
+	  ** driver).
+	  */
+#undef ___DEBUG_IT___
+#ifdef ___DEBUG_IT___
+	  kkprintf("I:%d R:%d P:%d Q:%d C:%d F:%x ",
+		   intCount,
+		   RxIntCnt,
+		   PortP->PortNum,
+		   TtyP->rxqueue.count,
+		   transCount,
+		   TtyP->flags );
+#endif
+	  ptr = (uchar *) PacketP->data + PortP->RxDataStart;
+
+	  rio_memcpy_fromio (TtyP->flip.char_buf_ptr, ptr, transCount);
+	  memset(TtyP->flip.flag_buf_ptr, TTY_NORMAL, transCount);
+
+#ifdef STATS
+	  /*
+	  ** keep a count for statistical purposes
+	  */
+	  PortP->Stat.RxCharCnt	+= transCount;
+#endif
+	  PortP->RxDataStart	+= transCount;
+	  PacketP->len		-= transCount;
+	  copied += transCount;
+	  TtyP->flip.count += transCount;
+	  TtyP->flip.char_buf_ptr += transCount;
+	  TtyP->flip.flag_buf_ptr += transCount;
+
+
+#ifdef ___DEBUG_IT___
+	  kkprintf("T:%d L:%d\n", DataCnt, PacketP->len );
+#endif
+
+	  if ( PacketP->len == 0 )
+	    {
+				/*
+				** If we have emptied the packet, then we can
+				** free it, and reset the start pointer for
+				** the next packet.
+				*/
+	      remove_receive( PortP );
+	      put_free_end( PortP->HostP, PacketP );
+	      PortP->RxDataStart = 0;
+#ifdef STATS
+				/*
+				** more lies ( oops, I mean statistics )
+				*/
+	      PortP->Stat.RxPktCnt++;
+#endif /* STATS */
+	    }
+	}
+    }
+  if (copied) {
+    rio_dprint ( RIO_DEBUG_REC, ("port %d: pushing tty flip buffer: %d total bytes copied.\n", PortP->PortNum,  copied));
+    tty_flip_buffer_push (TtyP);
+  }
+
+  return;
+}
+
+#ifdef FUTURE_RELEASE
+/*
+** The proc routine called by the line discipline to do the work for it.
+** The proc routine works hand in hand with the interrupt routine.
+*/
+int
+riotproc(p, tp, cmd, port)
+struct rio_info *	p;
+register struct ttystatics *tp;
+int cmd;
+int	port;
+{
+	register struct Port *PortP;
+	int SysPort;
+	struct PKT *PacketP;
+
+	SysPort = port;	/* Believe me, it works. */
+
+	if ( SysPort < 0 || SysPort >= RIO_PORTS ) {
+		rio_dprint(RIO_DEBUG_INTR, ("Illegal port %d derived from TTY in riotproc()\n",SysPort));
+		return 0;
+	}
+	PortP = p->RIOPortp[SysPort];
+
+	if ((uint)PortP->PhbP < (uint)PortP->Caddr || 
+			(uint)PortP->PhbP >= (uint)PortP->Caddr+SIXTY_FOUR_K ) {
+		rio_dprint(RIO_DEBUG_INTR, ("RIO: NULL or BAD PhbP on sys port %d in proc routine\n",
+							SysPort));
+		rio_dprint(RIO_DEBUG_INTR, ("	 PortP = 0x%x\n",PortP));
+		rio_dprint(RIO_DEBUG_INTR, ("	 PortP->PhbP = 0x%x\n",PortP->PhbP));
+		rio_dprint(RIO_DEBUG_INTR, ("	 PortP->Caddr = 0x%x\n",PortP->PhbP));
+		rio_dprint(RIO_DEBUG_INTR, ("	 PortP->HostPort = 0x%x\n",PortP->HostPort));
+		return 0;
+	}
+
+	switch(cmd) {
+		case T_WFLUSH:
+			rio_dprint(RIO_DEBUG_INTR, "T_WFLUSH\n");
+			/*
+			** Because of the spooky way the RIO works, we don't need
+			** to issue a flush command on any of the SET*F commands,
+			** as that causes trouble with getty and login, which issue
+			** these commands to incur a READ flush, and rely on the fact
+			** that the line discipline does a wait for drain for them.
+			** As the rio doesn't wait for drain, the write flush would
+			** destroy the Password: prompt. This isn't very friendly, so
+			** here we only issue a WFLUSH command if we are in the interrupt
+			** routine, or we aren't executing a SET*F command.
+			*/
+			if ( PortP->HostP->InIntr || !PortP->FlushCmdBodge ) {
+				/*
+				** form a wflush packet - 1 byte long, no data
+				*/
+				if ( PortP->State & RIO_DELETED ) {
+					rio_dprint(RIO_DEBUG_INTR, ("WFLUSH on deleted RTA\n"));
+				}
+				else {
+					if ( RIOPreemptiveCmd(p, PortP, WFLUSH ) == RIO_FAIL ) {
+						rio_dprint(RIO_DEBUG_INTR, ("T_WFLUSH Command failed\n"));
+					}
+					else
+						rio_dprint(RIO_DEBUG_INTR, ("T_WFLUSH Command\n"));
+				}
+				/*
+				** WFLUSH operation - flush the data!
+				*/
+				PortP->TxBufferIn = PortP->TxBufferOut = 0;
+			}
+			else {
+				rio_dprint(RIO_DEBUG_INTR, ("T_WFLUSH Command ignored\n"));
+			}
+			/*
+			** sort out the line discipline
+			*/
+			if (PortP->CookMode == COOK_WELL)
+				goto start;
+			break;
+	
+		case T_RESUME:
+			rio_dprint(RIO_DEBUG_INTR, ("T_RESUME\n"));
+			/*
+			** send pre-emptive resume packet
+			*/
+			if ( PortP->State & RIO_DELETED ) {
+				rio_dprint(RIO_DEBUG_INTR, ("RESUME on deleted RTA\n"));
+			}
+			else {
+				if ( RIOPreemptiveCmd(p, PortP, RESUME ) == RIO_FAIL ) {
+					rio_dprint(RIO_DEBUG_INTR, ("T_RESUME Command failed\n"));
+				}
+			}
+			/*
+			** and re-start the sender software!
+			*/
+			if (PortP->CookMode == COOK_WELL)
+				goto start;
+			break;
+	
+		case T_TIME:
+			rio_dprint(RIO_DEBUG_INTR, ("T_TIME\n"));
+			/*
+			** T_TIME is called when xDLY is set in oflags and
+			** the line discipline timeout has expired. It's
+			** function in life is to clear the TIMEOUT flag
+			** and to re-start output to the port.
+			*/
+			/*
+			** Fall through and re-start output
+			*/
+		case T_OUTPUT:
+start:
+			if ( PortP->MagicFlags & MAGIC_FLUSH ) {
+				PortP->MagicFlags |= MORE_OUTPUT_EYGOR;
+				return 0;
+			}
+			RIOTxEnable((char *)PortP);
+			PortP->MagicFlags &= ~MORE_OUTPUT_EYGOR;
+			/*rio_dprint(RIO_DEBUG_INTR, PortP,DBG_PROC,"T_OUTPUT finished\n");*/
+			break;
+	
+		case T_SUSPEND:
+			rio_dprint(RIO_DEBUG_INTR, ("T_SUSPEND\n"));
+			/*
+			** send a suspend pre-emptive packet.
+			*/
+			if ( PortP->State & RIO_DELETED ) {
+				rio_dprint(RIO_DEBUG_INTR, ("SUSPEND deleted RTA\n"));
+			}
+			else {
+				if ( RIOPreemptiveCmd(p, PortP, SUSPEND ) == RIO_FAIL ) {
+					rio_dprint(RIO_DEBUG_INTR, ("T_SUSPEND Command failed\n"));
+				}
+			}
+			/*
+			** done!
+			*/
+			break;
+	
+		case T_BLOCK:
+			rio_dprint(RIO_DEBUG_INTR, ("T_BLOCK\n"));
+			break;
+	
+		case T_RFLUSH:
+			rio_dprint(RIO_DEBUG_INTR, ("T_RFLUSH\n"));
+			if ( PortP->State & RIO_DELETED ) {
+				rio_dprint(RIO_DEBUG_INTR, ("RFLUSH on deleted RTA\n"));
+				PortP->RxDataStart = 0;
+			}
+			else {
+				if ( RIOPreemptiveCmd( p, PortP, RFLUSH ) == RIO_FAIL ) {
+					rio_dprint(RIO_DEBUG_INTR, ("T_RFLUSH Command failed\n"));
+					return 0;
+				}
+				PortP->RxDataStart = 0;
+				while ( can_remove_receive(&PacketP, PortP) ) {
+					remove_receive(PortP);
+					ShowPacket(DBG_PROC, PacketP );
+					put_free_end(PortP->HostP, PacketP );
+				}
+				if ( PortP->PhbP->handshake == PHB_HANDSHAKE_SET ) {
+					/*
+					** MAGIC!
+					*/
+					rio_dprint(RIO_DEBUG_INTR, ("Set receive handshake bit\n"));
+					PortP->PhbP->handshake |= PHB_HANDSHAKE_RESET;
+				}
+			}
+			break;
+			/* FALLTHROUGH */
+		case T_UNBLOCK:
+			rio_dprint(RIO_DEBUG_INTR, ("T_UNBLOCK\n"));
+			/*
+			** If there is any data to receive set a timeout to service it.
+			*/
+			RIOReceive(p, PortP);
+			break;
+	
+		case T_BREAK:
+			rio_dprint(RIO_DEBUG_INTR, ("T_BREAK\n"));
+			/*
+			** Send a break command. For Sys V
+			** this is a timed break, so we
+			** send a SBREAK[time] packet
+			*/
+			/*
+			** Build a BREAK command
+			*/
+			if ( PortP->State & RIO_DELETED ) {
+				rio_dprint(RIO_DEBUG_INTR, ("BREAK on deleted RTA\n"));
+			}
+			else {
+				if (RIOShortCommand(PortP,SBREAK,2,
+								p->RIOConf.BreakInterval)==RIO_FAIL) {
+			   		rio_dprint(RIO_DEBUG_INTR, ("SBREAK RIOShortCommand failed\n"));
+				}
+			}
+	
+			/*
+			** done!
+			*/
+			break;
+	
+		case T_INPUT:
+			rio_dprint(RIO_DEBUG_INTR, ("Proc T_INPUT called - I don't know what to do!\n"));
+			break;
+		case T_PARM:
+			rio_dprint(RIO_DEBUG_INTR, ("Proc T_PARM called - I don't know what to do!\n"));
+			break;
+	
+		case T_SWTCH:
+			rio_dprint(RIO_DEBUG_INTR, ("Proc T_SWTCH called - I don't know what to do!\n"));
+			break;
+	
+		default:
+			rio_dprint(RIO_DEBUG_INTR, ("Proc UNKNOWN command %d\n",cmd));
+	}
+	/*
+	** T_OUTPUT returns without passing through this point!
+	*/
+	/*rio_dprint(RIO_DEBUG_INTR, PortP,DBG_PROC,"riotproc done\n");*/
+	return(0);
+}
+#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/rioioctl.h linux.15p9/drivers/char/rio/rioioctl.h
--- linux.vanilla/drivers/char/rio/rioioctl.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/rioioctl.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,103 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: rioioctl.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:13
+**	Retrieved	: 11/6/98 11:34:22
+**
+**  ident @(#)rioioctl.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef	__rioioctl_h__
+#define	__rioioctl_h__
+
+#ifdef SCCS_LABELS
+static char *_rioioctl_h_sccs_ = "@(#)rioioctl.h	1.2";
+#endif
+
+/*
+** RIO device driver - user ioctls and associated structures.
+*/
+
+struct portStats {
+	int	port;
+	int	gather;
+	ulong	txchars;
+	ulong	rxchars;
+	ulong	opens;
+	ulong	closes;
+	ulong	ioctls;
+}; 
+
+
+#define rIOC	('r'<<8)
+#define	TCRIOSTATE	(rIOC | 1)
+#define	TCRIOXPON	(rIOC | 2)
+#define	TCRIOXPOFF	(rIOC | 3)
+#define	TCRIOXPCPS	(rIOC | 4)
+#define	TCRIOXPRINT	(rIOC | 5)
+#define TCRIOIXANYON	(rIOC | 6)
+#define	TCRIOIXANYOFF	(rIOC | 7)
+#define TCRIOIXONON	(rIOC | 8)
+#define	TCRIOIXONOFF	(rIOC | 9)
+#define	TCRIOMBIS	(rIOC | 10)
+#define	TCRIOMBIC	(rIOC | 11)
+#define	TCRIOTRIAD	(rIOC | 12)
+#define TCRIOTSTATE	(rIOC | 13)
+
+/*
+** 15.10.1998 ARG - ESIL 0761 part fix
+** Add RIO ioctls for manipulating RTS and CTS flow control, (as LynxOS
+** appears to not support hardware flow control).
+*/
+#define TCRIOCTSFLOWEN	(rIOC | 14)	/* enable CTS flow control */
+#define TCRIOCTSFLOWDIS	(rIOC | 15)	/* disable CTS flow control */
+#define TCRIORTSFLOWEN	(rIOC | 16)	/* enable RTS flow control */
+#define TCRIORTSFLOWDIS	(rIOC | 17)	/* disable RTS flow control */
+
+/*
+** 09.12.1998 ARG - ESIL 0776 part fix
+** Definition for 'RIOC' also appears in daemon.h, so we'd better do a
+** #ifndef here first.
+** 'RIO_QUICK_CHECK' also #define'd here as this ioctl is now
+** allowed to be used by customers.
+**
+** 05.02.1999 ARG -
+** This is what I've decied to do with ioctls etc., which are intended to be
+** invoked from users applications :
+** Anything that needs to be defined here will be removed from daemon.h, that
+** way it won't end up having to be defined/maintained in two places. The only
+** consequence of this is that this file should now be #include'd by daemon.h
+**
+** 'stats' ioctls now #define'd here as they are to be used by customers.
+*/
+#define	RIOC	('R'<<8)|('i'<<16)|('o'<<24)
+
+#define	RIO_QUICK_CHECK	  	(RIOC | 105)
+#define RIO_GATHER_PORT_STATS	(RIOC | 193)
+#define RIO_RESET_PORT_STATS	(RIOC | 194)
+#define RIO_GET_PORT_STATS	(RIOC | 195)
+
+#endif	/* __rioioctl_h__ */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/riolocks.h linux.15p9/drivers/char/rio/riolocks.h
--- linux.vanilla/drivers/char/rio/riolocks.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/riolocks.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,43 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: riolocks.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:13
+**	Retrieved	: 11/6/98 11:34:22
+**
+**  ident @(#)riolocks.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef	__rio_riolocks_h__
+#define	__rio_riolocks_h__
+
+#ifdef SCCS_LABELS
+static char *_riolocks_h_sccs_ = "@(#)riolocks.h	1.2";
+#endif
+
+#define LOCKB(lk)		lockb(lk);
+#define UNLOCKB(lk, oldspl)	unlockb(lk, oldspl);
+
+#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/rioparam.c linux.15p9/drivers/char/rio/rioparam.c
--- linux.vanilla/drivers/char/rio/rioparam.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/rioparam.c	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,728 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: rioparam.c
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 10:33:45
+**	Retrieved	: 11/6/98 10:33:50
+**
+**  ident @(#)rioparam.c	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifdef SCCS_LABELS
+static char *_rioparam_c_sccs_ = "@(#)rioparam.c	1.3";
+#endif
+
+#define __NO_VERSION__
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/malloc.h>
+#include <linux/errno.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/string.h>
+#include <asm/semaphore.h>
+#include <asm/uaccess.h>
+
+#include <linux/termios.h>
+#include <linux/serial.h>
+
+#include <linux/compatmac.h>
+#include <linux/generic_serial.h>
+
+
+#include "linux_compat.h"
+#include "rio_linux.h"
+#include "typdef.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "top.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "riotypes.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "error.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+#include "control.h"
+#include "cirrus.h"
+#include "rioioctl.h"
+#include "param.h"
+#include "list.h"
+#include "sam.h"
+
+
+
+/*
+** The Scam, based on email from jeremyr@bugs.specialix.co.uk....
+**
+** To send a command on a particular port, you put a packet with the
+** command bit set onto the port. The command bit is in the len field,
+** and gets ORed in with the actual byte count.
+**
+** When you send a packet with the command bit set, then the first
+** data byte ( data[0] ) is interpretted as the command to execute.
+** It also governs what data structure overlay should accompany the packet.
+** Commands are defined in cirrus/cirrus.h
+**
+** If you want the command to pre-emt data already on the queue for the
+** port, set the pre-emptive bit in conjunction with the command bit.
+** It is not defined what will happen if you set the preemptive bit
+** on a packet that is NOT a command.
+**
+** Pre-emptive commands should be queued at the head of the queue using
+** add_start(), whereas normal commands and data are enqueued using
+** add_end().
+**
+** Most commands do not use the remaining bytes in the data array. The
+** exceptions are OPEN MOPEN and CONFIG. (NB. As with the SI CONFIG and
+** OPEN are currently analagous). With these three commands the following
+** 11 data bytes are all used to pass config information such as baud rate etc.
+** The fields are also defined in cirrus.h. Some contain straightforward
+** information such as the transmit XON character. Two contain the transmit and
+** receive baud rates respectively. For most baud rates there is a direct
+** mapping between the rates defined in <sys/termio.h> and the byte in the
+** packet. There are additional (non UNIX-standard) rates defined in
+** /u/dos/rio/cirrus/h/brates.h.
+**
+** The rest of the data fields contain approximations to the Cirrus registers
+** that are used to program number of bits etc. Each registers bit fields is
+** defined in cirrus.h.
+** 
+** NB. Only use those bits that are defined as being driver specific
+** or common to the RTA and the driver.
+** 
+** All commands going from RTA->Host will be dealt with by the Host code - you
+** will never see them. As with the SI there will be three fields to look out
+** for in each phb (not yet defined - needs defining a.s.a.p).
+** 
+** modem_status	- current state of handshake pins.
+**
+** port_status	 - current port status - equivalent to hi_stat for SI, indicates
+** if port is IDLE_OPEN, IDLE_CLOSED etc.
+**
+** break_status	- bit X set if break has been received.
+** 
+** Happy hacking.
+** 
+*/
+
+/* 
+** RIOParam is used to open or configure a port. You pass it a PortP,
+** which will have a tty struct attached to it. You also pass a command,
+** either OPEN or CONFIG. The port's setup is taken from the t_ fields
+** of the tty struct inside the PortP, and the port is either opened
+** or re-configured. You must also tell RIOParam if the device is a modem
+** device or not (i.e. top bit of minor number set or clear - take special
+** care when deciding on this!).
+** RIOParam neither flushes nor waits for drain, and is NOT preemptive.
+**
+** RIOParam assumes it will be called at splrio(), and also assumes
+** that CookMode is set correctly in the port structure.
+**
+** NB. for MPX
+**	tty lock must NOT have been previously acquired.
+*/
+int
+RIOParam(PortP, cmd, Modem, SleepFlag)
+struct Port *PortP;
+int cmd;
+int Modem;
+int SleepFlag; 
+{
+	register struct tty_struct *TtyP;
+	int	retval;
+	register struct phb_param *phb_param_ptr;
+	PKT *PacketP;
+	int res;
+	uchar Cor1=0, Cor2=0, Cor4=0, Cor5=0;
+	uchar TxXon=0, TxXoff=0, RxXon=0, RxXoff=0;
+	uchar LNext=0, TxBaud=0, RxBaud=0;
+	int		retries = 0xff;
+	unsigned long flags;
+
+	TtyP = PortP->gs.tty;
+
+	rio_dprint(RIO_DEBUG_PARAM, ("RIOParam: Port:%d cmd:%d Modem:%d SleepFlag:%d Mapped: %d, tty=%p\n",
+	    PortP->PortNum, cmd, Modem, SleepFlag, PortP->Mapped, TtyP) );
+
+	if (!TtyP) {
+	  rio_dprint (RIO_DEBUG_PARAM, ("Can't call rioparam with null tty.\n"));
+	  return RIO_FAIL;
+	}
+	rio_spin_lock_irqsave(&PortP->portSem, flags );
+
+	if (cmd == OPEN) {
+		/*
+		** If the port is set to store or lock the parameters, and it is
+		** paramed with OPEN, we want to restore the saved port termio, but
+		** only if StoredTermio has been saved, i.e. NOT 1st open after reboot.
+		*/
+#if 0
+		if (PortP->FirstOpen) {
+			PortP->StoredTty.iflag = TtyP->tm.c_iflag;
+			PortP->StoredTty.oflag = TtyP->tm.c_oflag;
+			PortP->StoredTty.cflag = TtyP->tm.c_cflag;
+			PortP->StoredTty.lflag = TtyP->tm.c_lflag;
+			PortP->StoredTty.line = TtyP->tm.c_line;
+			for (i = 0; i < NCC + 5; i++)
+				PortP->StoredTty.cc[i] = TtyP->tm.c_cc[i];
+			PortP->FirstOpen = 0;
+		}
+		else if (PortP->Store || PortP->Lock) {
+			rio_dprint(RIO_DEBUG_PARAM, ("OPEN: Restoring stored/locked params\n"));
+			TtyP->tm.c_iflag = PortP->StoredTty.iflag;
+			TtyP->tm.c_oflag = PortP->StoredTty.oflag;
+			TtyP->tm.c_cflag = PortP->StoredTty.cflag;
+			TtyP->tm.c_lflag = PortP->StoredTty.lflag;
+			TtyP->tm.c_line = PortP->StoredTty.line;
+			for (i = 0; i < NCC + 5; i++)
+				TtyP->tm.c_cc[i] = PortP->StoredTty.cc[i];
+		}
+#endif
+	}
+
+	/*
+	** wait for space
+	*/
+	while ( !(res=can_add_transmit(&PacketP,PortP)) || 
+			(PortP->InUse != NOT_INUSE) ) {
+		if (retries -- <= 0) {
+			break;
+		}
+		if ( PortP->InUse != NOT_INUSE ) {
+			rio_dprint(RIO_DEBUG_PARAM, ("Port IN_USE for pre-emptive command\n"));
+		}
+
+		if ( !res ) {
+			rio_dprint(RIO_DEBUG_PARAM, ("Port has no space on transmit queue\n"));
+		}
+
+		if ( SleepFlag != OK_TO_SLEEP ) {
+			rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+			return RIO_FAIL;
+		}
+
+		rio_dprint(RIO_DEBUG_PARAM, ("wait for can_add_transmit\n"));
+		rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+		retval = RIODelay(PortP, HUNDRED_MS);
+		rio_spin_lock_irqsave( &PortP->portSem, flags);
+		if (retval == RIO_FAIL) {
+			rio_dprint(RIO_DEBUG_PARAM, ("wait for can_add_transmit broken by signal\n"));
+			rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+			pseterr(EINTR);
+			return RIO_FAIL;
+		}
+		if ( PortP->State & RIO_DELETED ) {
+			rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+			return RIO_SUCCESS;
+		}
+	}
+
+	if (!res) {
+		rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+		return RIO_FAIL;
+	}
+
+	rio_dprint(RIO_DEBUG_PARAM, ("can_add_transmit() returns %x\n",res));
+	rio_dprint(RIO_DEBUG_PARAM, ("Packet is 0x%x\n",(int) PacketP));
+
+	phb_param_ptr = (struct phb_param *)PacketP->data;
+
+
+#if 0
+	/*
+	** COR 1
+	*/
+	if ( TtyP->tm.c_iflag & INPCK ) {
+		rio_dprint(RIO_DEBUG_PARAM, ("Parity checking on input enabled\n"));
+		Cor1 |= COR1_INPCK;
+	}
+#endif
+
+	switch ( TtyP->termios->c_cflag & CSIZE ) {
+		case CS5:
+		{
+			rio_dprint(RIO_DEBUG_PARAM, ("5 bit data\n"));
+			Cor1 |= COR1_5BITS;
+			break;
+		}
+		case CS6:
+		{
+			rio_dprint(RIO_DEBUG_PARAM, ("6 bit data\n"));
+			Cor1 |= COR1_6BITS;
+			break;
+		}
+		case CS7:
+		{
+			rio_dprint(RIO_DEBUG_PARAM, ("7 bit data\n"));
+			Cor1 |= COR1_7BITS;
+			break;
+		}
+		case CS8:
+		{
+			rio_dprint(RIO_DEBUG_PARAM, ("8 bit data\n"));
+			Cor1 |= COR1_8BITS;
+			break;
+		}
+	}
+
+	if ( TtyP->termios->c_cflag & CSTOPB ) {
+		rio_dprint(RIO_DEBUG_PARAM, ("2 stop bits\n"));
+		Cor1 |= COR1_2STOP;
+	}
+	else {
+		rio_dprint(RIO_DEBUG_PARAM, ("1 stop bit\n"));
+		Cor1 |= COR1_1STOP;
+	}
+
+	if ( TtyP->termios->c_cflag & PARENB ) {
+		rio_dprint(RIO_DEBUG_PARAM, ("Enable parity\n"));
+		Cor1 |= COR1_NORMAL;
+	}
+	else {
+		rio_dprint(RIO_DEBUG_PARAM, ("Disable parity\n"));
+		Cor1 |= COR1_NOP;
+	}
+	if ( TtyP->termios->c_cflag & PARODD ) {
+		rio_dprint(RIO_DEBUG_PARAM, ("Odd parity\n"));
+		Cor1 |= COR1_ODD;
+	}
+	else {
+		rio_dprint(RIO_DEBUG_PARAM, ("Even parity\n"));
+		Cor1 |= COR1_EVEN; 
+	}
+
+	/*
+	** COR 2
+	*/
+	if ( TtyP->termios->c_iflag & IXON ) {
+		rio_dprint(RIO_DEBUG_PARAM, ("Enable start/stop output control\n"));
+		Cor2 |= COR2_IXON;
+	}
+	else {
+		if ( PortP->Config & RIO_IXON ) {
+			rio_dprint(RIO_DEBUG_PARAM, ("Force enable start/stop output control\n"));
+			Cor2 |= COR2_IXON;
+		}
+		else
+			rio_dprint(RIO_DEBUG_PARAM, ("IXON has been disabled.\n"));
+	}
+
+	if (TtyP->termios->c_iflag & IXANY) {
+		if ( PortP->Config & RIO_IXANY ) {
+			rio_dprint(RIO_DEBUG_PARAM, ("Enable any key to restart output\n"));
+			Cor2 |= COR2_IXANY;
+		}
+		else
+			rio_dprint(RIO_DEBUG_PARAM, ("IXANY has been disabled due to sanity reasons.\n"));
+	}
+
+	if ( TtyP->termios->c_iflag & IXOFF ) {
+		rio_dprint(RIO_DEBUG_PARAM, ("Enable start/stop input control 2\n"));
+		Cor2 |= COR2_IXOFF;
+	}
+
+	if ( TtyP->termios->c_cflag & HUPCL ) {
+		rio_dprint(RIO_DEBUG_PARAM, ("Hangup on last close\n"));
+		Cor2 |= COR2_HUPCL;
+	}
+
+	if ( C_CRTSCTS (TtyP)) {
+		rio_dprint(RIO_DEBUG_PARAM, ("Rx hardware flow control enabled\n"));
+		Cor2 |= COR2_CTSFLOW;
+		Cor2 |= COR2_RTSFLOW;
+	} else {
+		rio_dprint(RIO_DEBUG_PARAM, ("Rx hardware flow control disabled\n"));
+		Cor2 &= ~COR2_CTSFLOW;
+		Cor2 &= ~COR2_RTSFLOW;
+	}
+
+
+	if ( TtyP->termios->c_cflag & CLOCAL ) {
+		rio_dprint(RIO_DEBUG_PARAM, ("Local line\n"));
+	}
+	else {
+		rio_dprint(RIO_DEBUG_PARAM, ("Possible Modem line\n"));
+	}
+
+	/*
+	** COR 4 (there is no COR 3)
+	*/
+	if ( TtyP->termios->c_iflag & IGNBRK ) {
+		rio_dprint(RIO_DEBUG_PARAM, ("Ignore break condition\n"));
+		Cor4 |= COR4_IGNBRK;
+	}
+	if ( !(TtyP->termios->c_iflag & BRKINT) ) {
+		rio_dprint(RIO_DEBUG_PARAM, ("Break generates NULL condition\n"));
+		Cor4 |= COR4_NBRKINT;
+	} else {
+		rio_dprint(RIO_DEBUG_PARAM, ("Interrupt on	break condition\n"));
+	}
+
+	if ( TtyP->termios->c_iflag & INLCR ) {
+		rio_dprint(RIO_DEBUG_PARAM, ("Map newline to carriage return on input\n"));
+		Cor4 |= COR4_INLCR;
+	}
+
+	if ( TtyP->termios->c_iflag & IGNCR ) {
+		rio_dprint(RIO_DEBUG_PARAM, ("Ignore carriage return on input\n"));
+		Cor4 |= COR4_IGNCR;
+	}
+
+	if ( TtyP->termios->c_iflag & ICRNL ) {
+		rio_dprint(RIO_DEBUG_PARAM, ("Map carriage return to newline on input\n"));
+		Cor4 |= COR4_ICRNL;
+	}
+	if ( TtyP->termios->c_iflag & IGNPAR ) {
+		rio_dprint(RIO_DEBUG_PARAM, ("Ignore characters with parity errors\n"));
+		Cor4 |= COR4_IGNPAR;
+	}
+	if ( TtyP->termios->c_iflag & PARMRK ) {
+		rio_dprint(RIO_DEBUG_PARAM, ("Mark parity errors\n"));
+		Cor4 |= COR4_PARMRK;
+	}
+
+	/*
+	** Set the RAISEMOD flag to ensure that the modem lines are raised
+	** on reception of a config packet.
+	** The download code handles the zero baud condition.
+	*/
+	Cor4 |= COR4_RAISEMOD;
+
+	/*
+	** COR 5
+	*/
+
+	Cor5 = COR5_CMOE;
+
+	/*
+	** Set to monitor tbusy/tstop (or not).
+	*/
+
+	if (PortP->MonitorTstate)
+		Cor5 |= COR5_TSTATE_ON;
+	else
+		Cor5 |= COR5_TSTATE_OFF;
+
+	/*
+	** Could set LNE here if you wanted LNext processing. SVR4 will use it.
+	*/
+	if ( TtyP->termios->c_iflag & ISTRIP ) {
+		rio_dprint(RIO_DEBUG_PARAM, ("Strip input characters\n"));
+		if (! (PortP->State & RIO_TRIAD_MODE)) {
+			Cor5 |= COR5_ISTRIP;
+		}
+	}
+
+	if ( TtyP->termios->c_oflag & ONLCR ) {
+		rio_dprint(RIO_DEBUG_PARAM, ("Map newline to carriage-return, newline on output\n"));
+		if ( PortP->CookMode == COOK_MEDIUM )
+			Cor5 |= COR5_ONLCR;
+	}
+	if ( TtyP->termios->c_oflag & OCRNL ) {
+		rio_dprint(RIO_DEBUG_PARAM, ("Map carriage return to newline on output\n"));
+		if ( PortP->CookMode == COOK_MEDIUM )
+			Cor5 |= COR5_OCRNL;
+	}
+	if ( ( TtyP->termios->c_oflag & TABDLY) == TAB3 ) {
+		rio_dprint(RIO_DEBUG_PARAM, ("Tab delay 3 set\n"));
+		if ( PortP->CookMode == COOK_MEDIUM )
+			Cor5 |= COR5_TAB3;
+	}
+
+	/*
+	** Flow control bytes.
+	*/
+	TxXon = TtyP->termios->c_cc[VSTART];
+	TxXoff = TtyP->termios->c_cc[VSTOP];
+	RxXon = TtyP->termios->c_cc[VSTART];
+	RxXoff = TtyP->termios->c_cc[VSTOP];
+	/*
+	** LNEXT byte
+	*/
+	LNext = 0;
+
+	/*
+	** Baud rate bytes
+	*/
+	rio_dprint(RIO_DEBUG_PARAM, ("Mapping of rx/tx baud %x (%x)\n", 
+				     TtyP->termios->c_cflag, CBAUD));
+
+	switch (TtyP->termios->c_cflag & CBAUD) {
+#define e(b) case B ## b : RxBaud = TxBaud = RIO_B ## b ;break
+	  e(50);e(75);e(110);e(134);e(150);e(200);e(300);e(600);e(1200);
+	  e(1800);e(2400);e(4800);e(9600);e(19200);e(38400);e(57600);
+	  e(115200); /* e(230400);e(460800); e(921600);  */
+	}
+
+	/* XXX MIssing conversion table. XXX */
+	/* 	 (TtyP->termios->c_cflag & V_CBAUD); */
+
+	rio_dprint(RIO_DEBUG_PARAM, ("tx baud 0x%x, rx baud 0x%x\n", TxBaud, RxBaud));
+
+
+	/*
+	** Leftovers
+	*/
+	if ( TtyP->termios->c_cflag & CREAD )
+		rio_dprint(RIO_DEBUG_PARAM, ("Enable receiver\n"));
+#ifdef RCV1EN
+	if ( TtyP->termios->c_cflag & RCV1EN )
+		rio_dprint(RIO_DEBUG_PARAM, ("RCV1EN (?)\n"));
+#endif
+#ifdef XMT1EN
+	if ( TtyP->termios->c_cflag & XMT1EN )
+		rio_dprint(RIO_DEBUG_PARAM, ("XMT1EN (?)\n"));
+#endif
+#if 0
+	if ( TtyP->termios->c_cflag & LOBLK )
+		rio_dprint(RIO_DEBUG_PARAM, ("LOBLK - JCL output blocks when not current\n"));
+#endif
+	if ( TtyP->termios->c_lflag & ISIG )
+		rio_dprint(RIO_DEBUG_PARAM, ("Input character signal generating enabled\n"));
+	if ( TtyP->termios->c_lflag & ICANON )
+		rio_dprint(RIO_DEBUG_PARAM, ("Canonical input: erase and kill enabled\n"));
+	if ( TtyP->termios->c_lflag & XCASE )
+		rio_dprint(RIO_DEBUG_PARAM, ("Canonical upper/lower presentation\n"));
+	if ( TtyP->termios->c_lflag & ECHO )
+		rio_dprint(RIO_DEBUG_PARAM, ("Enable input echo\n"));
+	if ( TtyP->termios->c_lflag & ECHOE )
+		rio_dprint(RIO_DEBUG_PARAM, ("Enable echo erase\n"));
+	if ( TtyP->termios->c_lflag & ECHOK )
+		rio_dprint(RIO_DEBUG_PARAM, ("Enable echo kill\n"));
+	if ( TtyP->termios->c_lflag & ECHONL )
+		rio_dprint(RIO_DEBUG_PARAM, ("Enable echo newline\n"));
+	if ( TtyP->termios->c_lflag & NOFLSH )
+		rio_dprint(RIO_DEBUG_PARAM, ("Disable flush after interrupt or quit\n"));
+#ifdef TOSTOP
+	if ( TtyP->termios->c_lflag & TOSTOP )
+		rio_dprint(RIO_DEBUG_PARAM, ("Send SIGTTOU for background output\n"));
+#endif
+#ifdef XCLUDE
+	if ( TtyP->termios->c_lflag & XCLUDE )
+		rio_dprint(RIO_DEBUG_PARAM, ("Exclusive use of this line\n"));
+#endif
+	if ( TtyP->termios->c_iflag & IUCLC )
+		rio_dprint(RIO_DEBUG_PARAM, ("Map uppercase to lowercase on input\n"));
+	if ( TtyP->termios->c_oflag & OPOST )
+		rio_dprint(RIO_DEBUG_PARAM, ("Enable output post-processing\n"));
+	if ( TtyP->termios->c_oflag & OLCUC )
+		rio_dprint(RIO_DEBUG_PARAM, ("Map lowercase to uppercase on output\n"));
+	if ( TtyP->termios->c_oflag & ONOCR )
+		rio_dprint(RIO_DEBUG_PARAM, ("No carriage return output at column 0\n"));
+	if ( TtyP->termios->c_oflag & ONLRET )
+		rio_dprint(RIO_DEBUG_PARAM, ("Newline performs carriage return function\n"));
+	if ( TtyP->termios->c_oflag & OFILL )
+		rio_dprint(RIO_DEBUG_PARAM, ("Use fill characters for delay\n"));
+	if ( TtyP->termios->c_oflag & OFDEL )
+		rio_dprint(RIO_DEBUG_PARAM, ("Fill character is DEL\n"));
+	if ( TtyP->termios->c_oflag & NLDLY )
+		rio_dprint(RIO_DEBUG_PARAM, ("Newline delay set\n"));
+	if ( TtyP->termios->c_oflag & CRDLY )
+		rio_dprint(RIO_DEBUG_PARAM, ("Carriage return delay set\n"));
+	if ( TtyP->termios->c_oflag & TABDLY )
+		rio_dprint(RIO_DEBUG_PARAM, ("Tab delay set\n"));
+#if 0
+	if ( TtyP->termios->c_oflag & BSDLY )
+		rio_dprint(RIO_DEBUG_PARAM, ("Back-space delay set\n"));
+	if ( TtyP->termios->c_oflag & VTDLY )
+		rio_dprint(RIO_DEBUG_PARAM, ("Vertical tab delay set\n"));
+	if ( TtyP->termios->c_oflag & FFDLY )
+		rio_dprint(RIO_DEBUG_PARAM, ("Form-feed delay set\n"));
+#endif
+	/*
+	** These things are kind of useful in a later life!
+	*/
+	PortP->Cor2Copy = Cor2;
+
+	if ( PortP->State & RIO_DELETED ) {
+		rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+		return RIO_FAIL;
+	}
+
+	/*
+	** Actually write the info into the packet to be sent
+	*/
+	WBYTE(phb_param_ptr->Cmd,	cmd);
+	WBYTE(phb_param_ptr->Cor1,	 Cor1);
+	WBYTE(phb_param_ptr->Cor2,	 Cor2);
+	WBYTE(phb_param_ptr->Cor4,	 Cor4);
+	WBYTE(phb_param_ptr->Cor5,	 Cor5);
+	WBYTE(phb_param_ptr->TxXon,	TxXon);
+	WBYTE(phb_param_ptr->RxXon,	RxXon);
+	WBYTE(phb_param_ptr->TxXoff, TxXoff);
+	WBYTE(phb_param_ptr->RxXoff, RxXoff);
+	WBYTE(phb_param_ptr->LNext,	LNext);
+	WBYTE(phb_param_ptr->TxBaud, TxBaud);
+	WBYTE(phb_param_ptr->RxBaud, RxBaud);
+
+	/*
+	** Set the length/command field
+	*/
+	WBYTE(PacketP->len , 12 | PKT_CMD_BIT);
+
+	/*
+	** The packet is formed - now, whack it off
+	** to its final destination:
+	*/
+	add_transmit(PortP);
+	/*
+	** Count characters transmitted for port statistics reporting
+	*/
+	if (PortP->statsGather)
+		PortP->txchars += 12;
+
+	rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+
+	rio_dprint(RIO_DEBUG_PARAM, ("add_transmit returned.\n"));
+	/*
+	** job done.
+	*/
+	return RIO_SUCCESS;
+}
+
+
+/*
+** We can add another packet to a transmit queue if the packet pointer pointed
+** to by the TxAdd pointer has PKT_IN_USE clear in its address.
+*/
+int
+can_add_transmit(PktP, PortP)
+PKT **PktP;
+struct Port *PortP; 
+{
+	register PKT *tp;
+
+	*PktP = tp = (PKT *)RIO_PTR(PortP->Caddr,RWORD(*PortP->TxAdd));
+
+	return !((uint)tp & PKT_IN_USE);
+}
+
+/*
+** To add a packet to the queue, you set the PKT_IN_USE bit in the address,
+** and then move the TxAdd pointer along one position to point to the next
+** packet pointer. You must wrap the pointer from the end back to the start.
+*/
+void
+add_transmit(PortP)
+struct Port *PortP; 
+{
+  if (RWORD(*PortP->TxAdd) & PKT_IN_USE) {
+    rio_dprint (RIO_DEBUG_PARAM, ("add_transmit: Packet has been stolen!"));
+  }
+	WWORD( *(ushort *)PortP->TxAdd, RWORD(*PortP->TxAdd) | PKT_IN_USE);
+	PortP->TxAdd = (PortP->TxAdd == PortP->TxEnd) ? PortP->TxStart : 
+					PortP->TxAdd + 1;
+	WWORD( PortP->PhbP->tx_add , RIO_OFF(PortP->Caddr,PortP->TxAdd) );
+}
+
+/****************************************
+ * Put a packet onto the end of the
+ * free list
+ ****************************************/
+void
+put_free_end(HostP, PktP)
+struct Host *HostP;
+PKT *PktP;
+{
+	FREE_LIST *tmp_pointer;
+	ushort old_end, new_end;
+	unsigned long flags;
+
+	rio_spin_lock_irqsave(&HostP->HostLock, flags);
+
+	 /*************************************************
+	* Put a packet back onto the back of the free list
+	*
+	************************************************/
+
+	rio_dprint(RIO_DEBUG_PFE, ("put_free_end(PktP=%x)\n",(int)PktP));
+
+	if ((old_end=RWORD(HostP->ParmMapP->free_list_end)) != TPNULL) {
+		new_end = RIO_OFF(HostP->Caddr,PktP);
+		tmp_pointer = (FREE_LIST *)RIO_PTR(HostP->Caddr,old_end);
+		WWORD(tmp_pointer->next , new_end );
+		WWORD(((FREE_LIST *)PktP)->prev , old_end);
+		WWORD(((FREE_LIST *)PktP)->next , TPNULL);
+		WWORD(HostP->ParmMapP->free_list_end, new_end);
+	}
+	else {	/* First packet on the free list this should never happen! */
+		rio_dprint(RIO_DEBUG_PFE, ("put_free_end(): This should never happen\n"));
+		WWORD(HostP->ParmMapP->free_list_end , RIO_OFF(HostP->Caddr,PktP));
+		tmp_pointer = (FREE_LIST *)PktP;
+		WWORD(tmp_pointer->prev , TPNULL);
+		WWORD(tmp_pointer->next , TPNULL);
+	}
+	rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
+}
+
+/*
+** can_remove_receive(PktP,P) returns non-zero if PKT_IN_USE is set
+** for the next packet on the queue. It will also set PktP to point to the
+** relevent packet, [having cleared the PKT_IN_USE bit]. If PKT_IN_USE is clear,
+** then can_remove_receive() returns 0.
+*/
+int
+can_remove_receive(PktP, PortP)
+PKT **PktP;
+struct Port *PortP;
+{
+	if ( RWORD(*PortP->RxRemove) & PKT_IN_USE) {
+		*PktP = (PKT *)RIO_PTR(PortP->Caddr,
+					RWORD(*PortP->RxRemove) & ~PKT_IN_USE);
+		return 1;
+	}
+	return 0;
+}
+
+/*
+** To remove a packet from the receive queue you clear its PKT_IN_USE bit,
+** and then bump the pointers. Once the pointers get to the end, they must
+** be wrapped back to the start.
+*/
+void
+remove_receive(PortP)
+struct Port *PortP; 
+{
+	WWORD( *PortP->RxRemove, RWORD(*PortP->RxRemove) & ~PKT_IN_USE );
+	PortP->RxRemove = (PortP->RxRemove == PortP->RxEnd) ? PortP->RxStart : 
+								PortP->RxRemove + 1;
+	WWORD( PortP->PhbP->rx_remove , RIO_OFF(PortP->Caddr, PortP->RxRemove) );
+}
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/riopcicopy.c linux.15p9/drivers/char/rio/riopcicopy.c
--- linux.vanilla/drivers/char/rio/riopcicopy.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/riopcicopy.c	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,8 @@
+
+/* Yeah. We have copyright on this one. Sure. */
+
+void rio_pcicopy( char *from, char *to, int amount)
+{
+  while ( amount-- )
+    *to++ = *from++;
+}
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/rioroute.c linux.15p9/drivers/char/rio/rioroute.c
--- linux.vanilla/drivers/char/rio/rioroute.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/rioroute.c	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,1234 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: rioroute.c
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 10:33:46
+**	Retrieved	: 11/6/98 10:33:50
+**
+**  ident @(#)rioroute.c	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+#ifdef SCCS_LABELS
+static char *_rioroute_c_sccs_ = "@(#)rioroute.c	1.3";
+#endif
+
+#define __NO_VERSION__
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/malloc.h>
+#include <linux/errno.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/string.h>
+#include <asm/semaphore.h>
+#include <asm/uaccess.h>
+
+#include <linux/termios.h>
+#include <linux/serial.h>
+
+#include <linux/compatmac.h>
+#include <linux/generic_serial.h>
+
+
+#include "linux_compat.h"
+#include "rio_linux.h"
+#include "typdef.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "top.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "riotypes.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "error.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+#include "control.h"
+#include "cirrus.h"
+#include "rioioctl.h"
+#include "param.h"
+#include "list.h"
+#include "sam.h"
+
+/*
+** Incoming on the ROUTE_RUP
+** I wrote this while I was tired. Forgive me.
+*/
+int RIORouteRup( struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP )
+{
+  struct PktCmd *PktCmdP = (struct PktCmd *)PacketP->data;
+  struct PktCmd_M *PktReplyP;
+  struct CmdBlk *CmdBlkP;
+  struct Port *PortP;
+  struct Map *MapP;
+  struct Top *TopP;
+  int ThisLink, ThisLinkMin, ThisLinkMax;
+  int port;
+  int Mod, Mod1, Mod2;
+  ushort RtaType;
+  uint RtaUniq;
+  uint ThisUnit, ThisUnit2;	/* 2 ids to accommodate 16 port RTA */
+  uint OldUnit, NewUnit, OldLink, NewLink;
+  char *MyType, *MyName;
+  int Lies;
+  unsigned long flags;
+
+#ifdef STACK
+    RIOStackCheck("RIORouteRup");
+#endif
+#ifdef CHECK
+    CheckPacketP(PacketP);
+    CheckHostP(HostP);
+    CheckRup(Rup);
+    CheckHost(Host);
+#endif
+  /*
+  ** Is this unit telling us it's current link topology?
+  */
+  if ( RBYTE(PktCmdP->Command) == ROUTE_TOPOLOGY )
+  {
+    MapP = HostP->Mapping;
+
+    /*
+    ** The packet can be sent either by the host or by an RTA.
+    ** If it comes from the host, then we need to fill in the
+    ** Topology array in the host structure. If it came in
+    ** from an RTA then we need to fill in the Mapping structure's
+    ** Topology array for the unit.
+    */
+    if ( Rup >= (ushort)MAX_RUP )
+    {
+      ThisUnit = HOST_ID;
+      TopP = HostP->Topology;
+      MyType = "Host";
+      MyName = HostP->Name;
+      ThisLinkMin = ThisLinkMax = Rup - MAX_RUP;
+    }
+    else
+    {
+      ThisUnit = Rup+1;
+      TopP = HostP->Mapping[Rup].Topology;
+      MyType = "RTA";
+      MyName = HostP->Mapping[Rup].Name;
+      ThisLinkMin = 0;
+      ThisLinkMax = LINKS_PER_UNIT - 1;
+    }
+
+    /*
+    ** Lies will not be tolerated.
+    ** If any pair of links claim to be connected to the same
+    ** place, then ignore this packet completely.
+    */
+    Lies = 0;
+    for ( ThisLink=ThisLinkMin + 1; ThisLink <= ThisLinkMax; ThisLink++)
+    {
+      /*
+      ** it won't lie about network interconnect, total disconnects
+      ** and no-IDs. (or at least, it doesn't *matter* if it does)
+      */
+      if ( RBYTE(PktCmdP->RouteTopology[ThisLink].Unit) > (ushort)MAX_RUP )
+	  continue;
+
+      for ( NewLink=ThisLinkMin; NewLink < ThisLink; NewLink++ )
+      {
+        if ( (RBYTE(PktCmdP->RouteTopology[ThisLink].Unit) ==
+              RBYTE(PktCmdP->RouteTopology[NewLink].Unit)) &&
+	     (RBYTE(PktCmdP->RouteTopology[ThisLink].Link) ==
+              RBYTE(PktCmdP->RouteTopology[NewLink].Link)) )
+	{
+          Lies++;
+	}
+      }
+    }
+
+    if ( Lies )
+    {
+      rio_dprint(RIO_DEBUG_ROUTE, ("LIES! DAMN LIES! %d LIES!\n",Lies));
+      rio_dprint(RIO_DEBUG_ROUTE, ("%d:%c %d:%c %d:%c %d:%c\n",
+          RBYTE(PktCmdP->RouteTopology[0].Unit), 
+	  'A'+RBYTE(PktCmdP->RouteTopology[0].Link),
+          RBYTE(PktCmdP->RouteTopology[1].Unit),
+	  'A'+RBYTE(PktCmdP->RouteTopology[1].Link),
+          RBYTE(PktCmdP->RouteTopology[2].Unit),
+	  'A'+RBYTE(PktCmdP->RouteTopology[2].Link),
+          RBYTE(PktCmdP->RouteTopology[3].Unit),
+	  'A'+RBYTE(PktCmdP->RouteTopology[3].Link)));
+      return TRUE;
+    }
+
+    /*
+    ** now, process each link.
+    */
+    for ( ThisLink=ThisLinkMin; ThisLink <= ThisLinkMax; ThisLink++)
+    {
+      /*
+      ** this is what it was connected to
+      */
+      OldUnit = TopP[ThisLink].Unit;
+      OldLink = TopP[ThisLink].Link;
+
+      /*
+      ** this is what it is now connected to
+      */
+      NewUnit = RBYTE(PktCmdP->RouteTopology[ThisLink].Unit);
+      NewLink = RBYTE(PktCmdP->RouteTopology[ThisLink].Link);
+
+      if ( OldUnit != NewUnit || OldLink != NewLink )
+      {
+	/*
+	** something has changed!
+	*/
+
+        if ( NewUnit > MAX_RUP &&
+	     NewUnit != ROUTE_DISCONNECT &&
+	     NewUnit != ROUTE_NO_ID &&
+	     NewUnit != ROUTE_INTERCONNECT )
+	{
+	    rio_dprint(RIO_DEBUG_ROUTE, ("I have a link from %s %s to unit %d:%d - I don't like it.\n",
+		  MyType,
+		  MyName,
+		  NewUnit,
+		  NewLink));
+	}
+	else
+	{
+	  /*
+	  ** put the new values in
+	  */
+	  TopP[ThisLink].Unit = NewUnit;
+	  TopP[ThisLink].Link = NewLink;
+
+	  RIOSetChange(p);
+
+	  if ( OldUnit <= MAX_RUP )
+	  {
+	    /*
+	    ** If something has become bust, then re-enable them messages
+	    */
+	    if (! p->RIONoMessage)
+		RIOConCon(p,HostP,ThisUnit,ThisLink,OldUnit,OldLink,DISCONNECT);
+	  }
+
+	  if ( ( NewUnit <= MAX_RUP ) && !p->RIONoMessage )
+	    RIOConCon(p,HostP,ThisUnit,ThisLink,NewUnit,NewLink,CONNECT);
+
+	  if ( NewUnit == ROUTE_NO_ID )
+	    rio_dprint(RIO_DEBUG_ROUTE, ("%s %s (%c) is connected to an unconfigured unit.\n",
+		    MyType,MyName,'A'+ThisLink));
+
+	  if ( NewUnit == ROUTE_INTERCONNECT )
+	  {
+	    if (! p->RIONoMessage)
+		cprintf("%s '%s' (%c) is connected to another network.\n", MyType,MyName,'A'+ThisLink);
+	  }
+
+	  /*
+	  ** perform an update for 'the other end', so that these messages
+	  ** only appears once. Only disconnect the other end if it is pointing
+	  ** at us!
+	  */
+	  if ( OldUnit == HOST_ID )
+	  {
+	    if ( HostP->Topology[OldLink].Unit == ThisUnit &&
+		 HostP->Topology[OldLink].Link == ThisLink )
+	    {
+	      rio_dprint(RIO_DEBUG_ROUTE, ("SETTING HOST (%c) TO DISCONNECTED!\n", OldLink+'A'));
+	      HostP->Topology[OldLink].Unit = ROUTE_DISCONNECT;
+	      HostP->Topology[OldLink].Link = NO_LINK;
+	    }
+	    else
+	    {
+	      rio_dprint(RIO_DEBUG_ROUTE, ("HOST(%c) WAS NOT CONNECTED TO %s (%c)!\n",
+		    OldLink+'A',HostP->Mapping[ThisUnit-1].Name,ThisLink+'A'));
+	    }
+	  }
+	  else if ( OldUnit <= MAX_RUP )
+	  {
+	    if ( HostP->Mapping[OldUnit-1].Topology[OldLink].Unit == ThisUnit &&
+	         HostP->Mapping[OldUnit-1].Topology[OldLink].Link == ThisLink )
+	    {
+	      rio_dprint(RIO_DEBUG_ROUTE, ("SETTING RTA %s (%c) TO DISCONNECTED!\n",
+				   HostP->Mapping[OldUnit-1].Name,OldLink+'A'));
+	      HostP->Mapping[OldUnit-1].Topology[OldLink].Unit=ROUTE_DISCONNECT;
+	      HostP->Mapping[OldUnit-1].Topology[OldLink].Link=NO_LINK;
+	    }
+	    else
+	    {
+	      rio_dprint(RIO_DEBUG_ROUTE, ("RTA %s (%c) WAS NOT CONNECTED TO %s (%c)\n",
+			    HostP->Mapping[OldUnit-1].Name,OldLink+'A',
+			    HostP->Mapping[ThisUnit-1].Name,ThisLink+'A'));
+	    }
+	  }
+	  if ( NewUnit == HOST_ID )
+	  {
+	    rio_dprint(RIO_DEBUG_ROUTE, ("MARKING HOST (%c) CONNECTED TO %s (%c)\n",
+				NewLink+'A',MyName,ThisLink+'A'));
+	    HostP->Topology[NewLink].Unit = ThisUnit;
+	    HostP->Topology[NewLink].Link = ThisLink;
+	  }
+	  else if ( NewUnit <= MAX_RUP )
+	  {
+	    rio_dprint(RIO_DEBUG_ROUTE, ("MARKING RTA %s (%c) CONNECTED TO %s (%c)\n",
+	      HostP->Mapping[NewUnit-1].Name,NewLink+'A',MyName,ThisLink+'A'));
+	    HostP->Mapping[NewUnit-1].Topology[NewLink].Unit=ThisUnit;
+	    HostP->Mapping[NewUnit-1].Topology[NewLink].Link=ThisLink;
+	  }
+	}
+	RIOSetChange(p);
+	RIOCheckIsolated(p, HostP, OldUnit );
+      }
+    }
+    return TRUE;
+  }
+
+  /*
+  ** The only other command we recognise is a route_request command
+  */
+  if ( RBYTE(PktCmdP->Command) != ROUTE_REQUEST )
+  {
+    rio_dprint(RIO_DEBUG_ROUTE, ("Unknown command %d received on rup %d host %d ROUTE_RUP\n", 
+	   RBYTE(PktCmdP->Command),Rup,(int)HostP));
+    return TRUE;
+  }
+      
+  RtaUniq = (RBYTE(PktCmdP->UniqNum[0])) +
+	    (RBYTE(PktCmdP->UniqNum[1]) << 8) +
+	    (RBYTE(PktCmdP->UniqNum[2]) << 16) +
+	    (RBYTE(PktCmdP->UniqNum[3]) << 24);
+
+  /*
+  ** Determine if 8 or 16 port RTA
+  */
+  RtaType = GetUnitType(RtaUniq);
+
+  rio_dprint(RIO_DEBUG_ROUTE, ("Received a request for an ID for serial number %x\n", RtaUniq));
+
+  Mod = RBYTE(PktCmdP->ModuleTypes);
+  Mod1 = LONYBLE(Mod);
+  if (RtaType == TYPE_RTA16)
+  {
+    /*
+    ** Only one ident is set for a 16 port RTA. To make compatible
+    ** with 8 port, set 2nd ident in Mod2 to the same as Mod1.
+    */
+    Mod2 = Mod1;
+    rio_dprint(RIO_DEBUG_ROUTE, ("Backplane type is %s (all ports)\n",
+     p->RIOModuleTypes[Mod1].Name ));
+  }
+  else
+  {
+    Mod2 = HINYBLE(Mod);
+    rio_dprint(RIO_DEBUG_ROUTE, ("Module types are %s (ports 0-3) and %s (ports 4-7)\n",
+     p->RIOModuleTypes[Mod1].Name, p->RIOModuleTypes[Mod2].Name ));
+  }
+
+  if ( RtaUniq == 0xffffffff )
+  {
+      ShowPacket( DBG_SPECIAL, PacketP );
+  }
+
+  /*
+  ** try to unhook a command block from the command free list.
+  */
+  if ( !(CmdBlkP = RIOGetCmdBlk()) )
+  {
+    rio_dprint(RIO_DEBUG_ROUTE, ("No command blocks to route RTA! come back later.\n"));
+    return 0;
+  }
+
+  /*
+  ** Fill in the default info on the command block
+  */
+  CmdBlkP->Packet.dest_unit = Rup;
+  CmdBlkP->Packet.dest_port = ROUTE_RUP;
+  CmdBlkP->Packet.src_unit = HOST_ID;
+  CmdBlkP->Packet.src_port = ROUTE_RUP;
+  CmdBlkP->Packet.len = PKT_CMD_BIT | 1;
+  CmdBlkP->PreFuncP = CmdBlkP->PostFuncP = NULL;
+  PktReplyP = (struct PktCmd_M *)CmdBlkP->Packet.data;
+
+  if (! RIOBootOk(p, HostP, RtaUniq))
+  {
+    rio_dprint(RIO_DEBUG_ROUTE, ("RTA %x tried to get an ID, but does not belong - FOAD it!\n",
+	  RtaUniq));
+    PktReplyP->Command = ROUTE_FOAD;
+    HostP->Copy("RT_FOAD", PktReplyP->CommandText, 7);
+    RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
+    return TRUE;
+  }
+
+  /*
+  ** Check to see if the RTA is configured for this host
+  */
+  for ( ThisUnit=0; ThisUnit<MAX_RUP; ThisUnit++ )
+  {
+    rio_dprint(RIO_DEBUG_ROUTE, ("Entry %d Flags=%s %s UniqueNum=0x%x\n",
+			ThisUnit,
+			HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE ?
+					    "Slot-In-Use":"Not In Use",
+			HostP->Mapping[ThisUnit].Flags & SLOT_TENTATIVE ? 
+					    "Slot-Tentative":"Not Tentative",
+			HostP->Mapping[ThisUnit].RtaUniqueNum ));
+
+    /*
+    ** We have an entry for it.
+    */
+    if ( (HostP->Mapping[ThisUnit].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) &&
+         (HostP->Mapping[ThisUnit].RtaUniqueNum == RtaUniq) )
+    {
+      if (RtaType == TYPE_RTA16)
+      {
+	  ThisUnit2 = HostP->Mapping[ThisUnit].ID2 - 1;
+          rio_dprint(RIO_DEBUG_ROUTE, ("Found unit 0x%x at slots %d+%d\n",
+					    RtaUniq,ThisUnit,ThisUnit2));
+      }
+      else
+          rio_dprint(RIO_DEBUG_ROUTE, ("Found unit 0x%x at slot %d\n",
+					    RtaUniq,ThisUnit));
+      /*
+      ** If we have no knowledge of booting it, then the host has
+      ** been re-booted, and so we must kill the RTA, so that it
+      ** will be booted again (potentially with new bins)
+      ** and it will then re-ask for an ID, which we will service.
+      */
+      if ( (HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE) && 
+	  !(HostP->Mapping[ThisUnit].Flags & RTA_BOOTED) )
+      {
+	if ( !(HostP->Mapping[ThisUnit].Flags & MSG_DONE) )
+	{
+	    if ( !p->RIONoMessage )
+	        cprintf("RTA '%s' is being updated.\n",HostP->Mapping[ThisUnit].Name);
+	    HostP->Mapping[ThisUnit].Flags |= MSG_DONE;
+	}
+	PktReplyP->Command = ROUTE_FOAD;
+	HostP->Copy("RT_FOAD",PktReplyP->CommandText,7);
+	RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
+	return TRUE;
+      }
+
+      /*
+      ** Send the ID (entry) to this RTA. The ID number is implicit as
+      ** the offset into the table. It is worth noting at this stage
+      ** that offset zero in the table contains the entries for the
+      ** RTA with ID 1!!!!
+      */
+      PktReplyP->Command = ROUTE_ALLOCATE;
+      PktReplyP->IDNum   = ThisUnit+1;
+      if (RtaType == TYPE_RTA16)
+      {
+        if (HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE)
+	    /*
+	    ** Adjust the phb and tx pkt dest_units for 2nd block of 8
+	    ** only if the RTA has ports associated (SLOT_IN_USE)
+	    */
+	    RIOFixPhbs(p, HostP, ThisUnit2);
+	    PktReplyP->IDNum2  = ThisUnit2+1;
+	    rio_dprint(RIO_DEBUG_ROUTE, ("RTA '%s' has been allocated IDs %d+%d\n",
+	          HostP->Mapping[ThisUnit].Name, PktReplyP->IDNum, PktReplyP->IDNum2));
+      }
+      else
+      {
+	    PktReplyP->IDNum2 = ROUTE_NO_ID;
+	    rio_dprint(RIO_DEBUG_ROUTE, ("RTA '%s' has been allocated ID %d\n",
+	          HostP->Mapping[ThisUnit].Name,PktReplyP->IDNum));
+      }
+      HostP->Copy("RT_ALLOCAT",PktReplyP->CommandText,10);
+
+      RIOQueueCmdBlk( HostP, Rup, CmdBlkP);
+
+      /*
+      ** If this is a freshly booted RTA, then we need to re-open
+      ** the ports, if any where open, so that data may once more
+      ** flow around the system!
+      */
+      if ( (HostP->Mapping[ThisUnit].Flags & RTA_NEWBOOT) &&
+	   (HostP->Mapping[ThisUnit].SysPort != NO_PORT) )
+      {
+	/*
+	** look at the ports associated with this beast and
+	** see if any where open. If they was, then re-open
+	** them, using the info from the tty flags.
+	*/
+	for ( port=0; port<PORTS_PER_RTA; port++ )
+	{
+	  PortP = p->RIOPortp[port+HostP->Mapping[ThisUnit].SysPort];
+	  if ( PortP->State & (RIO_MOPEN|RIO_LOPEN) )
+	  {
+	    rio_dprint(RIO_DEBUG_ROUTE, ("Re-opened this port\n"));
+	    rio_spin_lock_irqsave(&PortP->portSem, flags);
+	    PortP->MagicFlags |= MAGIC_REBOOT;
+	    rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	  }
+	}
+	if (RtaType == TYPE_RTA16)
+	{
+	  for ( port=0; port<PORTS_PER_RTA; port++ )
+	  {
+	    PortP = p->RIOPortp[port+HostP->Mapping[ThisUnit2].SysPort];
+	    if ( PortP->State & (RIO_MOPEN|RIO_LOPEN) )
+	    {
+	      rio_dprint(RIO_DEBUG_ROUTE, ("Re-opened this port\n"));
+	      rio_spin_lock_irqsave(&PortP->portSem, flags);
+	      PortP->MagicFlags |= MAGIC_REBOOT;
+	      rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	    }
+	  }
+	}
+      }
+
+      /*
+      ** keep a copy of the module types!
+      */
+      HostP->UnixRups[ThisUnit].ModTypes = Mod;
+      if (RtaType == TYPE_RTA16)
+	      HostP->UnixRups[ThisUnit2].ModTypes = Mod;
+
+      /*
+      ** If either of the modules on this unit is read-only or write-only
+      ** or none-xprint, then we need to transfer that info over to the
+      ** relevent ports.
+      */
+      if ( HostP->Mapping[ThisUnit].SysPort != NO_PORT )
+      {
+        for ( port=0; port<PORTS_PER_MODULE; port++ )
+	{
+	  p->RIOPortp[port+HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK;
+	  p->RIOPortp[port+HostP->Mapping[ThisUnit].SysPort]->Config |=
+	   p->RIOModuleTypes[Mod1].Flags[port];
+	  p->RIOPortp[port+PORTS_PER_MODULE+HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK;
+	  p->RIOPortp[port+PORTS_PER_MODULE+HostP->Mapping[ThisUnit].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port];
+	}
+	if (RtaType == TYPE_RTA16)
+	{
+          for ( port=0; port<PORTS_PER_MODULE; port++ )
+	  {
+	    p->RIOPortp[port+HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK;
+	    p->RIOPortp[port+HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod1].Flags[port];
+	    p->RIOPortp[port+PORTS_PER_MODULE+HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK;
+	    p->RIOPortp[port+PORTS_PER_MODULE+HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port];
+          }
+	}
+      }
+
+      /*
+      ** Job done, get on with the interrupts!
+      */
+      return TRUE;
+    }
+  }
+  /*
+  ** There is no table entry for this RTA at all.
+  **
+  ** Lets check to see if we actually booted this unit - if not,
+  ** then we reset it and it will go round the loop of being booted
+  ** we can then worry about trying to fit it into the table.
+  */
+  for ( ThisUnit=0; ThisUnit<HostP->NumExtraBooted; ThisUnit++ )
+    if ( HostP->ExtraUnits[ThisUnit] == RtaUniq )
+      break;
+  if ( ThisUnit == HostP->NumExtraBooted && ThisUnit != MAX_EXTRA_UNITS )
+  {
+    /*
+    ** if the unit wasn't in the table, and the table wasn't full, then
+    ** we reset the unit, because we didn't boot it.
+    ** However, if the table is full, it could be that we did boot
+    ** this unit, and so we won't reboot it, because it isn't really
+    ** all that disasterous to keep the old bins in most cases. This
+    ** is a rather tacky feature, but we are on the edge of reallity
+    ** here, because the implication is that someone has connected
+    ** 16+MAX_EXTRA_UNITS onto one host.
+    */
+    static int UnknownMesgDone = 0;
+
+    if ( !UnknownMesgDone )
+    {
+	if (! p->RIONoMessage)
+	    cprintf("One or more unknown RTAs are being updated.\n");
+	UnknownMesgDone = 1;
+    }
+
+    PktReplyP->Command = ROUTE_FOAD;
+    HostP->Copy("RT_FOAD",PktReplyP->CommandText,7);
+  }
+  else
+  {
+    /*
+    ** we did boot it (as an extra), and there may now be a table
+    ** slot free (because of a delete), so we will try to make
+    ** a tentative entry for it, so that the configurator can see it
+    ** and fill in the details for us.
+    */
+    if (RtaType == TYPE_RTA16)
+    {
+	if (RIOFindFreeID(p, HostP, &ThisUnit, &ThisUnit2) == 0)
+	{
+	    RIODefaultName(p, HostP, ThisUnit);
+	    FillSlot(ThisUnit, ThisUnit2, RtaUniq, HostP);
+	}
+    }
+    else
+    {
+	if (RIOFindFreeID(p, HostP, &ThisUnit, NULL) == 0)
+	{
+	    RIODefaultName(p, HostP, ThisUnit);
+	    FillSlot(ThisUnit, 0, RtaUniq, HostP);
+	}
+    }
+    PktReplyP->Command = ROUTE_USED;
+    HostP->Copy("RT_USED",PktReplyP->CommandText,7);
+  }
+  RIOQueueCmdBlk( HostP, Rup, CmdBlkP);
+  return TRUE;
+}
+
+
+void
+RIOFixPhbs(p, HostP, unit)
+struct rio_info *p;
+struct Host *HostP;
+uint unit;
+{
+	ushort			link, port;
+	struct Port		*PortP;
+	unsigned long flags;
+	int PortN = HostP->Mapping[unit].SysPort;
+
+	rio_dprint(RIO_DEBUG_ROUTE, ("RIOFixPhbs unit %d sysport %d\n", unit, PortN));
+
+	if (PortN != -1) {
+		ushort		dest_unit = HostP->Mapping[unit].ID2;
+
+		/*
+		** Get the link number used for the 1st 8 phbs on this unit.
+		*/
+		PortP = p->RIOPortp[HostP->Mapping[dest_unit - 1].SysPort];
+
+		link = RWORD(PortP->PhbP->link);
+
+		for (port = 0; port < PORTS_PER_RTA; port++, PortN++) {
+			ushort		dest_port = port + 8;
+#if 0
+			uint		PktInt;
+#endif
+			WORD		*TxPktP;
+			PKT		*Pkt;
+
+			PortP = p->RIOPortp[PortN];
+
+			rio_spin_lock_irqsave(&PortP->portSem, flags);
+			/*
+			** If RTA is not powered on, the tx packets will be
+			** unset, so go no further.
+			*/
+			if (PortP->TxStart == 0) {
+					rio_dprint(RIO_DEBUG_ROUTE, ("Tx pkts not set up yet\n"));
+					break;
+			}
+
+			/*
+			** For the second slot of a 16 port RTA, the driver needs to
+			** sort out the phb to port mappings. The dest_unit for this
+			** group of 8 phbs is set to the dest_unit of the accompanying
+			** 8 port block. The dest_port of the second unit is set to
+			** be in the range 8-15 (i.e. 8 is added). Thus, for a 16 port
+			** RTA with IDs 5 and 6, traffic bound for port 6 of unit 6
+			** (being the second map ID) will be sent to dest_unit 5, port
+			** 14. When this RTA is deleted, dest_unit for ID 6 will be
+			** restored, and the dest_port will be reduced by 8.
+			** Transmit packets also have a destination field which needs
+			** adjusting in the same manner.
+			** Note that the unit/port bytes in 'dest' are swapped.
+			** We also need to adjust the phb and rup link numbers for the
+			** second block of 8 ttys.
+			*/
+			for (TxPktP = PortP->TxStart; TxPktP <= PortP->TxEnd; TxPktP++) {
+				/*
+				** *TxPktP is the pointer to the transmit packet on the host
+				** card. This needs to be translated into a 32 bit pointer
+				** so it can be accessed from the driver.
+				*/
+				Pkt = (PKT *) RIO_PTR(HostP->Caddr,RINDW(TxPktP));
+
+				/*
+				** If the packet is used, reset it.
+				*/
+				Pkt = (PKT *)((uint)Pkt & ~PKT_IN_USE);
+				WBYTE(Pkt->dest_unit, dest_unit);
+				WBYTE(Pkt->dest_port, dest_port);
+			}
+			rio_dprint(RIO_DEBUG_ROUTE, ("phb dest: Old %x:%x New %x:%x\n",
+					RWORD(PortP->PhbP->destination) & 0xff,
+					(RWORD(PortP->PhbP->destination) >> 8) & 0xff,
+					dest_unit, dest_port));
+			WWORD(PortP->PhbP->destination, dest_unit + (dest_port << 8));
+			WWORD(PortP->PhbP->link, link);
+
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		}
+		/*
+		** Now make sure the range of ports to be serviced includes
+		** the 2nd 8 on this 16 port RTA.
+		*/
+		if (link > 3) return;
+		if (((unit * 8) + 7) > RWORD(HostP->LinkStrP[link].last_port)) {
+			rio_dprint(RIO_DEBUG_ROUTE, ("last port on host link %d: %d\n", link, (unit * 8) + 7));
+			WWORD(HostP->LinkStrP[link].last_port, (unit * 8) + 7);
+		}
+	}
+}
+
+/*
+** Check to see if the new disconnection has isolated this unit.
+** If it has, then invalidate all its link information, and tell
+** the world about it. This is done to ensure that the configurator
+** only gets up-to-date information about what is going on.
+*/
+int
+RIOCheckIsolated(p, HostP, UnitId)
+struct rio_info *	p;
+struct Host *HostP;
+uint UnitId;
+{
+	unsigned long flags;
+	rio_spin_lock_irqsave(&HostP->HostLock, flags);
+
+#ifdef CHECK
+	CheckHostP( HostP );
+	CheckUnitId( UnitId );
+#endif
+	if ( RIOCheck( HostP, UnitId ) ) {
+		rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is NOT isolated\n",UnitId));
+		rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
+		return(0);
+	}
+
+	RIOIsolate(p, HostP, UnitId );
+	RIOSetChange(p);
+	rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
+	return 1;
+}
+
+/*
+** Invalidate all the link interconnectivity of this unit, and of
+** all the units attached to it. This will mean that the entire
+** subnet will re-introduce itself.
+*/
+int
+RIOIsolate(p, HostP, UnitId)
+struct rio_info *	p;
+struct Host *		HostP;
+uint UnitId; 
+{
+	uint link, unit;
+
+#ifdef CHECK
+	CheckHostP( HostP );
+	CheckUnitId( UnitId );
+#endif
+	UnitId--;		/* this trick relies on the Unit Id being UNSIGNED! */
+
+	if ( UnitId > MAX_RUP )		/* dontcha just lurv unsigned maths! */
+		return(0);
+
+	if ( HostP->Mapping[UnitId].Flags & BEEN_HERE )
+		return(0);
+
+	HostP->Mapping[UnitId].Flags |= BEEN_HERE;
+
+	if ( p->RIOPrintDisabled == DO_PRINT )
+		rio_dprint(RIO_DEBUG_ROUTE, ("RIOMesgIsolated %s",HostP->Mapping[UnitId].Name));
+
+	for ( link=0; link<LINKS_PER_UNIT; link++) {
+		unit = HostP->Mapping[UnitId].Topology[link].Unit;
+		HostP->Mapping[UnitId].Topology[link].Unit = ROUTE_DISCONNECT;
+		HostP->Mapping[UnitId].Topology[link].Link = NO_LINK;
+		RIOIsolate(p, HostP, unit );
+	}
+	HostP->Mapping[UnitId].Flags &= ~BEEN_HERE;
+	return 1;
+}
+
+int
+RIOCheck(HostP, UnitId)
+struct Host *HostP;
+uint UnitId;
+{
+  unsigned char link;
+
+#ifdef CHECK
+	CheckHostP( HostP );
+	CheckUnitId( UnitId );
+#endif
+/* 	rio_dprint(RIO_DEBUG_ROUTE, ("Check to see if unit %d has a route to the host\n",UnitId)); */
+	rio_dprint(RIO_DEBUG_ROUTE, ("RIOCheck : UnitID = %d\n",UnitId));
+
+	if ( UnitId == HOST_ID ) {
+		/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is NOT isolated - it IS the host!\n", UnitId)); */
+		return 1;
+	}
+
+	UnitId--;
+
+	if ( UnitId >= MAX_RUP ) {
+		/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d - ignored.\n", UnitId)); */
+		return 0;
+	}
+
+	for ( link=0; link<LINKS_PER_UNIT; link++ ) {
+		if ( HostP->Mapping[UnitId].Topology[link].Unit==HOST_ID ) {
+			/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is connected directly to host via link (%c).\n", 
+						UnitId, 'A'+link)); */
+			return 1;
+		}
+	}
+
+	if ( HostP->Mapping[UnitId].Flags & BEEN_HERE ) {
+		/* rio_dprint(RIO_DEBUG_ROUTE, ("Been to Unit %d before - ignoring\n", UnitId)); */
+		return 0;
+	}
+
+	HostP->Mapping[UnitId].Flags |= BEEN_HERE;
+
+	for ( link=0; link < LINKS_PER_UNIT; link++ ) {
+		/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d check link (%c)\n", UnitId,'A'+link)); */
+		if ( RIOCheck( HostP, HostP->Mapping[UnitId].Topology[link].Unit ) ) {
+			/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is connected to something that knows the host via link (%c)\n", UnitId,link+'A')); */
+			HostP->Mapping[UnitId].Flags &= ~BEEN_HERE;
+			return 1;
+		}
+	}
+
+	HostP->Mapping[UnitId].Flags &= ~BEEN_HERE;
+
+	/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d DOESNT KNOW THE HOST!\n", UnitId)); */
+	
+	return 0;
+}
+
+/*
+** Returns the type of unit (host, 16/8 port RTA)
+*/
+
+uint
+GetUnitType(Uniq)
+uint Uniq;
+{
+	switch ( (Uniq >> 28) & 0xf)
+	{
+		case RIO_AT:
+		case RIO_MCA:
+		case RIO_EISA:
+		case RIO_PCI:
+			rio_dprint(RIO_DEBUG_ROUTE, ("Unit type: Host\n"));
+			return(TYPE_HOST);
+		case RIO_RTA_16:
+			rio_dprint(RIO_DEBUG_ROUTE, ("Unit type: 16 port RTA\n"));
+			return(TYPE_RTA16);
+		case RIO_RTA:
+			rio_dprint(RIO_DEBUG_ROUTE, ("Unit type: 8 port RTA\n"));
+			return(TYPE_RTA8);
+		default :
+			rio_dprint(RIO_DEBUG_ROUTE, ("Unit type: Unrecognised\n"));
+			return(99);
+	}
+}
+
+int
+RIOSetChange(p)
+struct rio_info *	p;
+{
+	if ( p->RIOQuickCheck != NOT_CHANGED )
+		return(0);
+	p->RIOQuickCheck = CHANGED;
+	if ( p->RIOSignalProcess ) {
+		rio_dprint(RIO_DEBUG_ROUTE, ("Send SIG-HUP"));
+		/*
+		psignal( RIOSignalProcess, SIGHUP );
+		*/
+	}
+	return(0);
+}
+
+void
+RIOConCon(p, HostP, FromId, FromLink, ToId, ToLink, Change)
+struct rio_info *	p;
+struct Host *HostP;
+uint FromId;
+uint FromLink;
+uint ToId;
+uint ToLink;
+int Change; 
+{
+    char *FromName;
+    char *FromType;
+    char *ToName;
+    char *ToType;
+    unsigned int tp;
+
+/*
+** 15.10.1998 ARG - ESIL 0759
+** (Part) fix for port being trashed when opened whilst RTA "disconnected"
+**
+** What's this doing in here anyway ?
+** It was causing the port to be 'unmapped' if opened whilst RTA "disconnected"
+**
+** 09.12.1998 ARG - ESIL 0776 - part fix
+** Okay, We've found out what this was all about now !
+** Someone had botched this to use RIOHalted to indicated the number of RTAs
+** 'disconnected'. The value in RIOHalted was then being used in the
+** 'RIO_QUICK_CHECK' ioctl. A none zero value indicating that a least one RTA
+** is 'disconnected'. The change was put in to satisfy a customer's needs.
+** Having taken this bit of code out 'RIO_QUICK_CHECK' now no longer works for
+** the customer.
+**
+    if (Change == CONNECT) {
+		if (p->RIOHalted) p->RIOHalted --;
+	 }
+	 else {
+		p->RIOHalted ++;
+	 }
+**
+** So - we need to implement it slightly differently - a new member of the
+** rio_info struct - RIORtaDisCons (RIO RTA connections) keeps track of RTA
+** connections and disconnections. 
+*/
+    if (Change == CONNECT) {
+		if (p->RIORtaDisCons) p->RIORtaDisCons--;
+	 }
+	 else {
+		p->RIORtaDisCons++;
+	 }
+
+    if ( p->RIOPrintDisabled == DONT_PRINT )
+		return;
+
+    if ( FromId > ToId ) {
+		tp = FromId;
+		FromId = ToId;
+		ToId = tp;
+		tp = FromLink;
+		FromLink = ToLink;
+		ToLink = tp;
+    }
+
+    FromName = FromId ? HostP->Mapping[FromId-1].Name : HostP->Name;
+    FromType = FromId ? "RTA" : "HOST";
+    ToName = ToId ? HostP->Mapping[ToId-1].Name : HostP->Name;
+    ToType = ToId ? "RTA" : "HOST";
+
+    rio_dprint(RIO_DEBUG_ROUTE, ("Link between %s '%s' (%c) and %s '%s' (%c) %s.\n",
+			    FromType, FromName, 'A'+FromLink,
+			    ToType,   ToName,   'A'+ToLink,
+			    (Change==CONNECT) ? "established" : "disconnected"));
+    cprintf("Link between %s '%s' (%c) and %s '%s' (%c) %s.\n",
+			    FromType, FromName, 'A'+FromLink,
+			    ToType,   ToName,   'A'+ToLink,
+			    (Change==CONNECT) ? "established" : "disconnected");
+}
+
+/*
+** RIORemoveFromSavedTable :
+**
+** Delete and RTA entry from the saved table given to us
+** by the configuration program.
+*/
+int
+RIORemoveFromSavedTable(struct rio_info *p, struct Map *pMap)
+{
+    int		entry;
+
+    /*
+    ** We loop for all entries even after finding an entry and
+    ** zeroing it because we may have two entries to delete if
+    ** its a 16 port RTA.
+    */
+    for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++)
+    {
+	if (p->RIOSavedTable[entry].RtaUniqueNum == pMap->RtaUniqueNum)
+	{
+	    bzero((caddr_t)&p->RIOSavedTable[entry], sizeof(struct Map));
+	}
+    }
+    return 0;
+}
+
+
+/*
+** RIOCheckDisconnected :
+**
+** Scan the unit links to and return zero if the unit is completely
+** disconnected.
+*/
+int
+RIOFreeDisconnected(struct rio_info *p, struct Host *HostP, int unit)
+{
+    int		link;
+
+
+    rio_dprint(RIO_DEBUG_ROUTE, ("RIOFreeDisconnect unit %d\n",unit));
+    /*
+    ** If the slot is tentative and does not belong to the
+    ** second half of a 16 port RTA then scan to see if
+    ** is disconnected.
+    */
+    for (link = 0; link < LINKS_PER_UNIT; link++)
+    {
+	if (HostP->Mapping[unit].Topology[link].Unit != ROUTE_DISCONNECT)
+	    break;
+    }
+
+    /*
+    ** If not all links are disconnected then we can forget about it.
+    */
+    if (link < LINKS_PER_UNIT)
+	    return 1;
+
+#if NEED_TO_FIX_THIS
+    /* Ok so all the links are disconnected. But we may have only just
+    ** made this slot tentative and not yet received a topology update.
+    ** Lets check how long ago we made it tentative.
+    */
+    rio_dprint(RIO_DEBUG_ROUTE, ("Just about to check LBOLT on entry %d\n",unit));
+    if (drv_getparm(LBOLT, (ulong_t *) &current_time))
+        rio_dprint(RIO_DEBUG_ROUTE, ("drv_getparm(LBOLT,....) Failed.\n"));
+
+    elapse_time = current_time - TentTime[unit];
+    rio_dprint(RIO_DEBUG_ROUTE, ("elapse %d = current %d - tent %d (%d usec)\n",
+        elapse_time, current_time, TentTime[unit],drv_hztousec(elapse_time)));
+    if (drv_hztousec(elapse_time) < WAIT_TO_FINISH)
+    {
+        rio_dprint(RIO_DEBUG_ROUTE, ("Skipping slot %d, not timed out yet %d\n"
+            ,unit,drv_hztousec(elapse_time)));
+        return 1;
+    }
+#endif
+
+    /*
+    ** We have found an usable slot.
+    ** If it is half of a 16 port RTA then delete the other half.
+    */
+    if (HostP->Mapping[unit].ID2 != 0)
+    {
+	int nOther = (HostP->Mapping[unit].ID2) -1;
+
+	rio_dprint(RIO_DEBUG_ROUTE, ("RioFreedis second slot %d.\n",nOther));
+	bzero((caddr_t)&HostP->Mapping[nOther], sizeof(struct Map));
+    }
+    RIORemoveFromSavedTable(p, &HostP->Mapping[unit]);
+
+    return 0;
+}
+
+
+/*
+** RIOFindFreeID :
+**
+** This function scans the given host table for either one
+** or two free unit ID's.
+*/
+int
+RIOFindFreeID(struct rio_info *p, struct Host *HostP, uint *pID1, uint *pID2)
+{
+    int unit,tempID;
+
+    /*
+    ** Initialise the ID's to MAX_RUP.
+    ** We do this to make the loop for setting the ID's as simple as
+    ** possible.
+    */
+    *pID1 = MAX_RUP;
+    if (pID2 != NULL)
+	*pID2 = MAX_RUP;
+
+    /*
+    ** Scan all entries of the host mapping table for free slots.
+    ** We scan for free slots first and then if that is not successful
+    ** we start all over again looking for tentative slots we can re-use.
+    */
+    for (unit = 0; unit < MAX_RUP; unit++)
+    {
+	rio_dprint(RIO_DEBUG_ROUTE, ("Scanning unit %d\n",unit));
+	/*
+	** If the flags are zero then the slot is empty.
+	*/
+	if (HostP->Mapping[unit].Flags == 0)
+	{
+	    rio_dprint(RIO_DEBUG_ROUTE, ("      This slot is empty.\n"));
+	    /*
+	    ** If we haven't allocated the first ID then do it now.
+	    */
+	    if (*pID1 == MAX_RUP)
+	    {
+		rio_dprint(RIO_DEBUG_ROUTE, ("Make tentative entry for first unit %d\n", unit));
+		*pID1 = unit;
+
+		/*
+		** If the second ID is not needed then we can return
+		** now.
+		*/
+		if (pID2 == NULL)
+		    return 0;
+	    }
+	    else
+	    {
+		/*
+		** Allocate the second slot and return.
+		*/
+		rio_dprint(RIO_DEBUG_ROUTE, ("Make tentative entry for second unit %d\n", unit));
+		*pID2 = unit;
+		return 0;
+	    }
+	}
+    }
+
+    /*
+    ** If we manage to come out of the free slot loop then we
+    ** need to start all over again looking for tentative slots
+    ** that we can re-use.
+    */
+    rio_dprint(RIO_DEBUG_ROUTE, ("Starting to scan for tentative slots\n"));
+    for (unit = 0; unit < MAX_RUP; unit++)
+    {
+	if (((HostP->Mapping[unit].Flags & SLOT_TENTATIVE) ||
+	                       (HostP->Mapping[unit].Flags == 0))  && ! 
+	   (HostP->Mapping[unit].Flags & RTA16_SECOND_SLOT ))
+	{
+	    rio_dprint(RIO_DEBUG_ROUTE, ("    Slot %d looks promising.\n",unit));
+
+	    if(unit == *pID1)
+	    {
+	    	rio_dprint(RIO_DEBUG_ROUTE, ("    No it isn't, its the 1st half\n"));
+		continue;
+	    }
+
+	    /*
+	    ** Slot is Tentative or Empty, but not a tentative second 
+	    ** slot of a 16 porter.
+	    ** Attempt to free up this slot (and its parnter if
+	    ** it is a 16 port slot. The second slot will become
+	    ** empty after a call to RIOFreeDisconnected so thats why
+	    ** we look for empty slots above  as well).
+	    */
+	    if (HostP->Mapping[unit].Flags != 0) 
+	    	if (RIOFreeDisconnected(p, HostP, unit) != 0)
+			    continue;
+	    /*
+	    ** If we haven't allocated the first ID then do it now.
+	    */
+	    if (*pID1 == MAX_RUP)
+	    {
+		rio_dprint(RIO_DEBUG_ROUTE, ("Grab tentative entry for first unit %d\n", unit));
+		*pID1 = unit;
+
+		/*
+		** Clear out this slot now that we intend to use it.
+		*/
+		bzero(&HostP->Mapping[unit], sizeof(struct Map));
+
+		/*
+		** If the second ID is not needed then we can return
+		** now.
+		*/
+		if (pID2 == NULL)
+		    return 0;
+	    }
+	    else
+	    {
+		/*
+		** Allocate the second slot and return.
+		*/
+		rio_dprint(RIO_DEBUG_ROUTE, ("Grab tentative/empty  entry for second unit %d\n",
+		      unit));
+		*pID2 = unit;
+
+		/*
+		** Clear out this slot now that we intend to use it.
+		*/
+		bzero(&HostP->Mapping[unit], sizeof(struct Map));
+
+		/* At this point under the right(wrong?) conditions
+		** we may have a first unit ID being higher than the
+		** second unit ID. This is a bad idea if we are about
+		** to fill the slots with a 16 port RTA.
+		** Better check and swap them over.
+		*/
+
+		if (*pID1 > *pID2)
+		{
+			rio_dprint(RIO_DEBUG_ROUTE, ("Swapping IDS %d %d\n",*pID1,*pID2));
+			tempID = *pID1;
+			*pID1 = *pID2;
+			*pID2 = tempID;
+		}
+		return 0;
+	    }
+	}
+    }
+
+    /*
+    ** If we manage to get to the end of the second loop then we
+    ** can give up and return a failure.
+    */
+    return 1;
+}
+
+
+/*
+** The link switch scenario.
+**
+** Rta Wun (A) is connected to Tuw (A).
+** The tables are all up to date, and the system is OK.
+**
+** If Wun (A) is now moved to Wun (B) before Wun (A) can
+** become disconnected, then the follow happens:
+**
+** Tuw (A) spots the change of unit:link at the other end
+** of its link and Tuw sends a topology packet reflecting
+** the change: Tuw (A) now disconnected from Wun (A), and
+** this is closely followed by a packet indicating that 
+** Tuw (A) is now connected to Wun (B).
+**
+** Wun (B) will spot that it has now become connected, and
+** Wun will send a topology packet, which indicates that
+** both Wun (A) and Wun (B) is connected to Tuw (A).
+**
+** Eventually Wun (A) realises that it is now disconnected
+** and Wun will send out a topology packet indicating that
+** Wun (A) is now disconnected.
+*/
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/riospace.h linux.15p9/drivers/char/rio/riospace.h
--- linux.vanilla/drivers/char/rio/riospace.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/riospace.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,161 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: riospace.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:13
+**	Retrieved	: 11/6/98 11:34:22
+**
+**  ident @(#)riospace.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_riospace_h__
+#define __rio_riospace_h__
+
+#ifdef SCCS_LABELS
+static char *_riospace_h_sccs_ = "@(#)riospace.h	1.2";
+#endif
+
+#define	RIO_LOCATOR_LEN	16
+#define	MAX_RIO_BOARDS	4
+
+/*
+** DONT change this file. At all. Unless you can rebuild the entire
+** device driver, which you probably can't, then the rest of the
+** driver won't see any changes you make here. So don't make any.
+** In particular, it won't be able to see changes to RIO_SLOTS
+*/
+
+struct Conf
+{
+	char         Locator[24];
+	unsigned int StartupTime;
+	unsigned int SlowCook;
+	unsigned int IntrPollTime;
+	unsigned int BreakInterval;
+	unsigned int Timer;
+	unsigned int RtaLoadBase;
+	unsigned int HostLoadBase;
+	unsigned int XpHz;
+	unsigned int XpCps;
+	char         *XpOn;
+	char         *XpOff;
+	unsigned int MaxXpCps;
+	unsigned int MinXpCps;
+	unsigned int SpinCmds;
+	unsigned int FirstAddr;
+	unsigned int LastAddr;
+	unsigned int BufferSize;
+	unsigned int LowWater;
+	unsigned int LineLength;
+	unsigned int CmdTime;
+};
+
+/*
+**	Board types - these MUST correspond to product codes!
+*/ 
+#define	RIO_EMPTY	0x0
+#define	RIO_EISA	0x3
+#define	RIO_RTA_16	0x9
+#define	RIO_AT		0xA
+#define	RIO_MCA		0xB
+#define	RIO_PCI		0xD
+#define	RIO_RTA		0xE
+
+/*
+**	Board data structure. This is used for configuration info
+*/
+struct	Brd
+{
+    unsigned char Type;	/* RIO_EISA, RIO_MCA, RIO_AT, RIO_EMPTY... */
+    unsigned char Ivec;	/* POLLED or ivec number */
+    unsigned char Mode;	/* Control stuff, see below */
+};
+
+struct	Board
+{
+    char       Locator[RIO_LOCATOR_LEN];
+    int        NumSlots;
+    struct Brd Boards[MAX_RIO_BOARDS];
+};
+
+#define	BOOT_FROM_LINK		0x00
+#define	BOOT_FROM_RAM		0x01
+#define	EXTERNAL_BUS_OFF	0x00
+#define	EXTERNAL_BUS_ON		0x02
+#define	INTERRUPT_DISABLE	0x00
+#define	INTERRUPT_ENABLE	0x04
+#define	BYTE_OPERATION		0x00
+#define	WORD_OPERATION		0x08
+#define	POLLED			INTERRUPT_DISABLE
+#define	IRQ_15			(0x00 | INTERRUPT_ENABLE)
+#define	IRQ_12			(0x10 | INTERRUPT_ENABLE)
+#define	IRQ_11			(0x20 | INTERRUPT_ENABLE)
+#define	IRQ_9			(0x30 | INTERRUPT_ENABLE)
+#define	SLOW_LINKS		0x00
+#define	FAST_LINKS		0x40
+#define	SLOW_AT_BUS		0x00
+#define	FAST_AT_BUS		0x80
+#define	SLOW_PCI_TP		0x00
+#define	FAST_PCI_TP		0x80
+/*
+**	Debug levels
+*/
+#define	DBG_NONE	0x00000000
+
+#define	DBG_INIT	0x00000001
+#define	DBG_OPEN	0x00000002
+#define	DBG_CLOSE	0x00000004
+#define	DBG_IOCTL	0x00000008
+
+#define	DBG_READ	0x00000010
+#define	DBG_WRITE	0x00000020
+#define	DBG_INTR	0x00000040
+#define	DBG_PROC	0x00000080
+
+#define	DBG_PARAM	0x00000100
+#define	DBG_CMD		0x00000200
+#define	DBG_XPRINT	0x00000400
+#define	DBG_POLL	0x00000800
+
+#define	DBG_DAEMON	0x00001000
+#define	DBG_FAIL	0x00002000
+#define DBG_MODEM	0x00004000
+#define	DBG_LIST	0x00008000
+
+#define	DBG_ROUTE	0x00010000
+#define DBG_UTIL        0x00020000
+#define DBG_BOOT	0x00040000
+#define DBG_BUFFER	0x00080000
+
+#define	DBG_MON		0x00100000
+#define DBG_SPECIAL     0x00200000
+#define	DBG_VPIX	0x00400000
+#define	DBG_FLUSH	0x00800000
+
+#define	DBG_QENABLE	0x01000000
+
+#define	DBG_ALWAYS	0x80000000
+
+#endif /* __rio_riospace_h__ */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/riotable.c linux.15p9/drivers/char/rio/riotable.c
--- linux.vanilla/drivers/char/rio/riotable.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/riotable.c	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,1058 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: riotable.c
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 10:33:47
+**	Retrieved	: 11/6/98 10:33:50
+**
+**  ident @(#)riotable.c	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+#ifdef SCCS_LABELS
+static char *_riotable_c_sccs_ = "@(#)riotable.c	1.2";
+#endif
+
+#define __NO_VERSION__
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/malloc.h>
+#include <linux/errno.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/string.h>
+#include <asm/semaphore.h>
+#include <asm/uaccess.h>
+
+#include <linux/termios.h>
+#include <linux/serial.h>
+
+#include <linux/compatmac.h>
+#include <linux/generic_serial.h>
+
+
+#include "linux_compat.h"
+#include "rio_linux.h"
+#include "typdef.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "top.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "riotypes.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "error.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+#include "control.h"
+#include "cirrus.h"
+#include "rioioctl.h"
+#include "param.h"
+#include "list.h"
+#include "sam.h"
+#include "protsts.h"
+
+/*
+** A configuration table has been loaded. It is now up to us
+** to sort it out and use the information contained therein.
+*/
+int
+RIONewTable(p)
+struct rio_info *	p;
+{
+	int Host, Host1, Host2, NameIsUnique, Entry, SubEnt;
+	struct Map *MapP;
+	struct Map *HostMapP;
+	struct Host *HostP;
+
+	char *cptr;
+
+	/*
+	** We have been sent a new table to install. We need to break
+	** it down into little bits and spread it around a bit to see
+	** what we have got.
+	*/
+	/*
+	** Things to check:
+	** (things marked 'xx' aren't checked any more!)
+	** (1)	That there are no booted Hosts/RTAs out there.
+	** (2)	That the names are properly formed
+	** (3)	That blank entries really are.
+	** xx (4)	That hosts mentioned in the table actually exist. xx
+	** (5)	That the IDs are unique (per host).
+	** (6)	That host IDs are zero
+	** (7)	That port numbers are valid
+	** (8)	That port numbers aren't duplicated
+	** (9)	That names aren't duplicated
+	** xx (10) That hosts that actually exist are mentioned in the table. xx
+	*/
+	rio_dprint(RIO_DEBUG_TABLE, ("RIONewTable: entering(1)\n")); 
+	if ( p->RIOSystemUp ) {		/* (1) */
+		p->RIOError.Error = HOST_HAS_ALREADY_BEEN_BOOTED;
+		return EBUSY;
+	}
+
+	p->RIOError.Error = NOTHING_WRONG_AT_ALL;
+	p->RIOError.Entry = -1;
+	p->RIOError.Other = -1;
+
+	for ( Entry=0; Entry<TOTAL_MAP_ENTRIES; Entry++ ) {
+		MapP = &p->RIOConnectTable[Entry];
+		if ((MapP->Flags & RTA16_SECOND_SLOT) == 0) {
+			rio_dprint(RIO_DEBUG_TABLE, ("RIONewTable: entering(2)\n"));
+			cptr = MapP->Name;		/* (2) */
+			cptr[MAX_NAME_LEN-1]='\0';
+			if ( cptr[0]=='\0' ) {
+				bcopy(MapP->RtaUniqueNum?"RTA	NN":"HOST NN",MapP->Name,8);
+				MapP->Name[5] = '0'+Entry/10;
+				MapP->Name[6] = '0'+Entry%10;
+			}
+			while ( *cptr ) {
+				if ( *cptr<' ' || *cptr>'~' ) {
+					p->RIOError.Error = BAD_CHARACTER_IN_NAME;
+					p->RIOError.Entry = Entry;
+					return ENXIO;
+				}
+				cptr++;
+			}
+		}
+
+		/*
+		** If the entry saved was a tentative entry then just forget
+		** about it.
+		*/
+		if ( MapP->Flags & SLOT_TENTATIVE ) {
+			MapP->HostUniqueNum = 0;
+			MapP->RtaUniqueNum = 0;
+			continue;
+		}
+
+		rio_dprint(RIO_DEBUG_TABLE, ("RIONewTable: entering(3)\n"));
+		if ( !MapP->RtaUniqueNum && !MapP->HostUniqueNum ) { /* (3) */
+			if ( MapP->ID || MapP->SysPort || MapP->Flags ) {
+				rio_dprint(RIO_DEBUG_TABLE, ("%s pretending to be empty but isn't\n",MapP->Name));
+				p->RIOError.Error = TABLE_ENTRY_ISNT_PROPERLY_NULL;
+				p->RIOError.Entry = Entry;
+				return ENXIO;
+			}
+			rio_dprint(RIO_DEBUG_TABLE, ("!RIO: Daemon: test (3) passes\n"));
+			continue;
+		}
+
+		rio_dprint(RIO_DEBUG_TABLE, ("RIONewTable: entering(4)\n"));
+		for ( Host=0; Host<p->RIONumHosts; Host++ ) { /* (4) */
+			if ( p->RIOHosts[Host].UniqueNum==MapP->HostUniqueNum ) {
+				HostP = &p->RIOHosts[Host];
+				/*
+				** having done the lookup, we don't really want to do
+				** it again, so hang the host number in a safe place
+				*/
+				MapP->Topology[0].Unit = Host;
+				break;
+			}
+		}
+
+		if ( Host >= p->RIONumHosts ) {
+			rio_dprint(RIO_DEBUG_TABLE, ("RTA %s has unknown host unique number 0x%x\n",
+									MapP->Name,MapP->HostUniqueNum));
+			MapP->HostUniqueNum = 0;
+			/* MapP->RtaUniqueNum	= 0; */
+			/* MapP->ID			= 0; */
+			/* MapP->Flags		 = 0; */
+			/* MapP->SysPort		 = 0; */
+			/* MapP->Name[0]		 = 0; */
+			continue;
+		}
+
+		rio_dprint(RIO_DEBUG_TABLE, ("RIONewTable: entering(5)\n")); 
+		if ( MapP->RtaUniqueNum ) { /* (5) */
+			if ( !MapP->ID ) {
+				rio_dprint(RIO_DEBUG_TABLE, ("RIO: RTA %s has been allocated an ID of zero!\n",
+							MapP->Name));
+				p->RIOError.Error		 = ZERO_RTA_ID;
+				p->RIOError.Entry = Entry;
+				return ENXIO;
+			}
+			if ( MapP->ID > MAX_RUP ) {
+				rio_dprint(RIO_DEBUG_TABLE, ("RIO: RTA %s has been allocated an illegal ID %d\n",
+							MapP->Name, MapP->ID));
+				p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
+				p->RIOError.Entry = Entry;
+				return ENXIO;
+			}
+			for ( SubEnt=0; SubEnt<Entry; SubEnt++ ) {
+				if ( MapP->HostUniqueNum == 
+						p->RIOConnectTable[SubEnt].HostUniqueNum && 
+						MapP->ID == p->RIOConnectTable[SubEnt].ID ) {
+					rio_dprint(RIO_DEBUG_TABLE, ("Dupl. ID number allocated to RTA %s and RTA %s\n",
+							MapP->Name,p->RIOConnectTable[SubEnt].Name));
+					p->RIOError.Error = DUPLICATED_RTA_ID;
+					p->RIOError.Entry = Entry;
+					p->RIOError.Other = SubEnt;
+					return ENXIO;
+				}
+				/*
+				** If the RtaUniqueNum is the same, it may be looking at both
+				** entries for a 16 port RTA, so check the ids
+				*/
+				if ((MapP->RtaUniqueNum == 
+						p->RIOConnectTable[SubEnt].RtaUniqueNum)
+				 		&& (MapP->ID2 != p->RIOConnectTable[SubEnt].ID)) {
+					rio_dprint(RIO_DEBUG_TABLE, ("RTA %s has duplicate unique number\n",MapP->Name));
+					rio_dprint(RIO_DEBUG_TABLE, ("RTA %s has duplicate unique number\n",
+										p->RIOConnectTable[SubEnt].Name));
+					p->RIOError.Error = DUPLICATE_UNIQUE_NUMBER;
+					p->RIOError.Entry = Entry;
+					p->RIOError.Other = SubEnt;
+					return ENXIO;
+				}
+			}
+			rio_dprint(RIO_DEBUG_TABLE, ("RIONewTable: entering(7a)\n")); 
+			/* (7a) */
+			if ((MapP->SysPort != NO_PORT)&&(MapP->SysPort % PORTS_PER_RTA)) {
+				rio_dprint(RIO_DEBUG_TABLE, ("TTY Port number %d-RTA %s is not a multiple of %d!\n",
+					(int)MapP->SysPort,MapP->Name,PORTS_PER_RTA));
+				p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
+				p->RIOError.Entry = Entry;
+				return ENXIO;
+			}
+			rio_dprint(RIO_DEBUG_TABLE, ("RIONewTable: entering(7b)\n")); 
+			/* (7b) */
+			if ((MapP->SysPort != NO_PORT)&&(MapP->SysPort >= RIO_PORTS)) {
+				rio_dprint(RIO_DEBUG_TABLE, ("TTY Port number %d for RTA %s is too big\n",
+							(int)MapP->SysPort,MapP->Name));
+				p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
+				p->RIOError.Entry = Entry;
+				return ENXIO;
+			}
+			for ( SubEnt=0; SubEnt<Entry; SubEnt++ ) {
+				if ( p->RIOConnectTable[SubEnt].Flags & RTA16_SECOND_SLOT )
+						continue;
+				if ( p->RIOConnectTable[SubEnt].RtaUniqueNum ) {
+					rio_dprint(RIO_DEBUG_TABLE, ("RIONewTable: entering(8)\n")); 
+					/* (8) */
+					if ( (MapP->SysPort != NO_PORT) && (MapP->SysPort == 
+									p->RIOConnectTable[SubEnt].SysPort) ) {
+						rio_dprint(RIO_DEBUG_TABLE, ("RTA %s:same TTY port # as RTA %s (%d)\n",
+							MapP->Name, p->RIOConnectTable[SubEnt].Name,
+							(int)MapP->SysPort));
+						p->RIOError.Error = TTY_NUMBER_IN_USE;
+						p->RIOError.Entry = Entry;
+						p->RIOError.Other = SubEnt;
+						return ENXIO;
+					}
+					rio_dprint(RIO_DEBUG_TABLE, ("RIONewTable: entering(9)\n")); 
+					if (RIOStrCmp(MapP->Name,
+							p->RIOConnectTable[SubEnt].Name)==0 && !(MapP->Flags & RTA16_SECOND_SLOT)) { /* (9) */
+						rio_dprint(RIO_DEBUG_TABLE, ("RTA name %s used twice\n",MapP->Name));
+						p->RIOError.Error = NAME_USED_TWICE;
+						p->RIOError.Entry = Entry;
+						p->RIOError.Other = SubEnt;
+						return ENXIO;
+					}
+				}
+			}
+		}
+		else { /* (6) */
+			rio_dprint(RIO_DEBUG_TABLE, ("RIONewTable: entering(6)\n")); 
+			if ( MapP->ID ) {
+				rio_dprint(RIO_DEBUG_TABLE, ("RIO:HOST %s has been allocated ID that isn't zero!\n",
+					MapP->Name));
+				p->RIOError.Error = HOST_ID_NOT_ZERO;
+				p->RIOError.Entry = Entry;
+				return ENXIO;
+			}
+			if ( MapP->SysPort != NO_PORT ) {
+				rio_dprint(RIO_DEBUG_TABLE, ("RIO: HOST %s has been allocated port numbers!\n",
+					MapP->Name));
+				p->RIOError.Error = HOST_SYSPORT_BAD;
+				p->RIOError.Entry = Entry;
+				return ENXIO;
+			}
+		}
+	}
+
+	/*
+	** wow! if we get here then its a goody!
+	*/
+
+	/*
+	** Zero the (old) entries for each host...
+	*/
+	for ( Host=0; Host<RIO_HOSTS; Host++ ) {
+		for ( Entry=0; Entry<MAX_RUP; Entry++ ) {
+			bzero((caddr_t)&p->RIOHosts[Host].Mapping[Entry], 
+											sizeof(struct Map));
+		}
+		bzero((caddr_t)&p->RIOHosts[Host].Name[0],
+								sizeof(p->RIOHosts[Host].Name) );
+	}
+
+	/*
+	** Copy in the new table entries
+	*/
+	for ( Entry=0; Entry< TOTAL_MAP_ENTRIES; Entry++ ) {
+		rio_dprint(RIO_DEBUG_TABLE, ("RIONewTable: Copy table for Host entry %d\n", Entry));
+		MapP = &p->RIOConnectTable[Entry];
+
+		/*
+		** Now, if it is an empty slot ignore it!
+		*/
+		if ( MapP->HostUniqueNum==0 )
+			continue;
+
+		/*
+		** we saved the host number earlier, so grab it back
+		*/
+		HostP = &p->RIOHosts[MapP->Topology[0].Unit];
+
+		/*
+		** If it is a host, then we only need to fill in the name field.
+		*/
+		if ( MapP->ID==0 ) {
+			rio_dprint(RIO_DEBUG_TABLE, ("Host entry found. Name %s\n",MapP->Name));
+			bcopy(MapP->Name,HostP->Name,MAX_NAME_LEN);
+			continue;
+		}
+
+		/*
+		** Its an RTA entry, so fill in the host mapping entries for it
+		** and the port mapping entries. Notice that entry zero is for
+		** ID one.
+		*/
+		HostMapP = &HostP->Mapping[MapP->ID-1];
+
+		if (MapP->Flags & SLOT_IN_USE) {
+			rio_dprint(RIO_DEBUG_TABLE, ("Rta entry found. Name %s\n",MapP->Name));
+			/*
+			** structure assign, then sort out the bits we shouldn't have done
+			*/
+			*HostMapP = *MapP;
+
+			HostMapP->Flags = SLOT_IN_USE;
+			if (MapP->Flags & RTA16_SECOND_SLOT)
+				HostMapP->Flags |= RTA16_SECOND_SLOT;
+
+			RIOReMapPorts(p, HostP, HostMapP );
+		}
+		else {
+			rio_dprint(RIO_DEBUG_TABLE, ("TENTATIVE Rta entry found. Name %s\n",MapP->Name));
+		}
+	}
+
+	for ( Entry=0; Entry< TOTAL_MAP_ENTRIES; Entry++ ) {
+		p->RIOSavedTable[Entry] = p->RIOConnectTable[Entry];
+	}
+
+	for ( Host=0; Host<p->RIONumHosts; Host++ ) {
+		for ( SubEnt=0; SubEnt<LINKS_PER_UNIT; SubEnt++ ) {
+			p->RIOHosts[Host].Topology[SubEnt].Unit = ROUTE_DISCONNECT;
+			p->RIOHosts[Host].Topology[SubEnt].Link = NO_LINK;
+		}
+		for ( Entry=0; Entry<MAX_RUP; Entry++ ) {
+			for ( SubEnt=0; SubEnt<LINKS_PER_UNIT; SubEnt++ ) {
+				p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Unit = 
+								ROUTE_DISCONNECT;
+				p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Link = 
+								NO_LINK;
+			}
+		}
+		if ( !p->RIOHosts[Host].Name[0] ) {
+			bcopy("HOST 1",p->RIOHosts[Host].Name,7);
+			p->RIOHosts[Host].Name[5] += Host;
+		}
+		/*
+		** Check that default name assigned is unique.
+		*/
+		Host1 = Host;
+		NameIsUnique = 0;
+		while (!NameIsUnique) {
+			NameIsUnique = 1;
+			for ( Host2=0; Host2<p->RIONumHosts; Host2++ ) {
+				if (Host2 == Host)
+					continue;
+				if (RIOStrCmp(p->RIOHosts[Host].Name, p->RIOHosts[Host2].Name)
+									 == 0) {
+					NameIsUnique = 0;
+					Host1++;
+					if (Host1 >= p->RIONumHosts)
+						Host1 = 0;
+					p->RIOHosts[Host].Name[5] = '1' + Host1;
+				}
+			}
+		}
+		/*
+		** Rename host if name already used.
+		*/
+		if (Host1 != Host)
+		{
+			rio_dprint(RIO_DEBUG_TABLE, ("Default name %s already used\n", p->RIOHosts[Host].Name));
+			bcopy("HOST 1",p->RIOHosts[Host].Name,7);
+			p->RIOHosts[Host].Name[5] += Host1;
+		}
+		rio_dprint(RIO_DEBUG_TABLE, ("Assigning default name %s\n", p->RIOHosts[Host].Name));
+	}
+	return 0;
+}
+
+/*
+** User process needs the config table - build it from first
+** principles.
+*/
+int
+RIOApel(p)
+struct rio_info *	p;
+{
+	int Host;
+	int link;
+	int Rup;
+	int Next = 0;
+	struct Map *MapP;
+	struct Host *HostP;
+	int oldspl;
+
+	disable(oldspl);		/* strange but true! */
+ 
+	rio_dprint(RIO_DEBUG_TABLE, ("Generating a table to return to config.rio\n"));
+
+	bzero((caddr_t)&p->RIOConnectTable[0], 
+					sizeof(struct Map) * TOTAL_MAP_ENTRIES );
+
+	for ( Host=0; Host<RIO_HOSTS; Host++ ) {
+		rio_dprint(RIO_DEBUG_TABLE, ("Processing host %d\n", Host));
+		HostP = &p->RIOHosts[Host];
+		MapP = &p->RIOConnectTable[Next++];
+		MapP->HostUniqueNum = HostP->UniqueNum;
+		if ( (HostP->Flags & RUN_STATE) != RC_RUNNING )
+			continue;
+		MapP->RtaUniqueNum = 0;
+		MapP->ID = 0;
+		MapP->Flags = SLOT_IN_USE;
+		MapP->SysPort = NO_PORT;
+		for ( link=0; link<LINKS_PER_UNIT; link++ )
+			MapP->Topology[link] = HostP->Topology[link];
+		bcopy(HostP->Name,MapP->Name,MAX_NAME_LEN);
+		for ( Rup=0; Rup<MAX_RUP; Rup++ ) {
+			if ( HostP->Mapping[Rup].Flags & (SLOT_IN_USE|SLOT_TENTATIVE) ) {
+				p->RIOConnectTable[Next] = HostP->Mapping[Rup];
+				if ( HostP->Mapping[Rup].Flags & SLOT_IN_USE)
+					p->RIOConnectTable[Next].Flags |= SLOT_IN_USE;
+				if ( HostP->Mapping[Rup].Flags & SLOT_TENTATIVE)
+					p->RIOConnectTable[Next].Flags |= SLOT_TENTATIVE;
+				if ( HostP->Mapping[Rup].Flags & RTA16_SECOND_SLOT )
+					p->RIOConnectTable[Next].Flags |= RTA16_SECOND_SLOT;
+				Next++;
+			}
+		}
+	}
+	restore(oldspl);
+	return 0;
+}
+
+/*
+** config.rio has taken a dislike to one of the gross maps entries.
+** if the entry is suitably inactive, then we can gob on it and remove
+** it from the table.
+*/
+int
+RIODeleteRta(p, MapP)
+struct rio_info *p;
+struct Map *MapP;
+{
+	int host, entry, port, link;
+	int SysPort;
+	struct Host *HostP;
+	struct Map *HostMapP;
+	struct Port *PortP;
+	int work_done = 0;
+	unsigned long flags;
+
+	rio_dprint(RIO_DEBUG_TABLE, ("Delete entry on host %x, rta %x\n",
+								MapP->HostUniqueNum,MapP->RtaUniqueNum));
+
+	for ( host=0; host < p->RIONumHosts; host++ ) {
+		HostP = &p->RIOHosts[host];
+
+		rio_spin_lock_irqsave( &HostP->HostLock, flags );
+
+		if ( (HostP->Flags & RUN_STATE) != RC_RUNNING ) {
+			rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
+			continue;
+		}
+
+		for ( entry=0; entry<MAX_RUP; entry++ ) {
+			if ( MapP->RtaUniqueNum == HostP->Mapping[entry].RtaUniqueNum ) {
+				HostMapP = &HostP->Mapping[entry];
+				rio_dprint(RIO_DEBUG_TABLE, ("Found entry offset %d on host %s\n", 
+						entry,HostP->Name));
+
+				/*
+				** Check all four links of the unit are disconnected
+				*/
+				for ( link=0; link< LINKS_PER_UNIT; link++ ) {
+					if ( HostMapP->Topology[link].Unit != ROUTE_DISCONNECT ) {
+						rio_dprint(RIO_DEBUG_TABLE, ("Entry is in use and cannot be deleted!\n"));
+						p->RIOError.Error = UNIT_IS_IN_USE;
+						rio_spin_unlock_irqrestore( &HostP->HostLock, flags);
+						return EBUSY;
+					}
+				}
+				/*
+				** Slot has been allocated, BUT not booted/routed/
+				** connected/selected or anything else-ed
+				*/
+				SysPort = HostMapP->SysPort;
+
+				if ( SysPort != NO_PORT ) {
+					for (port=SysPort; port < SysPort+PORTS_PER_RTA; port++) {
+						PortP = p->RIOPortp[port];
+						rio_dprint(RIO_DEBUG_TABLE, ("Unmap port\n"));
+
+						rio_spin_lock_irqsave( &PortP->portSem, flags );
+
+						PortP->Mapped = 0;
+
+						if ( PortP->State & (RIO_MOPEN|RIO_LOPEN) ) {
+
+							rio_dprint(RIO_DEBUG_TABLE, ("Gob on port\n"));
+							PortP->TxBufferIn = PortP->TxBufferOut = 0;
+							/* What should I do 
+							wakeup( &PortP->TxBufferIn );
+							wakeup( &PortP->TxBufferOut);
+							*/
+							PortP->InUse = NOT_INUSE;
+							/* What should I do 
+							wakeup( &PortP->InUse );
+							signal(PortP->TtyP->t_pgrp,SIGKILL);
+							ttyflush(PortP->TtyP,(FREAD|FWRITE));
+							*/
+							PortP->State |= RIO_CLOSING | RIO_DELETED;
+						}
+
+						/*
+						** For the second slot of a 16 port RTA, the
+						** driver needs to reset the changes made to
+						** the phb to port mappings in RIORouteRup.
+						*/
+						if (PortP->SecondBlock) {
+							ushort dest_unit = HostMapP->ID;
+							ushort dest_port = port - SysPort;
+							WORD	 *TxPktP;
+							PKT	*Pkt;
+
+							for (TxPktP = PortP->TxStart;
+								TxPktP <= PortP->TxEnd; TxPktP++) {
+								/*
+								** *TxPktP is the pointer to the
+								** transmit packet on the host card.
+								** This needs to be translated into
+								** a 32 bit pointer so it can be
+								** accessed from the driver.
+								*/
+								Pkt = (PKT *) RIO_PTR(HostP->Caddr,
+								 	RWORD(*TxPktP));
+								rio_dprint(RIO_DEBUG_TABLE, (
+						"Tx packet (%x) destination: Old %x:%x New %x:%x\n",
+								 *TxPktP, Pkt->dest_unit,
+								 Pkt->dest_port, dest_unit, dest_port));
+								WWORD(Pkt->dest_unit, dest_unit);
+								WWORD(Pkt->dest_port, dest_port);
+							}
+							rio_dprint(RIO_DEBUG_TABLE, (
+						"Port %d phb destination: Old %x:%x New %x:%x\n",
+							 port, PortP->PhbP->destination & 0xff,
+							 (PortP->PhbP->destination >> 8) & 0xff,
+							 dest_unit, dest_port));
+							WWORD(PortP->PhbP->destination,
+							 dest_unit + (dest_port << 8));
+						}
+						rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+					}
+				}
+				rio_dprint(RIO_DEBUG_TABLE, ("Entry nulled.\n"));
+				bzero((char *)HostMapP,sizeof(struct Map));
+				work_done++;
+			}
+		}
+		rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
+	}
+
+	/* XXXXX lock me up */
+	for ( entry=0; entry< TOTAL_MAP_ENTRIES; entry++ ) {
+		if ( p->RIOSavedTable[entry].RtaUniqueNum == MapP->RtaUniqueNum ) {
+			bzero((char *)&p->RIOSavedTable[entry],sizeof(struct Map));
+			work_done++;
+		}
+		if ( p->RIOConnectTable[entry].RtaUniqueNum == MapP->RtaUniqueNum ) {
+			bzero((char *)&p->RIOConnectTable[entry],sizeof(struct Map));
+			work_done++;
+		}
+	}
+	if ( work_done )
+		return 0;
+
+	rio_dprint(RIO_DEBUG_TABLE, ("Couldn't find entry to be deleted\n"));
+	p->RIOError.Error = COULDNT_FIND_ENTRY;
+	return ENXIO;
+}
+
+int RIOAssignRta( struct rio_info *p, struct Map *MapP )
+{
+    int host;
+    struct Map *HostMapP;
+    char *sptr;
+    int	link;
+
+
+    rio_dprint(RIO_DEBUG_TABLE, ("Assign entry on host %x, rta %x, ID %d, Sysport %d\n",
+				MapP->HostUniqueNum,MapP->RtaUniqueNum,
+				MapP->ID, (int)MapP->SysPort ));
+
+    if ((MapP->ID != (ushort)-1) &&
+	((int)MapP->ID < (int)1 || (int)MapP->ID > MAX_RUP ))
+    {
+	rio_dprint(RIO_DEBUG_TABLE, ("Bad ID in map entry!\n"));
+	p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
+	return EINVAL;
+    }
+    if (MapP->RtaUniqueNum == 0)
+    {
+	rio_dprint(RIO_DEBUG_TABLE, ("Rta Unique number zero!\n"));
+	p->RIOError.Error = RTA_UNIQUE_NUMBER_ZERO;
+	return EINVAL;
+    }
+    if ( (MapP->SysPort != NO_PORT) && (MapP->SysPort % PORTS_PER_RTA) )
+    {
+	rio_dprint(RIO_DEBUG_TABLE, ("Port %d not multiple of %d!\n",(int)MapP->SysPort,PORTS_PER_RTA));
+	p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
+	return EINVAL;
+    }
+    if ( (MapP->SysPort != NO_PORT) && (MapP->SysPort >= RIO_PORTS) )
+    {
+	rio_dprint(RIO_DEBUG_TABLE, ("Port %d not valid!\n",(int)MapP->SysPort));
+	p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
+	return EINVAL;
+    }
+
+    /*
+    ** Copy the name across to the map entry.
+    */
+    MapP->Name[MAX_NAME_LEN-1] = '\0';
+    sptr = MapP->Name;
+    while ( *sptr )
+    {
+    if ( *sptr<' ' || *sptr>'~' )
+    {
+	rio_dprint(RIO_DEBUG_TABLE, ("Name entry contains non-printing characters!\n"));
+	p->RIOError.Error = BAD_CHARACTER_IN_NAME;
+	return EINVAL;
+    }
+    sptr++;
+    }
+
+    for ( host=0; host < p->RIONumHosts; host++ )
+    {
+	if ( MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum )
+	{
+	    if ( (p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING )
+	    {
+		p->RIOError.Error = HOST_NOT_RUNNING;
+		return ENXIO;
+	    }
+
+	    /*
+	    ** Now we have a host we need to allocate an ID
+	    ** if the the entry does not already have one.
+	    */
+	    if (MapP->ID == (ushort)-1)
+	    {
+		int nNewID;
+
+		rio_dprint(RIO_DEBUG_TABLE, ("Attempting to get a new ID for rta \"%s\"\n",
+		      MapP->Name));
+		/*
+		** The idea here is to allow RTA's to be assigned
+		** before they actually appear on the network.
+		** This allows the addition of RTA's without having
+		** to plug them in.
+		** What we do is:
+		**  - Find a free ID and allocate it to the RTA.
+		**  - If this map entry is the second half of a
+		**    16 port entry then find the other half and
+		**    make sure the 2 cross reference each other.
+		*/
+		if (RIOFindFreeID(p, &p->RIOHosts[host], &nNewID, NULL) != 0)
+		{
+		    p->RIOError.Error = COULDNT_FIND_ENTRY;
+		    return EBUSY;
+		}
+		MapP->ID = (ushort)nNewID + 1;
+		rio_dprint(RIO_DEBUG_TABLE, ("Allocated ID %d for this new RTA.\n",MapP->ID));
+		HostMapP = &p->RIOHosts[host].Mapping[nNewID];
+		HostMapP->RtaUniqueNum = MapP->RtaUniqueNum;
+		HostMapP->HostUniqueNum = MapP->HostUniqueNum;
+		HostMapP->ID = MapP->ID;
+		for (link = 0; link < LINKS_PER_UNIT; link++)
+		{
+		    HostMapP->Topology[link].Unit = ROUTE_DISCONNECT;
+		    HostMapP->Topology[link].Link = NO_LINK;
+		}
+		if (MapP->Flags & RTA16_SECOND_SLOT)
+		{
+		    int unit;
+
+		    for (unit = 0; unit < MAX_RUP; unit++)
+			if (p->RIOHosts[host].Mapping[unit].RtaUniqueNum ==
+			    MapP->RtaUniqueNum)
+			    break;
+		    if (unit == MAX_RUP)
+		    {
+			p->RIOError.Error = COULDNT_FIND_ENTRY;
+			return EBUSY;
+		    }
+		    HostMapP->Flags |= RTA16_SECOND_SLOT;
+		    HostMapP->ID2 = MapP->ID2 = p->RIOHosts[host].Mapping[unit].ID;
+		    p->RIOHosts[host].Mapping[unit].ID2 = MapP->ID;
+		    rio_dprint(RIO_DEBUG_TABLE, ("Cross referenced id %d to ID %d.\n",
+			  MapP->ID,
+			  p->RIOHosts[host].Mapping[unit].ID));
+		}
+	    }
+
+	    HostMapP = &p->RIOHosts[host].Mapping[MapP->ID-1];
+
+	    if ( HostMapP->Flags & SLOT_IN_USE )
+	    {
+		rio_dprint(RIO_DEBUG_TABLE, ("Map table slot for ID %d is already in use.\n",MapP->ID));
+		p->RIOError.Error = ID_ALREADY_IN_USE;
+		return EBUSY;
+	    }
+
+	    /*
+	    ** Assign the sys ports and the name, and mark the slot as
+	    ** being in use.
+	    */
+	    HostMapP->SysPort = MapP->SysPort;
+	    if ((MapP->Flags & RTA16_SECOND_SLOT) == 0)
+	      CCOPY( MapP->Name, HostMapP->Name, MAX_NAME_LEN );
+	    HostMapP->Flags = SLOT_IN_USE | RTA_BOOTED;
+#if NEED_TO_FIX
+	    RIO_SV_BROADCAST(p->RIOHosts[host].svFlags[MapP->ID-1]);
+#endif
+	    if (MapP->Flags & RTA16_SECOND_SLOT)
+		HostMapP->Flags |= RTA16_SECOND_SLOT;
+
+	    RIOReMapPorts( p, &p->RIOHosts[host], HostMapP );
+	    /*
+	    ** Adjust 2nd block of 8 phbs
+	    */
+	    if (MapP->Flags & RTA16_SECOND_SLOT)
+		RIOFixPhbs(p, &p->RIOHosts[host], HostMapP->ID - 1);
+
+	    if ( HostMapP->SysPort != NO_PORT )
+	    {
+		if ( HostMapP->SysPort < p->RIOFirstPortsBooted )
+		    p->RIOFirstPortsBooted = HostMapP->SysPort;
+		if ( HostMapP->SysPort > p->RIOLastPortsBooted )
+		    p->RIOLastPortsBooted = HostMapP->SysPort;
+	    }
+	    if (MapP->Flags & RTA16_SECOND_SLOT)
+	        rio_dprint(RIO_DEBUG_TABLE, ("Second map of RTA %s added to configuration\n",
+		 p->RIOHosts[host].Mapping[MapP->ID2 - 1].Name));
+	    else
+	        rio_dprint(RIO_DEBUG_TABLE, ("RTA %s added to configuration\n",MapP->Name));
+	    return 0;
+	}
+    }
+    p->RIOError.Error = UNKNOWN_HOST_NUMBER;
+    rio_dprint(RIO_DEBUG_TABLE, ("Unknown host %x\n",MapP->HostUniqueNum));
+    return ENXIO;
+}
+
+
+int
+RIOReMapPorts(p, HostP, HostMapP)
+struct rio_info *	p;
+struct Host *HostP;
+struct Map *HostMapP; 
+{
+	register struct Port *PortP;
+	uint SubEnt;
+	uint HostPort;
+	uint SysPort;
+	ushort RtaType;
+	unsigned long flags;
+
+#ifdef CHECK
+	CheckHostP( HostP );
+	CheckHostMapP( HostMapP );
+#endif
+
+	rio_dprint(RIO_DEBUG_TABLE, ("Mapping sysport %d to id %d\n",(int)HostMapP->SysPort, HostMapP->ID));
+
+	/*
+	** We need to tell the UnixRups which sysport the rup corresponds to
+	*/
+	HostP->UnixRups[HostMapP->ID-1].BaseSysPort = HostMapP->SysPort;
+
+	if ( HostMapP->SysPort == NO_PORT )
+		return(0);
+
+	RtaType = GetUnitType(HostMapP->RtaUniqueNum);
+	rio_dprint(RIO_DEBUG_TABLE, ("Mapping sysport %d-%d\n",
+				(int)HostMapP->SysPort,(int)HostMapP->SysPort+PORTS_PER_RTA-1));
+
+	/*
+	** now map each of its eight ports
+	*/
+	for ( SubEnt=0; SubEnt<PORTS_PER_RTA; SubEnt++) {
+	  rio_dprint  (RIO_DEBUG_TABLE, ("subent = %d, HostMapP->SysPort = %d\n", 
+		  SubEnt, (int) HostMapP->SysPort));
+		SysPort = HostMapP->SysPort+SubEnt;		/* portnumber within system */
+					/* portnumber on host */
+		
+		HostPort = (HostMapP->ID-1)*PORTS_PER_RTA+SubEnt; 
+
+		rio_dprint (RIO_DEBUG_TABLE, ("c1 p = %p, p->rioPortp = %p\n", p, p->RIOPortp));
+		PortP = p->RIOPortp[SysPort];
+#if 0
+		PortP->TtyP	= &p->channel[SysPort];
+#endif
+		rio_dprint(RIO_DEBUG_TABLE, ("Map port\n"));
+
+		/*
+		** Point at all the real neat data structures
+		*/
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+		PortP->HostP = HostP;
+		PortP->Caddr = HostP->Caddr;
+
+		/*
+		** The PhbP cannot be filled in yet
+		** unless the host has been booted
+		*/
+		if ((HostP->Flags & RUN_STATE) == RC_RUNNING) {
+			struct PHB *PhbP = PortP->PhbP = &HostP->PhbP[HostPort];
+			PortP->TxAdd =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->tx_add));
+			PortP->TxStart =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->tx_start));
+			PortP->TxEnd =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->tx_end));
+			PortP->RxRemove=(WORD *)RIO_PTR(HostP->Caddr,
+									RWORD(PhbP->rx_remove));
+			PortP->RxStart =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->rx_start));
+			PortP->RxEnd =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->rx_end));
+		}
+		else
+			PortP->PhbP = NULL;
+
+		/*
+		** port related flags
+		*/
+		PortP->HostPort	= HostPort;
+		/*
+		** For each part of a 16 port RTA, RupNum is ID - 1.
+		*/
+		PortP->RupNum = HostMapP->ID - 1;
+		if (HostMapP->Flags & RTA16_SECOND_SLOT) {
+			PortP->ID2			 = HostMapP->ID2 - 1;
+			PortP->SecondBlock	 = TRUE;
+		}
+		else {
+			PortP->ID2			 = 0;
+			PortP->SecondBlock	 = FALSE;
+		}
+		PortP->RtaUniqueNum	= HostMapP->RtaUniqueNum;
+
+		/*
+		** If the port was already mapped then thats all we need to do.
+		*/
+		if (PortP->Mapped) {
+			rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+			continue;
+		}
+		else HostMapP->Flags &= ~RTA_NEWBOOT;
+
+		PortP->State		 = 0;
+		PortP->Config		= 0;
+		/*
+		** Check out the module type - if it is special (read only etc.)
+		** then we need to set flags in the PortP->Config.
+		** Note: For 16 port RTA, all ports are of the same type.
+		*/
+		if (RtaType == TYPE_RTA16) {
+			PortP->Config |= p->RIOModuleTypes[HostP->UnixRups
+				[HostMapP->ID-1].ModTypes].Flags[SubEnt % PORTS_PER_MODULE];
+		} else {
+			if ( SubEnt < PORTS_PER_MODULE )
+				PortP->Config |= p->RIOModuleTypes[LONYBLE(HostP->UnixRups
+				[HostMapP->ID-1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE];
+			else
+				PortP->Config |= p->RIOModuleTypes[HINYBLE(HostP->UnixRups
+				[HostMapP->ID-1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE];
+		}
+
+		/*
+		** more port related flags
+		*/
+		PortP->PortState	= 0;
+		PortP->ModemLines	= 0;
+		PortP->ModemState	= 0;
+		PortP->CookMode		= COOK_WELL;
+		PortP->ParamSem		= 0;
+		PortP->FlushCmdBodge= 0;
+		PortP->WflushFlag	= 0;
+		PortP->MagicFlags	= 0;
+		PortP->Lock			= 0;
+		PortP->Store		= 0;
+		PortP->FirstOpen	= 1;
+
+		/*
+		** handle the xprint issues
+		*/
+#ifdef XPRINT_SUPPORT
+		PortP->Xprint.XpActive	= 0;
+		PortP->Xprint.XttyP = &riox_tty[SysPort];
+		/*				TO				FROM			MAXLEN */
+		RIOStrNCpy( PortP->Xprint.XpOn,	RIOConf.XpOn,	MAX_XP_CTRL_LEN );
+		RIOStrNCpy( PortP->Xprint.XpOff, RIOConf.XpOff, MAX_XP_CTRL_LEN );
+		PortP->Xprint.XpCps = RIOConf.XpCps;
+		PortP->Xprint.XpLen = RIOStrlen(PortP->Xprint.XpOn)+
+									RIOStrlen(PortP->Xprint.XpOff);
+#endif
+
+		/*
+		** Buffers 'n things
+		*/
+		PortP->RxDataStart	= 0;
+		PortP->Cor2Copy	 = 0;
+		PortP->Name		 = &HostMapP->Name[0];
+#ifdef STATS
+		bzero( (caddr_t)&PortP->Stat, sizeof(struct RIOStats) );
+#endif
+		PortP->statsGather = 0;
+		PortP->txchars = 0;
+		PortP->rxchars = 0;
+		PortP->opens = 0;
+		PortP->closes = 0;
+		PortP->ioctls = 0;
+		if ( PortP->TxRingBuffer )
+			bzero( PortP->TxRingBuffer, p->RIOBufferSize );
+		else if ( p->RIOBufferSize ) {
+			PortP->TxRingBuffer = sysbrk(p->RIOBufferSize);
+			bzero( PortP->TxRingBuffer, p->RIOBufferSize );
+		}
+		PortP->TxBufferOut	= 0;
+		PortP->TxBufferIn	 = 0;
+		PortP->Debug		= 0;
+		/*
+		** LastRxTgl stores the state of the rx toggle bit for this
+		** port, to be compared with the state of the next pkt received.
+		** If the same, we have received the same rx pkt from the RTA
+		** twice. Initialise to a value not equal to PHB_RX_TGL or 0.
+		*/
+		PortP->LastRxTgl	= ~(uchar)PHB_RX_TGL;
+
+		/*
+		** and mark the port as usable
+		*/
+		PortP->Mapped = 1;
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	}
+	if ( HostMapP->SysPort < p->RIOFirstPortsMapped )
+		p->RIOFirstPortsMapped = HostMapP->SysPort;
+	if ( HostMapP->SysPort > p->RIOLastPortsMapped )
+		p->RIOLastPortsMapped = HostMapP->SysPort;
+
+	return 0;
+}
+
+int
+RIOChangeName(p, MapP)
+struct rio_info *p;
+struct Map* MapP; 
+{
+	int host;
+	struct Map *HostMapP;
+	char *sptr;
+
+	rio_dprint(RIO_DEBUG_TABLE, ("Change name entry on host %x, rta %x, ID %d, Sysport %d\n",
+								MapP->HostUniqueNum,MapP->RtaUniqueNum,
+								MapP->ID, (int)MapP->SysPort ));
+
+	if ( MapP->ID > MAX_RUP ) {
+		rio_dprint(RIO_DEBUG_TABLE, ("Bad ID in map entry!\n"));
+		p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
+		return EINVAL;
+	}
+
+	MapP->Name[MAX_NAME_LEN-1] = '\0';
+	sptr = MapP->Name;
+
+	while ( *sptr ) {
+		if ( *sptr<' ' || *sptr>'~' ) {
+			rio_dprint(RIO_DEBUG_TABLE, ("Name entry contains non-printing characters!\n"));
+			p->RIOError.Error = BAD_CHARACTER_IN_NAME;
+			return EINVAL;
+		}
+		sptr++;
+	}
+
+	for ( host=0; host < p->RIONumHosts; host++ ) {
+		if ( MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum ) {
+			if ( (p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING ) {
+				p->RIOError.Error = HOST_NOT_RUNNING;
+				return ENXIO;
+			}
+			if ( MapP->ID==0 ) {
+				CCOPY( MapP->Name, p->RIOHosts[host].Name, MAX_NAME_LEN );
+				return 0;
+			}
+
+			HostMapP = &p->RIOHosts[host].Mapping[MapP->ID-1];
+
+			if ( HostMapP->RtaUniqueNum != MapP->RtaUniqueNum ) {
+				p->RIOError.Error = RTA_NUMBER_WRONG;
+				return ENXIO;
+			}
+			CCOPY( MapP->Name, HostMapP->Name, MAX_NAME_LEN );
+			return 0;
+		}
+	}
+	p->RIOError.Error = UNKNOWN_HOST_NUMBER;
+	rio_dprint(RIO_DEBUG_TABLE, ("Unknown host %x\n",MapP->HostUniqueNum));
+	return ENXIO;
+}
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/riotime.h linux.15p9/drivers/char/rio/riotime.h
--- linux.vanilla/drivers/char/rio/riotime.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/riotime.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,63 @@
+/****************************************************************************
+ *******                                                              *******
+ *******            T I M E
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _riotime_h
+#define _riotime_h 1
+
+#ifndef lint
+#ifdef SCCS
+static char *_rio_riotime_h_sccs = "@(#)riotime.h	1.1" ;
+#endif
+#endif
+
+#define TWO_POWER_FIFTEEN (ushort)32768
+#define RioTime()    riotime
+#define RioTimeAfter(time1,time2) ((ushort)time1 - (ushort)time2) < TWO_POWER_FIFTEEN
+#define RioTimePlus(time1,time2) ((ushort)time1 + (ushort)time2)
+
+/**************************************
+ * Convert a RIO tick (1/10th second)
+ * into transputer low priority ticks
+ *************************************/ 
+#define RioTimeToLow(time) (time*(100000 / 64))
+#define RioLowToTime(time) ((time*64)/100000)
+
+#define RIOTENTHSECOND (ushort)1
+#define RIOSECOND (ushort)(RIOTENTHSECOND * 10)
+#endif
+
+/*********** end of file ***********/
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/riotty.c linux.15p9/drivers/char/rio/riotty.c
--- linux.vanilla/drivers/char/rio/riotty.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/riotty.c	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,1322 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: riotty.c
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 10:33:47
+**	Retrieved	: 11/6/98 10:33:50
+**
+**  ident @(#)riotty.c	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+#ifdef SCCS_LABELS
+static char *_riotty_c_sccs_ = "@(#)riotty.c	1.3";
+#endif
+
+
+#define __EXPLICIT_DEF_H__
+
+#define __NO_VERSION__
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/malloc.h>
+#include <linux/errno.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/string.h>
+#include <asm/semaphore.h>
+#include <asm/uaccess.h>
+
+#include <linux/termios.h>
+
+#include <linux/serial.h>
+
+#include <linux/compatmac.h>
+#include <linux/generic_serial.h>
+
+
+#include "linux_compat.h"
+#include "rio_linux.h"
+#include "typdef.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "top.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "riotypes.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "error.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+#include "control.h"
+#include "cirrus.h"
+#include "rioioctl.h"
+#include "param.h"
+#include "list.h"
+#include "sam.h"
+
+
+#if 0
+static void ttyseth_pv(struct Port *, struct ttystatics *, 
+				struct termios *sg, int);
+#endif
+
+static void RIOClearUp(struct Port *PortP);
+static int RIOShortCommand(struct rio_info *p, struct Port *PortP, 
+			   int command, int len, int arg);
+
+
+extern int	conv_vb[];	/* now defined in ttymgr.c */
+extern int	conv_bv[];	/* now defined in ttymgr.c */
+ 
+/*
+** 16.09.1998 ARG - Fix to build riotty.k.o for Modular Kernel Support
+**
+** ep.def.h is necessary for Modular Kernel Support
+** DO NOT place any kernel 'extern's after this line
+** or this source file will not build riotty.k.o
+*/
+#ifdef uLYNX
+#include <ep.def.h>
+#endif
+
+#ifdef NEED_THIS2
+static struct old_sgttyb 
+default_sg = 
+{ 
+	B19200, B19200,				/* input and output speed */ 
+	'H' - '@',					/* erase char */ 
+	-1,							/* 2nd erase char */ 
+	'U' - '@',					/* kill char */ 
+	ECHO | CRMOD,				/* mode */ 
+	'C' - '@',					/* interrupt character */ 
+	'\\' - '@',					/* quit char */ 
+	'Q' - '@',					/* start char */
+	'S' - '@',					/* stop char */ 
+	'D' - '@',					/* EOF */
+	-1,							/* brk */
+	(LCRTBS | LCRTERA | LCRTKIL | LCTLECH),	/* local mode word */ 
+	'Z' - '@',					/* process stop */
+	'Y' - '@',					/* delayed stop */
+	'R' - '@',					/* reprint line */ 
+	'O' - '@',					/* flush output */
+	'W' - '@',					/* word erase */
+	'V' - '@'					/* literal next char */
+};
+#endif
+
+
+extern struct rio_info *p;
+extern void rio_inc_mod_count (void);
+
+
+int
+riotopen(struct tty_struct * tty, struct file * filp)
+{
+	register uint SysPort;
+	int Modem;
+	int repeat_this = 250;
+	struct Port *PortP;		 /* pointer to the port structure */
+	unsigned long flags;
+	int retval = 0;
+
+	SysPort = rio_minor (tty->device);
+	Modem   = rio_ismodem (tty->device);
+
+	if ( p->RIOFailed ) {
+		rio_dprint(RIO_DEBUG_TTY, ("System initialisation failed\n"));
+		pseterr(ENXIO);
+		return 0;
+	}
+
+	rio_dprint(RIO_DEBUG_TTY, ("port open SysPort %d (%s) (mapped:%d)\n",
+	       SysPort,  Modem ? "Modem" : "tty",
+				   p->RIOPortp[SysPort]->Mapped  ) );
+
+	/*
+	** Validate that we have received a legitimate request.
+	** Currently, just check that we are opening a port on
+	** a host card that actually exists, and that the port
+	** has been mapped onto a host.
+	*/
+	if (SysPort >= RIO_PORTS) {	/* out of range ? */
+		rio_dprint(RIO_DEBUG_TTY, ("Illegal port number %d\n",SysPort));
+		pseterr(ENXIO);
+		return 0;
+	}
+
+	/*
+	** Grab pointer to the port stucture
+	*/
+	PortP = p->RIOPortp[SysPort];	/* Get control struc */
+
+	if ( !PortP->Mapped ) {	/* we aren't mapped yet! */
+		/*
+		** The system doesn't know which RTA this port
+		** corresponds to.
+		*/
+		rio_dprint(RIO_DEBUG_TTY, ("port not mapped into system\n"));
+		pseterr(ENXIO);
+		return 0;
+	}
+
+	tty->driver_data = PortP;
+
+	PortP->gs.tty = tty;
+	PortP->gs.count++;
+	rio_dprint(RIO_DEBUG_TTY, ("%d bytes in tx buffer\n",
+				   PortP->gs.xmit_cnt));
+	gs_init_port (&PortP->gs);
+
+	/*
+	** If the host hasn't been booted yet, then 
+	** fail
+	*/
+	if ( (PortP->HostP->Flags & RUN_STATE) != RC_RUNNING ) {
+		rio_dprint(RIO_DEBUG_TTY, ("Host not running\n"));
+		pseterr(ENXIO);
+		return 0;
+	}
+
+	/*
+	** If the RTA has not booted yet and the user has choosen to block
+	** until the RTA is present then we must spin here waiting for
+	** the RTA to boot.
+	*/
+#if 0
+	if (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)) {
+		if (PortP->WaitUntilBooted) {
+			rio_dprint(RIO_DEBUG_TTY, ("Waiting for RTA to boot\n"));
+			do {
+				if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
+					rio_dprint(RIO_DEBUG_TTY, ("RTA EINTR in delay \n"));
+					return -EINTR;
+				}
+				if (repeat_this -- <= 0) {
+					rio_dprint(RIO_DEBUG_TTY, ("Waiting for RTA to boot timeout\n"));
+					RIOPreemptiveCmd(p, PortP, FCLOSE ); 
+					pseterr(EINTR);
+					return -EIO;
+				}
+			} while(!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED));
+			rio_dprint(RIO_DEBUG_TTY, ("RTA has been booted\n"));
+		} else {
+			rio_dprint(RIO_DEBUG_TTY, ("RTA never booted\n"));
+			pseterr(ENXIO);
+			return 0;
+		}
+	}
+#else
+	/* I find the above code a bit hairy. I find the below code
+           easier to read and shorter. Now, if it works too that would
+	   be great... -- REW 
+	*/
+	rio_dprint(RIO_DEBUG_TTY, ("Checking if RTA has booted... \n"));
+	while (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)) {
+	  if (!PortP->WaitUntilBooted) {
+	    rio_dprint(RIO_DEBUG_TTY, ("RTA never booted\n"));
+	    return -ENXIO;
+	  }
+
+	  /* Under Linux you'd normally use a wait instead of this
+	     busy-waiting. I'll stick with the old implementation for
+	     now. --REW 
+	  */
+	  if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
+	    rio_dprint(RIO_DEBUG_TTY, ("RTA_wait_for_boot: EINTR in delay \n"));
+	    return -EINTR;
+	  }
+	  if (repeat_this -- <= 0) {
+	    rio_dprint(RIO_DEBUG_TTY, ("Waiting for RTA to boot timeout\n"));
+	    return -EIO;
+	  }
+	}
+	rio_dprint(RIO_DEBUG_TTY, ("RTA has been booted\n"));
+#endif
+#if 0
+	tp =  PortP->TtyP;		/* get tty struct */
+#endif
+	rio_spin_lock_irqsave(&PortP->portSem, flags);
+	if ( p->RIOHalted ) {
+		goto bombout;
+	}
+#if 0
+	retval = gs_init_port(&PortP->gs);
+	if (retval)
+	  return retval;
+#endif
+
+	/*
+	** If the port is in the final throws of being closed,
+	** we should wait here (politely), waiting
+	** for it to finish, so that it doesn't close us!
+	*/
+	while ( (PortP->State & RIO_CLOSING) && !p->RIOHalted ) {
+		rio_dprint(RIO_DEBUG_TTY, ("Waiting for RIO_CLOSING to go away\n"));
+		if (repeat_this -- <= 0) {
+			rio_dprint(RIO_DEBUG_TTY, ("Waiting for not idle closed broken by signal\n"));
+			RIOPreemptiveCmd(p, PortP, FCLOSE ); 
+			retval = -EINTR;
+			goto bombout;
+		}
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
+			rio_spin_lock_irqsave(&PortP->portSem, flags); 
+			retval = -EINTR;
+			goto bombout;
+		}
+		rio_spin_lock_irqsave(&PortP->portSem, flags); 
+	}
+
+	if ( !PortP->Mapped ) {
+		rio_dprint(RIO_DEBUG_TTY, ("Port unmapped while closing!\n"));
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		retval = -ENXIO;
+		return retval;
+	}
+
+	if ( p->RIOHalted ) {
+		goto bombout;
+	}
+
+/*
+** 15.10.1998 ARG - ESIL 0761 part fix
+** RIO has it's own CTSFLOW and RTSFLOW flags in 'Config' in the port structure,
+** we need to make sure that the flags are clear when the port is opened.
+*/
+	/* Uh? Suppose I turn these on and then another process opens
+	   the port again? The flags get cleared! Not good. -- REW */
+	if ( !(PortP->State & (RIO_LOPEN | RIO_MOPEN)) ) {
+		PortP->Config &= ~(RIO_CTSFLOW|RIO_RTSFLOW);
+	}
+
+	if (!(PortP->firstOpen)) {	/* First time ? */
+		rio_dprint(RIO_DEBUG_TTY, ("First open for this port\n"));
+		rio_inc_mod_count ();
+
+		PortP->firstOpen++;
+		PortP->CookMode = 0; /* XXX RIOCookMode(tp); */
+		PortP->InUse = NOT_INUSE;
+
+		/* Tentative fix for bug PR27. Didn't work. */
+		/* PortP->gs.xmit_cnt = 0; */
+
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+#ifdef NEED_THIS
+		ttyseth(PortP, tp, (struct old_sgttyb *)&default_sg);
+#endif
+
+		/* Someone explain to me why this delay/config is
+                   here. If I read the docs correctly the "open"
+                   command piggybacks the parameters immediately. 
+		   -- REW */
+		RIOParam(PortP,OPEN,Modem,OK_TO_SLEEP);		/* Open the port */
+#if 0
+		/* This delay of 1 second was annoying. I removed it. -- REW */
+		RIODelay(PortP, HUNDRED_MS*10);
+		RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP);	/* Config the port */
+#endif
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+		/*
+		** wait for the port to be not closed.
+		*/
+		while ( !(PortP->PortState & PORT_ISOPEN) && !p->RIOHalted ) {
+			rio_dprint(RIO_DEBUG_TTY, ("Waiting for PORT_ISOPEN-currently %x\n",PortP->PortState));
+/*
+** 15.10.1998 ARG - ESIL 0759
+** (Part) fix for port being trashed when opened whilst RTA "disconnected"
+** Take out the limited wait - now wait for ever or until user
+** bangs us out.
+**
+			if (repeat_this -- <= 0) {
+				rio_dprint(RIO_DEBUG_TTY, ("Waiting for open to finish timed out.\n"));
+				RIOPreemptiveCmd(p, PortP, FCLOSE ); 
+				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+				return -EINTR;
+			}
+**
+*/
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
+				rio_dprint(RIO_DEBUG_TTY, ("Waiting for open to finish broken by signal\n"));
+				RIOPreemptiveCmd(p, PortP, FCLOSE );
+				return -EINTR;
+			}
+			rio_spin_lock_irqsave(&PortP->portSem, flags);
+		}
+
+		if ( p->RIOHalted ) {
+		  retval = -EIO;
+bombout:
+		  /* 			RIOClearUp( PortP ); */
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return retval;
+		}
+		rio_dprint(RIO_DEBUG_TTY, ("PORT_ISOPEN found\n"));
+	}
+
+#ifdef MODEM_SUPPORT 
+	if (Modem) {
+		rio_dprint(RIO_DEBUG_TTY, ("Modem - test for carrier\n"));
+		/*
+		** ACTION
+		** insert test for carrier here. -- ???
+		** I already see that test here. What's the deal? -- REW
+		*/
+		if ((tp->tm.c_cflag & CLOCAL) || (PortP->ModemState & MSVR1_CD))
+		{
+			rio_dprint(RIO_DEBUG_TTY, (PortP,DBG_OPEN,"open(%d) Modem carr on\n",SysPort));
+			tp->tm.c_state |= CARR_ON;
+			wakeup((caddr_t) &tp->tm.c_canq);
+		}
+		else /* no carrier - wait for DCD */
+		{
+			while (!(tp->tm.c_state&CARR_ON) && 
+			       !(filp->f_flags&O_NONBLOCK) && !p->RIOHalted )
+			{
+				rio_dprint(RIO_DEBUG_TTY, (PortP,DBG_OPEN,"open(%d) sleeping for carr on\n",SysPort));
+				tp->tm.c_state |= WOPEN;
+				PortP->State |= RIO_WOPEN;
+				if ( sleep((caddr_t)&tp->tm.c_canq, TTIPRI|PCATCH))
+				{
+					/*
+					** ACTION: verify that this is a good thing
+					** to do here. -- ???
+					** I think it's OK. -- REW
+					*/
+					rio_dprint(RIO_DEBUG_TTY, ("open(%d) sleeping for carr broken by signal\n",
+					       SysPort));
+					RIOPreemptiveCmd( p, PortP, FCLOSE );
+					tp->tm.c_state &= ~WOPEN;
+					PortP->State &= ~RIO_WOPEN;
+					rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+					return -EINTR;
+				}
+			}
+			PortP->State &= ~RIO_WOPEN;
+		}
+		if ( RIOHalted )
+			goto bombout;
+		PortP->State |= RIO_MOPEN;
+	}
+	else
+#endif
+	{
+		/*
+		** ACTION
+		** Direct line open - force carrier (will probably mean
+		** that sleeping Modem line fubar)
+		*/
+		PortP->State |= RIO_LOPEN;
+	}
+
+	if ( p->RIOHalted ) {
+		goto bombout;
+	}
+
+	rio_dprint(RIO_DEBUG_TTY, ("high level open done\n"));
+
+#ifdef STATS
+	PortP->Stat.OpenCnt++;
+#endif
+	/*
+	** Count opens for port statistics reporting
+	*/
+	if (PortP->statsGather)
+		PortP->opens++;
+
+	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	rio_dprint(RIO_DEBUG_TTY, ("Returning from open\n"));
+	return 0;
+}
+
+/*
+** RIOClose the port.
+** The operating system thinks that this is last close for the device.
+** As there are two interfaces to the port (Modem and tty), we need to
+** check that both are closed before we close the device.
+*/ 
+int
+riotclose(void  *ptr)
+{
+#if 0
+	register uint SysPort = dev;
+	struct ttystatics *tp;		/* pointer to our ttystruct */
+#endif
+	struct Port *PortP =ptr;	/* pointer to the port structure */
+	int deleted = 0;
+	int	try = 25;
+	int	repeat_this = 0xff;
+	struct tty_struct * tty;
+	unsigned long flags;
+	int Modem;
+	int rv =0;
+	
+	rio_dprint(RIO_DEBUG_TTY, ("port close SysPort %d\n",PortP->PortNum));
+
+	/* PortP = p->RIOPortp[SysPort]; */
+	rio_dprint(RIO_DEBUG_TTY, ("Port is at address 0x%x\n",(int)PortP));
+	/* tp = PortP->TtyP;*/			/* Get tty */
+	tty = PortP->gs.tty;
+	rio_dprint(RIO_DEBUG_TTY, ("TTY is at address 0x%x\n",(int)tty));
+	Modem = rio_ismodem(tty->device);
+#if 0
+	/* What F.CKING cache? Even then, a higly idle multiprocessor,
+	   system with large caches this won't work . Better find out when 
+	   this doesn't work asap, and fix the cause.  -- REW */
+	
+	RIODelay(PortP, HUNDRED_MS*10);	/* To flush the cache */
+#endif
+	rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+	/*
+	** Setting this flag will make any process trying to open
+	** this port block until we are complete closing it.
+	*/
+	PortP->State |= RIO_CLOSING;
+
+	if ( (PortP->State & RIO_DELETED) ) {
+		rio_dprint(RIO_DEBUG_TTY, ("Close on deleted RTA\n"));
+		deleted = 1;
+	}
+	
+	if ( p->RIOHalted ) {
+		RIOClearUp( PortP );
+		rv = -EIO;
+		goto close_end;
+	}
+
+	rio_dprint(RIO_DEBUG_TTY, ("Clear bits\n"));
+	/*
+	** clear the open bits for this device
+	*/
+	PortP->State &= (Modem ? ~RIO_MOPEN : ~RIO_LOPEN);
+
+	/*
+	** If the device was open as both a Modem and a tty line
+	** then we need to wimp out here, as the port has not really
+	** been finally closed (gee, whizz!) The test here uses the
+	** bit for the OTHER mode of operation, to see if THAT is
+	** still active!
+	*/
+	if ( (PortP->State & (RIO_LOPEN|RIO_MOPEN)) ) {
+		/*
+		** The port is still open for the other task -
+		** return, pretending that we are still active.
+		*/
+		rio_dprint(RIO_DEBUG_TTY, ("Channel %d still open !\n",PortP->PortNum));
+		PortP->State &= ~RIO_CLOSING;
+		if (PortP->firstOpen)
+			PortP->firstOpen--;
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		return -EIO;
+	}
+
+	rio_dprint(RIO_DEBUG_TTY, ("Closing down - everything must go!\n"));
+
+	PortP->State &= ~RIO_DYNOROD;
+
+	/*
+	** This is where we wait for the port
+	** to drain down before closing. Bye-bye....
+	** (We never meant to do this)
+	*/
+	rio_dprint(RIO_DEBUG_TTY, ("Timeout 1 starts\n"));
+
+#if 0
+	if (!deleted)
+	while ( (PortP->InUse != NOT_INUSE) && !p->RIOHalted && 
+		(PortP->TxBufferIn != PortP->TxBufferOut) ) {
+		cprintf("Need to flush the ttyport\n");
+		if (repeat_this -- <= 0) {
+			rv = -EINTR;
+			rio_dprint(RIO_DEBUG_TTY, ("Waiting for not idle closed broken by signal\n"));
+			RIOPreemptiveCmd(p, PortP, FCLOSE ); 
+			goto close_end;
+		}
+		rio_dprint(RIO_DEBUG_TTY, ("Calling timeout to flush in closing\n"));
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		if (RIODelay_ni(PortP, HUNDRED_MS*10) == RIO_FAIL) {
+			rio_dprint(RIO_DEBUG_TTY, ("RTA EINTR in delay \n"));
+			rv = -EINTR;
+			rio_spin_lock_irqsave(&PortP->portSem, flags);
+			goto close_end;
+		}
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+	}
+#endif
+	PortP->TxBufferIn = PortP->TxBufferOut = 0;
+	repeat_this = 0xff;
+
+	PortP->InUse = 0;
+	if ( (PortP->State & (RIO_LOPEN|RIO_MOPEN)) ) {
+		/*
+		** The port has been re-opened for the other task -
+		** return, pretending that we are still active.
+		*/
+		rio_dprint(RIO_DEBUG_TTY, ("Channel %d re-open!\n", PortP->PortNum));
+		PortP->State &= ~RIO_CLOSING;
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		if (PortP->firstOpen)
+			PortP->firstOpen--;
+		return -EIO;
+	}
+
+	if ( p->RIOHalted ) {
+		RIOClearUp( PortP );
+		goto close_end;
+	}
+
+	
+
+	/* Can't call RIOShortCommand with the port locked. */
+	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+
+	if (RIOShortCommand(p, PortP, CLOSE, 1, 0) == RIO_FAIL) {
+	  RIOPreemptiveCmd(p, PortP,FCLOSE);
+	  goto close_end;
+	}
+
+	if (!deleted)
+	  while (try && (PortP->PortState & PORT_ISOPEN)) {
+	        try--;
+		if (try == 0) {
+		  rio_dprint(RIO_DEBUG_TTY, ("Run out of tries - force the bugger shut!\n" ));
+		  RIOPreemptiveCmd(p, PortP,FCLOSE);
+		  break;
+		}
+		rio_dprint(RIO_DEBUG_TTY, ("Close: PortState:ISOPEN is %d\n", 
+					   PortP->PortState & PORT_ISOPEN));
+
+		if ( p->RIOHalted ) {
+			RIOClearUp( PortP );
+			goto close_end;
+		}
+		RIODelay_ni(PortP, HUNDRED_MS);
+	}
+	rio_spin_lock_irqsave(&PortP->portSem, flags);
+	rio_dprint(RIO_DEBUG_TTY, ("Close: try was %d on completion\n", try ));
+ 
+	/* RIOPreemptiveCmd(p, PortP, FCLOSE); */
+
+/*
+** 15.10.1998 ARG - ESIL 0761 part fix
+** RIO has it's own CTSFLOW and RTSFLOW flags in 'Config' in the port structure,** we need to make sure that the flags are clear when the port is opened.
+*/
+	PortP->Config &= ~(RIO_CTSFLOW|RIO_RTSFLOW);
+
+
+#ifdef STATS
+	PortP->Stat.CloseCnt++;
+#endif
+	/*
+	** Count opens for port statistics reporting
+	*/
+	if (PortP->statsGather)
+		PortP->closes++;
+
+close_end:
+	/* XXX: Why would a "DELETED" flag be reset here? I'd have
+	   thought that a "deleted" flag means that the port was
+	   permanently gone, but here we can make it reappear by it
+	   being in close during the "deletion".
+	*/
+	PortP->State &= ~(RIO_CLOSING|RIO_DELETED);
+	if (PortP->firstOpen)
+		PortP->firstOpen--;
+	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	rio_dprint(RIO_DEBUG_TTY, ("Return from close\n"));
+	return rv;
+}
+
+
+/*
+** decide if we need to use the line discipline.
+** This routine can return one of three values:
+** COOK_RAW if no processing has to be done by the line discipline or the card
+** COOK_WELL if the line discipline must be used to do the processing
+** COOK_MEDIUM if the card can do all the processing necessary.
+*/
+int
+RIOCookMode(struct ttystatics *tp)
+{
+	/*
+	** We cant handle tm.c_mstate != 0 on SCO
+	** We cant handle mapping
+	** We cant handle non-ttwrite line disc.
+	** We cant handle lflag XCASE
+	** We can handle oflag OPOST & (OCRNL, ONLCR, TAB3)
+	*/
+
+#ifdef CHECK
+	CheckTtyP( tp );
+#endif
+	if (!(tp->tm.c_oflag & OPOST))	/* No post processing */
+		return COOK_RAW;	/* Raw mode o/p */
+
+	if ( tp->tm.c_lflag & XCASE )
+		return COOK_WELL;	/* Use line disc */
+
+	if (tp->tm.c_oflag & ~(OPOST | ONLCR | OCRNL | TAB3 ) )
+		return COOK_WELL;	/* Use line disc for strange modes */
+
+	if ( tp->tm.c_oflag == OPOST )	/* If only OPOST is set, do RAW */
+		return COOK_RAW;
+
+	/*
+	** So, we need to output process!
+	*/
+	return COOK_MEDIUM;
+}
+
+
+static void
+RIOClearUp(PortP)
+struct Port *PortP;
+{
+	rio_dprint(RIO_DEBUG_TTY, ("RIOHalted set\n"));
+	PortP->Config = 0;	  /* Direct semaphore */
+	PortP->PortState = 0;
+	PortP->firstOpen = 0;
+	PortP->FlushCmdBodge = 0;
+	PortP->ModemState = PortP->CookMode = 0;
+	PortP->Mapped = 0;
+	PortP->WflushFlag = 0;
+	PortP->MagicFlags	= 0;
+	PortP->RxDataStart = 0;
+	PortP->TxBufferIn = 0;
+	PortP->TxBufferOut = 0;
+}
+
+/*
+** Put a command onto a port.
+** The PortPointer, command, length and arg are passed.
+** The len is the length *inclusive* of the command byte,
+** and so for a command that takes no data, len==1.
+** The arg is a single byte, and is only used if len==2.
+** Other values of len aren't allowed, and will cause
+** a panic.
+*/
+static int RIOShortCommand(struct rio_info *p, struct Port *PortP,
+		int command, int len, int arg)
+{
+	PKT *PacketP;
+	int		retries = 20; /* at 10 per second -> 2 seconds */
+	unsigned long flags;
+
+	rio_dprint(RIO_DEBUG_TTY, ("entering shortcommand.\n"));
+#ifdef CHECK
+	CheckPortP( PortP );
+	if ( len < 1 || len > 2 )
+		cprintf(("STUPID LENGTH %d\n",len));
+#endif
+
+	if ( PortP->State & RIO_DELETED ) {
+		rio_dprint(RIO_DEBUG_TTY, ("Short command to deleted RTA ignored\n"));
+		return RIO_FAIL;
+	}
+	rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+	/*
+	** If the port is in use for pre-emptive command, then wait for it to 
+	** be free again.
+	*/
+	while ( (PortP->InUse != NOT_INUSE) && !p->RIOHalted ) {
+		rio_dprint(RIO_DEBUG_TTY, ("Waiting for not in use (%d)\n", 
+					   retries));
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		if (retries-- <= 0) {
+			return RIO_FAIL;
+		}
+		if (RIODelay_ni(PortP, HUNDRED_MS) == RIO_FAIL) {
+			return RIO_FAIL;
+		}
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+	}
+	if ( PortP->State & RIO_DELETED ) {
+		rio_dprint(RIO_DEBUG_TTY, ("Short command to deleted RTA ignored\n"));
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		return RIO_FAIL;
+	}
+
+	while ( !can_add_transmit(&PacketP,PortP) && !p->RIOHalted ) {
+		rio_dprint(RIO_DEBUG_TTY, ("Waiting to add short command to queue (%d)\n", retries));
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		if (retries-- <= 0) {
+		  rio_dprint(RIO_DEBUG_TTY, ("out of tries. Failing\n"));
+			return RIO_FAIL;
+		}
+		if ( RIODelay_ni(PortP, HUNDRED_MS)==RIO_FAIL ) {
+			return RIO_FAIL;
+		}
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+	}
+
+	if ( p->RIOHalted ) {
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		return RIO_FAIL;
+	}
+
+	/*
+	** set the command byte and the argument byte
+	*/
+	WBYTE(PacketP->data[0] , command);
+
+	if ( len==2 )
+		WBYTE(PacketP->data[1] , arg);
+
+	/*
+	** set the length of the packet and set the command bit.
+	*/
+	WBYTE(PacketP->len , PKT_CMD_BIT | len);
+
+	add_transmit(PortP);
+	/*
+	** Count characters transmitted for port statistics reporting
+	*/
+	if (PortP->statsGather)
+		PortP->txchars += len;
+
+	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	return p->RIOHalted ? RIO_FAIL : ~RIO_FAIL;
+}
+
+
+#if 0
+/*
+** This is an ioctl interface. This is the twentieth century. You know what
+** its all about.
+*/
+int
+riotioctl(p, dev, cmd, arg)
+struct rio_info *		p;
+dev_t dev;
+register int cmd;
+register caddr_t arg;
+{
+	register struct		Port *PortP;
+	register struct		ttystatics *tp;
+	int					current;
+	int					ParamSemIncremented = 0;
+	int					old_oflag, old_cflag, old_iflag, changed, oldcook;
+	int					i;
+	unsigned char		sio_regs[5];		/* Here be magic */
+	short				vpix_cflag;
+	short				divisor;
+	int					baud;
+	uint				SysPort = dev;
+	int					Modem = rio_ismodem(dev);
+	int					ioctl_processed;
+
+	rio_dprint(RIO_DEBUG_TTY, ("port ioctl SysPort %d command 0x%x argument 0x%x %s\n",
+			SysPort,cmd,arg,Modem?"Modem":"tty"));
+
+	if ( SysPort >= RIO_PORTS ) {
+		rio_dprint(RIO_DEBUG_TTY, ("Bad port number %d\n",SysPort));
+		return -ENXIO;
+	}
+
+	PortP = p->RIOPortp[SysPort];
+	tp = PortP->TtyP;
+
+	rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+#ifdef STATS
+	PortP->Stat.IoctlCnt++;
+#endif
+
+	if ( PortP->State & RIO_DELETED ) {
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		return -EIO;
+	}
+
+
+	if ( p->RIOHalted ) {
+		RIOClearUp( PortP );
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		return -EIO;
+	}
+
+	/*
+	** Count ioctls for port statistics reporting
+	*/
+	if (PortP->statsGather)
+		PortP->ioctls++;
+
+	/*
+	** Specialix RIO Ioctl calls
+	*/
+	switch (cmd) {
+
+		case TCRIOTRIAD:
+			if ( arg )
+				PortP->State |= RIO_TRIAD_MODE;
+			else
+				PortP->State &= ~RIO_TRIAD_MODE;
+			/*
+			** Normally, when istrip is set on a port, a config is
+			** sent to the RTA instructing the CD1400 to do the
+			** stripping. In TRIAD mode, the interrupt receive routine
+			** must do the stripping instead, since it has to detect
+			** an 8 bit function key sequence. If istrip is set with
+			** TRIAD mode on(off), and 8 bit data is being read by
+			** the port, the user then turns TRIAD mode off(on), the RTA
+			** must be reconfigured (not) to do the stripping.
+			** Hence we call RIOParam here.
+			*/
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP);	
+			return 0;
+
+		case TCRIOTSTATE:
+			rio_dprint(RIO_DEBUG_TTY, ("tbusy/tstop monitoring %sabled\n",
+		 		arg ? "en" : "dis"));
+			/* MonitorTstate = 0 ;*/
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			RIOParam(PortP, CONFIG, Modem, OK_TO_SLEEP);
+			return 0;
+
+		case TCRIOSTATE: /* current state of Modem input pins */
+			rio_dprint(RIO_DEBUG_TTY, ("TCRIOSTATE\n"));
+			if (RIOPreemptiveCmd(p, PortP, MGET) == RIO_FAIL)
+				rio_dprint(RIO_DEBUG_TTY, ("TCRIOSTATE command failed\n"));
+			PortP->State |= RIO_BUSY;
+			current = PortP->ModemState;
+			if ( copyout((caddr_t)&current, (int)arg,
+							sizeof(current))==COPYFAIL ) {
+				rio_dprint(RIO_DEBUG_TTY, ("Copyout failed\n"));
+				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+				pseterr(EFAULT);
+			}
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return 0;
+
+		case TCRIOMBIS:		/* Set modem lines */
+		case TCRIOMBIC:		/* Clear modem lines */
+			rio_dprint(RIO_DEBUG_TTY, ("TCRIOMBIS/TCRIOMBIC\n"));
+			if (cmd == TCRIOMBIS) {
+				uint		state;
+				state = (uint)arg;
+				PortP->ModemState |= (ushort)state;
+				PortP->ModemLines = (ulong) arg;
+				if (RIOPreemptiveCmd(p, PortP, MBIS) == RIO_FAIL)
+					rio_dprint(RIO_DEBUG_TTY, (
+					 "TCRIOMBIS command failed\n"));
+			}
+			else {
+				uint		state;
+
+				state = (uint)arg;
+				PortP->ModemState &= ~(ushort)state;
+				PortP->ModemLines = (ulong) arg;
+				if (RIOPreemptiveCmd(p, PortP, MBIC) == RIO_FAIL)
+					rio_dprint(RIO_DEBUG_TTY, ("TCRIOMBIC command failed\n"));
+			}
+			PortP->State |= RIO_BUSY;
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return 0;
+
+		case TCRIOXPON: /* set Xprint ON string */
+			rio_dprint(RIO_DEBUG_TTY, ("TCRIOXPON\n"));
+			if ( copyin((int)arg, (caddr_t)PortP->Xprint.XpOn,
+						MAX_XP_CTRL_LEN)==COPYFAIL ) {
+				rio_dprint(RIO_DEBUG_TTY, ("Copyin failed\n"));
+				PortP->Xprint.XpOn[0] = '\0';
+				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+				pseterr(EFAULT);
+			}
+			PortP->Xprint.XpOn[MAX_XP_CTRL_LEN-1] = '\0';
+			PortP->Xprint.XpLen = RIOStrlen(PortP->Xprint.XpOn)+
+												RIOStrlen(PortP->Xprint.XpOff);
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return 0;
+
+		case TCRIOXPOFF: /* set Xprint OFF string */
+			rio_dprint(RIO_DEBUG_TTY, ("TCRIOXPOFF\n"));
+			if ( copyin( (int)arg, (caddr_t)PortP->Xprint.XpOff,
+						MAX_XP_CTRL_LEN)==COPYFAIL ) {
+				rio_dprint(RIO_DEBUG_TTY, ("Copyin failed\n"));
+				PortP->Xprint.XpOff[0] = '\0';
+				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+				pseterr(EFAULT);
+			}
+			PortP->Xprint.XpOff[MAX_XP_CTRL_LEN-1] = '\0';
+			PortP->Xprint.XpLen = RIOStrlen(PortP->Xprint.XpOn)+
+										RIOStrlen(PortP->Xprint.XpOff);
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return 0;
+
+		case TCRIOXPCPS: /* set Xprint CPS string */
+			rio_dprint(RIO_DEBUG_TTY, ("TCRIOXPCPS\n"));
+			if ( (uint)arg > p->RIOConf.MaxXpCps || 
+					(uint)arg < p->RIOConf.MinXpCps ) {
+				rio_dprint(RIO_DEBUG_TTY, ("%d CPS out of range\n",arg));
+				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+				pseterr(EINVAL);
+				return 0;
+			}
+			PortP->Xprint.XpCps = (uint)arg;
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return 0;
+
+		case TCRIOXPRINT:
+			rio_dprint(RIO_DEBUG_TTY, ("TCRIOXPRINT\n"));
+			if ( copyout((caddr_t)&PortP->Xprint, (int)arg,
+					sizeof(struct Xprint))==COPYFAIL ) {
+			        rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+				pseterr(EFAULT);
+			}
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return 0;
+
+		case TCRIOIXANYON:
+			rio_dprint(RIO_DEBUG_TTY, ("TCRIOIXANYON\n"));
+			PortP->Config |= RIO_IXANY;
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return 0;
+
+		case TCRIOIXANYOFF:
+			rio_dprint(RIO_DEBUG_TTY, ("TCRIOIXANYOFF\n"));
+			PortP->Config &= ~RIO_IXANY;
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return 0;
+
+		case TCRIOIXONON:
+			rio_dprint(RIO_DEBUG_TTY, ("TCRIOIXONON\n"));
+			PortP->Config |= RIO_IXON;
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return 0;
+
+		case TCRIOIXONOFF:
+			rio_dprint(RIO_DEBUG_TTY, ("TCRIOIXONOFF\n"));
+			PortP->Config &= ~RIO_IXON;
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return 0;
+
+/*
+** 15.10.1998 ARG - ESIL 0761 part fix
+** Added support for CTS and RTS flow control ioctls :
+*/
+		case TCRIOCTSFLOWEN:
+			rio_dprint(RIO_DEBUG_TTY, ("TCRIOCTSFLOWEN\n"));
+			PortP->Config |= RIO_CTSFLOW;
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP);	
+			return 0;
+
+		case TCRIOCTSFLOWDIS:
+			rio_dprint(RIO_DEBUG_TTY, ("TCRIOCTSFLOWDIS\n"));
+			PortP->Config &= ~RIO_CTSFLOW;
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP);	
+			return 0;
+
+		case TCRIORTSFLOWEN:
+			rio_dprint(RIO_DEBUG_TTY, ("TCRIORTSFLOWEN\n"));
+			PortP->Config |= RIO_RTSFLOW;
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP);	
+			return 0;
+
+		case TCRIORTSFLOWDIS:
+			rio_dprint(RIO_DEBUG_TTY, ("TCRIORTSFLOWDIS\n"));
+			PortP->Config &= ~RIO_RTSFLOW;
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP);	
+			return 0;
+
+/* end ESIL 0761 part fix */
+
+	}
+
+
+	/* Lynx IOCTLS */
+	switch (cmd) {
+		case TIOCSETP:
+		case TIOCSETN:
+		case OTIOCSETP:
+		case OTIOCSETN:
+			ioctl_processed++;
+			ttyseth(PortP, tp, (struct old_sgttyb *)arg);
+			break;
+		case TCSETA:
+		case TCSETAW:
+		case TCSETAF:
+			ioctl_processed++;
+			rio_dprint(RIO_DEBUG_TTY, ("NON POSIX ioctl\n"));
+			ttyseth_pv(PortP, tp, (struct termios *)arg, 0);
+			break;
+		case TCSETAP:	/* posix tcsetattr() */
+		case TCSETAWP:	/* posix tcsetattr() */
+		case TCSETAFP:	/* posix tcsetattr() */
+			rio_dprint(RIO_DEBUG_TTY, ("NON POSIX SYSV ioctl\n"));
+			ttyseth_pv(PortP, tp, (struct termios *)arg, 1);
+			ioctl_processed++;
+			break;
+	}
+
+	/*
+	** If its any of the commands that require the port to be in the
+	** non-busy state wait until all output has drained 
+	*/
+	if (!ioctl_processed)
+	switch(cmd) {
+		case TCSETAW:
+		case TCSETAF:
+		case TCSETA:
+		case TCSBRK:
+#define OLD_POSIX ('x' << 8)
+#define OLD_POSIX_SETA (OLD_POSIX | 2)
+#define OLD_POSIX_SETAW (OLD_POSIX | 3)
+#define OLD_POSIX_SETAF (OLD_POSIX | 4)
+#define NEW_POSIX (('i' << 24) | ('X' << 16))
+#define NEW_POSIX_SETA (NEW_POSIX | 2)
+#define NEW_POSIX_SETAW (NEW_POSIX | 3)
+#define NEW_POSIX_SETAF (NEW_POSIX | 4)
+		case OLD_POSIX_SETA:
+		case OLD_POSIX_SETAW:
+		case OLD_POSIX_SETAF:
+		case NEW_POSIX_SETA:
+		case NEW_POSIX_SETAW:
+		case NEW_POSIX_SETAF:
+#ifdef TIOCSETP
+		case TIOCSETP:
+#endif
+		case TIOCSETD:
+		case TIOCSETN:
+			rio_dprint(RIO_DEBUG_TTY, ("wait for non-BUSY, semaphore set\n"));
+			/*
+			** Wait for drain here, at least as far as the double buffer
+			** being empty.
+			*/
+			/* XXX Does the above comment mean that this has
+			   still to be implemented? -- REW */
+			/* XXX Is the locking OK together with locking
+                           in txenable? (Deadlock?) -- REW */
+			
+			RIOTxEnable((char *)PortP);
+			break;
+		default:
+			break;
+	}
+
+	old_cflag = tp->tm.c_cflag;
+	old_iflag = tp->tm.c_iflag;
+	old_oflag = tp->tm.c_oflag;
+	oldcook = PortP->CookMode;
+
+	if ( p->RIOHalted ) {
+		RIOClearUp( PortP );
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		pseterr(EIO);
+		return 0;
+	}
+
+	PortP->FlushCmdBodge = 0;
+
+	/*
+	** If the port is locked, and it is reconfigured, we want
+	** to restore the state of the tty structure so the change is NOT
+	** made.
+	*/
+	if (PortP->Lock) {
+		tp->tm.c_iflag = PortP->StoredTty.iflag;
+		tp->tm.c_oflag = PortP->StoredTty.oflag;
+		tp->tm.c_cflag = PortP->StoredTty.cflag;
+		tp->tm.c_lflag = PortP->StoredTty.lflag;
+		tp->tm.c_line = PortP->StoredTty.line;
+		for (i = 0; i < NCC + 1; i++)
+			tp->tm.c_cc[i] = PortP->StoredTty.cc[i];
+	}
+	else {
+		/*
+		** If the port is set to store the parameters, and it is
+		** reconfigured, we want to save the current tty struct so it
+		** may be restored on the next open.
+		*/
+		if (PortP->Store) {
+			PortP->StoredTty.iflag = tp->tm.c_iflag;
+			PortP->StoredTty.oflag = tp->tm.c_oflag;
+			PortP->StoredTty.cflag = tp->tm.c_cflag;
+			PortP->StoredTty.lflag = tp->tm.c_lflag;
+			PortP->StoredTty.line = tp->tm.c_line;
+			for (i = 0; i < NCC + 1; i++)
+				PortP->StoredTty.cc[i] = tp->tm.c_cc[i];
+		}
+	}
+
+	changed = (tp->tm.c_cflag != old_cflag) ||
+				(tp->tm.c_iflag != old_iflag) ||
+				(tp->tm.c_oflag != old_oflag);
+
+	PortP->CookMode = RIOCookMode(tp);	/* Set new cooking mode */
+
+	rio_dprint(RIO_DEBUG_TTY, ("RIOIoctl changed %d newcook %d oldcook %d\n",
+			changed,PortP->CookMode,oldcook));
+
+#ifdef MODEM_SUPPORT
+	/*
+	** kludge to force CARR_ON if CLOCAL set
+	*/
+	if ((tp->tm.c_cflag & CLOCAL) || (PortP->ModemState & MSVR1_CD))	{
+		tp->tm.c_state |= CARR_ON;
+		wakeup ((caddr_t)&tp->tm.c_canq);
+	}
+#endif
+
+	if ( p->RIOHalted ) {
+		RIOClearUp( PortP );
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		pseterr(EIO);
+		return 0;
+	}
+	/*
+	** Re-configure if modes or cooking have changed
+	*/
+	if (changed || oldcook != PortP->CookMode || (ioctl_processed)) {
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		rio_dprint(RIO_DEBUG_TTY, ("Ioctl changing the PORT settings\n"));
+		RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP);	
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+	}
+
+	if (p->RIOHalted) {
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		RIOClearUp( PortP );
+		pseterr(EIO);
+		return 0;
+	}
+	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	return 0;
+}
+
+/*
+	ttyseth -- set hardware dependant tty settings
+*/
+void
+ttyseth(PortP, s, sg)
+struct Port *		PortP;
+struct ttystatics *		s;
+struct old_sgttyb *sg;
+{
+	struct old_sgttyb *	tsg;
+	struct termios *tp = &s->tm;
+
+	tsg = &s->sg;
+
+	if (sg->sg_flags & (EVENP|ODDP))  {
+		tp->c_cflag &= PARENB;
+		if (sg->sg_flags & EVENP) {
+			if (sg->sg_flags & ODDP) {
+				tp->c_cflag &= V_CS7;
+				tp->c_cflag &= ~PARENB;
+			}
+			else {
+				tp->c_cflag &= V_CS7;
+				tp->c_cflag &= PARENB;
+				tp->c_cflag &= PARODD;
+			}
+		}
+		else if (sg->sg_flags & ODDP) {
+			tp->c_cflag &= V_CS7;
+			tp->c_cflag &= PARENB;
+			tp->c_cflag &= PARODD;
+		}
+		else {
+			tp->c_cflag &= V_CS7;
+			tp->c_cflag &= PARENB;
+		}
+	}
+/*
+ * Use ispeed as the desired speed.  Most implementations don't handle 
+ * separate input and output speeds very well. If the RIO handles this, 
+ * I will have to use separate sets of flags to store them in the 
+ * Port structure.
+ */
+	if ( !sg->sg_ospeed )
+		sg->sg_ospeed = sg->sg_ispeed;
+	else
+		sg->sg_ispeed = sg->sg_ospeed;
+	if (sg->sg_ispeed > V_EXTB ) 
+		sg->sg_ispeed = V_EXTB;
+	if (sg->sg_ispeed < V_B0)
+		sg->sg_ispeed = V_B0;
+	*tsg = *sg;
+   tp->c_cflag = (tp->c_cflag & ~V_CBAUD) | conv_bv[(int)sg->sg_ispeed];
+}
+
+/*
+	ttyseth_pv -- set hardware dependant tty settings using either the
+			POSIX termios structure or the System V termio structure.
+				sysv = 0 => (POSIX):	 struct termios *sg
+				sysv != 0 => (System V): struct termio *sg
+*/
+static void
+ttyseth_pv(PortP, s, sg, sysv)
+struct Port *PortP;
+struct ttystatics *s;
+struct termios *sg;
+int sysv;
+{
+    int speed;
+    unsigned char csize;
+    unsigned char cread;
+    unsigned int lcr_flags;
+    int ps;
+ 
+    if (sysv) {
+        /* sg points to a System V termio structure */
+        csize = ((struct termio *)sg)->c_cflag & CSIZE;
+        cread = ((struct termio *)sg)->c_cflag & CREAD;
+        speed = conv_vb[((struct termio *)sg)->c_cflag & V_CBAUD];
+    }
+    else {
+        /* sg points to a POSIX termios structure */
+        csize = sg->c_cflag & CSIZE;
+        cread = sg->c_cflag & CREAD;
+        speed = conv_vb[sg->c_cflag & V_CBAUD];
+    }
+    if (s->sg.sg_ispeed != speed || s->sg.sg_ospeed != speed) {
+        s->sg.sg_ispeed = speed;
+        s->sg.sg_ospeed = speed;
+        s->tm.c_cflag = (s->tm.c_cflag & ~V_CBAUD) |
+                         conv_bv[(int)s->sg.sg_ispeed];
+    }
+}
+#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/riotypes.h linux.15p9/drivers/char/rio/riotypes.h
--- linux.vanilla/drivers/char/rio/riotypes.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/riotypes.h	Tue Jan 18 00:52:10 2000
@@ -0,0 +1,135 @@
+/****************************************************************************
+ *******                                                              *******
+ *******                      R I O T Y P E S
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Jon Brawn
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _riotypes_h
+#define _riotypes_h 1
+
+#ifdef SCCS_LABELS
+#ifndef lint
+/* static char *_rio_riotypes_h_sccs = "@(#)riotypes.h	1.10"; */
+#endif
+#endif
+
+#ifdef INKERNEL
+
+#if !defined(MIPSAT)
+typedef unsigned short NUMBER_ptr;
+typedef unsigned short WORD_ptr;
+typedef unsigned short BYTE_ptr;
+typedef unsigned short char_ptr;
+typedef unsigned short Channel_ptr;
+typedef unsigned short FREE_LIST_ptr_ptr;
+typedef unsigned short FREE_LIST_ptr;
+typedef unsigned short LPB_ptr;
+typedef unsigned short Process_ptr;
+typedef unsigned short PHB_ptr;
+typedef unsigned short PKT_ptr;
+typedef unsigned short PKT_ptr_ptr;
+typedef unsigned short Q_BUF_ptr;
+typedef unsigned short Q_BUF_ptr_ptr;
+typedef unsigned short ROUTE_STR_ptr;
+typedef unsigned short RUP_ptr;
+typedef unsigned short short_ptr;
+typedef unsigned short u_short_ptr;
+typedef unsigned short ushort_ptr;
+#else
+/* MIPSAT types */
+typedef char RIO_POINTER[8];
+typedef RIO_POINTER NUMBER_ptr;
+typedef RIO_POINTER WORD_ptr;
+typedef RIO_POINTER BYTE_ptr;
+typedef RIO_POINTER char_ptr;
+typedef RIO_POINTER Channel_ptr;
+typedef RIO_POINTER FREE_LIST_ptr_ptr;
+typedef RIO_POINTER FREE_LIST_ptr;
+typedef RIO_POINTER LPB_ptr;
+typedef RIO_POINTER Process_ptr;
+typedef RIO_POINTER PHB_ptr;
+typedef RIO_POINTER PKT_ptr;
+typedef RIO_POINTER PKT_ptr_ptr;
+typedef RIO_POINTER Q_BUF_ptr;
+typedef RIO_POINTER Q_BUF_ptr_ptr;
+typedef RIO_POINTER ROUTE_STR_ptr;
+typedef RIO_POINTER RUP_ptr;
+typedef RIO_POINTER short_ptr;
+typedef RIO_POINTER u_short_ptr;
+typedef RIO_POINTER ushort_ptr;
+#endif
+
+#else /* not INKERNEL */
+typedef unsigned char   BYTE;
+typedef unsigned short  WORD;
+typedef unsigned long   DWORD;
+typedef short           NUMBER;
+typedef short           *NUMBER_ptr;
+typedef unsigned short  *WORD_ptr;
+typedef unsigned char   *BYTE_ptr;
+typedef unsigned char   uchar ;
+typedef unsigned short  ushort ;
+typedef unsigned int    uint ;
+typedef unsigned long   ulong ;
+typedef unsigned char   u_char ;
+typedef unsigned short  u_short ;
+typedef unsigned int    u_int ;
+typedef unsigned long   u_long ;
+typedef unsigned short  ERROR ;
+typedef unsigned long ID ;
+typedef char             *char_ptr;
+typedef Channel          *Channel_ptr;
+typedef struct FREE_LIST *FREE_LIST_ptr;
+typedef struct FREE_LIST **FREE_LIST_ptr_ptr;
+typedef struct LPB       *LPB_ptr;
+typedef struct Process   *Process_ptr;
+typedef struct PHB       *PHB_ptr;
+typedef struct PKT       *PKT_ptr;
+typedef struct PKT       **PKT_ptr_ptr;
+typedef struct Q_BUF     *Q_BUF_ptr;
+typedef struct Q_BUF     **Q_BUF_ptr_ptr;
+typedef struct ROUTE_STR *ROUTE_STR_ptr;
+typedef struct RUP       *RUP_ptr;
+typedef short            *short_ptr;
+typedef u_short          *u_short_ptr;
+typedef ushort           *ushort_ptr;
+typedef struct PKT	 PKT;
+typedef struct LPB	 LPB;
+typedef struct RUP	 RUP;
+#endif
+
+
+#endif /* __riotypes__ */
+
+/*********** end of file ***********/
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/riowinif.h linux.15p9/drivers/char/rio/riowinif.h
--- linux.vanilla/drivers/char/rio/riowinif.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/riowinif.h	Tue Jan 18 00:52:11 2000
@@ -0,0 +1,1335 @@
+/************************************************************************/
+/*									*/
+/*	Title		:	RIO Shared Memory Window Inteface	*/
+/*									*/
+/*	Author		:	N.P.Vassallo				*/
+/*									*/
+/*	Creation	:	7th June 1999				*/
+/*									*/
+/*	Version		:	1.0.0					*/
+/*									*/
+/*	Copyright	:	(c) Specialix International Ltd. 1999	*
+ *      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.
+ *									*/
+/*	Description	:	Prototypes, structures and definitions	*/
+/*				describing RIO host card shared	memory	*/
+/*				window interface structures:		*/
+/*					PARMMAP				*/
+/*					RUP				*/
+/*					PHB				*/
+/*					LPB				*/
+/*					PKT				*/
+/*									*/
+/************************************************************************/
+
+/* History...
+
+1.0.0	07/06/99 NPV	Creation. (based on PARMMAP.H)
+
+*/
+
+#ifndef	_riowinif_h				/* If RIOWINDIF.H not already defined */
+#define	_riowinif_h    1
+
+/*****************************************************************************
+********************************             *********************************
+********************************   General   *********************************
+********************************             *********************************
+*****************************************************************************/
+
+#define	TPNULL		((_u16)(0x8000))
+
+/*****************************************************************************
+********************************              ********************************
+********************************   PARM_MAP   ********************************
+********************************              ********************************
+*****************************************************************************/
+
+/* The PARM_MAP structure defines global values relating to the Host Card / RTA
+   and is the main structure from which all other structures are referenced. */
+
+typedef	struct	_PARM_MAP
+{
+	_u16	phb_ptr;		/* 0x00 Pointer to the PHB array */
+	_u16	phb_num_ptr;		/* 0x02 Ptr to Number of PHB's */
+	_u16	free_list;		/* 0x04 Free List pointer */
+	_u16	free_list_end;		/* 0x06 Free List End pointer */
+	_u16	q_free_list_ptr;	/* 0x08 Ptr to Q_BUF variable */
+	_u16	unit_id_ptr;		/* 0x0A Unit Id */
+	_u16	link_str_ptr;		/* 0x0C Link Structure Array */
+	_u16	bootloader_1;		/* 0x0E 1st Stage Boot Loader */
+	_u16	bootloader_2;		/* 0x10 2nd Stage Boot Loader */
+	_u16	port_route_map_ptr;	/* 0x12 Port Route Map */
+	_u16	route_ptr;		/* 0x14 Route Map */
+	_u16	map_present;		/* 0x16 Route Map present */
+	_u16	pkt_num;		/* 0x18 Total number of packets */
+	_u16	q_num;			/* 0x1A Total number of Q packets */
+	_u16	buffers_per_port;	/* 0x1C Number of buffers per port */
+	_u16	heap_size;		/* 0x1E Initial size of heap */
+	_u16	heap_left;		/* 0x20 Current Heap left */
+	_u16	error;			/* 0x22 Error code */
+	_u16	tx_max;			/* 0x24 Max number of tx pkts per phb */
+	_u16	rx_max;			/* 0x26 Max number of rx pkts per phb */
+	_u16	rx_limit;		/* 0x28 For high / low watermarks */
+	_u16	links;			/* 0x2A Links to use */
+	_u16	timer;			/* 0x2C Interrupts per second */
+	_u16	rups;			/* 0x2E Pointer to the RUPs */
+	_u16	max_phb;		/* 0x30 Mostly for debugging */
+	_u16	living;			/* 0x32 Just increments!! */
+	_u16	init_done;		/* 0x34 Initialisation over */
+	_u16	booting_link;		/* 0x36 */
+	_u16	idle_count;		/* 0x38 Idle time counter */
+	_u16	busy_count;		/* 0x3A Busy counter */
+	_u16	idle_control;		/* 0x3C Control Idle Process */
+	_u16	tx_intr;		/* 0x3E TX interrupt pending */
+	_u16	rx_intr;		/* 0x40 RX interrupt pending */
+	_u16	rup_intr;		/* 0x42 RUP interrupt pending */
+
+} PARM_MAP;
+
+/* Same thing again, but defined as offsets... */
+
+#define	PM_phb_ptr		0x00	/* 0x00 Pointer to the PHB array */
+#define	PM_phb_num_ptr		0x02	/* 0x02 Ptr to Number of PHB's */
+#define	PM_free_list		0x04	/* 0x04 Free List pointer */
+#define	PM_free_list_end	0x06	/* 0x06 Free List End pointer */
+#define	PM_q_free_list_ptr	0x08	/* 0x08 Ptr to Q_BUF variable */
+#define	PM_unit_id_ptr		0x0A	/* 0x0A Unit Id */
+#define	PM_link_str_ptr		0x0C	/* 0x0C Link Structure Array */
+#define	PM_bootloader_1		0x0E	/* 0x0E 1st Stage Boot Loader */
+#define	PM_bootloader_2		0x10	/* 0x10 2nd Stage Boot Loader */
+#define	PM_port_route_map_ptr	0x12	/* 0x12 Port Route Map */
+#define	PM_route_ptr		0x14	/* 0x14 Route Map */
+#define	PM_map_present		0x16	/* 0x16 Route Map present */
+#define	PM_pkt_num		0x18	/* 0x18 Total number of packets */
+#define	PM_q_num		0x1A	/* 0x1A Total number of Q packets */
+#define	PM_buffers_per_port	0x1C	/* 0x1C Number of buffers per port */
+#define	PM_heap_size		0x1E	/* 0x1E Initial size of heap */
+#define	PM_heap_left		0x20	/* 0x20 Current Heap left */
+#define	PM_error		0x22	/* 0x22 Error code */
+#define	PM_tx_max		0x24	/* 0x24 Max number of tx pkts per phb */
+#define	PM_rx_max		0x26	/* 0x26 Max number of rx pkts per phb */
+#define	PM_rx_limit		0x28	/* 0x28 For high / low watermarks */
+#define	PM_links		0x2A	/* 0x2A Links to use */
+#define	PM_timer		0x2C	/* 0x2C Interrupts per second */
+#define	PM_rups			0x2E	/* 0x2E Pointer to the RUPs */
+#define	PM_max_phb		0x30	/* 0x30 Mostly for debugging */
+#define	PM_living		0x32	/* 0x32 Just increments!! */
+#define	PM_init_done		0x34	/* 0x34 Initialisation over */
+#define	PM_booting_link		0x36	/* 0x36 */
+#define	PM_idle_count		0x38	/* 0x38 Idle time counter */
+#define	PM_busy_count		0x3A	/* 0x3A Busy counter */
+#define	PM_idle_control		0x3C	/* 0x3C Control Idle Process */
+#define	PM_tx_intr		0x3E	/* 0x4E TX interrupt pending */
+#define	PM_rx_intr		0x40	/* 0x40 RX interrupt pending */
+#define	PM_rup_intr		0x42	/* 0x42 RUP interrupt pending */
+#define	sizeof_PARM_MAP		0x44	/* structure size = 0x44 */
+
+/* PARM_MAP.error definitions... */
+#define	E_NO_ERROR		0x00
+#define	E_PROCESS_NOT_INIT	0x01
+#define	E_LINK_TIMEOUT		0x02
+#define	E_NO_ROUTE		0x03
+#define	E_CONFUSED		0x04
+#define	E_HOME			0x05
+#define	E_CSUM_FAIL		0x06
+#define	E_DISCONNECTED		0x07
+#define	E_BAD_RUP		0x08
+#define	E_NO_VIRGIN		0x09
+#define	E_BOOT_RUP_BUSY		0x10
+#define	E_CHANALLOC		0x80
+#define	E_POLL_ALLOC		0x81
+#define	E_LTTWAKE		0x82
+#define	E_LTT_ALLOC		0x83
+#define	E_LRT_ALLOC		0x84
+#define	E_CIRRUS		0x85
+#define	E_MONITOR		0x86
+#define	E_PHB_ALLOC		0x87
+#define	E_ARRAY_ALLOC		0x88
+#define	E_QBUF_ALLOC		0x89
+#define	E_PKT_ALLOC		0x8a
+#define	E_GET_TX_Q_BUF		0x8b
+#define	E_GET_RX_Q_BUF		0x8c
+#define	E_MEM_OUT		0x8d
+#define	E_MMU_INIT		0x8e
+#define	E_LTT_INIT		0x8f
+#define	E_LRT_INIT		0x90
+#define	E_LINK_RUN		0x91
+#define	E_MONITOR_ALLOC		0x92
+#define	E_MONITOR_INIT		0x93
+#define	E_POLL_INIT		0x94
+
+/* PARM_MAP.links definitions... */
+#define	RIO_LINK_ENABLE	0x80FF
+
+/*****************************************************************************
+**********************************         ***********************************
+**********************************   RUP   ***********************************
+**********************************         ***********************************
+*****************************************************************************/
+
+/* The RUP (Remote Unit Port) structure relates to the Remote Terminal Adapters
+   attached to the system and there is normally an array of MAX_RUPS (=16) structures
+   in a host card, defined by PARM_MAP->rup. */
+
+typedef	struct	_RUP
+{
+	_u16		txpkt;			/* 0x00 Outgoing packet */
+	_u16		rxpkt;			/* 0x02 ncoming packet */
+	_u16		link;			/* 0x04 Which link to send packet down ? */
+	_u8		rup_dest_unit[2];	/* 0x06 Destination Unit */
+	_u16		handshake;		/* 0x08 Handshaking */
+	_u16		timeout;		/* 0x0A Timeout */
+	_u16		status;			/* 0x0C Status */
+	_u16		txcontrol;		/* 0x0E Transmit control */
+	_u16		rxcontrol;		/* 0x10 Receive control */
+
+} RUP;
+
+/* Same thing again, but defined as offsets... */
+
+#define	RUP_txpkt		0x00		/* 0x00 Outgoing packet */
+#define	RUP_rxpkt		0x02		/* 0x02 Incoming packet */
+#define	RUP_link		0x04		/* 0x04 Which link to send packet down ? */
+#define	RUP_rup_dest_unit	0x06		/* 0x06 Destination Unit */
+#define	RUP_handshake		0x08		/* 0x08 Handshaking */
+#define	RUP_timeout		0x0A		/* 0x0A Timeout */
+#define	RUP_status		0x0C		/* 0x0C Status */
+#define	RUP_txcontrol		0x0E		/* 0x0E Transmit control */
+#define	RUP_rxcontrol		0x10		/* 0x10 Receive control */
+#define	sizeof_RUP		0x12		/* structure size = 0x12 */
+
+#define MAX_RUP			16
+
+/* RUP.txcontrol definitions... */
+#define	TX_RUP_INACTIVE		0		/* Nothing to transmit */
+#define	TX_PACKET_READY		1		/* Transmit packet ready */
+#define	TX_LOCK_RUP		2		/* Transmit side locked */
+
+/* RUP.txcontrol definitions... */
+#define	RX_RUP_INACTIVE		0		/* Nothing received */
+#define	RX_PACKET_READY		1		/* Packet received */
+
+#define	RUP_NO_OWNER		0xFF		/* RUP not owned by any process */
+
+/*****************************************************************************
+**********************************         ***********************************
+**********************************   PHB   ***********************************
+**********************************         ***********************************
+*****************************************************************************/
+
+/* The PHB (Port Header Block) structure relates to the serial ports attached
+   to the system and there is normally an array of MAX_PHBS (=128) structures
+   in a host card, defined by PARM_MAP->phb_ptr and PARM_MAP->phb_num_ptr. */
+
+typedef	struct	_PHB
+{
+	_u16		source;			/* 0x00 Location of the PHB in the host card */
+	_u16		handshake;		/* 0x02 Used to manage receive packet flow control */
+	_u16		status;			/* 0x04 Internal port transmit/receive status */
+	_u16		timeout;		/* 0x06 Time period to wait for an ACK */
+	_u16		link;			/* 0x08 The host link associated with the PHB */
+	_u16		destination;		/* 0x0A Location of the remote port on the network */
+
+	_u16		tx_start;		/* 0x0C first entry in the packet array for transmit packets */
+	_u16		tx_end;			/* 0x0E last entry in the packet array for transmit packets */
+	_u16		tx_add;			/* 0x10 position in the packet array for new transmit packets */
+	_u16		tx_remove;		/* 0x12 current position in the packet pointer array */
+
+	_u16		rx_start;		/* 0x14 first entry in the packet array for receive packets */
+	_u16		rx_end;			/* 0x16 last entry in the packet array for receive packets */
+	_u16		rx_add;			/* 0x18 position in the packet array for new receive packets */
+	_u16		rx_remove;		/* 0x1A current position in the packet pointer array */
+
+} PHB;
+
+/* Same thing again, but defined as offsets... */
+
+#define	PHB_source		0x00		/* 0x00 Location of the PHB in the host card */
+#define	PHB_handshake		0x02		/* 0x02 Used to manage receive packet flow control */
+#define	PHB_status		0x04		/* 0x04 Internal port transmit/receive status */
+#define	PHB_timeout		0x06		/* 0x06 Time period to wait for an ACK */
+#define	PHB_link		0x08		/* 0x08 The host link associated with the PHB */
+#define	PHB_destination		0x0A		/* 0x0A Location of the remote port on the network */
+#define	PHB_tx_start		0x0C		/* 0x0C first entry in the packet array for transmit packets */
+#define	PHB_tx_end		0x0E		/* 0x0E last entry in the packet array for transmit packets */
+#define	PHB_tx_add		0x10		/* 0x10 position in the packet array for new transmit packets */
+#define	PHB_tx_remove		0x12		/* 0x12 current position in the packet pointer array */
+#define	PHB_rx_start		0x14		/* 0x14 first entry in the packet array for receive packets */
+#define	PHB_rx_end		0x16		/* 0x16 last entry in the packet array for receive packets */
+#define	PHB_rx_add		0x18		/* 0x18 position in the packet array for new receive packets */
+#define	PHB_rx_remove		0x1A		/* 0x1A current position in the packet pointer array */
+#define	sizeof_PHB		0x1C		/* structure size = 0x1C */
+
+/* PHB.handshake definitions... */
+#define	PHB_HANDSHAKE_SET	0x0001		/* Set by LRT */
+#define	PHB_HANDSHAKE_RESET	0x0002		/* Set by ISR / driver */
+#define	PHB_HANDSHAKE_FLAGS	(PHB_HANDSHAKE_RESET|PHB_HANDSHAKE_SET)
+						/* Reset by ltt */
+
+#define	MAX_PHB			128		/* range 0-127 */
+
+/*****************************************************************************
+**********************************         ***********************************
+**********************************   LPB   ***********************************
+**********************************         ***********************************
+*****************************************************************************/
+
+/* The LPB (Link Parameter Block) structure relates to a RIO Network Link
+   and there is normally an array of MAX_LINKS (=4) structures in a host card,
+   defined by PARM_MAP->link_str_ptr. */
+
+typedef	struct	_LPB
+{
+	_u16		link_number;		/* 0x00 Link Number */
+	_u16		in_ch;			/* 0x02 Link In Channel */
+	_u16		out_ch;			/* 0x04 Link Out Channel */
+	_u8		attached_serial[4];	/* 0x06 Attached serial number */
+	_u8		attached_host_serial[4];/* 0x0A Serial number of Host who booted other end */
+	_u16		descheduled;		/* 0x0E Currently Descheduled */
+	_u16		state;			/* 0x10 Current state */
+	_u16		send_poll;		/* 0x12 Send a Poll Packet */
+	_u16		ltt_p;			/* 0x14 Process Descriptor */
+	_u16		lrt_p;			/* 0x16 Process Descriptor */
+	_u16		lrt_status;		/* 0x18 Current lrt status */
+	_u16		ltt_status;		/* 0x1A Current ltt status */
+	_u16		timeout;		/* 0x1C Timeout value */
+	_u16		topology;		/* 0x1E Topology bits */
+	_u16		mon_ltt;		/* 0x20 */
+	_u16		mon_lrt;		/* 0x22 */
+	_u16		num_pkts;		/* 0x24 */
+	_u16		add_packet_list;	/* 0x26 Add packets to here */
+	_u16		remove_packet_list;	/* 0x28 Send packets from here */
+
+	_u16		lrt_fail_chan;		/* 0x2A Lrt's failure channel */
+	_u16		ltt_fail_chan;		/* 0x2C Ltt's failure channel */
+
+	RUP		rup;			/* 0x2E RUP structure for HOST to driver comms */
+	RUP		link_rup;		/* 0x40 RUP for the link (POLL, topology etc.) */
+	_u16		attached_link;		/* 0x52 Number of attached link */
+	_u16		csum_errors;		/* 0x54 csum errors */
+	_u16		num_disconnects;	/* 0x56 number of disconnects */
+	_u16		num_sync_rcvd;		/* 0x58 # sync's received */
+	_u16		num_sync_rqst;		/* 0x5A # sync requests */
+	_u16		num_tx;			/* 0x5C Num pkts sent */
+	_u16		num_rx;			/* 0x5E Num pkts received */
+	_u16		module_attached;	/* 0x60 Module tpyes of attached */
+	_u16		led_timeout;		/* 0x62 LED timeout */
+	_u16		first_port;		/* 0x64 First port to service */
+	_u16		last_port;		/* 0x66 Last port to service */
+
+} LPB;
+
+/* Same thing again, but defined as offsets... */
+
+#define	LPB_link_number		0x00		/* 0x00 Link Number */
+#define	LPB_in_ch		0x02		/* 0x02 Link In Channel */
+#define	LPB_out_ch		0x04		/* 0x04 Link Out Channel */
+#define	LPB_attached_serial	0x06		/* 0x06 Attached serial number */
+#define	LPB_attached_host_serial 0x0A		/* 0x0A Serial number of Host who booted other end */
+#define	LPB_descheduled		0x0E		/* 0x0E Currently Descheduled */
+#define	LPB_state		0x10		/* 0x10 Current state */
+#define	LPB_send_poll		0x12		/* 0x12 Send a Poll Packet */
+#define	LPB_ltt_p		0x14		/* 0x14 Process Descriptor */
+#define	LPB_lrt_p		0x16		/* 0x16 Process Descriptor */
+#define	LPB_lrt_status		0x18		/* 0x18 Current lrt status */
+#define	LPB_ltt_status		0x1A		/* 0x1A Current ltt status */
+#define	LPB_timeout		0x1C		/* 0x1C Timeout value */
+#define	LPB_topology		0x1E		/* 0x1E Topology bits */
+#define	LPB_mon_ltt		0x20		/* 0x20 */
+#define	LPB_mon_lrt		0x22		/* 0x22 */
+#define	LPB_num_pkts		0x24		/* 0x24 */
+#define	LPB_add_packet_list	0x26		/* 0x26 Add packets to here */
+#define	LPB_remove_packet_list	0x28		/* 0x28 Send packets from here */
+#define	LPB_lrt_fail_chan	0x2A		/* 0x2A Lrt's failure channel */
+#define	LPB_ltt_fail_chan	0x2C		/* 0x2C Ltt's failure channel */
+#define	LPB_rup			0x2E		/* 0x2E RUP structure for HOST to driver comms */
+#define	LPB_link_rup		0x40		/* 0x40 RUP for the link (POLL, topology etc.) */
+#define	LPB_attached_link	0x52		/* 0x52 Number of attached link */
+#define	LPB_csum_errors		0x54		/* 0x54 csum errors */
+#define	LPB_num_disconnects	0x56		/* 0x56 number of disconnects */
+#define	LPB_num_sync_rcvd	0x58		/* 0x58 # sync's received */
+#define	LPB_num_sync_rqst	0x5A		/* 0x5A # sync requests */
+#define	LPB_num_tx		0x5C		/* 0x5C Num pkts sent */
+#define	LPB_num_rx		0x5E		/* 0x5E Num pkts received */
+#define	LPB_module_attached	0x60		/* 0x60 Module tpyes of attached */
+#define	LPB_led_timeout		0x62		/* 0x62 LED timeout */
+#define	LPB_first_port		0x64		/* 0x64 First port to service */
+#define	LPB_last_port		0x66		/* 0x66 Last port to service */
+#define	sizeof_LPB		0x68		/* structure size = 0x68 */
+
+#define	LINKS_PER_UNIT		4		/* number of links from a host */
+
+/*****************************************************************************
+********************************               *******************************
+********************************   FREE_LIST   *******************************
+********************************               *******************************
+*****************************************************************************/
+
+/* Used to overlay packet headers when allocating/freeing packets from the free list */
+
+typedef	struct	_FREE_LIST
+{
+	_u16		next;			/* 0x00 offset of next list item */
+	_u16		prev;			/* 0x02 offset of previous list item */
+
+} FREE_LIST;
+
+/* Same thing again, but defined as offsets... */
+
+#define	FL_next			0x00		/* 0x00 offset of next list item */
+#define	FL_prev			0x02		/* 0x02 offset of previous list item */
+
+/*****************************************************************************
+**********************************         ***********************************
+**********************************   PKT   ***********************************
+**********************************         ***********************************
+*****************************************************************************/
+
+/* The PKT is the main unit of communication between Host Cards and RTAs across
+   the RIO network.  */
+
+#define PKT_MAX_DATA_LEN   72			/* Size of packet data */
+
+typedef	struct	_PKT
+{
+	_u8		dest_unit;		/* 0x00 Destination Unit Id */
+	_u8		dest_port;		/* 0x01 Destination Port */
+	_u8		src_unit;		/* 0x02 Source Unit Id */
+	_u8		src_port;		/* 0x03 Source Port */
+	_u8		len;			/* 0x04 Length (in bytes) of data field */
+	_u8		control;		/* 0x05 */
+	_u8		data[PKT_MAX_DATA_LEN];	/* 0x06 Actual data */
+	_u16		csum;			/* 0x4E C-SUM */
+
+} PKT;
+
+/* Same thing again, but defined as offsets... */
+
+#define	PKT_dest_unit		0x00		/* 0x00 Destination Unit Id */
+#define	PKT_dest_port		0x01		/* 0x01 Destination Port */
+#define	PKT_src_unit		0x02		/* 0x02 Source Unit Id */
+#define	PKT_src_port		0x03		/* 0x03 Source Port */
+#define	PKT_len			0x04		/* 0x04 Length (in bytes) of data field */
+#define	PKT_control		0x05		/* 0x05 */
+#define	PKT_data		0x06		/* 0x06 Actual data */
+#define	PKT_csum		0x4E		/* 0x4E C-SUM */
+#define	sizeof_PKT		0x50		/* structure size = 0x50 */
+
+/* PKT.len definitions... */
+#define	PKT_CMD_BIT		0x80
+#define	PKT_CMD_DATA		0x80
+#define	PKT_LEN_MASK		0x7F
+
+/* PKT.control definitions... */
+#define	PKT_ACK			0x40
+#define	PKT_TGL			0x20
+#define	DATA_WNDW		0x10
+#define	PKT_TTL_MASK		0x0F
+#define	MAX_TTL			0x0F
+
+/*****************************************************************************
+*****************************                     ****************************
+*****************************   Control Packets   ****************************
+*****************************                     ****************************
+*****************************************************************************/
+
+/* The following definitions and structures define the control packets sent
+   between the driver and RIO Ports, RTAs and Host Cards. */
+
+#define	PRE_EMPTIVE		0x80			/* Pre-emptive command (sent via port's RUP) */
+
+/* "in-band" and "pre-emptive" port commands... */
+#define	OPEN			0x00			/* Driver->RIO Open a port */
+#define	CONFIG			0x01			/* Driver->RIO Configure a port */
+#define	MOPEN			0x02			/* Driver->RIO Modem open (wait for DCD) */
+#define	CLOSE			0x03			/* Driver->RIO Close a port */
+#define	WFLUSH			(0x04|PRE_EMPTIVE)	/* Driver->RIO Write flush */
+#define	RFLUSH			(0x05|PRE_EMPTIVE)	/* Driver->RIO Read flush */
+#define	RESUME			(0x06|PRE_EMPTIVE)	/* Driver->RIO Behave as if XON received */
+#define	SBREAK			0x07			/* Driver->RIO Start break */
+#define	EBREAK			0x08			/* Driver->RIO End break */
+#define	SUSPEND			(0x09|PRE_EMPTIVE)	/* Driver->RIO Behave as if XOFF received */
+#define	FCLOSE			(0x0A|PRE_EMPTIVE)	/* Driver->RIO Force close */
+#define	XPRINT			0x0B			/* Driver->RIO Xprint packet */
+#define	MBIS			(0x0C|PRE_EMPTIVE)	/* Driver->RIO Set modem lines */
+#define	MBIC			(0x0D|PRE_EMPTIVE)	/* Driver->RIO Clear modem lines */
+#define	MSET			(0x0E|PRE_EMPTIVE)	/* Driver->RIO Set modem lines */
+#define	PCLOSE			0x0F			/* Driver->RIO Pseudo close */
+#define	MGET			(0x10|PRE_EMPTIVE)	/* Driver->RIO Force update of modem status */
+#define	MEMDUMP			(0x11|PRE_EMPTIVE)	/* Driver->RIO DEBUG request for RTA memory */
+#define	READ_REGISTER		(0x12|PRE_EMPTIVE)	/* Driver->RIO DEBUG read CD1400 register */
+
+/* Remote Unit Port (RUP) packet definitions... (specified in PKT.dest_unit and PKT.src_unit) */
+#define	SYNC_RUP		0xFF			/* Download internal */
+#define	COMMAND_RUP		0xFE			/* Command ack/status */
+#define	ERROR_RUP		0xFD			/* Download internal */
+#define	POLL_RUP		0xFC			/* Download internal */
+#define	BOOT_RUP		0xFB			/* Used to boot RTAs */
+#define	ROUTE_RUP		0xFA			/* Used to specify routing/topology */
+#define	STATUS_RUP		0xF9			/* Not used */
+#define	POWER_RUP		0xF8			/* Download internal */
+
+/* COMMAND_RUP definitions... */
+#define	COMPLETE		(0x20|PRE_EMPTIVE)	/* RIO->Driver Command complete */
+#define	BREAK_RECEIVED		(0x21|PRE_EMPTIVE)	/* RIO->Driver Break received */
+#define	MODEM_STATUS		(0x22|PRE_EMPTIVE)	/* RIO->Driver Modem status change */
+
+/* BOOT_RUP definitions... */
+#define	BOOT_REQUEST		0x00			/* RIO->Driver Request for boot */
+#define	BOOT_ABORT		0x01			/* Driver->RIO Abort a boot */
+#define	BOOT_SEQUENCE		0x02			/* Driver->RIO Packet with firmware details */
+#define	BOOT_COMPLETED		0x03			/* RIO->Driver Boot completed */
+#define IFOAD			0x2F			/* Driver->RIO Shutdown/Reboot RTA (Fall Over And Die) */
+#define	IDENTIFY		0x30			/* Driver->RIO Identify RTA */
+#define	ZOMBIE			0x31			/* Driver->RIO Shutdown/Flash LEDs */
+#define	UFOAD			0x32			/* Driver->RIO Shutdown/Reboot neighbouring RTA */
+#define IWAIT			0x33			/* Driver->RIO Pause booting process */
+
+/* ROUTE_RUP definitions... */
+#define	ROUTE_REQUEST		0x00			/* RIO->Driver Request an ID */
+#define	ROUTE_FOAD		0x01			/* Driver->RIO Shutdown/reboot RTA */
+#define	ROUTE_ALREADY		0x02			/* Driver->RIO Not used */
+#define	ROUTE_USED		0x03			/* Driver->RIO Not used */
+#define	ROUTE_ALLOCATE		0x04			/* Driver->RIO Allocate RTA RUP numbers */
+#define	ROUTE_REQ_TOP		0x05			/* Driver->RIO Not used */
+#define ROUTE_TOPOLOGY		0x06			/* RIO->Driver Route/Topology status */
+
+/*****************************************************************************
+**********************************          **********************************
+**********************************   OPEN   **********************************
+**********************************          **********************************
+*****************************************************************************/
+
+/* (Driver->RIO,in-band)
+
+   Sent to open a port. 
+   Structure of configuration info used with OPEN, CONFIG and MOPEN packets... */
+
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_Cor1		(PKT_Data+1)		/* Channel Option Register 1 */
+#define	PKT_Cor2		(PKT_Data+2)		/* Channel Option Register 2 */
+#define	PKT_Cor4		(PKT_Data+3)		/* Channel Option Register 4 */
+#define	PKT_Cor5		(PKT_Data+4)		/* Channel Option Register 5 */
+#define	PKT_TxXon		(PKT_Data+5)		/* Transmit XON character */
+#define	PKT_TxXoff		(PKT_Data+6)		/* Transmit XOFF character */
+#define	PKT_RxXon		(PKT_Data+7)		/* Receive XON character */
+#define	PKT_RxXoff		(PKT_Data+8)		/* Receive XOFF character */
+#define	PKT_Lnext		(PKT_Data+9)		/* Lnext character */
+#define	PKT_TxBaud		(PKT_Data+10)		/* Transmit baud rate */
+#define	PKT_RxBaud		(PKT_Data+11)		/* Receive baud rate */
+
+/* COR1 definitions... */
+#define	COR1_PARITY		0xE0			/* Parity mask */
+#define	COR1_NONE		0x00			/* No parity */
+#define	COR1_SPACE		0x20			/* Space parity */
+#define	COR1_EVEN		0x40			/* Even parity */
+#define	COR1_MARK		0xA0			/* Mark parity */
+#define	COR1_ODD		0xC0			/* Odd parity */
+
+#define	COR1_STOPBITS		0x0C			/* Stop bits mask */
+#define	COR1_STOP1		0x00			/* 1 stop bit */
+#define	COR1_STOP1_5		0x04			/* 1.5 stop bits */
+#define	COR1_STOP2		0x08			/* 2 stop bits */
+
+#define	COR1_DATABITS		0x03			/* Data bits mask */
+#define	COR1_DATA5		0x00			/* 5 data bits */
+#define	COR1_DATA6		0x01			/* 6 data bits */
+#define	COR1_DATA7		0x02			/* 7 data bits */
+#define	COR1_DATA8		0x03			/* 8 data bits */
+
+/* COR2 definitions... */
+#define	COR2_XON_TXFLOW		0x40			/* XON/XOFF Transmit Flow */
+#define	COR2_XANY_TXFLOW	0xC0			/* XON/XANY Transmit Flow */
+#define	COR2_HUPCL		0x20			/* Hang Up On Close */
+#define	COR2_DSR_TXFLOW		0x08			/* DSR Transmit Flow Control */
+#define	COR2_RTS_RXFLOW		0x04			/* RTS Receive Flow Control */
+#define	COR2_CTS_TXFLOW		0x02			/* CTS Transmit Flow Control */
+#define	COR2_XON_RXFLOW		0x01			/* XON/XOFF Receive Flow */
+
+/* COR4 definition... */
+#define	COR4_IGNCR		0x80			/* Discard received CR */
+#define	COR4_ICRNL		0x40			/* Map received CR -> NL */
+#define	COR4_INLCR		0x20			/* Map received NL -> CR */
+#define	COR4_IGNBRK		0x10			/* Ignore Received Break */
+#define	COR4_NBRKINT		0x08			/* No interrupt on rx Break */
+#define	COR4_IGNPAR		0x04			/* ignore rx parity error chars */
+#define	COR4_PARMRK		0x02			/* Mark rx parity error chars */
+#define	COR4_RAISEMOD		0x01			/* Raise modem lines on !0 baud */
+
+/* COR5 definitions... */
+#define	COR5_ISTRIP		0x80			/* Strip input chars to 7 bits */
+#define	COR5_LNE		0x40			/* Enable LNEXT processing */
+#define	COR5_CMOE		0x20			/* Match good & error characters */
+#define	COR5_TAB3		0x10			/* TAB3 mode */
+#define	COR5_TSTATE_ON		0x08			/* Enable tbusy/tstop monitoring */
+#define	COR5_TSTATE_OFF		0x04			/* Disable tbusy/tstop monitoring */
+#define	COR5_ONLCR		0x02			/* NL -> CR NL on output */
+#define	COR5_OCRNL		0x01			/* CR -> NL on output */
+
+/* RxBaud and TxBaud definitions... */
+#define	RIO_B0			0x00			/* RTS / DTR signals dropped */
+#define	RIO_B50			0x01			/* 50 baud */
+#define	RIO_B75			0x02			/* 75 baud */
+#define	RIO_B110		0x03			/* 110 baud */
+#define	RIO_B134		0x04			/* 134.5 baud */
+#define	RIO_B150		0x05			/* 150 baud */
+#define	RIO_B200		0x06			/* 200 baud */
+#define	RIO_B300		0x07			/* 300 baud */
+#define	RIO_B600		0x08			/* 600 baud */
+#define	RIO_B1200		0x09			/* 1200 baud */
+#define	RIO_B1800		0x0A			/* 1800 baud */
+#define	RIO_B2400		0x0B			/* 2400 baud */
+#define	RIO_B4800		0x0C			/* 4800 baud */
+#define	RIO_B9600		0x0D			/* 9600 baud */
+#define	RIO_B19200		0x0E			/* 19200 baud */
+#define	RIO_B38400		0x0F			/* 38400 baud */
+#define	RIO_B56000		0x10			/* 56000 baud */
+#define	RIO_B57600		0x11			/* 57600 baud */
+#define	RIO_B64000		0x12			/* 64000 baud */
+#define	RIO_B115200		0x13			/* 115200 baud */
+#define	RIO_B2000		0x14			/* 2000 baud */
+
+/*****************************************************************************
+*********************************            *********************************
+*********************************   CONFIG   *********************************
+*********************************            *********************************
+*****************************************************************************/
+
+/* (Driver->RIO,in-band)
+
+   CONFIG is sent from the driver to configure an already opened port.
+   Packet structure is same as OPEN.  */
+
+/*****************************************************************************
+*********************************           **********************************
+*********************************   MOPEN   **********************************
+*********************************           **********************************
+*****************************************************************************/
+
+/* (Driver->RIO,in-band)
+
+   MOPEN is sent from the driver to open a port attached to a modem. (in-band)
+   Packet structure is same as OPEN.  */
+
+/*****************************************************************************
+*********************************           **********************************
+*********************************   CLOSE   **********************************
+*********************************           **********************************
+*****************************************************************************/
+
+/* (Driver->RIO,in-band)
+
+   CLOSE is sent from the driver to close a previously opened port.
+   No parameters.
+ */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+/*****************************************************************************
+*********************************            *********************************
+*********************************   WFLUSH   *********************************
+*********************************            *********************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   WFLUSH is sent pre-emptively from the driver to flush the write buffers and
+   packets of a port.  (pre-emptive)
+   
+   WFLUSH is also sent in-band from the driver to a port as a marker to end
+   write flushing previously started by a pre-emptive WFLUSH packet. (in-band)
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+
+/*****************************************************************************
+*********************************            *********************************
+*********************************   RFLUSH   *********************************
+*********************************            *********************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   RFLUSH is sent pre-emptively from the driver to flush the read buffers and
+   packets of a port.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#endif
+
+/*****************************************************************************
+*********************************            *********************************
+*********************************   RESUME   *********************************
+*********************************            *********************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   RESUME is sent pre-emptively from the driver to cause a port to resume 
+   transmission of data if blocked by XOFF.  (as if XON had been received)
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#endif
+
+/*****************************************************************************
+*********************************            *********************************
+*********************************   SBREAK   *********************************
+*********************************            *********************************
+*****************************************************************************/
+
+/* (Driver->RIO,in-band)
+
+   SBREAK is sent in-band from the driver to a port to suspend data and start
+   break signal transmission.
+
+   If the break delay is 0, the break signal will be acknowledged with a
+   RUP_COMMAND, COMPLETE packet and continue until an EBREAK packet is received.
+
+   Otherwise, there is no acknowledgement and the break signal will last for the
+   specified number of mS.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+#define	PKT_BreakDelay		(PKT_Data+1)		/* Break delay in mS */
+
+/*****************************************************************************
+*********************************            *********************************
+*********************************   EBREAK   *********************************
+*********************************            *********************************
+*****************************************************************************/
+
+/* (Driver->RIO,in-band)
+
+   EBREAK is sent in-band from the driver to a port to stop transmission of a
+   break signal.
+
+   No parameters.  */
+
+/*****************************************************************************
+*********************************             ********************************
+*********************************   SUSPEND   ********************************
+*********************************             ********************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   SUSPEND is sent pre-emptively from the driver to cause a port to suspend
+   transmission of data.  (as if XOFF had been received)
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#endif
+
+/*****************************************************************************
+*********************************            *********************************
+*********************************   FCLOSE   *********************************
+*********************************            *********************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   FCLOSE is sent pre-emptively from the driver to force close a port.
+   A force close flushes receive and transmit queues, and also lowers all output
+   modem signals if the COR5_HUPCL (Hang Up On Close) flag is set.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#endif
+
+/*****************************************************************************
+*********************************            *********************************
+*********************************   XPRINT   *********************************
+*********************************            *********************************
+*****************************************************************************/
+
+/* (Driver->RIO,in-band)
+
+   XPRINT is sent as a normal I/O data packet except that the PKT_CMD_BIT of
+   the "len" field is set, and the first "data" byte is XPRINT.
+
+   The I/O data in the XPRINT packet will contain the following:
+   -	Transparent Print Start Sequence
+   -	Transparent Print Data
+   -	Transparent Print Stop Sequence.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#endif
+
+/*****************************************************************************
+**********************************          **********************************
+**********************************   MBIS   **********************************
+**********************************          **********************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   MBIS is sent pre-emptively from the driver to set a port's modem signals.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#endif
+#define	PKT_ModemSet		(PKT_Data+4)		/* Modem set signals mask */
+
+/* ModemSet definitions... */
+#define	MBIS_RTS		0x01			/* RTS modem signal */
+#define	MBIS_DTR		0x02			/* DTR modem signal */
+
+/*****************************************************************************
+**********************************          **********************************
+**********************************   MBIC   **********************************
+**********************************          **********************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   MBIC is sent pre-emptively from the driver to clear a port's modem signals.
+   */
+#if 0   
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#endif
+
+#define	PKT_ModemClear		(PKT_Data+4)		/* Modem clear signals mask */
+
+/* ModemClear definitions... */
+#define	MBIC_RTS		0x01			/* RTS modem signal */
+#define	MBIC_DTR		0x02			/* DTR modem signal */
+
+/*****************************************************************************
+**********************************          **********************************
+**********************************   MSET   **********************************
+**********************************          **********************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   MSET is sent pre-emptively from the driver to set/clear a port's modem signals. */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#endif
+
+#define	PKT_ModemSet		(PKT_Data+4)		/* Modem set signals mask */
+
+/* ModemSet definitions... */
+#define	MSET_RTS		0x01			/* RTS modem signal */
+#define	MSET_DTR		0x02			/* DTR modem signal */
+
+/*****************************************************************************
+*********************************            *********************************
+*********************************   PCLOSE   *********************************
+*********************************            *********************************
+*****************************************************************************/
+
+/* (Driver->RIO,in-band)
+
+   PCLOSE is sent from the driver to pseudo close a previously opened port.
+   
+   The port will close when all data has been sent/received, however, the
+   port's transmit / receive and modem signals will be left enabled and the
+   port marked internally as Pseudo Closed. */
+
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+
+/*****************************************************************************
+**********************************          **********************************
+**********************************   MGET   **********************************
+**********************************          **********************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   MGET is sent pre-emptively from the driver to request the port's current modem signals. */
+
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+
+/*****************************************************************************
+*********************************             ********************************
+*********************************   MEMDUMP   ********************************
+*********************************             ********************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   MEMDUMP is sent pre-emptively from the driver to request a dump of 32 bytes
+   of the specified port's RTA address space.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#define	PKT_SubCmd		(PKT_Data+5)		/* Sub Command */
+#define	PKT_Address		(PKT_Data+6)		/* Requested address */
+
+/*****************************************************************************
+******************************                   *****************************
+******************************   READ_REGISTER   *****************************
+******************************                   *****************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   READ_REGISTER is sent pre-emptively from the driver to request the contents
+   of the CD1400 register specified in address.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#define	PKT_SubCmd		(PKT_Data+5)		/* Sub Command */
+#define	PKT_Address		(PKT_Data+6)		/* Requested address */
+
+/*****************************************************************************
+************************                            **************************
+************************   COMMAND_RUP - COMPLETE   **************************
+************************                            **************************
+*****************************************************************************/
+
+/* (RIO->Driver,pre-emptive)
+
+   COMMAND_RUP - COMPLETE is sent in response to all port I/O control command
+   packets, except MEMDUMP and READ_REGISTER.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#define	PKT_Cmd2		(PKT_Data+2)		/* Command code copy */
+#define	PKT_ModemStatus		(PKT_Data+3)		/* Modem signal status */
+#define	PKT_PortStatus		(PKT_Data+4)		/* Port signal status */
+#define	PKT_SubCmd		(PKT_Data+5)		/* Sub Command */
+
+/* ModemStatus definitions... */
+#define	MODEM_DSR		0x80			/* Data Set Ready modem state */
+#define	MODEM_CTS		0x40			/* Clear To Send modem state */
+#define	MODEM_RI		0x20			/* Ring Indicate modem state */
+#define	MODEM_CD		0x10			/* Carrier Detect modem state */
+#define	MODEM_TSTOP		0x08			/* Transmit Stopped state */
+#define	MODEM_TEMPTY		0x04			/* Transmit Empty state */
+#define	MODEM_DTR		0x02			/* DTR modem output state */
+#define	MODEM_RTS		0x01			/* RTS modem output state */
+
+/* PortStatus definitions... */
+#define	PORT_ISOPEN		0x01			/* Port open ? */
+#define	PORT_HUPCL		0x02			/* Hangup on close? */
+#define	PORT_MOPENPEND		0x04			/* Modem open pending */
+#define	PORT_ISPARALLEL		0x08			/* Parallel port */
+#define	PORT_BREAK		0x10			/* Port on break */
+#define	PORT_STATUSPEND		0020			/* Status packet pending */
+#define	PORT_BREAKPEND		0x40			/* Break packet pending */
+#define	PORT_MODEMPEND		0x80			/* Modem status packet pending */
+
+/*****************************************************************************
+************************                            **************************
+************************   COMMAND_RUP - COMPLETE   **************************
+************************                            **************************
+*****************************************************************************/
+
+/* (RIO->Driver,pre-emptive)
+
+   COMMAND_RUP - COMPLETE is sent in response to all port I/O control command
+   packets, except MEMDUMP and READ_REGISTER.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#define	PKT_Cmd2		(PKT_Data+2)		/* Command code copy */
+#endif
+#define	PKT_ModemStatus		(PKT_Data+3)		/* Modem signal status */
+#define	PKT_PortStatus		(PKT_Data+4)		/* Port signal status */
+#if 0
+#define	PKT_SubCmd		(PKT_Data+5)		/* Sub Command */
+#endif
+
+/* ModemStatus definitions... */
+#define	MODEM_DSR		0x80			/* Data Set Ready modem state */
+#define	MODEM_CTS		0x40			/* Clear To Send modem state */
+#define	MODEM_RI		0x20			/* Ring Indicate modem state */
+#define	MODEM_CD		0x10			/* Carrier Detect modem state */
+#define	MODEM_TSTOP		0x08			/* Transmit Stopped state */
+#define	MODEM_TEMPTY		0x04			/* Transmit Empty state */
+#define	MODEM_DTR		0x02			/* DTR modem output state */
+#define	MODEM_RTS		0x01			/* RTS modem output state */
+
+/* PortStatus definitions... */
+#define	PORT_ISOPEN		0x01			/* Port open ? */
+#define	PORT_HUPCL		0x02			/* Hangup on close? */
+#define	PORT_MOPENPEND		0x04			/* Modem open pending */
+#define	PORT_ISPARALLEL		0x08			/* Parallel port */
+#define	PORT_BREAK		0x10			/* Port on break */
+#define	PORT_STATUSPEND		0020			/* Status packet pending */
+#define	PORT_BREAKPEND		0x40			/* Break packet pending */
+#define	PORT_MODEMPEND		0x80			/* Modem status packet pending */
+
+/*****************************************************************************
+********************                                      ********************
+********************   COMMAND_RUP - COMPLETE - MEMDUMP   ********************
+********************                                      ********************
+*****************************************************************************/
+
+/* (RIO->Driver,pre-emptive)
+
+   COMMAND_RUP - COMPLETE - MEMDUMP is sent as an acknowledgement for a MEMDUMP
+   port I/O control command packet.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#define	PKT_Cmd2		(PKT_Data+2)		/* Command code copy */
+#define	PKT_ModemStatus		(PKT_Data+3)		/* Modem signal status */
+#define	PKT_PortStatus		(PKT_Data+4)		/* Port signal status */
+#define	PKT_SubCmd		(PKT_Data+5)		/* Sub Command */
+#define	PKT_Address		(PKT_Data+6)		/* Requested address */
+#endif
+#define	PKT_Dump		(PKT_Data+8)		/* 32bytes of requested dump data */
+
+/*****************************************************************************
+*****************                                            *****************
+*****************   COMMAND_RUP - COMPLETE - READ_REGISTER   *****************
+*****************                                            *****************
+*****************************************************************************/
+
+/* (RIO->Driver,pre-emptive)
+
+   COMMAND_RUP - COMPLETE - READ_REGISTER is sent as an acknowledgement for a
+   READ_REGISTER port I/O control command packet.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/*Command code */
+#define	PKT_PhbNum		(PKT_Data+1)		/*Port number wrt RTA */
+#define	PKT_Cmd2		(PKT_Data+2)		/* Command code copy */
+#endif
+#define	PKT_RegisterValue	(PKT_Data+3)		/* Modem signal status */
+#if 0
+#define	PKT_PortStatus		(PKT_Data+4)		/* Port signal status */
+#define	PKT_SubCmd		(PKT_Data+5)		/* Sub Command */
+#endif
+
+/*****************************************************************************
+*********************                                  ***********************
+*********************   COMMAND_RUP - BREAK_RECEIVED   ***********************
+*********************                                  ***********************
+*****************************************************************************/
+
+/* (RIO->Driver,pre-emptive)
+
+   COMMAND_RUP - BREAK_RECEIVED packets are sent when the port detects a receive BREAK signal.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#define	PKT_Cmd2		(PKT_Data+2)		/* Command code copy */
+#endif
+
+/*****************************************************************************
+*********************                                *************************
+*********************   COMMAND_RUP - MODEM_STATUS   *************************
+*********************                                *************************
+*****************************************************************************/
+
+/* (RIO->Driver,pre-emptive)
+
+   COMMAND_RUP - MODEM_STATUS packets are sent whenever the port detects a
+   change in the input modem signal states.
+
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#define	PKT_Cmd2		(PKT_Data+2)		/* Command code copy */
+#define	PKT_ModemStatus		(PKT_Data+3)		/* Modem signal status */
+#endif
+
+/*****************************************************************************
+************************                             *************************
+************************   BOOT_RUP - BOOT_REQUEST   *************************
+************************                             *************************
+*****************************************************************************/
+
+/* (RIO->Driver,pre-emptive)
+
+   BOOT_RUP - BOOT_REQUEST packets are sent to the Driver from RIO to request
+   firmware code to load onto attached RTAs.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+
+/*****************************************************************************
+************************                              ************************
+************************   BOOT_RUP - BOOT_SEQUENCE   ************************
+************************                              ************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   BOOT_RUP - BOOT_SEQUENCE packets are sent from the Driver to RIO in response
+   to a BOOT_RUP - BOOT_REQUEST packet.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+#define	PKT_NumPackets		(PKT_Data+2)		/* Packets required to load firmware */
+#define	PKT_LoadBase		(PKT_Data+4)		/* RTA firmware load address */
+#define	PKT_CodeSize		(PKT_Data+6)		/* Size of firmware in bytes */
+#define	PKT_CmdString		(PKT_Data+8)		/* Command string */
+
+/*****************************************************************************
+************************                               ***********************
+************************   BOOT_RUP - BOOT_COMPLETED   ***********************
+************************                               ***********************
+*****************************************************************************/
+
+/* (RIO->Driver,pre-emptive)
+
+   BOOT_RUP - BOOT_COMPLETE is sent to the Driver from RIO when downloading of
+   RTA firmware has completed.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+#define	PKT_LinkNumber		(PKT_Data+1)		/* Link number RTA booted on */
+#define	PKT_SerialNumber	(PKT_Data+2)		/* 4 byte serial number */
+
+/*****************************************************************************
+************************                               ***********************
+************************   BOOT_RUP - Packet Request   ***********************
+************************                               ***********************
+*****************************************************************************/
+
+/* (RIO->Driver,pre-emptive)
+
+   BOOT_RUP packet without the PKT_CMD_BIT set in the PKT->len field is sent
+   from RIO to the Driver as a request for a firmware boot packet. */
+
+#define	PKT_SequenceNumber	(PKT_Data+0)		/* Packet sequence number */
+
+/*****************************************************************************
+***********************                                ***********************
+***********************   BOOT_RUP - Packet Response   ***********************
+***********************                                ***********************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   In response to a BOOT_RUP boot packet request, the driver fills out the response
+   packet with the 70 bytes of the requested sequence.
+   */
+#if 0
+#define	PKT_SequenceNumber	(PKT_Data+0)		/* Packet sequence number */
+#endif
+#define	PKT_FirmwarePacket	(PKT_Data+2)		/* Firmware packet */
+
+/*****************************************************************************
+****************************                      ****************************
+****************************   BOOT_RUP - IFOAD   ****************************
+****************************                      ****************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   BOOT_RUP - IFOAD packets are sent from the Driver to an RTA to cause the
+   RTA to shut down and reboot.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+#define	PKT_IfoadId1		(PKT_Data+2)		/* IFOAD Id 1 */
+#define	PKT_IfoadId2		(PKT_Data+3)		/* IFOAD Id 2 */
+
+#define	IFOADID1		0xAD
+#define	IFOADID2		0xF0
+
+/*****************************************************************************
+**************************                         ***************************
+**************************   BOOT_RUP - IDENTIFY   ***************************
+**************************                         ***************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   BOOT_RUP - IDENTIFY packets are sent from the Driver to an RTA to cause the
+   RTA to flash its LEDs for a period of time.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+#define	PKT_IdentifyId		(PKT_Data+2)		/* defines pattern to flash */
+
+/*****************************************************************************
+****************************                       ***************************
+****************************   BOOT_RUP - ZOMBIE   ***************************
+****************************                       ***************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   BOOT_RUP - ZOMBIE packets are sent from the Driver to an RTA to cause the
+   RTA to shut down and flash it's LEDs.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+#define	PKT_ZombieId1		(PKT_Data+2)		/* ZOMBIE Id 1 */
+#define	PKT_ZombieId2		(PKT_Data+3)		/* ZOMBIE Id 2 */
+
+#define	ZOMBIEID1		0x52
+#define	ZOMBIEID2		0x21
+
+/*****************************************************************************
+****************************                      ****************************
+****************************   BOOT_RUP - UFOAD   ****************************
+****************************                      ****************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   BOOT_RUP - UFOAD packets are sent from the Driver to an RTA to cause the RTA
+   to ask it's neighbouring RTA to shut down and reboot.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_LinkNumber		(PKT_Data+1)		/* Link number of RTA to UFOAD */
+#endif
+#define	PKT_UfoadId1		(PKT_Data+2)		/* UFOAD Id 1 */
+#define	PKT_UfoadId2		(PKT_Data+3)		/* UFOAD Id 2 */
+
+#define	UFOADID1		0x1E
+#define	UFOADID2		0x0D
+
+/*****************************************************************************
+****************************                      ****************************
+****************************   BOOT_RUP - IWAIT   ****************************
+****************************                      ****************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   BOOT_RUP - IWAIT packets are sent from the Driver to an RTA to cause the RTA
+   to pause booting on the specified link for 30 seconds.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_LinkNumber		(PKT_Data+1)		/* Link number of RTA to UFOAD */
+#endif
+#define	PKT_IwaitId1		(PKT_Data+2)		/* IWAIT Id 1 */
+#define	PKT_IwaitId2		(PKT_Data+3)		/* IWAIT Id 2 */
+
+#define	IWAITID1		0xDE
+#define	IWAITID2		0xB1
+
+/*****************************************************************************
+************************                               ***********************
+************************   ROUTE_RUP - ROUTE_REQUEST   ***********************
+************************                               ***********************
+*****************************************************************************/
+
+/* (RIO->Driver,pre-emptive)
+
+   ROUTE_RUP - ROUTE_REQUEST packets are sent from a newly booted or connected
+   RTA to a Driver to request an ID (RUP or unit number).
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+#define	PKT_SerialNumber	(PKT_Data+2)		/* 4 byte serial number */
+#define	PKT_ModuleTypes		(PKT_Data+6)		/* RTA Module types */
+
+/* ModuleTypes definitions... */
+#define	MOD_BLANK		0x0F			/* Blank plate attached */
+#define	MOD_RS232DB25		0x00			/* RS232 DB25 connector */
+#define	MOD_RS232RJ45		0x01			/* RS232 RJ45 connector */
+#define	MOD_RS422DB25		0x02			/* RS422 DB25 connector */
+#define	MOD_RS485DB25		0x03			/* RS485 DB25 connector */
+#define	MOD_PARALLEL		0x04			/* Centronics parallel */
+
+#define	MOD2			0x08			/* Set to indicate Rev2 module */
+
+/*****************************************************************************
+*************************                            *************************
+*************************   ROUTE_RUP - ROUTE_FOAD   *************************
+*************************                            *************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   ROUTE_RUP - ROUTE_FOAD packet is sent as a response to a ROUTE_RUP - ROUTE_REQUEST
+   packet to cause the RTA to "Fall Over And Die"., i.e. shutdown and reboot.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+#define	PKT_RouteCmdString	(PKT_Data+2)		/* Command string */
+
+/*****************************************************************************
+***********************                                ***********************
+***********************   ROUTE_RUP - ROUTE_ALLOCATE   ***********************
+***********************                                ***********************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   ROUTE_RUP - ROUTE_ALLOCATE packet is sent as a response to a ROUTE_RUP - ROUTE_REQUEST
+   packet to allocate the RTA's Id number (RUP number 1..16)
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+#define	PKT_IdNum		(PKT_Data+1)		/* RUP number for ports 1..8 */
+#if 0
+#define	PKT_RouteCmdString	(PKT_Data+2)		/* Command string */
+#endif
+#define	PKT_IdNum2		(PKT_Data+0x17)		/* RUP number for ports 9..16 */
+
+/*****************************************************************************
+***********************                                ***********************
+***********************   ROUTE_RUP - ROUTE_TOPOLOGY   ***********************
+***********************                                ***********************
+*****************************************************************************/
+
+/* (RIO->Driver,pre-emptive)
+
+   ROUTE_RUP - ROUTE_TOPOLOGY packet is sent to inform the driver of an RTA's
+   current link status.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+#define	PKT_Link1Rup		(PKT_Data+2)		/* Link 1 RUP number */
+#define	PKT_Link1Link		(PKT_Data+3)		/* Link 1 link number */
+#define	PKT_Link2Rup		(PKT_Data+4)		/* Link 2 RUP number */
+#define	PKT_Link2Link		(PKT_Data+5)		/* Link 2 link number */
+#define	PKT_Link3Rup		(PKT_Data+6)		/* Link 3 RUP number */
+#define	PKT_Link3Link		(PKT_Data+7)		/* Link 3 link number */
+#define	PKT_Link4Rup		(PKT_Data+8)		/* Link 4 RUP number */
+#define	PKT_Link4Link		(PKT_Data+9)		/* Link 4 link number */
+#define	PKT_RtaVpdProm		(PKT_Data+10)		/* 32 bytes of RTA VPD PROM Contents */
+
+#endif						/* _sxwinif_h */
+
+/* End of RIOWINIF.H */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/riscos.h linux.15p9/drivers/char/rio/riscos.h
--- linux.vanilla/drivers/char/rio/riscos.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/riscos.h	Tue Jan 18 00:52:11 2000
@@ -0,0 +1,63 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: riscos.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:19
+**	Retrieved	: 11/6/98 11:34:22
+**
+**  ident @(#)riscos.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_riscos_h__
+#define __rio_riscos_h__
+
+#ifdef SCCS_LABELS
+static char *_riscos_h_sccs_ = "@(#)riscos.h	1.2";
+#endif
+
+/*
+** This module used to define all those little itsy bits required for RISC/OS
+** now it's full of null macros.
+*/
+
+/*
+**	RBYTE reads a byte from a location.
+**	RWORD reads a word from a location.
+**	WBYTE writes a byte to a location.
+**	WWORD writes a word to a location.
+**	RINDW reads a word through a pointer.
+**	WINDW writes a word through a pointer.
+**	RIOSWAB swaps the two bytes of a word, if needed.
+*/
+
+#define	RIOSWAB(N)      (N)
+#define	WBYTE(A,V)	(A)=(uchar)(V)
+#define WWORD(A,V)	(A)=(ushort)(V)
+#define RBYTE(A)	(uchar)(A)
+#define RWORD(A)	(ushort)(A)
+#define RINDW(A)	(*(ushort *)(A))
+#define WINDW(A,V)	(*(ushort *)(A)=(ushort)(V))
+
+#endif /* __rio_riscos_h__ */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/rom.h linux.15p9/drivers/char/rio/rom.h
--- linux.vanilla/drivers/char/rio/rom.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/rom.h	Tue Jan 18 00:52:11 2000
@@ -0,0 +1,64 @@
+/****************************************************************************
+ *******                                                              *******
+ *******                      R O M
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _rom_h
+#define _rom_h 1
+
+#ifndef lint
+#ifdef SCCS
+static char *_rio_rom_h_sccs = "@(#)rom.h	1.1" ;
+#endif
+#endif
+
+typedef struct  ROM  ROM ;
+struct  ROM  {
+                 u_short    slx ;
+                 char       pcb_letter_rev ;
+                 char       pcb_number_rev ;
+                 char       serial[4] ;
+                 char       year ;
+                 char       week ;
+             } ;
+
+#endif
+
+#define HOST_ROM    (ROM *) 0x7c00
+#define RTA_ROM	    (ROM *) 0x7801
+#define ROM_LENGTH  0x20
+
+/*********** end of file ***********/
+
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/route.h linux.15p9/drivers/char/rio/route.h
--- linux.vanilla/drivers/char/rio/route.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/route.h	Tue Jan 18 00:52:11 2000
@@ -0,0 +1,108 @@
+/****************************************************************************
+ *******                                                              *******
+ *******                 R O U T E     H E A D E R
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra / Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _route_h
+#define _route_h
+
+#ifdef SCCS_LABELS
+#ifndef lint
+/* static char *_rio_route_h_sccs = "@(#)route.h	1.3"; */
+#endif
+#endif
+
+#define MAX_LINKS 4
+#define MAX_NODES 17                          /* Maximum nodes in a subnet */
+#define NODE_BYTES ((MAX_NODES / 8) + 1)      /* Number of bytes needed for
+                                                 1 bit per node */
+#define ROUTE_DATA_SIZE  (NODE_BYTES + 2)     /* Number of bytes for complete 
+                                                 info about cost etc. */
+#define ROUTES_PER_PACKET ((PKT_MAX_DATA_LEN -2)/ ROUTE_DATA_SIZE)
+                                              /* Number of nodes we can squeeze
+                                                 into one packet */
+#define MAX_TOPOLOGY_PACKETS (MAX_NODES / ROUTES_PER_PACKET + 1)
+/************************************************
+ * Define the types of command for the ROUTE RUP.
+ ************************************************/
+#define ROUTE_REQUEST    0                    /* Request an ID */
+#define ROUTE_FOAD       1                    /* Kill the RTA */
+#define ROUTE_ALREADY    2                    /* ID given already */
+#define ROUTE_USED       3                    /* All ID's used */
+#define ROUTE_ALLOCATE   4                    /* Here it is */
+#define ROUTE_REQ_TOP    5                    /* I bet you didn't expect....
+                                                 the Topological Inquisition */
+#define ROUTE_TOPOLOGY   6                    /* Topology request answered FD */
+/*******************************************************************
+ * Define the Route Map Structure
+ *
+ * The route map gives a pointer to a Link Structure to use.
+ * This allows Disconnected Links to be checked quickly
+ ******************************************************************/
+typedef struct COST_ROUTE COST_ROUTE;
+struct COST_ROUTE {
+                      unsigned char cost;        /* Cost down this link */
+                      unsigned char route[NODE_BYTES]; /* Nodes thorough this route */
+                  } ;
+
+typedef struct ROUTE_STR ROUTE_STR ;
+struct  ROUTE_STR {
+                      COST_ROUTE cost_route[MAX_LINKS];
+                                                /* cost / route for this link */
+                      ushort favoured;          /* favoured link */
+                  } ;
+
+
+#define NO_LINK            (short) 5      /* Link unattached */
+#define ROUTE_NO_ID        (short) 100    /* No Id */
+#define ROUTE_DISCONNECT   (ushort) 0xff  /* Not connected */
+#define ROUTE_INTERCONNECT (ushort) 0x40  /* Sub-net interconnect */
+
+
+#define SYNC_RUP         (ushort) 255
+#define COMMAND_RUP      (ushort) 254
+#define ERROR_RUP        (ushort) 253
+#define POLL_RUP         (ushort) 252
+#define BOOT_RUP         (ushort) 251
+#define ROUTE_RUP        (ushort) 250
+#define STATUS_RUP       (ushort) 249
+#define POWER_RUP        (ushort) 248
+
+#define HIGHEST_RUP      (ushort) 255   /* Set to Top one */
+#define LOWEST_RUP       (ushort) 248   /* Set to bottom one */
+
+#endif
+
+/*********** end of file ***********/
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/rtahw.h linux.15p9/drivers/char/rio/rtahw.h
--- linux.vanilla/drivers/char/rio/rtahw.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/rtahw.h	Tue Jan 18 00:52:11 2000
@@ -0,0 +1,75 @@
+
+/****************************************************************************
+ *******                                                              *******
+ *******                R T A    H A R D W A R E
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef lint
+#ifdef SCCS_LABELS
+static char *_rio_rtahw_h_sccs = "@(#)rtahw.h	1.5" ;
+#endif
+#endif
+
+#define	WATCHDOG_ADDR	((unsigned short *)0x7a00)
+#define RTA_LED_ADDR	((unsigned short *)0x7c00)
+#define SERIALNUM_ADDR	((unsigned char *)0x7809)
+#define LATCH_ADDR      ((unsigned char *)0x7800)
+
+/*
+** Here we define where the cd1400 chips are in memory.
+*/
+#define CD1400_ONE_ADDR		(0x7300)
+#define CD1400_TWO_ADDR		(0x7200)
+#define CD1400_THREE_ADDR	(0x7100)
+#define CD1400_FOUR_ADDR	(0x7000)
+
+/*
+** Define the different types of modules we can have
+*/
+enum module {
+    MOD_BLANK		= 0x0f,		/* Blank plate attached */
+    MOD_RS232DB25	= 0x00,		/* RS232 DB25 connector */
+    MOD_RS232RJ45	= 0x01,		/* RS232 RJ45 connector */
+    MOD_RS422DB25	= 0x02,		/* RS422 DB25 connector */
+    MOD_RS485DB25	= 0x03,		/* RS485 DB25 connector */
+    MOD_PARALLEL	= 0x04		/* Centronics parallel */
+};
+
+#define TYPE_HOST	0
+#define TYPE_RTA8	1
+#define TYPE_RTA16	2
+
+#define	WATCH_DOG	WATCHDOG_ADDR
+
+/*********** end of file ***********/
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/rup.h linux.15p9/drivers/char/rio/rup.h
--- linux.vanilla/drivers/char/rio/rup.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/rup.h	Tue Jan 18 00:52:11 2000
@@ -0,0 +1,82 @@
+/****************************************************************************
+ *******                                                              *******
+ *******               R U P   S T R U C T U R E
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _rup_h
+#define _rup_h 1
+
+#ifdef SCCS_LABELS
+#ifndef lint
+/* static char *_rio_rup_h_sccs = "@(#)rup.h	1.5"; */
+#endif
+#endif
+
+#if defined( HOST ) || defined( INKERNEL )
+#define MAX_RUP          ((short) 16) 
+#endif
+#ifdef RTA
+#define MAX_RUP          ((short) 1)
+#endif
+
+#define PKTS_PER_RUP     ((short) 2)     /* They are always used in pairs */
+
+/*************************************************
+ * Define all the  packet request stuff
+ ************************************************/
+#define TX_RUP_INACTIVE          0        /* Nothing to transmit */
+#define TX_PACKET_READY          1        /* Transmit packet ready */
+#define TX_LOCK_RUP              2        /* Transmit side locked */
+
+#define RX_RUP_INACTIVE          0        /* Nothing received */
+#define RX_PACKET_READY          1        /* Packet received */
+
+#define RUP_NO_OWNER             0xff     /* RUP not owned by any process */
+
+struct RUP {
+             PKT_ptr    txpkt;            /* Outgoing packet */
+             PKT_ptr    rxpkt;            /* Incoming packet */
+             WORD       link;             /* Which link to send down? */
+             BYTE       rup_dest_unit[2]; /* Destination unit */
+             WORD       handshake;        /* For handshaking */
+             WORD       timeout;          /* Timeout */
+             WORD       status;           /* Status */
+             WORD       txcontrol;        /* Transmit control */
+             WORD       rxcontrol;        /* Receive control */
+           };
+ 
+#endif
+
+/*********** end of file ***********/
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/rupstat.h linux.15p9/drivers/char/rio/rupstat.h
--- linux.vanilla/drivers/char/rio/rupstat.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/rupstat.h	Tue Jan 18 00:52:11 2000
@@ -0,0 +1,51 @@
+/****************************************************************************
+ *******                                                              *******
+ *******                      RUPSTAT
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _rupstat_h
+#define _rupstat_h
+
+#ifndef lint
+#ifdef SCCS_LABELS
+static char *_rio_rupstat_h_sccs = "@(#)rupstat.h	1.1" ;
+#endif
+#endif
+
+#define    STATUS_SYNC    0
+#define    STATUS_REQ_TOP 1
+#define    STATUS_TOPOLOGY    2
+
+#endif
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/sam.h linux.15p9/drivers/char/rio/sam.h
--- linux.vanilla/drivers/char/rio/sam.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/sam.h	Tue Jan 18 00:52:11 2000
@@ -0,0 +1,74 @@
+/****************************************************************************
+ *******                                                              *******
+ *******                    S A M . H
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+#ifndef _sam_h
+#define _sam_h 1
+
+#ifdef SCCS_LABELS
+#ifndef lint
+/* static char *_rio_sam_h_sccs = "@(#)sam.h	1.3"; */
+#endif
+#endif
+
+
+#if !defined( HOST ) && !defined( INKERNEL )
+#define RTA 1
+#endif
+
+#define NUM_FREE_LIST_UNITS     500
+
+#ifndef FALSE
+#define FALSE (short)  0x00
+#endif
+#ifndef TRUE
+#define TRUE  (short)  !FALSE
+#endif
+
+#define TX    TRUE
+#define RX    FALSE
+
+
+typedef struct FREE_LIST FREE_LIST ;
+struct FREE_LIST   {
+                       FREE_LIST_ptr next ;
+                       FREE_LIST_ptr prev ;
+                   } ;
+
+
+#endif
+/*********** end of file ***********/
+
+
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/selftest.h linux.15p9/drivers/char/rio/selftest.h
--- linux.vanilla/drivers/char/rio/selftest.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/selftest.h	Tue Jan 18 00:52:11 2000
@@ -0,0 +1,73 @@
+/*
+** File:		selftest.h
+**
+** Author:		David Dix
+**
+** Created:		15th March 1993
+**
+** Last modified:	94/06/14
+**
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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	_selftests_h_
+#define _selftests_h_
+
+/*
+** Selftest identifier...
+*/
+#define SELFTEST_MAGIC	0x5a5a
+
+/*
+** This is the structure of the packet that is sent back after each
+** selftest on a booting RTA.
+*/
+typedef struct {
+    short		magic;			/* Identifies packet type */
+    int			test;			/* Test number, see below */
+    unsigned int	result;			/* Result value */
+    unsigned int	dataIn;
+    unsigned int	dataOut;
+}selftestStruct;
+
+/*
+** The different tests are identified by the following data values.
+*/
+enum test {
+    TESTS_COMPLETE	= 0x00,
+    MEMTEST_ADDR	= 0x01,
+    MEMTEST_BIT		= 0x02,
+    MEMTEST_FILL	= 0x03,
+    MEMTEST_DATABUS	= 0x04,
+    MEMTEST_ADDRBUS	= 0x05,
+    CD1400_INIT		= 0x10,
+    CD1400_LOOP		= 0x11,
+    CD1400_INTERRUPT    = 0x12
+};
+
+enum result {
+    E_PORT		= 0x10,
+    E_TX		= 0x11,
+    E_RX		= 0x12,
+    E_EXCEPT		= 0x13,
+    E_COMPARE		= 0x14,
+    E_MODEM		= 0x15,
+    E_TIMEOUT		= 0x16,
+    E_INTERRUPT         = 0x17
+};
+#endif	/* _selftests_h_ */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/space.h linux.15p9/drivers/char/rio/space.h
--- linux.vanilla/drivers/char/rio/space.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/space.h	Tue Jan 18 00:52:11 2000
@@ -0,0 +1,45 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: space.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:19
+**	Retrieved	: 11/6/98 11:34:22
+**
+**  ident @(#)space.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_space_h__
+#define __rio_space_h__
+
+#ifdef SCCS_LABELS
+static char *_space_h_sccs_ = "@(#)space.h	1.2";
+#endif
+
+extern int rio_cntls;
+extern int rio_bases[];
+extern int rio_limits[];
+extern int rio_vects[];
+
+#endif /* __rio_space_h__ */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/sysmap.h linux.15p9/drivers/char/rio/sysmap.h
--- linux.vanilla/drivers/char/rio/sysmap.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/sysmap.h	Tue Jan 18 00:52:11 2000
@@ -0,0 +1,63 @@
+
+/****************************************************************************
+ *******                                                              *******
+ *******          S Y S T E M   M A P   H E A D E R
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef lint
+#ifdef SCCS_LABELS
+static char *_rio_sysmap_h_sccs = "@(#)sysmap.h	1.1" ;
+#endif
+#endif
+
+#define SYSTEM_MAP_LEN     64           /* Len of System Map array */
+
+
+typedef struct SYS_MAP        SYS_MAP ;
+typedef struct SYS_MAP_LINK   SYS_MAP_LINK ;
+
+struct SYS_MAP_LINK {
+                        short id ;          /* Unit Id */
+                        short link ;        /* Id's Link */
+                        short been_here ;   /* Used by map_gen */
+                    } ;
+
+struct SYS_MAP {
+                   char         serial_num[4] ;
+                   SYS_MAP_LINK link[4] ;
+               } ;
+
+
+/*********** end of file ***********/
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/timeouts.h linux.15p9/drivers/char/rio/timeouts.h
--- linux.vanilla/drivers/char/rio/timeouts.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/timeouts.h	Tue Jan 18 00:52:11 2000
@@ -0,0 +1,51 @@
+
+/****************************************************************************
+ *******                                                              *******
+ *******                     T I M E O U T S
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef lint
+#ifdef SCCS_LABELS
+static char *_rio_defaults_h_sccs = "@(#)timeouts.h	1.3" ;
+#endif
+#endif
+
+#define MILLISECOND           (int) (1000/64)   /* 15.625 low ticks */
+#define SECOND                (int) 15625       /* Low priority ticks */
+
+#define TX_TIMEOUT          (int) (200 * MILLISECOND)
+
+
+/*********** end of file ***********/
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/top.h linux.15p9/drivers/char/rio/top.h
--- linux.vanilla/drivers/char/rio/top.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/top.h	Tue Jan 18 00:52:11 2000
@@ -0,0 +1,49 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: top.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:19
+**	Retrieved	: 11/6/98 11:34:22
+**
+**  ident @(#)top.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_top_h__
+#define __rio_top_h__
+
+#ifdef SCCS_LABELS
+static char *_top_h_sccs_ = "@(#)top.h	1.2";
+#endif
+
+/*
+** Topology information
+*/
+struct Top
+{
+    uchar Unit;
+    uchar Link;
+};
+
+#endif /* __rio_top_h__ */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/typdef.h linux.15p9/drivers/char/rio/typdef.h
--- linux.vanilla/drivers/char/rio/typdef.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/typdef.h	Tue Jan 18 00:52:11 2000
@@ -0,0 +1,82 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: typdef.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:20
+**	Retrieved	: 11/6/98 11:34:22
+**
+**  ident @(#)typdef.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_typdef_h__
+#define __rio_typdef_h__
+
+#ifdef SCCS_LABELS
+static char *_typdef_h_sccs_ = "@(#)typdef.h	1.2";
+#endif
+
+#undef VPIX
+
+/*
+** IT IS REALLY, REALLY, IMPORTANT THAT BYTES ARE UNSIGNED!
+**
+** These types are ONLY to be used for refering to data structures
+** on the RIO Host card!
+*/
+typedef	volatile unsigned char	BYTE;
+typedef volatile unsigned short	WORD;
+typedef volatile unsigned int	DWORD;
+typedef	volatile unsigned short RIOP;
+typedef	volatile short          NUMBER;
+
+
+/*
+** 27.01.199 ARG - mods to compile 'newutils' on LyxnOS -
+** These #defines are for the benefit of the 'libfuncs' library
+** only. They are not necessarily correct type mappings and
+** are here only to make the source compile.
+*/
+/* typedef unsigned int	uint; */
+typedef unsigned long	ulong_t;
+typedef unsigned short	ushort_t;
+typedef unsigned char	uchar_t;
+typedef unsigned char	queue_t;
+typedef unsigned char	mblk_t;
+typedef	unsigned int 	paddr_t;
+typedef unsigned char   uchar;
+
+#define	TPNULL	((ushort)(0x8000))
+
+
+/*
+** RIO structures defined in other include files.
+*/
+typedef struct PKT	 	PKT;
+typedef struct LPB	 	LPB;
+typedef struct RUP	 	RUP;
+typedef struct Port		Port;
+typedef struct DpRam		DpRam;
+
+#endif /* __rio_typdef_h__ */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/rio/unixrup.h linux.15p9/drivers/char/rio/unixrup.h
--- linux.vanilla/drivers/char/rio/unixrup.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/char/rio/unixrup.h	Tue Jan 18 00:52:11 2000
@@ -0,0 +1,56 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+**
+**	Module		: unixrup.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:20
+**	Retrieved	: 11/6/98 11:34:22
+**
+**  ident @(#)unixrup.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_unixrup_h__
+#define __rio_unixrup_h__
+
+#ifdef SCCS_LABELS
+static char *_unixrup_h_sccs_ = "@(#)unixrup.h	1.2";
+#endif
+
+/*
+**    UnixRup data structure. This contains pointers to actual RUPs on the
+**    host card, and all the command/boot control stuff.
+*/
+struct    UnixRup
+{
+    struct CmdBlk    *CmdsWaitingP;	/* Commands waiting to be done */
+    struct CmdBlk    *CmdPendingP;	/* The command currently being sent */
+    struct RUP       *RupP;		/* the Rup to send it to */
+    uint             Id;		/* Id number */
+    uint             BaseSysPort;	/* SysPort of first tty on this RTA */
+    uint             ModTypes;		/* Modules on this RTA */
+  semtype	RupLock;		/* Lock structure for MPX */
+/*    struct lockb     RupLock;	*/	/* Lock structure for MPX */
+};
+
+#endif /* __rio_unixrup_h__ */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/serial.c linux.15p9/drivers/char/serial.c
--- linux.vanilla/drivers/char/serial.c	Tue Jan  4 21:18:46 2000
+++ linux.15p9/drivers/char/serial.c	Tue Jan 18 01:03:46 2000
@@ -1383,8 +1383,13 @@
 	if (info->state->type == PORT_16750)
 		serial_outp(info, UART_FCR, fcr); 	/* set fcr */
 	serial_outp(info, UART_LCR, cval);		/* reset DLAB */
-	if (info->state->type != PORT_16750)
+	if (info->state->type != PORT_16750) {
+		if (fcr & UART_FCR_ENABLE_FIFO) {
+			/* emulated UARTs (Lucent Venus 167x) need two steps */
+			serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO);
+		}
 		serial_outp(info, UART_FCR, fcr); 	/* set fcr */
+	}
 	restore_flags(flags);
 }
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/specialix.c linux.15p9/drivers/char/specialix.c
--- linux.vanilla/drivers/char/specialix.c	Sat Aug 14 02:26:15 1999
+++ linux.15p9/drivers/char/specialix.c	Fri Jan 21 19:00:18 2000
@@ -59,11 +59,14 @@
  * Revision 1.8:  Jul 1  1997
  *                port to linux-2.1.43 kernel.
  * Revision 1.9:  Oct 9  1998
- *                Added stuff for the IO8+/PCI version. . 
+ *                Added stuff for the IO8+/PCI version.
+ * Revision 1.10: Oct 22  1999 / Jan 21 2000. 
+ *                Added stuff for setserial. 
+ *                Nicolas Mailhot (Nicolas.Mailhot@email.enst.fr)
  * 
  */
 
-#define VERSION "1.8"
+#define VERSION "1.10"
 
 
 /*
@@ -1069,10 +1072,17 @@
 	/*
 	 * Now we must calculate some speed depended things 
 	 */
-	
+
 	/* Set baud rate for port */
-	tmp = (((SX_OSCFREQ + baud_table[baud]/2) / baud_table[baud] +
-		CD186x_TPC/2) / CD186x_TPC);
+	tmp = port->custom_divisor ;
+	if ( tmp )
+		printk (KERN_INFO "sx%d: Using custom baud rate divisor %ld. \n"
+			        "This is an untested option, please be carefull.\n",
+			        port_No (port), tmp);
+	else
+		tmp = (((SX_OSCFREQ + baud_table[baud]/2) / baud_table[baud] +
+		         CD186x_TPC/2) / CD186x_TPC);
+
 	if ((tmp < 0x10) && time_before(again, jiffies)) { 
 		again = jiffies + HZ * 60;
 		/* Page 48 of version 2.0 of the CL-CD1865 databook */
@@ -1094,9 +1104,13 @@
 	sx_out(bp, CD186x_TBPRH, (tmp >> 8) & 0xff); 
 	sx_out(bp, CD186x_RBPRL, tmp & 0xff); 
 	sx_out(bp, CD186x_TBPRL, tmp & 0xff);
-	
-	baud = (baud_table[baud] + 5) / 10;   /* Estimated CPS */
-	
+
+	if (port->custom_divisor) {
+		baud = (SX_OSCFREQ + port->custom_divisor/2) / port->custom_divisor;
+		baud = ( baud + 5 ) / 10;
+	} else 
+		baud = (baud_table[baud] + 5) / 10;   /* Estimated CPS */
+
 	/* Two timer ticks seems enough to wakeup something like SLIP driver */
 	tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO;		
 	port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ?
@@ -1859,7 +1873,8 @@
 	if (error)
 		return error;
 
-	copy_from_user(&tmp, newinfo, sizeof(tmp));
+	if (copy_from_user(&tmp, newinfo, sizeof(tmp)))
+		return -EFAULT;
 	
 #if 0	
 	if ((tmp.irq != bp->irq) ||
@@ -1874,6 +1889,7 @@
 
 	change_speed = ((port->flags & ASYNC_SPD_MASK) !=
 			(tmp.flags & ASYNC_SPD_MASK));
+	change_speed |= (tmp.custom_divisor != port->custom_divisor);
 	
 	if (!capable(CAP_SYS_ADMIN)) {
 		if ((tmp.close_delay != port->close_delay) ||
@@ -1883,11 +1899,13 @@
 			return -EPERM;
 		port->flags = ((port->flags & ~ASYNC_USR_MASK) |
 		                  (tmp.flags & ASYNC_USR_MASK));
+		port->custom_divisor = tmp.custom_divisor;
 	} else {
 		port->flags = ((port->flags & ~ASYNC_FLAGS) |
 		                  (tmp.flags & ASYNC_FLAGS));
 		port->close_delay = tmp.close_delay;
 		port->closing_wait = tmp.closing_wait;
+		port->custom_divisor = tmp.custom_divisor;
 	}
 	if (change_speed) {
 		save_flags(flags); cli();
@@ -1918,8 +1936,10 @@
 	tmp.baud_base = (SX_OSCFREQ + CD186x_TPC/2) / CD186x_TPC;
 	tmp.close_delay = port->close_delay * HZ/100;
 	tmp.closing_wait = port->closing_wait * HZ/100;
+	tmp.custom_divisor =  port->custom_divisor;
 	tmp.xmit_fifo_size = CD186x_NFIFO;
-	copy_to_user(retinfo, &tmp, sizeof(tmp));
+	if (copy_to_user(retinfo, &tmp, sizeof(tmp)))
+		return -EFAULT;
 	return 0;
 }
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/stallion.c linux.15p9/drivers/char/stallion.c
--- linux.vanilla/drivers/char/stallion.c	Sat Aug 14 02:25:40 1999
+++ linux.15p9/drivers/char/stallion.c	Mon Feb  7 12:07:56 2000
@@ -3,8 +3,8 @@
 /*
  *	stallion.c  -- stallion multiport serial driver.
  *
- *	Copyright (C) 1996-1999  Stallion Technologies (support@stallion.oz.au).
- *	Copyright (C) 1994-1996  Greg Ungerer (gerg@stallion.oz.au).
+ *	Copyright (C) 1996-2000  Stallion Technologies (support@stallion.oz.au)
+ *	Copyright (C) 1994-1996  Greg Ungerer.
  *
  *	This code is loosely based on the Linux serial driver, written by
  *	Linus Torvalds, Theodore T'so and others.
@@ -28,6 +28,7 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/version.h>
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/tty_flip.h>
@@ -47,6 +48,7 @@
 #include <linux/pci.h>
 #endif
 
+
 /*****************************************************************************/
 
 /*
@@ -127,6 +129,7 @@
 #define	STL_TXBUFLOW		512
 #define	STL_TXBUFSIZE		4096
 
+#define	STL_IRQ_DEVID		(&stl_brds[0])
 /*****************************************************************************/
 
 /*
@@ -135,7 +138,7 @@
  */
 static char	*stl_drvtitle = "Stallion Multiport Serial Driver";
 static char	*stl_drvname = "stallion";
-static char	*stl_drvversion = "5.5.1";
+static char	*stl_drvversion = "5.6.0";
 static char	*stl_serialname = "ttyE";
 static char	*stl_calloutname = "cue";
 
@@ -313,7 +316,7 @@
 /*
  *	Define the module agruments.
  */
-MODULE_AUTHOR("Greg Ungerer");
+MODULE_AUTHOR("Stallion Technologies (support@stallion.oz.au)");
 MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
 
 MODULE_PARM(board0, "1-4s");
@@ -345,6 +348,7 @@
 #define	ID_BRD4		0x10
 #define	ID_BRD8		0x20
 #define	ID_BRD16	0x30
+#define	ID_BRD4_422     0x40    /* 4 port EIO supporting RS422*/
 
 #define	EIO_INTRPEND	0x08
 #define	EIO_INTEDGE	0x00
@@ -523,6 +527,8 @@
 static int	stl_getbrdstats(combrd_t *bp);
 static int	stl_getportstats(stlport_t *portp, comstats_t *cp);
 static int	stl_clrportstats(stlport_t *portp, comstats_t *cp);
+static int	stl_geticounters(stlport_t *portp,
+				 struct serial_icounter_struct *cp);
 static int	stl_getportstruct(unsigned long arg);
 static int	stl_getbrdstruct(unsigned long arg);
 static int	stl_waitcarrier(stlport_t *portp, struct file *filp);
@@ -853,7 +859,7 @@
 	}
 
 	for (i = 0; (i < stl_numintrs); i++)
-		free_irq(stl_gotintrs[i], NULL);
+		free_irq(stl_gotintrs[i], STL_IRQ_DEVID);
 
 	restore_flags(flags);
 }
@@ -1599,7 +1605,8 @@
 		return(-ENODEV);
 
 	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
- 	    (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) {
+ 	    (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS) &&
+	    (cmd != TIOCGICOUNT)) {
 		if (tty->flags & (1 << TTY_IO_ERROR))
 			return(-EIO);
 	}
@@ -1671,6 +1678,13 @@
 		    sizeof(comstats_t))) == 0)
 			rc = stl_clrportstats(portp, (comstats_t *) arg);
 		break;
+	case TIOCGICOUNT:
+		if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
+		    sizeof(struct serial_icounter_struct *))) == 0)
+			rc = stl_geticounters(portp,
+				      (struct serial_icounter_struct *) arg);
+		break;
+		
 	case TIOCSERCONFIG:
 	case TIOCSERGWILD:
 	case TIOCSERSWILD:
@@ -2294,7 +2308,8 @@
 			break;
 	}
 	if (i >= stl_numintrs) {
-		if (request_irq(irq, stl_intr, SA_INTERRUPT, name, NULL) != 0) {
+		if (request_irq(irq, stl_intr, SA_SHIRQ, name,
+				STL_IRQ_DEVID) != 0) {
 			printk("STALLION: failed to register interrupt "
 				"routine for %s irq=%d\n", name, irq);
 			rc = -ENODEV;
@@ -2348,6 +2363,8 @@
 		portp->callouttermios = stl_deftermios;
 		portp->tqueue.routine = stl_offintr;
 		portp->tqueue.data = portp;
+		portp->open_wait = 0;
+		portp->close_wait = 0;
 		portp->stats.brd = portp->brdnr;
 		portp->stats.panel = portp->panelnr;
 		portp->stats.port = portp->portnr;
@@ -2445,6 +2462,9 @@
 		case ID_BRD16:
 			brdp->nrports = 16;
 			break;
+		case ID_BRD4_422:
+			brdp->nrports = 4;
+			break;
 		default:
 			return(-ENODEV);
 		}
@@ -2780,7 +2800,7 @@
 
 #if DEBUG
 	printk("stl_initpcibrd(brdtype=%d,busnr=%x,devnr=%x)\n", brdtype,
-		dev->bus->number, dev->devfn);
+		devp->bus->number, devp->devfn);
 #endif
 
 	if ((brdp = stl_allocbrd()) == (stlbrd_t *) NULL)
@@ -3084,6 +3104,28 @@
 	return(0);
 }
 
+static int stl_geticounters(stlport_t *portp,
+			    struct serial_icounter_struct *icp)
+{
+	struct serial_icounter_struct icount;
+	comstats_t *s	= &portp->stats;
+	
+	memset(&icount, 0, sizeof(icount));
+	/*
+	 * we only support a subset of the icounters - the others are handled
+	 * by the uart and we don't get interrupted for them
+	 */
+	icount.dcd	= s->modem;
+	icount.rx	= s->rxtotal;
+	icount.tx	= s->txtotal;
+	icount.frame	= s->rxframing;
+	icount.overrun	= s->rxoverrun;
+	icount.parity	= s->rxparity;
+	icount.brk	= s->rxbreaks;
+	
+	return (copy_to_user(icp, &icount, sizeof(icount)));
+}
+
 /*****************************************************************************/
 
 /*
@@ -4209,6 +4251,7 @@
 		if ((tty == (struct tty_struct *) NULL) ||
 		    (tty->flip.char_buf_ptr == (char *) NULL) ||
 		    ((buflen = TTY_FLIPBUF_SIZE - tty->flip.count) == 0)) {
+			len = MIN(len, sizeof(stl_unwanted));
 			outb((RDSR + portp->uartaddr), ioaddr);
 			insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
 			portp->stats.rxlost += len;
@@ -5175,6 +5218,7 @@
 		if ((tty == (struct tty_struct *) NULL) ||
 		    (tty->flip.char_buf_ptr == (char *) NULL) ||
 		    ((buflen = TTY_FLIPBUF_SIZE - tty->flip.count) == 0)) {
+			len = MIN(len, sizeof(stl_unwanted));
 			outb(GRXFIFO, (ioaddr + XP_ADDR));
 			insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
 			portp->stats.rxlost += len;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/sx.c linux.15p9/drivers/char/sx.c
--- linux.vanilla/drivers/char/sx.c	Wed Oct 20 01:12:36 1999
+++ linux.15p9/drivers/char/sx.c	Fri Jan 21 18:59:28 2000
@@ -4,7 +4,7 @@
  *  This driver will also support the older SI, and XIO cards.
  *
  *
- *   (C) 1998 R.E.Wolff@BitWizard.nl
+ *   (C) 1998 - 2000  R.E.Wolff@BitWizard.nl
  *
  *  Simon Allen (simonallen@cix.compulink.co.uk) wrote a previous
  *  version of this driver. Some fragments may have been copied. (none
@@ -33,6 +33,9 @@
  *
  * Revision history:
  * $Log: sx.c,v $
+ * Revision 1.30  2000/01/21 17:43:06  wolff
+ * - Added support for SX+
+ *
  * Revision 1.26  1999/08/05 15:22:14  wolff
  * - Port to 2.3.x
  * - Reformatted to Linus' liking.
@@ -185,8 +188,8 @@
  * */
 
 
-#define RCS_ID "$Id: sx.c,v 1.26 1999/08/05 15:22:14 wolff Exp $"
-#define RCS_REV "$Revision: 1.26 $"
+#define RCS_ID "$Id: sx.c,v 1.30 2000/01/21 17:43:06 wolff Exp $"
+#define RCS_REV "$Revision: 1.30 $"
 
 
 #include <linux/module.h>
@@ -222,153 +225,26 @@
 #include "sxboards.h"
 #include "sxwindow.h"
 
+#include <linux/compatmac.h>
+#include <linux/generic_serial.h>
+#include "sx.h"
+
 
 /* I don't think that this driver can handle more than 256 ports on
    one machine. You'll have to increase the number of boards in sx.h
    if you want more than 4 boards.  */
 
 
-/* ************************************************************** */
-/* * This section can be removed when 2.0 becomes outdated....  * */
-/* ************************************************************** */
-
-
-#if LINUX_VERSION_CODE < 0x020100    /* Less than 2.1.0 */
-#define TWO_ZERO
-#else
-#if LINUX_VERSION_CODE < 0x020200   /* less than 2.2.x */
-#warning "Please use a 2.2.x kernel. "
-#else
-#if LINUX_VERSION_CODE < 0x020300   /* less than 2.3.x */
-#define TWO_TWO
-#else
-#define TWO_THREE
-#endif
-#endif
-#endif
-
-#ifdef TWO_ZERO
-
-/* Here is the section that makes the 2.2 compatible driver source 
-   work for 2.0 too! We mostly try to adopt the "new thingies" from 2.2, 
-   and provide for compatibility stuff here if possible. */
-
-#include <linux/bios32.h>
-
-#define Get_user(a,b)                a = get_user(b)
-#define Put_user(a,b)                0,put_user(a,b)
-#define copy_to_user(a,b,c)          memcpy_tofs(a,b,c)
-
-static inline int copy_from_user(void *to,const void *from, int c) 
-{
-  memcpy_fromfs(to, from, c);
-  return 0;
-}
-
-#define pci_present                  pcibios_present
-#define pci_read_config_word         pcibios_read_config_word
-#define pci_read_config_dword        pcibios_read_config_dword
-
-static inline unsigned char get_irq (unsigned char bus, unsigned char fn)
-{
-	unsigned char t; 
-	pcibios_read_config_byte (bus, fn, PCI_INTERRUPT_LINE, &t);
-	return t;
-}
-
-static inline void *ioremap(unsigned long base, long length)
-{
-	if (base < 0x100000) return (void *)base;
-	return vremap (base, length);
-}
-
-#define my_iounmap(x, b)             (((long)x<0x100000)?0:vfree ((void*)x))
-
-#define capable(x)                   suser()
-
-#define queue_task                   queue_task_irq_off
-#define tty_flip_buffer_push(tty)    queue_task(&tty->flip.tqueue, &tq_timer)
-#define signal_pending(current)      (current->signal & ~current->blocked)
-#define schedule_timeout(to)         do {current->timeout = jiffies + (to);schedule ();} while (0)
-#define time_after(t1,t2)            (((long)t1-t2) > 0)
-
-
-#define test_and_set_bit(nr, addr)   set_bit(nr, addr)
-#define test_and_clear_bit(nr, addr) clear_bit(nr, addr)
-
-/* Not yet implemented on 2.0 */
-#define ASYNC_SPD_SHI  -1
-#define ASYNC_SPD_WARP -1
-
-
-/* Ugly hack: the driver_name doesn't exist in 2.0.x . So we define it
-   to the "name" field that does exist. As long as the assignments are
-   done in the right order, there is nothing to worry about. */
-#define driver_name           name 
-
-/* Should be in a header somewhere. They are in tty.h on 2.2 */
-#define TTY_HW_COOK_OUT       14 /* Flag to tell ntty what we can handle */
-#define TTY_HW_COOK_IN        15 /* in hardware - output and input       */
-
-/* The return type of a "close" routine. */
-#define INT                   void
-#define NO_ERROR              /* Nothing */
-
-#else
-
-/* The 2.2.x compatibility section. */
-#include <asm/uaccess.h>
-
-
-#define Get_user(a,b)         get_user(a,b)
-#define Put_user(a,b)         put_user(a,b)
-#define get_irq(pdev)         pdev->irq
-
-#define INT                   int
-#define NO_ERROR              0
-
-#define my_iounmap(x,b)       (iounmap((char *)(b)))
-
-#endif
-
-#ifndef TWO_THREE
-/* These are new in 2.3. The source now uses 2.3 syntax, and here is 
-   the compatibility define... */
-#define wait_queue_head_t struct wait_queue *
-#define DECLARE_MUTEX(name) struct semaphore name = MUTEX
-#define DECLARE_WAITQUEUE(wait, current) struct wait_queue wait = { current, NULL }
-
-#endif
-
-
-
-#include "generic_serial.h"
-#include "sx.h"
-
-
-/* ************************************************************** */
-/* *                End of compatibility section..              * */
-/* ************************************************************** */
-
-
-
 /* Why the hell am I defining these here? */
 #define SX_TYPE_NORMAL 1
 #define SX_TYPE_CALLOUT 2
 
-#ifndef SX_NORMAL_MAJOR
-/* This allows overriding on the compiler commandline, or in a "major.h" 
-   include or something like that */
-#define SX_NORMAL_MAJOR  32
-#define SX_CALLOUT_MAJOR 33
-#endif
 
 #ifndef PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8
 #define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000
 #endif
 
 
-
 /* Configurable options: 
    (Don't be too sure that it'll work if you toggle them) */
 
@@ -408,7 +284,7 @@
 static void sx_enable_rx_interrupts (void * ptr); 
 static int  sx_get_CD (void * ptr); 
 static void sx_shutdown_port (void * ptr);
-static void sx_set_real_termios (void  *ptr);
+static int  sx_set_real_termios (void  *ptr);
 static void sx_hungup (void  *ptr);
 static void sx_close (void  *ptr);
 static int sx_chars_in_buffer (void * ptr);
@@ -419,8 +295,6 @@
 static int sx_fw_open(struct inode *inode, struct file *filp);
 static INT sx_fw_release(struct inode *inode, struct file *filp);
 static int sx_init_drivers(void);
-void my_hd (unsigned char *addr, int len);
-
 
 
 static struct tty_driver sx_driver, sx_callout_driver;
@@ -591,6 +465,27 @@
 #define TIMEOUT_2 1000000
 
 
+#ifdef DEBUG
+static void my_hd (unsigned char *addr, int len)
+{
+	int i, j, ch;
+
+	for (i=0;i<len;i+=16) {
+		printk ("%08x ", (int) addr+i);
+		for (j=0;j<16;j++) {
+			printk ("%02x %s", addr[j+i], (j==7)?" ":"");
+		}
+		for (j=0;j<16;j++) {
+			ch = addr[j+i];
+			printk ("%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch));
+		}
+		printk ("\n");
+	}
+}
+#endif
+
+
+
 /* This needs redoing for Alpha -- REW -- Done. */
 
 inline void write_sx_byte (struct sx_board *board, int offset, u8 byte)
@@ -759,7 +654,7 @@
 		write_sx_byte (board, SX_CONFIG, SX_CONF_BUSEN);
 	} else {
 		/* Don't bug me about the clear_set. 
-		   I haven't the foggiest idea what it's about -- REW*/
+		   I haven't the foggiest idea what it's about -- REW */
 		write_sx_byte (board, SI2_ISA_RESET,    SI2_ISA_RESET_CLEAR);
 		write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
 	}
@@ -965,7 +860,7 @@
 /* Simon Allen's version of this routine was 225 lines long. 85 is a lot
    better. -- REW */
 
-static void sx_set_real_termios (void *ptr)
+static int sx_set_real_termios (void *ptr)
 {
 	struct sx_port *port = ptr;
 
@@ -1056,6 +951,7 @@
 	            O_OTHER(port->gs.tty));
 	/* port->c_dcd = sx_get_CD (port); */
 	func_exit ();
+	return 0;
 }
 
 
@@ -1113,7 +1009,7 @@
 
 		/* Don't copy pas the end of the source buffer */
 		if (c > SERIAL_XMIT_SIZE - port->gs.xmit_tail) 
-                	c = SERIAL_XMIT_SIZE - port->gs.xmit_tail;
+			c = SERIAL_XMIT_SIZE - port->gs.xmit_tail;
 
 		sx_dprintk (SX_DEBUG_TRANSMIT, " %d(%d) \n", 
 		            c, SERIAL_XMIT_SIZE- port->gs.xmit_tail);
@@ -1722,7 +1618,7 @@
 
 
 static int sx_fw_ioctl (struct inode *inode, struct file *filp,
-		         unsigned int cmd, unsigned long arg)
+                        unsigned int cmd, unsigned long arg)
 {
 	int rc = 0;
 	int *descr = (int *)arg, i;
@@ -1765,7 +1661,10 @@
 		board = &boards[arg];
 		break;
 	case SXIO_GET_TYPE:
-		rc = IS_SX_BOARD (board)? SX_TYPE_SX:SX_TYPE_SI;
+		rc = -1; /* If we manage to miss one, return error. */
+		if (IS_SX_BOARD (board)) rc = SX_TYPE_SX;
+		if (IS_CF_BOARD (board)) rc = SX_TYPE_CF;
+		if (IS_SI_BOARD (board)) rc = SX_TYPE_SI;
 		sx_dprintk (SX_DEBUG_FIRMWARE, "returning type= %d\n", rc);
 		break;
 	case SXIO_DO_RAMTEST:
@@ -1797,7 +1696,7 @@
 			for (i=0;i<nbytes;i += SX_CHUNK_SIZE) {
 				copy_from_user (tmp, (char *)data+i, 
 				                (i+SX_CHUNK_SIZE>nbytes)?nbytes-i:SX_CHUNK_SIZE);
-				memcpy_toio    ((char *) (board->base + offset + i), tmp, 
+				memcpy_toio    ((char *) (board->base2 + offset + i), tmp, 
 				                (i+SX_CHUNK_SIZE>nbytes)?nbytes-i:SX_CHUNK_SIZE);
 			}
 
@@ -1841,6 +1740,9 @@
 	case SXIO_GETGSDEBUG:
 		rc = gs_debug;
 		break;
+	case SXIO_GETNPORTS:
+		rc = sx_nports;
+		break;
 	default:
 		printk (KERN_WARNING "Unknown ioctl on firmware device (%x).\n", cmd);
 		break;
@@ -1991,13 +1893,17 @@
 
 	board->flags |= SX_BOARD_INITIALIZED;
 
+	if (read_sx_byte (board, 0))
+		/* CF boards may need this. */
+		write_sx_byte(board,0, 0);
+
 	/* This resets the processor again, to make sure it didn't do any
 	   foolish things while we were downloading the image */
 	if (!sx_reset (board))
 		return 0;
 
 	sx_start_board (board);
-
+	udelay (10);
 	if (!sx_busy_wait_neq (board, 0, 0xff, 0)) {
 		printk (KERN_ERR "sx: Ooops. Board won't initialize.\n");
 		return 0;
@@ -2158,52 +2064,56 @@
 	int i;
 
 	func_enter();
-	sx_dprintk (SX_DEBUG_PROBE, "Going to verify vpd prom at %x.\n", 
-	            board->base + SX_VPD_ROM);
 
-	if (sx_debug & SX_DEBUG_PROBE)
-		my_hd ((char *)(board->base + SX_VPD_ROM), 0x40);
+	if (!IS_CF_BOARD (board)) {    
+		sx_dprintk (SX_DEBUG_PROBE, "Going to verify vpd prom at %x.\n", 
+		            board->base + SX_VPD_ROM);
 
-	p = (char *) &vpdp;
-	for (i=0;i< sizeof (struct vpd_prom);i++)
-		*p++ = read_sx_byte (board, SX_VPD_ROM + i*2);
+		if (sx_debug & SX_DEBUG_PROBE)
+			my_hd ((char *)(board->base + SX_VPD_ROM), 0x40);
 
-	if (sx_debug & SX_DEBUG_PROBE)
-		my_hd ((char *)&vpdp, 0x20);
+		p = (char *) &vpdp;
+		for (i=0;i< sizeof (struct vpd_prom);i++)
+			*p++ = read_sx_byte (board, SX_VPD_ROM + i*2);
 
-	sx_dprintk (SX_DEBUG_PROBE, "checking identifier...\n");
+		if (sx_debug & SX_DEBUG_PROBE)
+			my_hd ((char *)&vpdp, 0x20);
 
-	if (strncmp (vpdp.identifier, SX_VPD_IDENT_STRING, 16) != 0) {
-		sx_dprintk (SX_DEBUG_PROBE, "Got non-SX identifier: '%s'\n", 
-		            vpdp.identifier); 
-		return 0;
+		sx_dprintk (SX_DEBUG_PROBE, "checking identifier...\n");
+
+		if (strncmp (vpdp.identifier, SX_VPD_IDENT_STRING, 16) != 0) {
+			sx_dprintk (SX_DEBUG_PROBE, "Got non-SX identifier: '%s'\n", 
+			            vpdp.identifier); 
+			return 0;
+		}
 	}
 
 	printheader ();
 
-	printk (KERN_DEBUG "sx: Found an SX board at %x\n", board->hw_base);
-	printk (KERN_DEBUG "sx: hw_rev: %d, assembly level: %d, uniq ID:%08x, ", 
-	        vpdp.hwrev, vpdp.hwass, vpdp.uniqid);
-	printk (           "Manufactured: %d/%d\n", 
-	        1970 + vpdp.myear, vpdp.mweek);
-
-
-	if ((((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) != SX_PCI_UNIQUEID1) &&
-	    (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) != SX_ISA_UNIQUEID1)) {
-		/* This might be a bit harsh. This was the primary reason the
-		   SX/ISA card didn't work at first... */
-		printk (KERN_ERR "sx: Hmm. Not an SX/PCI or SX/ISA card. Sorry: giving up.\n");
-		return (0);
-	}
-
-	if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) == SX_ISA_UNIQUEID1) {
-		if (board->base & 0x8000) {
-			printk (KERN_WARNING "sx: Warning: There may be hardware problems with the card at %x.\n", board->base);
-			printk (KERN_WARNING "sx: Read sx.txt for more info.\n");
+	if (!IS_CF_BOARD (board)) {
+		printk (KERN_DEBUG "sx: Found an SX board at %x\n", board->hw_base);
+		printk (KERN_DEBUG "sx: hw_rev: %d, assembly level: %d, uniq ID:%08x, ", 
+		        vpdp.hwrev, vpdp.hwass, vpdp.uniqid);
+		printk (           "Manufactured: %d/%d\n", 
+		        1970 + vpdp.myear, vpdp.mweek);
+
+
+		if ((((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) != SX_PCI_UNIQUEID1) &&
+		    (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) != SX_ISA_UNIQUEID1)) {
+			/* This might be a bit harsh. This was the primary reason the
+			   SX/ISA card didn't work at first... */
+			printk (KERN_ERR "sx: Hmm. Not an SX/PCI or SX/ISA card. Sorry: giving up.\n");
+			return (0);
+		}
+
+		if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) == SX_ISA_UNIQUEID1) {
+			if (board->base & 0x8000) {
+				printk (KERN_WARNING "sx: Warning: There may be hardware problems with the card at %x.\n", board->base);
+				printk (KERN_WARNING "sx: Read sx.txt for more info.\n");
+			}
 		}
 	}
 
-
 	board->nports = -1;
 
 	/* This resets the processor, and keeps it off the bus. */
@@ -2529,22 +2439,35 @@
 			tshort = (tint >> 16) & 0xffff;
 			sx_dprintk (SX_DEBUG_PROBE, "Got a specialix card: %x.\n", tint);
 			/* sx_dprintk (SX_DEBUG_PROBE, "pdev = %d/%d	(%x)\n", pdev, tint); */ 
-			if (tshort != 0x0200) {
+			if ((tshort != 0x0200) && (tshort != 0x0300)) {
 				sx_dprintk (SX_DEBUG_PROBE, "But it's not an SX card (%d)...\n", 
 				            tshort);
 				continue;
 			}
 			board = &boards[found];
 
-			pci_read_config_dword(pdev, PCI_BASE_ADDRESS_2, &tint);
+			board->flags &= ~SX_BOARD_TYPE;
+			board->flags |= (tshort == 0x200)?SX_PCI_BOARD:
+			                                  SX_CFPCI_BOARD;
+
+			/* CF boards use base address 3.... */
+			if (IS_CF_BOARD (board))
+				pci_read_config_dword(pdev, PCI_BASE_ADDRESS_3,
+				                      &tint);
+			else
+				pci_read_config_dword(pdev, PCI_BASE_ADDRESS_2,
+				                      &tint);
 			board->hw_base = tint & PCI_BASE_ADDRESS_MEM_MASK;
-			board->base = (ulong) ioremap(board->hw_base, SX_WINDOW_LEN);
+			board->base2 = 
+			board->base = (ulong) ioremap(board->hw_base, WINDOW_LEN (board));
+			/* Most of the stuff on the CF board is offset by
+			   0x18000 ....  */
+			if (IS_CF_BOARD (board)) board->base += 0x18000;
+
 			board->irq = get_irq (pdev);
-			board->flags &= ~SX_BOARD_TYPE;
-			board->flags |=  SX_PCI_BOARD;
 
-			sx_dprintk (SX_DEBUG_PROBE, "Got a specialix card: %x/%x(%d).\n", 
-			            tint, boards[found].base, board->irq);
+			sx_dprintk (SX_DEBUG_PROBE, "Got a specialix card: %x/%x(%d) %x.\n", 
+			            tint, boards[found].base, board->irq, board->flags);
 
 			if (probe_sx (board)) {
 				found++;
@@ -2599,7 +2522,7 @@
 }
 
 
-
+#ifdef MODULE
 void cleanup_module(void)
 {
 	int i; 
@@ -2633,33 +2556,9 @@
 	kfree (sx_termios_locked);
 	func_exit();
 }
-
-
-#ifdef DEBUG
-void my_hd (unsigned char *addr, int len)
-{
-	int i, j, ch;
-
-	for (i=0;i<len;i+=16) {
-		printk ("%08x ", (int) addr+i);
-		for (j=0;j<16;j++) {
-			printk ("%02x %s", addr[j+i], (j==7)?" ":"");
-		}
-		for (j=0;j<16;j++) {
-			ch = addr[j+i];
-			printk ("%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch));
-		}
-		printk ("\n");
-	}
-}
 #endif
 
-#ifdef MODULE
-#undef func_enter
-#undef func_exit
 
-#include "generic_serial.c"
-#endif
 
 
 /*
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/sx.h linux.15p9/drivers/char/sx.h
--- linux.vanilla/drivers/char/sx.h	Sat Aug 14 02:27:17 1999
+++ linux.15p9/drivers/char/sx.h	Fri Jan 21 18:59:28 2000
@@ -37,6 +37,7 @@
 struct sx_board {
   int magic;
   unsigned int base;
+  unsigned int base2;
   unsigned int hw_base;
   int port_base; /* Number of the first port */
   struct sx_port *ports;
@@ -65,19 +66,24 @@
 #define MOD_RS232DB25MALE 0x0a
 #endif
 
-
-#define SX_BOARD_PRESENT     0x00000001
+#define SI_ISA_BOARD         0x00000001
 #define SX_ISA_BOARD         0x00000002
 #define SX_PCI_BOARD         0x00000004
-#define SI_ISA_BOARD         0x00000008
-#define SX_BOARD_INITIALIZED 0x00000010
-#define SX_IRQ_ALLOCATED     0x00000020
+#define SX_CFPCI_BOARD       0x00000008
+#define SX_CFISA_BOARD       0x00000010
+
+#define SX_BOARD_PRESENT     0x00001000
+#define SX_BOARD_INITIALIZED 0x00002000
+#define SX_IRQ_ALLOCATED     0x00004000
 
-#define SX_BOARD_TYPE (SX_ISA_BOARD|SX_PCI_BOARD|SI_ISA_BOARD)
+#define SX_BOARD_TYPE        0x000000ff
+
+#define IS_SX_BOARD(board) (board->flags & (SX_PCI_BOARD | SX_CFPCI_BOARD | \
+                                            SX_ISA_BOARD | SX_CFISA_BOARD))
 
-#define IS_SX_BOARD(board) (board->flags & (SX_PCI_BOARD | SX_ISA_BOARD))
 #define IS_SI_BOARD(board) (board->flags & SI_ISA_BOARD)
 
+#define IS_CF_BOARD(board) (board->flags & (SX_CFISA_BOARD | SX_CFPCI_BOARD))
 
 #define SERIAL_TYPE_NORMAL 1
 
@@ -168,6 +174,7 @@
 #define SXIO_DO_RAMTEST     SPXL(0x07)
 #define SXIO_SETGSDEBUG     SPXL(0x08)
 #define SXIO_GETGSDEBUG     SPXL(0x09)
+#define SXIO_GETNPORTS      SPXL(0x0a)
 
 
 #ifndef SXCTL_MISC_MINOR 
@@ -175,6 +182,19 @@
 #define SXCTL_MISC_MINOR    167
 #endif
 
+#ifndef SX_NORMAL_MAJOR
+/* This allows overriding on the compiler commandline, or in a "major.h" 
+   include or something like that */
+#define SX_NORMAL_MAJOR  32
+#define SX_CALLOUT_MAJOR 33
+#endif
+
+
 #define SX_TYPE_SX          0x01
 #define SX_TYPE_SI          0x02
+#define SX_TYPE_CF          0x03
+
+
+#define WINDOW_LEN(board) (IS_CF_BOARD(board)?0x20000:SX_WINDOW_LEN)
+/*                         Need a #define for ^^^^^^^ !!! */
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/sysrq.c linux.15p9/drivers/char/sysrq.c
--- linux.vanilla/drivers/char/sysrq.c	Sat Aug 14 02:27:18 1999
+++ linux.15p9/drivers/char/sysrq.c	Wed Feb 16 18:35:25 2000
@@ -24,10 +24,6 @@
 
 #include <asm/ptrace.h>
 
-#ifdef CONFIG_APM
-#include <linux/apm_bios.h>
-#endif
-
 #ifdef CONFIG_MAGIC_SYSRQ
 int sysrq_enabled = 1;
 #endif
@@ -37,6 +33,9 @@
 extern int console_loglevel;
 extern struct vfsmount *vfsmntlist;
 
+/* Machine specific power off function */
+void (*sysrq_power_off)(void) = NULL;
+
 /* Send a signal to all user processes */
 
 static void send_sig_all(int sig, int even_init)
@@ -86,12 +85,12 @@
 		printk("Resetting\n");
 		machine_restart(NULL);
 		break;
-#ifdef CONFIG_APM
 	case 'o':					    /* O -- power off */
-		printk("Power off\n");
-		apm_power_off();
+		if (sysrq_power_off) {
+			printk("Power off\n");
+			sysrq_power_off();
+		}
 		break;
-#endif
 	case 's':					    /* S -- emergency sync */
 		printk("Emergency Sync\n");
 		emergency_sync_scheduled = EMERG_SYNC;
@@ -141,11 +140,10 @@
 		if (tty)
 			printk("saK ");
 #endif
-		printk("Boot "
-#ifdef CONFIG_APM
-		       "Off "
-#endif
-		       "Sync Unmount showPc showTasks showMem loglevel0-8 tErm kIll killalL\n");
+		printk("Boot ");
+		if (sysrq_power_off)
+			printk("Off ");
+		printk("Sync Unmount showPc showTasks showMem loglevel0-8 tErm kIll killalL\n");
 		/* Don't use 'A' as it's handled specially on the Sparc */
 	}
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/tty_io.c linux.15p9/drivers/char/tty_io.c
--- linux.vanilla/drivers/char/tty_io.c	Tue Jan  4 21:18:46 2000
+++ linux.15p9/drivers/char/tty_io.c	Tue Jan 18 00:52:11 2000
@@ -2205,6 +2205,9 @@
 #ifdef CONFIG_SX
 	sx_init();
 #endif
+#ifdef CONFIG_RIO
+	rio_init();
+#endif
 #ifdef CONFIG_8xx
         rs_8xx_init();
 #endif /* CONFIG_8xx */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/char/videodev.c linux.15p9/drivers/char/videodev.c
--- linux.vanilla/drivers/char/videodev.c	Wed Oct 20 01:12:36 1999
+++ linux.15p9/drivers/char/videodev.c	Mon Feb  7 12:30:39 2000
@@ -54,6 +54,9 @@
 #ifdef CONFIG_VIDEO_BWQCAM
 extern int init_bw_qcams(struct video_init *);
 #endif
+#ifdef CONFIG_VIDEO_CPIA
+extern int cpia_init(struct video_init *);
+#endif
 #ifdef CONFIG_VIDEO_PLANB
 extern int init_planbs(struct video_init *);
 #endif
@@ -104,6 +107,9 @@
 #endif	
 #ifdef CONFIG_VIDEO_BWQCAM
 	{"bw-qcam", init_bw_qcams},
+#endif        
+#ifdef CONFIG_VIDEO_CPIA
+        {"cpia", cpia_init},
 #endif	
 #ifdef CONFIG_VIDEO_PMS
 	{"PMS", init_pms_cards}, 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/isdn/Config.in linux.15p9/drivers/isdn/Config.in
--- linux.vanilla/drivers/isdn/Config.in	Tue Jan  4 21:18:46 2000
+++ linux.15p9/drivers/isdn/Config.in	Wed Jan 26 23:08:43 2000
@@ -12,68 +12,87 @@
 if [ "$CONFIG_ISDN_AUDIO" != "n" ]; then
    bool '    Support AT-Fax Class 2 commands' CONFIG_ISDN_TTY_FAX
 fi
-bool '  Support isdn diversion services' CONFIG_ISDN_DIVERSION
 if [ "$CONFIG_X25" != "n" ]; then
    bool '  X.25 PLP on top of ISDN' CONFIG_ISDN_X25
 fi
-dep_tristate '  ICN 2B and 4B support' CONFIG_ISDN_DRV_ICN $CONFIG_ISDN
-dep_tristate '  isdnloop support' CONFIG_ISDN_DRV_LOOP $CONFIG_ISDN
-dep_tristate '  PCBIT-D support' CONFIG_ISDN_DRV_PCBIT $CONFIG_ISDN
-dep_tristate '  HiSax SiemensChipSet driver support' CONFIG_ISDN_DRV_HISAX $CONFIG_ISDN
+
+mainmenu_option next_comment
+comment 'ISDN feature submodules'
+   dep_tristate 'isdnloop support' CONFIG_ISDN_DRV_LOOP $CONFIG_ISDN
+   bool 'Support isdn diversion services' CONFIG_ISDN_DIVERSION
+endmenu
+
+comment 'low-level hardware drivers'
+
+mainmenu_option next_comment
+comment 'Passive ISDN cards'
+dep_tristate 'HiSax SiemensChipSet driver support' CONFIG_ISDN_DRV_HISAX $CONFIG_ISDN
 if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then
-   bool '    HiSax Support for EURO/DSS1' CONFIG_HISAX_EURO
+   comment '  D-channel protocol features'
+   bool '  HiSax Support for EURO/DSS1' CONFIG_HISAX_EURO
    if [ "$CONFIG_HISAX_EURO" != "n" ]; then
-      bool '      Support for german chargeinfo' CONFIG_DE_AOC
-      bool '      Disable sending complete' CONFIG_HISAX_NO_SENDCOMPLETE
-      bool '      Disable sending low layer compatibility' CONFIG_HISAX_NO_LLC
+      bool '    Support for german chargeinfo' CONFIG_DE_AOC
+      bool '    Disable sending complete' CONFIG_HISAX_NO_SENDCOMPLETE
+      bool '    Disable sending low layer compatibility' CONFIG_HISAX_NO_LLC
+      bool '    Disable keypad protocol option' CONFIG_HISAX_NO_KEYPAD
    fi
-   bool '    HiSax Support for german 1TR6' CONFIG_HISAX_1TR6
-   bool '    HiSax Support for Teles 16.0/8.0' CONFIG_HISAX_16_0
-   bool '    HiSax Support for Teles 16.3 or PNP or PCMCIA' CONFIG_HISAX_16_3
-   bool '    HiSax Support for Teles PCI' CONFIG_HISAX_TELESPCI 
-   bool '    HiSax Support for Teles S0Box' CONFIG_HISAX_S0BOX 
-   bool '    HiSax Support for AVM A1 (Fritz)' CONFIG_HISAX_AVM_A1
-   bool '    HiSax Support for AVM PnP/PCI (Fritz!PnP/PCI)' CONFIG_HISAX_FRITZPCI
-   bool '    HiSax Support for AVM A1 PCMCIA (Fritz)' CONFIG_HISAX_AVM_A1_PCMCIA
-   bool '    HiSax Support for Elsa cards' CONFIG_HISAX_ELSA
-   bool '    HiSax Support for ITK ix1-micro Revision 2' CONFIG_HISAX_IX1MICROR2
-   bool '    HiSax Support for Eicon.Diehl Diva cards' CONFIG_HISAX_DIEHLDIVA
-   bool '    HiSax Support for ASUSCOM cards' CONFIG_HISAX_ASUSCOM
-   bool '    HiSax Support for TELEINT cards' CONFIG_HISAX_TELEINT
-   bool '    HiSax Support for HFC-S based cards' CONFIG_HISAX_HFCS
-   bool '    HiSax Support for Sedlbauer cards' CONFIG_HISAX_SEDLBAUER
-   bool '    HiSax Support for USR Sportster internal TA' CONFIG_HISAX_SPORTSTER
-   bool '    HiSax Support for MIC card' CONFIG_HISAX_MIC
-   bool '    HiSax Support for NETjet card' CONFIG_HISAX_NETJET
-   bool '    HiSax Support for Niccy PnP/PCI card' CONFIG_HISAX_NICCY
-   bool '    HiSax Support for Siemens I-Surf card' CONFIG_HISAX_ISURF
-   bool '    HiSax Support for HST Saphir card' CONFIG_HISAX_HSTSAPHIR
-   bool '    HiSax Support for Telekom A4T card' CONFIG_HISAX_BKM_A4T
-   bool '    HiSax Support for Scitel Quadro card' CONFIG_HISAX_SCT_QUADRO
-   bool '    HiSax Support for Gazel cards' CONFIG_HISAX_GAZEL
-   bool '    HiSax Support for HFC PCI-Bus cards' CONFIG_HISAX_HFC_PCI
-   bool '    HiSax Support for Winbond W6692 based cards' CONFIG_HISAX_W6692
+   bool '  HiSax Support for german 1TR6' CONFIG_HISAX_1TR6
+   comment '  HiSax supported cards'
+   bool '  Teles 16.0/8.0' CONFIG_HISAX_16_0
+   bool '  Teles 16.3 or PNP or PCMCIA' CONFIG_HISAX_16_3
+   bool '  Teles PCI' CONFIG_HISAX_TELESPCI 
+   bool '  Teles S0Box' CONFIG_HISAX_S0BOX 
+   bool '  AVM A1 (Fritz)' CONFIG_HISAX_AVM_A1
+   bool '  AVM PnP/PCI (Fritz!PnP/PCI)' CONFIG_HISAX_FRITZPCI
+   bool '  AVM A1 PCMCIA (Fritz)' CONFIG_HISAX_AVM_A1_PCMCIA
+   bool '  Elsa cards' CONFIG_HISAX_ELSA
+   bool '  ITK ix1-micro Revision 2' CONFIG_HISAX_IX1MICROR2
+   bool '  Eicon.Diehl Diva cards' CONFIG_HISAX_DIEHLDIVA
+   bool '  ASUSCOM ISA cards' CONFIG_HISAX_ASUSCOM
+   bool '  TELEINT cards' CONFIG_HISAX_TELEINT
+   bool '  HFC-S based cards' CONFIG_HISAX_HFCS
+   bool '  Sedlbauer cards' CONFIG_HISAX_SEDLBAUER
+   bool '  USR Sportster internal TA' CONFIG_HISAX_SPORTSTER
+   bool '  MIC card' CONFIG_HISAX_MIC
+   bool '  NETjet card' CONFIG_HISAX_NETJET
+   bool '  Niccy PnP/PCI card' CONFIG_HISAX_NICCY
+   bool '  Siemens I-Surf card' CONFIG_HISAX_ISURF
+   bool '  HST Saphir card' CONFIG_HISAX_HSTSAPHIR
+   bool '  Telekom A4T card' CONFIG_HISAX_BKM_A4T
+   bool '  Scitel Quadro card' CONFIG_HISAX_SCT_QUADRO
+   bool '  Gazel cards' CONFIG_HISAX_GAZEL
+   bool '  HFC PCI-Bus cards' CONFIG_HISAX_HFC_PCI
+   bool '  Winbond W6692 based cards' CONFIG_HISAX_W6692
    if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
-#      bool '    HiSax Support for TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU
+      bool '  HFC-S+, HFC-SP, HFC-PCMCIA cards' CONFIG_HISAX_HFC_SX
+#      bool '  TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU
       if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
-	 bool '    HiSax Support for Am7930' CONFIG_HISAX_AMD7930
+	 bool '  Am7930' CONFIG_HISAX_AMD7930
       fi
    fi
 fi
+endmenu
+
+mainmenu_option next_comment
+comment 'Active ISDN cards'
+dep_tristate 'ICN 2B and 4B support' CONFIG_ISDN_DRV_ICN $CONFIG_ISDN
+dep_tristate 'PCBIT-D support' CONFIG_ISDN_DRV_PCBIT $CONFIG_ISDN
 if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
-   dep_tristate '  Spellcaster support (EXPERIMENTAL)' CONFIG_ISDN_DRV_SC $CONFIG_ISDN
-   dep_tristate '  IBM Active 2000 support (EXPERIMENTAL)' CONFIG_ISDN_DRV_ACT2000 $CONFIG_ISDN
+   dep_tristate 'Spellcaster support (EXPERIMENTAL)' CONFIG_ISDN_DRV_SC $CONFIG_ISDN
+   dep_tristate 'IBM Active 2000 support (EXPERIMENTAL)' CONFIG_ISDN_DRV_ACT2000 $CONFIG_ISDN
 fi
-dep_tristate '  Eicon.Diehl active card support' CONFIG_ISDN_DRV_EICON $CONFIG_ISDN
+dep_tristate 'Eicon active card support' CONFIG_ISDN_DRV_EICON $CONFIG_ISDN
 if [ "$CONFIG_ISDN_DRV_EICON" != "n" ]; then
-   bool '    Eicon S,SX,SCOM,Quadro,S2M support' CONFIG_ISDN_DRV_EICON_ISA
+   bool '  Eicon S,SX,SCOM,Quadro,S2M support' CONFIG_ISDN_DRV_EICON_ISA
 fi
-dep_tristate '  AVM CAPI2.0 support' CONFIG_ISDN_DRV_AVMB1 $CONFIG_ISDN
+dep_tristate 'AVM CAPI2.0 support' CONFIG_ISDN_DRV_AVMB1 $CONFIG_ISDN
 if [ "$CONFIG_ISDN_DRV_AVMB1" != "n" ]; then
-   bool '    AVM B1 ISA support' CONFIG_ISDN_DRV_AVMB1_B1ISA
-   bool '    AVM B1 PCI support' CONFIG_ISDN_DRV_AVMB1_B1PCI
-   bool '    AVM T1/T1-B ISA support' CONFIG_ISDN_DRV_AVMB1_T1ISA
-   bool '    AVM B1/M1/M2 PCMCIA support' CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
-   bool '    AVM T1/T1-B PCI support' CONFIG_ISDN_DRV_AVMB1_T1PCI
-   bool '    Verbose reason code reporting (kernel size +=7K)' CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON
+   bool '  AVM B1 ISA support' CONFIG_ISDN_DRV_AVMB1_B1ISA
+   bool '  AVM B1 PCI support' CONFIG_ISDN_DRV_AVMB1_B1PCI
+   bool '  AVM T1/T1-B ISA support' CONFIG_ISDN_DRV_AVMB1_T1ISA
+   bool '  AVM B1/M1/M2 PCMCIA support' CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
+   bool '  AVM T1/T1-B PCI support' CONFIG_ISDN_DRV_AVMB1_T1PCI
+   bool '  AVM C4 support' CONFIG_ISDN_DRV_AVMB1_C4
+   bool '  Verbose reason code reporting (kernel size +=7K)' CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON
 fi
+endmenu
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/isdn/avmb1/c4.c linux.15p9/drivers/isdn/avmb1/c4.c
--- linux.vanilla/drivers/isdn/avmb1/c4.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/isdn/avmb1/c4.c	Wed Jan 26 23:08:43 2000
@@ -0,0 +1,1316 @@
+/*
+ * $Id: c4.c,v 1.2 2000/01/21 20:52:58 keil Exp $
+ * 
+ * Module for AVM C4 card.
+ * 
+ * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
+ * 
+ * $Log: c4.c,v $
+ * Revision 1.2  2000/01/21 20:52:58  keil
+ * pci_find_subsys as local function for 2.2.X kernel
+ *
+ * Revision 1.1  2000/01/20 10:51:37  calle
+ * Added driver for C4.
+ *
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/capi.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include "capicmd.h"
+#include "capiutil.h"
+#include "capilli.h"
+#include "avmcard.h"
+
+static char *revision = "$Revision: 1.2 $";
+
+#undef CONFIG_C4_DEBUG
+#undef CONFIG_C4_POLLDEBUG
+
+/* ------------------------------------------------------------- */
+
+#ifndef PCI_VENDOR_ID_DEC
+#define PCI_VENDOR_ID_DEC	0x1011
+#endif
+
+#ifndef PCI_DEVICE_ID_DEC_21285
+#define PCI_DEVICE_ID_DEC_21285	0x1065
+#endif
+
+#ifndef PCI_VENDOR_ID_AVM
+#define PCI_VENDOR_ID_AVM	0x1244
+#endif
+
+#ifndef PCI_DEVICE_ID_AVM_C4
+#define PCI_DEVICE_ID_AVM_C4	0x0800
+#endif
+
+/* ------------------------------------------------------------- */
+
+int suppress_pollack = 0;
+
+MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
+
+MODULE_PARM(suppress_pollack, "0-1i");
+
+/* ------------------------------------------------------------- */
+
+static struct capi_driver_interface *di;
+
+/* ------------------------------------------------------------- */
+
+static void c4_dispatch_tx(avmcard *card);
+
+/* ------------------------------------------------------------- */
+
+#define DC21285_DRAM_A0MR	0x40000000
+#define DC21285_DRAM_A1MR	0x40004000
+#define DC21285_DRAM_A2MR	0x40008000
+#define DC21285_DRAM_A3MR	0x4000C000
+
+#define	CAS_OFFSET	0x88
+
+#define DC21285_ARMCSR_BASE	0x42000000
+
+#define	PCI_OUT_INT_STATUS	0x30
+#define	PCI_OUT_INT_MASK	0x34
+#define	MAILBOX_0		0x50
+#define	MAILBOX_1		0x54
+#define	MAILBOX_2		0x58
+#define	MAILBOX_3		0x5C
+#define	DOORBELL		0x60
+#define	DOORBELL_SETUP		0x64
+
+#define CHAN_1_CONTROL		0x90
+#define CHAN_2_CONTROL		0xB0
+#define DRAM_TIMING		0x10C
+#define DRAM_ADDR_SIZE_0	0x110
+#define DRAM_ADDR_SIZE_1	0x114
+#define DRAM_ADDR_SIZE_2	0x118
+#define DRAM_ADDR_SIZE_3	0x11C
+#define	SA_CONTROL		0x13C
+#define	XBUS_CYCLE		0x148
+#define	XBUS_STROBE		0x14C
+#define	DBELL_PCI_MASK		0x150
+#define DBELL_SA_MASK		0x154
+
+#define SDRAM_SIZE		0x1000000
+
+/* ------------------------------------------------------------- */
+
+#define	MBOX_PEEK_POKE		MAILBOX_0
+
+#define DBELL_ADDR		0x01
+#define DBELL_DATA		0x02
+#define DBELL_RNWR		0x40
+#define DBELL_INIT		0x80
+
+/* ------------------------------------------------------------- */
+
+#define	MBOX_UP_ADDR		MAILBOX_0
+#define	MBOX_UP_LEN		MAILBOX_1
+#define	MBOX_DOWN_ADDR		MAILBOX_2
+#define	MBOX_DOWN_LEN		MAILBOX_3
+
+#define	DBELL_UP_HOST		0x00000100
+#define	DBELL_UP_ARM		0x00000200
+#define	DBELL_DOWN_HOST		0x00000400
+#define	DBELL_DOWN_ARM		0x00000800
+#define	DBELL_RESET_HOST	0x40000000
+#define	DBELL_RESET_ARM		0x80000000
+
+/* ------------------------------------------------------------- */
+
+#define	DRAM_TIMING_DEF		0x001A01A5
+#define DRAM_AD_SZ_DEF0		0x00000045
+#define DRAM_AD_SZ_NULL		0x00000000
+
+#define SA_CTL_ALLRIGHT		0x64AA0271
+
+#define	INIT_XBUS_CYCLE		0x100016DB
+#define	INIT_XBUS_STROBE	0xF1F1F1F1
+
+/* ------------------------------------------------------------- */
+
+#define	RESET_TIMEOUT		(15*HZ)	/* 15 sec */
+#define	PEEK_POKE_TIMEOUT	(HZ/10)	/* 0.1 sec */
+
+/* ------------------------------------------------------------- */
+
+#define c4outmeml(addr, value)	writel(value, addr)
+#define c4inmeml(addr)	readl(addr)
+#define c4outmemw(addr, value)	writew(value, addr)
+#define c4inmemw(addr)	readw(addr)
+#define c4outmemb(addr, value)	writeb(value, addr)
+#define c4inmemb(addr)	readb(addr)
+
+/* ------------------------------------------------------------- */
+
+static inline int wait_for_doorbell(avmcard *card, unsigned long t)
+{
+	unsigned long stop;
+
+	stop = jiffies + t;
+	while (c4inmeml(card->mbase+DOORBELL) != 0xffffffff) {
+		if (!time_before(jiffies, stop))
+			return -1;
+	}
+	return 0;
+}
+
+static int c4_poke(avmcard *card,  unsigned long off, unsigned long value)
+{
+
+	if (wait_for_doorbell(card, HZ/10) < 0)
+		return -1;
+	
+	c4outmeml(card->mbase+MBOX_PEEK_POKE, off);
+	c4outmeml(card->mbase+DOORBELL, DBELL_ADDR);
+
+	if (wait_for_doorbell(card, HZ/10) < 0)
+		return -1;
+
+	c4outmeml(card->mbase+MBOX_PEEK_POKE, value);
+	c4outmeml(card->mbase+DOORBELL, DBELL_DATA | DBELL_ADDR);
+
+	return 0;
+}
+
+static int c4_peek(avmcard *card,  unsigned long off, unsigned long *valuep)
+{
+	if (wait_for_doorbell(card, HZ/10) < 0)
+		return -1;
+
+	c4outmeml(card->mbase+MBOX_PEEK_POKE, off);
+	c4outmeml(card->mbase+DOORBELL, DBELL_RNWR | DBELL_ADDR);
+
+	if (wait_for_doorbell(card, HZ/10) < 0)
+		return -1;
+
+	*valuep = c4inmeml(card->mbase+MBOX_PEEK_POKE);
+
+	return 0;
+}
+
+/* ------------------------------------------------------------- */
+
+static int c4_load_t4file(avmcard *card, capiloaddatapart * t4file)
+{
+	__u32 val;
+	unsigned char *dp;
+	int left, retval;
+	__u32 loadoff = 0;
+
+	dp = t4file->data;
+	left = t4file->len;
+	while (left >= sizeof(__u32)) {
+	        if (t4file->user) {
+			retval = copy_from_user(&val, dp, sizeof(val));
+			if (retval)
+				return -EFAULT;
+		} else {
+			memcpy(&val, dp, sizeof(val));
+		}
+		if (c4_poke(card, loadoff, val)) {
+			printk(KERN_ERR "%s: corrupted firmware file ?\n",
+					card->name);
+			return -EIO;
+		}
+		left -= sizeof(__u32);
+		dp += sizeof(__u32);
+		loadoff += sizeof(__u32);
+	}
+	if (left) {
+		val = 0;
+		if (t4file->user) {
+			retval = copy_from_user(&val, dp, left);
+			if (retval)
+				return -EFAULT;
+		} else {
+			memcpy(&val, dp, left);
+		}
+		if (c4_poke(card, loadoff, val)) {
+			printk(KERN_ERR "%s: corrupted firmware file ?\n",
+					card->name);
+			return -EIO;
+		}
+	}
+	return 0;
+}
+
+/* ------------------------------------------------------------- */
+
+static inline void _put_byte(void **pp, __u8 val)
+{
+	__u8 *s = *pp;
+	*s++ = val;
+	*pp = s;
+}
+
+static inline void _put_word(void **pp, __u32 val)
+{
+	__u8 *s = *pp;
+	*s++ = val & 0xff;
+	*s++ = (val >> 8) & 0xff;
+	*s++ = (val >> 16) & 0xff;
+	*s++ = (val >> 24) & 0xff;
+	*pp = s;
+}
+
+static inline void _put_slice(void **pp, unsigned char *dp, unsigned int len)
+{
+	unsigned i = len;
+	_put_word(pp, i);
+	while (i-- > 0)
+		_put_byte(pp, *dp++);
+}
+
+static inline __u8 _get_byte(void **pp)
+{
+	__u8 *s = *pp;
+	__u8 val;
+	val = *s++;
+	*pp = s;
+	return val;
+}
+
+static inline __u32 _get_word(void **pp)
+{
+	__u8 *s = *pp;
+	__u32 val;
+	val = *s++;
+	val |= (*s++ << 8);
+	val |= (*s++ << 16);
+	val |= (*s++ << 24);
+	*pp = s;
+	return val;
+}
+
+static inline __u32 _get_slice(void **pp, unsigned char *dp)
+{
+	unsigned int len, i;
+
+	len = i = _get_word(pp);
+	while (i-- > 0) *dp++ = _get_byte(pp);
+	return len;
+}
+
+/* ------------------------------------------------------------- */
+
+static void c4_reset(avmcard *card)
+{
+	unsigned long stop;
+
+	c4outmeml(card->mbase+DOORBELL, DBELL_RESET_ARM);
+
+	stop = jiffies + HZ*10;
+	while (c4inmeml(card->mbase+DOORBELL) != 0xffffffff) {
+		if (!time_before(jiffies, stop))
+			return;
+		c4outmeml(card->mbase+DOORBELL, DBELL_ADDR);
+	}
+
+	c4_poke(card, DC21285_ARMCSR_BASE + CHAN_1_CONTROL, 0);
+	c4_poke(card, DC21285_ARMCSR_BASE + CHAN_2_CONTROL, 0);
+}
+
+/* ------------------------------------------------------------- */
+
+static int c4_detect(avmcard *card)
+{
+	unsigned long stop, dummy;
+
+	c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x0c);
+	if (c4inmeml(card->mbase+PCI_OUT_INT_MASK) != 0x0c)
+		return	1;
+
+	c4outmeml(card->mbase+DOORBELL, DBELL_RESET_ARM);
+
+	stop = jiffies + HZ*10;
+	while (c4inmeml(card->mbase+DOORBELL) != 0xffffffff) {
+		if (!time_before(jiffies, stop))
+			return 2;
+		c4outmeml(card->mbase+DOORBELL, DBELL_ADDR);
+	}
+
+	c4_poke(card, DC21285_ARMCSR_BASE + CHAN_1_CONTROL, 0);
+	c4_poke(card, DC21285_ARMCSR_BASE + CHAN_2_CONTROL, 0);
+
+	c4outmeml(card->mbase+MAILBOX_0, 0x55aa55aa);
+	if (c4inmeml(card->mbase+MAILBOX_0) != 0x55aa55aa) return 3;
+
+	c4outmeml(card->mbase+MAILBOX_0, 0xaa55aa55);
+	if (c4inmeml(card->mbase+MAILBOX_0) != 0xaa55aa55) return 4;
+
+	if (c4_poke(card, DC21285_ARMCSR_BASE+DBELL_SA_MASK, 0)) return 5;
+	if (c4_poke(card, DC21285_ARMCSR_BASE+DBELL_PCI_MASK, 0)) return 6;
+	if (c4_poke(card, DC21285_ARMCSR_BASE+SA_CONTROL, SA_CTL_ALLRIGHT))
+		return 7;
+	if (c4_poke(card, DC21285_ARMCSR_BASE+XBUS_CYCLE, INIT_XBUS_CYCLE))
+		return 8;
+	if (c4_poke(card, DC21285_ARMCSR_BASE+XBUS_STROBE, INIT_XBUS_STROBE))
+		return 8;
+	if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_TIMING, 0)) return 9;
+
+        udelay(1000);
+
+	if (c4_peek(card, DC21285_DRAM_A0MR, &dummy)) return 10;
+	if (c4_peek(card, DC21285_DRAM_A1MR, &dummy)) return 11;
+	if (c4_peek(card, DC21285_DRAM_A2MR, &dummy)) return 12;
+	if (c4_peek(card, DC21285_DRAM_A3MR, &dummy)) return 13;
+
+	if (c4_poke(card, DC21285_DRAM_A0MR+CAS_OFFSET, 0)) return 14;
+	if (c4_poke(card, DC21285_DRAM_A1MR+CAS_OFFSET, 0)) return 15;
+	if (c4_poke(card, DC21285_DRAM_A2MR+CAS_OFFSET, 0)) return 16;
+	if (c4_poke(card, DC21285_DRAM_A3MR+CAS_OFFSET, 0)) return 17;
+
+        udelay(1000);
+
+	if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_TIMING, DRAM_TIMING_DEF))
+		return 18;
+
+	if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_ADDR_SIZE_0,DRAM_AD_SZ_DEF0))
+		return 19;
+	if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_ADDR_SIZE_1,DRAM_AD_SZ_NULL))
+		return 20;
+	if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_ADDR_SIZE_2,DRAM_AD_SZ_NULL))
+		return 21;
+	if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_ADDR_SIZE_3,DRAM_AD_SZ_NULL))
+		return 22;
+
+	/* Transputer test */
+	
+	if (   c4_poke(card, 0x000000, 0x11111111)
+	    || c4_poke(card, 0x400000, 0x22222222)
+	    || c4_poke(card, 0x800000, 0x33333333)
+	    || c4_poke(card, 0xC00000, 0x44444444))
+		return 23;
+
+	if (   c4_peek(card, 0x000000, &dummy) || dummy != 0x11111111
+	    || c4_peek(card, 0x400000, &dummy) || dummy != 0x22222222
+	    || c4_peek(card, 0x800000, &dummy) || dummy != 0x33333333
+	    || c4_peek(card, 0xC00000, &dummy) || dummy != 0x44444444)
+		return 24;
+
+	if (   c4_poke(card, 0x000000, 0x55555555)
+	    || c4_poke(card, 0x400000, 0x66666666)
+	    || c4_poke(card, 0x800000, 0x77777777)
+	    || c4_poke(card, 0xC00000, 0x88888888))
+		return 25;
+
+	if (   c4_peek(card, 0x000000, &dummy) || dummy != 0x55555555
+	    || c4_peek(card, 0x400000, &dummy) || dummy != 0x66666666
+	    || c4_peek(card, 0x800000, &dummy) || dummy != 0x77777777
+	    || c4_peek(card, 0xC00000, &dummy) || dummy != 0x88888888)
+		return 26;
+
+	return 0;
+}
+
+/* ------------------------------------------------------------- */
+
+static void c4_dispatch_tx(avmcard *card)
+{
+	avmcard_dmainfo *dma = card->dma;
+	unsigned long flags;
+	struct sk_buff *skb;
+	__u8 cmd, subcmd;
+	__u16 len;
+	__u32 txlen;
+	void *p;
+	
+	save_flags(flags);
+	cli();
+
+	if (card->csr & DBELL_DOWN_ARM) { /* tx busy */
+	        restore_flags(flags);
+		return;
+	}
+
+	skb = skb_dequeue(&dma->send_queue);
+	if (!skb) {
+#ifdef CONFIG_C4_DEBUG
+		printk(KERN_DEBUG "%s: tx underrun\n", card->name);
+#endif
+	        restore_flags(flags);
+		return;
+	}
+
+	len = CAPIMSG_LEN(skb->data);
+
+	if (len) {
+		cmd = CAPIMSG_COMMAND(skb->data);
+		subcmd = CAPIMSG_SUBCOMMAND(skb->data);
+
+		p = dma->sendbuf;
+
+		if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
+			__u16 dlen = CAPIMSG_DATALEN(skb->data);
+			_put_byte(&p, SEND_DATA_B3_REQ);
+			_put_slice(&p, skb->data, len);
+			_put_slice(&p, skb->data + len, dlen);
+		} else {
+			_put_byte(&p, SEND_MESSAGE);
+			_put_slice(&p, skb->data, len);
+		}
+		txlen = (__u8 *)p - (__u8 *)dma->sendbuf;
+#ifdef CONFIG_C4_DEBUG
+		printk(KERN_DEBUG "%s: tx put msg len=%d\n", card->name, txlen);
+#endif
+	} else {
+		txlen = skb->len-2;
+#ifdef CONFIG_C4_POLLDEBUG
+		if (skb->data[2] == SEND_POLLACK)
+			printk(KERN_INFO "%s: ack to c4\n", card->name);
+#endif
+#ifdef CONFIG_C4_DEBUG
+		printk(KERN_DEBUG "%s: tx put 0x%x len=%d\n",
+				card->name, skb->data[2], txlen);
+#endif
+		memcpy(dma->sendbuf, skb->data+2, skb->len-2);
+	}
+	txlen = (txlen + 3) & ~3;
+
+	c4outmeml(card->mbase+MBOX_DOWN_ADDR, virt_to_phys(dma->sendbuf));
+	c4outmeml(card->mbase+MBOX_DOWN_LEN, txlen);
+
+	card->csr |= DBELL_DOWN_ARM;
+
+	c4outmeml(card->mbase+DOORBELL, DBELL_DOWN_ARM);
+
+	restore_flags(flags);
+	dev_kfree_skb(skb);
+}
+
+/* ------------------------------------------------------------- */
+
+static void queue_pollack(avmcard *card)
+{
+	struct sk_buff *skb;
+	void *p;
+
+	skb = alloc_skb(3, GFP_ATOMIC);
+	if (!skb) {
+		printk(KERN_CRIT "%s: no memory, lost poll ack\n",
+					card->name);
+		return;
+	}
+	p = skb->data;
+	_put_byte(&p, 0);
+	_put_byte(&p, 0);
+	_put_byte(&p, SEND_POLLACK);
+	skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
+
+	skb_queue_tail(&card->dma->send_queue, skb);
+	c4_dispatch_tx(card);
+}
+
+/* ------------------------------------------------------------- */
+
+static void c4_handle_rx(avmcard *card)
+{
+	avmcard_dmainfo *dma = card->dma;
+	struct capi_ctr *ctrl;
+	avmctrl_info *cinfo;
+	struct sk_buff *skb;
+	void *p = dma->recvbuf;
+	__u32 ApplId, MsgLen, DataB3Len, NCCI, WindowSize;
+	__u8 b1cmd =  _get_byte(&p);
+	__u32 cidx;
+
+
+#ifdef CONFIG_C4_DEBUG
+	printk(KERN_DEBUG "%s: rx 0x%x len=%lu\n", card->name,
+				b1cmd, (unsigned long)dma->recvlen);
+#endif
+	
+	switch (b1cmd) {
+	case RECEIVE_DATA_B3_IND:
+
+		ApplId = (unsigned) _get_word(&p);
+		MsgLen = _get_slice(&p, card->msgbuf);
+		DataB3Len = _get_slice(&p, card->databuf);
+		cidx = CAPIMSG_CONTROLLER(card->msgbuf)-card->cardnr;
+		if (cidx > 3) cidx = 0;
+		ctrl = card->ctrlinfo[cidx].capi_ctrl;
+
+		if (MsgLen < 30) { /* not CAPI 64Bit */
+			memset(card->msgbuf+MsgLen, 0, 30-MsgLen);
+			MsgLen = 30;
+			CAPIMSG_SETLEN(card->msgbuf, 30);
+		}
+		if (!(skb = alloc_skb(DataB3Len+MsgLen, GFP_ATOMIC))) {
+			printk(KERN_ERR "%s: incoming packet dropped\n",
+					card->name);
+		} else {
+			memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
+			memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len);
+			ctrl->handle_capimsg(ctrl, ApplId, skb);
+		}
+		break;
+
+	case RECEIVE_MESSAGE:
+
+		ApplId = (unsigned) _get_word(&p);
+		MsgLen = _get_slice(&p, card->msgbuf);
+		cidx = CAPIMSG_CONTROLLER(card->msgbuf)-card->cardnr;
+		if (cidx > 3) cidx = 0;
+		ctrl = card->ctrlinfo[cidx].capi_ctrl;
+
+		if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
+			printk(KERN_ERR "%s: incoming packet dropped\n",
+					card->name);
+		} else {
+			memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
+			ctrl->handle_capimsg(ctrl, ApplId, skb);
+		}
+		break;
+
+	case RECEIVE_NEW_NCCI:
+
+		ApplId = _get_word(&p);
+		NCCI = _get_word(&p);
+		WindowSize = _get_word(&p);
+		cidx = (NCCI&0x7f) - card->cardnr;
+		if (cidx > 3) cidx = 0;
+		ctrl = card->ctrlinfo[cidx].capi_ctrl;
+
+		ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize);
+
+		break;
+
+	case RECEIVE_FREE_NCCI:
+
+		ApplId = _get_word(&p);
+		NCCI = _get_word(&p);
+
+		if (NCCI != 0xffffffff) {
+			cidx = (NCCI&0x7f) - card->cardnr;
+			if (cidx > 3) cidx = 0;
+			ctrl = card->ctrlinfo[cidx].capi_ctrl;
+			ctrl->free_ncci(ctrl, ApplId, NCCI);
+		} else {
+			for (cidx=0; cidx < 4; cidx++) {
+				ctrl = card->ctrlinfo[cidx].capi_ctrl;
+				ctrl->appl_released(ctrl, ApplId);
+			}
+		}
+		break;
+
+	case RECEIVE_START:
+#ifdef CONFIG_C4_POLLDEBUG
+		printk(KERN_INFO "%s: poll from c4\n", card->name);
+#endif
+		if (!suppress_pollack)
+			queue_pollack(card);
+		for (cidx=0; cidx < 4; cidx++) {
+			ctrl = card->ctrlinfo[cidx].capi_ctrl;
+			ctrl->resume_output(ctrl);
+		}
+		break;
+
+	case RECEIVE_STOP:
+		for (cidx=0; cidx < 4; cidx++) {
+			ctrl = card->ctrlinfo[cidx].capi_ctrl;
+			ctrl->suspend_output(ctrl);
+		}
+		break;
+
+	case RECEIVE_INIT:
+
+	        cidx = card->nlogcontr++;
+	        cinfo = &card->ctrlinfo[cidx];
+		ctrl = cinfo->capi_ctrl;
+		cinfo->versionlen = _get_slice(&p, cinfo->versionbuf);
+		b1_parse_version(cinfo);
+		printk(KERN_INFO "%s: %s-card (%s) now active\n",
+		       card->name,
+		       cinfo->version[VER_CARDTYPE],
+		       cinfo->version[VER_DRIVER]);
+		ctrl->ready(cinfo->capi_ctrl);
+		break;
+
+	case RECEIVE_TASK_READY:
+		ApplId = (unsigned) _get_word(&p);
+		MsgLen = _get_slice(&p, card->msgbuf);
+		card->msgbuf[MsgLen--] = 0;
+		while (    MsgLen >= 0
+		       && (   card->msgbuf[MsgLen] == '\n'
+			   || card->msgbuf[MsgLen] == '\r'))
+			card->msgbuf[MsgLen--] = 0;
+		printk(KERN_INFO "%s: task %d \"%s\" ready.\n",
+				card->name, ApplId, card->msgbuf);
+		break;
+
+	case RECEIVE_DEBUGMSG:
+		MsgLen = _get_slice(&p, card->msgbuf);
+		card->msgbuf[MsgLen--] = 0;
+		while (    MsgLen >= 0
+		       && (   card->msgbuf[MsgLen] == '\n'
+			   || card->msgbuf[MsgLen] == '\r'))
+			card->msgbuf[MsgLen--] = 0;
+		printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf);
+		break;
+
+	default:
+		printk(KERN_ERR "%s: c4_interrupt: 0x%x ???\n",
+				card->name, b1cmd);
+		return;
+	}
+}
+
+/* ------------------------------------------------------------- */
+
+static void c4_handle_interrupt(avmcard *card)
+{
+	__u32 status = c4inmeml(card->mbase+DOORBELL);
+
+	if (status & DBELL_RESET_HOST) {
+		int i;
+		c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x0c);
+		printk(KERN_ERR "%s: unexpected reset\n", card->name);
+                for (i=0; i < 4; i++) {
+			avmctrl_info *cinfo = &card->ctrlinfo[i];
+			memset(cinfo->version, 0, sizeof(cinfo->version));
+			if (cinfo->capi_ctrl)
+				cinfo->capi_ctrl->reseted(cinfo->capi_ctrl);
+		}
+		return;
+	}
+
+	status &= (DBELL_UP_HOST | DBELL_DOWN_HOST);
+	if (!status)
+		return;
+	c4outmeml(card->mbase+DOORBELL, status);
+
+	if ((status & DBELL_UP_HOST) != 0) {
+		card->dma->recvlen = c4inmeml(card->mbase+MBOX_UP_LEN);
+		c4outmeml(card->mbase+MBOX_UP_LEN, 0);
+		c4_handle_rx(card);
+		card->dma->recvlen = 0;
+		c4outmeml(card->mbase+MBOX_UP_LEN, sizeof(card->dma->recvbuf));
+		c4outmeml(card->mbase+DOORBELL, DBELL_UP_ARM);
+	}
+
+	if ((status & DBELL_DOWN_HOST) != 0) {
+		card->csr &= ~DBELL_DOWN_ARM;
+	        c4_dispatch_tx(card);
+	} else if (card->csr & DBELL_DOWN_HOST) {
+		if (c4inmeml(card->mbase+MBOX_DOWN_LEN) == 0) {
+		        card->csr &= ~DBELL_DOWN_ARM;
+			c4_dispatch_tx(card);
+		}
+	}
+}
+
+static void c4_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
+{
+	avmcard *card;
+
+	card = (avmcard *) devptr;
+
+	if (!card) {
+		printk(KERN_WARNING "%s: interrupt: wrong device\n", card->name);
+		return;
+	}
+	if (card->interrupt) {
+		printk(KERN_ERR "%s: reentering interrupt hander\n",
+				card->name);
+		return;
+	}
+
+	card->interrupt = 1;
+
+	c4_handle_interrupt(card);
+
+	card->interrupt = 0;
+}
+
+/* ------------------------------------------------------------- */
+
+static void c4_send_init(avmcard *card)
+{
+	struct sk_buff *skb;
+	void *p;
+
+	skb = alloc_skb(15, GFP_ATOMIC);
+	if (!skb) {
+		printk(KERN_CRIT "%s: no memory, lost register appl.\n",
+					card->name);
+		return;
+	}
+	p = skb->data;
+	_put_byte(&p, 0);
+	_put_byte(&p, 0);
+	_put_byte(&p, SEND_INIT);
+	_put_word(&p, AVM_NAPPS);
+	_put_word(&p, AVM_NCCI_PER_CHANNEL*30);
+	_put_word(&p, card->cardnr - 1);
+	skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
+
+	skb_queue_tail(&card->dma->send_queue, skb);
+	c4_dispatch_tx(card);
+}
+
+static int c4_send_config(avmcard *card, capiloaddatapart * config)
+{
+	struct sk_buff *skb;
+	__u8 val[sizeof(__u32)];
+	void *p;
+	unsigned char *dp;
+	int left, retval;
+	
+	skb = alloc_skb(12 + ((config->len+3)/4)*5, GFP_ATOMIC);
+	if (!skb) {
+		printk(KERN_CRIT "%s: no memory, can't send config.\n",
+					card->name);
+		return	-ENOMEM;
+	}
+	p = skb->data;
+	_put_byte(&p, 0);
+	_put_byte(&p, 0);
+	_put_byte(&p, SEND_CONFIG);
+	_put_word(&p, 1);
+	_put_byte(&p, SEND_CONFIG);
+	_put_word(&p, config->len);	/* 12 */
+
+	dp = config->data;
+	left = config->len;
+	while (left >= sizeof(__u32)) {
+	        if (config->user) {
+			retval = copy_from_user(val, dp, sizeof(val));
+			if (retval) {
+				dev_kfree_skb(skb);
+				return -EFAULT;
+			}
+		} else {
+			memcpy(val, dp, sizeof(val));
+		}
+		_put_byte(&p, SEND_CONFIG);
+		_put_byte(&p, val[0]);
+		_put_byte(&p, val[1]);
+		_put_byte(&p, val[2]);
+		_put_byte(&p, val[3]);
+		left -= sizeof(val);
+		dp += sizeof(val);
+	}
+	if (left) {
+		memset(val, 0, sizeof(val));
+		if (config->user) {
+			retval = copy_from_user(&val, dp, left);
+			if (retval) {
+				dev_kfree_skb(skb);
+				return -EFAULT;
+			}
+		} else {
+			memcpy(&val, dp, left);
+		}
+		_put_byte(&p, SEND_CONFIG);
+		_put_byte(&p, val[0]);
+		_put_byte(&p, val[1]);
+		_put_byte(&p, val[2]);
+		_put_byte(&p, val[3]);
+	}
+
+	skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
+
+	skb_queue_tail(&card->dma->send_queue, skb);
+	c4_dispatch_tx(card);
+
+	return 0;
+}
+
+static int c4_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
+{
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+	avmcard *card = cinfo->card;
+	unsigned long flags;
+	int retval;
+
+	if ((retval = c4_load_t4file(card, &data->firmware))) {
+		printk(KERN_ERR "%s: failed to load t4file!!\n",
+					card->name);
+		c4_reset(card);
+		return retval;
+	}
+
+	save_flags(flags);
+	cli();
+
+	card->csr = 0;
+	c4outmeml(card->mbase+MBOX_UP_LEN, 0);
+	c4outmeml(card->mbase+MBOX_DOWN_LEN, 0);
+	c4outmeml(card->mbase+DOORBELL, DBELL_INIT);
+	udelay(1000);
+	c4outmeml(card->mbase+DOORBELL,
+			DBELL_UP_HOST | DBELL_DOWN_HOST | DBELL_RESET_HOST);
+
+	c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x08);
+
+	card->dma->recvlen = 0;
+	c4outmeml(card->mbase+MBOX_UP_ADDR, virt_to_phys(card->dma->recvbuf));
+	c4outmeml(card->mbase+MBOX_UP_LEN, sizeof(card->dma->recvbuf));
+	c4outmeml(card->mbase+DOORBELL, DBELL_UP_ARM);
+	restore_flags(flags);
+
+	if (data->configuration.len > 0 && data->configuration.data)
+		c4_send_config(card, &data->configuration);
+
+        c4_send_init(card);
+
+	return 0;
+}
+
+
+void c4_reset_ctr(struct capi_ctr *ctrl)
+{
+	avmcard *card = ((avmctrl_info *)(ctrl->driverdata))->card;
+	avmctrl_info *cinfo;
+	int i;
+
+ 	c4_reset(card);
+
+        for (i=0; i < 4; i++) {
+		cinfo = &card->ctrlinfo[i];
+		memset(cinfo->version, 0, sizeof(cinfo->version));
+		if (cinfo->capi_ctrl)
+			cinfo->capi_ctrl->reseted(cinfo->capi_ctrl);
+	}
+}
+
+static void c4_remove_ctr(struct capi_ctr *ctrl)
+{
+	avmcard *card = ((avmctrl_info *)(ctrl->driverdata))->card;
+	avmctrl_info *cinfo;
+	int i;
+
+ 	c4_reset(card);
+
+        for (i=0; i <= 4; i++) {
+		cinfo = &card->ctrlinfo[i];
+		if (cinfo->capi_ctrl)
+			di->detach_ctr(cinfo->capi_ctrl);
+	}
+
+	free_irq(card->irq, card);
+	iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
+	release_region(card->port, AVMB1_PORTLEN);
+	ctrl->driverdata = 0;
+	kfree(card->ctrlinfo);
+	kfree(card->dma);
+	kfree(card);
+
+	MOD_DEC_USE_COUNT;
+}
+
+/* ------------------------------------------------------------- */
+
+
+void c4_register_appl(struct capi_ctr *ctrl,
+				__u16 appl,
+				capi_register_params *rp)
+{
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+	avmcard *card = cinfo->card;
+	struct sk_buff *skb;
+	int want = rp->level3cnt;
+	int nconn;
+	void *p;
+
+	if (ctrl->cnr == card->cardnr) {
+
+		if (want > 0) nconn = want;
+		else nconn = ctrl->profile.nbchannel * 4 * -want;
+		if (nconn == 0) nconn = ctrl->profile.nbchannel * 4;
+
+		skb = alloc_skb(23, GFP_ATOMIC);
+		if (!skb) {
+			printk(KERN_CRIT "%s: no memory, lost register appl.\n",
+						card->name);
+			return;
+		}
+		p = skb->data;
+		_put_byte(&p, 0);
+		_put_byte(&p, 0);
+		_put_byte(&p, SEND_REGISTER);
+		_put_word(&p, appl);
+		_put_word(&p, 1024 * (nconn+1));
+		_put_word(&p, nconn);
+		_put_word(&p, rp->datablkcnt);
+		_put_word(&p, rp->datablklen);
+		skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
+
+		skb_queue_tail(&card->dma->send_queue, skb);
+		c4_dispatch_tx(card);
+	}
+
+	ctrl->appl_registered(ctrl, appl);
+}
+
+/* ------------------------------------------------------------- */
+
+void c4_release_appl(struct capi_ctr *ctrl, __u16 appl)
+{
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+	avmcard *card = cinfo->card;
+	struct sk_buff *skb;
+	void *p;
+
+	if (ctrl->cnr == card->cardnr) {
+		skb = alloc_skb(7, GFP_ATOMIC);
+		if (!skb) {
+			printk(KERN_CRIT "%s: no memory, lost release appl.\n",
+						card->name);
+			return;
+		}
+		p = skb->data;
+		_put_byte(&p, 0);
+		_put_byte(&p, 0);
+		_put_byte(&p, SEND_RELEASE);
+		_put_word(&p, appl);
+
+		skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
+		skb_queue_tail(&card->dma->send_queue, skb);
+		c4_dispatch_tx(card);
+	}
+}
+
+/* ------------------------------------------------------------- */
+
+
+static void c4_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
+{
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+	avmcard *card = cinfo->card;
+	skb_queue_tail(&card->dma->send_queue, skb);
+	c4_dispatch_tx(card);
+}
+
+/* ------------------------------------------------------------- */
+
+static char *c4_procinfo(struct capi_ctr *ctrl)
+{
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+
+	if (!cinfo)
+		return "";
+	sprintf(cinfo->infobuf, "%s %s 0x%x %d 0x%lx",
+		cinfo->cardname[0] ? cinfo->cardname : "-",
+		cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-",
+		cinfo->card ? cinfo->card->port : 0x0,
+		cinfo->card ? cinfo->card->irq : 0,
+		cinfo->card ? cinfo->card->membase : 0
+		);
+	return cinfo->infobuf;
+}
+
+static int c4_read_proc(char *page, char **start, off_t off,
+        		int count, int *eof, struct capi_ctr *ctrl)
+{
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+	avmcard *card = cinfo->card;
+	__u8 flag;
+	int len = 0;
+	char *s;
+
+	len += sprintf(page+len, "%-16s %s\n", "name", card->name);
+	len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port);
+	len += sprintf(page+len, "%-16s %d\n", "irq", card->irq);
+	len += sprintf(page+len, "%-16s 0x%lx\n", "membase", card->membase);
+	switch (card->cardtype) {
+	case avm_b1isa: s = "B1 ISA"; break;
+	case avm_b1pci: s = "B1 PCI"; break;
+	case avm_b1pcmcia: s = "B1 PCMCIA"; break;
+	case avm_m1: s = "M1"; break;
+	case avm_m2: s = "M2"; break;
+	case avm_t1isa: s = "T1 ISA (HEMA)"; break;
+	case avm_t1pci: s = "T1 PCI"; break;
+	case avm_c4: s = "C4"; break;
+	default: s = "???"; break;
+	}
+	len += sprintf(page+len, "%-16s %s\n", "type", s);
+	if ((s = cinfo->version[VER_DRIVER]) != 0)
+	   len += sprintf(page+len, "%-16s %s\n", "ver_driver", s);
+	if ((s = cinfo->version[VER_CARDTYPE]) != 0)
+	   len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s);
+	if ((s = cinfo->version[VER_SERIAL]) != 0)
+	   len += sprintf(page+len, "%-16s %s\n", "ver_serial", s);
+
+	if (card->cardtype != avm_m1) {
+        	flag = ((__u8 *)(ctrl->profile.manu))[3];
+        	if (flag)
+			len += sprintf(page+len, "%-16s%s%s%s%s%s%s%s\n",
+			"protocol",
+			(flag & 0x01) ? " DSS1" : "",
+			(flag & 0x02) ? " CT1" : "",
+			(flag & 0x04) ? " VN3" : "",
+			(flag & 0x08) ? " NI1" : "",
+			(flag & 0x10) ? " AUSTEL" : "",
+			(flag & 0x20) ? " ESS" : "",
+			(flag & 0x40) ? " 1TR6" : ""
+			);
+	}
+	if (card->cardtype != avm_m1) {
+        	flag = ((__u8 *)(ctrl->profile.manu))[5];
+		if (flag)
+			len += sprintf(page+len, "%-16s%s%s%s%s\n",
+			"linetype",
+			(flag & 0x01) ? " point to point" : "",
+			(flag & 0x02) ? " point to multipoint" : "",
+			(flag & 0x08) ? " leased line without D-channel" : "",
+			(flag & 0x04) ? " leased line with D-channel" : ""
+			);
+	}
+	len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname);
+
+	if (off+count >= len)
+	   *eof = 1;
+	if (len < off)
+           return 0;
+	*start = page + off;
+	return ((count < len-off) ? count : len-off);
+}
+
+/* ------------------------------------------------------------- */
+
+static int c4_add_card(struct capi_driver *driver, struct capicardparams *p)
+{
+	unsigned long page_offset, base;
+	avmctrl_info *cinfo;
+	avmcard *card;
+	int retval;
+	int i;
+
+	card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
+
+	if (!card) {
+		printk(KERN_WARNING "%s: no memory.\n", driver->name);
+		return -ENOMEM;
+	}
+	memset(card, 0, sizeof(avmcard));
+	card->dma = (avmcard_dmainfo *) kmalloc(sizeof(avmcard_dmainfo), GFP_ATOMIC);
+	if (!card->dma) {
+		printk(KERN_WARNING "%s: no memory.\n", driver->name);
+		kfree(card);
+		return -ENOMEM;
+	}
+	memset(card->dma, 0, sizeof(avmcard_dmainfo));
+        cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info)*4, GFP_ATOMIC);
+	if (!cinfo) {
+		printk(KERN_WARNING "%s: no memory.\n", driver->name);
+	        kfree(card->ctrlinfo);
+		kfree(card->dma);
+		kfree(card);
+		return -ENOMEM;
+	}
+	memset(cinfo, 0, sizeof(avmctrl_info)*4);
+	card->ctrlinfo = cinfo;
+	for (i=0; i < 4; i++) {
+		cinfo = &card->ctrlinfo[i];
+		cinfo->card = card;
+	}
+	sprintf(card->name, "c4-%x", p->port);
+	card->port = p->port;
+	card->irq = p->irq;
+	card->membase = p->membase;
+	card->cardtype = avm_c4;
+
+	if (check_region(card->port, AVMB1_PORTLEN)) {
+		printk(KERN_WARNING
+		       "%s: ports 0x%03x-0x%03x in use.\n",
+		       driver->name, card->port, card->port + AVMB1_PORTLEN);
+	        kfree(card->ctrlinfo);
+		kfree(card->dma);
+		kfree(card);
+		return -EBUSY;
+	}
+
+        base = card->membase & PAGE_MASK;
+	page_offset = card->membase - base;
+	card->mbase = ioremap_nocache(base, page_offset + 64);
+
+	if ((retval = c4_detect(card)) != 0) {
+		printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n",
+					driver->name, card->port, retval);
+                iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
+	        kfree(card->ctrlinfo);
+		kfree(card->dma);
+		kfree(card);
+		return -EIO;
+	}
+	c4_reset(card);
+
+	request_region(p->port, AVMB1_PORTLEN, card->name);
+
+	retval = request_irq(card->irq, c4_interrupt, SA_SHIRQ, card->name, card);
+	if (retval) {
+		printk(KERN_ERR "%s: unable to get IRQ %d.\n",
+				driver->name, card->irq);
+                iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
+		release_region(card->port, AVMB1_PORTLEN);
+	        kfree(card->ctrlinfo);
+		kfree(card->dma);
+		kfree(card);
+		return -EBUSY;
+	}
+
+	for (i=0; i < 4; i++) {
+		cinfo = &card->ctrlinfo[i];
+		cinfo->card = card;
+		cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo);
+		if (!cinfo->capi_ctrl) {
+			printk(KERN_ERR "%s: attach controller failed (%d).\n",
+					driver->name, i);
+			for (i--; i >= 0; i--) {
+				cinfo = &card->ctrlinfo[i];
+				di->detach_ctr(cinfo->capi_ctrl);
+			}
+                	iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
+			free_irq(card->irq, card);
+			release_region(card->port, AVMB1_PORTLEN);
+	        	kfree(card->dma);
+	        	kfree(card->ctrlinfo);
+			kfree(card);
+			return -EBUSY;
+		}
+		if (i == 0)
+			card->cardnr = cinfo->capi_ctrl->cnr;
+	}
+
+	skb_queue_head_init(&card->dma->send_queue);
+
+	MOD_INC_USE_COUNT;
+
+	return 0;
+}
+
+/* ------------------------------------------------------------- */
+
+static struct capi_driver c4_driver = {
+    "c4",
+    "0.0",
+    c4_load_firmware,
+    c4_reset_ctr,
+    c4_remove_ctr,
+    c4_register_appl,
+    c4_release_appl,
+    c4_send_message,
+
+    c4_procinfo,
+    c4_read_proc,
+    0,	/* use standard driver_read_proc */
+
+    0, /* no add_card function */
+};
+
+#ifdef MODULE
+#define c4_init init_module
+void cleanup_module(void);
+#endif
+
+#ifndef PCI_ANY_ID
+#define PCI_ANY_ID (~0)
+#endif
+
+static struct pci_dev *
+pci_find_subsys(unsigned int vendor, unsigned int device,
+		unsigned int ss_vendor, unsigned int ss_device,
+		struct pci_dev *from)
+{
+	unsigned short subsystem_vendor, subsystem_device;
+
+	while ((from = pci_find_device(vendor, device, from))) {
+		pci_read_config_word(from, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
+		pci_read_config_word(from, PCI_SUBSYSTEM_ID, &subsystem_device);
+		if ((ss_vendor == PCI_ANY_ID || subsystem_vendor == ss_vendor) &&
+		    (ss_device == PCI_ANY_ID || subsystem_device == ss_device))
+			return from;
+	}
+	return NULL;
+}
+
+static int ncards = 0;
+
+int c4_init(void)
+{
+	struct capi_driver *driver = &c4_driver;
+	struct pci_dev *dev = NULL;
+	char *p;
+	int retval;
+
+	if ((p = strchr(revision, ':'))) {
+		strncpy(driver->revision, p + 1, sizeof(driver->revision));
+		p = strchr(driver->revision, '$');
+		*p = 0;
+	}
+
+	printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision);
+
+        di = attach_capi_driver(driver);
+
+	if (!di) {
+		printk(KERN_ERR "%s: failed to attach capi_driver\n",
+				driver->name);
+		return -EIO;
+	}
+
+#ifdef CONFIG_PCI
+	if (!pci_present()) {
+		printk(KERN_ERR "%s: no PCI bus present\n", driver->name);
+    		detach_capi_driver(driver);
+		return -EIO;
+	}
+
+	while ((dev = pci_find_subsys(
+			PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285,
+			PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C4, dev))) {
+		struct capicardparams param;
+
+		param.port = dev->base_address[ 1] & PCI_BASE_ADDRESS_IO_MASK;
+		param.irq = dev->irq;
+		param.membase = dev->base_address[ 0] & PCI_BASE_ADDRESS_MEM_MASK;
+
+		printk(KERN_INFO
+			"%s: PCI BIOS reports AVM-C4 at i/o %#x, irq %d, mem %#x\n",
+			driver->name, param.port, param.irq, param.membase);
+		retval = c4_add_card(driver, &param);
+		if (retval != 0) {
+		        printk(KERN_ERR
+			"%s: no AVM-C4 at i/o %#x, irq %d detected, mem %#x\n",
+			driver->name, param.port, param.irq, param.membase);
+#ifdef MODULE
+			cleanup_module();
+#endif
+			return retval;
+		}
+		ncards++;
+	}
+	if (ncards) {
+		printk(KERN_INFO "%s: %d C4 card(s) detected\n",
+				driver->name, ncards);
+		return 0;
+	}
+	printk(KERN_ERR "%s: NO C4 card detected\n", driver->name);
+	return -ESRCH;
+#else
+	printk(KERN_ERR "%s: kernel not compiled with PCI.\n", driver->name);
+	return -EIO;
+#endif
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+    detach_capi_driver(&c4_driver);
+}
+#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/isdn/avmb1/t1pci.c linux.15p9/drivers/isdn/avmb1/t1pci.c
--- linux.vanilla/drivers/isdn/avmb1/t1pci.c	Tue Jan  4 21:18:46 2000
+++ linux.15p9/drivers/isdn/avmb1/t1pci.c	Wed Feb 16 18:18:52 2000
@@ -55,7 +55,7 @@
 
 /* ------------------------------------------------------------- */
 
-int suppress_pollack = 0;
+static int suppress_pollack = 0;
 
 MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/isdn/eicon/eicon_idi.c linux.15p9/drivers/isdn/eicon/eicon_idi.c
--- linux.vanilla/drivers/isdn/eicon/eicon_idi.c	Tue Jan  4 21:18:47 2000
+++ linux.15p9/drivers/isdn/eicon/eicon_idi.c	Wed Jan 26 23:08:43 2000
@@ -1,4 +1,4 @@
-/* $Id: eicon_idi.c,v 1.27 1999/11/29 13:12:03 armin Exp $
+/* $Id: eicon_idi.c,v 1.28 2000/01/20 19:55:34 keil Exp $
  *
  * ISDN lowlevel-module for Eicon.Diehl active cards.
  *        IDI interface 
@@ -26,6 +26,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_idi.c,v $
+ * Revision 1.28  2000/01/20 19:55:34  keil
+ * Add FAX Class 1 support
+ *
  * Revision 1.27  1999/11/29 13:12:03  armin
  * Autoconnect on L2_TRANS doesn't work with link_level correctly,
  * changed back to former mode.
@@ -142,7 +145,7 @@
 
 #undef EICON_FULL_SERVICE_OKTETT
 
-char *eicon_idi_revision = "$Revision: 1.27 $";
+char *eicon_idi_revision = "$Revision: 1.28 $";
 
 eicon_manifbuf *manbuf;
 
@@ -224,7 +227,7 @@
 			reqbuf->XBuffer.P[l++] = 1;
 	}
 	switch(chan->l3prot) {
-		case ISDN_PROTO_L3_FAX:
+		case ISDN_PROTO_L3_FCLASS2:
 #ifdef CONFIG_ISDN_TTY_FAX
 			reqbuf->XBuffer.P[l++] = 6;
 			reqbuf->XBuffer.P[l++] = NLC;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/isdn/eicon/eicon_mod.c linux.15p9/drivers/isdn/eicon/eicon_mod.c
--- linux.vanilla/drivers/isdn/eicon/eicon_mod.c	Tue Jan  4 21:18:47 2000
+++ linux.15p9/drivers/isdn/eicon/eicon_mod.c	Wed Jan 26 23:08:43 2000
@@ -1,4 +1,4 @@
-/* $Id: eicon_mod.c,v 1.22 1999/11/27 12:56:19 armin Exp $
+/* $Id: eicon_mod.c,v 1.23 2000/01/20 19:55:34 keil Exp $
  *
  * ISDN lowlevel-module for Eicon.Diehl active cards.
  * 
@@ -31,6 +31,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_mod.c,v $
+ * Revision 1.23  2000/01/20 19:55:34  keil
+ * Add FAX Class 1 support
+ *
  * Revision 1.22  1999/11/27 12:56:19  armin
  * Forgot some iomem changes for last ioremap compat.
  *
@@ -133,7 +136,7 @@
 static eicon_card *cards = (eicon_card *) NULL;   /* glob. var , contains
                                                      start of card-list   */
 
-static char *eicon_revision = "$Revision: 1.22 $";
+static char *eicon_revision = "$Revision: 1.23 $";
 
 extern char *eicon_pci_revision;
 extern char *eicon_isa_revision;
@@ -669,7 +672,7 @@
 				break;
 			chan->l3prot = (c->arg >> 8);
 #ifdef CONFIG_ISDN_TTY_FAX
-			if (chan->l3prot == ISDN_PROTO_L3_FAX)
+			if (chan->l3prot == ISDN_PROTO_L3_FCLASS2)
 				chan->fax = c->parm.fax;
 #endif
 			return 0;
@@ -1086,7 +1089,7 @@
 					ISDN_FEATURE_L2_MODEM |
 					ISDN_FEATURE_L2_FAX | 
 					ISDN_FEATURE_L3_TRANSDSP |
-					ISDN_FEATURE_L3_FAX;
+					ISDN_FEATURE_L3_FCLASS2;
                                 card->hwif.pci.card = (void *)card;
 				card->hwif.pci.PCIreg = pcic->PCIreg;
 				card->hwif.pci.PCIcfg = pcic->PCIcfg;
@@ -1110,7 +1113,7 @@
 					ISDN_FEATURE_L2_MODEM |
 					ISDN_FEATURE_L2_FAX |
 					ISDN_FEATURE_L3_TRANSDSP |
-					ISDN_FEATURE_L3_FAX;
+					ISDN_FEATURE_L3_FCLASS2;
                                 card->hwif.pci.card = (void *)card;
                                 card->hwif.pci.shmem = (eicon_pci_shmem *)pcic->shmem;
 				card->hwif.pci.PCIreg = pcic->PCIreg;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/isdn/hisax/Makefile linux.15p9/drivers/isdn/hisax/Makefile
--- linux.vanilla/drivers/isdn/hisax/Makefile	Wed Oct 20 01:12:37 1999
+++ linux.15p9/drivers/isdn/hisax/Makefile	Wed Jan 26 23:08:43 2000
@@ -137,6 +137,10 @@
 	 HFC_2BDS0 += hfc_pci.o
 endif
 
+ifeq ($(CONFIG_HISAX_HFC_SX),y)
+	 HFC_2BDS0 += hfc_sx.o
+endif
+
 ifeq ($(CONFIG_HISAX_NICCY),y)
 	 O_OBJS += niccy.o
 	 ISAC_OBJ := isac.o
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/isdn/hisax/config.c linux.15p9/drivers/isdn/hisax/config.c
--- linux.vanilla/drivers/isdn/hisax/config.c	Tue Jan  4 21:18:47 2000
+++ linux.15p9/drivers/isdn/hisax/config.c	Wed Jan 26 23:08:43 2000
@@ -1,14 +1,21 @@
-/* $Id: config.c,v 2.42 1999/12/19 13:09:41 keil Exp $
+/* $Id: config.c,v 2.43 2000/01/20 19:49:36 keil Exp $
 
  * Author       Karsten Keil (keil@isdn4linux.de)
  *              based on the teles driver from Jan den Ouden
  *
  *
  * $Log: config.c,v $
+ * Revision 2.43  2000/01/20 19:49:36  keil
+ * Support teles 13.3c vendor version 2.1
+ *
  * Revision 2.42  1999/12/19 13:09:41  keil
  * changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for
  * signal proof delays
  *
+ * Revision 2.41  1999/11/18 00:00:43  werner
+ *
+ * Added support for HFC-S+ and HFC-SP cards
+ *
  * Revision 2.40  1999/10/30 13:09:45  keil
  * Version 3.3c
  *
@@ -205,6 +212,7 @@
  *   34	Gazel ISDN cards
  *   35 HFC 2BDS0 PCI           none
  *   36 Winbond 6692 PCI        none
+ *   37 HFC 2BDS0 S+/SP         p0=irq p1=iobase
  *
  * protocol can be either ISDN_PTYPE_EURO or ISDN_PTYPE_1TR6 or ISDN_PTYPE_NI1
  *
@@ -220,6 +228,7 @@
  "AMD 7930", "NICCY", "S0Box", "AVM A1 (PCMCIA)", "AVM Fritz PnP/PCI",
  "Sedlbauer Speed Fax +", "Siemens I-Surf", "Acer P10", "HST Saphir",
  "Telekom A4T", "Scitel Quadro", "Gazel", "HFC 2BDS0 PCI", "Winbond 6692",
+ "HFC 2BDS0 SX",
 };
 
 void HiSax_closecard(int cardnr);
@@ -355,6 +364,13 @@
 #define DEFAULT_CFG {0,0,0,0}
 #endif
 
+#ifdef CONFIG_HISAX_HFC_SX
+#undef DEFAULT_CARD
+#undef DEFAULT_CFG
+#define DEFAULT_CARD ISDN_CTYPE_HFC_SX
+#define DEFAULT_CFG {5,0x2E0,0,0}
+#endif
+
 
 #ifdef CONFIG_HISAX_AMD7930
 #undef DEFAULT_CARD
@@ -532,9 +548,9 @@
 
 	printk(KERN_INFO "HiSax: Linux Driver for passive ISDN cards\n");
 #ifdef MODULE
-	printk(KERN_INFO "HiSax: Version 3.3c (module)\n");
+	printk(KERN_INFO "HiSax: Version 3.3d (module)\n");
 #else
-	printk(KERN_INFO "HiSax: Version 3.3c (kernel)\n");
+	printk(KERN_INFO "HiSax: Version 3.3d (kernel)\n");
 #endif
 	strcpy(tmp, l1_revision);
 	printk(KERN_INFO "HiSax: Layer1 Revision %s\n", HiSax_getrev(tmp));
@@ -682,6 +698,10 @@
 extern int setup_hfcpci(struct IsdnCard *card);
 #endif
 
+#if CARD_HFC_SX
+extern int setup_hfcsx(struct IsdnCard *card);
+#endif
+
 #if CARD_AMD7930
 extern int setup_amd7930(struct IsdnCard *card);
 #endif
@@ -1203,6 +1223,11 @@
 				ret = setup_hfcpci(card);
 				break;
 #endif
+#if CARD_HFC_SX
+		        case ISDN_CTYPE_HFC_SX: 
+				ret = setup_hfcsx(card);
+				break;
+#endif
 #if CARD_NICCY
 			case ISDN_CTYPE_NICCY:
 				ret = setup_niccy(card);
@@ -1510,6 +1535,7 @@
 			case ISDN_CTYPE_FRITZPCI:
 			case ISDN_CTYPE_HSTSAPHIR:
 			case ISDN_CTYPE_GAZEL:
+		        case ISDN_CTYPE_HFC_SX:
 				cards[i].para[0] = irq[i];
 				cards[i].para[1] = io[i];
 				break;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/isdn/hisax/hfc_sx.c linux.15p9/drivers/isdn/hisax/hfc_sx.c
--- linux.vanilla/drivers/isdn/hisax/hfc_sx.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/isdn/hisax/hfc_sx.c	Wed Jan 26 23:08:43 2000
@@ -0,0 +1,1584 @@
+/* $Id: hfc_sx.c,v 1.3 2000/01/20 19:49:36 keil Exp $
+
+ * hfc_sx.c     low level driver for CCD´s hfc-s+/sp based cards
+ *
+ * Author     Werner Cornelius (werner@isdn4linux.de)
+ *            based on existing driver for CCD HFC PCI cards
+ *
+ * Copyright 1999  by Werner Cornelius (werner@isdn4linux.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Log: hfc_sx.c,v $
+ * Revision 1.3  2000/01/20 19:49:36  keil
+ * Support teles 13.3c vendor version 2.1
+ *
+ * Revision 1.2  1999/12/19 13:09:42  keil
+ * changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for
+ * signal proof delays
+ *
+ * Revision 1.1  1999/11/18 00:09:18  werner
+ *
+ * Initial release of files for HFC-S+ and HFC-SP cards with 32K-RAM.
+ * Audio and Echo are supported.
+ *
+ *
+ *
+ */
+
+#include <linux/config.h>
+#define __NO_VERSION__
+#include "hisax.h"
+#include "hfc_sx.h"
+#include "isdnl1.h"
+#include <linux/interrupt.h>
+
+extern const char *CardType[];
+
+static const char *hfcsx_revision = "$Revision: 1.3 $";
+
+/***************************************/
+/* IRQ-table for CCDs demo board       */
+/* IRQs 6,5,10,11,12,15 are supported  */
+/***************************************/
+
+/* Teles 16.3c Vendor Id TAG2620, Version 1.0, Vendor version 2.1
+ *
+ * Thanks to Uwe Wisniewski
+ *
+ * ISA-SLOT  Signal      PIN
+ * B25        IRQ3     92 IRQ_G
+ * B23        IRQ5     94 IRQ_A
+ * B4         IRQ2/9   95 IRQ_B
+ * D3         IRQ10    96 IRQ_C
+ * D4         IRQ11    97 IRQ_D
+ * D5         IRQ12    98 IRQ_E
+ * D6         IRQ15    99 IRQ_F
+ */
+
+#undef CCD_DEMO_BOARD
+#ifdef CCD_DEMO_BOARD
+static u_char ccd_sp_irqtab[16] = {
+  0,0,0,0,0,2,1,0,0,0,3,4,5,0,0,6
+};
+#else /* Teles 16.3c */
+static u_char ccd_sp_irqtab[16] = {
+  0,0,0,7,0,1,0,0,0,2,3,4,5,0,0,6
+};
+#endif
+#define NT_T1_COUNT 20		/* number of 3.125ms interrupts for G2 timeout */
+
+#define byteout(addr,val) outb(val,addr)
+#define bytein(addr) inb(addr)
+
+/******************************/
+/* In/Out access to registers */
+/******************************/
+static inline void
+Write_hfc(struct IsdnCardState *cs, u_char regnum, u_char val)
+{       register int flags;
+
+        save_flags(flags);
+	cli();
+        byteout(cs->hw.hfcsx.base+1, regnum);
+	byteout(cs->hw.hfcsx.base, val);
+	restore_flags(flags);
+} 
+
+static inline u_char
+Read_hfc(struct IsdnCardState *cs, u_char regnum)
+{       register int flags;
+        register u_char ret; 
+
+        save_flags(flags);
+	cli();
+        byteout(cs->hw.hfcsx.base+1, regnum);
+	ret = bytein(cs->hw.hfcsx.base);
+	restore_flags(flags);
+	return(ret);
+} 
+
+
+/**************************************************/
+/* select a fifo and remember which one for reuse */
+/**************************************************/
+static void
+fifo_select(struct IsdnCardState *cs, u_char fifo)
+{       int flags;
+
+        if (fifo == cs->hw.hfcsx.last_fifo) 
+	  return; /* still valid */
+
+	save_flags(flags);
+	cli();
+        byteout(cs->hw.hfcsx.base+1, HFCSX_FIF_SEL);
+	byteout(cs->hw.hfcsx.base, fifo);
+	while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */
+	udelay(4);
+	byteout(cs->hw.hfcsx.base, fifo);
+	while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */
+	restore_flags(flags);
+}
+
+/******************************************/
+/* reset the specified fifo to defaults.  */
+/* If its a send fifo init needed markers */
+/******************************************/
+static void
+reset_fifo(struct IsdnCardState *cs, u_char fifo)
+{       int flags;
+
+        save_flags(flags); 
+	cli();
+	fifo_select(cs, fifo); /* first select the fifo */
+	byteout(cs->hw.hfcsx.base+1, HFCSX_CIRM);
+	byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.cirm | 0x80); /* reset cmd */
+	udelay(1);
+	while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */
+	restore_flags(flags);
+} 
+
+
+/*************************************************************/
+/* write_fifo writes the skb contents to the desired fifo    */
+/* if no space is available or an error occurs 0 is returned */
+/* the skb is not released in any way.                       */
+/*************************************************************/
+static int
+write_fifo(struct IsdnCardState *cs, struct sk_buff *skb, u_char fifo, int trans_max)
+{       unsigned short *msp;
+        int fifo_size, count, z1, z2;
+	u_char f_msk, f1, f2, *src;
+
+	if (skb->len <= 0) return(0);
+        if (fifo & 1) return(0); /* no write fifo */
+
+	fifo_select(cs, fifo);
+	if (fifo & 4) {
+	  fifo_size = D_FIFO_SIZE; /* D-channel */
+	  f_msk = MAX_D_FRAMES;
+	  if (trans_max) return(0); /* only HDLC */
+	}
+	else {
+	  fifo_size = cs->hw.hfcsx.b_fifo_size; /* B-channel */
+	  f_msk = MAX_B_FRAMES;
+	}
+
+        z1 = Read_hfc(cs, HFCSX_FIF_Z1H);
+	z1 = ((z1 << 8) | Read_hfc(cs, HFCSX_FIF_Z1L));
+
+	/* Check for transparent mode */
+	if (trans_max) {
+	  z2 = Read_hfc(cs, HFCSX_FIF_Z2H);
+	  z2 = ((z2 << 8) | Read_hfc(cs, HFCSX_FIF_Z2L));
+	  count = z2 - z1;
+	  if (count <= 0)
+	    count += fifo_size; /* free bytes */
+	  if (count < skb->len+1) return(0); /* no room */
+	  count = fifo_size - count; /* bytes still not send */
+	  if (count > 2 * trans_max) return(0); /* delay to long */
+	  count = skb->len;
+	  src = skb->data;
+	  while (count--)
+	    Write_hfc(cs, HFCSX_FIF_DWR, *src++);
+	  return(1); /* success */
+	}
+
+        msp = ((struct hfcsx_extra *)(cs->hw.hfcsx.extra))->marker;
+	msp += (((fifo >> 1) & 3) * (MAX_B_FRAMES+1));
+	f1 = Read_hfc(cs, HFCSX_FIF_F1) & f_msk;
+	f2 = Read_hfc(cs, HFCSX_FIF_F2) & f_msk;
+
+	count = f1 - f2; /* frame count actually buffered */
+	if (count < 0)
+		count += (f_msk + 1);	/* if wrap around */
+	if (count > f_msk-1) {
+	  if (cs->debug & L1_DEB_ISAC_FIFO)
+	    debugl1(cs, "hfcsx_write_fifo %d more as %d frames",fifo,f_msk-1);
+	  return(0);
+	}
+
+	*(msp + f1) = z1; /* remember marker */
+
+	if (cs->debug & L1_DEB_ISAC_FIFO)
+		debugl1(cs, "hfcsx_write_fifo %d f1(%x) f2(%x) z1(f1)(%x)",
+			fifo, f1, f2, z1);
+	/* now determine free bytes in FIFO buffer */
+	count = *(msp + f2) - z1;
+	if (count <= 0)
+	  count += fifo_size;	/* count now contains available bytes */
+
+	if (cs->debug & L1_DEB_ISAC_FIFO)
+	  debugl1(cs, "hfcsx_write_fifo %d count(%ld/%d)",
+		  fifo, skb->len, count);
+	if (count < skb->len) {
+	  if (cs->debug & L1_DEB_ISAC_FIFO)
+	    debugl1(cs, "hfcsx_write_fifo %d no fifo mem", fifo);
+	  return(0);
+	}
+	
+	count = skb->len; /* get frame len */
+	src = skb->data;	/* source pointer */
+	while (count--)
+	  Write_hfc(cs, HFCSX_FIF_DWR, *src++);
+	
+	Read_hfc(cs, HFCSX_FIF_INCF1); /* increment F1 */
+	udelay(1);
+	while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */
+	return(1);
+} 
+
+/***************************************************************/
+/* read_fifo reads data to an skb from the desired fifo        */
+/* if no data is available or an error occurs NULL is returned */
+/* the skb is not released in any way.                         */
+/***************************************************************/
+static struct sk_buff * 
+read_fifo(struct IsdnCardState *cs, u_char fifo, int trans_max)
+{       int fifo_size, count, z1, z2;
+	u_char f_msk, f1, f2, *dst;
+	struct sk_buff *skb;
+
+        if (!(fifo & 1)) return(NULL); /* no read fifo */
+	fifo_select(cs, fifo);
+	if (fifo & 4) {
+	  fifo_size = D_FIFO_SIZE; /* D-channel */
+	  f_msk = MAX_D_FRAMES;
+	  if (trans_max) return(NULL); /* only hdlc */
+	}
+	else {
+	  fifo_size = cs->hw.hfcsx.b_fifo_size; /* B-channel */
+	  f_msk = MAX_B_FRAMES;
+	}
+
+	/* transparent mode */
+	if (trans_max) {
+	  z1 = Read_hfc(cs, HFCSX_FIF_Z1H);
+	  z1 = ((z1 << 8) | Read_hfc(cs, HFCSX_FIF_Z1L));
+	  z2 = Read_hfc(cs, HFCSX_FIF_Z2H);
+	  z2 = ((z2 << 8) | Read_hfc(cs, HFCSX_FIF_Z2L));
+	  /* now determine bytes in actual FIFO buffer */
+	  count = z1 - z2;
+	  if (count <= 0)
+	    count += fifo_size;	/* count now contains buffered bytes */
+	  count++;
+	  if (count > trans_max) 
+	    count = trans_max; /* limit length */
+	    if ((skb = dev_alloc_skb(count))) {
+	      dst = skb_put(skb, count);
+	      while (count--) 
+		*dst++ = Read_hfc(cs, HFCSX_FIF_DRD);
+	      return(skb);
+	    }
+	    else return(NULL); /* no memory */
+	}
+
+	do {
+	  f1 = Read_hfc(cs, HFCSX_FIF_F1) & f_msk;
+	  f2 = Read_hfc(cs, HFCSX_FIF_F2) & f_msk;
+
+	  if (f1 == f2) return(NULL); /* no frame available */
+
+	  z1 = Read_hfc(cs, HFCSX_FIF_Z1H);
+	  z1 = ((z1 << 8) | Read_hfc(cs, HFCSX_FIF_Z1L));
+	  z2 = Read_hfc(cs, HFCSX_FIF_Z2H);
+	  z2 = ((z2 << 8) | Read_hfc(cs, HFCSX_FIF_Z2L));
+
+	  if (cs->debug & L1_DEB_ISAC_FIFO)
+	    debugl1(cs, "hfcsx_read_fifo %d f1(%x) f2(%x) z1(f2)(%x) z2(f2)(%x)",
+			fifo, f1, f2, z1, z2);
+	  /* now determine bytes in actual FIFO buffer */
+	  count = z1 - z2;
+	  if (count <= 0)
+	    count += fifo_size;	/* count now contains buffered bytes */
+	  count++;
+
+	  if (cs->debug & L1_DEB_ISAC_FIFO)
+	    debugl1(cs, "hfcsx_read_fifo %d count %ld)",
+		    fifo, count);
+
+	  if ((count > fifo_size) || (count < 4)) {
+	    if (cs->debug & L1_DEB_WARN)
+	      debugl1(cs, "hfcsx_read_fifo %d paket inv. len %d ", fifo , count);
+	    while (count) {
+	      count--; /* empty fifo */
+	      Read_hfc(cs, HFCSX_FIF_DRD);
+	    }
+	    skb = NULL;
+	  } else 
+	    if ((skb = dev_alloc_skb(count - 3))) {
+	      count -= 3;
+	      dst = skb_put(skb, count);
+
+	      while (count--) 
+		*dst++ = Read_hfc(cs, HFCSX_FIF_DRD);
+		    
+	      Read_hfc(cs, HFCSX_FIF_DRD); /* CRC 1 */
+	      Read_hfc(cs, HFCSX_FIF_DRD); /* CRC 2 */
+	      if (Read_hfc(cs, HFCSX_FIF_DRD)) {
+		dev_kfree_skb(skb);
+		if (cs->debug & L1_DEB_ISAC_FIFO)
+		  debugl1(cs, "hfcsx_read_fifo %d crc error", fifo);
+		skb = NULL;
+	      }
+	    } else {
+	      printk(KERN_WARNING "HFC-SX: receive out of memory\n");
+	      return(NULL);
+	    }
+
+	  Read_hfc(cs, HFCSX_FIF_INCF2); /* increment F2 */
+	  udelay(1);
+	  while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */
+	  udelay(1);
+	} while (!skb); /* retry in case of crc error */
+	return(skb);
+} 
+
+/******************************************/
+/* free hardware resources used by driver */
+/******************************************/
+void
+release_io_hfcsx(struct IsdnCardState *cs)
+{
+	int flags;
+
+	save_flags(flags);
+	cli();
+	cs->hw.hfcsx.int_m2 = 0;	/* interrupt output off ! */
+	Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
+	restore_flags(flags);
+	Write_hfc(cs, HFCSX_CIRM, HFCSX_RESET);	/* Reset On */
+	sti();
+	current->state = TASK_UNINTERRUPTIBLE;
+	schedule_timeout((30 * HZ) / 1000);	/* Timeout 30ms */
+	Write_hfc(cs, HFCSX_CIRM, 0);	/* Reset Off */
+	del_timer(&cs->hw.hfcsx.timer);
+	release_region(cs->hw.hfcsx.base, 2); /* release IO-Block */
+	kfree(cs->hw.hfcsx.extra);
+	cs->hw.hfcsx.extra = NULL;
+}
+
+/**********************************************************/
+/* set_fifo_size determines the size of the RAM and FIFOs */
+/* returning 0 -> need to reset the chip again.           */
+/**********************************************************/
+static int set_fifo_size(struct IsdnCardState *cs)
+{
+        
+        if (cs->hw.hfcsx.b_fifo_size) return(1); /* already determined */
+
+	if ((cs->hw.hfcsx.chip >> 4) == 9) {
+	  cs->hw.hfcsx.b_fifo_size = B_FIFO_SIZE_32K;
+	  return(1);
+	}
+
+	  cs->hw.hfcsx.b_fifo_size = B_FIFO_SIZE_8K;
+	  cs->hw.hfcsx.cirm |= 0x10; /* only 8K of ram */
+	  return(0);
+
+}
+
+/********************************************************************************/
+/* function called to reset the HFC SX chip. A complete software reset of chip */
+/* and fifos is done.                                                           */
+/********************************************************************************/
+static void
+reset_hfcsx(struct IsdnCardState *cs)
+{
+	long flags;
+
+	save_flags(flags);
+	cli();
+	cs->hw.hfcsx.int_m2 = 0;	/* interrupt output off ! */
+	Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
+
+	printk(KERN_INFO "HFC_SX: resetting card\n");
+	while (1) {
+	  Write_hfc(cs, HFCSX_CIRM, HFCSX_RESET | cs->hw.hfcsx.cirm ); /* Reset */
+	  sti();
+	  current->state = TASK_UNINTERRUPTIBLE;
+	  schedule_timeout((30 * HZ) / 1000);	/* Timeout 30ms */
+	  Write_hfc(cs, HFCSX_CIRM, cs->hw.hfcsx.cirm); /* Reset Off */
+	  current->state = TASK_UNINTERRUPTIBLE;
+	  schedule_timeout((20 * HZ) / 1000);	/* Timeout 20ms */
+	  if (Read_hfc(cs, HFCSX_STATUS) & 2)
+	    printk(KERN_WARNING "HFC-SX init bit busy\n");
+	  cs->hw.hfcsx.last_fifo = 0xff; /* invalidate */
+	  if (!set_fifo_size(cs)) continue;
+	  break;
+	}
+
+	cs->hw.hfcsx.trm = 0 + HFCSX_BTRANS_THRESMASK;	/* no echo connect , threshold */
+	Write_hfc(cs, HFCSX_TRM, cs->hw.hfcsx.trm);
+
+	Write_hfc(cs, HFCSX_CLKDEL, 0x0e);	/* ST-Bit delay for TE-Mode */
+	cs->hw.hfcsx.sctrl_e = HFCSX_AUTO_AWAKE;
+	Write_hfc(cs, HFCSX_SCTRL_E, cs->hw.hfcsx.sctrl_e);	/* S/T Auto awake */
+	cs->hw.hfcsx.bswapped = 0;	/* no exchange */
+	cs->hw.hfcsx.nt_mode = 0;	/* we are in TE mode */
+	cs->hw.hfcsx.ctmt = HFCSX_TIM3_125 | HFCSX_AUTO_TIMER;
+	Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt);
+
+	cs->hw.hfcsx.int_m1 = HFCSX_INTS_DTRANS | HFCSX_INTS_DREC | 
+	    HFCSX_INTS_L1STATE | HFCSX_INTS_TIMER;
+	Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
+
+	/* Clear already pending ints */
+	if (Read_hfc(cs, HFCSX_INT_S1));
+
+	Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 2);	/* HFC ST 2 */
+	udelay(10);
+	Write_hfc(cs, HFCSX_STATES, 2);	/* HFC ST 2 */
+	cs->hw.hfcsx.mst_m = HFCSX_MASTER;	/* HFC Master Mode */
+
+	Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);
+	cs->hw.hfcsx.sctrl = 0x40;	/* set tx_lo mode, error in datasheet ! */
+	Write_hfc(cs, HFCSX_SCTRL, cs->hw.hfcsx.sctrl);
+	cs->hw.hfcsx.sctrl_r = 0;
+	Write_hfc(cs, HFCSX_SCTRL_R, cs->hw.hfcsx.sctrl_r);
+
+	/* Init GCI/IOM2 in master mode */
+	/* Slots 0 and 1 are set for B-chan 1 and 2 */
+	/* D- and monitor/CI channel are not enabled */
+	/* STIO1 is used as output for data, B1+B2 from ST->IOM+HFC */
+	/* STIO2 is used as data input, B1+B2 from IOM->ST */
+	/* ST B-channel send disabled -> continous 1s */
+	/* The IOM slots are always enabled */
+	cs->hw.hfcsx.conn = 0x36;	/* set data flow directions */
+	Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);
+	Write_hfc(cs, HFCSX_B1_SSL, 0x80);	/* B1-Slot 0 STIO1 out enabled */
+	Write_hfc(cs, HFCSX_B2_SSL, 0x81);	/* B2-Slot 1 STIO1 out enabled */
+	Write_hfc(cs, HFCSX_B1_RSL, 0x80);	/* B1-Slot 0 STIO2 in enabled */
+	Write_hfc(cs, HFCSX_B2_RSL, 0x81);	/* B2-Slot 1 STIO2 in enabled */
+
+	/* Finally enable IRQ output */
+	cs->hw.hfcsx.int_m2 = HFCSX_IRQ_ENABLE;
+	Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
+	if (Read_hfc(cs, HFCSX_INT_S2));
+	restore_flags(flags);
+}
+
+/***************************************************/
+/* Timer function called when kernel timer expires */
+/***************************************************/
+static void
+hfcsx_Timer(struct IsdnCardState *cs)
+{
+	cs->hw.hfcsx.timer.expires = jiffies + 75;
+	/* WD RESET */
+/*      WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcsx.ctmt | 0x80);
+   add_timer(&cs->hw.hfcsx.timer);
+ */
+}
+
+
+/*********************************/
+/* schedule a new D-channel task */
+/*********************************/
+static void
+sched_event_D_sx(struct IsdnCardState *cs, int event)
+{
+	test_and_set_bit(event, &cs->event);
+	queue_task(&cs->tqueue, &tq_immediate);
+	mark_bh(IMMEDIATE_BH);
+}
+
+/*********************************/
+/* schedule a new b_channel task */
+/*********************************/
+static void
+hfcsx_sched_event(struct BCState *bcs, int event)
+{
+	bcs->event |= 1 << event;
+	queue_task(&bcs->tqueue, &tq_immediate);
+	mark_bh(IMMEDIATE_BH);
+}
+
+/************************************************/
+/* select a b-channel entry matching and active */
+/************************************************/
+static
+struct BCState *
+Sel_BCS(struct IsdnCardState *cs, int channel)
+{
+	if (cs->bcs[0].mode && (cs->bcs[0].channel == channel))
+		return (&cs->bcs[0]);
+	else if (cs->bcs[1].mode && (cs->bcs[1].channel == channel))
+		return (&cs->bcs[1]);
+	else
+		return (NULL);
+}
+
+/*******************************/
+/* D-channel receive procedure */
+/*******************************/
+static
+int
+receive_dmsg(struct IsdnCardState *cs)
+{
+	struct sk_buff *skb;
+	int count = 5;
+
+	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+		debugl1(cs, "rec_dmsg blocked");
+		return (1);
+	}
+
+	do {
+	  skb = read_fifo(cs, HFCSX_SEL_D_RX, 0);
+	  if (skb) {
+	    skb_queue_tail(&cs->rq, skb);
+	    sched_event_D_sx(cs, D_RCVBUFREADY);
+	  }
+	} while (--count && skb);
+
+	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+	return (1);
+}
+
+/**********************************/
+/* B-channel main receive routine */
+/**********************************/
+void
+main_rec_hfcsx(struct BCState *bcs)
+{
+	long flags;
+	struct IsdnCardState *cs = bcs->cs;
+	int count = 5;
+	struct sk_buff *skb;
+
+	save_flags(flags);
+	  
+      Begin:
+	count--;
+	cli();
+	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+		debugl1(cs, "rec_data %d blocked", bcs->channel);
+		restore_flags(flags);
+		return;
+	}
+	sti();
+	skb = read_fifo(cs, ((bcs->channel) && (!cs->hw.hfcsx.bswapped)) ? 
+			HFCSX_SEL_B2_RX : HFCSX_SEL_B1_RX,
+			(bcs->mode == L1_MODE_TRANS) ? 
+			HFCSX_BTRANS_THRESHOLD : 0);
+
+	if (skb) {
+	  cli();
+	  skb_queue_tail(&bcs->rqueue, skb);
+	  sti();
+	  hfcsx_sched_event(bcs, B_RCVBUFREADY);
+	}
+
+	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+	if (count && skb)
+		goto Begin;
+	restore_flags(flags);
+	return;
+}
+
+/**************************/
+/* D-channel send routine */
+/**************************/
+static void
+hfcsx_fill_dfifo(struct IsdnCardState *cs)
+{
+	if (!cs->tx_skb)
+		return;
+	if (cs->tx_skb->len <= 0)
+		return;
+
+	if (write_fifo(cs, cs->tx_skb, HFCSX_SEL_D_TX, 0)) {
+	  dev_kfree_skb(cs->tx_skb);
+	  cs->tx_skb = NULL;
+	}
+	return;
+}
+
+/**************************/
+/* B-channel send routine */
+/**************************/
+static void
+hfcsx_fill_fifo(struct BCState *bcs)
+{
+	struct IsdnCardState *cs = bcs->cs;
+	int flags;
+
+	if (!bcs->tx_skb)
+		return;
+	if (bcs->tx_skb->len <= 0)
+		return;
+
+	save_flags(flags);
+	sti();
+
+	if (write_fifo(cs, bcs->tx_skb, 
+		       ((bcs->channel) && (!cs->hw.hfcsx.bswapped)) ? 
+		       HFCSX_SEL_B2_TX : HFCSX_SEL_B1_TX,
+		       (bcs->mode == L1_MODE_TRANS) ? 
+		       HFCSX_BTRANS_THRESHOLD : 0)) {
+
+	  bcs->tx_cnt -= bcs->tx_skb->len;
+	  if (bcs->st->lli.l1writewakeup &&
+	      (PACKET_NOACK != bcs->tx_skb->pkt_type))
+	    bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len);
+	  dev_kfree_skb(bcs->tx_skb);
+	  bcs->tx_skb = NULL;
+	  test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+	}
+
+	cli();
+	restore_flags(flags);
+	return;
+}
+
+/**********************************************/
+/* D-channel l1 state call for leased NT-mode */
+/**********************************************/
+static void
+dch_nt_l2l1(struct PStack *st, int pr, void *arg)
+{
+	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
+
+	switch (pr) {
+		case (PH_DATA | REQUEST):
+		case (PH_PULL | REQUEST):
+		case (PH_PULL | INDICATION):
+			st->l1.l1hw(st, pr, arg);
+			break;
+		case (PH_ACTIVATE | REQUEST):
+			st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
+			break;
+		case (PH_TESTLOOP | REQUEST):
+			if (1 & (long) arg)
+				debugl1(cs, "PH_TEST_LOOP B1");
+			if (2 & (long) arg)
+				debugl1(cs, "PH_TEST_LOOP B2");
+			if (!(3 & (long) arg))
+				debugl1(cs, "PH_TEST_LOOP DISABLED");
+			st->l1.l1hw(st, HW_TESTLOOP | REQUEST, arg);
+			break;
+		default:
+			if (cs->debug)
+				debugl1(cs, "dch_nt_l2l1 msg %04X unhandled", pr);
+			break;
+	}
+}
+
+
+
+/***********************/
+/* set/reset echo mode */
+/***********************/
+static int
+hfcsx_auxcmd(struct IsdnCardState *cs, isdn_ctrl * ic)
+{
+	int flags;
+	int i = *(unsigned int *) ic->parm.num;
+
+	if ((ic->arg == 98) &&
+	    (!(cs->hw.hfcsx.int_m1 & (HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC + HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC)))) {
+		save_flags(flags);
+		cli();
+		Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 0);	/* HFC ST G0 */
+		udelay(10);
+		cs->hw.hfcsx.sctrl |= SCTRL_MODE_NT;
+		Write_hfc(cs, HFCSX_SCTRL, cs->hw.hfcsx.sctrl);	/* set NT-mode */
+		udelay(10);
+		Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 1);	/* HFC ST G1 */
+		udelay(10);
+		Write_hfc(cs, HFCSX_STATES, 1 | HFCSX_ACTIVATE | HFCSX_DO_ACTION);
+		cs->dc.hfcsx.ph_state = 1;
+		cs->hw.hfcsx.nt_mode = 1;
+		cs->hw.hfcsx.nt_timer = 0;
+		cs->stlist->l2.l2l1 = dch_nt_l2l1;
+		restore_flags(flags);
+		debugl1(cs, "NT mode activated");
+		return (0);
+	}
+	if ((cs->chanlimit > 1) || (cs->hw.hfcsx.bswapped) ||
+	    (cs->hw.hfcsx.nt_mode) || (ic->arg != 12))
+		return (-EINVAL);
+
+	save_flags(flags);
+	cli();
+	if (i) {
+		cs->logecho = 1;
+		cs->hw.hfcsx.trm |= 0x20;	/* enable echo chan */
+		cs->hw.hfcsx.int_m1 |= HFCSX_INTS_B2REC;
+		/* reset Channel !!!!! */
+	} else {
+		cs->logecho = 0;
+		cs->hw.hfcsx.trm &= ~0x20;	/* disable echo chan */
+		cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_B2REC;
+	}
+	cs->hw.hfcsx.sctrl_r &= ~SCTRL_B2_ENA;
+	cs->hw.hfcsx.sctrl &= ~SCTRL_B2_ENA;
+	cs->hw.hfcsx.conn |= 0x10;	/* B2-IOM -> B2-ST */
+	cs->hw.hfcsx.ctmt &= ~2;
+	Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt);
+	Write_hfc(cs, HFCSX_SCTRL_R, cs->hw.hfcsx.sctrl_r);
+	Write_hfc(cs, HFCSX_SCTRL, cs->hw.hfcsx.sctrl);
+	Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);
+	Write_hfc(cs, HFCSX_TRM, cs->hw.hfcsx.trm);
+	Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
+	restore_flags(flags);
+	return (0);
+}				/* hfcsx_auxcmd */
+
+/*****************************/
+/* E-channel receive routine */
+/*****************************/
+static void
+receive_emsg(struct IsdnCardState *cs)
+{
+	int flags;
+	int count = 5;
+	u_char *ptr;
+	struct sk_buff *skb;
+
+
+	save_flags(flags);
+	cli();
+	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+		debugl1(cs, "echo_rec_data blocked");
+		restore_flags(flags);
+		return;
+	}
+	sti();
+
+	do {
+	  skb = read_fifo(cs, HFCSX_SEL_B2_RX, 0);
+	  if (skb) {
+	    if (cs->debug & DEB_DLOG_HEX) {
+	      ptr = cs->dlog;
+	      if ((skb->len) < MAX_DLOG_SPACE / 3 - 10) {
+		*ptr++ = 'E';
+		*ptr++ = 'C';
+		*ptr++ = 'H';
+		*ptr++ = 'O';
+		*ptr++ = ':';
+		ptr += QuickHex(ptr, skb->data, skb->len);
+		ptr--;
+		*ptr++ = '\n';
+		*ptr = 0;
+		HiSax_putstatus(cs, NULL, cs->dlog);
+	      } else
+		HiSax_putstatus(cs, "LogEcho: ", "warning Frame too big (%d)", skb->len);
+	    }
+	    dev_kfree_skb(skb);
+	  }
+	} while (--count && skb);
+
+	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+	restore_flags(flags);
+	return;
+}				/* receive_emsg */
+
+
+/*********************/
+/* Interrupt handler */
+/*********************/
+static void
+hfcsx_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char exval;
+	struct BCState *bcs;
+	int count = 15;
+	long flags;
+	u_char val, stat;
+
+	if (!cs) {
+		printk(KERN_WARNING "HFC-SX: Spurious interrupt!\n");
+		return;
+	}
+	if (!(cs->hw.hfcsx.int_m2 & 0x08))
+		return;		/* not initialised */
+
+	if (HFCSX_ANYINT & (stat = Read_hfc(cs, HFCSX_STATUS))) {
+		val = Read_hfc(cs, HFCSX_INT_S1);
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "HFC-SX: stat(%02x) s1(%02x)", stat, val);
+	} else
+		return;
+
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "HFC-SX irq %x %s", val,
+			test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ?
+			"locked" : "unlocked");
+	val &= cs->hw.hfcsx.int_m1;
+	if (val & 0x40) {	/* state machine irq */
+		exval = Read_hfc(cs, HFCSX_STATES) & 0xf;
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcsx.ph_state,
+				exval);
+		cs->dc.hfcsx.ph_state = exval;
+		sched_event_D_sx(cs, D_L1STATECHANGE);
+		val &= ~0x40;
+	}
+	if (val & 0x80) {	/* timer irq */
+		if (cs->hw.hfcsx.nt_mode) {
+			if ((--cs->hw.hfcsx.nt_timer) < 0)
+				sched_event_D_sx(cs, D_L1STATECHANGE);
+		}
+		val &= ~0x80;
+		Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt | HFCSX_CLTIMER);
+	}
+	while (val) {
+		save_flags(flags);
+		cli();
+		if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+			cs->hw.hfcsx.int_s1 |= val;
+			restore_flags(flags);
+			return;
+		}
+		if (cs->hw.hfcsx.int_s1 & 0x18) {
+			exval = val;
+			val = cs->hw.hfcsx.int_s1;
+			cs->hw.hfcsx.int_s1 = exval;
+		}
+		if (val & 0x08) {
+			if (!(bcs = Sel_BCS(cs, cs->hw.hfcsx.bswapped ? 1 : 0))) {
+				if (cs->debug)
+					debugl1(cs, "hfcsx spurious 0x08 IRQ");
+			} else
+				main_rec_hfcsx(bcs);
+		}
+		if (val & 0x10) {
+			if (cs->logecho)
+				receive_emsg(cs);
+			else if (!(bcs = Sel_BCS(cs, 1))) {
+				if (cs->debug)
+					debugl1(cs, "hfcsx spurious 0x10 IRQ");
+			} else
+				main_rec_hfcsx(bcs);
+		}
+		if (val & 0x01) {
+			if (!(bcs = Sel_BCS(cs, cs->hw.hfcsx.bswapped ? 1 : 0))) {
+				if (cs->debug)
+					debugl1(cs, "hfcsx spurious 0x01 IRQ");
+			} else {
+				if (bcs->tx_skb) {
+					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+						hfcsx_fill_fifo(bcs);
+						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+					} else
+						debugl1(cs, "fill_data %d blocked", bcs->channel);
+				} else {
+					if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+						if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+							hfcsx_fill_fifo(bcs);
+							test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+						} else
+							debugl1(cs, "fill_data %d blocked", bcs->channel);
+					} else {
+						hfcsx_sched_event(bcs, B_XMTBUFREADY);
+					}
+				}
+			}
+		}
+		if (val & 0x02) {
+			if (!(bcs = Sel_BCS(cs, 1))) {
+				if (cs->debug)
+					debugl1(cs, "hfcsx spurious 0x02 IRQ");
+			} else {
+				if (bcs->tx_skb) {
+					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+						hfcsx_fill_fifo(bcs);
+						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+					} else
+						debugl1(cs, "fill_data %d blocked", bcs->channel);
+				} else {
+					if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+						if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+							hfcsx_fill_fifo(bcs);
+							test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+						} else
+							debugl1(cs, "fill_data %d blocked", bcs->channel);
+					} else {
+						hfcsx_sched_event(bcs, B_XMTBUFREADY);
+					}
+				}
+			}
+		}
+		if (val & 0x20) {	/* receive dframe */
+			receive_dmsg(cs);
+		}
+		if (val & 0x04) {	/* dframe transmitted */
+			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
+				del_timer(&cs->dbusytimer);
+			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
+				sched_event_D_sx(cs, D_CLEARBUSY);
+			if (cs->tx_skb) {
+				if (cs->tx_skb->len) {
+					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+						hfcsx_fill_dfifo(cs);
+						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+					} else {
+						debugl1(cs, "hfcsx_fill_dfifo irq blocked");
+					}
+					goto afterXPR;
+				} else {
+					dev_kfree_skb(cs->tx_skb);
+					cs->tx_cnt = 0;
+					cs->tx_skb = NULL;
+				}
+			}
+			if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
+				cs->tx_cnt = 0;
+				if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+					hfcsx_fill_dfifo(cs);
+					test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+				} else {
+					debugl1(cs, "hfcsx_fill_dfifo irq blocked");
+				}
+			} else
+				sched_event_D_sx(cs, D_XMTBUFREADY);
+		}
+	      afterXPR:
+		if (cs->hw.hfcsx.int_s1 && count--) {
+			val = cs->hw.hfcsx.int_s1;
+			cs->hw.hfcsx.int_s1 = 0;
+			if (cs->debug & L1_DEB_ISAC)
+				debugl1(cs, "HFC-SX irq %x loop %d", val, 15 - count);
+		} else
+			val = 0;
+		restore_flags(flags);
+	}
+}
+
+/********************************************************************/
+/* timer callback for D-chan busy resolution. Currently no function */
+/********************************************************************/
+static void
+hfcsx_dbusy_timer(struct IsdnCardState *cs)
+{
+}
+
+/*************************************/
+/* Layer 1 D-channel hardware access */
+/*************************************/
+static void
+HFCSX_l1hw(struct PStack *st, int pr, void *arg)
+{
+	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
+	struct sk_buff *skb = arg;
+	int flags;
+
+	switch (pr) {
+		case (PH_DATA | REQUEST):
+			if (cs->debug & DEB_DLOG_HEX)
+				LogFrame(cs, skb->data, skb->len);
+			if (cs->debug & DEB_DLOG_VERBOSE)
+				dlogframe(cs, skb, 0);
+			if (cs->tx_skb) {
+				skb_queue_tail(&cs->sq, skb);
+#ifdef L2FRAME_DEBUG		/* psa */
+				if (cs->debug & L1_DEB_LAPD)
+					Logl2Frame(cs, skb, "PH_DATA Queued", 0);
+#endif
+			} else {
+				cs->tx_skb = skb;
+				cs->tx_cnt = 0;
+#ifdef L2FRAME_DEBUG		/* psa */
+				if (cs->debug & L1_DEB_LAPD)
+					Logl2Frame(cs, skb, "PH_DATA", 0);
+#endif
+				if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+				        hfcsx_fill_dfifo(cs); 
+					test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+				} else
+					debugl1(cs, "hfcsx_fill_dfifo blocked");
+
+			}
+			break;
+		case (PH_PULL | INDICATION):
+			if (cs->tx_skb) {
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
+				skb_queue_tail(&cs->sq, skb);
+				break;
+			}
+			if (cs->debug & DEB_DLOG_HEX)
+				LogFrame(cs, skb->data, skb->len);
+			if (cs->debug & DEB_DLOG_VERBOSE)
+				dlogframe(cs, skb, 0);
+			cs->tx_skb = skb;
+			cs->tx_cnt = 0;
+#ifdef L2FRAME_DEBUG		/* psa */
+			if (cs->debug & L1_DEB_LAPD)
+				Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
+#endif
+			if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+				hfcsx_fill_dfifo(cs); 
+				test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+			} else
+				debugl1(cs, "hfcsx_fill_dfifo blocked");
+			break;
+		case (PH_PULL | REQUEST):
+#ifdef L2FRAME_DEBUG		/* psa */
+			if (cs->debug & L1_DEB_LAPD)
+				debugl1(cs, "-> PH_REQUEST_PULL");
+#endif
+			if (!cs->tx_skb) {
+				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+			} else
+				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+			break;
+		case (HW_RESET | REQUEST):
+			Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 3);	/* HFC ST 3 */
+			udelay(6);
+			Write_hfc(cs, HFCSX_STATES, 3);	/* HFC ST 2 */
+			cs->hw.hfcsx.mst_m |= HFCSX_MASTER;
+			Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);
+			Write_hfc(cs, HFCSX_STATES, HFCSX_ACTIVATE | HFCSX_DO_ACTION);
+			l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
+			break;
+		case (HW_ENABLE | REQUEST):
+			Write_hfc(cs, HFCSX_STATES, HFCSX_ACTIVATE | HFCSX_DO_ACTION);
+			break;
+		case (HW_DEACTIVATE | REQUEST):
+			cs->hw.hfcsx.mst_m &= ~HFCSX_MASTER;
+			Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);
+			break;
+		case (HW_INFO3 | REQUEST):
+			cs->hw.hfcsx.mst_m |= HFCSX_MASTER;
+			Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);
+			break;
+		case (HW_TESTLOOP | REQUEST):
+			switch ((int) arg) {
+				case (1):
+					Write_hfc(cs, HFCSX_B1_SSL, 0x80);	/* tx slot */
+					Write_hfc(cs, HFCSX_B1_RSL, 0x80);	/* rx slot */
+					save_flags(flags);
+					cli();
+					cs->hw.hfcsx.conn = (cs->hw.hfcsx.conn & ~7) | 1;
+					Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);
+					restore_flags(flags);
+					break;
+
+				case (2):
+					Write_hfc(cs, HFCSX_B2_SSL, 0x81);	/* tx slot */
+					Write_hfc(cs, HFCSX_B2_RSL, 0x81);	/* rx slot */
+					save_flags(flags);
+					cli();
+					cs->hw.hfcsx.conn = (cs->hw.hfcsx.conn & ~0x38) | 0x08;
+					Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);
+					restore_flags(flags);
+					break;
+
+				default:
+					if (cs->debug & L1_DEB_WARN)
+						debugl1(cs, "hfcsx_l1hw loop invalid %4x", (int) arg);
+					return;
+			}
+			save_flags(flags);
+			cli();
+			cs->hw.hfcsx.trm |= 0x80;	/* enable IOM-loop */
+			Write_hfc(cs, HFCSX_TRM, cs->hw.hfcsx.trm);
+			restore_flags(flags);
+			break;
+		default:
+			if (cs->debug & L1_DEB_WARN)
+				debugl1(cs, "hfcsx_l1hw unknown pr %4x", pr);
+			break;
+	}
+}
+
+/***********************************************/
+/* called during init setting l1 stack pointer */
+/***********************************************/
+void
+setstack_hfcsx(struct PStack *st, struct IsdnCardState *cs)
+{
+	st->l1.l1hw = HFCSX_l1hw;
+}
+
+/**************************************/
+/* send B-channel data if not blocked */
+/**************************************/
+static void
+hfcsx_send_data(struct BCState *bcs)
+{
+	struct IsdnCardState *cs = bcs->cs;
+
+	if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+	  hfcsx_fill_fifo(bcs);
+		test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+	} else
+		debugl1(cs, "send_data %d blocked", bcs->channel);
+}
+
+/***************************************************************/
+/* activate/deactivate hardware for selected channels and mode */
+/***************************************************************/
+void
+mode_hfcsx(struct BCState *bcs, int mode, int bc)
+{
+	struct IsdnCardState *cs = bcs->cs;
+	int flags, fifo2;
+
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "HFCSX bchannel mode %d bchan %d/%d",
+			mode, bc, bcs->channel);
+	bcs->mode = mode;
+	bcs->channel = bc;
+	fifo2 = bc;
+	save_flags(flags);
+	cli();
+	if (cs->chanlimit > 1) {
+		cs->hw.hfcsx.bswapped = 0;	/* B1 and B2 normal mode */
+		cs->hw.hfcsx.sctrl_e &= ~0x80;
+	} else {
+		if (bc) {
+			if (mode != L1_MODE_NULL) {
+				cs->hw.hfcsx.bswapped = 1;	/* B1 and B2 exchanged */
+				cs->hw.hfcsx.sctrl_e |= 0x80;
+			} else {
+				cs->hw.hfcsx.bswapped = 0;	/* B1 and B2 normal mode */
+				cs->hw.hfcsx.sctrl_e &= ~0x80;
+			}
+			fifo2 = 0;
+		} else {
+			cs->hw.hfcsx.bswapped = 0;	/* B1 and B2 normal mode */
+			cs->hw.hfcsx.sctrl_e &= ~0x80;
+		}
+	}
+	switch (mode) {
+		case (L1_MODE_NULL):
+			if (bc) {
+				cs->hw.hfcsx.sctrl &= ~SCTRL_B2_ENA;
+				cs->hw.hfcsx.sctrl_r &= ~SCTRL_B2_ENA;
+			} else {
+				cs->hw.hfcsx.sctrl &= ~SCTRL_B1_ENA;
+				cs->hw.hfcsx.sctrl_r &= ~SCTRL_B1_ENA;
+			}
+			if (fifo2) {
+				cs->hw.hfcsx.int_m1 &= ~(HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC);
+			} else {
+				cs->hw.hfcsx.int_m1 &= ~(HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC);
+			}
+			break;
+		case (L1_MODE_TRANS):
+			if (bc) {
+				cs->hw.hfcsx.sctrl |= SCTRL_B2_ENA;
+				cs->hw.hfcsx.sctrl_r |= SCTRL_B2_ENA;
+			} else {
+				cs->hw.hfcsx.sctrl |= SCTRL_B1_ENA;
+				cs->hw.hfcsx.sctrl_r |= SCTRL_B1_ENA;
+			}
+			if (fifo2) {
+				cs->hw.hfcsx.int_m1 |= (HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC);
+				cs->hw.hfcsx.ctmt |= 2;
+				cs->hw.hfcsx.conn &= ~0x18;
+			} else {
+				cs->hw.hfcsx.int_m1 |= (HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC);
+				cs->hw.hfcsx.ctmt |= 1;
+				cs->hw.hfcsx.conn &= ~0x03;
+			}
+			break;
+		case (L1_MODE_HDLC):
+			if (bc) {
+				cs->hw.hfcsx.sctrl |= SCTRL_B2_ENA;
+				cs->hw.hfcsx.sctrl_r |= SCTRL_B2_ENA;
+			} else {
+				cs->hw.hfcsx.sctrl |= SCTRL_B1_ENA;
+				cs->hw.hfcsx.sctrl_r |= SCTRL_B1_ENA;
+			}
+			if (fifo2) {
+				cs->hw.hfcsx.int_m1 |= (HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC);
+				cs->hw.hfcsx.ctmt &= ~2;
+				cs->hw.hfcsx.conn &= ~0x18;
+			} else {
+				cs->hw.hfcsx.int_m1 |= (HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC);
+				cs->hw.hfcsx.ctmt &= ~1;
+				cs->hw.hfcsx.conn &= ~0x03;
+			}
+			break;
+		case (L1_MODE_EXTRN):
+			if (bc) {
+				cs->hw.hfcsx.conn |= 0x10;
+				cs->hw.hfcsx.sctrl |= SCTRL_B2_ENA;
+				cs->hw.hfcsx.sctrl_r |= SCTRL_B2_ENA;
+				cs->hw.hfcsx.int_m1 &= ~(HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC);
+			} else {
+				cs->hw.hfcsx.conn |= 0x02;
+				cs->hw.hfcsx.sctrl |= SCTRL_B1_ENA;
+				cs->hw.hfcsx.sctrl_r |= SCTRL_B1_ENA;
+				cs->hw.hfcsx.int_m1 &= ~(HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC);
+			}
+			break;
+	}
+	Write_hfc(cs, HFCSX_SCTRL_E, cs->hw.hfcsx.sctrl_e);
+	Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
+	Write_hfc(cs, HFCSX_SCTRL, cs->hw.hfcsx.sctrl);
+	Write_hfc(cs, HFCSX_SCTRL_R, cs->hw.hfcsx.sctrl_r);
+	Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt);
+	Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);
+	if (mode != L1_MODE_EXTRN) {
+	  reset_fifo(cs, fifo2 ? HFCSX_SEL_B2_RX : HFCSX_SEL_B1_RX);
+	  reset_fifo(cs, fifo2 ? HFCSX_SEL_B2_TX : HFCSX_SEL_B1_TX);
+	}
+	restore_flags(flags);
+}
+
+/******************************/
+/* Layer2 -> Layer 1 Transfer */
+/******************************/
+static void
+hfcsx_l2l1(struct PStack *st, int pr, void *arg)
+{
+	struct sk_buff *skb = arg;
+	long flags;
+
+	switch (pr) {
+		case (PH_DATA | REQUEST):
+			save_flags(flags);
+			cli();
+			if (st->l1.bcs->tx_skb) {
+				skb_queue_tail(&st->l1.bcs->squeue, skb);
+				restore_flags(flags);
+			} else {
+				st->l1.bcs->tx_skb = skb;
+/*                              test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+ */ st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
+				restore_flags(flags);
+			}
+			break;
+		case (PH_PULL | INDICATION):
+			if (st->l1.bcs->tx_skb) {
+				printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n");
+				break;
+			}
+			save_flags(flags);
+			cli();
+/*                      test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+ */ st->l1.bcs->tx_skb = skb;
+			st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
+			restore_flags(flags);
+			break;
+		case (PH_PULL | REQUEST):
+			if (!st->l1.bcs->tx_skb) {
+				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+			} else
+				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+			break;
+		case (PH_ACTIVATE | REQUEST):
+			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+			mode_hfcsx(st->l1.bcs, st->l1.mode, st->l1.bc);
+			l1_msg_b(st, pr, arg);
+			break;
+		case (PH_DEACTIVATE | REQUEST):
+			l1_msg_b(st, pr, arg);
+			break;
+		case (PH_DEACTIVATE | CONFIRM):
+			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+			test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+			mode_hfcsx(st->l1.bcs, 0, st->l1.bc);
+			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
+			break;
+	}
+}
+
+/******************************************/
+/* deactivate B-channel access and queues */
+/******************************************/
+static void
+close_hfcsx(struct BCState *bcs)
+{
+	mode_hfcsx(bcs, 0, bcs->channel);
+	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
+		discard_queue(&bcs->rqueue);
+		discard_queue(&bcs->squeue);
+		if (bcs->tx_skb) {
+			dev_kfree_skb(bcs->tx_skb);
+			bcs->tx_skb = NULL;
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+		}
+	}
+}
+
+/*************************************/
+/* init B-channel queues and control */
+/*************************************/
+static int
+open_hfcsxstate(struct IsdnCardState *cs, struct BCState *bcs)
+{
+	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
+		skb_queue_head_init(&bcs->rqueue);
+		skb_queue_head_init(&bcs->squeue);
+	}
+	bcs->tx_skb = NULL;
+	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+	bcs->event = 0;
+	bcs->tx_cnt = 0;
+	return (0);
+}
+
+/*********************************/
+/* inits the stack for B-channel */
+/*********************************/
+static int
+setstack_2b(struct PStack *st, struct BCState *bcs)
+{
+	bcs->channel = st->l1.bc;
+	if (open_hfcsxstate(st->l1.hardware, bcs))
+		return (-1);
+	st->l1.bcs = bcs;
+	st->l2.l2l1 = hfcsx_l2l1;
+	setstack_manager(st);
+	bcs->st = st;
+	setstack_l1_B(st);
+	return (0);
+}
+
+/***************************/
+/* handle L1 state changes */
+/***************************/
+static void
+hfcsx_bh(struct IsdnCardState *cs)
+{
+	int flags;
+/*      struct PStack *stptr;
+ */
+	if (!cs)
+		return;
+	if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
+		if (!cs->hw.hfcsx.nt_mode)
+			switch (cs->dc.hfcsx.ph_state) {
+				case (0):
+					l1_msg(cs, HW_RESET | INDICATION, NULL);
+					break;
+				case (3):
+					l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
+					break;
+				case (8):
+					l1_msg(cs, HW_RSYNC | INDICATION, NULL);
+					break;
+				case (6):
+					l1_msg(cs, HW_INFO2 | INDICATION, NULL);
+					break;
+				case (7):
+					l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
+					break;
+				default:
+					break;
+		} else {
+			switch (cs->dc.hfcsx.ph_state) {
+				case (2):
+					save_flags(flags);
+					cli();
+					if (cs->hw.hfcsx.nt_timer < 0) {
+						cs->hw.hfcsx.nt_timer = 0;
+						cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER;
+						Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
+						/* Clear already pending ints */
+						if (Read_hfc(cs, HFCSX_INT_S1));
+
+						Write_hfc(cs, HFCSX_STATES, 4 | HFCSX_LOAD_STATE);
+						udelay(10);
+						Write_hfc(cs, HFCSX_STATES, 4);
+						cs->dc.hfcsx.ph_state = 4;
+					} else {
+						cs->hw.hfcsx.int_m1 |= HFCSX_INTS_TIMER;
+						Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
+						cs->hw.hfcsx.ctmt &= ~HFCSX_AUTO_TIMER;
+						cs->hw.hfcsx.ctmt |= HFCSX_TIM3_125;
+						Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt | HFCSX_CLTIMER);
+						Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt | HFCSX_CLTIMER);
+						cs->hw.hfcsx.nt_timer = NT_T1_COUNT;
+						Write_hfc(cs, HFCSX_STATES, 2 | HFCSX_NT_G2_G3);	/* allow G2 -> G3 transition */
+					}
+					restore_flags(flags);
+					break;
+				case (1):
+				case (3):
+				case (4):
+					save_flags(flags);
+					cli();
+					cs->hw.hfcsx.nt_timer = 0;
+					cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER;
+					Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
+					restore_flags(flags);
+					break;
+				default:
+					break;
+			}
+		}
+	}
+	if (test_and_clear_bit(D_RCVBUFREADY, &cs->event))
+		DChannel_proc_rcv(cs);
+	if (test_and_clear_bit(D_XMTBUFREADY, &cs->event))
+		DChannel_proc_xmt(cs);
+}
+
+
+/********************************/
+/* called for card init message */
+/********************************/
+__initfunc(void
+	   inithfcsx(struct IsdnCardState *cs))
+{
+	cs->setstack_d = setstack_hfcsx;
+	cs->dbusytimer.function = (void *) hfcsx_dbusy_timer;
+	cs->dbusytimer.data = (long) cs;
+	init_timer(&cs->dbusytimer);
+	cs->tqueue.routine = (void *) (void *) hfcsx_bh;
+	cs->BC_Send_Data = &hfcsx_send_data;
+	cs->bcs[0].BC_SetStack = setstack_2b;
+	cs->bcs[1].BC_SetStack = setstack_2b;
+	cs->bcs[0].BC_Close = close_hfcsx;
+	cs->bcs[1].BC_Close = close_hfcsx;
+	mode_hfcsx(cs->bcs, 0, 0);
+	mode_hfcsx(cs->bcs + 1, 0, 1);
+}
+
+
+
+/*******************************************/
+/* handle card messages from control layer */
+/*******************************************/
+static int
+hfcsx_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	long flags;
+
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "HFCSX: card_msg %x", mt);
+	switch (mt) {
+		case CARD_RESET:
+			reset_hfcsx(cs);
+			return (0);
+		case CARD_RELEASE:
+			release_io_hfcsx(cs);
+			return (0);
+		case CARD_INIT:
+			inithfcsx(cs);
+			save_flags(flags);
+			sti();
+			current->state = TASK_UNINTERRUPTIBLE;
+			schedule_timeout((80 * HZ) / 1000);	/* Timeout 80ms */
+			/* now switch timer interrupt off */
+			cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER;
+			Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
+			/* reinit mode reg */
+			Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);
+			restore_flags(flags);
+			return (0);
+		case CARD_TEST:
+			return (0);
+	}
+	return (0);
+}
+
+
+
+__initfunc(int
+	   setup_hfcsx(struct IsdnCard *card))
+{
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+	int flags;
+
+	strcpy(tmp, hfcsx_revision);
+	printk(KERN_INFO "HiSax: HFC-SX driver Rev. %s\n", HiSax_getrev(tmp));
+	cs->hw.hfcsx.base = card->para[1] & 0xfffe;
+	cs->irq = card->para[0];
+	cs->hw.hfcsx.int_s1 = 0;
+	cs->dc.hfcsx.ph_state = 0;
+	cs->hw.hfcsx.fifo = 255;
+	if (cs->typ == ISDN_CTYPE_HFC_SX) {
+	        if ((!cs->hw.hfcsx.base) || 
+		    check_region((cs->hw.hfcsx.base), 2)) {
+		  printk(KERN_WARNING
+			 "HiSax: HFC-SX io-base 0x%x already in use\n",
+		          cs->hw.hfcsx.base);
+		  return(0);
+		} else {
+		  request_region(cs->hw.hfcsx.base, 2, "HFCSX isdn");
+		}
+		byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF);
+		byteout(cs->hw.hfcsx.base + 1,
+			((cs->hw.hfcsx.base >> 8) & 3) | 0x54);
+		udelay(10);
+	        cs->hw.hfcsx.chip = Read_hfc(cs,HFCSX_CHIP_ID);
+                switch (cs->hw.hfcsx.chip >> 4) {
+		  case 1: 
+		    tmp[0] ='+';
+		    break;
+		  case 9: 
+		    tmp[0] ='P';
+		    break;
+		  default:
+		    printk(KERN_WARNING
+			   "HFC-SX: invalid chip id 0x%x\n",
+			   cs->hw.hfcsx.chip >> 4);
+		    release_region(cs->hw.hfcsx.base, 2);
+		    return(0);
+		}  
+		if (!ccd_sp_irqtab[cs->irq & 0xF]) {
+		  printk(KERN_WARNING 
+			 "HFC_SX: invalid irq %d specified\n",cs->irq & 0xF);
+		  release_region(cs->hw.hfcsx.base, 2);
+		  return(0);
+		}  
+		save_flags(flags);
+		cli();
+		if (!(cs->hw.hfcsx.extra = (void *)
+		      kmalloc(sizeof(struct hfcsx_extra), GFP_ATOMIC))) {
+		  restore_flags(flags);
+		  release_region(cs->hw.hfcsx.base, 2);
+		  printk(KERN_WARNING "HFC-SX: unable to allocate memory\n");
+		  return(0);
+		}
+		restore_flags(flags);
+
+		printk(KERN_INFO
+		       "HFC-S%c chip detected at base 0x%x IRQ %d HZ %d\n",
+		       tmp[0], (u_int) cs->hw.hfcsx.base,
+		       cs->irq, HZ);
+		cs->hw.hfcsx.int_m2 = 0;	/* disable alle interrupts */
+		cs->hw.hfcsx.int_m1 = 0;
+		Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
+		Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
+	} else
+		return (0);	/* no valid card type */
+
+	cs->readisac = NULL;
+	cs->writeisac = NULL;
+	cs->readisacfifo = NULL;
+	cs->writeisacfifo = NULL;
+	cs->BC_Read_Reg = NULL;
+	cs->BC_Write_Reg = NULL;
+	cs->irq_func = &hfcsx_interrupt;
+
+	cs->hw.hfcsx.timer.function = (void *) hfcsx_Timer;
+	cs->hw.hfcsx.timer.data = (long) cs;
+	cs->hw.hfcsx.b_fifo_size = 0; /* fifo size still unknown */
+	cs->hw.hfcsx.cirm = ccd_sp_irqtab[cs->irq & 0xF]; /* RAM not evaluated */
+	init_timer(&cs->hw.hfcsx.timer);
+
+	reset_hfcsx(cs);
+	cs->cardmsg = &hfcsx_card_msg;
+	cs->auxcmd = &hfcsx_auxcmd;
+	return (1);
+}
+
+
+
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/isdn/hisax/hfc_sx.h linux.15p9/drivers/isdn/hisax/hfc_sx.h
--- linux.vanilla/drivers/isdn/hisax/hfc_sx.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/isdn/hisax/hfc_sx.h	Wed Jan 26 23:08:43 2000
@@ -0,0 +1,216 @@
+/* $Id: hfc_sx.h,v 1.1 1999/11/18 00:09:18 werner Exp $
+
+ *  specific defines for CCD's HFC 2BDS0 S+,SP chips
+ *
+ * Author     Werner Cornelius (werner@isdn4linux.de)      
+ *
+ * Copyright 1999  by Werner Cornelius (werner@isdn4linux.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Log: hfc_sx.h,v $
+ * Revision 1.1  1999/11/18 00:09:18  werner
+ *
+ * Initial release of files for HFC-S+ and HFC-SP cards with 32K-RAM.
+ * Audio and Echo are supported.
+ *
+ *
+ *
+ */
+
+/*********************************************/
+/* thresholds for transparent B-channel mode */
+/* change mask and threshold simultaneously  */
+/*********************************************/
+#define HFCSX_BTRANS_THRESHOLD 128
+#define HFCSX_BTRANS_THRESMASK 0x00
+
+/* GCI/IOM bus monitor registers */
+
+#define HFCSX_C_I       0x02
+#define HFCSX_TRxR      0x03
+#define HFCSX_MON1_D    0x0A
+#define HFCSX_MON2_D    0x0B
+
+
+/* GCI/IOM bus timeslot registers */
+
+#define HFCSX_B1_SSL    0x20
+#define HFCSX_B2_SSL    0x21
+#define HFCSX_AUX1_SSL  0x22
+#define HFCSX_AUX2_SSL  0x23
+#define HFCSX_B1_RSL    0x24
+#define HFCSX_B2_RSL    0x25
+#define HFCSX_AUX1_RSL  0x26
+#define HFCSX_AUX2_RSL  0x27
+
+/* GCI/IOM bus data registers */
+
+#define HFCSX_B1_D      0x28
+#define HFCSX_B2_D      0x29
+#define HFCSX_AUX1_D    0x2A
+#define HFCSX_AUX2_D    0x2B
+
+/* GCI/IOM bus configuration registers */
+
+#define HFCSX_MST_EMOD  0x2D
+#define HFCSX_MST_MODE	0x2E
+#define HFCSX_CONNECT 	0x2F
+
+
+/* Interrupt and status registers */
+
+#define HFCSX_TRM       0x12
+#define HFCSX_B_MODE    0x13
+#define HFCSX_CHIP_ID   0x16
+#define HFCSX_CIRM  	0x18
+#define HFCSX_CTMT	0x19
+#define HFCSX_INT_M1  	0x1A
+#define HFCSX_INT_M2  	0x1B
+#define HFCSX_INT_S1  	0x1E
+#define HFCSX_INT_S2  	0x1F
+#define HFCSX_STATUS  	0x1C
+
+/* S/T section registers */
+
+#define HFCSX_STATES  	0x30
+#define HFCSX_SCTRL  	0x31
+#define HFCSX_SCTRL_E   0x32
+#define HFCSX_SCTRL_R   0x33
+#define HFCSX_SQ  	0x34
+#define HFCSX_CLKDEL  	0x37
+#define HFCSX_B1_REC    0x3C
+#define HFCSX_B1_SEND   0x3C
+#define HFCSX_B2_REC    0x3D
+#define HFCSX_B2_SEND   0x3D
+#define HFCSX_D_REC     0x3E
+#define HFCSX_D_SEND    0x3E
+#define HFCSX_E_REC     0x3F
+
+/****************/
+/* FIFO section */
+/****************/
+#define HFCSX_FIF_SEL   0x10
+#define HFCSX_FIF_Z1L   0x80
+#define HFCSX_FIF_Z1H   0x84
+#define HFCSX_FIF_Z2L   0x88
+#define HFCSX_FIF_Z2H   0x8C
+#define HFCSX_FIF_INCF1 0xA8
+#define HFCSX_FIF_DWR   0xAC
+#define HFCSX_FIF_F1    0xB0
+#define HFCSX_FIF_F2    0xB4
+#define HFCSX_FIF_INCF2 0xB8
+#define HFCSX_FIF_DRD   0xBC
+
+/* bits in status register (READ) */
+#define HFCSX_SX_PROC    0x02
+#define HFCSX_NBUSY	 0x04 
+#define HFCSX_TIMER_ELAP 0x10
+#define HFCSX_STATINT	 0x20
+#define HFCSX_FRAMEINT	 0x40
+#define HFCSX_ANYINT	 0x80
+
+/* bits in CTMT (Write) */
+#define HFCSX_CLTIMER    0x80
+#define HFCSX_TIM3_125   0x04
+#define HFCSX_TIM25      0x10
+#define HFCSX_TIM50      0x14
+#define HFCSX_TIM400     0x18
+#define HFCSX_TIM800     0x1C
+#define HFCSX_AUTO_TIMER 0x20
+#define HFCSX_TRANSB2    0x02
+#define HFCSX_TRANSB1    0x01
+
+/* bits in CIRM (Write) */
+#define HFCSX_IRQ_SELMSK 0x07
+#define HFCSX_IRQ_SELDIS 0x00
+#define HFCSX_RESET  	 0x08
+#define HFCSX_FIFO_RESET 0x80
+
+
+/* bits in INT_M1 and INT_S1 */
+#define HFCSX_INTS_B1TRANS  0x01
+#define HFCSX_INTS_B2TRANS  0x02
+#define HFCSX_INTS_DTRANS   0x04
+#define HFCSX_INTS_B1REC    0x08
+#define HFCSX_INTS_B2REC    0x10
+#define HFCSX_INTS_DREC     0x20
+#define HFCSX_INTS_L1STATE  0x40
+#define HFCSX_INTS_TIMER    0x80
+
+/* bits in INT_M2 */
+#define HFCSX_PROC_TRANS    0x01
+#define HFCSX_GCI_I_CHG     0x02
+#define HFCSX_GCI_MON_REC   0x04
+#define HFCSX_IRQ_ENABLE    0x08
+
+/* bits in STATES */
+#define HFCSX_STATE_MSK     0x0F
+#define HFCSX_LOAD_STATE    0x10
+#define HFCSX_ACTIVATE	    0x20
+#define HFCSX_DO_ACTION     0x40
+#define HFCSX_NT_G2_G3      0x80
+
+/* bits in HFCD_MST_MODE */
+#define HFCSX_MASTER	    0x01
+#define HFCSX_SLAVE         0x00
+/* remaining bits are for codecs control */
+
+/* bits in HFCD_SCTRL */
+#define SCTRL_B1_ENA	    0x01
+#define SCTRL_B2_ENA	    0x02
+#define SCTRL_MODE_TE       0x00
+#define SCTRL_MODE_NT       0x04
+#define SCTRL_LOW_PRIO	    0x08
+#define SCTRL_SQ_ENA	    0x10
+#define SCTRL_TEST	    0x20
+#define SCTRL_NONE_CAP	    0x40
+#define SCTRL_PWR_DOWN	    0x80
+
+/* bits in SCTRL_E  */
+#define HFCSX_AUTO_AWAKE    0x01
+#define HFCSX_DBIT_1        0x04
+#define HFCSX_IGNORE_COL    0x08
+#define HFCSX_CHG_B1_B2     0x80
+
+/**********************************/
+/* definitions for FIFO selection */
+/**********************************/
+#define HFCSX_SEL_D_RX      5
+#define HFCSX_SEL_D_TX      4
+#define HFCSX_SEL_B1_RX     1
+#define HFCSX_SEL_B1_TX     0
+#define HFCSX_SEL_B2_RX     3
+#define HFCSX_SEL_B2_TX     2
+
+#define MAX_D_FRAMES 15
+#define MAX_B_FRAMES 31
+#define B_SUB_VAL_32K       0x0200
+#define B_FIFO_SIZE_32K    (0x2000 - B_SUB_VAL_32K)
+#define B_SUB_VAL_8K        0x1A00
+#define B_FIFO_SIZE_8K     (0x2000 - B_SUB_VAL_8K)
+#define D_FIFO_SIZE  512
+#define D_FREG_MASK  0xF
+
+/************************************************************/
+/* structure holding additional dynamic data -> send marker */
+/************************************************************/
+struct hfcsx_extra {
+  unsigned short marker[2*(MAX_B_FRAMES+1) + (MAX_D_FRAMES+1)];
+};
+
+extern void main_irq_hfcsx(struct BCState *bcs);
+extern void inithfcsx(struct IsdnCardState *cs);
+extern void releasehfcsx(struct IsdnCardState *cs);
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/isdn/hisax/hisax.h linux.15p9/drivers/isdn/hisax/hisax.h
--- linux.vanilla/drivers/isdn/hisax/hisax.h	Tue Jan  4 21:18:47 2000
+++ linux.15p9/drivers/isdn/hisax/hisax.h	Wed Feb 16 20:56:39 2000
@@ -1,8 +1,16 @@
-/* $Id: hisax.h,v 2.38 1999/11/14 23:37:03 keil Exp $
+/* $Id: hisax.h,v 2.40 2000/01/20 19:51:46 keil Exp $
 
  *   Basic declarations, defines and prototypes
  *
  * $Log: hisax.h,v $
+ * Revision 2.40  2000/01/20 19:51:46  keil
+ * Fix AddTimer message
+ * Change CONFIG defines
+ *
+ * Revision 2.39  1999/11/18 00:00:43  werner
+ *
+ * Added support for HFC-S+ and HFC-SP cards
+ *
  * Revision 2.38  1999/11/14 23:37:03  keil
  * new ISA memory mapped IO
  *
@@ -784,6 +792,31 @@
 	struct timer_list timer;
 };
 
+struct hfcSX_hw {
+        unsigned int  base;
+	unsigned char cirm;
+	unsigned char ctmt;
+	unsigned char conn;
+	unsigned char mst_m;
+	unsigned char int_m1;
+	unsigned char int_m2;
+	unsigned char int_s1;
+	unsigned char sctrl;
+        unsigned char sctrl_r;
+        unsigned char sctrl_e;
+        unsigned char trm;
+	unsigned char stat;
+	unsigned char fifo;
+        unsigned char bswapped;
+        unsigned char nt_mode;
+        unsigned char chip;
+        int b_fifo_size;
+        unsigned char last_fifo;
+        void *extra;
+        int nt_timer;
+	struct timer_list timer;
+};
+
 struct hfcD_hw {
 	unsigned int addr;
 	unsigned int bfifosize;
@@ -894,6 +927,10 @@
 	int ph_state;
 };
 
+struct hfcsx_chip {
+	int ph_state;
+};
+
 struct w6692_chip {
 	int ph_state;
 };
@@ -934,6 +971,7 @@
 		struct njet_hw njet;
 		struct hfcD_hw hfcD;
 		struct hfcPCI_hw hfcpci;
+		struct hfcSX_hw hfcsx;
 		struct ix1_hw niccy;
 		struct isurf_hw isurf;
 		struct saphir_hw saphir;
@@ -973,6 +1011,7 @@
 		struct isac_chip isac;
 		struct hfcd_chip hfcd;
 		struct hfcpci_chip hfcpci;
+		struct hfcsx_chip hfcsx;
 		struct w6692_chip w6692;
 	} dc;
 	u_char *rcvbuf;
@@ -1032,7 +1071,8 @@
 #define  ISDN_CTYPE_GAZEL	34
 #define  ISDN_CTYPE_HFC_PCI	35
 #define  ISDN_CTYPE_W6692	36
-#define  ISDN_CTYPE_COUNT	36
+#define  ISDN_CTYPE_HFC_SX      37
+#define  ISDN_CTYPE_COUNT	37
 
 
 #ifdef ISDN_CHIP_ISAC
@@ -1201,6 +1241,12 @@
 #define  CARD_HFC_PCI 0
 #endif
 
+#ifdef	CONFIG_HISAX_HFC_SX
+#define  CARD_HFC_SX 1
+#else
+#define  CARD_HFC_SX 0
+#endif
+
 #ifdef  CONFIG_HISAX_AMD7930
 #define CARD_AMD7930 1
 #else
@@ -1298,19 +1344,6 @@
 #ifdef CONFIG_HISAX_EURO
 #undef TEI_PER_CARD
 #define TEI_PER_CARD 1
-#define HISAX_EURO_SENDCOMPLETE 1
-#define EXT_BEARER_CAPS 1
-#define HISAX_SEND_STD_LLC_IE 1
-#ifdef	CONFIG_HISAX_NO_SENDCOMPLETE
-#undef HISAX_EURO_SENDCOMPLETE
-#endif
-#ifdef	CONFIG_HISAX_NO_LLC
-#undef HISAX_SEND_STD_LLC_IE
-#endif
-#undef HISAX_DE_AOC
-#ifdef CONFIG_DE_AOC
-#define HISAX_DE_AOC 1
-#endif
 #endif
 
 /* L1 Debug */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/isdn/hisax/isar.c linux.15p9/drivers/isdn/hisax/isar.c
--- linux.vanilla/drivers/isdn/hisax/isar.c	Tue Jan  4 21:18:47 2000
+++ linux.15p9/drivers/isdn/hisax/isar.c	Wed Jan 26 23:08:43 2000
@@ -1,4 +1,4 @@
-/* $Id: isar.c,v 1.8 1999/12/19 13:00:56 keil Exp $
+/* $Id: isar.c,v 1.9 2000/01/20 19:47:45 keil Exp $
 
  * isar.c   ISAR (Siemens PSB 7110) specific routines
  *
@@ -6,6 +6,9 @@
  *
  *
  * $Log: isar.c,v $
+ * Revision 1.9  2000/01/20 19:47:45  keil
+ * Add Fax Class 1 support
+ *
  * Revision 1.8  1999/12/19 13:00:56  keil
  * Fix races in setting a new mode
  *
@@ -45,7 +48,17 @@
 
 #define MIN(a,b) ((a<b)?a:b)
 
+#define DLE	0x10
+#define ETX	0x03
+
+
+const u_char faxmodulation_s[] = "3,24,48,72,73,74,96,97,98,121,122,145,146"; 
+const u_char faxmodulation[] = {3,24,48,72,73,74,96,97,98,121,122,145,146}; 
+#define FAXMODCNT 13
+
 void isar_setup(struct IsdnCardState *cs);
+static void isar_pump_cmd(struct BCState *bcs, u_char cmd, u_char para);
+static inline void ll_deliver_faxstat(struct BCState *bcs, u_char status);
 
 static inline int
 waitforHIA(struct IsdnCardState *cs, int timeout)
@@ -435,6 +448,12 @@
 isar_bh(struct BCState *bcs)
 {
 	BChannel_bh(bcs);
+	if (test_and_clear_bit(B_LL_NOCARRIER, &bcs->event))
+		ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_NOCARR);
+	if (test_and_clear_bit(B_LL_CONNECT, &bcs->event))
+		ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_CONNECT);
+	if (test_and_clear_bit(B_LL_OK, &bcs->event))
+		ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_OK);
 }
 
 static void
@@ -446,6 +465,42 @@
 }
 
 static inline void
+send_DLE_ETX(struct BCState *bcs)
+{
+	u_char dleetx[2] = {DLE,ETX};
+	struct sk_buff *skb;
+	
+	if ((skb = dev_alloc_skb(2))) {
+		memcpy(skb_put(skb, 2), dleetx, 2);
+		skb_queue_tail(&bcs->rqueue, skb);
+		isar_sched_event(bcs, B_RCVBUFREADY);
+	} else {
+		printk(KERN_WARNING "HiSax: skb out of memory\n");
+	}
+}
+
+static inline int
+dle_count(unsigned char *buf, int len)
+{
+	int count = 0;
+
+	while (len--)
+		if (*buf++ == DLE)
+			count++;
+	return count;
+}
+
+static inline void
+insert_dle(unsigned char *dest, unsigned char *src, int count) {
+	/* <DLE> in input stream have to be flagged as <DLE><DLE> */
+	while (count--) {
+		*dest++ = *src;
+		if (*src++ == DLE)
+			*dest++ = DLE;
+	}
+}
+ 
+static inline void
 isar_rcv_frame(struct IsdnCardState *cs, struct BCState *bcs)
 {
 	u_char *ptr;
@@ -515,6 +570,88 @@
 			}
 		}
 		break;
+	case L1_MODE_FAX:
+		if (bcs->hw.isar.state != STFAX_ACTIV) {
+			if (cs->debug & L1_DEB_WARN)
+				debugl1(cs, "isar_rcv_frame: not ACTIV");
+			cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+			bcs->hw.isar.rcvidx = 0;
+			break;
+		}
+		if (bcs->hw.isar.cmd == PCTRL_CMD_FRM) {
+			rcv_mbox(cs, ireg, bcs->hw.isar.rcvbuf);
+			bcs->hw.isar.rcvidx = ireg->clsb +
+				dle_count(bcs->hw.isar.rcvbuf, ireg->clsb);
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "isar_rcv_frame: raw(%d) dle(%d)",
+					ireg->clsb, bcs->hw.isar.rcvidx);
+			if ((skb = dev_alloc_skb(bcs->hw.isar.rcvidx))) {
+				insert_dle((u_char *)skb_put(skb, bcs->hw.isar.rcvidx),
+					bcs->hw.isar.rcvbuf, ireg->clsb);
+				skb_queue_tail(&bcs->rqueue, skb);
+				isar_sched_event(bcs, B_RCVBUFREADY);
+				if (ireg->cmsb & SART_NMD) { /* ABORT */
+					if (cs->debug & L1_DEB_WARN)
+						debugl1(cs, "isar_rcv_frame: no more data");
+					cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+					bcs->hw.isar.rcvidx = 0;
+					send_DLE_ETX(bcs);
+					sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) |
+						ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC,
+						0, NULL);
+					bcs->hw.isar.state = STFAX_ESCAPE;
+					isar_sched_event(bcs, B_LL_NOCARRIER);
+				}
+			} else {
+				printk(KERN_WARNING "HiSax: skb out of memory\n");
+				cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+			}
+			break;
+		}
+		if (bcs->hw.isar.cmd != PCTRL_CMD_FRH) {
+			if (cs->debug & L1_DEB_WARN)
+				debugl1(cs, "isar_rcv_frame: unknown fax mode %x",
+					bcs->hw.isar.cmd);
+			cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+			bcs->hw.isar.rcvidx = 0;
+			break;
+		}
+		/* PCTRL_CMD_FRH */
+		if ((bcs->hw.isar.rcvidx + ireg->clsb) > HSCX_BUFMAX) {
+			if (cs->debug & L1_DEB_WARN)
+				debugl1(cs, "isar_rcv_frame: incoming packet too large");
+			cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+			bcs->hw.isar.rcvidx = 0;
+		} else if (ireg->cmsb & HDLC_ERROR) {
+			if (cs->debug & L1_DEB_WARN)
+				debugl1(cs, "isar frame error %x len %d",
+					ireg->cmsb, ireg->clsb);
+			bcs->hw.isar.rcvidx = 0;
+			cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+		} else {
+			if (ireg->cmsb & HDLC_FSD)
+				bcs->hw.isar.rcvidx = 0;
+			ptr = bcs->hw.isar.rcvbuf + bcs->hw.isar.rcvidx;
+			bcs->hw.isar.rcvidx += ireg->clsb;
+			rcv_mbox(cs, ireg, ptr);
+			if (ireg->cmsb & HDLC_FED) {
+				if (bcs->hw.isar.rcvidx < 3) { /* last 2 bytes are the FCS */
+					printk(KERN_WARNING "ISAR: HDLC frame too short(%d)\n",
+						bcs->hw.isar.rcvidx);
+				} else if (!(skb = dev_alloc_skb(bcs->hw.isar.rcvidx))) {
+					printk(KERN_WARNING "ISAR: receive out of memory\n");
+				} else {
+					memcpy(skb_put(skb, bcs->hw.isar.rcvidx),
+						bcs->hw.isar.rcvbuf,
+						bcs->hw.isar.rcvidx);
+					skb_queue_tail(&bcs->rqueue, skb);
+					isar_sched_event(bcs, B_RCVBUFREADY);
+					send_DLE_ETX(bcs);
+					isar_sched_event(bcs, B_LL_OK);
+				}
+			}
+		}
+		break;
 	default:
 		printk(KERN_ERR"isar_rcv_frame mode (%x)error\n", bcs->mode);
 		cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
@@ -547,38 +684,57 @@
 		count = bcs->tx_skb->len;
 		msb = HDLC_FED;
 	}
-	if (!bcs->hw.isar.txcnt)
-		msb |= HDLC_FST;
 	save_flags(flags);
 	cli();
 	ptr = bcs->tx_skb->data;
+	if (!bcs->hw.isar.txcnt) {
+		msb |= HDLC_FST;
+		if ((bcs->mode == L1_MODE_FAX) &&
+			(bcs->hw.isar.cmd == PCTRL_CMD_FTH)) {
+			if (bcs->tx_skb->len > 1) {
+				if ((ptr[0]== 0xff) && (ptr[1] == 0x13))
+					/* last frame */
+					test_and_set_bit(BC_FLG_LASTDATA,
+						&bcs->Flag);
+			}  
+		}
+	}
 	skb_pull(bcs->tx_skb, count);
 	bcs->tx_cnt -= count;
 	bcs->hw.isar.txcnt += count;
 	switch (bcs->mode) {
-	case L1_MODE_NULL:
-		printk(KERN_ERR"isar_fill_fifo wrong mode 0\n");
-		break;
-	case L1_MODE_TRANS:
-	case L1_MODE_V32:
-		if (!sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA,
-			0, count, ptr)) {
-			if (cs->debug)
-				debugl1(cs, "isar bin data send dp%d failed",
-					bcs->hw.isar.dpath);
-		}
-		break;
-	case L1_MODE_HDLC:
-		if (!sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA,
-			msb, count, ptr)) {
+		case L1_MODE_NULL:
+			printk(KERN_ERR"isar_fill_fifo wrong mode 0\n");
+			break;
+		case L1_MODE_TRANS:
+		case L1_MODE_V32:
+			sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA,
+				0, count, ptr);
+			break;
+		case L1_MODE_HDLC:
+			sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA,
+				msb, count, ptr);
+			break;
+		case L1_MODE_FAX:
+			if (bcs->hw.isar.state != STFAX_ACTIV) {
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "isar_fill_fifo: not ACTIV");
+			} else if (bcs->hw.isar.cmd == PCTRL_CMD_FTH) { 
+				sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA,
+					msb, count, ptr);
+			} else if (bcs->hw.isar.cmd == PCTRL_CMD_FTM) {
+				sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA,
+					0, count, ptr);
+			} else {
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "isar_fill_fifo: not FTH/FTM");
+			}
+			break;
+		default:
 			if (cs->debug)
-				debugl1(cs, "isar hdlc data send dp%d failed",
-					bcs->hw.isar.dpath);
-		}
-		break;
-	default:
-		printk(KERN_ERR"isar_fill_fifo mode (%x)error\n", bcs->mode);
-		break;
+				debugl1(cs, "isar_fill_fifo mode(%x) error", bcs->mode);
+			printk(KERN_ERR"isar_fill_fifo mode(%x) error\n", bcs->mode);
+			break;
 	}
 	restore_flags(flags);
 }
@@ -606,6 +762,18 @@
 			if (bcs->st->lli.l1writewakeup &&
 				(PACKET_NOACK != bcs->tx_skb->pkt_type))
 					bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.isar.txcnt);
+			if (bcs->mode == L1_MODE_FAX) {
+				if (bcs->hw.isar.cmd == PCTRL_CMD_FTH) {
+					if (test_bit(BC_FLG_LASTDATA, &bcs->Flag)) {
+						test_and_set_bit(BC_FLG_NMD_DATA, &bcs->Flag);
+					}
+				} else if (bcs->hw.isar.cmd == PCTRL_CMD_FTM) {
+					if (test_bit(BC_FLG_DLEETX, &bcs->Flag)) {
+						test_and_set_bit(BC_FLG_LASTDATA, &bcs->Flag);
+						test_and_set_bit(BC_FLG_NMD_DATA, &bcs->Flag);
+					}
+				}
+			}
 			dev_kfree_skb(bcs->tx_skb);
 			bcs->hw.isar.txcnt = 0; 
 			bcs->tx_skb = NULL;
@@ -616,6 +784,18 @@
 		test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
 		isar_fill_fifo(bcs);
 	} else {
+		if (test_and_clear_bit(BC_FLG_DLEETX, &bcs->Flag)) {
+			if (test_and_clear_bit(BC_FLG_LASTDATA, &bcs->Flag)) {
+				if (test_and_clear_bit(BC_FLG_NMD_DATA, &bcs->Flag)) {
+					u_char dummy = 0;
+					sendmsg(bcs->cs, SET_DPS(bcs->hw.isar.dpath) |
+						ISAR_HIS_SDATA, 0x01, 1, &dummy);
+				}
+				test_and_set_bit(BC_FLG_LL_OK, &bcs->Flag);
+			} else {
+				isar_sched_event(bcs, B_LL_CONNECT);
+			}
+		}
 		test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 		isar_sched_event(bcs, B_XMTBUFREADY);
 	}
@@ -642,6 +822,7 @@
 	}
 	
 }
+
 const char *dmril[] = {"NO SPEED", "1200/75", "NODEF2", "75/1200", "NODEF4",
 			"300", "600", "1200", "2400", "4800", "7200",
 			"9600nt", "9600t", "12000", "14400", "WRONG"};
@@ -703,7 +884,7 @@
 }
 
 static void
-isar_pump_status_ev(struct BCState *bcs, u_char devt) {
+isar_pump_statev_modem(struct BCState *bcs, u_char devt) {
 	struct IsdnCardState *cs = bcs->cs;
 	u_char dps = SET_DPS(bcs->hw.isar.dpath);
 
@@ -772,6 +953,192 @@
 	}
 }
 
+static inline void
+ll_deliver_faxstat(struct BCState *bcs, u_char status)
+{
+        isdn_ctrl ic;
+	struct Channel *chanp = (struct Channel *) bcs->st->lli.userdata;
+ 
+	if (bcs->cs->debug & L1_DEB_HSCX)
+		debugl1(bcs->cs, "HL->LL FAXIND %x", status);
+	ic.driver = bcs->cs->myid;
+	ic.command = ISDN_STAT_FAXIND;
+	ic.arg = chanp->chan;
+	ic.parm.aux.cmd = status;
+	bcs->cs->iif.statcallb(&ic);
+}
+
+static void
+isar_pump_statev_fax(struct BCState *bcs, u_char devt) {
+	struct IsdnCardState *cs = bcs->cs;
+	u_char dps = SET_DPS(bcs->hw.isar.dpath);
+	u_char p1;
+
+	switch(devt) {
+		case PSEV_10MS_TIMER:
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "pump stev TIMER");
+			break;
+		case PSEV_RSP_READY:
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "pump stev RSP_READY");
+			bcs->hw.isar.state = STFAX_READY;
+			l1_msg_b(bcs->st, PH_ACTIVATE | REQUEST, NULL);
+			if (test_bit(BC_FLG_ORIG, &bcs->Flag)) {
+				isar_pump_cmd(bcs, ISDN_FAX_CLASS1_FRH, 3);
+			} else {
+				isar_pump_cmd(bcs, ISDN_FAX_CLASS1_FTH, 3);
+			}
+			break;
+		case PSEV_LINE_TX_H:
+			if (bcs->hw.isar.state == STFAX_LINE) {
+				if (cs->debug & L1_DEB_HSCX)
+					debugl1(cs, "pump stev LINE_TX_H");
+				bcs->hw.isar.state = STFAX_CONT;
+				sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_CONT, 0, NULL);
+			} else {
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "pump stev LINE_TX_H wrong st %x",
+						bcs->hw.isar.state);
+			}
+			break;
+		case PSEV_LINE_RX_H:
+			if (bcs->hw.isar.state == STFAX_LINE) {
+				if (cs->debug & L1_DEB_HSCX)
+					debugl1(cs, "pump stev LINE_RX_H");
+				bcs->hw.isar.state = STFAX_CONT;
+				sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_CONT, 0, NULL);
+			} else {
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "pump stev LINE_RX_H wrong st %x",
+						bcs->hw.isar.state);
+			}
+			break;
+		case PSEV_LINE_TX_B:
+			if (bcs->hw.isar.state == STFAX_LINE) {
+				if (cs->debug & L1_DEB_HSCX)
+					debugl1(cs, "pump stev LINE_TX_B");
+				bcs->hw.isar.state = STFAX_CONT;
+				sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_CONT, 0, NULL);
+			} else {
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "pump stev LINE_TX_B wrong st %x",
+						bcs->hw.isar.state);
+			}
+			break;
+		case PSEV_LINE_RX_B:
+			if (bcs->hw.isar.state == STFAX_LINE) {
+				if (cs->debug & L1_DEB_HSCX)
+					debugl1(cs, "pump stev LINE_RX_B");
+				bcs->hw.isar.state = STFAX_CONT;
+				sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_CONT, 0, NULL);
+			} else {
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "pump stev LINE_RX_B wrong st %x",
+						bcs->hw.isar.state);
+			}
+			break;
+		case PSEV_RSP_CONN:
+			if (bcs->hw.isar.state == STFAX_CONT) {
+				if (cs->debug & L1_DEB_HSCX)
+					debugl1(cs, "pump stev RSP_CONN");
+				bcs->hw.isar.state = STFAX_ACTIV;
+				test_and_set_bit(ISAR_RATE_REQ, &bcs->hw.isar.reg->Flags);
+				sendmsg(cs, dps | ISAR_HIS_PSTREQ, 0, 0, NULL);
+				if (bcs->hw.isar.cmd == PCTRL_CMD_FTH) {
+					/* 1s Flags before data */
+					if (test_and_set_bit(BC_FLG_FTI_RUN, &bcs->Flag))
+						del_timer(&bcs->hw.isar.ftimer);
+					/* 1000 ms */
+					bcs->hw.isar.ftimer.expires =
+						jiffies + ((1000 * HZ)/1000);
+					test_and_set_bit(BC_FLG_LL_CONN,
+						&bcs->Flag);
+					add_timer(&bcs->hw.isar.ftimer);
+				} else {
+					isar_sched_event(bcs, B_LL_CONNECT);
+				}
+			} else {
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "pump stev RSP_CONN wrong st %x",
+						bcs->hw.isar.state);
+			}
+			break;
+		case PSEV_FLAGS_DET:
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "pump stev FLAGS_DET");
+			break;
+		case PSEV_RSP_DISC:
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "pump stev RSP_DISC");
+			if (bcs->hw.isar.state == STFAX_ESCAPE) {
+				switch(bcs->hw.isar.newcmd) {
+					case PCTRL_CMD_FTH:
+					case PCTRL_CMD_FTM:
+						p1 = 10;
+						sendmsg(cs, dps | ISAR_HIS_PUMPCTRL,
+							PCTRL_CMD_SILON, 1, &p1);
+						bcs->hw.isar.state = STFAX_SILDET;
+						break;
+					case PCTRL_CMD_FRH:
+					case PCTRL_CMD_FRM:
+						p1 = bcs->hw.isar.newmod;
+						bcs->hw.isar.newmod = 0;
+						bcs->hw.isar.cmd = bcs->hw.isar.newcmd;
+						bcs->hw.isar.newcmd = 0;
+						sendmsg(cs, dps | ISAR_HIS_PUMPCTRL,
+							bcs->hw.isar.cmd, 1, &p1);
+						bcs->hw.isar.state = STFAX_LINE;
+						break;
+					default:
+						if (cs->debug & L1_DEB_HSCX)
+							debugl1(cs, "RSP_DISC unknown newcmd %x", bcs->hw.isar.newcmd);
+						break;
+				}
+			} else if (bcs->hw.isar.state == STFAX_ACTIV) {
+				if (test_and_clear_bit(BC_FLG_LL_OK, &bcs->Flag)) {
+					isar_sched_event(bcs, B_LL_OK);
+				} else if (bcs->hw.isar.cmd == PCTRL_CMD_FRM) {
+					send_DLE_ETX(bcs);
+					isar_sched_event(bcs, B_LL_NOCARRIER);
+				} else {
+					ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_FCERROR);
+				}
+				bcs->hw.isar.state = STFAX_READY;
+			} else {
+				bcs->hw.isar.state = STFAX_READY;
+				ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_FCERROR);
+			}
+			break;
+		case PSEV_RSP_SILDET:
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "pump stev RSP_SILDET");
+			if (bcs->hw.isar.state == STFAX_SILDET) {
+				p1 = bcs->hw.isar.newmod;
+				bcs->hw.isar.newmod = 0;
+				bcs->hw.isar.cmd = bcs->hw.isar.newcmd;
+				bcs->hw.isar.newcmd = 0;
+				sendmsg(cs, dps | ISAR_HIS_PUMPCTRL,
+					bcs->hw.isar.cmd, 1, &p1);
+				bcs->hw.isar.state = STFAX_LINE;
+			}
+			break;
+		case PSEV_RSP_SILOFF:
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "pump stev RSP_SILOFF");
+			break;
+		case PSEV_RSP_FCERR:
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "pump stev RSP_FCERR");
+			bcs->hw.isar.state = STFAX_ESCAPE;
+			sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL);
+			ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_FCERROR);
+			break;
+		default:
+			break;
+	}
+}
+
 static char debbuf[128];
 
 void
@@ -791,8 +1158,6 @@
 			} else {
 				debugl1(cs, "isar spurious IIS_RDATA %x/%x/%x",
 					ireg->iis, ireg->cmsb, ireg->clsb);
-				printk(KERN_WARNING"isar spurious IIS_RDATA %x/%x/%x\n",
-					ireg->iis, ireg->cmsb, ireg->clsb);
 				cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
 			}
 			break;
@@ -818,12 +1183,18 @@
 		case ISAR_IIS_PSTEV:
 			if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) {
 				rcv_mbox(cs, ireg, (u_char *)ireg->par);
-				isar_pump_status_ev(bcs, ireg->cmsb);
+				if (bcs->mode == L1_MODE_V32) {
+					isar_pump_statev_modem(bcs, ireg->cmsb);
+				} else if (bcs->mode == L1_MODE_FAX) {
+					isar_pump_statev_fax(bcs, ireg->cmsb);
+				} else {
+					if (cs->debug & L1_DEB_WARN)
+						debugl1(cs, "isar IIS_PSTEV pmode %d stat %x",
+							bcs->mode, ireg->cmsb);
+				}
 			} else {
 				debugl1(cs, "isar spurious IIS_PSTEV %x/%x/%x",
 					ireg->iis, ireg->cmsb, ireg->clsb);
-				printk(KERN_WARNING"isar spurious IIS_PSTEV %x/%x/%x\n",
-					ireg->iis, ireg->cmsb, ireg->clsb);
 				cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
 			}
 			break;
@@ -834,8 +1205,6 @@
 			} else {
 				debugl1(cs, "isar spurious IIS_PSTRSP %x/%x/%x",
 					ireg->iis, ireg->cmsb, ireg->clsb);
-				printk(KERN_WARNING"isar spurious IIS_PSTRSP %x/%x/%x\n",
-					ireg->iis, ireg->cmsb, ireg->clsb);
 				cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
 			}
 			break;
@@ -870,6 +1239,17 @@
 }
 
 static void
+ftimer_handler(struct BCState *bcs) {
+	if (bcs->cs->debug)
+		debugl1(bcs->cs, "ftimer flags %04x",
+			bcs->Flag);
+	test_and_clear_bit(BC_FLG_FTI_RUN, &bcs->Flag);
+	if (test_and_clear_bit(BC_FLG_LL_CONN, &bcs->Flag)) {
+		isar_sched_event(bcs, B_LL_CONNECT);
+	}
+}
+
+static void
 setup_pump(struct BCState *bcs) {
 	struct IsdnCardState *cs = bcs->cs;
 	u_char dps = SET_DPS(bcs->hw.isar.dpath);
@@ -879,11 +1259,7 @@
 		case L1_MODE_NULL:
 		case L1_MODE_TRANS:
 		case L1_MODE_HDLC:
-			if (!sendmsg(cs, dps | ISAR_HIS_PUMPCFG, PMOD_BYPASS, 0, NULL)) {
-				if (cs->debug)
-					debugl1(cs, "isar pump bypass cfg dp%d failed",
-						bcs->hw.isar.dpath);
-			}
+			sendmsg(cs, dps | ISAR_HIS_PUMPCFG, PMOD_BYPASS, 0, NULL);
 			break;
 		case L1_MODE_V32:
 			ctrl = PMOD_DATAMODEM;
@@ -899,11 +1275,7 @@
 			param[2] = PV32P3_AMOD | PV32P3_V32B | PV32P3_V23B;
 			param[3] = PV32P4_UT144;
 			param[4] = PV32P5_UT144;
-			if (!sendmsg(cs, dps | ISAR_HIS_PUMPCFG, ctrl, 6, param)) {
-				if (cs->debug)
-					debugl1(cs, "isar pump datamodem cfg dp%d failed",
-						bcs->hw.isar.dpath);
-			}
+			sendmsg(cs, dps | ISAR_HIS_PUMPCFG, ctrl, 6, param);
 			break;
 		case L1_MODE_FAX:
 			ctrl = PMOD_FAX;
@@ -914,11 +1286,11 @@
 				param[1] = PFAXP2_ATN;
 			}
 			param[0] = 6; /* 6 db */
-			if (!sendmsg(cs, dps | ISAR_HIS_PUMPCFG, ctrl, 2, param)) {
-				if (cs->debug)
-					debugl1(cs, "isar pump faxmodem cfg dp%d failed",
-						bcs->hw.isar.dpath);
-			}
+			sendmsg(cs, dps | ISAR_HIS_PUMPCFG, ctrl, 2, param);
+			bcs->hw.isar.state = STFAX_NULL;
+			bcs->hw.isar.newcmd = 0;
+			bcs->hw.isar.newmod = 0;
+			test_and_set_bit(BC_FLG_FTI_RUN, &bcs->Flag);
 			break;
 	}
 	udelay(1000);
@@ -934,37 +1306,25 @@
 	
 	switch (bcs->mode) {
 		case L1_MODE_NULL:
-			if (!sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_DISABLE, 0, NULL)) {
-				if (cs->debug)
-					debugl1(cs, "isar sart disable dp%d failed",
-						bcs->hw.isar.dpath);
-			}
+			sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_DISABLE, 0,
+				NULL);
 			break;
 		case L1_MODE_TRANS:
-			if (!sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_BINARY, 2, "\0\0")) {
-				if (cs->debug)
-					debugl1(cs, "isar sart binary dp%d failed",
-						bcs->hw.isar.dpath);
-			}
+			sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_BINARY, 2,
+				"\0\0");
 			break;
 		case L1_MODE_HDLC:
 		case L1_MODE_FAX:
 			param[0] = 0;
-			if (!sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_HDLC, 1, param)) {
-				if (cs->debug)
-					debugl1(cs, "isar sart hdlc dp%d failed",
-						bcs->hw.isar.dpath);
-			}
+			sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_HDLC, 1,
+				param);
 			break;
 		case L1_MODE_V32:
 			ctrl = SMODE_V14 | SCTRL_HDMC_BOTH;
 			param[0] = S_P1_CHS_8;
 			param[1] = S_P2_BFT_DEF;
-			if (!sendmsg(cs, dps | ISAR_HIS_SARTCFG, ctrl, 2, param)) {
-				if (cs->debug)
-					debugl1(cs, "isar sart v14 dp%d failed",
-						bcs->hw.isar.dpath);
-			}
+			sendmsg(cs, dps | ISAR_HIS_SARTCFG, ctrl, 2,
+				param);
 			break;
 	}
 	udelay(1000);
@@ -1035,8 +1395,8 @@
 					&bcs->hw.isar.reg->Flags))
 					bcs->hw.isar.dpath = 1;
 				else {
-					printk(KERN_WARNING"isar modeisar analog works only with DP1\n");
-					debugl1(cs, "isar modeisar analog works only with DP1");
+					printk(KERN_WARNING"isar modeisar analog funktions only with DP1\n");
+					debugl1(cs, "isar modeisar analog funktions only with DP1");
 					return(1);
 				}
 				break;
@@ -1060,6 +1420,107 @@
 	return(0);
 }
 
+static void
+isar_pump_cmd(struct BCState *bcs, u_char cmd, u_char para) 
+{
+	struct IsdnCardState *cs = bcs->cs;
+	u_char dps = SET_DPS(bcs->hw.isar.dpath);
+	u_char ctrl = 0, nom = 0, p1 = 0;
+
+	switch(cmd) {
+		case ISDN_FAX_CLASS1_FTM:
+			if (bcs->hw.isar.state == STFAX_READY) {
+				p1 = para;
+				ctrl = PCTRL_CMD_FTM;
+				nom = 1;
+				bcs->hw.isar.state = STFAX_LINE;
+				bcs->hw.isar.cmd = ctrl;
+				bcs->hw.isar.mod = para;
+				bcs->hw.isar.newmod = 0;
+				bcs->hw.isar.newcmd = 0;
+			} else if ((bcs->hw.isar.state == STFAX_ACTIV) &&
+				(bcs->hw.isar.cmd == PCTRL_CMD_FTM) &&
+				(bcs->hw.isar.mod == para)) {
+				ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_CONNECT);
+			} else {
+				bcs->hw.isar.newmod = para;
+				bcs->hw.isar.newcmd = PCTRL_CMD_FTM;
+				nom = 0;
+				ctrl = PCTRL_CMD_ESC;
+				bcs->hw.isar.state = STFAX_ESCAPE; 
+			}
+			break;
+		case ISDN_FAX_CLASS1_FTH:
+			if (bcs->hw.isar.state == STFAX_READY) {
+				p1 = para;
+				ctrl = PCTRL_CMD_FTH;
+				nom = 1;
+				bcs->hw.isar.state = STFAX_LINE;
+				bcs->hw.isar.cmd = ctrl;
+				bcs->hw.isar.mod = para;
+				bcs->hw.isar.newmod = 0;
+				bcs->hw.isar.newcmd = 0;
+			} else if ((bcs->hw.isar.state == STFAX_ACTIV) &&
+				(bcs->hw.isar.cmd == PCTRL_CMD_FTH) &&
+				(bcs->hw.isar.mod == para)) {
+				ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_CONNECT);
+			} else {
+				bcs->hw.isar.newmod = para;
+				bcs->hw.isar.newcmd = PCTRL_CMD_FTH;
+				nom = 0;
+				ctrl = PCTRL_CMD_ESC;
+				bcs->hw.isar.state = STFAX_ESCAPE; 
+			}
+			break;
+		case ISDN_FAX_CLASS1_FRM:
+			if (bcs->hw.isar.state == STFAX_READY) {
+				p1 = para;
+				ctrl = PCTRL_CMD_FRM;
+				nom = 1;
+				bcs->hw.isar.state = STFAX_LINE;
+				bcs->hw.isar.cmd = ctrl;
+				bcs->hw.isar.mod = para;
+				bcs->hw.isar.newmod = 0;
+				bcs->hw.isar.newcmd = 0;
+			} else if ((bcs->hw.isar.state == STFAX_ACTIV) &&
+				(bcs->hw.isar.cmd == PCTRL_CMD_FRM) &&
+				(bcs->hw.isar.mod == para)) {
+				ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_CONNECT);
+			} else {
+				bcs->hw.isar.newmod = para;
+				bcs->hw.isar.newcmd = PCTRL_CMD_FRM;
+				nom = 0;
+				ctrl = PCTRL_CMD_ESC;
+				bcs->hw.isar.state = STFAX_ESCAPE; 
+			}
+			break;
+		case ISDN_FAX_CLASS1_FRH:
+			if (bcs->hw.isar.state == STFAX_READY) {
+				p1 = para;
+				ctrl = PCTRL_CMD_FRH;
+				nom = 1;
+				bcs->hw.isar.state = STFAX_LINE;
+				bcs->hw.isar.cmd = ctrl;
+				bcs->hw.isar.mod = para;
+				bcs->hw.isar.newmod = 0;
+				bcs->hw.isar.newcmd = 0;
+			} else if ((bcs->hw.isar.state == STFAX_ACTIV) &&
+				(bcs->hw.isar.cmd == PCTRL_CMD_FRH) &&
+				(bcs->hw.isar.mod == para)) {
+				ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_CONNECT);
+			} else {
+				bcs->hw.isar.newmod = para;
+				bcs->hw.isar.newcmd = PCTRL_CMD_FRH;
+				nom = 0;
+				ctrl = PCTRL_CMD_ESC;
+				bcs->hw.isar.state = STFAX_ESCAPE; 
+			}
+			break;
+	}
+	if (ctrl)
+		sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, ctrl, nom, &p1);
+}
+
 void
 isar_setup(struct IsdnCardState *cs)
 {
@@ -1070,11 +1531,8 @@
 	msg = 61;
 	for (i=0; i<2; i++) {
 		/* Buffer Config */
-		if (!sendmsg(cs, (i ? ISAR_HIS_DPS2 : ISAR_HIS_DPS1) |
-			ISAR_HIS_P12CFG, 4, 1, &msg)) {
-			if (cs->debug)
-				debugl1(cs, "isar P%dCFG failed", i+1);
-		}
+		sendmsg(cs, (i ? ISAR_HIS_DPS2 : ISAR_HIS_DPS1) |
+			ISAR_HIS_P12CFG, 4, 1, &msg);
 		cs->bcs[i].hw.isar.mml = msg;
 		cs->bcs[i].mode = 0;
 		cs->bcs[i].hw.isar.dpath = i + 1;
@@ -1141,6 +1599,7 @@
 						l1_msg_b(st, PH_ACTIVATE | REQUEST, arg);
 					break;
 				case L1_MODE_V32:
+				case L1_MODE_FAX:
 					if (modeisar(st->l1.bcs, st->l1.mode, st->l1.bc))
 						l1_msg_b(st, PH_DEACTIVATE | REQUEST, arg);
 					break;
@@ -1179,6 +1638,7 @@
 				debugl1(bcs->cs, "closeisar clear BC_FLG_BUSY");
 		}
 	}
+	del_timer(&bcs->hw.isar.ftimer);
 }
 
 int
@@ -1200,6 +1660,9 @@
 	bcs->event = 0;
 	bcs->hw.isar.rcvidx = 0;
 	bcs->tx_cnt = 0;
+	bcs->hw.isar.ftimer.function = (void *) ftimer_handler;
+	bcs->hw.isar.ftimer.data = (long) bcs;
+	init_timer(&bcs->hw.isar.ftimer);
 	return (0);
 }
 
@@ -1220,15 +1683,66 @@
 int
 isar_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) {
 	u_long adr;
-	int features;
+	int features, i;
+	struct BCState *bcs;
 
 	if (cs->debug & L1_DEB_HSCX)
 		debugl1(cs, "isar_auxcmd cmd/ch %x/%d", ic->command, ic->arg);
 	switch (ic->command) {
+		case (ISDN_CMD_FAXCMD):
+			bcs = cs->channel[ic->arg].bcs;
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "isar_auxcmd cmd/subcmd %d/%d",
+					ic->parm.aux.cmd, ic->parm.aux.subcmd);
+			switch(ic->parm.aux.cmd) {
+				case ISDN_FAX_CLASS1_CTRL:
+					if (ic->parm.aux.subcmd == ETX)
+						test_and_set_bit(BC_FLG_DLEETX,
+							&bcs->Flag);
+					break;
+				case ISDN_FAX_CLASS1_FRM:
+				case ISDN_FAX_CLASS1_FRH:
+				case ISDN_FAX_CLASS1_FTM:
+				case ISDN_FAX_CLASS1_FTH:
+					if (ic->parm.aux.subcmd == AT_QUERY) {
+						sprintf(ic->parm.aux.para,
+							"%d", bcs->hw.isar.mod);
+						ic->command = ISDN_STAT_FAXIND;
+						ic->parm.aux.cmd = ISDN_FAX_CLASS1_QUERY;
+						cs->iif.statcallb(ic);
+						return(0);
+					} else if (ic->parm.aux.subcmd == AT_EQ_QUERY) {
+						strcpy(ic->parm.aux.para, faxmodulation_s);
+						ic->command = ISDN_STAT_FAXIND;
+						ic->parm.aux.cmd = ISDN_FAX_CLASS1_QUERY;
+						cs->iif.statcallb(ic);
+						return(0);
+					} else if (ic->parm.aux.subcmd == AT_EQ_VALUE) {
+						for(i=0;i<FAXMODCNT;i++)
+							if (faxmodulation[i]==ic->parm.aux.para[0])
+								break;
+						if ((FAXMODCNT > i) && 
+							test_bit(BC_FLG_INIT, &bcs->Flag)) {
+							isar_pump_cmd(bcs,
+								ic->parm.aux.cmd,
+								ic->parm.aux.para[0]);
+							return(0);
+						}
+					}
+					/* wrong modulation or not activ */
+					/* fall through */
+				default:
+					ic->command = ISDN_STAT_FAXIND;
+					ic->parm.aux.cmd = ISDN_FAX_CLASS1_ERROR;
+					cs->iif.statcallb(ic);
+			}
+			break;
 		case (ISDN_CMD_IOCTL):
 			switch (ic->arg) {
 				case (9): /* load firmware */
-					features = ISDN_FEATURE_L2_MODEM;
+					features = ISDN_FEATURE_L2_MODEM |
+						ISDN_FEATURE_L2_FAX |
+						ISDN_FEATURE_L3_FCLASS1;
 					memcpy(&adr, ic->parm.num, sizeof(ulong));
 					if (isar_load_firmware(cs, (u_char *)adr))
 						return(1);
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/isdn/hisax/isar.h linux.15p9/drivers/isdn/hisax/isar.h
--- linux.vanilla/drivers/isdn/hisax/isar.h	Tue Jan  4 21:18:47 2000
+++ linux.15p9/drivers/isdn/hisax/isar.h	Wed Jan 26 23:08:44 2000
@@ -1,10 +1,13 @@
-/* $Id: isar.h,v 1.6 1999/10/14 20:25:29 keil Exp $
+/* $Id: isar.h,v 1.7 2000/01/20 19:47:45 keil Exp $
  * isar.h   ISAR (Siemens PSB 7110) specific defines
  *
  * Author Karsten Keil (keil@isdn4linux.de)
  *
  *
  * $Log: isar.h,v $
+ * Revision 1.7  2000/01/20 19:47:45  keil
+ * Add Fax Class 1 support
+ *
  * Revision 1.6  1999/10/14 20:25:29  keil
  * add a statistic for error monitoring
  *
@@ -145,6 +148,28 @@
 #define PSEV_REM_REN	0xcd
 #define PSEV_GSTN_CLR	0xd4
 
+#define PSEV_RSP_READY	0xbc
+#define PSEV_LINE_TX_H	0xb3
+#define PSEV_LINE_TX_B	0xb2
+#define PSEV_LINE_RX_H	0xb1
+#define PSEV_LINE_RX_B	0xb0
+#define PSEV_RSP_CONN	0xb5
+#define PSEV_RSP_DISC	0xb7
+#define PSEV_RSP_FCERR	0xb9
+#define PSEV_RSP_SILDET	0xbe
+#define PSEV_RSP_SILOFF	0xab
+#define PSEV_FLAGS_DET	0xba
+
+#define PCTRL_CMD_FTH	0xa7
+#define PCTRL_CMD_FRH	0xa5
+#define PCTRL_CMD_FTM	0xa8
+#define PCTRL_CMD_FRM	0xa6
+#define PCTRL_CMD_SILON	0xac
+#define PCTRL_CMD_CONT	0xa2
+#define PCTRL_CMD_ESC	0xa4
+#define PCTRL_CMD_SILOFF 0xab
+#define PCTRL_CMD_HALT	0xa9
+
 #define PCTRL_LOC_RET	0xcf
 #define PCTRL_LOC_REN	0xce
 
@@ -192,6 +217,15 @@
 #define BSTAT_RDM3	0x8
 #define BSTEV_TBO	0x1f
 #define BSTEV_RBO	0x2f
+
+/* FAX State Machine */
+#define STFAX_NULL	0
+#define STFAX_READY	1
+#define STFAX_LINE	2
+#define STFAX_CONT	3
+#define STFAX_ACTIV	4
+#define STFAX_ESCAPE	5
+#define STFAX_SILDET	6
 
 extern int ISARVersion(struct IsdnCardState *cs, char *s);
 extern void isar_int_main(struct IsdnCardState *cs);
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/isdn/hisax/isdnl1.c linux.15p9/drivers/isdn/hisax/isdnl1.c
--- linux.vanilla/drivers/isdn/hisax/isdnl1.c	Wed Oct 20 01:12:37 1999
+++ linux.15p9/drivers/isdn/hisax/isdnl1.c	Wed Jan 26 23:08:44 2000
@@ -1,4 +1,4 @@
-/* $Id: isdnl1.c,v 2.36 1999/08/25 16:50:57 keil Exp $
+/* $Id: isdnl1.c,v 2.37 2000/01/20 19:51:46 keil Exp $
 
  * isdnl1.c     common low level stuff for Siemens Chipsetbased isdn cards
  *              based on the teles driver from Jan den Ouden
@@ -15,6 +15,10 @@
  *
  *
  * $Log: isdnl1.c,v $
+ * Revision 2.37  2000/01/20 19:51:46  keil
+ * Fix AddTimer message
+ * Change CONFIG defines
+ *
  * Revision 2.36  1999/08/25 16:50:57  keil
  * Fix bugs which cause 2.3.14 hangs (waitqueue init)
  *
@@ -138,7 +142,7 @@
  *
  */
 
-const char *l1_revision = "$Revision: 2.36 $";
+const char *l1_revision = "$Revision: 2.37 $";
 
 #define __NO_VERSION__
 #include "hisax.h"
@@ -362,7 +366,8 @@
 					stptr = stptr->next;
 			if (!found)
 				dev_kfree_skb(skb);
-		}
+		} else
+			dev_kfree_skb(skb);
 	}
 }
 
@@ -559,11 +564,8 @@
 	struct PStack *st = fi->userdata;
 
 	FsmChangeState(fi, ST_L1_F3);
-//	if (!test_bit(FLG_L1_T3RUN, &st->l1.Flags)) {
-		FsmDelTimer(&st->l1.timer, 1);
-		FsmAddTimer(&st->l1.timer, 550, EV_TIMER_DEACT, NULL, 2);
-		test_and_set_bit(FLG_L1_DEACTTIMER, &st->l1.Flags);
-//	}
+	FsmRestartTimer(&st->l1.timer, 550, EV_TIMER_DEACT, NULL, 2);
+	test_and_set_bit(FLG_L1_DEACTTIMER, &st->l1.Flags);
 }
 
 static void
@@ -574,8 +576,7 @@
 	if (test_bit(FLG_L1_ACTIVATING, &st->l1.Flags)) {
 		FsmChangeState(fi, ST_L1_F4);
 		st->l1.l1hw(st, HW_INFO3 | REQUEST, NULL);
-		FsmDelTimer(&st->l1.timer, 1);
-		FsmAddTimer(&st->l1.timer, TIMER3_VALUE, EV_TIMER3, NULL, 2);
+		FsmRestartTimer(&st->l1.timer, TIMER3_VALUE, EV_TIMER3, NULL, 2);
 		test_and_set_bit(FLG_L1_T3RUN, &st->l1.Flags);
 	} else
 		FsmChangeState(fi, ST_L1_F3);
@@ -614,7 +615,7 @@
 	if (!test_bit(FLG_L1_ACTIVATED, &st->l1.Flags)) {
 		if (test_and_clear_bit(FLG_L1_T3RUN, &st->l1.Flags))
 			FsmDelTimer(&st->l1.timer, 3);
-		FsmAddTimer(&st->l1.timer, 110, EV_TIMER_ACT, NULL, 2);
+		FsmRestartTimer(&st->l1.timer, 110, EV_TIMER_ACT, NULL, 2);
 		test_and_set_bit(FLG_L1_ACTTIMER, &st->l1.Flags);
 	}
 }
@@ -729,7 +730,7 @@
 	struct PStack *st = fi->userdata;
 
 	FsmChangeState(fi, ST_L1_WAIT_ACT);
-	FsmAddTimer(&st->l1.timer, st->l1.delay, EV_TIMER_ACT, NULL, 2);
+	FsmRestartTimer(&st->l1.timer, st->l1.delay, EV_TIMER_ACT, NULL, 2);
 }
 
 static void
@@ -738,7 +739,7 @@
 	struct PStack *st = fi->userdata;
 
 	FsmChangeState(fi, ST_L1_WAIT_DEACT);
-	FsmAddTimer(&st->l1.timer, 10, EV_TIMER_DEACT, NULL, 2);
+	FsmRestartTimer(&st->l1.timer, 10, EV_TIMER_DEACT, NULL, 2);
 }
 
 static void
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/isdn/hisax/l3_1tr6.c linux.15p9/drivers/isdn/hisax/l3_1tr6.c
--- linux.vanilla/drivers/isdn/hisax/l3_1tr6.c	Wed Oct 20 01:12:37 1999
+++ linux.15p9/drivers/isdn/hisax/l3_1tr6.c	Wed Jan 26 23:08:44 2000
@@ -1,4 +1,4 @@
-/* $Id: l3_1tr6.c,v 2.9 1999/07/01 08:11:55 keil Exp $
+/* $Id: l3_1tr6.c,v 2.10 2000/01/20 19:42:01 keil Exp $
 
  *  German 1TR6 D-channel protocol
  *
@@ -10,6 +10,9 @@
  *
  *
  * $Log: l3_1tr6.c,v $
+ * Revision 2.10  2000/01/20 19:42:01  keil
+ * Fixed uninitialiesed location
+ *
  * Revision 2.9  1999/07/01 08:11:55  keil
  * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
  *
@@ -59,7 +62,7 @@
 #include <linux/ctype.h>
 
 extern char *HiSax_getrev(const char *revision);
-const char *l3_1tr6_revision = "$Revision: 2.9 $";
+const char *l3_1tr6_revision = "$Revision: 2.10 $";
 
 #define MsgHead(ptr, cref, mty, dis) \
 	*ptr++ = dis; \
@@ -699,6 +702,7 @@
 {
         newl3state(pc, 0);
         pc->para.cause = 0x1b;          /* Destination out of order */
+        pc->para.loc = 0;
         pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
         release_l3_process(pc);
 }
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/isdn/hisax/l3dss1.c linux.15p9/drivers/isdn/hisax/l3dss1.c
--- linux.vanilla/drivers/isdn/hisax/l3dss1.c	Tue Jan  4 21:18:47 2000
+++ linux.15p9/drivers/isdn/hisax/l3dss1.c	Wed Jan 26 23:08:44 2000
@@ -1,4 +1,4 @@
-/* $Id: l3dss1.c,v 2.21 1999/12/19 20:25:17 keil Exp $
+/* $Id: l3dss1.c,v 2.22 2000/01/20 19:44:20 keil Exp $
 
  * EURO/DSS1 D-channel protocol
  *
@@ -13,6 +13,12 @@
  *              Fritz Elfert
  *
  * $Log: l3dss1.c,v $
+ * Revision 2.22  2000/01/20 19:44:20  keil
+ * Fixed uninitialiesed location
+ * Fixed redirecting number IE in Setup
+ * Changes from certification
+ * option for disabling use of KEYPAD protocol
+ *
  * Revision 2.21  1999/12/19 20:25:17  keil
  * fixed LLC for outgoing analog calls
  * IE Signal is valid on older local switches
@@ -95,9 +101,10 @@
 #include "isdnl3.h"
 #include "l3dss1.h"
 #include <linux/ctype.h>
+#include <linux/config.h>
 
 extern char *HiSax_getrev(const char *revision);
-const char *dss1_revision = "$Revision: 2.21 $";
+const char *dss1_revision = "$Revision: 2.22 $";
 
 #define EXT_BEARER_CAPS 1
 
@@ -698,8 +705,8 @@
 static int ie_SETUP[] = {IE_COMPLETE, IE_BEARER  | IE_MANDATORY,
 		IE_CHANNEL_ID| IE_MANDATORY, IE_FACILITY, IE_PROGRESS,
 		IE_NET_FAC, IE_DISPLAY, IE_KEYPAD, IE_SIGNAL, IE_CALLING_PN,
-		IE_CALLING_SUB, IE_CALLED_PN, IE_CALLED_SUB, IE_LLC, IE_HLC,
-		IE_USER_USER, -1};
+		IE_CALLING_SUB, IE_CALLED_PN, IE_CALLED_SUB, IE_REDIR_NR,
+		IE_LLC, IE_HLC, IE_USER_USER, -1};
 static int ie_SETUP_ACKNOWLEDGE[] = {IE_CHANNEL_ID | IE_MANDATORY, IE_FACILITY,
 		IE_PROGRESS, IE_DISPLAY, IE_SIGNAL, -1};
 static int ie_STATUS[] = {IE_CAUSE | IE_MANDATORY, IE_CALL_STATE |
@@ -1278,6 +1285,7 @@
 	u_char tmp[128];
 	u_char *p = tmp;
 	u_char channel = 0;
+
         u_char send_keypad;
 	u_char screen = 0x80;
 	u_char *teln;
@@ -1289,14 +1297,18 @@
 	MsgHead(p, pc->callref, MT_SETUP);
 
 	teln = pc->para.setup.phone;
+#ifndef CONFIG_HISAX_NO_KEYPAD
         send_keypad = (strchr(teln,'*') || strchr(teln,'#')) ? 1 : 0; 
+#else
+	send_keypad = 0;
+#endif
+#ifndef CONFIG_HISAX_NO_SENDCOMPLETE
+	if (!send_keypad)
+		*p++ = 0xa1;		/* complete indicator */
+#endif
 	/*
 	 * Set Bearer Capability, Map info from 1TR6-convention to EDSS1
 	 */
-#if HISAX_EURO_SENDCOMPLETE
-	if (!send_keypad)
-	  *p++ = 0xa1;		/* complete indicator */
-#endif
         if (!send_keypad)
 	  switch (pc->para.setup.si1) {
 		case 1:	/* Telephony                               */
@@ -1458,7 +1470,7 @@
 		*p++ = 0x90;
 		*p++ = 0x21;
 		p = EncodeASyncParams(p, pc->para.setup.si2 - 192);
-#if HISAX_SEND_STD_LLC_IE
+#ifndef CONFIG_HISAX_NO_LLC
 	} else {
 	  switch (pc->para.setup.si1) {
 		case 1:	/* Telephony                               */
@@ -2757,6 +2769,7 @@
 l3dss1_dl_reset(struct l3_process *pc, u_char pr, void *arg)
 {
         pc->para.cause = 0x29;          /* Temporary failure */
+        pc->para.loc = 0;
         l3dss1_disconnect_req(pc, pr, NULL);
         pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
 }
@@ -2766,6 +2779,7 @@
 {
         newl3state(pc, 0);
         pc->para.cause = 0x1b;          /* Destination out of order */
+        pc->para.loc = 0;
         pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
         release_l3_process(pc);
 }
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/isdn/hisax/l3dss1.h linux.15p9/drivers/isdn/hisax/l3dss1.h
--- linux.vanilla/drivers/isdn/hisax/l3dss1.h	Sat Aug 14 02:27:26 1999
+++ linux.15p9/drivers/isdn/hisax/l3dss1.h	Wed Jan 26 23:08:44 2000
@@ -1,8 +1,11 @@
-/* $Id: l3dss1.h,v 1.7 1999/07/01 08:12:02 keil Exp $
+/* $Id: l3dss1.h,v 1.8 2000/01/20 19:46:15 keil Exp $
  *
  *  DSS1 (Euro) D-channel protocol defines
  *
  * $Log: l3dss1.h,v $
+ * Revision 1.8  2000/01/20 19:46:15  keil
+ * Changes from certification
+ *
  * Revision 1.7  1999/07/01 08:12:02  keil
  * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
  *
@@ -35,6 +38,8 @@
 #define T304	30000
 #define T305	30000
 #define T308	4000
+/* for layer 1 certification T309 < layer1 T3 (e.g. 4000) */
+/* This makes some tests easier and quicker */
 #define T309	40000
 #define T310	30000
 #define T313	4000
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/isdn/hisax/md5sums.asc linux.15p9/drivers/isdn/hisax/md5sums.asc
--- linux.vanilla/drivers/isdn/hisax/md5sums.asc	Tue Jan  4 21:18:47 2000
+++ linux.15p9/drivers/isdn/hisax/md5sums.asc	Wed Jan 26 23:08:44 2000
@@ -7,14 +7,14 @@
 # Read ../../../Documentation/isdn/HiSax.cert for more informations.
 # 
 3c2b1c96274cba97a8261d1cecc662b8  isac.c
-a9a15d069dbacb383cc24c238cb5ebbe  isdnl1.c
+dd3955847bbf680b41233478fe521d88  isdnl1.c
 bb51bd223040b511c18f091da5ab6456  isdnl2.c
 b7aa7f97b2374967a4aca7c52991142c  isdnl3.c
 a23fbf8879c1432b04640b8b04bdf419  tei.c
 ce248e56c2e1326012d0b25f92bbf99b  callc.c
 bf9605b36429898f7be6630034e83230  cert.c
-2dbd5fadc33657c654f71385ff84127a  l3dss1.c
-2d748ced0eea375b21fe7ea91ca7917c  l3_1tr6.c
+233960fa9fc46aaffcaa883b5b59cf4e  l3dss1.c
+a3a570781f828b6d59e6b231653133de  l3_1tr6.c
 8188deeb4a1b34c574cd51638cd214d0  elsa.c
 a3c2b8e9d2c623658888b5f1d4317c2a  diva.c
 # end of md5sums
@@ -23,9 +23,9 @@
 Version: 2.6.3i
 Charset: noconv
 
-iQCVAwUBOGUfJzpxHvX/mS9tAQFpwwP/UFR+IP3URpDrRPJgWdzaP+Ho/nu4uOQM
-+l2d0MNZlBPIPiRJnP921mcSXUw37OsuXf8cfqihuCgc+2+ExNZe9s9o/Wz5TttA
-L1fhoP85OXy6m5Ap77Feh1tzxAQodRwIzzFvrXqUUN82JW32Q931dJzxVbYtgP16
-SkErM8N2GbM=
-=QeLI
+iQCVAwUBOIdqVzpxHvX/mS9tAQGaWQP+Pj0oVxbhusXnlNOQ+FV6YOGj1HGMXPsO
+C/9555qSbvcKg64OO8VdU1LWq/RCsAwBkJ3eSizF5LbWD8lhCHUpkNlzEv4fIaHe
+fAA9zLnC8Vk4h/YLwUNfZxezYvf22NGSydXGZH4VvLAigF0OGRlKaewsR61KZ/Fh
+4GnVqcxYaH8=
+=eINS
 -----END PGP SIGNATURE-----
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/isdn/hisax/sedlbauer.c linux.15p9/drivers/isdn/hisax/sedlbauer.c
--- linux.vanilla/drivers/isdn/hisax/sedlbauer.c	Tue Jan  4 21:18:47 2000
+++ linux.15p9/drivers/isdn/hisax/sedlbauer.c	Wed Jan 26 23:08:44 2000
@@ -1,4 +1,4 @@
-/* $Id: sedlbauer.c,v 1.19 1999/12/19 13:09:42 keil Exp $
+/* $Id: sedlbauer.c,v 1.20 2000/01/20 19:47:45 keil Exp $
 
  * sedlbauer.c  low level stuff for Sedlbauer cards
  *              includes support for the Sedlbauer speed star (speed star II),
@@ -17,6 +17,9 @@
  *            Edgar Toernig
  *
  * $Log: sedlbauer.c,v $
+ * Revision 1.20  2000/01/20 19:47:45  keil
+ * Add Fax Class 1 support
+ *
  * Revision 1.19  1999/12/19 13:09:42  keil
  * changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for
  * signal proof delays
@@ -114,7 +117,7 @@
 
 extern const char *CardType[];
 
-const char *Sedlbauer_revision = "$Revision: 1.19 $";
+const char *Sedlbauer_revision = "$Revision: 1.20 $";
 
 const char *Sedlbauer_Types[] =
 	{"None", "speed card/win", "speed star", "speed fax+", 
@@ -663,15 +666,13 @@
 			(sub_id == PCI_SUB_ID_SPEEDFAXP)) {
 			cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
 			cs->subtyp = SEDL_SPEEDFAX_PCI;
-			cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg +
-						SEDL_ISAR_PCI_ISAR_RESET_ON;
-			cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg +
-						SEDL_ISAR_PCI_ISAR_RESET_OFF;
 		} else {
 			cs->hw.sedl.chip = SEDL_CHIP_IPAC;
 			cs->subtyp = SEDL_SPEED_PCI;
 		}
 		bytecnt = 256;
+		cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON;
+		cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF;
 		byteout(cs->hw.sedl.cfg_reg, 0xff);
 		byteout(cs->hw.sedl.cfg_reg, 0x00);
 		byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/isdn/isdn_common.c linux.15p9/drivers/isdn/isdn_common.c
--- linux.vanilla/drivers/isdn/isdn_common.c	Tue Jan  4 21:18:48 2000
+++ linux.15p9/drivers/isdn/isdn_common.c	Wed Jan 26 23:08:44 2000
@@ -1,4 +1,4 @@
-/* $Id: isdn_common.c,v 1.93 1999/11/04 13:11:36 keil Exp $
+/* $Id: isdn_common.c,v 1.97 2000/01/23 18:45:37 keil Exp $
 
  * Linux ISDN subsystem, common used functions (linklevel).
  *
@@ -21,6 +21,32 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_common.c,v $
+ * Revision 1.97  2000/01/23 18:45:37  keil
+ * Change EAZ mapping to forbit the use of cards (insert a "-" for the MSN)
+ *
+ * Revision 1.96  2000/01/20 19:55:33  keil
+ * Add FAX Class 1 support
+ *
+ * Revision 1.95  2000/01/09 20:43:13  detabc
+ * exand logical bind-group's for both call's (in and out).
+ * add first part of kernel-config-help for abc-extension.
+ *
+ * Revision 1.94  1999/11/20 22:14:13  detabc
+ * added channel dial-skip in case of external use
+ * (isdn phone or another isdn device) on the same NTBA.
+ * usefull with two or more card's connected the different NTBA's.
+ * global switchable in kernel-config and also per netinterface.
+ *
+ * add auto disable of netinterface's in case of:
+ * 	to many connection's in short time.
+ * 	config mistakes (wrong encapsulation, B2-protokoll or so on) on local
+ * 	or remote side.
+ * 	wrong password's or something else to a ISP (syncppp).
+ *
+ * possible encapsulations for this future are:
+ * ISDN_NET_ENCAP_SYNCPPP, ISDN_NET_ENCAP_UIHDLC, ISDN_NET_ENCAP_RAWIP,
+ * and ISDN_NET_ENCAP_CISCOHDLCK.
+ *
  * Revision 1.93  1999/11/04 13:11:36  keil
  * Reinit of v110 structs
  *
@@ -416,7 +442,7 @@
 
 isdn_dev *dev = (isdn_dev *) 0;
 
-static char *isdn_revision = "$Revision: 1.93 $";
+static char *isdn_revision = "$Revision: 1.97 $";
 
 extern char *isdn_net_revision;
 extern char *isdn_tty_revision;
@@ -438,6 +464,7 @@
 
 
 static int isdn_writebuf_stub(int, int, const u_char *, int, int);
+static void set_global_features(void);
 
 void
 isdn_MOD_INC_USE_COUNT(void)
@@ -720,29 +747,33 @@
 int
 isdn_command(isdn_ctrl *cmd)
 {
+	if (cmd->driver == -1) {
+		printk(KERN_WARNING "isdn_command command(%x) driver -1\n", cmd->command);
+		return(1);
+	}
 	if (cmd->command == ISDN_CMD_SETL2) {
-			int idx = isdn_dc2minor(cmd->driver, cmd->arg & 255);
-			unsigned long l2prot = (cmd->arg >> 8) & 255;
-			unsigned long features = (dev->drv[cmd->driver]->interface->features
-						 >> ISDN_FEATURE_L2_SHIFT) &
-				ISDN_FEATURE_L2_MASK;
-			unsigned long l2_feature = (1 << l2prot);
-
-			switch (l2prot) {
-				case ISDN_PROTO_L2_V11096:
-				case ISDN_PROTO_L2_V11019:
-				case ISDN_PROTO_L2_V11038:
-						/* If V.110 requested, but not supported by
-						 * HL-driver, set emulator-flag and change
-						 * Layer-2 to transparent
-						 */
-					if (!(features & l2_feature)) {
-						dev->v110emu[idx] = l2prot;
-						cmd->arg = (cmd->arg & 255) |
-								   (ISDN_PROTO_L2_TRANS << 8);
-					} else
-						dev->v110emu[idx] = 0;
-			}
+		int idx = isdn_dc2minor(cmd->driver, cmd->arg & 255);
+		unsigned long l2prot = (cmd->arg >> 8) & 255;
+		unsigned long features = (dev->drv[cmd->driver]->interface->features
+						>> ISDN_FEATURE_L2_SHIFT) &
+						ISDN_FEATURE_L2_MASK;
+		unsigned long l2_feature = (1 << l2prot);
+
+		switch (l2prot) {
+			case ISDN_PROTO_L2_V11096:
+			case ISDN_PROTO_L2_V11019:
+			case ISDN_PROTO_L2_V11038:
+			/* If V.110 requested, but not supported by
+			 * HL-driver, set emulator-flag and change
+			 * Layer-2 to transparent
+			 */
+				if (!(features & l2_feature)) {
+					dev->v110emu[idx] = l2prot;
+					cmd->arg = (cmd->arg & 255) |
+						(ISDN_PROTO_L2_TRANS << 8);
+				} else
+					dev->v110emu[idx] = 0;
+		}
 	}
 	return dev->drv[cmd->driver]->interface->command(cmd);
 }
@@ -822,6 +853,7 @@
 			for (i = 0; i < ISDN_MAX_CHANNELS; i++)
 				if (dev->drvmap[i] == di)
 					isdn_all_eaz(di, dev->chanmap[i]);
+			set_global_features();
 			break;
 		case ISDN_STAT_STOP:
 			dev->drv[di]->flags &= ~DRV_FLAG_RUNNING;
@@ -1079,6 +1111,7 @@
 			dev->drv[di] = NULL;
 			dev->drvid[di][0] = '\0';
 			isdn_info_update();
+			set_global_features();
 			restore_flags(flags);
 			return 0;
 		case ISDN_STAT_L1ERR:
@@ -1564,6 +1597,9 @@
  * are serialized by means of a semaphore.
  */
 		switch (cmd) {
+			case IIOCNETDWRSET:
+				printk(KERN_INFO "INFO: ISDN_DW_ABC_EXTENSION not enabled\n");
+				return(-EINVAL);
 			case IIOCNETLCR:
 				printk(KERN_INFO "INFO: ISDN_ABC_LCR_SUPPORT not enabled\n");
 				return -ENODEV;
@@ -1855,7 +1891,7 @@
 						for (i = 0; i < 10; i++) {
 							sprintf(bname, "%s%s",
 								strlen(dev->drv[drvidx]->msn2eaz[i]) ?
-								dev->drv[drvidx]->msn2eaz[i] : "-",
+								dev->drv[drvidx]->msn2eaz[i] : "_",
 								(i < 9) ? "," : "\0");
 							if (copy_to_user(p, bname, strlen(bname) + 1))
 								return -EFAULT;
@@ -2061,7 +2097,7 @@
 
 int
 isdn_get_free_channel(int usage, int l2_proto, int l3_proto, int pre_dev
-		      ,int pre_chan)
+		      ,int pre_chan, char *msn)
 {
 	int i;
 	ulong flags;
@@ -2084,6 +2120,8 @@
 			if ((dev->usage[i] & ISDN_USAGE_EXCLUSIVE) &&
 			((pre_dev != d) || (pre_chan != dev->chanmap[i])))
 				continue;
+			if (!strcmp(isdn_map_eaz2msn(msn, d), "-"))
+				continue;
 			if (dev->usage[i] & ISDN_USAGE_DISABLED)
 			        continue; /* usage not allowed */
 			if (dev->drv[d]->flags & DRV_FLAG_RUNNING) {
@@ -2374,6 +2412,19 @@
  * Low-level-driver registration
  */
 
+static void
+set_global_features(void)
+{
+	int drvidx;
+
+	dev->global_features = 0;
+	for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++) {
+		if (!dev->drv[drvidx])
+			continue;
+		if (dev->drv[drvidx]->interface)
+			dev->global_features |= dev->drv[drvidx]->interface->features;
+	}
+}
 
 #ifdef CONFIG_ISDN_DIVERSION
 extern isdn_divert_if *divert_if;
@@ -2487,6 +2538,7 @@
 	strcpy(dev->drvid[drvidx], i->id);
 	isdn_info_update();
 	dev->drivers++;
+	set_global_features();
 	restore_flags(flags);
 	return 1;
 }
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/isdn/isdn_common.h linux.15p9/drivers/isdn/isdn_common.h
--- linux.vanilla/drivers/isdn/isdn_common.h	Tue Jan  4 21:18:49 2000
+++ linux.15p9/drivers/isdn/isdn_common.h	Wed Jan 26 23:08:44 2000
@@ -1,4 +1,4 @@
-/* $Id: isdn_common.h,v 1.17 1999/10/27 21:21:17 detabc Exp $
+/* $Id: isdn_common.h,v 1.18 2000/01/23 18:45:37 keil Exp $
 
  * header for Linux ISDN subsystem, common used functions and debugging-switches (linklevel).
  *
@@ -21,6 +21,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_common.h,v $
+ * Revision 1.18  2000/01/23 18:45:37  keil
+ * Change EAZ mapping to forbit the use of cards (insert a "-" for the MSN)
+ *
  * Revision 1.17  1999/10/27 21:21:17  detabc
  * Added support for building logically-bind-group's per interface.
  * usefull for outgoing call's with more then one isdn-card.
@@ -128,7 +131,7 @@
 extern void isdn_unexclusive_channel(int di, int ch);
 extern int isdn_getnum(char **);
 extern int isdn_readbchan(int, int, u_char *, u_char *, int, struct wait_queue**);
-extern int isdn_get_free_channel(int, int, int, int, int);
+extern int isdn_get_free_channel(int, int, int, int, int, char *);
 extern int isdn_writebuf_skb_stub(int, int, int, struct sk_buff *);
 extern int register_isdn(isdn_if * i);
 extern int isdn_wildmat(char *, char *);
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/isdn/isdn_net.c linux.15p9/drivers/isdn/isdn_net.c
--- linux.vanilla/drivers/isdn/isdn_net.c	Tue Jan  4 21:18:50 2000
+++ linux.15p9/drivers/isdn/isdn_net.c	Wed Jan 26 23:08:44 2000
@@ -1,4 +1,4 @@
-/* $Id: isdn_net.c,v 1.95 1999/10/27 21:21:17 detabc Exp $
+/* $Id: isdn_net.c,v 1.103 2000/01/23 18:45:37 keil Exp $
 
  * Linux ISDN subsystem, network interfaces and related functions (linklevel).
  *
@@ -21,6 +21,46 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_net.c,v $
+ * Revision 1.103  2000/01/23 18:45:37  keil
+ * Change EAZ mapping to forbit the use of cards (insert a "-" for the MSN)
+ *
+ * Revision 1.102  2000/01/09 20:43:14  detabc
+ * exand logical bind-group's for both call's (in and out).
+ * add first part of kernel-config-help for abc-extension.
+ *
+ * Revision 1.101  1999/12/05 16:06:08  detabc
+ * add resethandling for rawip-compression.
+ * at now all B2-Protocols are usable with rawip-compression
+ *
+ * Revision 1.100  1999/12/04 15:05:25  detabc
+ * bugfix abc-rawip-bsdcompress with channel-bundeling
+ *
+ * Revision 1.99  1999/11/30 11:29:06  detabc
+ * add a on the fly frame-counter and limit
+ *
+ * Revision 1.98  1999/11/28 14:49:07  detabc
+ * In case of rawip-compress adjust dev[x]->ibytes/obytes to reflect the
+ * uncompressed size.
+ *
+ * Revision 1.97  1999/11/26 15:54:59  detabc
+ * added compression (isdn_bsdcompress) for rawip interfaces with x75i B2-protocol.
+ *
+ * Revision 1.96  1999/11/20 22:14:13  detabc
+ * added channel dial-skip in case of external use
+ * (isdn phone or another isdn device) on the same NTBA.
+ * usefull with two or more card's connected the different NTBA's.
+ * global switchable in kernel-config and also per netinterface.
+ *
+ * add auto disable of netinterface's in case of:
+ * 	to many connection's in short time.
+ * 	config mistakes (wrong encapsulation, B2-protokoll or so on) on local
+ * 	or remote side.
+ * 	wrong password's or something else to a ISP (syncppp).
+ *
+ * possible encapsulations for this future are:
+ * ISDN_NET_ENCAP_SYNCPPP, ISDN_NET_ENCAP_UIHDLC, ISDN_NET_ENCAP_RAWIP,
+ * and ISDN_NET_ENCAP_CISCOHDLCK.
+ *
  * Revision 1.95  1999/10/27 21:21:17  detabc
  * Added support for building logically-bind-group's per interface.
  * usefull for outgoing call's with more then one isdn-card.
@@ -443,7 +483,7 @@
 static int isdn_net_start_xmit(struct sk_buff *, struct device *);
 static int isdn_net_xmit(struct device *, isdn_net_local *, struct sk_buff *);
 
-char *isdn_net_revision = "$Revision: 1.95 $";
+char *isdn_net_revision = "$Revision: 1.103 $";
 
  /*
   * Code for raw-networking over ISDN
@@ -1259,14 +1299,16 @@
 					strcpy(addinfo, " IDP");
 					break;
 			}
-			printk(KERN_INFO "OPEN: %d.%d.%d.%d -> %d.%d.%d.%d%s\n",
+			printk(KERN_INFO
+				"OPEN: %d.%d.%d.%d -> %d.%d.%d.%d%s\n",
 
 			       p[12], p[13], p[14], p[15],
 			       p[16], p[17], p[18], p[19],
 			       addinfo);
 			break;
 		case ETH_P_ARP:
-			printk(KERN_INFO "OPEN: ARP %d.%d.%d.%d -> *.*.*.* ?%d.%d.%d.%d\n",
+			printk(KERN_INFO
+				"OPEN: ARP %d.%d.%d.%d -> *.*.*.* ?%d.%d.%d.%d\n",
 			       p[14], p[15], p[16], p[17],
 			       p[24], p[25], p[26], p[27]);
 			break;
@@ -1286,8 +1328,8 @@
  */
 #endif
 int
-isdn_net_send_skb(struct device *ndev, isdn_net_local * lp,
-		  struct sk_buff *skb)
+isdn_net_send_skb
+		(struct device *ndev, isdn_net_local * lp,struct sk_buff *skb)
 {
 	int ret;
 	int len = skb->len;     /* save len */
@@ -1484,7 +1526,6 @@
 					} else
 						lp->dialwait_timer = 0;
 				}
-
 				/* Grab a free ISDN-Channel */
 				if (((chi =
 				     isdn_get_free_channel(
@@ -1492,7 +1533,8 @@
 							lp->l2_proto,
 							lp->l3_proto,
 							lp->pre_device,
-						 	lp->pre_channel)
+						 	lp->pre_channel,
+							lp->msn)
 							) < 0) &&
 					((chi =
 				     isdn_get_free_channel(
@@ -1500,7 +1542,8 @@
 							lp->l2_proto,
 							lp->l3_proto,
 							lp->pre_device,
-						    lp->pre_channel^1)
+							lp->pre_channel^1,
+							lp->msn)
 							) < 0)) {
 					restore_flags(flags);
 					isdn_net_unreachable(ndev, skb,
@@ -2389,7 +2432,7 @@
 						p = (isdn_net_dev *) p->next;
 						continue;
 					}
-				}
+				} 
 				if (lp->flags & ISDN_NET_CALLBACK) {
 					int chi;
 					/*
@@ -2411,9 +2454,10 @@
 							isdn_get_free_channel(
 								ISDN_USAGE_NET,
 								lp->l2_proto,
-							    lp->l3_proto,
+								lp->l3_proto,
 							  	lp->pre_device,
-						 		lp->pre_channel)
+						 		lp->pre_channel,
+						 		lp->msn)
 								) < 0) {
 
 							printk(KERN_WARNING "isdn_net_find_icall: No channel for %s\n", lp->name);
@@ -2528,7 +2572,8 @@
 							lp->l2_proto,
 							lp->l3_proto,
 							lp->pre_device,
-						 	lp->pre_channel)
+						 	lp->pre_channel,
+							lp->msn)
 							) < 0) {
 				printk(KERN_WARNING "isdn_net_force_dial: No channel for %s\n", lp->name);
 				restore_flags(flags);
@@ -2837,10 +2882,9 @@
 
 			/* If binding is exclusive, try to grab the channel */
 			save_flags(flags);
-			if ((i = isdn_get_free_channel(ISDN_USAGE_NET, lp->l2_proto,
-						       lp->l3_proto,
-						       drvidx,
-						       chidx)) < 0) {
+			if ((i = isdn_get_free_channel(ISDN_USAGE_NET,
+				lp->l2_proto, lp->l3_proto, drvidx,
+				chidx, lp->msn)) < 0) {
 				/* Grab failed, because desired channel is in use */
 				lp->exclusive = -1;
 				restore_flags(flags);
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/isdn/isdn_ppp.c linux.15p9/drivers/isdn/isdn_ppp.c
--- linux.vanilla/drivers/isdn/isdn_ppp.c	Tue Jan  4 21:18:50 2000
+++ linux.15p9/drivers/isdn/isdn_ppp.c	Wed Jan 26 23:08:44 2000
@@ -1,4 +1,4 @@
-/* $Id: isdn_ppp.c,v 1.60 1999/11/04 20:29:55 he Exp $
+/* $Id: isdn_ppp.c,v 1.61 1999/11/20 22:14:14 detabc Exp $
  *
  * Linux ISDN subsystem, functions for synchronous PPP (linklevel).
  *
@@ -19,6 +19,22 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_ppp.c,v $
+ * Revision 1.61  1999/11/20 22:14:14  detabc
+ * added channel dial-skip in case of external use
+ * (isdn phone or another isdn device) on the same NTBA.
+ * usefull with two or more card's connected the different NTBA's.
+ * global switchable in kernel-config and also per netinterface.
+ *
+ * add auto disable of netinterface's in case of:
+ * 	to many connection's in short time.
+ * 	config mistakes (wrong encapsulation, B2-protokoll or so on) on local
+ * 	or remote side.
+ * 	wrong password's or something else to a ISP (syncppp).
+ *
+ * possible encapsulations for this future are:
+ * ISDN_NET_ENCAP_SYNCPPP, ISDN_NET_ENCAP_UIHDLC, ISDN_NET_ENCAP_RAWIP,
+ * and ISDN_NET_ENCAP_CISCOHDLCK.
+ *
  * Revision 1.60  1999/11/04 20:29:55  he
  * applied Andre Beck's reset_free fix
  *
@@ -306,7 +322,7 @@
 static void isdn_ppp_free_mpqueue(isdn_net_dev *);
 #endif
 
-char *isdn_ppp_revision = "$Revision: 1.60 $";
+char *isdn_ppp_revision = "$Revision: 1.61 $";
 
 static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/isdn/isdn_tty.c linux.15p9/drivers/isdn/isdn_tty.c
--- linux.vanilla/drivers/isdn/isdn_tty.c	Tue Jan  4 21:18:50 2000
+++ linux.15p9/drivers/isdn/isdn_tty.c	Wed Jan 26 23:11:36 2000
@@ -1,4 +1,4 @@
-/* $Id: isdn_tty.c,v 1.80 1999/11/07 13:34:30 armin Exp $
+/* $Id: isdn_tty.c,v 1.82 2000/01/23 18:45:37 keil Exp $
 
  * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel).
  *
@@ -20,6 +20,12 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_tty.c,v $
+ * Revision 1.82  2000/01/23 18:45:37  keil
+ * Change EAZ mapping to forbit the use of cards (insert a "-" for the MSN)
+ *
+ * Revision 1.81  2000/01/20 19:55:33  keil
+ * Add FAX Class 1 support
+ *
  * Revision 1.80  1999/11/07 13:34:30  armin
  * Fixed AT command line editor
  *
@@ -348,6 +354,7 @@
 #endif
 
 #define FIX_FILE_TRANSFER
+#define	DUMMY_HAYES_AT
 
 /* Prototypes */
 
@@ -372,7 +379,7 @@
 static int si2bit[8] =
 {4, 1, 4, 4, 4, 4, 4, 4};
 
-char *isdn_tty_revision = "$Revision: 1.80 $";
+char *isdn_tty_revision = "$Revision: 1.82 $";
 
 
 /* isdn_tty_try_read() is called from within isdn_tty_rcv_skb()
@@ -976,7 +983,7 @@
 	m->mdmreg[REG_SI1I] = si2bit[si];
 	save_flags(flags);
 	cli();
-	i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1);
+	i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
 	if (i < 0) {
 		restore_flags(flags);
 		isdn_tty_modem_result(6, info);
@@ -1187,7 +1194,7 @@
 	m->mdmreg[REG_SI1I] = si2bit[si];
 	save_flags(flags);
 	cli();
-	i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1);
+	i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
 	if (i < 0) {
 		restore_flags(flags);
 		isdn_tty_modem_result(6, info);
@@ -1281,7 +1288,7 @@
 	m->mdmreg[REG_SI1I] = si2bit[si];
 	save_flags(flags);
 	cli();
-	i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1);
+	i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
 	if (i < 0) {
 		restore_flags(flags);
 		isdn_tty_modem_result(6, info);
@@ -1555,6 +1562,23 @@
 					}
 				}
 			} else
+			if (TTY_IS_FCLASS1(info)) {
+				int cc = isdn_tty_handleDLEdown(info, m, c);
+				
+				if (info->vonline & 4) { /* ETX seen */
+					isdn_ctrl c;
+
+					c.command = ISDN_CMD_FAXCMD;
+					c.driver = info->isdn_driver;
+					c.arg = info->isdn_channel;
+					c.parm.aux.cmd = ISDN_FAX_CLASS1_CTRL;
+					c.parm.aux.subcmd = ETX;
+					isdn_command(&c);
+				}
+				info->vonline = 0;
+				printk(KERN_DEBUG "fax dle cc/c %d/%d\n", cc,c);
+				info->xmit_count += cc;
+			} else
 #endif
 				info->xmit_count += c;
 		} else {
@@ -2568,7 +2592,7 @@
 	(info->flags & (ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE))
 
 int
-isdn_tty_stat_callback(int i, isdn_ctrl * c)
+isdn_tty_stat_callback(int i, isdn_ctrl *c)
 {
 	int mi;
 	modem_info *info;
@@ -2669,8 +2693,7 @@
 						if (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) {
 							strcpy(info->emu.connmsg, c->parm.num);
 							isdn_tty_modem_result(1, info);
-						}
-						else
+						} else
 							isdn_tty_modem_result(5, info);
 					}
 					if (USG_VOICE(dev->usage[i]))
@@ -2721,7 +2744,7 @@
 #ifdef CONFIG_ISDN_TTY_FAX
 			case ISDN_STAT_FAXIND:
 				if (TTY_IS_ACTIVE(info)) {
-					isdn_tty_fax_command(info); 
+					isdn_tty_fax_command(info, c); 
 				}
 				break;
 #endif
@@ -3248,8 +3271,22 @@
 					info->xmit_size /= 10;		
 			}
 			break;
+		case 'C':
+			/* &C - DCD Status */
+			p[0]++;
+			switch (isdn_getnum(p)) {
+				case 0:
+					m->mdmreg[REG_DCD] &= ~BIT_DCD;
+					break;
+				case 1:
+					m->mdmreg[REG_DCD] |= BIT_DCD;
+					break;
+				default:
+					PARSE_ERROR1
+			}
+			break;
 		case 'D':
-			/* &D - Set DCD-Low-behavior */
+			/* &D - Set DTR-Low-behavior */
 			p[0]++;
 			switch (isdn_getnum(p)) {
 				case 0:
@@ -3281,6 +3318,14 @@
 			isdn_tty_reset_profile(m);
 			isdn_tty_modem_reset_regs(info, 1);
 			break;
+#ifdef DUMMY_HAYES_AT
+		case 'K':
+			/* only for be compilant with common scripts */
+			/* &K Flowcontrol - no function */
+			p[0]++;
+			isdn_getnum(p);
+			break;
+#endif
 		case 'L':
 			/* &L -Set Numbers to listen on */
 			p[0]++;
@@ -3566,8 +3611,10 @@
 				sprintf(rs, "\r\n%d",
 					(m->mdmreg[REG_SI1] & 1) ? 8 : 0);
 #ifdef CONFIG_ISDN_TTY_FAX
-				if (m->mdmreg[REG_L2PROT] == ISDN_PROTO_L2_FAX)
-				sprintf(rs, "\r\n2");
+				if (TTY_IS_FCLASS2(info))
+						sprintf(rs, "\r\n2");
+				else if (TTY_IS_FCLASS1(info))
+						sprintf(rs, "\r\n1");
 #endif
 				isdn_tty_at_cout(rs, info);
 				break;
@@ -3583,11 +3630,25 @@
 						    m->mdmreg[REG_PSIZE] * 16;
 						break;
 #ifdef CONFIG_ISDN_TTY_FAX
+					case '1':
+						p[0]++;
+						if (!(dev->global_features &
+							ISDN_FEATURE_L3_FCLASS1))
+							PARSE_ERROR1;
+						m->mdmreg[REG_SI1] = 1;
+						m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_FAX;
+						m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_FCLASS1;
+						info->xmit_size =
+						    m->mdmreg[REG_PSIZE] * 16;
+						break;
 					case '2':
 						p[0]++;
+						if (!(dev->global_features &
+							ISDN_FEATURE_L3_FCLASS2))
+							PARSE_ERROR1;
 						m->mdmreg[REG_SI1] = 1;
 						m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_FAX;
-						m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_FAX;
+						m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_FCLASS2;
 						info->xmit_size =
 						    m->mdmreg[REG_PSIZE] * 16;
 						break;
@@ -3602,11 +3663,17 @@
 						break;
 					case '?':
 						p[0]++;
+						strcpy(rs, "\r\n0,");
 #ifdef CONFIG_ISDN_TTY_FAX
-						isdn_tty_at_cout("\r\n0,2,8", info);
-#else
-						isdn_tty_at_cout("\r\n0,8", info);
+						if (dev->global_features &
+							ISDN_FEATURE_L3_FCLASS1)
+							strcat(rs, "1,");
+						if (dev->global_features &
+							ISDN_FEATURE_L3_FCLASS2)
+							strcat(rs, "2,");
 #endif
+						strcat(rs, "8");
+						isdn_tty_at_cout(rs, info);
 						break;
 					default:
 						PARSE_ERROR1;
@@ -3996,6 +4063,15 @@
 					default:
 				}
 				break;
+#ifdef DUMMY_HAYES_AT
+			case 'L':
+			case 'M':
+				/* only for be compilant with common scripts */
+				/* no function */
+				p++;
+				isdn_getnum(&p);
+				break;
+#endif
 			case 'O':
 				/* O - Go online */
 				p++;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/isdn/isdn_tty.h linux.15p9/drivers/isdn/isdn_tty.h
--- linux.vanilla/drivers/isdn/isdn_tty.h	Wed Oct 20 01:12:38 1999
+++ linux.15p9/drivers/isdn/isdn_tty.h	Wed Jan 26 23:11:36 2000
@@ -1,4 +1,4 @@
-/* $Id: isdn_tty.h,v 1.17 1999/09/21 19:00:35 armin Exp $
+/* $Id: isdn_tty.h,v 1.18 2000/01/20 19:55:33 keil Exp $
 
  * header for Linux ISDN subsystem, tty related functions (linklevel).
  *
@@ -20,6 +20,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_tty.h,v $
+ * Revision 1.18  2000/01/20 19:55:33  keil
+ * Add FAX Class 1 support
+ *
  * Revision 1.17  1999/09/21 19:00:35  armin
  * Extended FCON message with added CPN
  * can now be activated with Bit 1 of Reg 23.
@@ -160,6 +163,13 @@
 #define BIT_CPN       1
 #define BIT_CPNFCON   2
 
+#define TTY_IS_FCLASS1(info) \
+	((info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_FAX) && \
+	 (info->emu.mdmreg[REG_L3PROT] == ISDN_PROTO_L3_FCLASS1))
+#define TTY_IS_FCLASS2(info) \
+	((info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_FAX) && \
+	 (info->emu.mdmreg[REG_L3PROT] == ISDN_PROTO_L3_FCLASS2))
+
 extern void isdn_tty_modem_escape(void);
 extern void isdn_tty_modem_ring(void);
 extern void isdn_tty_carrier_timeout(void);
@@ -175,6 +185,6 @@
 extern void isdn_tty_modem_hup(modem_info *, int);
 #ifdef CONFIG_ISDN_TTY_FAX
 extern int isdn_tty_cmd_PLUSF_FAX(char **, modem_info *);
-extern int isdn_tty_fax_command(modem_info *);
+extern int isdn_tty_fax_command(modem_info *, isdn_ctrl *);
 extern void isdn_tty_fax_bitorder(modem_info *, struct sk_buff *);
 #endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/isdn/isdn_ttyfax.c linux.15p9/drivers/isdn/isdn_ttyfax.c
--- linux.vanilla/drivers/isdn/isdn_ttyfax.c	Wed Oct 20 01:12:38 1999
+++ linux.15p9/drivers/isdn/isdn_ttyfax.c	Wed Jan 26 23:11:36 2000
@@ -1,9 +1,9 @@
-/* $Id: isdn_ttyfax.c,v 1.4 1999/09/21 19:00:35 armin Exp $
+/* $Id: isdn_ttyfax.c,v 1.6 2000/01/26 00:41:13 keil Exp $
  * Linux ISDN subsystem, tty_fax AT-command emulator (linklevel).
  *
  * Copyright 1999    by Armin Schindler (mac@melware.de)
  * Copyright 1999    by Ralf Spachmann (mel@melware.de)
- * Copyright 1999    by Cytronics & Melware 
+ * Copyright 1999    by Cytronics & Melware
  *
  * 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
@@ -20,6 +20,12 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_ttyfax.c,v $
+ * Revision 1.6  2000/01/26 00:41:13  keil
+ * add "00" as dummy msn in isdn_get_free_channel call
+ *
+ * Revision 1.5  2000/01/20 19:55:33  keil
+ * Add FAX Class 1 support
+ *
  * Revision 1.4  1999/09/21 19:00:35  armin
  * Extended FCON message with added CPN
  * can now be activated with Bit 1 of Reg 23.
@@ -50,31 +56,32 @@
 #include "isdn_ttyfax.h"
 
 
-static char *isdn_tty_fax_revision = "$Revision: 1.4 $";
+static char *isdn_tty_fax_revision = "$Revision: 1.6 $";
 
 #define PARSE_ERROR1 { isdn_tty_fax_modem_result(1, info); return 1; }
 
 static char *
 isdn_getrev(const char *revision)
 {
-        char *rev;
-        char *p;
+	char *rev;
+	char *p;
 
-        if ((p = strchr(revision, ':'))) {
-                rev = p + 2;
-                p = strchr(rev, '$');
-                *--p = 0;
-        } else
-                rev = "???";
-        return rev;
+	if ((p = strchr(revision, ':'))) {
+		rev = p + 2;
+		p = strchr(rev, '$');
+		*--p = 0;
+	} else
+		rev = "???";
+	return rev;
 }
 
-
 /*
  * Fax Class 2 Modem results
  *
  */
-static void isdn_tty_fax_modem_result(int code, modem_info * info)
+
+static void
+isdn_tty_fax_modem_result(int code, modem_info * info)
 {
 	atemu *m = &info->emu;
 	T30_s *f = info->fax;
@@ -85,7 +92,7 @@
 	static char *msg[] =
 	{"OK", "ERROR", "+FCON", "+FCSI:", "+FDIS:",
 	 "+FHNG:", "+FDCS:", "CONNECT", "+FTSI:",
-	 "+FCFR", "+FPTS:", "+FET:" };
+	 "+FCFR", "+FPTS:", "+FET:"};
 
 
 	isdn_tty_at_cout("\r\n", info);
@@ -115,12 +122,12 @@
 		case 3:	/* +FCSI */
 		case 8:	/* +FTSI */
 			sprintf(rs, "\"%s\"", f->r_id);
-			isdn_tty_at_cout(rs, info); 
+			isdn_tty_at_cout(rs, info);
 			break;
 		case 4:	/* +FDIS */
 			rs[0] = 0;
 			rp = &f->r_resolution;
-			for(i = 0; i < 8; i++) {
+			for (i = 0; i < 8; i++) {
 				sprintf(rss, "%c%s", rp[i] + 48,
 					(i < 7) ? "," : "");
 				strcat(rs, rss);
@@ -128,18 +135,18 @@
 			isdn_tty_at_cout(rs, info);
 #ifdef ISDN_TTY_FAX_CMD_DEBUG
 			printk(KERN_DEBUG "isdn_tty: Fax DIS=%s on ttyI%d\n",
-				rs, info->line);
+			       rs, info->line);
 #endif
 			break;
 		case 5:	/* +FHNG */
 			sprintf(rs, "%d", f->code);
-			isdn_tty_at_cout(rs, info); 
+			isdn_tty_at_cout(rs, info);
 			info->faxonline = 0;
 			break;
 		case 6:	/* +FDCS */
 			rs[0] = 0;
 			rp = &f->r_resolution;
-			for(i = 0; i < 8; i++) {
+			for (i = 0; i < 8; i++) {
 				sprintf(rss, "%c%s", rp[i] + 48,
 					(i < 7) ? "," : "");
 				strcat(rs, rss);
@@ -147,127 +154,169 @@
 			isdn_tty_at_cout(rs, info);
 #ifdef ISDN_TTY_FAX_CMD_DEBUG
 			printk(KERN_DEBUG "isdn_tty: Fax DCS=%s on ttyI%d\n",
-				rs, info->line);
+			       rs, info->line);
 #endif
 			break;
 		case 7:	/* CONNECT */
 			info->faxonline |= 2;
 			break;
-		case 9: /* FCFR */
+		case 9:	/* FCFR */
 			break;
-		case 10: /* FPTS */
+		case 10:	/* FPTS */
 			isdn_tty_at_cout("1", info);
 			break;
-		case 11: /* FET */
+		case 11:	/* FET */
 			sprintf(rs, "%d", f->fet);
-			isdn_tty_at_cout(rs, info); 
+			isdn_tty_at_cout(rs, info);
 			break;
 	}
 
 	isdn_tty_at_cout("\r\n", info);
 
 	switch (code) {
-		case 7: /* CONNECT */
+		case 7:	/* CONNECT */
 			info->online = 2;
 			if (info->faxonline & 1) {
 				sprintf(rs, "%c", XON);
-				isdn_tty_at_cout(rs, info); 
+				isdn_tty_at_cout(rs, info);
 			}
 			break;
 	}
 }
 
 int
-isdn_tty_fax_command(modem_info * info)
+isdn_tty_fax_command1(modem_info * info, isdn_ctrl * c)
+{
+	static char *msg[] =
+	{"OK", "CONNECT", "NO CARRIER", "ERROR", "FCERROR"};
+
+#ifdef ISDN_TTY_FAX_CMD_DEBUG
+	printk(KERN_DEBUG "isdn_tty: FCLASS1 cmd(%d)\n", c->parm.aux.cmd);
+#endif
+	if (c->parm.aux.cmd < ISDN_FAX_CLASS1_QUERY) {
+		if (info->online)
+			info->online = 1;
+		isdn_tty_at_cout("\r\n", info);
+		isdn_tty_at_cout(msg[c->parm.aux.cmd], info);
+		isdn_tty_at_cout("\r\n", info);
+	}
+	switch (c->parm.aux.cmd) {
+		case ISDN_FAX_CLASS1_CONNECT:
+			info->online = 2;
+			break;
+		case ISDN_FAX_CLASS1_OK:
+		case ISDN_FAX_CLASS1_FCERROR:
+		case ISDN_FAX_CLASS1_ERROR:
+		case ISDN_FAX_CLASS1_NOCARR:
+			break;
+		case ISDN_FAX_CLASS1_QUERY:
+			isdn_tty_at_cout("\r\n", info);
+			if (!c->parm.aux.para[0]) {
+				isdn_tty_at_cout(msg[ISDN_FAX_CLASS1_ERROR], info);
+				isdn_tty_at_cout("\r\n", info);
+			} else {
+				isdn_tty_at_cout(c->parm.aux.para, info);
+				isdn_tty_at_cout("\r\nOK\r\n", info);
+			}
+			break;
+	}
+	return (0);
+}
+
+int
+isdn_tty_fax_command(modem_info * info, isdn_ctrl * c)
 {
 	T30_s *f = info->fax;
 	char rs[10];
 
+	if (TTY_IS_FCLASS1(info))
+		return (isdn_tty_fax_command1(info, c));
+
 #ifdef ISDN_TTY_FAX_CMD_DEBUG
 	printk(KERN_DEBUG "isdn_tty: Fax cmd %d on ttyI%d\n",
-		f->r_code, info->line);
+	       f->r_code, info->line);
 #endif
-	switch(f->r_code) {
+	switch (f->r_code) {
 		case ISDN_TTY_FAX_FCON:
 			info->faxonline = 1;
-			isdn_tty_fax_modem_result(2, info); /* +FCON */
-			return(0);
+			isdn_tty_fax_modem_result(2, info);	/* +FCON */
+			return (0);
 		case ISDN_TTY_FAX_FCON_I:
 			info->faxonline = 16;
-			isdn_tty_fax_modem_result(2, info); /* +FCON */
-			return(0);
+			isdn_tty_fax_modem_result(2, info);	/* +FCON */
+			return (0);
 		case ISDN_TTY_FAX_RID:
 			if (info->faxonline & 1)
-				isdn_tty_fax_modem_result(3, info); /* +FCSI */
+				isdn_tty_fax_modem_result(3, info);	/* +FCSI */
 			if (info->faxonline & 16)
-				isdn_tty_fax_modem_result(8, info); /* +FTSI */
-			return(0);
+				isdn_tty_fax_modem_result(8, info);	/* +FTSI */
+			return (0);
 		case ISDN_TTY_FAX_DIS:
-			isdn_tty_fax_modem_result(4, info); /* +FDIS */
-			return(0);
+			isdn_tty_fax_modem_result(4, info);	/* +FDIS */
+			return (0);
 		case ISDN_TTY_FAX_HNG:
 			if (f->phase == ISDN_FAX_PHASE_C) {
 				if (f->direction == ISDN_TTY_FAX_CONN_IN) {
 					sprintf(rs, "%c%c", DLE, ETX);
-					isdn_tty_at_cout(rs, info); 
+					isdn_tty_at_cout(rs, info);
 				} else {
 					sprintf(rs, "%c", 0x18);
-					isdn_tty_at_cout(rs, info); 
+					isdn_tty_at_cout(rs, info);
 				}
-				info->faxonline &= ~2; /* leave data mode */
+				info->faxonline &= ~2;	/* leave data mode */
 				info->online = 1;
 			}
 			f->phase = ISDN_FAX_PHASE_E;
-			isdn_tty_fax_modem_result(5, info); /* +FHNG */
-			isdn_tty_fax_modem_result(0, info); /* OK */
-			return(0);
+			isdn_tty_fax_modem_result(5, info);	/* +FHNG */
+			isdn_tty_fax_modem_result(0, info);	/* OK */
+			return (0);
 		case ISDN_TTY_FAX_DCS:
-			isdn_tty_fax_modem_result(6, info); /* +FDCS */
-			isdn_tty_fax_modem_result(7, info); /* CONNECT */
+			isdn_tty_fax_modem_result(6, info);	/* +FDCS */
+			isdn_tty_fax_modem_result(7, info);	/* CONNECT */
 			f->phase = ISDN_FAX_PHASE_C;
-			return(0);
+			return (0);
 		case ISDN_TTY_FAX_TRAIN_OK:
-			isdn_tty_fax_modem_result(6, info); /* +FDCS */
-			isdn_tty_fax_modem_result(0, info); /* OK */
-			return(0);
+			isdn_tty_fax_modem_result(6, info);	/* +FDCS */
+			isdn_tty_fax_modem_result(0, info);	/* OK */
+			return (0);
 		case ISDN_TTY_FAX_SENT:
-			isdn_tty_fax_modem_result(0, info); /* OK */
-			return(0);
+			isdn_tty_fax_modem_result(0, info);	/* OK */
+			return (0);
 		case ISDN_TTY_FAX_CFR:
-			isdn_tty_fax_modem_result(9, info); /* +FCFR */
-			return(0);
+			isdn_tty_fax_modem_result(9, info);	/* +FCFR */
+			return (0);
 		case ISDN_TTY_FAX_ET:
 			sprintf(rs, "%c%c", DLE, ETX);
-			isdn_tty_at_cout(rs, info); 
-			isdn_tty_fax_modem_result(10, info); /* +FPTS */
-			isdn_tty_fax_modem_result(11, info); /* +FET */
-			isdn_tty_fax_modem_result(0, info); /* OK */
-			info->faxonline &= ~2; /* leave data mode */
+			isdn_tty_at_cout(rs, info);
+			isdn_tty_fax_modem_result(10, info);	/* +FPTS */
+			isdn_tty_fax_modem_result(11, info);	/* +FET */
+			isdn_tty_fax_modem_result(0, info);	/* OK */
+			info->faxonline &= ~2;	/* leave data mode */
 			info->online = 1;
 			f->phase = ISDN_FAX_PHASE_D;
-			return(0);
+			return (0);
 		case ISDN_TTY_FAX_PTS:
-			isdn_tty_fax_modem_result(10, info); /* +FPTS */
+			isdn_tty_fax_modem_result(10, info);	/* +FPTS */
 			if (f->direction == ISDN_TTY_FAX_CONN_OUT) {
 				if (f->fet == 1)
 					f->phase = ISDN_FAX_PHASE_B;
 				if (f->fet == 0)
-					isdn_tty_fax_modem_result(0, info); /* OK */
+					isdn_tty_fax_modem_result(0, info);	/* OK */
 			}
-			return(0);
+			return (0);
 		case ISDN_TTY_FAX_EOP:
-			info->faxonline &= ~2; /* leave data mode */
+			info->faxonline &= ~2;	/* leave data mode */
 			info->online = 1;
 			f->phase = ISDN_FAX_PHASE_D;
-			return(0);
+			return (0);
 
 	}
-	return(-1);
+	return (-1);
 }
 
 
 void
-isdn_tty_fax_bitorder(modem_info *info, struct sk_buff *skb)
+isdn_tty_fax_bitorder(modem_info * info, struct sk_buff *skb)
 {
 	__u8 LeftMask;
 	__u8 RightMask;
@@ -276,13 +325,13 @@
 	int i;
 
 	if (!info->fax->bor) {
-		for(i = 0; i < skb->len; i++) {
+		for (i = 0; i < skb->len; i++) {
 			Data = skb->data[i];
 			for (
-				LeftMask = 0x80, RightMask = 0x01;
-				LeftMask > RightMask;
-				LeftMask >>= 1, RightMask <<= 1
-			) {
+				    LeftMask = 0x80, RightMask = 0x01;
+				    LeftMask > RightMask;
+				    LeftMask >>= 1, RightMask <<= 1
+			    ) {
 				fBit = (Data & LeftMask);
 				if (Data & RightMask)
 					Data |= LeftMask;
@@ -300,10 +349,103 @@
 }
 
 /*
+ * Parse AT+F.. FAX class 1 commands
+ */
+
+int
+isdn_tty_cmd_FCLASS1(char **p, modem_info * info)
+{
+	static char *cmd[] =
+	{"AE", "TS", "RS", "TM", "RM", "TH", "RH"};
+	isdn_ctrl c;
+	int par, i;
+	long flags;
+
+	for (c.parm.aux.cmd = 0; c.parm.aux.cmd < 7; c.parm.aux.cmd++)
+		if (!strncmp(p[0], cmd[c.parm.aux.cmd], 2))
+			break;
+
+#ifdef ISDN_TTY_FAX_CMD_DEBUG
+	printk(KERN_DEBUG "isdn_tty_cmd_FCLASS1 (%s,%d)\n", p[0], c.parm.aux.cmd);
+#endif
+	if (c.parm.aux.cmd == 7)
+		PARSE_ERROR1;
+
+	p[0] += 2;
+	switch (*p[0]) {
+		case '?':
+			p[0]++;
+			c.parm.aux.subcmd = AT_QUERY;
+			break;
+		case '=':
+			p[0]++;
+			if (*p[0] == '?') {
+				p[0]++;
+				c.parm.aux.subcmd = AT_EQ_QUERY;
+			} else {
+				par = isdn_getnum(p);
+				if ((par < 0) || (par > 255))
+					PARSE_ERROR1;
+				c.parm.aux.subcmd = AT_EQ_VALUE;
+				c.parm.aux.para[0] = par;
+			}
+			break;
+		case 0:
+			c.parm.aux.subcmd = AT_COMMAND;
+			break;
+		default:
+			PARSE_ERROR1;
+	}
+	c.command = ISDN_CMD_FAXCMD;
+#ifdef ISDN_TTY_FAX_CMD_DEBUG
+	printk(KERN_DEBUG "isdn_tty_cmd_FCLASS1 %d/%d/%d)\n",
+	       c.parm.aux.cmd, c.parm.aux.subcmd, c.parm.aux.para[0]);
+#endif
+	if (info->isdn_driver < 0) {
+		save_flags(flags);
+		cli();
+		if ((c.parm.aux.subcmd == AT_EQ_VALUE) ||
+		    (c.parm.aux.subcmd == AT_COMMAND)) {
+			restore_flags(flags);
+			PARSE_ERROR1;
+		}
+		/* get a temporary connection to the first free fax driver */
+		i = isdn_get_free_channel(ISDN_USAGE_FAX, ISDN_PROTO_L2_FAX,
+					  ISDN_PROTO_L3_FCLASS1, -1, -1, "00");
+		if (i < 0) {
+			restore_flags(flags);
+			PARSE_ERROR1;
+		}
+		info->isdn_driver = dev->drvmap[i];
+		info->isdn_channel = dev->chanmap[i];
+		info->drv_index = i;
+		dev->m_idx[i] = info->line;
+		c.driver = info->isdn_driver;
+		c.arg = info->isdn_channel;
+		isdn_command(&c);
+		isdn_free_channel(info->isdn_driver, info->isdn_channel,
+				  ISDN_USAGE_FAX);
+		info->isdn_driver = -1;
+		info->isdn_channel = -1;
+		if (info->drv_index >= 0) {
+			dev->m_idx[info->drv_index] = -1;
+			info->drv_index = -1;
+		}
+		restore_flags(flags);
+	} else {
+		c.driver = info->isdn_driver;
+		c.arg = info->isdn_channel;
+		isdn_command(&c);
+	}
+	return 1;
+}
+
+/*
  * Parse AT+F.. FAX class 2 commands
  */
 
-int isdn_tty_cmd_PLUSF_FAX(char **p, modem_info * info)
+int
+isdn_tty_cmd_FCLASS2(char **p, modem_info * info)
 {
 	atemu *m = &info->emu;
 	T30_s *f = info->fax;
@@ -311,10 +453,11 @@
 	int par;
 	char rs[50];
 	char rss[50];
-	int maxdccval[]={1,5,2,2,3,2,0,7};
+	int maxdccval[] =
+	{1, 5, 2, 2, 3, 2, 0, 7};
 
 	/* FAA still unchanged */
-        if (!strncmp(p[0], "AA", 2)) { /* TODO */
+	if (!strncmp(p[0], "AA", 2)) {	/* TODO */
 		p[0] += 2;
 		switch (*p[0]) {
 			case '?':
@@ -332,399 +475,363 @@
 				PARSE_ERROR1;
 		}
 		return 0;
-       }
-
+	}
 	/* BADLIN=value - dummy 0=disable errorchk disabled, 1-255 nr. of lines for making page bad */
-        if (!strncmp(p[0], "BADLIN", 6)) {
-            p[0] += 6;
+	if (!strncmp(p[0], "BADLIN", 6)) {
+		p[0] += 6;
 		switch (*p[0]) {
 			case '?':
 				p[0]++;
-                                sprintf(rs, "\r\n%d",f->badlin);
-                                isdn_tty_at_cout(rs, info);
+				sprintf(rs, "\r\n%d", f->badlin);
+				isdn_tty_at_cout(rs, info);
 				break;
 			case '=':
-                                p[0]++;
-                                if (*p[0] == '?')
-                                {
-                                     p[0]++;
-                                     sprintf(rs, "\r\n0-255");
-                       		     isdn_tty_at_cout(rs, info);
-                                    }
-                                    else
-                                    {
-                                        par = isdn_getnum(p);
-                                        if ((par < 0) || (par > 255))
-                                            PARSE_ERROR1;
-                                        f->badlin = par;
+				p[0]++;
+				if (*p[0] == '?') {
+					p[0]++;
+					sprintf(rs, "\r\n0-255");
+					isdn_tty_at_cout(rs, info);
+				} else {
+					par = isdn_getnum(p);
+					if ((par < 0) || (par > 255))
+						PARSE_ERROR1;
+					f->badlin = par;
 #ifdef ISDN_TTY_FAX_STAT_DEBUG
-                                        printk(KERN_DEBUG "isdn_tty: Fax FBADLIN=%d\n", par);
+					printk(KERN_DEBUG "isdn_tty: Fax FBADLIN=%d\n", par);
 #endif
-                                    }
-                                break;
+				}
+				break;
 			default:
-			        PARSE_ERROR1;
+				PARSE_ERROR1;
 		}
-                return 0;
-        }
-
+		return 0;
+	}
 	/* BADMUL=value - dummy 0=disable errorchk disabled (treshold multiplier) */
-        if (!strncmp(p[0], "BADMUL", 6)){
-            p[0] +=6;
+	if (!strncmp(p[0], "BADMUL", 6)) {
+		p[0] += 6;
 		switch (*p[0]) {
 			case '?':
 				p[0]++;
-                                sprintf(rs, "\r\n%d", f->badmul);
-                                isdn_tty_at_cout(rs, info);
+				sprintf(rs, "\r\n%d", f->badmul);
+				isdn_tty_at_cout(rs, info);
 				break;
 			case '=':
-                                p[0]++;
-                                if (*p[0] == '?')
-                                    {
-                                     p[0]++;
-                                     sprintf(rs, "\r\n0-255");
-                       		     isdn_tty_at_cout(rs, info);
-                                    }
-                                    else
-                                    {
-                                        par = isdn_getnum(p);
-                                        if ((par < 0) || (par > 255))
-                                            PARSE_ERROR1;
-                                        f->badmul = par;
+				p[0]++;
+				if (*p[0] == '?') {
+					p[0]++;
+					sprintf(rs, "\r\n0-255");
+					isdn_tty_at_cout(rs, info);
+				} else {
+					par = isdn_getnum(p);
+					if ((par < 0) || (par > 255))
+						PARSE_ERROR1;
+					f->badmul = par;
 #ifdef ISDN_TTY_FAX_STAT_DEBUG
-                                        printk(KERN_DEBUG "isdn_tty: Fax FBADMUL=%d\n", par);
+					printk(KERN_DEBUG "isdn_tty: Fax FBADMUL=%d\n", par);
 #endif
-                                    }
-                                    break;
+				}
+				break;
 			default:
 				PARSE_ERROR1;
 		}
-                return 0;
-        }
-
+		return 0;
+	}
 	/* BOR=n - Phase C bit order, 0=direct, 1=reverse */
-        if (!strncmp(p[0], "BOR", 3)){
-            p[0] +=3;
+	if (!strncmp(p[0], "BOR", 3)) {
+		p[0] += 3;
 		switch (*p[0]) {
 			case '?':
 				p[0]++;
-                                sprintf(rs, "\r\n%d", f->bor);
-                                isdn_tty_at_cout(rs, info);
+				sprintf(rs, "\r\n%d", f->bor);
+				isdn_tty_at_cout(rs, info);
 				break;
 			case '=':
-                                p[0]++;
-                                if (*p[0] == '?')
-                                    {
-                                     p[0]++;
-                                     sprintf(rs, "\r\n0,1");
-                       		     isdn_tty_at_cout(rs, info);
-                                    }
-                                    else
-                                    {
-                                        par = isdn_getnum(p);
-                                        if ((par < 0) || (par > 1))
-                                            PARSE_ERROR1;
-                                        f->bor = par;
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-                                        printk(KERN_DEBUG "isdn_tty: Fax FBOR=%d\n", par);
-#endif
-                                    }
-                                break;
-                        default:
-                                PARSE_ERROR1;
-                                }
-                       return 0;
-        }
-
+				p[0]++;
+				if (*p[0] == '?') {
+					p[0]++;
+					sprintf(rs, "\r\n0,1");
+					isdn_tty_at_cout(rs, info);
+				} else {
+					par = isdn_getnum(p);
+					if ((par < 0) || (par > 1))
+						PARSE_ERROR1;
+					f->bor = par;
+#ifdef ISDN_TTY_FAX_STAT_DEBUG
+					printk(KERN_DEBUG "isdn_tty: Fax FBOR=%d\n", par);
+#endif
+				}
+				break;
+			default:
+				PARSE_ERROR1;
+		}
+		return 0;
+	}
 	/* NBC=n - No Best Capabilities */
-        if (!strncmp(p[0], "NBC", 3)){
-            p[0] +=3;
+	if (!strncmp(p[0], "NBC", 3)) {
+		p[0] += 3;
 		switch (*p[0]) {
 			case '?':
 				p[0]++;
-                                sprintf(rs, "\r\n%d", f->nbc);
-                                isdn_tty_at_cout(rs, info);
+				sprintf(rs, "\r\n%d", f->nbc);
+				isdn_tty_at_cout(rs, info);
 				break;
 			case '=':
-                                p[0]++;
-                                if (*p[0] == '?')
-                                    {
-                                     p[0]++;
-                                     sprintf(rs, "\r\n0,1");
-                       		     isdn_tty_at_cout(rs, info);
-                                    }
-                                    else
-                                    {
-                                        par = isdn_getnum(p);
-                                        if ((par < 0) || (par > 1))
-                                            PARSE_ERROR1;
-                                        f->nbc = par;
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-                                        printk(KERN_DEBUG "isdn_tty: Fax FNBC=%d\n", par);
-#endif
-                                    }
-                                break;
-                        default:
-                                PARSE_ERROR1;
-                                }
-                       return 0;
-        }
-
+				p[0]++;
+				if (*p[0] == '?') {
+					p[0]++;
+					sprintf(rs, "\r\n0,1");
+					isdn_tty_at_cout(rs, info);
+				} else {
+					par = isdn_getnum(p);
+					if ((par < 0) || (par > 1))
+						PARSE_ERROR1;
+					f->nbc = par;
+#ifdef ISDN_TTY_FAX_STAT_DEBUG
+					printk(KERN_DEBUG "isdn_tty: Fax FNBC=%d\n", par);
+#endif
+				}
+				break;
+			default:
+				PARSE_ERROR1;
+		}
+		return 0;
+	}
 	/* BUF? - Readonly buffersize readout  */
-        if (!strncmp(p[0], "BUF?", 4)) {
-                p[0] += 4;
+	if (!strncmp(p[0], "BUF?", 4)) {
+		p[0] += 4;
 #ifdef ISDN_TTY_FAX_STAT_DEBUG
-                printk(KERN_DEBUG "isdn_tty: Fax FBUF? (%d) \n", (16 * m->mdmreg[REG_PSIZE]));
+		printk(KERN_DEBUG "isdn_tty: Fax FBUF? (%d) \n", (16 * m->mdmreg[REG_PSIZE]));
 #endif
-                                p[0]++;
-                                 sprintf(rs, "\r\n %d ", (16 * m->mdmreg[REG_PSIZE]));
-                                isdn_tty_at_cout(rs, info);
-                return 0;
-        }
-        
+		p[0]++;
+		sprintf(rs, "\r\n %d ", (16 * m->mdmreg[REG_PSIZE]));
+		isdn_tty_at_cout(rs, info);
+		return 0;
+	}
 	/* CIG=string - local fax station id string for polling rx */
-        if (!strncmp(p[0], "CIG", 3)) {
+	if (!strncmp(p[0], "CIG", 3)) {
 		int i, r;
-                p[0] += 3;
+		p[0] += 3;
 		switch (*p[0]) {
 			case '?':
 				p[0]++;
 				sprintf(rs, "\r\n\"%s\"", f->pollid);
-                                isdn_tty_at_cout(rs, info);
-                                break;
+				isdn_tty_at_cout(rs, info);
+				break;
 			case '=':
-                                p[0]++;
-                                if (*p[0] == '?')
-                                    {
-                                     p[0]++;
-                                     sprintf(rs, "\r\n\"STRING\"");
-                       		     isdn_tty_at_cout(rs, info);
-                                    }
-                                    else
-                                    {
-                                        if (*p[0] =='"')
-                                            p[0]++;
-                                        for(i=0; (*p[0]) && i < (FAXIDLEN-1) && (*p[0] != '"'); i++)
-                                        {
-                                            f->pollid[i] = *p[0]++;
-                                        }
-                                        if (*p[0] =='"')
-                                            p[0]++;
-                                        for(r=i; r < FAXIDLEN; r++)
-                                        {
-                                        	f->pollid[r] = 32;
-                                        }
-                                        f->pollid[FAXIDLEN-1] = 0;
+				p[0]++;
+				if (*p[0] == '?') {
+					p[0]++;
+					sprintf(rs, "\r\n\"STRING\"");
+					isdn_tty_at_cout(rs, info);
+				} else {
+					if (*p[0] == '"')
+						p[0]++;
+					for (i = 0; (*p[0]) && i < (FAXIDLEN - 1) && (*p[0] != '"'); i++) {
+						f->pollid[i] = *p[0]++;
+					}
+					if (*p[0] == '"')
+						p[0]++;
+					for (r = i; r < FAXIDLEN; r++) {
+						f->pollid[r] = 32;
+					}
+					f->pollid[FAXIDLEN - 1] = 0;
 #ifdef ISDN_TTY_FAX_STAT_DEBUG
-                                       printk(KERN_DEBUG "isdn_tty: Fax local poll ID rx \"%s\"\n", f->pollid);
+					printk(KERN_DEBUG "isdn_tty: Fax local poll ID rx \"%s\"\n", f->pollid);
 #endif
-                                    }
-                                break;
+				}
+				break;
 			default:
 				PARSE_ERROR1;
 		}
-                return 0;
-        }
-
+		return 0;
+	}
 	/* CQ=n - copy qlty chk, 0= no chk, 1=only 1D chk, 2=1D+2D chk */
-        if (!strncmp(p[0], "CQ", 2)) {
-                p[0] += 2;
+	if (!strncmp(p[0], "CQ", 2)) {
+		p[0] += 2;
 		switch (*p[0]) {
 			case '?':
 				p[0]++;
-                                sprintf(rs, "\r\n%d", f->cq);
-                                isdn_tty_at_cout(rs, info);
+				sprintf(rs, "\r\n%d", f->cq);
+				isdn_tty_at_cout(rs, info);
 				break;
 			case '=':
-                                p[0]++;
-                                if (*p[0] == '?')
-                                    {
-                                     p[0]++;
-                                     sprintf(rs, "\r\n0,1,2");
-                       		     isdn_tty_at_cout(rs, info);
-                                    }
-                                    else
-                                    {
-                                        par = isdn_getnum(p);
-                                        if ((par < 0) || (par > 2))
-                                            PARSE_ERROR1;
-                                        f->cq = par;
+				p[0]++;
+				if (*p[0] == '?') {
+					p[0]++;
+					sprintf(rs, "\r\n0,1,2");
+					isdn_tty_at_cout(rs, info);
+				} else {
+					par = isdn_getnum(p);
+					if ((par < 0) || (par > 2))
+						PARSE_ERROR1;
+					f->cq = par;
 #ifdef ISDN_TTY_FAX_STAT_DEBUG
-                                        printk(KERN_DEBUG "isdn_tty: Fax FCQ=%d\n", par);
+					printk(KERN_DEBUG "isdn_tty: Fax FCQ=%d\n", par);
 #endif
-                                    }
-                                    break;
+				}
+				break;
 			default:
 				PARSE_ERROR1;
 		}
-                return 0;
-        }
-
+		return 0;
+	}
 	/* CR=n - can receive? 0= no data rx or poll remote dev, 1=do receive data or poll remote dev */
-        if (!strncmp(p[0], "CR", 2)) {
-                p[0] += 2;
+	if (!strncmp(p[0], "CR", 2)) {
+		p[0] += 2;
 		switch (*p[0]) {
 			case '?':
 				p[0]++;
-                                sprintf(rs, "\r\n%d", f->cr); /* read actual value from struct and print */
-                                isdn_tty_at_cout(rs, info);
+				sprintf(rs, "\r\n%d", f->cr);	/* read actual value from struct and print */
+				isdn_tty_at_cout(rs, info);
 				break;
 			case '=':
-                                p[0]++;
-                                if (*p[0] == '?')
-                                    {
-                                     p[0]++;
-                                     sprintf(rs, "\r\n0,1"); /* display online help */
-                       		     isdn_tty_at_cout(rs, info);
-                                    }
-                                    else
-                                    {
-                                        par = isdn_getnum(p);
-                                        if ((par < 0) || (par > 1))
-                                            PARSE_ERROR1;
-                                        f->cr = par;
+				p[0]++;
+				if (*p[0] == '?') {
+					p[0]++;
+					sprintf(rs, "\r\n0,1");		/* display online help */
+					isdn_tty_at_cout(rs, info);
+				} else {
+					par = isdn_getnum(p);
+					if ((par < 0) || (par > 1))
+						PARSE_ERROR1;
+					f->cr = par;
 #ifdef ISDN_TTY_FAX_STAT_DEBUG
-                                        printk(KERN_DEBUG "isdn_tty: Fax FCR=%d\n", par);
+					printk(KERN_DEBUG "isdn_tty: Fax FCR=%d\n", par);
 #endif
-                                    }
-                                    break;
+				}
+				break;
 			default:
 				PARSE_ERROR1;
 		}
-                return 0;
-        }
-
+		return 0;
+	}
 	/* CTCRTY=value - ECM retry count */
-        if (!strncmp(p[0], "CTCRTY", 6)){
-            p[0] +=6;
+	if (!strncmp(p[0], "CTCRTY", 6)) {
+		p[0] += 6;
 		switch (*p[0]) {
 			case '?':
 				p[0]++;
-                                sprintf(rs, "\r\n%d",f->ctcrty);
-                                isdn_tty_at_cout(rs, info);
+				sprintf(rs, "\r\n%d", f->ctcrty);
+				isdn_tty_at_cout(rs, info);
 				break;
 			case '=':
-                                p[0]++;
-                                if (*p[0] == '?')
-                                    {
-                                     p[0]++;
-                                     sprintf(rs, "\r\n0-255");
-                       		     isdn_tty_at_cout(rs, info);
-                                    }
-                                    else
-                                    {
-                                        par = isdn_getnum(p);
-                                        if ((par < 0) || (par > 255))
-                                            PARSE_ERROR1;
-                                        f->ctcrty = par;
+				p[0]++;
+				if (*p[0] == '?') {
+					p[0]++;
+					sprintf(rs, "\r\n0-255");
+					isdn_tty_at_cout(rs, info);
+				} else {
+					par = isdn_getnum(p);
+					if ((par < 0) || (par > 255))
+						PARSE_ERROR1;
+					f->ctcrty = par;
 #ifdef ISDN_TTY_FAX_STAT_DEBUG
-                                        printk(KERN_DEBUG "isdn_tty: Fax FCTCRTY=%d\n", par);
+					printk(KERN_DEBUG "isdn_tty: Fax FCTCRTY=%d\n", par);
 #endif
-                                    }
-                                    break;
+				}
+				break;
 			default:
 				PARSE_ERROR1;
 		}
-                return 0;
-        }
-
+		return 0;
+	}
 	/* DCC=vr,br,wd,ln,df,ec,bf,st - DCE capabilities parms */
-        if (!strncmp(p[0], "DCC", 3)) {
+	if (!strncmp(p[0], "DCC", 3)) {
 		char *rp = &f->resolution;
 		int i;
 
-                p[0] += 3;
-		switch(*p[0]) {
+		p[0] += 3;
+		switch (*p[0]) {
 			case '?':
 				p[0]++;
-	                        strcpy(rs, "\r\n");
-	                        for(i = 0; i < 8; i++) {
-        	                        sprintf(rss, "%c%s", rp[i] + 48,
-                	                        (i < 7) ? "," : "");
-                        	        strcat(rs, rss);
-	                        }
-        	                isdn_tty_at_cout(rs, info);
+				strcpy(rs, "\r\n");
+				for (i = 0; i < 8; i++) {
+					sprintf(rss, "%c%s", rp[i] + 48,
+						(i < 7) ? "," : "");
+					strcat(rs, rss);
+				}
+				isdn_tty_at_cout(rs, info);
 				break;
 			case '=':
-                                p[0]++;
-		                if (*p[0] == '?') {
-					isdn_tty_at_cout("\r\n(0,1),(0-5),(0-2),(0-2),(0-3),(0-2),(0),(0-7)",info);
-                                	p[0]++;
-		                } else {
-					for (i=0; (((*p[0]>='0')&&(*p[0]<='9'))||(*p[0]==','))&&(i<8); i++) {
+				p[0]++;
+				if (*p[0] == '?') {
+					isdn_tty_at_cout("\r\n(0,1),(0-5),(0-2),(0-2),(0-3),(0-2),(0),(0-7)", info);
+					p[0]++;
+				} else {
+					for (i = 0; (((*p[0] >= '0') && (*p[0] <= '9')) || (*p[0] == ',')) && (i < 8); i++) {
 						if (*p[0] != ',') {
 							if ((*p[0] - 48) > maxdccval[i]) {
 								PARSE_ERROR1;
 							}
 							rp[i] = *p[0] - 48;
 							p[0]++;
-							if (*p[0] == ',') 
+							if (*p[0] == ',')
 								p[0]++;
-						} else p[0]++;
+						} else
+							p[0]++;
 					}
 #ifdef ISDN_TTY_FAX_STAT_DEBUG
-				printk(KERN_DEBUG "isdn_tty: Fax FDCC capabilities DCE=%d,%d,%d,%d,%d,%d,%d,%d\n",
-				       rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], rp[6], rp[7]);
+					printk(KERN_DEBUG "isdn_tty: Fax FDCC capabilities DCE=%d,%d,%d,%d,%d,%d,%d,%d\n",
+					       rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], rp[6], rp[7]);
 #endif
-        		        }
+				}
 				break;
 			default:
 				PARSE_ERROR1;
 		}
-                return 0;
-        }
-       
+		return 0;
+	}
 	/* DIS=vr,br,wd,ln,df,ec,bf,st - current session parms */
-        if (!strncmp(p[0], "DIS", 3)) {
+	if (!strncmp(p[0], "DIS", 3)) {
 		char *rp = &f->resolution;
 		int i;
 
-                p[0] += 3;
-		switch(*p[0]) {
+		p[0] += 3;
+		switch (*p[0]) {
 			case '?':
 				p[0]++;
-	                        strcpy(rs, "\r\n");
-	                        for(i = 0; i < 8; i++) {
-        	                        sprintf(rss, "%c%s", rp[i] + 48,
-                	                        (i < 7) ? "," : "");
-                        	        strcat(rs, rss);
-	                        }
-        	                isdn_tty_at_cout(rs, info);
+				strcpy(rs, "\r\n");
+				for (i = 0; i < 8; i++) {
+					sprintf(rss, "%c%s", rp[i] + 48,
+						(i < 7) ? "," : "");
+					strcat(rs, rss);
+				}
+				isdn_tty_at_cout(rs, info);
 				break;
 			case '=':
-                                p[0]++;
-		                if (*p[0] == '?') {
-					isdn_tty_at_cout("\r\n(0,1),(0-5),(0-2),(0-2),(0-3),(0-2),(0),(0-7)",info);
-                                	p[0]++;
-		                } else {
-					for (i=0; (((*p[0]>='0')&&(*p[0]<='9'))||(*p[0]==','))&&(i<8); i++) {
+				p[0]++;
+				if (*p[0] == '?') {
+					isdn_tty_at_cout("\r\n(0,1),(0-5),(0-2),(0-2),(0-3),(0-2),(0),(0-7)", info);
+					p[0]++;
+				} else {
+					for (i = 0; (((*p[0] >= '0') && (*p[0] <= '9')) || (*p[0] == ',')) && (i < 8); i++) {
 						if (*p[0] != ',') {
 							if ((*p[0] - 48) > maxdccval[i]) {
 								PARSE_ERROR1;
 							}
 							rp[i] = *p[0] - 48;
 							p[0]++;
-							if (*p[0] == ',') 
+							if (*p[0] == ',')
 								p[0]++;
-						} else p[0]++;
+						} else
+							p[0]++;
 					}
 #ifdef ISDN_TTY_FAX_STAT_DEBUG
-				printk(KERN_DEBUG "isdn_tty: Fax FDIS session parms=%d,%d,%d,%d,%d,%d,%d,%d\n",
-				       rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], rp[6], rp[7]);
+					printk(KERN_DEBUG "isdn_tty: Fax FDIS session parms=%d,%d,%d,%d,%d,%d,%d,%d\n",
+					       rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], rp[6], rp[7]);
 #endif
-        		        }
+				}
 				break;
 			default:
 				PARSE_ERROR1;
 		}
-                return 0;
-        }
-       
-	/* DR - Receive Phase C data command, initiates document reception */ 
-        if (!strncmp(p[0], "DR", 2)) {
-                p[0] += 2;
+		return 0;
+	}
+	/* DR - Receive Phase C data command, initiates document reception */
+	if (!strncmp(p[0], "DR", 2)) {
+		p[0] += 2;
 		if ((info->faxonline & 16) &&	/* incoming connection */
-   		   ((f->phase == ISDN_FAX_PHASE_B) || (f->phase == ISDN_FAX_PHASE_D))) {
+		    ((f->phase == ISDN_FAX_PHASE_B) || (f->phase == ISDN_FAX_PHASE_D))) {
 #ifdef ISDN_TTY_FAX_STAT_DEBUG
 			printk(KERN_DEBUG "isdn_tty: Fax FDR\n");
 #endif
@@ -735,11 +842,11 @@
 			isdn_command(&cmd);
 			if (f->phase == ISDN_FAX_PHASE_B) {
 				f->phase = ISDN_FAX_PHASE_C;
-			} else if (f->phase == ISDN_FAX_PHASE_D) { 
-				switch(f->fet) {
+			} else if (f->phase == ISDN_FAX_PHASE_D) {
+				switch (f->fet) {
 					case 0:	/* next page will be received */
 						f->phase = ISDN_FAX_PHASE_C;
-						isdn_tty_fax_modem_result(7, info); /* CONNECT */
+						isdn_tty_fax_modem_result(7, info);	/* CONNECT */
 						break;
 					case 1:	/* next doc will be received */
 						f->phase = ISDN_FAX_PHASE_B;
@@ -747,35 +854,36 @@
 					case 2:	/* fax session is terminating */
 						f->phase = ISDN_FAX_PHASE_E;
 						break;
-					default:	
+					default:
 						PARSE_ERROR1;
 				}
 			}
 		} else {
 			PARSE_ERROR1;
 		}
-                return 1;
+		return 1;
 	}
- 
 	/* DT=df,vr,wd,ln - TX phase C data command (release DCE to proceed with negotiation) */
-        if (!strncmp(p[0], "DT", 2)) {
-		int i, val[]={4,0,2,3};
+	if (!strncmp(p[0], "DT", 2)) {
+		int i, val[] =
+		{4, 0, 2, 3};
 		char *rp = &f->resolution;
 
-                p[0] += 2;
-		if (!info->faxonline & 1) 	/* not outgoing connection */
+		p[0] += 2;
+		if (!info->faxonline & 1)	/* not outgoing connection */
 			PARSE_ERROR1;
 
-		for (i=0; (((*p[0]>='0')&&(*p[0]<='9'))||(*p[0]==','))&&(i<4); i++) {
+		for (i = 0; (((*p[0] >= '0') && (*p[0] <= '9')) || (*p[0] == ',')) && (i < 4); i++) {
 			if (*p[0] != ',') {
 				if ((*p[0] - 48) > maxdccval[val[i]]) {
 					PARSE_ERROR1;
 				}
 				rp[val[i]] = *p[0] - 48;
 				p[0]++;
-				if (*p[0] == ',') 
+				if (*p[0] == ',')
 					p[0]++;
-			} else p[0]++;
+			} else
+				p[0]++;
 		}
 #ifdef ISDN_TTY_FAX_STAT_DEBUG
 		printk(KERN_DEBUG "isdn_tty: Fax FDT tx data command parms=%d,%d,%d,%d\n",
@@ -789,48 +897,43 @@
 			isdn_command(&cmd);
 			if (f->phase == ISDN_FAX_PHASE_D) {
 				f->phase = ISDN_FAX_PHASE_C;
-				isdn_tty_fax_modem_result(7, info); /* CONNECT */
+				isdn_tty_fax_modem_result(7, info);	/* CONNECT */
 			}
 		} else {
 			PARSE_ERROR1;
 		}
-                return 1;
-        }
-
+		return 1;
+	}
 	/* ECM=n - Error mode control 0=disabled, 2=enabled, handled by DCE alone incl. buff of partial pages */
-        if (!strncmp(p[0], "ECM", 3)) {
-                p[0] += 3;
+	if (!strncmp(p[0], "ECM", 3)) {
+		p[0] += 3;
 		switch (*p[0]) {
 			case '?':
 				p[0]++;
-                                sprintf(rs, "\r\n%d",f->ecm);
-                                isdn_tty_at_cout(rs, info);
+				sprintf(rs, "\r\n%d", f->ecm);
+				isdn_tty_at_cout(rs, info);
 				break;
 			case '=':
-                                p[0]++;
-                                if (*p[0] == '?')
-                                    {
-                                     p[0]++;
-                                     sprintf(rs, "\r\n0,2");
-                       		     isdn_tty_at_cout(rs, info);
-                                    }
-                                    else
-                                    {
-                                        par = isdn_getnum(p);
-                                        if ((par != 0) && (par != 2))
-                                            PARSE_ERROR1;
-                                        f->ecm = par;
+				p[0]++;
+				if (*p[0] == '?') {
+					p[0]++;
+					sprintf(rs, "\r\n0,2");
+					isdn_tty_at_cout(rs, info);
+				} else {
+					par = isdn_getnum(p);
+					if ((par != 0) && (par != 2))
+						PARSE_ERROR1;
+					f->ecm = par;
 #ifdef ISDN_TTY_FAX_STAT_DEBUG
-                                        printk(KERN_DEBUG "isdn_tty: Fax FECM=%d\n", par);
+					printk(KERN_DEBUG "isdn_tty: Fax FECM=%d\n", par);
 #endif
-                                    }
-                                    break;
+				}
+				break;
 			default:
 				PARSE_ERROR1;
 		}
-                return 0;
-        }
-
+		return 0;
+	}
 	/* ET=n - End of page or document */
 	if (!strncmp(p[0], "ET=", 3)) {
 		p[0] += 3;
@@ -857,7 +960,6 @@
 		}
 		return 0;
 	}
-
 	/* K - terminate */
 	if (!strncmp(p[0], "K", 1)) {
 		p[0] += 1;
@@ -866,205 +968,191 @@
 		isdn_tty_modem_hup(info, 1);
 		return 1;
 	}
-
 	/* LID=string - local fax ID */
-        if (!strncmp(p[0], "LID", 3)) {
+	if (!strncmp(p[0], "LID", 3)) {
 		int i, r;
-                p[0] += 3;
+		p[0] += 3;
 		switch (*p[0]) {
 			case '?':
 				p[0]++;
 				sprintf(rs, "\r\n\"%s\"", f->id);
-                                isdn_tty_at_cout(rs, info);
-                                break;
+				isdn_tty_at_cout(rs, info);
+				break;
 			case '=':
-                                p[0]++;
-                                if (*p[0] == '?')
-                                    {
-                                     p[0]++;
-                                     sprintf(rs, "\r\n\"STRING\"");
-                       		     isdn_tty_at_cout(rs, info);
-                                    }
-                                    else
-                                    {
-                                        if (*p[0] =='"')
-                                            p[0]++;
-                                        for(i=0; (*p[0]) && i < (FAXIDLEN-1) && (*p[0] != '"'); i++)
-                                        {
-                                            f->id[i] = *p[0]++;
-                                        }
-                                        if (*p[0] =='"')
-                                            p[0]++;
-                                        for(r=i; r < FAXIDLEN; r++)
-                                        {
-                                        	f->id[r] = 32;
-                                        }
-                                        f->id[FAXIDLEN-1] = 0;
+				p[0]++;
+				if (*p[0] == '?') {
+					p[0]++;
+					sprintf(rs, "\r\n\"STRING\"");
+					isdn_tty_at_cout(rs, info);
+				} else {
+					if (*p[0] == '"')
+						p[0]++;
+					for (i = 0; (*p[0]) && i < (FAXIDLEN - 1) && (*p[0] != '"'); i++) {
+						f->id[i] = *p[0]++;
+					}
+					if (*p[0] == '"')
+						p[0]++;
+					for (r = i; r < FAXIDLEN; r++) {
+						f->id[r] = 32;
+					}
+					f->id[FAXIDLEN - 1] = 0;
 #ifdef ISDN_TTY_FAX_STAT_DEBUG
-                                       printk(KERN_DEBUG "isdn_tty: Fax local ID \"%s\"\n", f->id);
+					printk(KERN_DEBUG "isdn_tty: Fax local ID \"%s\"\n", f->id);
 #endif
-                                    }
-                                break;
+				}
+				break;
 			default:
 				PARSE_ERROR1;
 		}
-                return 0;
-        }
-
+		return 0;
+	}
 
 	/* MDL? - DCE Model       */
-        if (!strncmp(p[0], "MDL?", 4)) {
-                p[0] += 4;
+	if (!strncmp(p[0], "MDL?", 4)) {
+		p[0] += 4;
 #ifdef ISDN_TTY_FAX_STAT_DEBUG
-                printk(KERN_DEBUG "isdn_tty: FMDL?\n");
+		printk(KERN_DEBUG "isdn_tty: FMDL?\n");
 #endif
-                isdn_tty_at_cout("\r\nisdn4linux", info);
-                return 0;
-        }
-
+		isdn_tty_at_cout("\r\nisdn4linux", info);
+		return 0;
+	}
 	/* MFR? - DCE Manufacturer */
-        if (!strncmp(p[0], "MFR?", 4)) {
-                p[0] += 4;
+	if (!strncmp(p[0], "MFR?", 4)) {
+		p[0] += 4;
 #ifdef ISDN_TTY_FAX_STAT_DEBUG
-                printk(KERN_DEBUG "isdn_tty: FMFR?\n");
+		printk(KERN_DEBUG "isdn_tty: FMFR?\n");
 #endif
-                isdn_tty_at_cout("\r\nisdn4linux", info);
-                return 0;
-        }
-
+		isdn_tty_at_cout("\r\nisdn4linux", info);
+		return 0;
+	}
 	/* MINSP=n - Minimum Speed for Phase C */
-        if (!strncmp(p[0], "MINSP", 5)) {
-                p[0] += 5;
+	if (!strncmp(p[0], "MINSP", 5)) {
+		p[0] += 5;
 		switch (*p[0]) {
 			case '?':
 				p[0]++;
-                                sprintf(rs, "\r\n%d",f->minsp);
-                                isdn_tty_at_cout(rs, info);
+				sprintf(rs, "\r\n%d", f->minsp);
+				isdn_tty_at_cout(rs, info);
 				break;
 			case '=':
-                                p[0]++;
-                                if (*p[0] == '?')
-                                    {
-                                     p[0]++;
-                                     sprintf(rs, "\r\n0-5");
-                       		     isdn_tty_at_cout(rs, info);
-                                    }
-                                    else
-                                    {
-                                        par = isdn_getnum(p);
-                                        if ((par < 0) || (par > 5))
-                                            PARSE_ERROR1;
-                                        f->minsp = par;
+				p[0]++;
+				if (*p[0] == '?') {
+					p[0]++;
+					sprintf(rs, "\r\n0-5");
+					isdn_tty_at_cout(rs, info);
+				} else {
+					par = isdn_getnum(p);
+					if ((par < 0) || (par > 5))
+						PARSE_ERROR1;
+					f->minsp = par;
 #ifdef ISDN_TTY_FAX_STAT_DEBUG
-                                        printk(KERN_DEBUG "isdn_tty: Fax FMINSP=%d\n", par);
+					printk(KERN_DEBUG "isdn_tty: Fax FMINSP=%d\n", par);
 #endif
-                                    }
-                                    break;
+				}
+				break;
 			default:
 				PARSE_ERROR1;
 		}
-                return 0;
-        }
-
+		return 0;
+	}
 	/* PHCTO=value - DTE phase C timeout */
-        if (!strncmp(p[0], "PHCTO", 5)){
-            p[0] +=5;
+	if (!strncmp(p[0], "PHCTO", 5)) {
+		p[0] += 5;
 		switch (*p[0]) {
 			case '?':
 				p[0]++;
-                                sprintf(rs, "\r\n%d",f->phcto);
-                                isdn_tty_at_cout(rs, info);
+				sprintf(rs, "\r\n%d", f->phcto);
+				isdn_tty_at_cout(rs, info);
 				break;
 			case '=':
-                                p[0]++;
-                                if (*p[0] == '?')
-                                    {
-                                     p[0]++;
-                                     sprintf(rs, "\r\n0-255");
-                       		     isdn_tty_at_cout(rs, info);
-                                    }
-                                    else
-                                    {
-                                        par = isdn_getnum(p);
-                                        if ((par < 0) || (par > 255))
-                                            PARSE_ERROR1;
-                                        f->phcto = par;
+				p[0]++;
+				if (*p[0] == '?') {
+					p[0]++;
+					sprintf(rs, "\r\n0-255");
+					isdn_tty_at_cout(rs, info);
+				} else {
+					par = isdn_getnum(p);
+					if ((par < 0) || (par > 255))
+						PARSE_ERROR1;
+					f->phcto = par;
 #ifdef ISDN_TTY_FAX_STAT_DEBUG
-                                        printk(KERN_DEBUG "isdn_tty: Fax FPHCTO=%d\n", par);
+					printk(KERN_DEBUG "isdn_tty: Fax FPHCTO=%d\n", par);
 #endif
-                                    }
-                                    break;
+				}
+				break;
 			default:
 				PARSE_ERROR1;
 		}
-                return 0;
-        }
-
+		return 0;
+	}
 
 	/* REL=n - Phase C received EOL alignment */
-        if (!strncmp(p[0], "REL", 3)) {
-                p[0] += 3;
+	if (!strncmp(p[0], "REL", 3)) {
+		p[0] += 3;
 		switch (*p[0]) {
 			case '?':
 				p[0]++;
-                                sprintf(rs, "\r\n%d",f->rel);
-                                isdn_tty_at_cout(rs, info);
+				sprintf(rs, "\r\n%d", f->rel);
+				isdn_tty_at_cout(rs, info);
 				break;
 			case '=':
-                                p[0]++;
-                                if (*p[0] == '?')
-                                    {
-                                     p[0]++;
-                                     sprintf(rs, "\r\n0,1");
-                       		     isdn_tty_at_cout(rs, info);
-                                    }
-                                    else
-                                    {
-                                        par = isdn_getnum(p);
-                                        if ((par < 0) || (par > 1))
-                                            PARSE_ERROR1;
-                                        f->rel = par;
+				p[0]++;
+				if (*p[0] == '?') {
+					p[0]++;
+					sprintf(rs, "\r\n0,1");
+					isdn_tty_at_cout(rs, info);
+				} else {
+					par = isdn_getnum(p);
+					if ((par < 0) || (par > 1))
+						PARSE_ERROR1;
+					f->rel = par;
 #ifdef ISDN_TTY_FAX_STAT_DEBUG
-                                        printk(KERN_DEBUG "isdn_tty: Fax FREL=%d\n", par);
+					printk(KERN_DEBUG "isdn_tty: Fax FREL=%d\n", par);
 #endif
-                                    }
-                                    break;
+				}
+				break;
 			default:
 				PARSE_ERROR1;
 		}
-                return 0;
-        }
-
+		return 0;
+	}
 	/* REV? - DCE Revision */
-        if (!strncmp(p[0], "REV?", 4)) {
-                p[0] += 4;
+	if (!strncmp(p[0], "REV?", 4)) {
+		p[0] += 4;
 #ifdef ISDN_TTY_FAX_STAT_DEBUG
-                printk(KERN_DEBUG "isdn_tty: FREV?\n");
+		printk(KERN_DEBUG "isdn_tty: FREV?\n");
 #endif
 		strcpy(rss, isdn_tty_fax_revision);
 		sprintf(rs, "\r\nRev: %s", isdn_getrev(rss));
-                isdn_tty_at_cout(rs, info);
-                return 0;
-        }
-
+		isdn_tty_at_cout(rs, info);
+		return 0;
+	}
 
 	/* Phase C Transmit Data Block Size */
-	if (!strncmp(p[0], "TBC=", 4)) { /* dummy, not used */
+	if (!strncmp(p[0], "TBC=", 4)) {	/* dummy, not used */
 		p[0] += 4;
 #ifdef ISDN_TTY_FAX_STAT_DEBUG
-                printk(KERN_DEBUG "isdn_tty: Fax FTBC=%c\n", *p[0]);
+		printk(KERN_DEBUG "isdn_tty: Fax FTBC=%c\n", *p[0]);
 #endif
-                switch (*p[0]) {
-                        case '0':
-                                p[0]++;
-                                break;
-                        default:
-                                PARSE_ERROR1;
-                }
-                return 0;
+		switch (*p[0]) {
+			case '0':
+				p[0]++;
+				break;
+			default:
+				PARSE_ERROR1;
+		}
+		return 0;
 	}
-
-        printk(KERN_DEBUG "isdn_tty: unknown token=>AT+F%s<\n", p[0]);
+	printk(KERN_DEBUG "isdn_tty: unknown token=>AT+F%s<\n", p[0]);
 	PARSE_ERROR1;
 }
 
+int
+isdn_tty_cmd_PLUSF_FAX(char **p, modem_info * info)
+{
+	if (TTY_IS_FCLASS2(info))
+		return (isdn_tty_cmd_FCLASS2(p, info));
+	else if (TTY_IS_FCLASS1(info))
+		return (isdn_tty_cmd_FCLASS1(p, info));
+	PARSE_ERROR1;
+}
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/misc/parport_ax.c linux.15p9/drivers/misc/parport_ax.c
--- linux.vanilla/drivers/misc/parport_ax.c	Tue Mar 16 00:11:30 1999
+++ linux.15p9/drivers/misc/parport_ax.c	Fri Jan 14 15:56:16 2000
@@ -1,4 +1,4 @@
-/* $Id: parport_ax.c,v 1.17 1999/01/20 06:18:54 davem Exp $
+/* $Id: parport_ax.c,v 1.17.2.1 2000/01/09 18:29:28 ecd Exp $
  * Parallel-port routines for Sun Ultra/AX architecture
  * 
  * Author: Eddie C. Dost <ecd@skynet.be>
@@ -30,13 +30,6 @@
 #include <asm/irq.h>
 
 
-/*
- * Define this if you have Devices which don't support short
- * host read/write cycles.
- */
-#undef HAVE_SLOW_DEVICES
-
-
 #define DATA		0x00
 #define STATUS		0x01
 #define CONTROL		0x02
@@ -513,7 +506,6 @@
 	struct parport tmpport, *p;
 	unsigned long base;
 	unsigned long config;
-	unsigned char tmp;
 	int irq, dma;
 
 	/* Pointer to NS87303 Configuration Registers */
@@ -523,29 +515,15 @@
 	tmpport.base = dev->base_address[0];
 	tmpport.ops = &parport_ax_ops;
 
+	/* Configure IRQ to Push Pull, Level Low */
 	/* Enable ECP mode, set bit 2 of the CTR first */
 	tmpport.ops->write_control(&tmpport, 0x04);
-	tmp = ns87303_readb(config, PCR);
-	tmp |= (PCR_EPP_IEEE | PCR_ECP_ENABLE | PCR_ECP_CLK_ENA);
-	ns87303_writeb(config, PCR, tmp);
+	ns87303_modify(config, PCR,
+		       PCR_EPP_ENABLE | PCR_IRQ_ODRAIN,
+		       PCR_ECP_ENABLE | PCR_ECP_CLK_ENA | PCR_IRQ_POLAR);
 
 	/* LPT CTR bit 5 controls direction of parallel port */
-	tmp = ns87303_readb(config, PTR);
-	tmp |= PTR_LPT_REG_DIR;
-	ns87303_writeb(config, PTR, tmp);
-
-	/* Configure IRQ to Push Pull, Level Low */
-	tmp = ns87303_readb(config, PCR);
-	tmp &= ~(PCR_IRQ_ODRAIN);
-	tmp |= PCR_IRQ_POLAR;
-	ns87303_writeb(config, PCR, tmp);
-
-#ifndef HAVE_SLOW_DEVICES
-	/* Enable Zero Wait State for ECP */
-	tmp = ns87303_readb(config, FCR);
-	tmp |= FCR_ZWS_ENA;
-	ns87303_writeb(config, FCR, tmp);
-#endif
+	ns87303_modify(config, PTR, 0, PTR_LPT_REG_DIR);
 
 	/*
 	 * Now continue initializing the port
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/misc/parport_pc.c linux.15p9/drivers/misc/parport_pc.c
--- linux.vanilla/drivers/misc/parport_pc.c	Tue Jan  4 21:18:51 2000
+++ linux.15p9/drivers/misc/parport_pc.c	Wed Jan 26 23:06:16 2000
@@ -839,11 +839,6 @@
 		 * Put the ECP detected port in the more PS2 like mode.
 		 */
 		parport_pc_write_econtrol(p, 0x34);
-	parport_pc_write_control(p, 0x8);
-	parport_pc_write_data(p, 0);
-	udelay (50);
-	parport_pc_write_control(p, 0xc);
-	udelay (50);
 
 	if (parport_probe_hook)
 		(*parport_probe_hook)(p);
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/3c509.c linux.15p9/drivers/net/3c509.c
--- linux.vanilla/drivers/net/3c509.c	Wed Oct 20 01:12:38 1999
+++ linux.15p9/drivers/net/3c509.c	Fri Jan 21 18:53:55 2000
@@ -251,6 +251,7 @@
 				if (el3_debug > 2) {
 					printk("3c529: irq %d  ioaddr 0x%x  ifport %d\n", irq, ioaddr, if_port);
 				}
+				EL3WINDOW(0);
 				for (i = 0; i < 3; i++) {
 					phys_addr[i] = htons(read_eeprom(ioaddr, i));
 				}
@@ -577,7 +578,7 @@
 		outw(0x00, ioaddr + TX_FIFO);
 		/* ... and the packet rounded to a doubleword. */
 #ifdef  __powerpc__
-		outsl_unswapped(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
+		outsl_ns(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
 #else
 		outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
 #endif
@@ -797,7 +798,7 @@
 
 				/* 'skb->data' points to the start of sk_buff data area. */
 #ifdef  __powerpc__
-				insl_unswapped(ioaddr+RX_FIFO, skb_put(skb,pkt_len),
+				insl_ns(ioaddr+RX_FIFO, skb_put(skb,pkt_len),
 							   (pkt_len + 3) >> 2);
 #else
 				insl(ioaddr + RX_FIFO, skb_put(skb,pkt_len),
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/82596.c linux.15p9/drivers/net/82596.c
--- linux.vanilla/drivers/net/82596.c	Thu Jan  7 16:46:59 1999
+++ linux.15p9/drivers/net/82596.c	Wed Jan 12 01:16:34 2000
@@ -283,7 +283,7 @@
 		volatile u32 i = *(volatile u32 *) (dev->base_addr);
 	}
 #endif
-#ifdef CONFIG_APRICOT_i596
+#ifdef CONFIG_APRICOT
 	if (MACH_IS_APRICOT) {
 		outw(0, (short) (dev->base_addr) + 4);
 	}
@@ -444,7 +444,7 @@
 	if (MACH_IS_BVME6000)
 		lp->scp.sysbus = 0x0000004c;
 #endif
-#ifdef CONFIG_APRICOT_i596
+#ifdef CONFIG_APRICOT
 	if (MACH_IS_APRICOT)
 		lp->scp.sysbus = 0x00440000;
 #endif
@@ -914,7 +914,7 @@
 		dev->irq = (unsigned) BVME_IRQ_I596;
 	}
 #endif
-#ifdef CONFIG_APRICOT_INTEL
+#ifdef CONFIG_APRICOT
 	int checksum = 0;
 	int ioaddr = 0x300;
 
@@ -1163,7 +1163,7 @@
 		*ethirq = 3;
 	}
 #endif
-#ifdef CONFIG_APRICOT_INTEL
+#ifdef CONFIG_APRICOT
 	(void) inb(ioaddr + 0x10);
 	outb(4, ioaddr + 0xf);
 #endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/Config.in linux.15p9/drivers/net/Config.in
--- linux.vanilla/drivers/net/Config.in	Tue Jan  4 21:18:51 2000
+++ linux.15p9/drivers/net/Config.in	Wed Jan 26 23:15:27 2000
@@ -18,6 +18,7 @@
 endmenu
 
 tristate 'Dummy net driver support' CONFIG_DUMMY
+tristate 'Bonding driver support' CONFIG_BONDING
 tristate 'EQL (serial line load balancing) support' CONFIG_EQUALIZER
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
   if [ "$CONFIG_NETLINK" = "y" ]; then
@@ -278,6 +279,11 @@
 # There is no way to detect a Sealevel board. Force it modular
 #
 dep_tristate 'Sealevel Systems 4021 support' CONFIG_SEALEVEL_4021 m
+
+#
+# Lan Media's board. Currently 1000, 1200, 5200, 5245
+#
+tristate 'LanMedia Corp. SSI/V.35, T1/E1, HSSI, T3 boards' CONFIG_LANMEDIA
 
 #
 # COMX drivers
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/Makefile linux.15p9/drivers/net/Makefile
--- linux.vanilla/drivers/net/Makefile	Tue Jan  4 21:18:51 2000
+++ linux.15p9/drivers/net/Makefile	Wed Feb  9 17:09:22 2000
@@ -5,7 +5,7 @@
 
 SUB_DIRS     := 
 MOD_SUB_DIRS := $(SUB_DIRS)
-ALL_SUB_DIRS := $(SUB_DIRS) hamradio irda fc sk98lin
+ALL_SUB_DIRS := $(SUB_DIRS) hamradio irda fc sk98lin lmc
 
 L_TARGET := net.a
 L_OBJS   :=
@@ -366,6 +366,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_BONDING),y)
+L_OBJS += bonding.o
+else
+  ifeq ($(CONFIG_BONDING),m)
+  M_OBJS += bonding.o
+  endif
+endif
+
 ifeq ($(CONFIG_DE600),y)
 L_OBJS += de600.o
 else
@@ -847,6 +855,17 @@
   endif
 endif
 
+ifeq ($(CONFIG_LANMEDIA),y)
+  SUB_DIRS += lmc
+  MOD_IN_SUB_DIRS += lmc
+  L_OBJS += lmc/lmc.o
+  CONFIG_SYNCPPP_BUILTIN = y
+else
+  ifeq ($(CONFIG_LANMEDIA),m)
+  CONFIG_SYNCPPP_MODULE = y
+  MOD_IN_SUB_DIRS += lmc
+  endif
+endif
 
 ifeq ($(CONFIG_COSA),y)
 L_OBJS += cosa.o
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/Space.c linux.15p9/drivers/net/Space.c
--- linux.vanilla/drivers/net/Space.c	Tue Jan  4 21:18:51 2000
+++ linux.15p9/drivers/net/Space.c	Tue Jan 25 14:49:55 2000
@@ -120,7 +120,7 @@
 extern int tc515_probe(struct device *dev);
 extern int lance_probe(struct device *dev);
 extern int rcpci_probe(struct device *);
-extern int dmfe_reg_board(struct device *);
+extern int dmfe_probe(struct device *);
 
 /* Gigabit Ethernet adapters */
 extern int yellowfin_probe(struct device *dev);
@@ -146,6 +146,9 @@
 /* SBNI adapters */
 extern int sbni_probe(struct device *);
 
+/* WAN Adapters */
+extern int lmc_probe_fake(struct device *);
+
 struct devprobe
 {
 	int (*probe)(struct device *dev);
@@ -201,6 +204,9 @@
 #ifdef CONFIG_EEXPRESS_PRO100	/* Intel EtherExpress Pro/100 */
 	{eepro100_probe, 0},
 #endif
+#ifdef CONFIG_LANMEDIA          /* Lanmedia must be before Tulip */
+        {lmc_probe_fake, 0},
+#endif
 #if defined(CONFIG_DEC_ELCP) || defined(CONFIG_DEC_ELCP_OLD)
 	{tulip_probe, 0},
 #endif
@@ -221,7 +227,7 @@
 #endif
 
 #ifdef CONFIG_DM9102
-	{dmfe_reg_board, 0}, 
+	{dmfe_probe, 0}, 
 #endif
 
 #ifdef CONFIG_YELLOWFIN
@@ -237,7 +243,7 @@
 	{via_rhine_probe, 0},
 #endif
 #ifdef CONFI_NET_DM9102
-	{dmfe_reg_board, 0},
+	{dmfe_probe, 0},
 #endif	
 	{NULL, 0},
 };
@@ -621,6 +627,12 @@
     static struct device tap0_dev = { "tap0", 0, 0, 0, 0, NETLINK_TAPBASE, 0, 0, 0, 0, NEXT_DEV, ethertap_probe, };
 #   undef NEXT_DEV
 #   define NEXT_DEV	(&tap0_dev)
+#endif
+
+#ifdef CONFIG_LANMEDIA
+static struct device lmc_dev = { "lmc_dev", 0, 0, 0, 0, 0, 0, 0, 0, 0, NEXT_DEV, lmc_probe_fake, };
+#    undef NEXT_DEV
+#    define NEXT_DEV    (&lmc_dev)
 #endif
 
 #ifdef CONFIG_SDLA
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/bonding.c linux.15p9/drivers/net/bonding.c
--- linux.vanilla/drivers/net/bonding.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/net/bonding.c	Wed Jan 26 23:15:27 2000
@@ -0,0 +1,353 @@
+/*
+ * originally based on the dummy device.
+ *
+ * Copyright 1999, Thomas Davis, tadavis@lbl.gov.  
+ * Licensed under the GPL. Based on dummy.c, and eql.c devices.
+ *
+ * bond.c: a bonding/etherchannel/sun trunking net driver
+ *
+ * This is useful to talk to a Cisco 5500, running Etherchannel, aka:
+ *	Linux Channel Bonding
+ *	Sun Trunking (Solaris)
+ *
+ * How it works:
+ *    ifconfig bond0 ipaddress netmask up
+ *      will setup a network device, with an ip address.  No mac address 
+ *	will be assigned at this time.  The hw mac address will come from 
+ *	the first slave bonded to the channel.  All slaves will then use 
+ *	this hw mac address.
+ *
+ *    ifconfig bond0 down
+ *         will release all slaves, marking them as down.
+ *
+ *    ifenslave bond0 eth0
+ *	will attache eth0 to bond0 as a slave.  eth0 hw mac address will either
+ *	a: be used as initial mac address
+ *	b: if a hw mac address already is there, eth0's hw mac address 
+ *	   will then  be set from bond0.
+ *
+ * v0.1 - first working version.
+ * v0.2 - changed stats to be calculated by summing slaves stats.
+ * 
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/uaccess.h>
+#include <linux/errno.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#include <linux/if_bonding.h>
+
+static int bond_xmit(struct sk_buff *skb, struct device *dev);
+static struct net_device_stats *bond_get_stats(struct device *dev);
+
+static int bond_open(struct device *dev)
+{
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static int bond_close(struct device *master)
+{
+	bonding_t *private = (struct bonding *) master->priv;
+	slave_queue_t *queue = (struct slave_queue *) private->queue;
+	slave_t *slave, *next;
+
+	for( slave=queue->head; slave != NULL; slave=next) {
+#ifdef BONDING_DEBUG
+		printk("freeing = %s\n", slave->dev->name);
+#endif
+		slave->dev->flags &= ~IFF_SLAVE;
+		slave->dev->slave = NULL;
+		next = slave->next;
+		kfree(slave);
+		queue->num_slaves++;
+	}
+
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+/* fake multicast ability */
+static void set_multicast_list(struct device *dev)
+{
+}
+
+static int bond_enslave(struct device *master, struct device *slave)
+{
+	bonding_t *private = (struct bonding *) master->priv;
+	slave_queue_t *queue = (struct slave_queue *) private->queue;
+	slave_t *new_slave;
+	int flags;
+	
+	if (master == NULL || slave == NULL) 
+		return -ENODEV;
+
+#ifdef BONDING_DEBUG
+	printk (KERN_WARNING "%s: enslaving '%s'\n", master->name, slave->name);
+#endif
+
+	save_flags(flags);
+	cli();
+
+	/* not running. */
+	if ((slave->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
+		restore_flags(flags);
+		return -EINVAL;
+	}
+
+	/* already enslaved */
+	if (master->flags & IFF_SLAVE || slave->flags & IFF_SLAVE) {
+		restore_flags(flags);
+		return -EBUSY;
+	}
+		   
+	slave->slave = master;     /* save the master in slave->slave */
+	slave->flags |= IFF_SLAVE;
+
+	if ((new_slave = kmalloc(sizeof(slave_t), GFP_KERNEL)) == NULL) {
+		return -ENOMEM;
+	}
+	memset(new_slave, 0, sizeof(slave_t));
+
+	new_slave->dev = slave;
+
+	if (queue->head == NULL) {
+		queue->head = new_slave;
+		queue->current_slave = queue->head;
+	} else {
+		queue->tail->next = new_slave;
+	}
+
+	queue->tail = new_slave;
+	queue->num_slaves++;
+
+	restore_flags(flags);
+
+	return 0;
+}
+
+static int bond_release(struct device *master, struct device *slave)
+{
+	printk (KERN_DEBUG "%s: releasing `%s`\n", master->name, slave->name);
+
+	return -EINVAL;
+}
+
+static int bond_sethwaddr(struct device *master, struct device *slave)
+{
+	memcpy(master->dev_addr, slave->dev_addr, slave->addr_len);
+	return 0;
+}
+
+static int bond_ioctl(struct device *master, struct ifreq *ifr, int cmd)
+{
+	struct device *slave = dev_get(ifr->ifr_slave);
+
+#ifdef BONDING_DEBUG
+	printk("master=%s, slave=%s\n", master->name, slave->name);
+#endif
+
+	switch (cmd) {
+	case BOND_ENSLAVE:
+		return bond_enslave(master, slave);
+	case BOND_RELEASE:
+		return bond_release(master, slave);
+	case BOND_SETHWADDR:
+		return bond_sethwaddr(master, slave);
+	default:
+			return -EOPNOTSUPP;
+	}
+}
+
+#ifdef CONFIG_NET_FASTROUTE
+static int bond_accept_fastpath(struct device *dev, struct dst_entry *dst)
+{
+	return -1;
+}
+#endif
+
+__initfunc(int bond_init(struct device *dev))
+{
+	bonding_t *bond;
+
+	/* Initialize the device structure. */
+	dev->hard_start_xmit = bond_xmit;
+
+	dev->priv = kmalloc(sizeof(struct bonding), GFP_KERNEL);
+	if (dev->priv == NULL)
+		return -ENOMEM;
+
+	memset(dev->priv, 0, sizeof(struct bonding));
+
+	bond = (struct bonding *) dev->priv;
+
+	bond->queue = kmalloc(sizeof(struct slave_queue), GFP_KERNEL);
+	if (bond->queue == NULL)
+		return -ENOMEM;
+
+	memset(bond->queue, 0, sizeof(struct slave_queue));
+
+	bond->stats = kmalloc(sizeof(struct enet_statistics), GFP_KERNEL);
+	if (bond->stats == NULL)
+		return -ENOMEM;
+
+	memset(bond->stats, 0, sizeof(struct enet_statistics));
+
+	dev->get_stats	= bond_get_stats;
+
+	dev->open = bond_open;
+	dev->stop = bond_close;
+	dev->set_multicast_list = set_multicast_list;
+
+	dev->do_ioctl = bond_ioctl;
+
+	/* Fill in the fields of the device structure with ethernet-generic 
+	   values. */
+	ether_setup(dev);
+	dev->tx_queue_len = 0;
+	dev->flags |= (IFF_MASTER|IFF_MULTICAST);
+#ifdef CONFIG_NET_FASTROUTE
+	dev->accept_fastpath = bond_accept_fastpath;
+#endif
+
+	return 0;
+}
+
+static int bond_xmit(struct sk_buff *skb, struct device *dev)
+{
+	struct device *slave;
+	struct bonding *bond = (struct bonding *) dev->priv;
+	struct slave_queue *queue = bond->queue;
+	int good = 0;
+	
+	while (good == 0) {
+		slave = queue->current_slave->dev;
+		if (slave->flags & (IFF_UP|IFF_RUNNING)) {
+			skb->dev = slave;
+			skb->priority = 1;
+			dev_queue_xmit(skb);
+			good = 1;
+		}
+		if (queue->current_slave->next != NULL) {
+			queue->current_slave = queue->current_slave->next;
+		} else {
+			queue->current_slave = queue->head;
+		}
+	}
+
+	return 0;
+}
+
+static struct net_device_stats *bond_get_stats(struct device *dev)
+{
+	bonding_t *private = dev->priv;
+	slave_queue_t *queue = private->queue;
+	struct net_device_stats *stats = private->stats, *sstats;
+	slave_t *slave;
+	
+	memset(private->stats, 0, sizeof(struct net_device_stats));
+	for (slave=queue->head; slave != NULL; slave=slave->next) {
+		sstats = slave->dev->get_stats(slave->dev);
+ 
+		stats->rx_packets += sstats->rx_packets;
+		stats->rx_bytes += sstats->rx_bytes;
+		stats->rx_errors += sstats->rx_errors;
+		stats->rx_dropped += sstats->rx_dropped;
+
+		stats->tx_packets += sstats->tx_packets;
+		stats->tx_bytes += sstats->tx_bytes;
+		stats->tx_errors += sstats->tx_errors;
+		stats->tx_dropped += sstats->tx_dropped;
+
+		stats->multicast += sstats->multicast;
+		stats->collisions += sstats->collisions;
+
+		stats->rx_length_errors += sstats->rx_length_errors;
+		stats->rx_over_errors += sstats->rx_over_errors;
+		stats->rx_crc_errors += sstats->rx_crc_errors;
+		stats->rx_frame_errors += sstats->rx_frame_errors;
+		stats->rx_fifo_errors += sstats->rx_fifo_errors;	
+		stats->rx_missed_errors += sstats->rx_missed_errors;
+	
+		stats->tx_aborted_errors += sstats->tx_aborted_errors;
+		stats->tx_carrier_errors += sstats->tx_carrier_errors;
+		stats->tx_fifo_errors += sstats->tx_fifo_errors;
+		stats->tx_heartbeat_errors += sstats->tx_heartbeat_errors;
+		stats->tx_window_errors += sstats->tx_window_errors;
+
+	}
+
+	return stats;
+}
+
+#ifdef MODULE
+
+__initfunc(static int bond_probe(struct device *dev))
+{
+	bond_init(dev);
+	return 0;
+}
+
+static char bond_name[16];
+
+static struct device dev_bond = {
+		bond_name, 	/* Needs to be writeable */
+		0, 0, 0, 0,
+	 	0x0, 0,
+	 	0, 0, 0, NULL, bond_probe };
+
+int init_module(void)
+{
+	/* Find a name for this unit */
+	int err=dev_alloc_name(&dev_bond,"bond%d");
+
+	if (err<0)
+		return err;
+
+	if (register_netdev(&dev_bond) != 0)
+		return -EIO;
+
+	return 0;
+}
+
+void cleanup_module(void)
+{
+	struct bonding *bond = (struct bonding *) dev_bond.priv;
+
+	unregister_netdev(&dev_bond);
+
+	kfree(bond->queue);
+	kfree(bond->stats);
+	kfree(dev_bond.priv);
+
+	dev_bond.priv = NULL;
+}
+#endif /* MODULE */
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/dmfe.c linux.15p9/drivers/net/dmfe.c
--- linux.vanilla/drivers/net/dmfe.c	Wed Oct 20 01:12:38 1999
+++ linux.15p9/drivers/net/dmfe.c	Tue Jan 25 14:49:55 2000
@@ -1,15 +1,26 @@
 /*
-   dmfe.c: Version 1.26
+   dmfe.c: Version 1.28 01/18/2000
 
-   A Davicom DM9102 fast ethernet driver for Linux. 
+   A Davicom DM9102(A)/DM9132/DM9801 fast ethernet driver for Linux. 
+   Copyright (C) 1997  Sten Wang
+
+   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.
 
-   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, version 1.
 
    Compiler command:
    "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall 
-		-Wstrict-prototypes -O6 -c dmfe.c"
+   -Wstrict-prototypes -O6 -c dmfe.c"
+   OR
+   "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net -Wall 
+   -Wstrict-prototypes -O6 -c dmfe.c"
 
    The following steps teach you how to active DM9102 board:
    1. Used the upper compiler command to compile dmfe.c
@@ -21,35 +32,22 @@
    "insmod dmfe mode=5" ;;Force 100M Full Duplex
    3. config a dm9102 network interface
    "ifconfig eth0 172.22.3.18"
+   ^^^^^^^^^^^ your IP address
    4. active the IP routing table
    "route add -net 172.22.3.0 eth0"
    5. Well done. Your DM9102 adapter actived now.
 
-   Author: Sten Wang, E-mail: sten_wang@davicom.com.tw
+   Author: Sten Wang, 886-3-5798797-8517, E-mail: sten_wang@davicom.com.tw
 
    Date:   10/28,1998
 
-   (C)Copyright 1997-1998 DAVICOM Semiconductor, Inc. All Rights Reserved.
-
-   Marcelo Tosatti <marcelo@conectiva.com.br> : 
-   Made it compile in 2.3 (device to net_device)
-   
-   Alan Cox <alan@redhat.com> :
-   Removed the back compatibility support
-   Reformatted, fixing spelling etc as I went
-   Removed IRQ 0-15 assumption
+   (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved.
    
-   TODO
-   
-   Check and fix on 64bit and big endian boxes.
-   Sort out the PCI latency.
+   Cleaned up for kernel merge by Alan Cox (alan@redhat.com)
    
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/version.h>
-
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/string.h>
@@ -60,38 +58,41 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-
 #include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
 #include <asm/processor.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-
+#include <linux/version.h>
 
 /* Board/System/Debug information/definition ---------------- */
+#define PCI_DM9132_ID   0x91321282	/* Davicom DM9132 ID */
 #define PCI_DM9102_ID   0x91021282	/* Davicom DM9102 ID */
 #define PCI_DM9100_ID   0x91001282	/* Davicom DM9100 ID */
 
 #define DMFE_SUCC       0
 #define DM9102_IO_SIZE  0x80
-#define TX_FREE_DESC_CNT 0x1	/* Tx packet count */
+#define DM9102A_IO_SIZE 0x100
+#define TX_FREE_DESC_CNT 0xc	/* Tx packet count */
+#define TX_MAX_SEND_CNT 0x1	/* Maximum tx packet per time */
 #define TX_DESC_CNT     0x10	/* Allocated Tx descriptors */
 #define RX_DESC_CNT     0x10	/* Allocated Rx descriptors */
 #define DESC_ALL_CNT    TX_DESC_CNT+RX_DESC_CNT
 #define TX_BUF_ALLOC    0x600
 #define RX_ALLOC_SIZE   0x620
 #define DM910X_RESET    1
-#define CR6_DEFAULT     0x002c0000	/* SF, MII, HD */
+#define CR6_DEFAULT     0x00280000	/* SF, HD */
 #define CR7_DEFAULT     0x1a2cd
 #define CR15_DEFAULT    0x06	/* TxJabber RxWatchdog */
 #define TDES0_ERR_MASK  0x4302	/* TXJT, LC, EC, FUE */
 #define MAX_PACKET_SIZE 1514
 #define DMFE_MAX_MULTICAST 14
-#define RX_MAX_TRAFFIC 0x5000
+#define RX_MAX_TRAFFIC  0x14000
 #define MAX_CHECK_PACKET 0x8000
 
 #define DMFE_10MHF      0
@@ -100,8 +101,8 @@
 #define DMFE_100MFD     5
 #define DMFE_AUTO       8
 
-#define DMFE_TIMER_WUT  jiffies+HZ*1	/* timer wakeup time : 1 second */
-#define DMFE_TX_TIMEOUT HZ*2	/* tx packet time-out time */
+#define DMFE_TIMER_WUT  jiffies+(HZ*2)/2	/* timer wakeup time : 1 second */
+#define DMFE_TX_TIMEOUT HZ*1.5	/* tx packet time-out time 1.5 s" */
 
 #define DMFE_DBUG(dbug_now, msg, vaule) if (dmfe_debug || dbug_now) printk("DBUG: %s %x\n", msg, vaule)
 
@@ -109,7 +110,7 @@
 
 #define DELAY_1US udelay(1)	/* udelay scale 1 usec */
 
-#define SHOW_MEDIA_TYPE(mode) printk("\n<WARN> Change Speed to %sMhz %s duplex\n",mode & 1 ?"100":"10", mode & 4 ? "full":"half");
+#define SHOW_MEDIA_TYPE(mode) printk(KERN_WARNING "dmfe: Change Speed to %sMhz %s duplex\n",mode & 1 ?"100":"10", mode & 4 ? "full":"half");
 
 
 /* CR9 definition: SROM/MII */
@@ -125,9 +126,8 @@
 
 #define SROM_CLK_WRITE(data, ioaddr) outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr);DELAY_5US;outl(data|CR9_SROM_READ|CR9_SRCS|CR9_SRCLK,ioaddr);DELAY_5US;outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr);DELAY_5US;
 
-#if LINUX_VERSION_CODE < 0x20123
-#define test_and_set_bit(val, addr) set_bit(val, addr)
-#endif
+#define CHK_IO_SIZE(pci_id, dev_rev) ( (pci_id==PCI_DM9132_ID) || (dev_rev >= 0x02000030) ) ? DM9102A_IO_SIZE: DM9102_IO_SIZE
+
 
 /* Structure/enum declaration ------------------------------- */
 struct tx_desc {
@@ -153,13 +153,14 @@
 
 	struct pci_dev *net_dev;	/* PCI device */
 
-	u32 ioaddr;		/* I/O base address */
+	unsigned long ioaddr;		/* I/O base address */
+	u32 cr0_data;
 	u32 cr5_data;
 	u32 cr6_data;
 	u32 cr7_data;
 	u32 cr15_data;
-
-/* descriptor pointer */
+	
+	/* descriptor pointer */
 	unsigned char *buf_pool_ptr;	/* Tx buffer pool memory */
 	unsigned char *buf_pool_start;	/* Tx buffer pool align dword */
 	unsigned char *desc_pool_ptr;	/* descriptor pool memory */
@@ -170,9 +171,12 @@
 	struct rx_desc *rx_insert_ptr;
 	struct rx_desc *rx_ready_ptr;	/* packet come pointer */
 	u32 tx_packet_cnt;	/* transmitted packet count */
+	u32 tx_queue_cnt;	/* wait to send packet count */
 	u32 rx_avail_cnt;	/* available rx descriptor count */
 	u32 interval_rx_cnt;	/* rx packet count a callback time */
 
+	u16 phy_id2;		/* Phyxcer ID2 */
+
 	u8 media_mode;		/* user specify media mode */
 	u8 op_mode;		/* real work media mode */
 	u8 phy_addr;
@@ -194,14 +198,14 @@
 
 enum dmfe_CR6_bits {
 	CR6_RXSC = 0x2, CR6_PBF = 0x8, CR6_PM = 0x40, CR6_PAM = 0x80, CR6_FDM = 0x200,
-	CR6_TXSC = 0x2000, CR6_STI = 0x100000, CR6_SFT = 0x200000, CR6_RXA = 0x40000000
+	CR6_TXSC = 0x2000, CR6_STI = 0x100000, CR6_SFT = 0x200000, CR6_RXA = 0x40000000,
+	CR6_NO_PURGE = 0x20000000
 };
 
 /* Global variable declaration ----------------------------- */
-
 static int dmfe_debug = 0;
 static unsigned char dmfe_media_mode = 8;
-static struct device *dmfe_root_dev = NULL;		/* First device */
+static struct device *dmfe_root_dev = NULL;	/* First device */
 static u32 dmfe_cr6_user_set = 0;
 
 /* For module input parameter */
@@ -210,7 +214,7 @@
 static unsigned char mode = 8;
 static u8 chkmode = 1;
 
-unsigned long CrcTable[256] =
+static unsigned long CrcTable[256] =
 {
 	0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL,
 	0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L,
@@ -279,7 +283,7 @@
 };
 
 /* function declaration ------------------------------------- */
-int dmfe_reg_board(struct device *);
+int dmfe_probe(struct device *);
 static int dmfe_open(struct device *);
 static int dmfe_start_xmit(struct sk_buff *, struct device *);
 static int dmfe_stop(struct device *);
@@ -292,11 +296,11 @@
 static void allocated_rx_buffer(struct dmfe_board_info *);
 static void update_cr6(u32, u32);
 static void send_filter_frame(struct device *, int);
-static u16 phy_read(u32, u8, u8);
-static void phy_write(u32, u8, u8, u16);
+static void dm9132_id_table(struct device *, int);
+static u16 phy_read(u32, u8, u8, u32);
+static void phy_write(u32, u8, u8, u16, u32);
 static void phy_write_1bit(u32, u32);
 static u16 phy_read_1bit(u32);
-static void parser_ctrl_info(struct dmfe_board_info *);
 static void dmfe_sense_speed(struct dmfe_board_info *);
 static void dmfe_process_mode(struct dmfe_board_info *);
 static void dmfe_timer(unsigned long);
@@ -305,17 +309,16 @@
 static void dmfe_dynamic_reset(struct device *);
 static void dmfe_free_rxbuffer(struct dmfe_board_info *);
 static void dmfe_init_dm910x(struct device *);
-static unsigned long cal_CRC(unsigned char *, unsigned int);
+static unsigned long cal_CRC(unsigned char *, unsigned int, u8);
 
-/* DM910X network board routine ---------------------------- */
+/* DM910X network baord routine ---------------------------- */
 
 /*
- *	Search DM910X board, allocate space and register it
+   Search DM910X board ,allocate space and register it
  */
- 
-int dmfe_reg_board(struct device *dev)
+int dmfe_probe(struct device *dev)
 {
-	u32 pci_iobase;
+	unsigned long pci_iobase;
 	u16 dm9102_count = 0;
 	u8 pci_irqline;
 	static int index = 0;	/* For multiple call */
@@ -323,7 +326,7 @@
 	int i;
 	struct pci_dev *net_dev = NULL;
 
-	DMFE_DBUG(0, "dmfe_reg_board()", 0);
+	DMFE_DBUG(0, "dmfe_probe()", 0);
 
 	if (!pci_present())
 		return -ENODEV;
@@ -332,39 +335,43 @@
 	while ((net_dev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, net_dev)))
 	{
 		u32 pci_id;
+		u32 dev_rev;
 		u8 pci_cmd;
 
 		index++;
 		if (pci_read_config_dword(net_dev, PCI_VENDOR_ID, &pci_id) != DMFE_SUCC)
 			continue;
 
-		if (pci_id != PCI_DM9102_ID)
+		if ((pci_id != PCI_DM9102_ID) && (pci_id != PCI_DM9132_ID))
 			continue;
 
-		pci_iobase = net_dev->base_address[0] & ~3;
-		pci_irqline = net_dev->irq;
-				
+		/* read PCI IO base address and IRQ to check */
+		pci_read_config_dword(net_dev, PCI_BASE_ADDRESS_0, &pci_iobase);
+		pci_read_config_byte(net_dev, PCI_INTERRUPT_LINE, &pci_irqline);
+		pci_iobase &= ~0x7f;	/* mask off bit0~6 */
+
 		/* Enable Master/IO access, Disable memory access */
-		
-		pci_set_master(net_dev);
-		
 		pci_read_config_byte(net_dev, PCI_COMMAND, &pci_cmd);
-		pci_cmd |= PCI_COMMAND_IO;
+		pci_cmd |= PCI_COMMAND_IO + PCI_COMMAND_MASTER;
 		pci_cmd &= ~PCI_COMMAND_MEMORY;
 		pci_write_config_byte(net_dev, PCI_COMMAND, pci_cmd);
 
 		/* Set Latency Timer 80h */
-		
-		/* FIXME: setting values > 32 breaks some SiS 559x stuff.
-		   Need a PCI quirk.. */
-		   
 		pci_write_config_byte(net_dev, PCI_LATENCY_TIMER, 0x80);
 
-		/* IO range and interrupt check */
+		/* Read Chip revesion */
+		pci_read_config_dword(net_dev, 8, &dev_rev);
 
-		if (check_region(pci_iobase, DM9102_IO_SIZE))	/* IO range check */
+		/* IO range check */
+		if (check_region(pci_iobase, CHK_IO_SIZE(pci_id, dev_rev))) {
+			printk(KERN_ERR "dmfe: I/O conflict : IO=%x Range=%x\n", pci_iobase, CHK_IO_SIZE(pci_id, dev_rev));
 			continue;
-
+		}
+		/* Interrupt check */
+		if (pci_irqline == 0) {
+			printk(KERN_ERR "dmfe: Interrupt wrong : IRQ=%d\n", pci_irqline);
+			continue;
+		}
 		/* Found DM9102 card and PCI resource allocated OK */
 		dm9102_count++;	/* Found a DM9102 card */
 
@@ -373,9 +380,6 @@
 
 		/* Allocated board information structure */
 		db = (void *) (kmalloc(sizeof(*db), GFP_KERNEL | GFP_DMA));
-		if(db==NULL)
-			continue;	/* Out of memory */
-			
 		memset(db, 0, sizeof(*db));
 		dev->priv = db;	/* link device and board info */
 		db->next_dev = dmfe_root_dev;
@@ -383,7 +387,7 @@
 
 		db->chip_id = pci_id;	/* keep Chip vandor/Device ID */
 		db->ioaddr = pci_iobase;
-		pci_read_config_dword(net_dev, 8, &db->chip_revesion);
+		db->chip_revesion = dev_rev;
 
 		db->net_dev = net_dev;
 
@@ -396,7 +400,7 @@
 		dev->set_multicast_list = &dmfe_set_filter_mode;
 		dev->do_ioctl = &dmfe_do_ioctl;
 
-		request_region(pci_iobase, DM9102_IO_SIZE, dev->name);
+		request_region(pci_iobase, CHK_IO_SIZE(pci_id, dev_rev), dev->name);
 
 		/* read 64 word srom data */
 		for (i = 0; i < 64; i++)
@@ -408,19 +412,13 @@
 
 		dev = 0;	/* NULL device */
 	}
-
-#ifdef MODULE
-	if (!dm9102_count)
-		printk(KERN_WARNING "dmfe: Can't find DM910X board\n");
-#endif		
 	return dm9102_count ? 0 : -ENODEV;
 }
 
 /*
- *	Open the interface.
- *	The interface is opened whenever "ifconfig" actives it.
+   Open the interface.
+   The interface is opened whenever "ifconfig" actives it.
  */
- 
 static int dmfe_open(struct device *dev)
 {
 	struct dmfe_board_info *db = dev->priv;
@@ -434,20 +432,17 @@
 	db->desc_pool_ptr = kmalloc(sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20, GFP_KERNEL | GFP_DMA);
 	if (db->desc_pool_ptr == NULL)
 		return -ENOMEM;
-
 	if ((u32) db->desc_pool_ptr & 0x1f)
 		db->first_tx_desc = (struct tx_desc *) (((u32) db->desc_pool_ptr & ~0x1f) + 0x20);
 	else
 		db->first_tx_desc = (struct tx_desc *) db->desc_pool_ptr;
 
 	/* Allocated Tx buffer memory */
-	
 	db->buf_pool_ptr = kmalloc(TX_BUF_ALLOC * TX_DESC_CNT + 4, GFP_KERNEL | GFP_DMA);
 	if (db->buf_pool_ptr == NULL) {
 		kfree(db->desc_pool_ptr);
 		return -ENOMEM;
 	}
-	
 	if ((u32) db->buf_pool_ptr & 0x3)
 		db->buf_pool_start = (char *) (((u32) db->buf_pool_ptr & ~0x3) + 0x4);
 	else
@@ -456,16 +451,21 @@
 	/* system variable init */
 	db->cr6_data = CR6_DEFAULT | dmfe_cr6_user_set;
 	db->tx_packet_cnt = 0;
+	db->tx_queue_cnt = 0;
 	db->rx_avail_cnt = 0;
 	db->link_failed = 0;
 	db->wait_reset = 0;
 	db->in_reset_state = 0;
 	db->rx_error_cnt = 0;
 
-	if (chkmode && (db->chip_revesion < 0x02000030)) {
-		db->dm910x_chk_mode = 1;	/* Enter the check mode */
-	} else {
+	if (!chkmode || (db->chip_id == PCI_DM9132_ID) || (db->chip_revesion >= 0x02000030)) {
+		//db->cr6_data &= ~CR6_SFT;         /* Used Tx threshold */
+		//db->cr6_data |= CR6_NO_PURGE;     /* No purge if rx unavailable */
+		db->cr0_data = 0xc00000;	/* TX/RX desc burst mode */
 		db->dm910x_chk_mode = 4;	/* Enter the normal mode */
+	} else {
+		db->cr0_data = 0;
+		db->dm910x_chk_mode = 1;	/* Enter the check mode */
 	}
 
 	/* Initilize DM910X board */
@@ -486,14 +486,12 @@
 	return 0;
 }
 
-/*
- *	Initialize DM910X board
- *	Reset DM910X board
- *	Initialize TX/Rx descriptor chain structure
- *	Send the set-up frame
- *	Enable Tx/Rx machine
+/* Initilize DM910X board
+   Reset DM910X board
+   Initilize TX/Rx descriptor chain structure
+   Send the set-up frame
+   Enable Tx/Rx machine
  */
- 
 static void dmfe_init_dm910x(struct device *dev)
 {
 	struct dmfe_board_info *db = dev->priv;
@@ -502,16 +500,18 @@
 	DMFE_DBUG(0, "dmfe_init_dm910x()", 0);
 
 	/* Reset DM910x board : need 32 PCI clock to complete */
-	outl(DM910X_RESET, ioaddr + DCR0);
+	outl(DM910X_RESET, ioaddr + DCR0);	/* RESET MAC */
 	DELAY_5US;
-	outl(0, ioaddr + DCR0);
+	outl(db->cr0_data, ioaddr + DCR0);
 
 	outl(0x180, ioaddr + DCR12);	/* Let bit 7 output port */
-	outl(0x80, ioaddr + DCR12);	/* Reset DM9102 phyxcer */
+	outl(0x80, ioaddr + DCR12);	/* RESET DM9102 phyxcer */
 	outl(0x0, ioaddr + DCR12);	/* Clear RESET signal */
 
-	/* Parser control information: Phy addr */
-	parser_ctrl_info(db);
+	/* Phy addr : DM910(A)2/DM9132/9801, phy address = 1 */
+	db->phy_addr = 1;
+
+	/* Media Mode Check */
 	db->media_mode = dmfe_media_mode;
 	if (db->media_mode & DMFE_AUTO)
 		dmfe_sense_speed(db);
@@ -526,7 +526,10 @@
 	update_cr6(db->cr6_data, ioaddr);
 
 	/* Send setup frame */
-	send_filter_frame(dev, 0);
+	if (db->chip_id == PCI_DM9132_ID)
+		dm9132_id_table(dev, dev->mc_count);	/* DM9132 */
+	else
+		send_filter_frame(dev, dev->mc_count);	/* DM9102/DM9102A */
 
 	/* Init CR5/CR7, interrupt active bit */
 	outl(0xffffffff, ioaddr + DCR5);	/* clear all CR5 status */
@@ -545,10 +548,9 @@
 
 
 /*
- *	Hardware start transmission.
- *	Send a packet to media from the upper layer.
+   Hardware start transmission.
+   Send a packet to media from the upper layer.
  */
- 
 static int dmfe_start_xmit(struct sk_buff *skb, struct device *dev)
 {
 	struct dmfe_board_info *db = dev->priv;
@@ -556,58 +558,54 @@
 
 	DMFE_DBUG(0, "dmfe_start_xmit", 0);
 
-	if ((dev->tbusy == 1) && (db->tx_packet_cnt != 0))
+	/* Resource flag check */
+	if (dev->tbusy == 1)	/* Resource Busy */
 		return 1;
-	else
-		dev->tbusy = 0;
 
 	/* Too large packet check */
 	if (skb->len > MAX_PACKET_SIZE) {
-		printk(KERN_ERR "%s: oversized frame received (%d bytes).\n", dev->name, (u16) skb->len);
+		printk(KERN_WARNING "%s: big packet, size=%d\n", dev->name, (u16) skb->len);
 		dev_kfree_skb(skb);
 		return 0;
 	}
-	/* No Tx resource check, it never happen nromally */
-	if (db->tx_packet_cnt >= TX_FREE_DESC_CNT) {
-		printk(KERN_WARNING "%s: No Tx resource, enter xmit() again \n", dev->name);
+	/* No Tx resource check, it never happen normally */
+	if (db->tx_queue_cnt >= TX_FREE_DESC_CNT) {
 		dev_kfree_skb(skb);
 		dev->tbusy = 1;
 		return -EBUSY;
 	}
-
 	/* transmit this packet */
 	txptr = db->tx_insert_ptr;
 	memcpy((char *) txptr->tx_buf_ptr, (char *) skb->data, skb->len);
 	txptr->tdes1 = 0xe1000000 | skb->len;
-	txptr->tdes0 = 0x80000000;	/* set owner bit to DM910X */
 
 	/* Point to next transmit free descriptor */
 	db->tx_insert_ptr = (struct tx_desc *) txptr->next_tx_desc;
 
-	/* transmit counter increase 1 */
-	db->tx_packet_cnt++;
-	db->stats.tx_packets++;
-
-	/* issue Tx polling command */
-	outl(0x1, dev->base_addr + DCR1);
+	/* Transmit Packet Process */
+	if (db->tx_packet_cnt < TX_MAX_SEND_CNT) {
+		txptr->tdes0 = 0x80000000;	/* set owner bit to DM910X */
+		db->tx_packet_cnt++;	/* Ready to send count */
+		outl(0x1, dev->base_addr + DCR1);	/* Issue Tx polling comand */
+		dev->trans_start = jiffies;	/* saved the time stamp */
+	} else {
+		db->tx_queue_cnt++;	/* queue the tx packet */
+		outl(0x1, dev->base_addr + DCR1);	/* Issue Tx polling comand */
+	}
 
 	/* Tx resource check */
-	if (db->tx_packet_cnt >= TX_FREE_DESC_CNT)
+	if (db->tx_queue_cnt >= TX_FREE_DESC_CNT) {
 		dev->tbusy = 1;
-
-	/* Set transmit time stamp */
-	dev->trans_start = jiffies;	/* saved the time stamp */
-
+	}
 	/* free this SKB */
 	dev_kfree_skb(skb);
 	return 0;
 }
 
 /*
- *	Stop the interface.
- *	The interface is stopped when it is brought.
+   Stop the interface.
+   The interface is stopped when it is brought.
  */
-
 static int dmfe_stop(struct device *dev)
 {
 	struct dmfe_board_info *db = dev->priv;
@@ -642,8 +640,8 @@
 }
 
 /*
- *	DM9102 insterrupt handler
- *	receive the packet to upper layer, free the transmitted packet
+   DM9102 insterrupt handler
+   receive the packet to upper layer, free the transmitted packet
  */
 
 static void dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -661,7 +659,6 @@
 		DMFE_DBUG(1, "dmfe_interrupt() re-entry ", 0);
 		return;
 	}
-
 	/* A real interrupt coming */
 	dev->interrupt = 1;	/* Lock interrupt */
 	db = (struct dmfe_board_info *) dev->priv;
@@ -669,22 +666,22 @@
 
 	DMFE_DBUG(0, "dmfe_interrupt()", 0);
 
-	/* Disable all interrupt in CR7 to solve the interrupt edge problem */
+/* Disable all interrupt in CR7 to solve the interrupt edge problem */
 	outl(0, ioaddr + DCR7);
 
-	/* Got DM910X status */
+/* Got DM910X status */
 	db->cr5_data = inl(ioaddr + DCR5);
 	outl(db->cr5_data, ioaddr + DCR5);
 	/* printk("CR5=%x\n", db->cr5_data); */
 
 	/* Check system status */
 	if (db->cr5_data & 0x2000) {
-		/* A system bus error occurred */
-		DMFE_DBUG(1, "A system bus error occurred. CR5=", db->cr5_data);
+		/* system bus error happen */
+		DMFE_DBUG(1, "System bus error happen. CR5=", db->cr5_data);
 		dev->tbusy = 1;
-		db->wait_reset = 1;		/* Need to RESET */
+		db->wait_reset = 1;	/* Need to RESET */
 		outl(0, ioaddr + DCR7);		/* disable all interrupt */
-		dev->interrupt = 0;		/* unlock interrupt */
+		dev->interrupt = 0;	/* unlock interrupt */
 		return;
 	}
 	/* Free the transmitted descriptor */
@@ -693,17 +690,36 @@
 		/* printk("tdes0=%x\n", txptr->tdes0); */
 		if (txptr->tdes0 & 0x80000000)
 			break;
-		if ((txptr->tdes0 & TDES0_ERR_MASK) && (txptr->tdes0 != 0x7fffffff)) {
+
+		/* A packet sent completed */
+		db->stats.tx_packets++;
+
+		/* Transmit statistic counter */
+		if (txptr->tdes0 != 0x7fffffff) {
 			/* printk("tdes0=%x\n", txptr->tdes0); */
-			db->stats.tx_errors++;
+			db->stats.collisions += (txptr->tdes0 >> 3) & 0xf;
+			db->stats.tx_bytes += txptr->tdes1 & 0x7ff;
+			if (txptr->tdes0 & TDES0_ERR_MASK)
+				db->stats.tx_errors++;
 		}
 		txptr = (struct tx_desc *) txptr->next_tx_desc;
 		db->tx_packet_cnt--;
-	}
+	}			/* End of while */
+
+	/* Update TX remove pointer to next */
 	db->tx_remove_ptr = (struct tx_desc *) txptr;
 
-	if (dev->tbusy && (db->tx_packet_cnt < TX_FREE_DESC_CNT)) {
-		dev->tbusy = 0;		/* free a resource */
+	/* Send the Tx packet in queue */
+	if ((db->tx_packet_cnt < TX_MAX_SEND_CNT) && db->tx_queue_cnt) {
+		txptr->tdes0 = 0x80000000;	/* set owner bit to DM910X */
+		db->tx_packet_cnt++;	/* Ready to send count */
+		outl(0x1, ioaddr + DCR1);	/* Issue Tx polling command */
+		dev->trans_start = jiffies;	/* saved the time stamp */
+		db->tx_queue_cnt--;
+	}
+	/* Resource available check */
+	if (dev->tbusy && (db->tx_queue_cnt < TX_FREE_DESC_CNT)) {
+		dev->tbusy = 0;	/* free a resource */
 		mark_bh(NET_BH);	/* active bottom half */
 	}
 	/* Received the coming packet */
@@ -723,7 +739,6 @@
 	dev->interrupt = 0;	/* release interrupt lock */
 
 	/* Restore CR7 to enable interrupt mask */
-	
 	if (db->interval_rx_cnt > RX_MAX_TRAFFIC)
 		db->cr7_data = 0x1a28d;
 	else
@@ -732,9 +747,8 @@
 }
 
 /*
- *	Receive the come packet and pass to upper layer
+   Receive the come packet and pass to upper layer
  */
- 
 static void dmfe_rx_packet(struct device *dev, struct dmfe_board_info *db)
 {
 	struct rx_desc *rxptr;
@@ -755,11 +769,11 @@
 			/* reused this SKB */
 			DMFE_DBUG(0, "Reused SK buffer, rdes0", rxptr->rdes0);
 			dmfe_reused_skb(db, (struct sk_buff *) rxptr->rx_skb_ptr);
-			db->rx_error_cnt++;
+			/* db->rx_error_cnt++; */
 		} else {
+			/* A packet with First/Last flag */
 			rxlen = ((rxptr->rdes0 >> 16) & 0x3fff) - 4;	/* skip CRC */
 
-			/* A packet with First/Last flag */
 			if (rxptr->rdes0 & 0x8000) {	/* error summary bit check */
 				/* This is a error packet */
 				/* printk("rdes0 error : %x \n", rxptr->rdes0); */
@@ -776,7 +790,7 @@
 				skb = (struct sk_buff *) rxptr->rx_skb_ptr;
 
 				/* Received Packet CRC check need or not */
-				if ((db->dm910x_chk_mode & 1) && (cal_CRC(skb->tail, rxlen) != (*(unsigned long *) (skb->tail + rxlen)))) {
+				if ((db->dm910x_chk_mode & 1) && (cal_CRC(skb->tail, rxlen, 1) != (*(unsigned long *) (skb->tail + rxlen)))) {
 					/* Found a error received packet */
 					dmfe_reused_skb(db, (struct sk_buff *) rxptr->rx_skb_ptr);
 					db->dm910x_chk_mode = 3;
@@ -786,11 +800,12 @@
 					skb_put(skb, rxlen);
 					skb->protocol = eth_type_trans(skb, dev);
 					netif_rx(skb);	/* Send to upper layer */
-					/* skb->ip_summed = CHECKSUM_UNNECESSARY; */
 					dev->last_rx = jiffies;
 					db->stats.rx_packets++;
+					db->stats.rx_bytes += rxlen;
 				}
 			} else {
+				/* Reuse SKB buffer when the packet is error */
 				DMFE_DBUG(0, "Reused SK buffer, rdes0", rxptr->rdes0);
 				dmfe_reused_skb(db, (struct sk_buff *) rxptr->rx_skb_ptr);
 			}
@@ -800,12 +815,12 @@
 	}
 
 	db->rx_ready_ptr = rxptr;
+
 }
 
 /*
- *	Get statistics from driver.
+   Get statistics from driver.
  */
- 
 static struct enet_statistics *dmfe_get_stats(struct device *dev)
 {
 	struct dmfe_board_info *db = (struct dmfe_board_info *) dev->priv;
@@ -815,9 +830,8 @@
 }
 
 /*
- *	Set DM910X multicast address
+   Set DM910X multicast address
  */
- 
 static void dmfe_set_filter_mode(struct device *dev)
 {
 	struct dmfe_board_info *db = dev->priv;
@@ -837,13 +851,15 @@
 		return;
 	}
 	DMFE_DBUG(0, "Set multicast address", dev->mc_count);
-	send_filter_frame(dev, dev->mc_count);
+	if (db->chip_id == PCI_DM9132_ID)
+		dm9132_id_table(dev, dev->mc_count);	/* DM9132 */
+	else
+		send_filter_frame(dev, dev->mc_count);	/* DM9102/DM9102A */
 }
 
 /*
- *	Process the upper socket ioctl command
+   Process the upper socket ioctl command
  */
- 
 static int dmfe_do_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
 {
 	DMFE_DBUG(0, "dmfe_do_ioctl()", 0);
@@ -851,10 +867,9 @@
 }
 
 /*
- *	A periodic timer routine
- *	Dynamic media sense, allocated Rx buffer...
+   A periodic timer routine
+   Dynamic media sense, allocated Rx buffer...
  */
- 
 static void dmfe_timer(unsigned long data)
 {
 	u32 tmp_cr8;
@@ -889,18 +904,26 @@
 
 	if (db->wait_reset | (db->tx_packet_cnt &&
 			      ((jiffies - dev->trans_start) > DMFE_TX_TIMEOUT)) | (db->rx_error_cnt > 3)) {
-		/* printk("wait_reset %x, tx cnt %x, rx err %x, time %x\n", db->wait_reset, db->tx_packet_cnt, db->rx_error_cnt, jiffies-dev->trans_start); */
+		/*
+		   printk("wait_reset %x, tx cnt %x, rx err %x, time %x\n", db->wait_reset, db->tx_packet_cnt, db->rx_error_cnt, jiffies-dev->trans_start);
+		 */
 		DMFE_DBUG(0, "Warn!! Warn!! Tx/Rx moniotr step1", db->tx_packet_cnt);
 		dmfe_dynamic_reset(dev);
 		db->timer.expires = DMFE_TIMER_WUT;
 		add_timer(&db->timer);
 		return;
 	}
-	db->rx_error_cnt = 0;	/* Clear previous counter */
+	db->rx_error_cnt = 0;	/* Clear previos counter */
 
 	/* Link status check, Dynamic media type change */
-	tmp_cr12 = inb(db->ioaddr + DCR12);
-	if (db->chip_revesion == 0x02000030) {
+	if (db->chip_id == PCI_DM9132_ID)
+		tmp_cr12 = inb(db->ioaddr + DCR9 + 3);	/* DM9132 */
+	else
+		tmp_cr12 = inb(db->ioaddr + DCR12);	/* DM9102/DM9102A */
+
+	if (((db->chip_id == PCI_DM9102_ID) && (db->chip_revesion == 0x02000030)) ||
+	    ((db->chip_id == PCI_DM9132_ID) && (db->chip_revesion == 0x02000010))) {
+		/* DM9102A Chip */
 		if (tmp_cr12 & 2)
 			tmp_cr12 = 0x0;		/* Link failed */
 		else
@@ -910,10 +933,26 @@
 		/* Link Failed */
 		DMFE_DBUG(0, "Link Failed", tmp_cr12);
 		db->link_failed = 1;
-		phy_write(db->ioaddr, db->phy_addr, 0, 0x8000);		/* reset Phy controller */
+		phy_write(db->ioaddr, db->phy_addr, 0, 0x8000, db->chip_id);	/* reset Phy */
+
+		/* 10/100M link failed, used 1M Home-Net */
+		db->cr6_data |= 0x00040000;	/* CR6 bit18 = 1, select Home-Net */
+		db->cr6_data &= ~0x00000200;	/* CR6 bit9 =0, half duplex mode */
+		update_cr6(db->cr6_data, db->ioaddr);
+
+		/* For DM9801 : PHY ID1 0181h, PHY ID2 B900h */
+		db->phy_id2 = phy_read(db->ioaddr, db->phy_addr, 3, db->chip_id);
+		if (db->phy_id2 == 0xb900)
+			phy_write(db->ioaddr, db->phy_addr, 25, 0x7e08, db->chip_id);
 	} else if ((tmp_cr12 & 0x3) && db->link_failed) {
 		DMFE_DBUG(0, "Link link OK", tmp_cr12);
 		db->link_failed = 0;
+
+		/* CR6 bit18=0, select 10/100M */
+		db->cr6_data &= ~0x00040000;
+		update_cr6(db->cr6_data, db->ioaddr);
+
+		/* Auto Sense Speed */
 		if (db->media_mode & DMFE_AUTO)
 			dmfe_sense_speed(db);
 		dmfe_process_mode(db);
@@ -930,13 +969,12 @@
 }
 
 /*
- *	Dynamic reset the DM910X board
- *	Stop DM910X board
- *	Free Tx/Rx allocated memory
- *	Reset DM910X board
- *	Re-initilize DM910X board
+   Dynamic reset the DM910X board
+   Stop DM910X board
+   Free Tx/Rx allocated memory
+   Reset DM910X board
+   Re-initilize DM910X board
  */
- 
 static void dmfe_dynamic_reset(struct device *dev)
 {
 	struct dmfe_board_info *db = dev->priv;
@@ -958,6 +996,7 @@
 
 	/* system variable init */
 	db->tx_packet_cnt = 0;
+	db->tx_queue_cnt = 0;
 	db->rx_avail_cnt = 0;
 	db->link_failed = 0;
 	db->wait_reset = 0;
@@ -975,9 +1014,8 @@
 }
 
 /*
- *	Free all allocated rx buffer 
+   free all allocated rx buffer 
  */
-
 static void dmfe_free_rxbuffer(struct dmfe_board_info *db)
 {
 	DMFE_DBUG(0, "dmfe_free_rxbuffer()", 0);
@@ -991,9 +1029,8 @@
 }
 
 /*
- *	Reused the SK buffer
+   Reused the SK buffer
  */
- 
 static void dmfe_reused_skb(struct dmfe_board_info *db, struct sk_buff *skb)
 {
 	struct rx_desc *rxptr = db->rx_insert_ptr;
@@ -1009,10 +1046,9 @@
 }
 
 /*
- *	Initialize transmit/Receive descriptor 
- *	Using Chain structure, and allocated Tx/Rx buffer
+   Initialize transmit/Receive descriptor 
+   Using Chain structure, and allocated Tx/Rx buffer
  */
- 
 static void dmfe_descriptor_init(struct dmfe_board_info *db, u32 ioaddr)
 {
 	struct tx_desc *tmp_tx;
@@ -1063,10 +1099,9 @@
 }
 
 /*
- *	Update CR6 vaule
- *	Firstly stop DM910X , then written value and start
+   Update CR6 vaule
+   Firstly stop DM910X , then written value and start
  */
- 
 static void update_cr6(u32 cr6_data, u32 ioaddr)
 {
 	u32 cr6_tmp;
@@ -1079,11 +1114,50 @@
 	/* printk("CR6 update %x ", cr6_tmp); */
 }
 
-/*
- *	Send a setup frame
- *	This setup frame initilize DM910X addres filter mode
+/* Send a setup frame for DM9132
+   This setup frame initilize DM910X addres filter mode
+ */
+static void dm9132_id_table(struct device *dev, int mc_cnt)
+{
+	struct dev_mc_list *mcptr;
+	u16 *addrptr;
+	u32 ioaddr = dev->base_addr + 0xc0;	/* ID Table */
+	u32 hash_val;
+	u16 i, hash_table[4];
+
+	DMFE_DBUG(0, "dm9132_id_table()", 0);
+
+	/* Node address */
+	addrptr = (u16 *) dev->dev_addr;
+	outw(addrptr[0], ioaddr);
+	ioaddr += 4;
+	outw(addrptr[1], ioaddr);
+	ioaddr += 4;
+	outw(addrptr[2], ioaddr);
+	ioaddr += 4;
+
+	/* Clear Hash Table */
+	for (i = 0; i < 4; i++)
+		hash_table[i] = 0x0;
+
+	/* broadcast address */
+	hash_table[3] = 0x8000;
+
+	/* the multicast address in Hash Table : 64 bits */
+	for (mcptr = dev->mc_list, i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {
+		hash_val = cal_CRC((char *) mcptr->dmi_addr, 6, 0) & 0x3f;
+		hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16);
+	}
+
+	/* Write the hash table to MAC MD table */
+	for (i = 0; i < 4; i++, ioaddr += 4) {
+		outw(hash_table[i], ioaddr);
+	}
+}
+
+/* Send a setup frame for DM9102/DM9102A
+   This setup frame initilize DM910X addres filter mode
  */
- 
 static void send_filter_frame(struct device *dev, int mc_cnt)
 {
 	struct dmfe_board_info *db = dev->priv;
@@ -1098,17 +1172,17 @@
 	txptr = db->tx_insert_ptr;
 	suptr = (u32 *) txptr->tx_buf_ptr;
 
-	/* broadcast address */
-	*suptr++ = 0xffff;
-	*suptr++ = 0xffff;
-	*suptr++ = 0xffff;
-
 	/* Node address */
 	addrptr = (u16 *) dev->dev_addr;
 	*suptr++ = addrptr[0];
 	*suptr++ = addrptr[1];
 	*suptr++ = addrptr[2];
 
+	/* broadcast address */
+	*suptr++ = 0xffff;
+	*suptr++ = 0xffff;
+	*suptr++ = 0xffff;
+
 	/* fit the multicast address */
 	for (mcptr = dev->mc_list, i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {
 		addrptr = (u16 *) mcptr->dmi_addr;
@@ -1124,22 +1198,28 @@
 	}
 
 	/* prepare the setup frame */
-	db->tx_packet_cnt++;
-	dev->tbusy = 1;
-	txptr->tdes1 = 0x890000c0;
-	txptr->tdes0 = 0x80000000;
 	db->tx_insert_ptr = (struct tx_desc *) txptr->next_tx_desc;
+	txptr->tdes1 = 0x890000c0;
 
-	update_cr6(db->cr6_data | 0x2000, dev->base_addr);
-	outl(0x1, dev->base_addr + DCR1);
-	update_cr6(db->cr6_data, dev->base_addr);
-	dev->trans_start = jiffies;
+	/* Resource Check and Send the setup packet */
+	if (!db->tx_packet_cnt) {
+		/* Resource Empty */
+		db->tx_packet_cnt++;
+		txptr->tdes0 = 0x80000000;
+		update_cr6(db->cr6_data | 0x2000, dev->base_addr);
+		outl(0x1, dev->base_addr + DCR1);	/* Issue Tx polling command */
+		update_cr6(db->cr6_data, dev->base_addr);
+		dev->trans_start = jiffies;
+	} else {
+		/* Put into TX queue */
+		db->tx_queue_cnt++;
+	}
 
 }
 
 /*
- *	Allocate rx buffer,
- *	Allocate as many Rx buffers as possible.
+   Allocate rx buffer,
+   As possible as allocated maxiumn Rx buffer
  */
 static void allocated_rx_buffer(struct dmfe_board_info *db)
 {
@@ -1162,9 +1242,8 @@
 }
 
 /*
- *	Read one word data from the serial ROM
+   Read one word data from the serial ROM
  */
- 
 static u16 read_srom_word(long ioaddr, int offset)
 {
 	int i;
@@ -1200,38 +1279,8 @@
 }
 
 /*
- *	Parser Control media block to get Phy address
+   Auto sense the media mode
  */
- 
-static void parser_ctrl_info(struct dmfe_board_info *db)
-{
-	int i;
-	char *sdata = db->srom;
-	unsigned char count;
-
-	/* point to info leaf0 */
-	count = *(sdata + 33);
-
-	/* Point to First media block */
-	sdata += 34;
-	for (i = 0; i < count; i++) {
-		if (*(sdata + 1) == 1) {
-			db->phy_addr = *(sdata + 2);
-			break;
-		}
-		sdata += ((unsigned char) *(sdata) & 0x7f) + 1;
-	}
-
-	if (i >= count) {
-		printk("Can't find Control Block\n");
-		db->phy_addr = 1;
-	}
-}
-
-/*
- *	Auto sense the media mode
- */
- 
 static void dmfe_sense_speed(struct dmfe_board_info *db)
 {
 	int i;
@@ -1239,13 +1288,16 @@
 
 	for (i = 1000; i; i--) {
 		DELAY_5US;
-		phy_mode = phy_read(db->ioaddr, db->phy_addr, 1);
+		phy_mode = phy_read(db->ioaddr, db->phy_addr, 1, db->chip_id);
 		if ((phy_mode & 0x24) == 0x24)
 			break;
 	}
 
 	if (i) {
-		phy_mode = phy_read(db->ioaddr, db->phy_addr, 17) & 0xf000;
+		if (db->chip_id == PCI_DM9132_ID)	/* DM9132 */
+			phy_mode = phy_read(db->ioaddr, db->phy_addr, 7, db->chip_id) & 0xf000;
+		else		/* DM9102/DM9102A */
+			phy_mode = phy_read(db->ioaddr, db->phy_addr, 17, db->chip_id) & 0xf000;
 		/* printk("Phy_mode %x ",phy_mode); */
 		switch (phy_mode) {
 		case 0x1000:
@@ -1261,23 +1313,22 @@
 			db->op_mode = DMFE_100MFD;
 			break;
 		default:
-			db->op_mode = DMFE_100MHF;
-			DMFE_DBUG(1, "Media Type error, phy reg17", phy_mode);
+			db->op_mode = DMFE_10MHF;
+			DMFE_DBUG(0, "Media Type error, phy reg17", phy_mode);
 			break;
 		}
 	} else {
-		db->op_mode = DMFE_100MHF;
+		db->op_mode = DMFE_10MHF;
 		DMFE_DBUG(0, "Link Failed :", phy_mode);
 	}
 }
 
 /*
- *	Process op-mode
- *	AUTO mode : PHY controller in Auto-negotiation Mode
- *	Force mode: PHY controller in force mode with HUB
- *	N-way force capability with SWITCH
+   Process op-mode
+   AUTO mode : PHY controller in Auto-negotiation Mode
+   Force mode: PHY controller in force mode with HUB
+   N-way force capability with SWITCH
  */
- 
 static void dmfe_process_mode(struct dmfe_board_info *db)
 {
 	u16 phy_reg;
@@ -1289,11 +1340,11 @@
 
 	if (!(db->media_mode & DMFE_AUTO)) {	/* Force Mode Check */
 		/* User force the media type */
-		phy_reg = phy_read(db->ioaddr, db->phy_addr, 5);
+		phy_reg = phy_read(db->ioaddr, db->phy_addr, 5, db->chip_id);
 		/* printk("Nway phy_reg5 %x ",phy_reg); */
 		if (phy_reg & 0x1) {
 			/* parter own the N-Way capability */
-			phy_reg = phy_read(db->ioaddr, db->phy_addr, 4) & ~0x1e0;
+			phy_reg = phy_read(db->ioaddr, db->phy_addr, 4, db->chip_id) & ~0x1e0;
 			switch (db->op_mode) {
 			case DMFE_10MHF:
 				phy_reg |= 0x20;
@@ -1308,7 +1359,7 @@
 				phy_reg |= 0x100;
 				break;
 			}
-			phy_write(db->ioaddr, db->phy_addr, 4, phy_reg);
+			phy_write(db->ioaddr, db->phy_addr, 4, phy_reg, db->chip_id);
 		} else {
 			/* parter without the N-Way capability */
 			switch (db->op_mode) {
@@ -1325,95 +1376,109 @@
 				phy_reg = 0x2100;
 				break;
 			}
-			phy_write(db->ioaddr, db->phy_addr, 0, phy_reg);
+			phy_write(db->ioaddr, db->phy_addr, 0, phy_reg, db->chip_id);
 		}
 	}
 }
 
 /*
- *	Write a word to Phy register
+   Write a word to Phy register
  */
- 
-static void phy_write(u32 iobase, u8 phy_addr, u8 offset, u16 phy_data)
+static void phy_write(u32 iobase, u8 phy_addr, u8 offset, u16 phy_data, u32 chip_id)
 {
 	u16 i;
-	u32 ioaddr = iobase + DCR9;
+	u32 ioaddr;
 
-	/* Send 33 synchronization clock to Phy controller */
-	for (i = 0; i < 35; i++)
-		phy_write_1bit(ioaddr, PHY_DATA_1);
+	if (chip_id == PCI_DM9132_ID) {
+		ioaddr = iobase + 0x80 + offset * 4;
+		outw(phy_data, ioaddr);
+	} else {
+		/* DM9102/DM9102A Chip */
+		ioaddr = iobase + DCR9;
 
-	/* Send start command(01) to Phy */
-	phy_write_1bit(ioaddr, PHY_DATA_0);
-	phy_write_1bit(ioaddr, PHY_DATA_1);
+		/* Send 33 synchronization clock to Phy controller */
+		for (i = 0; i < 35; i++)
+			phy_write_1bit(ioaddr, PHY_DATA_1);
 
-	/* Send write command(01) to Phy */
-	phy_write_1bit(ioaddr, PHY_DATA_0);
-	phy_write_1bit(ioaddr, PHY_DATA_1);
+		/* Send start command(01) to Phy */
+		phy_write_1bit(ioaddr, PHY_DATA_0);
+		phy_write_1bit(ioaddr, PHY_DATA_1);
 
-	/* Send Phy addres */
-	for (i = 0x10; i > 0; i = i >> 1)
-		phy_write_1bit(ioaddr, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0);
+		/* Send write command(01) to Phy */
+		phy_write_1bit(ioaddr, PHY_DATA_0);
+		phy_write_1bit(ioaddr, PHY_DATA_1);
 
-	/* Send register addres */
-	for (i = 0x10; i > 0; i = i >> 1)
-		phy_write_1bit(ioaddr, offset & i ? PHY_DATA_1 : PHY_DATA_0);
+		/* Send Phy addres */
+		for (i = 0x10; i > 0; i = i >> 1)
+			phy_write_1bit(ioaddr, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0);
+
+		/* Send register addres */
+		for (i = 0x10; i > 0; i = i >> 1)
+			phy_write_1bit(ioaddr, offset & i ? PHY_DATA_1 : PHY_DATA_0);
 
-	/* written trasnition */
-	phy_write_1bit(ioaddr, PHY_DATA_1);
-	phy_write_1bit(ioaddr, PHY_DATA_0);
+		/* written trasnition */
+		phy_write_1bit(ioaddr, PHY_DATA_1);
+		phy_write_1bit(ioaddr, PHY_DATA_0);
 
-	/* Write a word data to PHY controller */
-	for (i = 0x8000; i > 0; i >>= 1)
-		phy_write_1bit(ioaddr, phy_data & i ? PHY_DATA_1 : PHY_DATA_0);
+		/* Write a word data to PHY controller */
+		for (i = 0x8000; i > 0; i >>= 1)
+			phy_write_1bit(ioaddr, phy_data & i ? PHY_DATA_1 : PHY_DATA_0);
+	}
 }
 
 /*
- *	Read a word data from phy register
+   Read a word data from phy register
  */
- 
-static u16 phy_read(u32 iobase, u8 phy_addr, u8 offset)
+static u16 phy_read(u32 iobase, u8 phy_addr, u8 offset, u32 chip_id)
 {
 	int i;
 	u16 phy_data;
-	u32 ioaddr = iobase + DCR9;
+	u32 ioaddr;
+
+	if (chip_id == PCI_DM9132_ID) {
+		/* DM9132 Chip */
+		ioaddr = iobase + 0x80 + offset * 4;
+		phy_data = inw(ioaddr);
+	} else {
+		/* DM9102/DM9102A Chip */
+
+		ioaddr = iobase + DCR9;
+		/* Send 33 synchronization clock to Phy controller */
+		for (i = 0; i < 35; i++)
+			phy_write_1bit(ioaddr, PHY_DATA_1);
 
-	/* Send 33 synchronization clock to Phy controller */
-	for (i = 0; i < 35; i++)
+		/* Send start command(01) to Phy */
+		phy_write_1bit(ioaddr, PHY_DATA_0);
 		phy_write_1bit(ioaddr, PHY_DATA_1);
 
-	/* Send start command(01) to Phy */
-	phy_write_1bit(ioaddr, PHY_DATA_0);
-	phy_write_1bit(ioaddr, PHY_DATA_1);
-
-	/* Send read command(10) to Phy */
-	phy_write_1bit(ioaddr, PHY_DATA_1);
-	phy_write_1bit(ioaddr, PHY_DATA_0);
-
-	/* Send Phy addres */
-	for (i = 0x10; i > 0; i = i >> 1)
-		phy_write_1bit(ioaddr, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0);
-
-	/* Send register addres */
-	for (i = 0x10; i > 0; i = i >> 1)
-		phy_write_1bit(ioaddr, offset & i ? PHY_DATA_1 : PHY_DATA_0);
-
-	/* Skip transition state */
-	phy_read_1bit(ioaddr);
-
-	/* read 16bit data */
-	for (phy_data = 0, i = 0; i < 16; i++) {
-		phy_data <<= 1;
-		phy_data |= phy_read_1bit(ioaddr);
+		/* Send read command(10) to Phy */
+		phy_write_1bit(ioaddr, PHY_DATA_1);
+		phy_write_1bit(ioaddr, PHY_DATA_0);
+
+		/* Send Phy addres */
+		for (i = 0x10; i > 0; i = i >> 1)
+			phy_write_1bit(ioaddr, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0);
+
+		/* Send register addres */
+		for (i = 0x10; i > 0; i = i >> 1)
+			phy_write_1bit(ioaddr, offset & i ? PHY_DATA_1 : PHY_DATA_0);
+
+		/* Skip transition state */
+		phy_read_1bit(ioaddr);
+
+		/* read 16bit data */
+		for (phy_data = 0, i = 0; i < 16; i++) {
+			phy_data <<= 1;
+			phy_data |= phy_read_1bit(ioaddr);
+		}
 	}
 
 	return phy_data;
 }
 
 /*
- *	Write one bit data to Phy Controller
+   Write one bit data to Phy Controller
  */
- 
 static void phy_write_1bit(u32 ioaddr, u32 phy_data)
 {
 	outl(phy_data, ioaddr);	/* MII Clock Low */
@@ -1425,9 +1490,8 @@
 }
 
 /*
- *	Read one bit phy data from PHY controller
+   Read one bit phy data from PHY controller
  */
- 
 static u16 phy_read_1bit(u32 ioaddr)
 {
 	u16 phy_data;
@@ -1442,10 +1506,11 @@
 }
 
 /*
- *	Calculate the CRC valude of the Rx packet
+   Calculate the CRC valude of the Rx packet
+   flag = 1 : return the reverse CRC (for the received packet CRC)
+   0 : return the normal CRC (for Hash Table index)
  */
- 
-static unsigned long cal_CRC(unsigned char *Data, unsigned int Len)
+unsigned long cal_CRC(unsigned char *Data, unsigned int Len, u8 flag)
 {
 	unsigned long Crc = 0xffffffff;
 
@@ -1453,8 +1518,10 @@
 		Crc = CrcTable[(Crc ^ *Data++) & 0xFF] ^ (Crc >> 8);
 	}
 
-	return ~Crc;
-
+	if (flag)
+		return ~Crc;
+	else
+		return Crc;
 }
 
 #ifdef MODULE
@@ -1466,11 +1533,10 @@
 MODULE_PARM(cr6set, "i");
 MODULE_PARM(chkmode, "i");
 
-/*	Description: 
- *	when user used insmod to add module, system invoked init_module()
- *	to initilize and register.
+/* Description: 
+   when user used insmod to add module, system invoked init_module()
+   to initilize and register.
  */
- 
 int init_module(void)
 {
 	DMFE_DBUG(0, "init_module() ", debug);
@@ -1492,29 +1558,30 @@
 		break;
 	}
 
-	return dmfe_reg_board(0);	/* search board and register */
+	return dmfe_probe(0);	/* search board and register */
 }
 
-/*
- *	Description: 
- *	when user used rmmod to delete module, system invoked clean_module()
- *	to un-register device.
+/* Description: 
+   when user used rmmod to delete module, system invoked clean_module()
+   to  un-register device.
  */
- 
 void cleanup_module(void)
 {
 	struct device *next_dev;
+	struct dmfe_board_info *db;
 
 	DMFE_DBUG(0, "clean_module()", 0);
 
 	while (dmfe_root_dev) {
 		next_dev = ((struct dmfe_board_info *) dmfe_root_dev->priv)->next_dev;
 		unregister_netdev(dmfe_root_dev);
-		release_region(dmfe_root_dev->base_addr, DM9102_IO_SIZE);
-		kfree(dmfe_root_dev->priv);	/* free board information */
+		db = dmfe_root_dev->priv;
+		release_region(dmfe_root_dev->base_addr, CHK_IO_SIZE(db->chip_id, db->chip_revesion));
+		kfree(db);	/* free board information */
 		kfree(dmfe_root_dev);	/* free device structure */
 		dmfe_root_dev = next_dev;
 	}
+
 	DMFE_DBUG(0, "clean_module() exit", 0);
 }
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/eepro100.c linux.15p9/drivers/net/eepro100.c
--- linux.vanilla/drivers/net/eepro100.c	Wed Oct 20 01:12:39 1999
+++ linux.15p9/drivers/net/eepro100.c	Wed Feb 16 18:40:15 2000
@@ -1,14 +1,14 @@
-/* drivers/net/eepro100.c: An Intel i82557 Ethernet driver for Linux. */
+/* drivers/net/eepro100.c: An Intel i82557-559 Ethernet driver for Linux. */
 /*
    NOTICE: this version tested with kernels 1.3.72 and later only!
-	Written 1996-1998 by Donald Becker.
+	Written 1996-1999 by Donald Becker.
 
 	This software may be used and distributed according to the terms
 	of the GNU Public License, incorporated herein by reference.
 
-	This driver is for the Intel EtherExpress Pro 100B boards.
-	It should work with other i82557 and i82558 boards.
-	To use a built-in driver, install as drivers/net/eepro100.c.
+	This driver is for the Intel EtherExpress Pro100 (Speedo3) design.
+	It should work with all i82557/558/559 boards.
+
 	To use as a module, use the compile-command at the end of the file.
 
 	The author may be reached as becker@CESDIS.usra.edu, or C/O
@@ -16,15 +16,23 @@
 	   Code 930.5, NASA Goddard Space Flight Center, Greenbelt MD 20771
 	For updates see
 		http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html
-	There is also a mailing list based at
+	For installation instructions
+		http://cesdis.gsfc.nasa.gov/linux/misc/modules.html
+	There is a Majordomo mailing list based at
 		linux-eepro100@cesdis.gsfc.nasa.gov
+	
+	This driver also contains updates by Andrey Savochkin and others.
+	For this specific driver variant please use linux-kernel for 
+	bug reports.
+
 */
 
 static const char *version =
-"eepro100.c:v1.06 10/16/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n";
+"eepro100.c:v1.09j-t 9/29/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n"
+"eepro100.c: $Revision: 1.18 $ 1999/12/29 Modified by Andrey V. Savochkin <saw@msu.ru>\n";
 
 /* A few user-configurable values that apply to all boards.
-   First set are undocumented and spelled per Intel recommendations. */
+   First set is undocumented and spelled per Intel recommendations. */
 
 static int congenb = 0;		/* Enable congestion control in the DP83840. */
 static int txfifo = 8;		/* Tx FIFO threshold in 4 byte units, 0-15 */
@@ -35,17 +43,60 @@
 
 /* Set the copy breakpoint for the copy-only-tiny-buffer Rx method.
    Lower values use more memory, but are faster. */
+#ifdef __alpha__
+/* force copying of all packets to avoid unaligned accesses on Alpha */
+static int rx_copybreak = 1518;
+#else
 static int rx_copybreak = 200;
+#endif
 
 /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 200;
+static int max_interrupt_work = 20;
 
 /* Maximum number of multicast addresses to filter (vs. rx-all-multicast) */
 static int multicast_filter_limit = 64;
 
-#include <linux/module.h>
+/* 'options' is used to pass a transceiver override or full-duplex flag
+   e.g. "options=16" for FD, "options=32" for 100mbps-only. */
+static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+#ifdef MODULE
+static int debug = -1;			/* The debug level */
+#endif
+
+/* A few values that may be tweaked. */
+/* The ring sizes should be a power of two for efficiency. */
+#define TX_RING_SIZE	32
+#define RX_RING_SIZE	32
+/* How much slots multicast filter setup may take.
+   Do not descrease without changing set_rx_mode() implementaion. */
+#define TX_MULTICAST_SIZE   2
+#define TX_MULTICAST_RESERV (TX_MULTICAST_SIZE*2)
+/* Actual number of TX packets queued, must be
+   <= TX_RING_SIZE-TX_MULTICAST_RESERV. */
+#define TX_QUEUE_LIMIT  (TX_RING_SIZE-TX_MULTICAST_RESERV)
+/* Hysteresis marking queue as no longer full. */
+#define TX_QUEUE_UNFULL (TX_QUEUE_LIMIT-4)
+
+/* Operational parameters that usually are not changed. */
+
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT		(2*HZ)
+/* Size of an pre-allocated Rx buffer: <Ethernet MTU> + slack.*/
+#define PKT_BUF_SZ		1536
+
+#if !defined(__OPTIMIZE__)  ||  !defined(__KERNEL__)
+#warning  You must compile this file with the correct options!
+#warning  See the last lines of the source file.
+#error You must compile this driver with "-O".
+#endif
 
 #include <linux/version.h>
+#include <linux/module.h>
+#if defined(MODVERSIONS)
+#include <linux/modversions.h>
+#endif
+
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/timer.h>
@@ -53,19 +104,27 @@
 #include <linux/ioport.h>
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
+#ifdef HAS_PCI_NETIF
+#include "pci-netif.h"
+#else
+#include <linux/pci.h>
+#endif
 #include <linux/pci.h>
+#if LINUX_VERSION_CODE >= 0x20312
+#include <linux/spinlock.h>
+#else
+#include <asm/spinlock.h>
+#endif
+
+#include <asm/bitops.h>
+#include <asm/io.h>
+
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/delay.h>
 
-#include <asm/spinlock.h>
-#include <asm/bitops.h>
-#include <asm/io.h>
-
-/*
- * Module documentation
- */
+#if defined(MODULE)
 MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
 MODULE_DESCRIPTION("Intel i82557/i82558 PCI EtherExpressPro driver");
 MODULE_PARM(debug, "i");
@@ -79,16 +138,35 @@
 MODULE_PARM(rx_copybreak, "i");
 MODULE_PARM(max_interrupt_work, "i");
 MODULE_PARM(multicast_filter_limit, "i");
+#endif
 
 #define RUN_AT(x) (jiffies + (x))
+/* Condensed bus+endian portability operations. */
+#define virt_to_le32desc(addr)  cpu_to_le32(virt_to_bus(addr))
+#define le32desc_to_virt(addr)  bus_to_virt(le32_to_cpu(addr))
+
+#if LINUX_VERSION_CODE < 0x020314
+#define net_device              device
+#define pci_base_address(p, n)  (p)->base_address[n]
+#else
+#define pci_base_address(p, n)  (p)->resource[n].start
+#endif
 
-#define dev_free_skb(skb) dev_kfree_skb(skb);
+#define dev_free_skb(skb)       dev_kfree_skb(skb);
+#if ! defined(HAS_NETIF_QUEUE)
+#define netif_wake_queue(dev)   do { \
+									clear_bit(0, (void*)&dev->tbusy); \
+									mark_bh(NET_BH); \
+								} while(0)
+#define netif_start_queue(dev)  clear_bit(0, (void*)&dev->tbusy)
+#define netif_stop_queue(dev)   set_bit(0, (void*)&dev->tbusy)
+#endif
 
 /* The total I/O port extent of the board.
    The registers beyond 0x18 only exist on the i82558. */
 #define SPEEDO3_TOTAL_SIZE 0x20
 
-int speedo_debug = 0;
+int speedo_debug = 1;
 
 /*
 				Theory of Operation
@@ -196,24 +274,6 @@
 is non-trivial, and the larger copy might flush the cache of useful data, so
 we pass up the skbuff the packet was received into.
 
-IIID. Synchronization
-The driver runs as two independent, single-threaded flows of control.  One
-is the send-packet routine, which enforces single-threaded use by the
-dev->tbusy flag.  The other thread is the interrupt handler, which is single
-threaded by the hardware and other software.
-
-The send packet thread has partial control over the Tx ring and 'dev->tbusy'
-flag.  It sets the tbusy flag whenever it's queuing a Tx packet. If the next
-queue slot is empty, it clears the tbusy flag when finished otherwise it sets
-the 'sp->tx_full' flag.
-
-The interrupt handler has exclusive control over the Rx ring and records stats
-from the Tx ring.  (The Tx-done interrupt can't be selectively turned off, so
-we can't avoid the interrupt overhead by having the Tx routine reap the Tx
-stats.)	 After reaping the stats, it marks the queue entry as empty by setting
-the 'base' to zero.	 Iff the 'sp->tx_full' flag is set, it clears both the
-tx_full and tbusy flags.
-
 IV. Notes
 
 Thanks to Steve Williams of Intel for arranging the non-disclosure agreement
@@ -222,15 +282,55 @@
 
 */
 
-/* A few values that may be tweaked. */
-/* The ring sizes should be a power of two for efficiency. */
-#define TX_RING_SIZE	16		/* Effectively 2 entries fewer. */
-#define RX_RING_SIZE	16
-/* Size of an pre-allocated Rx buffer: <Ethernet MTU> + slack.*/
-#define PKT_BUF_SZ		1536
+/* This table drives the PCI probe routines. */
+static struct net_device *speedo_found1(int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt);
 
-/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT  ((800*HZ)/1000)
+#ifdef USE_IO
+#define SPEEDO_IOTYPE   PCI_USES_MASTER|PCI_USES_IO|PCI_ADDR1
+#define SPEEDO_SIZE		32
+#else
+#define SPEEDO_IOTYPE   PCI_USES_MASTER|PCI_USES_MEM|PCI_ADDR0
+#define SPEEDO_SIZE		0x1000
+#endif
+
+#if defined(HAS_PCI_NETIF)
+struct pci_id_info static pci_tbl[] = {
+	{ "Intel PCI EtherExpress Pro100",
+	  { 0x12298086, 0xffffffff,}, SPEEDO_IOTYPE, SPEEDO_SIZE,
+	  0, speedo_found1 },
+	{0,},						/* 0 terminated list. */
+};
+#else
+enum pci_flags_bit {
+	PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
+	PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
+};
+struct pci_id_info {
+	const char *name;
+	u16	vendor_id, device_id, device_id_mask, flags;
+	int io_size;
+	struct net_device *(*probe1)(int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt);
+} static pci_tbl[] = {
+	{ "Intel PCI EtherExpress Pro100",
+	  0x8086, 0x1229, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 32, speedo_found1 },
+	{0,},						/* 0 terminated list. */
+};
+#endif
+
+#ifndef USE_IO
+#undef inb
+#undef inw
+#undef inl
+#undef outb
+#undef outw
+#undef outl
+#define inb readb
+#define inw readw
+#define inl readl
+#define outb writeb
+#define outw writew
+#define outl writel
+#endif
 
 /* How to wait for the command unit to accept a command.
    Typically this takes 0 ticks. */
@@ -241,10 +341,6 @@
 	while(inb(cmd_ioaddr) && --wait >= 0);
 }
 
-/* Operational parameter that usually are not changed. */
-
-/* The rest of these values should never change. */
-
 /* Offsets to the various registers.
    All accesses need not be longword aligned. */
 enum speedo_offsets {
@@ -257,34 +353,48 @@
 };
 /* Commands that can be put in a command list entry. */
 enum commands {
-	CmdNOp = 0, CmdIASetup = 1, CmdConfigure = 2, CmdMulticastList = 3,
-	CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7,
-	CmdSuspend = 0x4000,		/* Suspend after completion. */
-	CmdIntr = 0x2000,			/* Interrupt after completion. */
-	CmdTxFlex = 0x0008,			/* Use "Flexible mode" for CmdTx command. */
+	CmdNOp = 0, CmdIASetup = 0x10000, CmdConfigure = 0x20000,
+	CmdMulticastList = 0x30000, CmdTx = 0x40000, CmdTDR = 0x50000,
+	CmdDump = 0x60000, CmdDiagnose = 0x70000,
+	CmdSuspend = 0x40000000,	/* Suspend after completion. */
+	CmdIntr = 0x20000000,		/* Interrupt after completion. */
+	CmdTxFlex = 0x00080000,		/* Use "Flexible mode" for CmdTx command. */
+};
+/* Clear CmdSuspend (1<<30) atomically.
+   Otherwise the command status in the lower 16 bits may be reset after
+   an asynchronous change.  Previous driver version used separate 16 bit fields
+   for commands and statuses.  --SAW
+ */
+#ifdef __i386__
+#define speedo_fool_gcc(x) (*(volatile struct { int a[100]; } *)x)
+#define speedo_clear_mask(mask, addr) \
+__asm__ __volatile__("lock; andl %0,%1" \
+: : "r" (~(mask)),"m" (speedo_fool_gcc(addr)) : "memory")
+#define clear_suspend(cmd)  speedo_clear_mask(CmdSuspend, &(cmd)->cmd_status)
+#else
+#define clear_suspend(cmd)	(cmd)->cmd_status &= cpu_to_le32(~CmdSuspend)
+#endif
+
+enum SCBCmdBits {
+     SCBMaskCmdDone=0x8000, SCBMaskRxDone=0x4000, SCBMaskCmdIdle=0x2000,
+     SCBMaskRxSuspend=0x1000, SCBMaskEarlyRx=0x0800, SCBMaskFlowCtl=0x0400,
+     SCBTriggerIntr=0x0200, SCBMaskAll=0x0100,
+     /* The rest are Rx and Tx commands. */
+     CUStart=0x0010, CUResume=0x0020, CUStatsAddr=0x0040, CUShowStats=0x0050,
+     CUCmdBase=0x0060,  /* CU Base address (set to zero) . */
+     CUDumpStats=0x0070, /* Dump then reset stats counters. */
+     RxStart=0x0001, RxResume=0x0002, RxAbort=0x0004, RxAddrLoad=0x0006,
+     RxResumeNoResources=0x0007,
 };
 
-/* The SCB accepts the following controls for the Tx and Rx units: */
-#define	 CU_START		0x0010
-#define	 CU_RESUME		0x0020
-#define	 CU_STATSADDR	0x0040
-#define	 CU_SHOWSTATS	0x0050	/* Dump statistics counters. */
-#define	 CU_CMD_BASE	0x0060	/* Base address to add to add CU commands. */
-#define	 CU_DUMPSTATS	0x0070	/* Dump then reset stats counters. */
-
-#define	 RX_START	0x0001
-#define	 RX_RESUME	0x0002
-#define	 RX_ABORT	0x0004
-#define	 RX_ADDR_LOAD	0x0006
-#define	 RX_RESUMENR	0x0007
-#define INT_MASK	0x0100
-#define DRVR_INT	0x0200		/* Driver generated interrupt. */
+enum SCBPort_cmds {
+	PortReset=0, PortSelfTest=1, PortPartialReset=2, PortDump=3,
+};
 
 /* The Speedo3 Rx and Tx frame/buffer descriptors. */
-struct descriptor {			/* A generic descriptor. */
-	s16 status;		/* Offset 0. */
-	s16 command;		/* Offset 2. */
-	u32 link;					/* struct descriptor *  */
+struct descriptor {			    /* A generic descriptor. */
+	s32 cmd_status;				/* All command and status fields. */
+	u32 link;				    /* struct descriptor *  */
 	unsigned char params[0];
 };
 
@@ -293,8 +403,7 @@
 	s32 status;
 	u32 link;					/* struct RxFD * */
 	u32 rx_buf_addr;			/* void * */
-	u16 count;
-	u16 size;
+	u32 count;
 };
 
 /* Selected elements of the Tx/RxFD.status word. */
@@ -302,7 +411,7 @@
 	RxComplete=0x8000, RxOK=0x2000,
 	RxErrCRC=0x0800, RxErrAlign=0x0400, RxErrTooBig=0x0200, RxErrSymbol=0x0010,
 	RxEth2Type=0x0020, RxNoMatch=0x0004, RxNoIAMatch=0x0002,
-	StatusComplete=0x8000,
+	TxUnderrun=0x1000,  StatusComplete=0x8000,
 };
 
 struct TxFD {					/* Transmit frame descriptor set. */
@@ -317,6 +426,14 @@
 	s32 tx_buf_size1;			/* Length of Tx frame. */
 };
 
+/* Multicast filter setting block.  --SAW */
+struct speedo_mc_block {
+	struct speedo_mc_block *next;
+	unsigned int tx;
+	char fill[16 - sizeof(struct speedo_mc_block *) - sizeof(unsigned int)];
+	struct descriptor frame;
+};
+
 /* Elements of the dump_statistics block. This block must be lword aligned. */
 struct speedo_stats {
 	u32 tx_good_frames;
@@ -338,49 +455,60 @@
 	u32 done_marker;
 };
 
+enum Rx_ring_state_bits {
+	RrNoMem=1, RrPostponed=2, RrNoResources=4, RrOOMReported=8,
+};
+
+/* Do not change the position (alignment) of the first few elements!
+   The later elements are grouped for cache locality. */
 struct speedo_private {
-	char devname[8];			/* Used only for kernel debugging. */
-	const char *product_name;
-	struct device *next_module;
-	spinlock_t lock;
-	struct TxFD	tx_ring[TX_RING_SIZE] 	/* Commands (usually CmdTxPacket). */
-				__attribute__ ((aligned (L1_CACHE_BYTES)));;
-	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
+	struct TxFD	tx_ring[TX_RING_SIZE];	/* Commands (usually CmdTxPacket). */
+	struct RxFD *rx_ringp[RX_RING_SIZE];	/* Rx descriptor, used as ring. */
+	/* The addresses of a Tx/Rx-in-place packets/buffers. */
 	struct sk_buff* tx_skbuff[TX_RING_SIZE];
-	struct descriptor  *last_cmd;	/* Last command sent. */
-	/* Rx descriptor ring & addresses of receive-in-place skbuffs. */
-	struct RxFD *rx_ringp[RX_RING_SIZE];
 	struct sk_buff* rx_skbuff[RX_RING_SIZE];
+	struct descriptor  *last_cmd;	/* Last command sent. */
+	unsigned int cur_tx, dirty_tx;	/* The ring entries to be free()ed. */
+	spinlock_t lock;				/* Group with Tx control cache line. */
+	u32 tx_threshold;					/* The value for txdesc.count. */
 	struct RxFD *last_rxf;	/* Last command sent. */
+	unsigned int cur_rx, dirty_rx;		/* The next free ring entry */
+	long last_rx_time;			/* Last Rx, in jiffies, to handle Rx hang. */
+	const char *product_name;
+	struct net_device *next_module;
+	void *priv_addr;					/* Unaligned address for kfree */
 	struct enet_statistics stats;
 	struct speedo_stats lstats;
+	int chip_id;
+	unsigned char pci_bus, pci_devfn, acpi_pwr;
 	struct timer_list timer;	/* Media selection timer. */
-	long last_rx_time;			/* Last Rx, in jiffies, to handle Rx hang. */
-	unsigned int cur_rx, cur_tx;		/* The next free ring entry */
-	unsigned int dirty_rx, dirty_tx;	/* The ring entries to be free()ed. */
-	int mc_setup_frm_len;			 	/* The length of an allocated.. */
-	struct descriptor *mc_setup_frm; 	/* ..multicast setup frame. */
-	int mc_setup_busy;					/* Avoid double-use of setup frame. */
+	struct speedo_mc_block *mc_setup_head;/* Multicast setup frame list head. */
+	struct speedo_mc_block *mc_setup_tail;/* Multicast setup frame list tail. */
+	int in_interrupt;					/* Word-aligned dev->interrupt */
 	char rx_mode;						/* Current PROMISC/ALLMULTI setting. */
 	unsigned int tx_full:1;				/* The Tx queue is full. */
 	unsigned int full_duplex:1;			/* Full-duplex operation requested. */
-	unsigned int default_port:1;		/* Last dev->if_port value. */
+	unsigned int flow_ctrl:1;			/* Use 802.3x flow control. */
 	unsigned int rx_bug:1;				/* Work around receiver hang errata. */
 	unsigned int rx_bug10:1;			/* Receiver might hang at 10mbps. */
 	unsigned int rx_bug100:1;			/* Receiver might hang at 100mbps. */
+	unsigned char default_port:8;		/* Last dev->if_port value. */
+	unsigned char rx_ring_state;		/* RX ring status flags. */
 	unsigned short phy[2];				/* PHY media interfaces available. */
+	unsigned short advertising;			/* Current PHY advertised caps. */
+	unsigned short partner;				/* Link partner caps. */
 };
 
 /* The parameters for a CmdConfigure operation.
    There are so many options that it would be difficult to document each bit.
    We mostly use the default or recommended settings. */
 const char i82557_config_cmd[22] = {
-	22, 0x08, 0, 0,  0, 0x80, 0x32, 0x03,  1, /* 1=Use MII  0=Use AUI */
+	22, 0x08, 0, 0,  0, 0, 0x32, 0x03,  1, /* 1=Use MII  0=Use AUI */
 	0, 0x2E, 0,  0x60, 0,
 	0xf2, 0x48,   0, 0x40, 0xf2, 0x80, 		/* 0x40=Force full-duplex */
 	0x3f, 0x05, };
 const char i82558_config_cmd[22] = {
-	22, 0x08, 0, 1,  0, 0x80, 0x22, 0x03,  1, /* 1=Use MII  0=Use AUI */
+	22, 0x08, 0, 1,  0, 0, 0x22, 0x03,  1, /* 1=Use MII  0=Use AUI */
 	0, 0x2E, 0,  0x60, 0x08, 0x88,
 	0x68, 0, 0x40, 0xf2, 0xBD, 		/* 0xBD->0xFD=Force full-duplex */
 	0x31, 0x05, };
@@ -394,35 +522,29 @@
 enum phy_chips { NonSuchPhy=0, I82553AB, I82553C, I82503, DP83840, S80C240,
 					 S80C24, I82555, DP83840A=10, };
 static const char is_mii[] = { 0, 1, 1, 0, 1, 1, 0, 1 };
+#define EE_READ_CMD		(6)
 
-static void speedo_found1(struct device *dev, long ioaddr, int irq,
-						  int card_idx);
-
-static int read_eeprom(long ioaddr, int location, int addr_len);
+static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len);
 static int mdio_read(long ioaddr, int phy_id, int location);
 static int mdio_write(long ioaddr, int phy_id, int location, int value);
-static int speedo_open(struct device *dev);
+static int speedo_open(struct net_device *dev);
+static void speedo_resume(struct net_device *dev);
 static void speedo_timer(unsigned long data);
-static void speedo_init_rx_ring(struct device *dev);
-static int speedo_start_xmit(struct sk_buff *skb, struct device *dev);
-static int speedo_rx(struct device *dev);
+static void speedo_init_rx_ring(struct net_device *dev);
+static void speedo_tx_timeout(struct net_device *dev);
+static int speedo_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static void speedo_refill_rx_buffers(struct net_device *dev, int force);
+static int speedo_rx(struct net_device *dev);
+static void speedo_tx_buffer_gc(struct net_device *dev);
 static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
-static int speedo_close(struct device *dev);
-static struct enet_statistics *speedo_get_stats(struct device *dev);
-static int speedo_ioctl(struct device *dev, struct ifreq *rq, int cmd);
-static void set_rx_mode(struct device *dev);
+static int speedo_close(struct net_device *dev);
+static struct enet_statistics *speedo_get_stats(struct net_device *dev);
+static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static void set_rx_mode(struct net_device *dev);
+static void speedo_show_state(struct net_device *dev);
 
 
 
-/* The parameters that may be passed in... */
-/* 'options' is used to pass a transceiver override or full-duplex flag
-   e.g. "options=16" for FD, "options=32" for 100mbps-only. */
-static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-#ifdef MODULE
-static int debug = -1;			/* The debug level */
-#endif
-
 #ifdef honor_default_port
 /* Optional driver feature to allow forcing the transceiver setting.
    Not recommended. */
@@ -431,9 +553,10 @@
 #endif
 
 /* A list of all installed Speedo devices, for removing the driver module. */
-static struct device *root_speedo_dev = NULL;
+static struct net_device *root_speedo_dev = NULL;
 
-int eepro100_init(struct device *dev)
+#if ! defined(HAS_PCI_NETIF)
+int eepro100_init(void)
 {
 	int cards_found = 0;
 	static int pci_index = 0;
@@ -443,6 +566,7 @@
 
 	for (; pci_index < 8; pci_index++) {
 		unsigned char pci_bus, pci_device_fn, pci_latency;
+		unsigned long pciaddr;
 		long ioaddr;
 		int irq;
 
@@ -455,11 +579,23 @@
 			break;
 		{
 			struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
-			ioaddr = pdev->base_address[1];		/* Use [0] to mem-map */
+#ifdef USE_IO
+			pciaddr = pci_base_address(pdev, 1);	/* Use [0] to mem-map */
+#else
+			pciaddr = pci_base_address(pdev, 0);
+#endif
 			irq = pdev->irq;
 		}
 		/* Remove I/O space marker in bit 0. */
-		ioaddr &= ~3UL;
+		if (pciaddr & 1) {
+			ioaddr = pciaddr & ~3UL;
+			if (check_region(ioaddr, 32))
+				continue;
+		} else if ((ioaddr = (long)ioremap(pciaddr & ~0xfUL, 0x1000)) == 0) {
+			printk(KERN_INFO "Failed to map PCI address %#x.\n",
+				   pciaddr);
+			continue;
+		}
 		if (speedo_debug > 2)
 			printk("Found Intel i82557 PCI Speedo at I/O %#lx, IRQ %d.\n",
 				   ioaddr, irq);
@@ -485,27 +621,78 @@
 		} else if (speedo_debug > 1)
 			printk("  PCI latency timer (CFLT) is %#x.\n", pci_latency);
 
-		speedo_found1(dev, ioaddr, irq, cards_found);
-		dev = NULL;
-		cards_found++;
+		if (speedo_found1(pci_bus, pci_device_fn, ioaddr, irq, 0, cards_found))
+			cards_found++;
+	}
+
+	for (; pci_index < 8; pci_index++) {
+		unsigned char pci_bus, pci_device_fn, pci_latency;
+		long ioaddr;
+		int irq;
+
+		u16 pci_command, new_command;
+
+		if (pcibios_find_device(PCI_VENDOR_ID_INTEL,
+					PCI_DEVICE_ID_INTEL_82559ER,
+					pci_index, &pci_bus,
+					&pci_device_fn))
+		    break;
+		{
+		    struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
+		    ioaddr = pdev->base_address[1];		/* Use [0] to mem-map */
+		    irq = pdev->irq;
+		}
+		/* Remove I/O space marker in bit 0. */
+		ioaddr &= ~3;
+		if (speedo_debug > 2)
+		    printk("Found Intel i82559ER PCI Speedo at I/O %#lx, IRQ %d.\n",
+			   ioaddr, irq);
+		
+		/* Get and check the bus-master and latency values. */
+		pcibios_read_config_word(pci_bus, pci_device_fn,
+					 PCI_COMMAND, &pci_command);
+		new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
+		if (pci_command != new_command) {
+		    printk(KERN_INFO "  The PCI BIOS has not enabled this"
+			   " device!  Updating PCI command %4.4x->%4.4x.\n",
+			   pci_command, new_command);
+		    pcibios_write_config_word(pci_bus, pci_device_fn,
+					      PCI_COMMAND, new_command);
+		}
+		pcibios_read_config_byte(pci_bus, pci_device_fn,
+					 PCI_LATENCY_TIMER, &pci_latency);
+		if (pci_latency < 32) {
+		    printk("  PCI latency timer (CFLT) is unreasonably low at %d."
+			   "  Setting to 32 clocks.\n", pci_latency);
+		    pcibios_write_config_byte(pci_bus, pci_device_fn,
+					      PCI_LATENCY_TIMER, 32);
+		} else if (speedo_debug > 1)
+			printk("  PCI latency timer (CFLT) is %#x.\n", pci_latency);
+		
+		if(speedo_found1(pci_bus, pci_device_fn, ioaddr, irq, 0, cards_found))
+			cards_found++;
 	}
 
 	return cards_found;
 }
+#endif
 
-static void speedo_found1(struct device *dev, long ioaddr, int irq,
-						  int card_idx)
+static struct net_device *speedo_found1(int pci_bus, int pci_devfn, 
+			  long ioaddr, int irq, int chip_idx, int card_idx)
 {
-	static int did_version = 0;			/* Already printed version info. */
+	struct net_device *dev;
 	struct speedo_private *sp;
-	char *product;
+	const char *product;
 	int i, option;
-	u16 eeprom[0x40];
-
+	u16 eeprom[0x100];
+	int acpi_idle_state = 0;
+#ifndef MODULE
+	static int did_version = 0;			/* Already printed version info. */
 	if (speedo_debug > 0  &&  did_version++ == 0)
 		printk(version);
+#endif
 
-	dev = init_etherdev(dev, sizeof(struct speedo_private));
+	dev = init_etherdev(NULL, sizeof(struct speedo_private));
 
 	if (dev->mem_start > 0)
 		option = dev->mem_start;
@@ -514,16 +701,31 @@
 	else
 		option = 0;
 
+#if defined(HAS_PCI_NETIF)
+	acpi_idle_state = acpi_set_pwr_state(pci_bus, pci_devfn, ACPI_D0);
+#endif
+
 	/* Read the station address EEPROM before doing the reset.
-	   Perhaps this should even be done before accepting the device,
-	   then we wouldn't have a device name with which to report the error. */
+	   Nominally his should even be done before accepting the device, but
+	   then we wouldn't have a device name with which to report the error.
+	   The size test is for 6 bit vs. 8 bit address serial EEPROMs.
+	*/
 	{
 		u16 sum = 0;
 		int j;
-		int addr_len = read_eeprom(ioaddr, 0, 6) == 0xffff ? 8 : 6;
+		int read_cmd, ee_size;
 
-		for (j = 0, i = 0; i < 0x40; i++) {
-			u16 value = read_eeprom(ioaddr, i, addr_len);
+		if ((do_eeprom_cmd(ioaddr, EE_READ_CMD << 24, 27) & 0xffe0000)
+			== 0xffe0000) {
+			ee_size = 0x100;
+			read_cmd = EE_READ_CMD << 24;
+		} else {
+			ee_size = 0x40;
+			read_cmd = EE_READ_CMD << 22;
+		}
+
+		for (j = 0, i = 0; i < ee_size; i++) {
+			u16 value = do_eeprom_cmd(ioaddr, read_cmd | (i << 16), 27);
 			eeprom[i] = value;
 			sum += value;
 			if (i < 3) {
@@ -542,12 +744,12 @@
 	/* Reset the chip: stop Tx and Rx processes and clear counters.
 	   This takes less than 10usec and will easily finish before the next
 	   action. */
-	outl(0, ioaddr + SCBPort);
+	outl(PortReset, ioaddr + SCBPort);
 
 	if (eeprom[3] & 0x0100)
 		product = "OEM i82557/i82558 10/100 Ethernet";
 	else
-		product = "Intel EtherExpress Pro 10/100";
+		product = pci_tbl[chip_idx].name;
 
 	printk(KERN_INFO "%s: %s at %#3lx, ", dev->name, product, ioaddr);
 
@@ -555,7 +757,7 @@
 		printk("%2.2X:", dev->dev_addr[i]);
 	printk("%2.2X, IRQ %d.\n", dev->dev_addr[i], irq);
 
-#ifndef kernel_bloat
+#if 1 || defined(kernel_bloat)
 	/* OK, this is pure kernel bloat.  I don't like it when other drivers
 	   waste non-pageable kernel space to emit similar messages, but I need
 	   them for bug reports. */
@@ -600,7 +802,7 @@
 		self_test_results = (s32*) ((((long) str) + 15) & ~0xf);
 		self_test_results[0] = 0;
 		self_test_results[1] = -1;
-		outl(virt_to_bus(self_test_results) | 1, ioaddr + SCBPort);
+		outl(virt_to_bus(self_test_results) | PortSelfTest, ioaddr + SCBPort);
 		do {
 			udelay(10);
 		} while (self_test_results[1] == -1  &&  --boguscnt >= 0);
@@ -624,19 +826,33 @@
 	}
 #endif  /* kernel_bloat */
 
+	outl(PortReset, ioaddr + SCBPort);
+#if defined(HAS_PCI_NETIF)
+	/* Return the chip to its original power state. */
+	acpi_set_pwr_state(pci_bus, pci_devfn, acpi_idle_state);
+#endif
+
 	/* We do a request_region() only to register /proc/ioports info. */
 	request_region(ioaddr, SPEEDO3_TOTAL_SIZE, "Intel Speedo3 Ethernet");
 
 	dev->base_addr = ioaddr;
 	dev->irq = irq;
 
-	if (dev->priv == NULL)
-		dev->priv = kmalloc(sizeof(*sp), GFP_KERNEL);
 	sp = dev->priv;
+	if (dev->priv == NULL) {
+		void *mem = kmalloc(sizeof(*sp), GFP_KERNEL);
+		dev->priv = sp = mem;		/* Cache align here if kmalloc does not. */
+		sp->priv_addr = mem;
+	}
 	memset(sp, 0, sizeof(*sp));
 	sp->next_module = root_speedo_dev;
 	root_speedo_dev = dev;
 
+	sp->pci_bus = pci_bus;
+	sp->pci_devfn = pci_devfn;
+	sp->chip_id = chip_idx;
+	sp->acpi_pwr = acpi_idle_state;
+
 	sp->full_duplex = option >= 0 && (option & 0x10) ? 1 : 0;
 	if (card_idx >= 0) {
 		if (full_duplex[card_idx] >= 0)
@@ -654,12 +870,16 @@
 	/* The Speedo-specific entries in the device structure. */
 	dev->open = &speedo_open;
 	dev->hard_start_xmit = &speedo_start_xmit;
+#if defined(HAS_NETIF_QUEUE)
+	dev->tx_timeout = &speedo_tx_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT;
+#endif
 	dev->stop = &speedo_close;
 	dev->get_stats = &speedo_get_stats;
 	dev->set_multicast_list = &set_rx_mode;
 	dev->do_ioctl = &speedo_ioctl;
 
-	return;
+	return dev;
 }
 
 /* Serial EEPROM section.
@@ -668,47 +888,33 @@
 #define EE_SHIFT_CLK	0x01	/* EEPROM shift clock. */
 #define EE_CS			0x02	/* EEPROM chip select. */
 #define EE_DATA_WRITE	0x04	/* EEPROM chip data in. */
-#define EE_WRITE_0		0x01
-#define EE_WRITE_1		0x05
 #define EE_DATA_READ	0x08	/* EEPROM chip data out. */
 #define EE_ENB			(0x4800 | EE_CS)
+#define EE_WRITE_0		0x4802
+#define EE_WRITE_1		0x4806
+#define EE_OFFSET		SCBeeprom
 
 /* Delay between EEPROM clock transitions.
-   This will actually work with no delay on 33Mhz PCI.  */
-#define eeprom_delay(nanosec)		udelay(1);
-
-/* The EEPROM commands include the alway-set leading bit. */
-#define EE_WRITE_CMD	(5 << addr_len)
-#define EE_READ_CMD		(6 << addr_len)
-#define EE_ERASE_CMD	(7 << addr_len)
+   The code works with no delay on 33Mhz PCI.  */
+#define eeprom_delay()	inw(ee_addr)
 
-static int read_eeprom(long ioaddr, int location, int addr_len)
+static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len)
 {
-	unsigned short retval = 0;
+	unsigned retval = 0;
 	long ee_addr = ioaddr + SCBeeprom;
-	int read_cmd = location | EE_READ_CMD;
-	int i;
-
-	outw(EE_ENB & ~EE_CS, ee_addr);
-	outw(EE_ENB, ee_addr);
 
-	/* Shift the read command bits out. */
-	for (i = 12; i >= 0; i--) {
-		short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
-		outw(EE_ENB | dataval, ee_addr);
-		eeprom_delay(100);
-		outw(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
-		eeprom_delay(150);
-	}
-	outw(EE_ENB, ee_addr);
+	outw(EE_ENB | EE_SHIFT_CLK, ee_addr);
 
-	for (i = 15; i >= 0; i--) {
-		outw(EE_ENB | EE_SHIFT_CLK, ee_addr);
-		eeprom_delay(100);
+	/* Shift the command bits out. */
+	do {
+		short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0;
+		outw(dataval, ee_addr);
+		eeprom_delay();
+		outw(dataval | EE_SHIFT_CLK, ee_addr);
+		eeprom_delay();
 		retval = (retval << 1) | ((inw(ee_addr) & EE_DATA_READ) ? 1 : 0);
-		outw(EE_ENB, ee_addr);
-		eeprom_delay(100);
-	}
+	} while (--cmd_len >= 0);
+	outw(EE_ENB, ee_addr);
 
 	/* Terminate the EEPROM access. */
 	outw(EE_ENB & ~EE_CS, ee_addr);
@@ -723,6 +929,7 @@
 		val = inl(ioaddr + SCBCtrlMDI);
 		if (--boguscnt < 0) {
 			printk(KERN_ERR " mdio_read() timed out with val = %8.8x.\n", val);
+			break;
 		}
 	} while (! (val & 0x10000000));
 	return val & 0xffff;
@@ -737,6 +944,7 @@
 		val = inl(ioaddr + SCBCtrlMDI);
 		if (--boguscnt < 0) {
 			printk(KERN_ERR" mdio_write() timed out with val = %8.8x.\n", val);
+			break;
 		}
 	} while (! (val & 0x10000000));
 	return val & 0xffff;
@@ -744,24 +952,34 @@
 
 
 static int
-speedo_open(struct device *dev)
+speedo_open(struct net_device *dev)
 {
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
 	long ioaddr = dev->base_addr;
 
-#ifdef notdef
-	/* We could reset the chip, but should not need to. */
-	/* In fact we MUST NOT, unless we also re-do the init */
-	outl(0, ioaddr + SCBPort);
-	udelay(10);
+#if defined(HAS_PCI_NETIF)
+	acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D0);
 #endif
 
-	/* This had better be initialized before we initialize the interrupt! */
-	sp->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
-
 	if (speedo_debug > 1)
 		printk(KERN_DEBUG "%s: speedo_open() irq %d.\n", dev->name, dev->irq);
 
+	/* Set up the Tx queue early.. */
+	sp->cur_tx = 0;
+	sp->dirty_tx = 0;
+	sp->last_cmd = 0;
+	sp->tx_full = 0;
+	sp->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
+	sp->in_interrupt = 0;
+
+	/* .. we can safely take handler calls during init. */
+	if (request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ, dev->name, dev)) {
+		return -EAGAIN;
+	}
+	MOD_INC_USE_COUNT;
+
+	dev->if_port = sp->default_port;
+
 #ifdef oh_no_you_dont_unless_you_honour_the_options_passed_in_to_us
 	/* Retrigger negotiation to reset previous errors. */
 	if ((sp->phy[0] & 0x8000) == 0) {
@@ -780,88 +998,30 @@
 	}
 #endif
 
-	/* Load the statistics block address. */
-	wait_for_cmd_done(ioaddr + SCBCmd);
-	outl(virt_to_bus(&sp->lstats), ioaddr + SCBPointer);
-	outw(INT_MASK | CU_STATSADDR, ioaddr + SCBCmd);
-	sp->lstats.done_marker = 0;
-
 	speedo_init_rx_ring(dev);
-	wait_for_cmd_done(ioaddr + SCBCmd);
-	outl(0, ioaddr + SCBPointer);
-	outw(INT_MASK | RX_ADDR_LOAD, ioaddr + SCBCmd);
 
-	/* Todo: verify that we must wait for previous command completion. */
-	wait_for_cmd_done(ioaddr + SCBCmd);
-	outl(virt_to_bus(sp->rx_ringp[0]), ioaddr + SCBPointer);
-	outw(INT_MASK | RX_START, ioaddr + SCBCmd);
-
-	/* Fill the first command with our physical address. */
-	{
-		u16 *eaddrs = (u16 *)dev->dev_addr;
-		u16 *setup_frm = (u16 *)&(sp->tx_ring[0].tx_desc_addr);
-
-		/* Avoid a bug(?!) here by marking the command already completed. */
-		sp->tx_ring[0].status = cpu_to_le32(((CmdSuspend | CmdIASetup) << 16) | 0xa000);
-		sp->tx_ring[0].link = cpu_to_le32(virt_to_bus(&(sp->tx_ring[1])));
-		*setup_frm++ = eaddrs[0];
-		*setup_frm++ = eaddrs[1];
-		*setup_frm++ = eaddrs[2];
-	}
-	sp->last_cmd = (struct descriptor *)&sp->tx_ring[0];
-	sp->cur_tx = 1;
-	sp->dirty_tx = 0;
-	sp->tx_full = 0;
-
-	wait_for_cmd_done(ioaddr + SCBCmd);
-	outl(0, ioaddr + SCBPointer);
-	outw(INT_MASK | CU_CMD_BASE, ioaddr + SCBCmd);
+	/* Fire up the hardware. */
+	outw(SCBMaskAll, ioaddr + SCBCmd);
+	speedo_resume(dev);
 
-	dev->if_port = sp->default_port;
-
-	dev->tbusy = 0;
 	dev->interrupt = 0;
 	dev->start = 1;
-
-	/*
-	 * Request the IRQ last, after we have set up all data structures.
-	 * It would be bad to get an interrupt before we're ready.
-	 *
-	 * Register ourself first before turn on the interrupt. Someone
-	 * else may share the same interrupt. H.J.
-	 */
-	if (request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ,
-					"Intel EtherExpress Pro 10/100 Ethernet", dev)) {
-		return -EAGAIN;
-	}
-
-	/* Start the chip's Tx process and unmask interrupts. */
-	/* Todo: verify that we must wait for previous command completion. */
-	wait_for_cmd_done(ioaddr + SCBCmd);
-	outl(virt_to_bus(&sp->tx_ring[0]), ioaddr + SCBPointer);
-	outw(CU_START, ioaddr + SCBCmd);
+	netif_start_queue(dev);
 
 	/* Setup the chip and configure the multicast list. */
-	sp->mc_setup_frm = NULL;
-	sp->mc_setup_frm_len = 0;
-	sp->mc_setup_busy = 0;
+	sp->mc_setup_head = NULL;
+	sp->mc_setup_tail = NULL;
+	sp->flow_ctrl = sp->partner = 0;
 	sp->rx_mode = -1;			/* Invalid -> always reset the mode. */
 	set_rx_mode(dev);
+	if ((sp->phy[0] & 0x8000) == 0)
+		sp->advertising = mdio_read(ioaddr, sp->phy[0] & 0x1f, 4);
 
 	if (speedo_debug > 2) {
 		printk(KERN_DEBUG "%s: Done speedo_open(), status %8.8x.\n",
 			   dev->name, inw(ioaddr + SCBStatus));
 	}
 
-	wait_for_cmd_done(ioaddr + SCBCmd);
-	outw(CU_DUMPSTATS, ioaddr + SCBCmd);
-
-	/* No need to wait for the command unit to accept here. */
-	if ((sp->phy[0] & 0x8000) == 0)
-		mdio_read(ioaddr, sp->phy[0] & 0x1f, 0);
-
-	MOD_INC_USE_COUNT;
-
 	/* Set the timer.  The timer serves a dual purpose:
 	   1) to monitor the media interface (e.g. link beat) and perhaps switch
 	   to an alternate media type
@@ -873,17 +1033,100 @@
 	sp->timer.function = &speedo_timer;					/* timer handler */
 	add_timer(&sp->timer);
 
+	/* No need to wait for the command unit to accept here. */
+	if ((sp->phy[0] & 0x8000) == 0)
+		mdio_read(ioaddr, sp->phy[0] & 0x1f, 0);
+
 	return 0;
 }
 
+/* Start the chip hardware after a full reset. */
+static void speedo_resume(struct net_device *dev)
+{
+	struct speedo_private *sp = (struct speedo_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+
+	/* Start with a Tx threshold of 256 (0x..20.... 8 byte units). */
+	sp->tx_threshold = 0x01208000;
+
+	/* Set the segment registers to '0'. */
+	wait_for_cmd_done(ioaddr + SCBCmd);
+	outl(0, ioaddr + SCBPointer);
+	outb(RxAddrLoad, ioaddr + SCBCmd);
+	wait_for_cmd_done(ioaddr + SCBCmd);
+	outb(CUCmdBase, ioaddr + SCBCmd);
+	wait_for_cmd_done(ioaddr + SCBCmd);
+
+	/* Load the statistics block and rx ring addresses. */
+	outl(virt_to_bus(&sp->lstats), ioaddr + SCBPointer);
+	outb(CUStatsAddr, ioaddr + SCBCmd);
+	sp->lstats.done_marker = 0;
+	wait_for_cmd_done(ioaddr + SCBCmd);
+
+	if (sp->rx_ringp[sp->cur_rx % RX_RING_SIZE] == NULL) {
+		if (speedo_debug > 2)
+			printk(KERN_DEBUG "%s: NULL cur_rx in speedo_resume().\n",
+					dev->name);
+	} else {
+		outl(virt_to_bus(sp->rx_ringp[sp->cur_rx % RX_RING_SIZE]),
+			 ioaddr + SCBPointer);
+		outb(RxStart, ioaddr + SCBCmd);
+		wait_for_cmd_done(ioaddr + SCBCmd);
+	}
+
+	outb(CUDumpStats, ioaddr + SCBCmd);
+
+	/* Fill the first command with our physical address. */
+	{
+		struct descriptor *ias_cmd;
+
+		ias_cmd =
+			(struct descriptor *)&sp->tx_ring[sp->cur_tx++ % TX_RING_SIZE];
+		/* Avoid a bug(?!) here by marking the command already completed. */
+		ias_cmd->cmd_status = cpu_to_le32((CmdSuspend | CmdIASetup) | 0xa000);
+		ias_cmd->link =
+			virt_to_le32desc(&sp->tx_ring[sp->cur_tx % TX_RING_SIZE]);
+		memcpy(ias_cmd->params, dev->dev_addr, 6);
+		sp->last_cmd = ias_cmd;
+	}
+
+	/* Start the chip's Tx process and unmask interrupts. */
+	wait_for_cmd_done(ioaddr + SCBCmd);
+	outl(virt_to_bus(&sp->tx_ring[sp->dirty_tx % TX_RING_SIZE]),
+		 ioaddr + SCBPointer);
+	outw(CUStart, ioaddr + SCBCmd);
+}
+
 /* Media monitoring and control. */
 static void speedo_timer(unsigned long data)
 {
-	struct device *dev = (struct device *)data;
+	struct net_device *dev = (struct net_device *)data;
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+	int phy_num = sp->phy[0] & 0x1f;
 
+	/* We have MII and lost link beat. */
+	if ((sp->phy[0] & 0x8000) == 0) {
+		int partner = mdio_read(ioaddr, phy_num, 5);
+		if (partner != sp->partner) {
+			int flow_ctrl = sp->advertising & partner & 0x0400 ? 1 : 0;
+			if (speedo_debug > 2)
+				printk(KERN_DEBUG "%s: Link status change.\n", dev->name);
+			sp->partner = partner;
+			if (flow_ctrl != sp->flow_ctrl) {
+				sp->flow_ctrl = flow_ctrl;
+				sp->rx_mode = -1;	/* Trigger a reload. */
+			}
+			/* Clear sticky bit. */
+			mdio_read(ioaddr, phy_num, 1);
+			/* If link beat has returned... */
+			if (mdio_read(ioaddr, phy_num, 1) & 0x0004)
+				dev->flags |= IFF_RUNNING;
+			else
+				dev->flags &= ~IFF_RUNNING;
+		}
+	}
 	if (speedo_debug > 3) {
-		long ioaddr = dev->base_addr;
 		printk(KERN_DEBUG "%s: Media control tick, status %4.4x.\n",
 			   dev->name, inw(ioaddr + SCBStatus));
 	}
@@ -892,6 +1135,9 @@
 		/* We haven't received a packet in a Long Time.  We might have been
 		   bitten by the receiver hang bug.  This can be cleared by sending
 		   a set multicast list command. */
+		if (speedo_debug > 2)
+			printk(KERN_DEBUG "%s: Sending a multicast list set command"
+				   " from a timer routine.\n", dev->name);
 		set_rx_mode(dev);
 	}
 	/* We must continue to monitor the media. */
@@ -899,9 +1145,48 @@
 	add_timer(&sp->timer);
 }
 
+static void speedo_show_state(struct net_device *dev)
+{
+	struct speedo_private *sp = (struct speedo_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+	int phy_num = sp->phy[0] & 0x1f;
+	int i;
+
+	/* Print a few items for debugging. */
+	if (speedo_debug > 0) {
+		int i;
+		printk(KERN_DEBUG "%s: Tx ring dump,  Tx queue %u / %u:\n", dev->name,
+			   sp->cur_tx, sp->dirty_tx);
+		for (i = 0; i < TX_RING_SIZE; i++)
+			printk(KERN_DEBUG "%s:  %c%c%2d %8.8x.\n", dev->name,
+				   i == sp->dirty_tx % TX_RING_SIZE ? '*' : ' ',
+				   i == sp->cur_tx % TX_RING_SIZE ? '=' : ' ',
+				   i, sp->tx_ring[i].status);
+	}
+	printk(KERN_DEBUG "%s: Printing Rx ring"
+		   " (next to receive into %u, dirty index %u).\n",
+		   dev->name, sp->cur_rx, sp->dirty_rx);
+
+	for (i = 0; i < RX_RING_SIZE; i++)
+		printk(KERN_DEBUG "%s: %c%c%c%2d %8.8x.\n", dev->name,
+			   sp->rx_ringp[i] == sp->last_rxf ? 'l' : ' ',
+			   i == sp->dirty_rx % RX_RING_SIZE ? '*' : ' ',
+			   i == sp->cur_rx % RX_RING_SIZE ? '=' : ' ',
+			   i, (sp->rx_ringp[i] != NULL) ?
+					   (unsigned)sp->rx_ringp[i]->status : 0);
+
+	for (i = 0; i < 16; i++) {
+		/* FIXME: what does it mean?  --SAW */
+		if (i == 6) i = 21;
+		printk(KERN_DEBUG "%s:  PHY index %d register %d is %4.4x.\n",
+			   dev->name, phy_num, i, mdio_read(ioaddr, phy_num, i));
+	}
+
+}
+
 /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
 static void
-speedo_init_rx_ring(struct device *dev)
+speedo_init_rx_ring(struct net_device *dev)
 {
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
 	struct RxFD *rxf, *last_rxf = NULL;
@@ -920,139 +1205,264 @@
 		sp->rx_ringp[i] = rxf;
 		skb_reserve(skb, sizeof(struct RxFD));
 		if (last_rxf)
-			last_rxf->link = cpu_to_le32(virt_to_bus(rxf));
+			last_rxf->link = virt_to_le32desc(rxf);
 		last_rxf = rxf;
-		rxf->status = cpu_to_le32(0x00000001); 			/* '1' is flag value only. */
+		rxf->status = cpu_to_le32(0x00000001);	/* '1' is flag value only. */
 		rxf->link = 0;						/* None yet. */
 		/* This field unused by i82557, we use it as a consistency check. */
 #ifdef final_version
 		rxf->rx_buf_addr = 0xffffffff;
 #else
-		rxf->rx_buf_addr = cpu_to_le32(virt_to_bus(skb->tail));
+		rxf->rx_buf_addr = virt_to_bus(skb->tail);
 #endif
-		rxf->count = 0;
-		rxf->size = cpu_to_le16(PKT_BUF_SZ);
+		rxf->count = cpu_to_le32(PKT_BUF_SZ << 16);
 	}
 	sp->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
 	/* Mark the last entry as end-of-list. */
-	last_rxf->status = cpu_to_le32(0xC0000002); 			/* '2' is flag value only. */
+	last_rxf->status = cpu_to_le32(0xC0000002);	/* '2' is flag value only. */
 	sp->last_rxf = last_rxf;
 }
 
-static void speedo_tx_timeout(struct device *dev)
+static void speedo_purge_tx(struct net_device *dev)
+{
+	struct speedo_private *sp = (struct speedo_private *)dev->priv;
+	int entry;
+
+	while ((int)(sp->cur_tx - sp->dirty_tx) > 0) {
+		entry = sp->dirty_tx % TX_RING_SIZE;
+		if (sp->tx_skbuff[entry]) {
+			sp->stats.tx_errors++;
+			dev_free_skb(sp->tx_skbuff[entry]);
+			sp->tx_skbuff[entry] = 0;
+		}
+		sp->dirty_tx++;
+	}
+	while (sp->mc_setup_head != NULL) {
+		struct speedo_mc_block *t;
+		if (speedo_debug > 1)
+			printk(KERN_DEBUG "%s: freeing mc frame.\n", dev->name);
+		t = sp->mc_setup_head->next;
+		kfree(sp->mc_setup_head);
+		sp->mc_setup_head = t;
+	}
+	sp->mc_setup_tail = NULL;
+	sp->tx_full = 0;
+	netif_wake_queue(dev);
+}
+
+static void speedo_tx_timeout(struct net_device *dev)
 {
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
 	long ioaddr = dev->base_addr;
+	int status = inw(ioaddr + SCBStatus);
+	unsigned long flags;
 
 	printk(KERN_WARNING "%s: Transmit timed out: status %4.4x "
 		   " %4.4x at %d/%d command %8.8x.\n",
-		   dev->name, inw(ioaddr + SCBStatus), inw(ioaddr + SCBCmd),
+		   dev->name, status, inw(ioaddr + SCBCmd),
 		   sp->dirty_tx, sp->cur_tx,
-		   le32_to_cpu(sp->tx_ring[sp->dirty_tx % TX_RING_SIZE].status));
-	if ((inw(ioaddr + SCBStatus) & 0x00C0) != 0x0080) {
+		   sp->tx_ring[sp->dirty_tx % TX_RING_SIZE].status);
+
+	/* Trigger a stats dump to give time before the reset. */
+	speedo_get_stats(dev);
+
+	speedo_show_state(dev);
+#if 0
+	if ((status & 0x00C0) != 0x0080
+		&&  (status & 0x003C) == 0x0010) {
+		/* Only the command unit has stopped. */
 		printk(KERN_WARNING "%s: Trying to restart the transmitter...\n",
 			   dev->name);
 		outl(virt_to_bus(&sp->tx_ring[sp->dirty_tx % TX_RING_SIZE]),
 			 ioaddr + SCBPointer);
-		outw(CU_START, ioaddr + SCBCmd);
+		outw(CUStart, ioaddr + SCBCmd);
 	} else {
-		outw(DRVR_INT, ioaddr + SCBCmd);
+#else
+	{
+#endif
+		start_bh_atomic();
+		/* Ensure that timer routine doesn't run! */
+		del_timer(&sp->timer);
+		end_bh_atomic();
+		/* Reset the Tx and Rx units. */
+		outl(PortReset, ioaddr + SCBPort);
+		/* We may get spurious interrupts here.  But I don't think that they
+		   may do much harm.  1999/12/09 SAW */
+		udelay(10);
+		/* Disable interrupts. */
+		outw(SCBMaskAll, ioaddr + SCBCmd);
+		synchronize_irq();
+		speedo_tx_buffer_gc(dev);
+		/* Free as much as possible.
+		   It helps to recover from a hang because of out-of-memory.
+		   It also simplifies speedo_resume() in case TX ring is full or
+		   close-to-be full. */
+		speedo_purge_tx(dev);
+		speedo_refill_rx_buffers(dev, 1);
+		spin_lock_irqsave(&sp->lock, flags);
+		speedo_resume(dev);
+		sp->rx_mode = -1;
+		dev->trans_start = jiffies;
+		spin_unlock_irqrestore(&sp->lock, flags);
+		set_rx_mode(dev); /* it takes the spinlock itself --SAW */
+		sp->timer.expires = RUN_AT(2*HZ);
+		add_timer(&sp->timer);
 	}
-#ifdef oh_no_you_dont_unless_you_honour_the_options_passed_in_to_us
 	/* Reset the MII transceiver, suggested by Fred Young @ scalable.com. */
 	if ((sp->phy[0] & 0x8000) == 0) {
 		int phy_addr = sp->phy[0] & 0x1f;
+		int advertising = mdio_read(ioaddr, phy_addr, 4);
+		int mii_bmcr = mdio_read(ioaddr, phy_addr, 0);
 		mdio_write(ioaddr, phy_addr, 0, 0x0400);
 		mdio_write(ioaddr, phy_addr, 1, 0x0000);
 		mdio_write(ioaddr, phy_addr, 4, 0x0000);
 		mdio_write(ioaddr, phy_addr, 0, 0x8000);
 #ifdef honor_default_port
 		mdio_write(ioaddr, phy_addr, 0, mii_ctrl[dev->default_port & 7]);
+#else
+		mdio_read(ioaddr, phy_addr, 0);
+		mdio_write(ioaddr, phy_addr, 0, mii_bmcr);
+		mdio_write(ioaddr, phy_addr, 4, advertising);
 #endif
 	}
-#endif
-	sp->stats.tx_errors++;
-	dev->trans_start = jiffies;
 	return;
 }
 
 static int
-speedo_start_xmit(struct sk_buff *skb, struct device *dev)
+speedo_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
 	long ioaddr = dev->base_addr;
 	int entry;
 
-	/* Block a timer-based transmit from overlapping.  This could better be
-	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
-	   If this ever occurs the queue layer is doing something evil! */
-	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
+#if ! defined(HAS_NETIF_QUEUE)
+	if (test_bit(0, (void*)&dev->tbusy) != 0) {
 		int tickssofar = jiffies - dev->trans_start;
 		if (tickssofar < TX_TIMEOUT - 2)
 			return 1;
 		if (tickssofar < TX_TIMEOUT) {
 			/* Reap sent packets from the full Tx queue. */
-			outw(DRVR_INT, ioaddr + SCBCmd);
+			outw(SCBTriggerIntr, ioaddr + SCBCmd);
 			return 1;
 		}
 		speedo_tx_timeout(dev);
 		return 1;
 	}
-
-	/* Caution: the write order is important here, set the base address
-	   with the "ownership" bits last. */
+#endif
 
 	{	/* Prevent interrupts from changing the Tx ring from underneath us. */
 		unsigned long flags;
 
 		spin_lock_irqsave(&sp->lock, flags);
 
+		/* Check if there are enough space. */
+		if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) {
+			printk(KERN_ERR "%s: incorrect tbusy state, fixed.\n", dev->name);
+			netif_stop_queue(dev);
+			sp->tx_full = 1;
+			spin_unlock_irqrestore(&sp->lock, flags);
+			return 1;
+		}
+
 		/* Calculate the Tx descriptor entry. */
 		entry = sp->cur_tx++ % TX_RING_SIZE;
 
 		sp->tx_skbuff[entry] = skb;
-		/* Todo: be a little more clever about setting the interrupt bit. */
 		sp->tx_ring[entry].status =
-			cpu_to_le32((CmdSuspend | CmdTx | CmdTxFlex) << 16);
+			cpu_to_le32(CmdSuspend | CmdTx | CmdTxFlex);
+		if (!(entry & ((TX_RING_SIZE>>2)-1)))
+			sp->tx_ring[entry].status |= cpu_to_le32(CmdIntr);
 		sp->tx_ring[entry].link =
-		  cpu_to_le32(virt_to_bus(&sp->tx_ring[sp->cur_tx % TX_RING_SIZE]));
+			virt_to_le32desc(&sp->tx_ring[sp->cur_tx % TX_RING_SIZE]);
 		sp->tx_ring[entry].tx_desc_addr =
-		  cpu_to_le32(virt_to_bus(&sp->tx_ring[entry].tx_buf_addr0));
-		/* The data region is always in one buffer descriptor, Tx FIFO
-		   threshold of 256. */
-		sp->tx_ring[entry].count = cpu_to_le32(0x01208000);
-		sp->tx_ring[entry].tx_buf_addr0 = cpu_to_le32(virt_to_bus(skb->data));
+			virt_to_le32desc(&sp->tx_ring[entry].tx_buf_addr0);
+		/* The data region is always in one buffer descriptor. */
+		sp->tx_ring[entry].count = cpu_to_le32(sp->tx_threshold);
+		sp->tx_ring[entry].tx_buf_addr0 = virt_to_le32desc(skb->data);
 		sp->tx_ring[entry].tx_buf_size0 = cpu_to_le32(skb->len);
-		/* Todo: perhaps leave the interrupt bit set if the Tx queue is more
-		   than half full.  Argument against: we should be receiving packets
-		   and scavenging the queue.  Argument for: if so, it shouldn't
-		   matter. */
-		sp->last_cmd->command &= cpu_to_le16(~(CmdSuspend | CmdIntr));
-		sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry];
-
 		/* Trigger the command unit resume. */
 		wait_for_cmd_done(ioaddr + SCBCmd);
-		outw(CU_RESUME, ioaddr + SCBCmd);
+		clear_suspend(sp->last_cmd);
+		/* We want the time window between clearing suspend flag on the previous
+		   command and resuming CU to be as small as possible.
+		   Interrupts in between are very undesired.  --SAW */
+		outb(CUResume, ioaddr + SCBCmd);
+		sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry];
+
+		/* Leave room for set_rx_mode(). If there is no more space than reserved
+		   for multicast filter mark the ring as full. */
+		if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) {
+			netif_stop_queue(dev);
+			sp->tx_full = 1;
+		}
 
 		spin_unlock_irqrestore(&sp->lock, flags);
 	}
 
-	/* Leave room for set_rx_mode() to fill two entries. */
-	if (sp->cur_tx - sp->dirty_tx > TX_RING_SIZE - 3)
-		sp->tx_full = 1;
-	else
-		clear_bit(0, (void*)&dev->tbusy);
-
 	dev->trans_start = jiffies;
 
 	return 0;
 }
 
+static void speedo_tx_buffer_gc(struct net_device *dev)
+{
+	unsigned int dirty_tx;
+	struct speedo_private *sp = (struct speedo_private *)dev->priv;
+
+	dirty_tx = sp->dirty_tx;
+	while ((int)(sp->cur_tx - dirty_tx) > 0) {
+		int entry = dirty_tx % TX_RING_SIZE;
+		int status = le32_to_cpu(sp->tx_ring[entry].status);
+
+		if (speedo_debug > 5)
+			printk(KERN_DEBUG " scavenge candidate %d status %4.4x.\n",
+				   entry, status);
+		if ((status & StatusComplete) == 0)
+			break;			/* It still hasn't been processed. */
+		if (status & TxUnderrun)
+			if (sp->tx_threshold < 0x01e08000) {
+				if (speedo_debug > 2)
+					printk(KERN_DEBUG "%s: TX underrun, threshold adjusted.\n",
+						   dev->name);
+				sp->tx_threshold += 0x00040000;
+			}
+		/* Free the original skb. */
+		if (sp->tx_skbuff[entry]) {
+			sp->stats.tx_packets++;	/* Count only user packets. */
+			sp->stats.tx_bytes += sp->tx_skbuff[entry]->len;
+			dev_free_skb(sp->tx_skbuff[entry]);
+			sp->tx_skbuff[entry] = 0;
+		}
+		dirty_tx++;
+	}
+
+	if (speedo_debug && (int)(sp->cur_tx - dirty_tx) > TX_RING_SIZE) {
+		printk(KERN_ERR "out-of-sync dirty pointer, %d vs. %d,"
+			   " full=%d.\n",
+			   dirty_tx, sp->cur_tx, sp->tx_full);
+		dirty_tx += TX_RING_SIZE;
+	}
+
+	while (sp->mc_setup_head != NULL
+		   && (int)(dirty_tx - sp->mc_setup_head->tx - 1) > 0) {
+		struct speedo_mc_block *t;
+		if (speedo_debug > 1)
+			printk(KERN_DEBUG "%s: freeing mc frame.\n", dev->name);
+		t = sp->mc_setup_head->next;
+		kfree(sp->mc_setup_head);
+		sp->mc_setup_head = t;
+	}
+	if (sp->mc_setup_head == NULL)
+		sp->mc_setup_tail = NULL;
+
+	sp->dirty_tx = dirty_tx;
+}
+
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
 static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 {
-	struct device *dev = (struct device *)dev_instance;
+	struct net_device *dev = (struct net_device *)dev_instance;
 	struct speedo_private *sp;
 	long ioaddr, boguscnt = max_interrupt_work;
 	unsigned short status;
@@ -1066,9 +1476,15 @@
 
 	ioaddr = dev->base_addr;
 	sp = (struct speedo_private *)dev->priv;
-	spin_lock(&sp->lock);
 
 #ifndef final_version
+	/* A lock to prevent simultaneous entry on SMP machines. */
+	if (test_and_set_bit(0, (void*)&sp->in_interrupt)) {
+		printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
+			   dev->name);
+		sp->in_interrupt = 0;	/* Avoid halting machine. */
+		return;
+	}
 	dev->interrupt = 1;
 #endif
 
@@ -1084,63 +1500,90 @@
 		if ((status & 0xfc00) == 0)
 			break;
 
-		if (status & 0x4000)	 /* Packet received. */
+		/* Always check if all rx buffers are allocated.  --SAW */
+		speedo_refill_rx_buffers(dev, 0);
+
+		if ((status & 0x5000) ||	/* Packet received, or Rx error. */
+			(sp->rx_ring_state&(RrNoMem|RrPostponed)) == RrPostponed)
+									/* Need to gather the postponed packet. */
 			speedo_rx(dev);
 
 		if (status & 0x1000) {
-		  if ((status & 0x003c) == 0x0028) /* No more Rx buffers. */
-			outw(RX_RESUMENR, ioaddr + SCBCmd);
-		  else if ((status & 0x003c) == 0x0008) { /* No resources (why?!) */
-			/* No idea of what went wrong.  Restart the receiver. */
+			spin_lock(&sp->lock);
+			if ((status & 0x003c) == 0x0028) {		/* No more Rx buffers. */
+				struct RxFD *rxf;
+				printk(KERN_WARNING "%s: card reports no RX buffers.\n",
+						dev->name);
+				rxf = sp->rx_ringp[sp->cur_rx % RX_RING_SIZE];
+				if (rxf == NULL) {
+					if (speedo_debug > 2)
+						printk(KERN_DEBUG
+								"%s: NULL cur_rx in speedo_interrupt().\n",
+								dev->name);
+					sp->rx_ring_state |= RrNoMem|RrNoResources;
+				} else if (rxf == sp->last_rxf) {
+					if (speedo_debug > 2)
+						printk(KERN_DEBUG
+								"%s: cur_rx is last in speedo_interrupt().\n",
+								dev->name);
+					sp->rx_ring_state |= RrNoMem|RrNoResources;
+				} else
+					outb(RxResumeNoResources, ioaddr + SCBCmd);
+			} else if ((status & 0x003c) == 0x0008) { /* No resources. */
+				struct RxFD *rxf;
+				printk(KERN_WARNING "%s: card reports no resources.\n",
+						dev->name);
+				rxf = sp->rx_ringp[sp->cur_rx % RX_RING_SIZE];
+				if (rxf == NULL) {
+					if (speedo_debug > 2)
+						printk(KERN_DEBUG
+								"%s: NULL cur_rx in speedo_interrupt().\n",
+								dev->name);
+					sp->rx_ring_state |= RrNoMem|RrNoResources;
+				} else if (rxf == sp->last_rxf) {
+					if (speedo_debug > 2)
+						printk(KERN_DEBUG
+								"%s: cur_rx is last in speedo_interrupt().\n",
+								dev->name);
+					sp->rx_ring_state |= RrNoMem|RrNoResources;
+				} else {
+					/* Restart the receiver. */
+					outl(virt_to_bus(sp->rx_ringp[sp->cur_rx % RX_RING_SIZE]),
+					   ioaddr + SCBPointer);
+					outb(RxStart, ioaddr + SCBCmd);
+				}
+			}
+			sp->stats.rx_errors++;
+			spin_unlock(&sp->lock);
+		}
+
+		if ((sp->rx_ring_state&(RrNoMem|RrNoResources)) == RrNoResources) {
+			printk(KERN_WARNING
+					"%s: restart the receiver after a possible hang.\n",
+					dev->name);
+			spin_lock(&sp->lock);
+			/* Restart the receiver.
+			   I'm not sure if it's always right to restart the receiver
+			   here but I don't know another way to prevent receiver hangs.
+			   1999/12/25 SAW */
 			outl(virt_to_bus(sp->rx_ringp[sp->cur_rx % RX_RING_SIZE]),
-				 ioaddr + SCBPointer);
-			outw(RX_START, ioaddr + SCBCmd);
-		  }
-		  sp->stats.rx_errors++;
+			   ioaddr + SCBPointer);
+			outb(RxStart, ioaddr + SCBCmd);
+			sp->rx_ring_state &= ~RrNoResources;
+			spin_unlock(&sp->lock);
 		}
 
 		/* User interrupt, Command/Tx unit interrupt or CU not active. */
 		if (status & 0xA400) {
-			unsigned int dirty_tx = sp->dirty_tx;
-
-			while (sp->cur_tx - dirty_tx > 0) {
-				int entry = dirty_tx % TX_RING_SIZE;
-				int status = le32_to_cpu(sp->tx_ring[entry].status);
-
-				if (speedo_debug > 5)
-					printk(KERN_DEBUG " scavenge candidate %d status %4.4x.\n",
-						   entry, status);
-				if ((status & StatusComplete) == 0)
-					break;			/* It still hasn't been processed. */
-				/* Free the original skb. */
-				if (sp->tx_skbuff[entry]) {
-					sp->stats.tx_packets++;	/* Count only user packets. */
-					sp->stats.tx_bytes += sp->tx_skbuff[entry]->len; /* Count transmitted bytes */
-					dev_free_skb(sp->tx_skbuff[entry]);
-					sp->tx_skbuff[entry] = 0;
-				} else if ((status&0x70000) == CmdNOp << 16)
-					sp->mc_setup_busy = 0;
-				dirty_tx++;
-			}
-
-#ifndef final_version
-			if (sp->cur_tx - dirty_tx > TX_RING_SIZE) {
-				printk(KERN_ERR "out-of-sync dirty pointer, %d vs. %d,"
-					   " full=%d.\n",
-					   dirty_tx, sp->cur_tx, sp->tx_full);
-				dirty_tx += TX_RING_SIZE;
-			}
-#endif
-
-			if (sp->tx_full && dev->tbusy
-				&& dirty_tx > sp->cur_tx - TX_RING_SIZE + 2) {
-				/* The ring is no longer full, clear tbusy. */
+			spin_lock(&sp->lock);
+			speedo_tx_buffer_gc(dev);
+			if (sp->tx_full
+				&& (int)(sp->cur_tx - sp->dirty_tx) < TX_QUEUE_UNFULL) {
+				/* The ring is no longer full. */
 				sp->tx_full = 0;
-				clear_bit(0, (void*)&dev->tbusy);
-				mark_bh(NET_BH);
+				netif_wake_queue(dev); /* Attention: under a spinlock.  --SAW */
 			}
-
-			sp->dirty_tx = dirty_tx;
+			spin_unlock(&sp->lock);
 		}
 
 		if (--boguscnt < 0) {
@@ -1157,34 +1600,131 @@
 			   dev->name, inw(ioaddr + SCBStatus));
 
 	dev->interrupt = 0;
-	spin_unlock(&sp->lock);
+	clear_bit(0, (void*)&sp->in_interrupt);
 	return;
 }
 
+static inline struct RxFD *speedo_rx_alloc(struct net_device *dev, int entry)
+{
+	struct speedo_private *sp = (struct speedo_private *)dev->priv;
+	struct RxFD *rxf;
+	struct sk_buff *skb;
+	/* Get a fresh skbuff to replace the consumed one. */
+	skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD));
+	sp->rx_skbuff[entry] = skb;
+	if (skb == NULL) {
+		sp->rx_ringp[entry] = NULL;
+		return NULL;
+	}
+	rxf = sp->rx_ringp[entry] = (struct RxFD *)skb->tail;
+	skb->dev = dev;
+	skb_reserve(skb, sizeof(struct RxFD));
+	rxf->rx_buf_addr = virt_to_bus(skb->tail);
+	return rxf;
+}
+
+static inline void speedo_rx_link(struct net_device *dev, int entry,
+								  struct RxFD *rxf)
+{
+	struct speedo_private *sp = (struct speedo_private *)dev->priv;
+	rxf->status = cpu_to_le32(0xC0000001); 	/* '1' for driver use only. */
+	rxf->link = 0;			/* None yet. */
+	rxf->count = cpu_to_le32(PKT_BUF_SZ << 16);
+	sp->last_rxf->link = virt_to_le32desc(rxf);
+	sp->last_rxf->status &= cpu_to_le32(~0xC0000000);
+	sp->last_rxf = rxf;
+}
+
+static int speedo_refill_rx_buf(struct net_device *dev, int force)
+{
+	struct speedo_private *sp = (struct speedo_private *)dev->priv;
+	int entry;
+	struct RxFD *rxf;
+
+	entry = sp->dirty_rx % RX_RING_SIZE;
+	if (sp->rx_skbuff[entry] == NULL) {
+		rxf = speedo_rx_alloc(dev, entry);
+		if (rxf == NULL) {
+			unsigned int forw;
+			int forw_entry;
+			if (speedo_debug > 2 || !(sp->rx_ring_state & RrOOMReported)) {
+				printk(KERN_WARNING "%s: can't fill rx buffer (force %d)!\n",
+						dev->name, force);
+				speedo_show_state(dev);
+				sp->rx_ring_state |= RrOOMReported;
+			}
+			if (!force)
+				return -1;	/* Better luck next time!  */
+			/* Borrow an skb from one of next entries. */
+			for (forw = sp->dirty_rx + 1; forw != sp->cur_rx; forw++)
+				if (sp->rx_skbuff[forw % RX_RING_SIZE] != NULL)
+					break;
+			if (forw == sp->cur_rx)
+				return -1;
+			forw_entry = forw % RX_RING_SIZE;
+			sp->rx_skbuff[entry] = sp->rx_skbuff[forw_entry];
+			sp->rx_skbuff[forw_entry] = NULL;
+			rxf = sp->rx_ringp[forw_entry];
+			sp->rx_ringp[forw_entry] = NULL;
+			sp->rx_ringp[entry] = rxf;
+		}
+	} else {
+		rxf = sp->rx_ringp[entry];
+	}
+	speedo_rx_link(dev, entry, rxf);
+	sp->dirty_rx++;
+	sp->rx_ring_state &= ~(RrNoMem|RrOOMReported); /* Mark the progress. */
+	return 0;
+}
+
+static void speedo_refill_rx_buffers(struct net_device *dev, int force)
+{
+	struct speedo_private *sp = (struct speedo_private *)dev->priv;
+
+	/* Refill the RX ring. */
+	while ((int)(sp->cur_rx - sp->dirty_rx) > 0 &&
+			speedo_refill_rx_buf(dev, force) != -1);
+}
+
 static int
-speedo_rx(struct device *dev)
+speedo_rx(struct net_device *dev)
 {
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
 	int entry = sp->cur_rx % RX_RING_SIZE;
 	int status;
 	int rx_work_limit = sp->dirty_rx + RX_RING_SIZE - sp->cur_rx;
+	int alloc_ok = 1;
 
 	if (speedo_debug > 4)
 		printk(KERN_DEBUG " In speedo_rx().\n");
 	/* If we own the next entry, it's a new packet. Send it up. */
 	while (sp->rx_ringp[entry] != NULL &&
 		   (status = le32_to_cpu(sp->rx_ringp[entry]->status)) & RxComplete) {
+		int pkt_len = le32_to_cpu(sp->rx_ringp[entry]->count) & 0x3fff;
 
 		if (--rx_work_limit < 0)
 			break;
+
+		/* Check for a rare out-of-memory case: the current buffer is
+		   the last buffer allocated in the RX ring.  --SAW */
+		if (sp->last_rxf == sp->rx_ringp[entry]) {
+			/* Postpone the packet.  It'll be reaped at an interrupt when this
+			   packet is no longer the last packet in the ring. */
+			if (speedo_debug > 2)
+				printk(KERN_DEBUG "%s: RX packet postponed!\n",
+					   dev->name);
+			sp->rx_ring_state |= RrPostponed;
+			break;
+		}
+
 		if (speedo_debug > 4)
 			printk(KERN_DEBUG "  speedo_rx() status %8.8x len %d.\n", status,
-				   le16_to_cpu(sp->rx_ringp[entry]->count) & 0x3fff);
-		if ((status & (RxErrTooBig|RxOK)) != RxOK) {
+				   pkt_len);
+		if ((status & (RxErrTooBig|RxOK|0x0f90)) != RxOK) {
 			if (status & RxErrTooBig)
 				printk(KERN_ERR "%s: Ethernet frame overran the Rx buffer, "
 					   "status %8.8x!\n", dev->name, status);
-			else if ( ! (status & 0x2000)) {
+			else if (! (status & RxOK)) {
 				/* There was a fatal error.  This *should* be impossible. */
 				sp->stats.rx_errors++;
 				printk(KERN_ERR "%s: Anomalous event in speedo_rx(), "
@@ -1192,7 +1732,6 @@
 					   dev->name, status);
 			}
 		} else {
-			int pkt_len = le16_to_cpu(sp->rx_ringp[entry]->count) & 0x3fff;
 			struct sk_buff *skb;
 
 			/* Check if the packet is long enough to just accept without
@@ -1202,15 +1741,13 @@
 				skb->dev = dev;
 				skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
 				/* 'skb_put()' points to the start of sk_buff data area. */
-#if 1 || USE_IP_CSUM
+#if !defined(__alpha__)
 				/* Packet is in one chunk -- we can copy + cksum. */
-				eth_copy_and_sum(skb,
-								 bus_to_virt(le32_to_cpu(sp->rx_ringp[entry]->rx_buf_addr)),
-								 pkt_len, 0);
+				eth_copy_and_sum(skb, sp->rx_skbuff[entry]->tail, pkt_len, 0);
 				skb_put(skb, pkt_len);
 #else
-				memcpy(skb_put(skb, pkt_len),
-					   bus_to_virt(le32_to_cpu(sp->rx_ringp[entry]->rx_buf_addr)), pkt_len);
+				memcpy(skb_put(skb, pkt_len), sp->rx_skbuff[entry]->tail,
+					   pkt_len);
 #endif
 			} else {
 				void *temp;
@@ -1223,64 +1760,44 @@
 				}
 				sp->rx_skbuff[entry] = NULL;
 				temp = skb_put(skb, pkt_len);
-				if (bus_to_virt(le32_to_cpu(sp->rx_ringp[entry]->rx_buf_addr)) != temp)
+				if (bus_to_virt(sp->rx_ringp[entry]->rx_buf_addr) != temp)
 					printk(KERN_ERR "%s: Rx consistency error -- the skbuff "
 						   "addresses do not match in speedo_rx: %p vs. %p "
 						   "/ %p.\n", dev->name,
-						   bus_to_virt(le32_to_cpu(sp->rx_ringp[entry]->rx_buf_addr)),
+						   bus_to_virt(sp->rx_ringp[entry]->rx_buf_addr),
 						   skb->head, temp);
 				sp->rx_ringp[entry] = NULL;
 			}
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);
 			sp->stats.rx_packets++;
-			sp->stats.rx_bytes += pkt_len; /* Count received bytes */
+			sp->stats.rx_bytes += pkt_len;
 		}
 		entry = (++sp->cur_rx) % RX_RING_SIZE;
+		sp->rx_ring_state &= ~RrPostponed;
+		/* Refill the recently taken buffers.
+		   Do it one-by-one to handle traffic bursts better. */
+		if (alloc_ok && speedo_refill_rx_buf(dev, 0) == -1)
+			alloc_ok = 0;
 	}
 
-	/* Refill the Rx ring buffers. */
-	for (; sp->dirty_rx < sp->cur_rx; sp->dirty_rx++) {
-		struct RxFD *rxf;
-		entry = sp->dirty_rx % RX_RING_SIZE;
-		if (sp->rx_skbuff[entry] == NULL) {
-			struct sk_buff *skb;
-			/* Get a fresh skbuff to replace the consumed one. */
-			skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD));
-			sp->rx_skbuff[entry] = skb;
-			if (skb == NULL) {
-				sp->rx_ringp[entry] = NULL;
-				break;			/* Better luck next time!  */
-			}
-			rxf = sp->rx_ringp[entry] = (struct RxFD *)skb->tail;
-			skb->dev = dev;
-			skb_reserve(skb, sizeof(struct RxFD));
-			rxf->rx_buf_addr = cpu_to_le32(virt_to_bus(skb->tail));
-		} else {
-			rxf = sp->rx_ringp[entry];
-		}
-		rxf->status = cpu_to_le32(0xC0000001); 	/* '1' for driver use only. */
-		rxf->link = 0;			/* None yet. */
-		rxf->count = 0;
-		rxf->size = cpu_to_le16(PKT_BUF_SZ);
-		sp->last_rxf->link = cpu_to_le32(virt_to_bus(rxf));
-		sp->last_rxf->status &= cpu_to_le32(~0xC0000000);
-		sp->last_rxf = rxf;
-	}
+	/* Try hard to refill the recently taken buffers. */
+	speedo_refill_rx_buffers(dev, 1);
 
 	sp->last_rx_time = jiffies;
+
 	return 0;
 }
 
 static int
-speedo_close(struct device *dev)
+speedo_close(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
 	int i;
 
 	dev->start = 0;
-	dev->tbusy = 1;
+	netif_stop_queue(dev);
 
 	if (speedo_debug > 1)
 		printk(KERN_DEBUG "%s: Shutting down ethercard, status was %4.4x.\n",
@@ -1289,13 +1806,16 @@
 	/* Shut off the media monitoring timer. */
 	del_timer(&sp->timer);
 
-	/* Disable interrupts, and stop the chip's Rx process. */
-	outw(INT_MASK, ioaddr + SCBCmd);
-	outw(INT_MASK | RX_ABORT, ioaddr + SCBCmd);
+	/* Shutting down the chip nicely fails to disable flow control. So.. */
+	outl(PortPartialReset, ioaddr + SCBPort);
 
 	free_irq(dev->irq, dev);
 
-	/* Free all the skbuffs in the Rx and Tx queues. */
+	/* Print a few items for debugging. */
+	if (speedo_debug > 3)
+		speedo_show_state(dev);
+
+    /* Free all the skbuffs in the Rx and Tx queues. */
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		struct sk_buff *skb = sp->rx_skbuff[i];
 		sp->rx_skbuff[i] = 0;
@@ -1311,28 +1831,22 @@
 		if (skb)
 			dev_free_skb(skb);
 	}
-	if (sp->mc_setup_frm) {
-		kfree(sp->mc_setup_frm);
-		sp->mc_setup_frm_len = 0;
-	}
 
-	/* Print a few items for debugging. */
-	if (speedo_debug > 3) {
-		int phy_num = sp->phy[0] & 0x1f;
-		printk(KERN_DEBUG "%s:Printing Rx ring (next to receive into %d).\n",
-			   dev->name, sp->cur_rx);
-
-		for (i = 0; i < RX_RING_SIZE; i++)
-			printk(KERN_DEBUG "  Rx ring entry %d  %8.8x.\n",
-				   i, (int)le32_to_cpu(sp->rx_ringp[i]->status));
-
-		for (i = 0; i < 5; i++)
-			printk(KERN_DEBUG "  PHY index %d register %d is %4.4x.\n",
-				   phy_num, i, mdio_read(ioaddr, phy_num, i));
-		for (i = 21; i < 26; i++)
-			printk(KERN_DEBUG "  PHY index %d register %d is %4.4x.\n",
-				   phy_num, i, mdio_read(ioaddr, phy_num, i));
-	}
+	/* Free multicast setting blocks. */
+	for (i = 0; sp->mc_setup_head != NULL; i++) {
+		struct speedo_mc_block *t;
+		t = sp->mc_setup_head->next;
+		kfree(sp->mc_setup_head);
+		sp->mc_setup_head = t;
+	}
+	sp->mc_setup_tail = NULL;
+	if (speedo_debug > 0)
+		printk(KERN_DEBUG "%s: %d multicast blocks dropped.\n", dev->name, i);
+
+#if defined(HAS_PCI_NETIF)
+	/* Alt: acpi_set_pwr_state(pci_bus, pci_devfn, sp->acpi_pwr); */
+	acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D2);
+#endif
 	MOD_DEC_USE_COUNT;
 
 	return 0;
@@ -1351,12 +1865,13 @@
    Oh, and incoming frames are dropped while executing dump-stats!
    */
 static struct enet_statistics *
-speedo_get_stats(struct device *dev)
+speedo_get_stats(struct net_device *dev)
 {
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
 	long ioaddr = dev->base_addr;
 
-	if (le32_to_cpu(sp->lstats.done_marker) == 0xA007) {	/* Previous dump finished */
+	/* Update only if the previous dump finished. */
+	if (sp->lstats.done_marker == le32_to_cpu(0xA007)) {
 		sp->stats.tx_aborted_errors += le32_to_cpu(sp->lstats.tx_coll16_errs);
 		sp->stats.tx_window_errors += le32_to_cpu(sp->lstats.tx_late_colls);
 		sp->stats.tx_fifo_errors += le32_to_cpu(sp->lstats.tx_underruns);
@@ -1370,30 +1885,50 @@
 		sp->stats.rx_length_errors += le32_to_cpu(sp->lstats.rx_runt_errs);
 		sp->lstats.done_marker = 0x0000;
 		if (dev->start) {
+			unsigned long flags;
+			/* Take a spinlock to make wait_for_cmd_done and sending the
+			 * command atomic.  --SAW */
+			spin_lock_irqsave(&sp->lock, flags);
 			wait_for_cmd_done(ioaddr + SCBCmd);
-			outw(CU_DUMPSTATS, ioaddr + SCBCmd);
+			outb(CUDumpStats, ioaddr + SCBCmd);
+			spin_unlock_irqrestore(&sp->lock, flags);
 		}
 	}
 	return &sp->stats;
 }
 
-static int speedo_ioctl(struct device *dev, struct ifreq *rq, int cmd)
+static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
 	long ioaddr = dev->base_addr;
 	u16 *data = (u16 *)&rq->ifr_data;
 	int phy = sp->phy[0] & 0x1f;
+#if defined(HAS_PCI_NETIF)
+	int saved_acpi;
+#endif
 
     switch(cmd) {
 	case SIOCDEVPRIVATE:		/* Get the address of the PHY in use. */
 		data[0] = phy;
 	case SIOCDEVPRIVATE+1:		/* Read the specified MII register. */
+#if defined(HAS_PCI_NETIF)
+		saved_acpi = acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D0);
+		data[3] = mdio_read(ioaddr, data[0], data[1]);
+		acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, saved_acpi);
+#else
 		data[3] = mdio_read(ioaddr, data[0], data[1]);
+#endif
 		return 0;
 	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
+#if defined(HAS_PCI_NETIF)
+		saved_acpi = acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D0);
+		mdio_write(ioaddr, data[0], data[1], data[2]);
+		acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, saved_acpi);
+#else
 		mdio_write(ioaddr, data[0], data[1], data[2]);
+#endif
 		return 0;
 	default:
 		return -EOPNOTSUPP;
@@ -1409,8 +1944,7 @@
    loaded the link -- we convert the current command block, normally a Tx
    command, into a no-op and link it to the new command.
 */
-static void
-set_rx_mode(struct device *dev)
+static void set_rx_mode(struct net_device *dev)
 {
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -1427,9 +1961,13 @@
 	} else
 		new_rx_mode = 0;
 
-	if (sp->cur_tx - sp->dirty_tx >= TX_RING_SIZE - 1) {
-	  /* The Tx ring is full -- don't add anything!  Presumably the new mode
-		 is in config_cmd_data and will be added anyway. */
+	if (speedo_debug > 3)
+		printk(KERN_DEBUG "%s: set_rx_mode %d -> %d\n", dev->name,
+				sp->rx_mode, new_rx_mode);
+
+	if ((int)(sp->cur_tx - sp->dirty_tx) > TX_RING_SIZE - TX_MULTICAST_SIZE) {
+	    /* The Tx ring is full -- don't add anything!  Hope the mode will be
+		 * set again later. */
 		sp->rx_mode = -1;
 		return;
 	}
@@ -1443,9 +1981,9 @@
 		sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry];
 
 		sp->tx_skbuff[entry] = 0;			/* Redundant. */
-		sp->tx_ring[entry].status = cpu_to_le32((CmdSuspend | CmdConfigure) << 16);
+		sp->tx_ring[entry].status = cpu_to_le32(CmdSuspend | CmdConfigure);
 		sp->tx_ring[entry].link =
-			cpu_to_le32(virt_to_bus(&sp->tx_ring[(entry + 1) % TX_RING_SIZE]));
+			virt_to_le32desc(&sp->tx_ring[(entry + 1) % TX_RING_SIZE]);
 		config_cmd_data = (void *)&sp->tx_ring[entry].tx_desc_addr;
 		/* Construct a full CmdConfig frame. */
 		memcpy(config_cmd_data, i82558_config_cmd, sizeof(i82558_config_cmd));
@@ -1453,6 +1991,7 @@
 		config_cmd_data[4] = rxdmacount;
 		config_cmd_data[5] = txdmacount + 0x80;
 		config_cmd_data[15] |= (new_rx_mode & 2) ? 1 : 0;
+		config_cmd_data[19] = sp->flow_ctrl ? 0xBD : 0x80;
 		config_cmd_data[19] |= sp->full_duplex ? 0x40 : 0;
 		config_cmd_data[21] = (new_rx_mode & 1) ? 0x0D : 0x05;
 		if (sp->phy[0] & 0x8000) {			/* Use the AUI port instead. */
@@ -1460,11 +1999,13 @@
 			config_cmd_data[8] = 0;
 		}
 		/* Trigger the command unit resume. */
-		last_cmd->command &= cpu_to_le16(~CmdSuspend);
-
 		wait_for_cmd_done(ioaddr + SCBCmd);
-		outw(CU_RESUME, ioaddr + SCBCmd);
-
+		clear_suspend(last_cmd);
+		outb(CUResume, ioaddr + SCBCmd);
+		if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) {
+			netif_stop_queue(dev);
+			sp->tx_full = 1;
+		}
 		spin_unlock_irqrestore(&sp->lock, flags);
 	}
 
@@ -1480,9 +2021,9 @@
 		sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry];
 
 		sp->tx_skbuff[entry] = 0;
-		sp->tx_ring[entry].status = cpu_to_le32((CmdSuspend | CmdMulticastList) << 16);
+		sp->tx_ring[entry].status = cpu_to_le32(CmdSuspend | CmdMulticastList);
 		sp->tx_ring[entry].link =
-			cpu_to_le32(virt_to_bus(&sp->tx_ring[(entry + 1) % TX_RING_SIZE]));
+			virt_to_le32desc(&sp->tx_ring[(entry + 1) % TX_RING_SIZE]);
 		sp->tx_ring[entry].tx_desc_addr = 0; /* Really MC list count. */
 		setup_params = (u16 *)&sp->tx_ring[entry].tx_desc_addr;
 		*setup_params++ = cpu_to_le16(dev->mc_count*6);
@@ -1495,48 +2036,40 @@
 			*setup_params++ = *eaddrs++;
 		}
 
-		last_cmd->command &= cpu_to_le16(~CmdSuspend);
-
-		/* Immediately trigger the command unit resume. */
 		wait_for_cmd_done(ioaddr + SCBCmd);
-		outw(CU_RESUME, ioaddr + SCBCmd);
+		clear_suspend(last_cmd);
+		/* Immediately trigger the command unit resume. */
+		outb(CUResume, ioaddr + SCBCmd);
 
+		if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) {
+			netif_stop_queue(dev);
+			sp->tx_full = 1;
+		}
 		spin_unlock_irqrestore(&sp->lock, flags);
 	} else if (new_rx_mode == 0) {
 		struct dev_mc_list *mclist;
 		u16 *setup_params, *eaddrs;
-		struct descriptor *mc_setup_frm = sp->mc_setup_frm;
+		struct speedo_mc_block *mc_blk;
+		struct descriptor *mc_setup_frm;
 		int i;
 
-		if (sp->mc_setup_frm_len < 10 + dev->mc_count*6
-			|| sp->mc_setup_frm == NULL) {
-			/* Allocate a full setup frame, 10bytes + <max addrs>. */
-			if (sp->mc_setup_frm)
-				kfree(sp->mc_setup_frm);
-			sp->mc_setup_busy = 0;
-			sp->mc_setup_frm_len = 10 + multicast_filter_limit*6;
-			sp->mc_setup_frm = kmalloc(sp->mc_setup_frm_len, GFP_ATOMIC);
-			if (sp->mc_setup_frm == NULL) {
-				printk(KERN_ERR "%s: Failed to allocate a setup frame.\n",
-					   dev->name);
-				sp->rx_mode = -1; /* We failed, try again. */
-				return;
-			}
-		}
-		/* If we are busy, someone might be quickly adding to the MC list.
-		   Try again later when the list changes stop. */
-		if (sp->mc_setup_busy) {
-			sp->rx_mode = -1;
+		mc_blk = kmalloc(sizeof(*mc_blk) + 2 + multicast_filter_limit*6,
+						 GFP_ATOMIC);
+		if (mc_blk == NULL) {
+			printk(KERN_ERR "%s: Failed to allocate a setup frame.\n",
+				   dev->name);
+			sp->rx_mode = -1; /* We failed, try again. */
 			return;
 		}
-		mc_setup_frm = sp->mc_setup_frm;
+		mc_blk->next = NULL;
+		mc_setup_frm = &mc_blk->frame;
+
 		/* Fill the setup frame. */
 		if (speedo_debug > 1)
-			printk(KERN_DEBUG "%s: Constructing a setup frame at %p, "
-				   "%d bytes.\n",
-				   dev->name, sp->mc_setup_frm, sp->mc_setup_frm_len);
-		mc_setup_frm->status = 0;
-		mc_setup_frm->command = cpu_to_le16(CmdSuspend | CmdIntr | CmdMulticastList);
+			printk(KERN_DEBUG "%s: Constructing a setup frame at %p.\n",
+				   dev->name, mc_setup_frm);
+		mc_setup_frm->cmd_status =
+			cpu_to_le32(CmdSuspend | CmdIntr | CmdMulticastList);
 		/* Link set below. */
 		setup_params = (u16 *)&mc_setup_frm->params;
 		*setup_params++ = cpu_to_le16(dev->mc_count*6);
@@ -1552,26 +2085,35 @@
 		/* Disable interrupts while playing with the Tx Cmd list. */
 		spin_lock_irqsave(&sp->lock, flags);
 
+		if (sp->mc_setup_tail)
+			sp->mc_setup_tail->next = mc_blk;
+		else
+			sp->mc_setup_head = mc_blk;
+		sp->mc_setup_tail = mc_blk;
+		mc_blk->tx = sp->cur_tx;
+
 		entry = sp->cur_tx++ % TX_RING_SIZE;
 		last_cmd = sp->last_cmd;
 		sp->last_cmd = mc_setup_frm;
-		sp->mc_setup_busy++;
 
 		/* Change the command to a NoOp, pointing to the CmdMulti command. */
 		sp->tx_skbuff[entry] = 0;
-		sp->tx_ring[entry].status = cpu_to_le32(CmdNOp << 16);
-		sp->tx_ring[entry].link = cpu_to_le32(virt_to_bus(mc_setup_frm));
+		sp->tx_ring[entry].status = cpu_to_le32(CmdNOp);
+		sp->tx_ring[entry].link = virt_to_le32desc(mc_setup_frm);
 
 		/* Set the link in the setup frame. */
 		mc_setup_frm->link =
-			cpu_to_le32(virt_to_bus(&(sp->tx_ring[(entry+1) % TX_RING_SIZE])));
-
-		last_cmd->command &= cpu_to_le16(~CmdSuspend);
+			virt_to_le32desc(&(sp->tx_ring[(entry+1) % TX_RING_SIZE]));
 
-		/* Immediately trigger the command unit resume. */
 		wait_for_cmd_done(ioaddr + SCBCmd);
-		outw(CU_RESUME, ioaddr + SCBCmd);
+		clear_suspend(last_cmd);
+		/* Immediately trigger the command unit resume. */
+		outb(CUResume, ioaddr + SCBCmd);
 
+		if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) {
+			netif_stop_queue(dev);
+			sp->tx_full = 1;
+		}
 		spin_unlock_irqrestore(&sp->lock, flags);
 
 		if (speedo_debug > 5)
@@ -1584,41 +2126,65 @@
 
 #ifdef MODULE
 
-int
-init_module(void)
+int init_module(void)
 {
 	int cards_found;
 
+	if (debug >= 0 && speedo_debug != debug)
+		printk(KERN_INFO "eepro100.c: Debug level is %d.\n", debug);
 	if (debug >= 0)
 		speedo_debug = debug;
+	/* Always emit the version message. */
 	if (speedo_debug)
 		printk(KERN_INFO "%s", version);
 
-	root_speedo_dev = NULL;
-	cards_found = eepro100_init(NULL);
-	return cards_found ? 0 : -ENODEV;
+#if defined(HAS_PCI_NETIF)
+	cards_found = netif_pci_probe(pci_tbl);
+	if (cards_found < 0)
+		printk(KERN_INFO "eepro100: No cards found, driver not installed.\n");
+	return cards_found;
+#else
+	cards_found = eepro100_init();
+	if (cards_found <= 0) {
+		printk(KERN_INFO "eepro100: No cards found, driver not installed.\n");
+		return -ENODEV;
+	}
+#endif
+	return 0;
 }
 
 void
 cleanup_module(void)
 {
-	struct device *next_dev;
+	struct net_device *next_dev;
 
 	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
 	while (root_speedo_dev) {
-		next_dev = ((struct speedo_private *)root_speedo_dev->priv)->next_module;
+		struct speedo_private *sp = (void *)root_speedo_dev->priv;
 		unregister_netdev(root_speedo_dev);
+#ifdef USE_IO
 		release_region(root_speedo_dev->base_addr, SPEEDO3_TOTAL_SIZE);
+#else
+		iounmap((char *)root_speedo_dev->base_addr);
+#endif
+#if defined(HAS_PCI_NETIF)
+		acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, sp->acpi_pwr);
+#endif
+		next_dev = sp->next_module;
+		if (sp->priv_addr)
+			kfree(sp->priv_addr);
 		kfree(root_speedo_dev);
 		root_speedo_dev = next_dev;
 	}
 }
+
 #else   /* not MODULE */
-int eepro100_probe(struct device *dev)
+
+int eepro100_probe(void)
 {
 	int cards_found = 0;
 
-	cards_found = eepro100_init(dev);
+	cards_found = eepro100_init();
 
 	if (speedo_debug > 0  &&  cards_found)
 		printk(version);
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/epic100.c linux.15p9/drivers/net/epic100.c
--- linux.vanilla/drivers/net/epic100.c	Sat Aug 14 02:26:16 1999
+++ linux.15p9/drivers/net/epic100.c	Tue Jan 18 01:09:21 2000
@@ -1,6 +1,6 @@
 /* epic100.c: A SMC 83c170 EPIC/100 Fast Ethernet driver for Linux. */
 /*
-	Written/copyright 1997-1998 by Donald Becker.
+	Written/copyright 1997-1999 by Donald Becker.
 
 	This software may be used and distributed according to the terms
 	of the GNU Public License, incorporated herein by reference.
@@ -18,44 +18,46 @@
 */
 
 static const char *version =
-"epic100.c:v1.04 8/23/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/epic100.html\n";
+"epic100.c:v1.07h 8/18/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/epic100.html\n";
 
-/* A few user-configurable values. */
+/* User-tunable values. */
 
-/* Keep the ring sizes a power of two for efficiency.
-   Making the Tx ring too large decreases the effectiveness of channel
-   bonding and packet priority.
-   There are no ill effects from too-large receive rings. */
-#define TX_RING_SIZE	16
-#define RX_RING_SIZE	32
+static int debug = 1;
+#define epic_debug debug
+
+/* Used to pass the full-duplex flag, etc. */
+#define MAX_UNITS 8
+static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
+static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 
 /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
    Setting to > 1518 effectively disables this feature. */
 static int rx_copybreak = 200;
 
 /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 10;
+static int max_interrupt_work = 32;
 
 /* Operational parameters that usually are not changed. */
+/* Keep the ring sizes a power of two for efficiency.
+   Making the Tx ring too large decreases the effectiveness of channel
+   bonding and packet priority.
+   There are no ill effects from too-large receive rings. */
+#define TX_RING_SIZE	16
+#define RX_RING_SIZE	32
+
 /* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT  ((2000*HZ)/1000)
+#define TX_TIMEOUT  (2*HZ)
 
 #define PKT_BUF_SZ		1536			/* Size of each temporary Rx buffer.*/
 
 /* Bytes transferred to chip before transmission starts. */
-#define TX_FIFO_THRESH 256		/* Rounded down to 4 byte units. */
+/* Initial threshold, increased on underflow, rounded down to 4 byte units. */
+#define TX_FIFO_THRESH 256
 #define RX_FIFO_THRESH 1		/* 0-3, 0==32, 64,96, or 3==128 bytes  */
 
+#include <linux/config.h>
 #include <linux/version.h>		/* Evil, but neccessary */
-#ifdef MODULE
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
 #include <linux/module.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
 
 #include <linux/kernel.h>
 #include <linux/string.h>
@@ -65,16 +67,12 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#if LINUX_VERSION_CODE >= 0x20155
-#define PCI_SUPPORT_VER2
-#else
-#include <linux/bios32.h>
-#endif
 #include <linux/delay.h>
 
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
+#include <asm/spinlock.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -89,7 +87,6 @@
 
 #define RUN_AT(x) (jiffies + (x))
 
-#if defined(MODULE) && (LINUX_VERSION_CODE >= 0x20115)
 MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
 MODULE_DESCRIPTION("SMC 83c170 EPIC series Ethernet driver");
 MODULE_PARM(debug, "i");
@@ -97,26 +94,12 @@
 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
 MODULE_PARM(rx_copybreak, "i");
 MODULE_PARM(max_interrupt_work, "i");
-#endif
-#if LINUX_VERSION_CODE < 0x20123
-#define test_and_set_bit(val, addr) set_bit(val, addr)
-#endif
-#if LINUX_VERSION_CODE <= 0x20139
-#define	net_device_stats enet_statistics
-#define NETSTATS_VER2
-#endif
-#if LINUX_VERSION_CODE < 0x20159
-#define DEV_FREE_SKB(skb) dev_kfree_skb(skb, FREE_WRITE);
-#else  /* Grrr, unneeded incompatible change. */
-#define DEV_FREE_SKB(skb) dev_kfree_skb(skb);
-#endif
+
+static char kernel_version[] = UTS_RELEASE;
 
 /* The I/O extent. */
 #define EPIC_TOTAL_SIZE 0x100
 
-#define epic_debug debug
-static int epic_debug = 1;
-
 /*
 				Theory of Operation
 
@@ -152,8 +135,20 @@
 /* The rest of these values should never change. */
 
 static struct device *epic_probe1(int pci_bus, int pci_devfn,
+
 								  struct device *dev, long ioaddr, int irq,
 								  int chip_id, int card_idx);
+								  
+/* For 2.2 resource management we are kind of stuck with this */
+#define USE_IO
+
+								  
+#ifdef USE_IO
+#define EPIC_USE_IO
+#define EPIC_IOTYPE PCI_USES_MASTER|PCI_USES_IO|PCI_ADDR0
+#else
+#define EPIC_IOTYPE PCI_USES_MASTER|PCI_USES_MEM|PCI_ADDR1
+#endif
 
 enum pci_flags_bit {
 	PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
@@ -166,14 +161,33 @@
 	int io_size, min_latency;
 	struct device *(*probe1)(int pci_bus, int pci_devfn, struct device *dev,
 							 long ioaddr, int irq, int chip_idx, int fnd_cnt);
-} chip_tbl[] = {
+} static chip_tbl[] = {
 	{"SMSC EPIC/100 83c170", 0x10B8, 0x0005, 0x7fff,
-	 PCI_USES_IO|PCI_USES_MASTER|PCI_ADDR0, EPIC_TOTAL_SIZE, 32, epic_probe1},
+	 EPIC_IOTYPE, EPIC_TOTAL_SIZE, 32, epic_probe1},
 	{"SMSC EPIC/C 83c175", 0x10B8, 0x0006, 0x7fff,
-	 PCI_USES_IO|PCI_USES_MASTER|PCI_ADDR0, EPIC_TOTAL_SIZE, 32, epic_probe1},
+	 EPIC_IOTYPE, EPIC_TOTAL_SIZE, 32, epic_probe1},
 	{0,},
 };
 
+/* This matches the table above. */
+static enum { MII_PWRDWN=1, TYPE2_INTR=2 } chip_features[] ={
+	TYPE2_INTR, TYPE2_INTR | MII_PWRDWN, };
+
+#ifndef USE_IO
+#undef inb
+#undef inw
+#undef inl
+#undef outb
+#undef outw
+#undef outl
+#define inb readb
+#define inw readw
+#define inl readl
+#define outb writeb
+#define outw writew
+#define outl writel
+#endif
+
 /* Offsets to registers, using the (ugh) SMC names. */
 enum epic_registers {
   COMMAND=0, INTSTAT=4, INTMASK=8, GENCTL=0x0C, NVCTL=0x10, EECTL=0x14,
@@ -188,13 +202,21 @@
 
 /* Interrupt register bits, using my own meaningful names. */
 enum IntrStatus {
-  TxIdle=0x40000, RxIdle=0x20000, IntrSummary=0x010000,
-  PCIBusErr170=0x7000, PCIBusErr175=0x1000, PhyEvent175=0x8000,
-  RxStarted=0x0800, RxEarlyWarn=0x0400, CntFull=0x0200, TxUnderrun=0x0100,
-  TxEmpty=0x0080, TxDone=0x0020, RxError=0x0010,
-  RxOverflow=0x0008, RxFull=0x0004, RxHeader=0x0002, RxDone=0x0001,
+	TxIdle=0x40000, RxIdle=0x20000, IntrSummary=0x010000,
+	PCIBusErr170=0x7000, PCIBusErr175=0x1000, PhyEvent175=0x8000,
+	RxStarted=0x0800, RxEarlyWarn=0x0400, CntFull=0x0200, TxUnderrun=0x0100,
+	TxEmpty=0x0080, TxDone=0x0020, RxError=0x0010,
+	RxOverflow=0x0008, RxFull=0x0004, RxHeader=0x0002, RxDone=0x0001,
+};
+enum CommandBits {
+	StopRx=1, StartRx=2, TxQueued=4, RxQueued=8,
+	StopTxDMA=0x20, StopRxDMA=0x40, RestartTx=0x80,
 };
 
+static u16 media2miictl[16] = {
+	0, 0x0C00, 0x0C00, 0x2000,  0x0100, 0x2100, 0, 0,
+	0, 0, 0, 0,  0, 0, 0, 0 };
+
 /* The EPIC100 Rx and Tx buffer descriptors. */
 
 struct epic_tx_desc {
@@ -228,16 +250,22 @@
 	struct sk_buff* rx_skbuff[RX_RING_SIZE];
 
 	/* Ring pointers. */
-	unsigned int cur_rx, cur_tx;		/* The next free ring entry */
-	unsigned int dirty_rx, dirty_tx;	/* The ring entries to be free()ed. */
+	spinlock_t lock;				/* Group with Tx control cache line. */
+	unsigned int cur_tx, dirty_tx;
+	struct descriptor  *last_tx_desc;
+	unsigned int cur_rx, dirty_rx;
+	struct descriptor  *last_rx_desc;
+	long last_rx_time;				/* Last Rx, in jiffies. */
 
 	u8 pci_bus, pci_dev_fn;				/* PCI bus location. */
-	u16 chip_id;
+	u16 chip_flags;
 
 	struct net_device_stats stats;
 	struct timer_list timer;			/* Media selection timer. */
+	int tx_threshold;
 	unsigned char mc_filter[8];
 	signed char phys[4];				/* MII device addresses. */
+	int mii_phy_cnt;
 	unsigned int tx_full:1;				/* The Tx queue is full. */
 	unsigned int full_duplex:1;			/* Current duplex setting. */
 	unsigned int force_fd:1;			/* Full-duplex operation requested. */
@@ -248,11 +276,6 @@
 	int pad0, pad1;						/* Used for 8-byte alignment */
 };
 
-/* Used to pass the full-duplex flag, etc. */
-#define MAX_UNITS 8
-static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
-static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
-
 static int epic_open(struct device *dev);
 static int read_eeprom(long ioaddr, int location);
 static int mdio_read(long ioaddr, int phy_id, int location);
@@ -273,19 +296,19 @@
 /* A list of all installed EPIC devices, for removing the driver module. */
 static struct device *root_epic_dev = NULL;
 
-#ifndef CARDBUS
+#if !defined(CARDBUS)  && !defined(HAS_PCI_NETIF)
 int epic100_probe(struct device *dev)
 {
 	int cards_found = 0;
-	int chip_idx, irq;
+	int chip_idx, irq, pci_flags;
 	u16 pci_command, new_command;
 	unsigned char pci_bus, pci_device_fn;
+	long ioaddr;
 
-#ifdef PCI_SUPPORT_VER2
 	struct pci_dev *pcidev = NULL;
 	while ((pcidev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pcidev))
 			!= NULL) {
-		long pci_ioaddr = pcidev->base_address[0] & ~3;
+		long pciaddr;
 		int vendor = pcidev->vendor;
 		int device = pcidev->device;
 
@@ -294,59 +317,33 @@
 				&& (device & chip_tbl[chip_idx].device_id_mask) ==
 				chip_tbl[chip_idx].device_id)
 				break;
-		if (chip_tbl[chip_idx].vendor_id == 0 		/* Compiled out! */
-			||	check_region(pci_ioaddr, chip_tbl[chip_idx].io_size))
+		if (chip_tbl[chip_idx].vendor_id == 0)		/* Compiled out! */
 			continue;
+
+		pci_flags = chip_tbl[chip_idx].pci_flags;
+		pciaddr = pcidev->base_address[pci_flags & PCI_ADDR0 ? 0 : 1];
 		pci_bus = pcidev->bus->number;
 		pci_device_fn = pcidev->devfn;
 		irq = pcidev->irq;
-#else
-	int pci_index;
-
-	if ( ! pcibios_present())
-		return -ENODEV;
-
-	for (pci_index = 0; pci_index < 0xff; pci_index++) {
-		u8 pci_irq_line;
-		u16 vendor, device;
-		u32 pci_ioaddr;
-
-		if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8,
-								pci_index, &pci_bus, &pci_device_fn)
-			!= PCIBIOS_SUCCESSFUL)
-			break;
-		pcibios_read_config_word(pci_bus, pci_device_fn,
-								 PCI_VENDOR_ID, &vendor);
-		pcibios_read_config_word(pci_bus, pci_device_fn,
-								 PCI_DEVICE_ID, &device);
-
-		for (chip_idx = 0; chip_tbl[chip_idx].vendor_id; chip_idx++)
-			if (vendor == chip_tbl[chip_idx].vendor_id
-				&& (device & chip_tbl[chip_idx].device_id_mask) ==
-				chip_tbl[chip_idx].device_id)
-				break;
-		if (chip_tbl[chip_idx].vendor_id == 0) 		/* Compiled out! */
-			continue;
-
-		pcibios_read_config_dword(pci_bus, pci_device_fn,
-								  PCI_BASE_ADDRESS_0, &pci_ioaddr);
-		pcibios_read_config_byte(pci_bus, pci_device_fn,
-								 PCI_INTERRUPT_LINE, &pci_irq_line);
-		/* Remove I/O space marker in bit 0. */
-		pci_ioaddr &= ~3;
-		irq = pci_irq_line;
 
-		if (check_region(pci_ioaddr, chip_tbl[chip_idx].io_size))
+		if ((pciaddr & PCI_BASE_ADDRESS_SPACE_IO)) {
+			ioaddr = pciaddr & PCI_BASE_ADDRESS_IO_MASK;
+			if (check_region(ioaddr, chip_tbl[chip_idx].io_size))
+				continue;
+		} else if ((ioaddr = (long)ioremap(pciaddr & PCI_BASE_ADDRESS_MEM_MASK,
+										   chip_tbl[chip_idx].io_size)) == 0) {
+			printk(KERN_INFO "Failed to map PCI address %#x.\n",
+				   (int)pciaddr);
 			continue;
-#endif
+		}
 
 		/* EPIC-specific code: Soft-reset the chip ere setting as master. */
-		outl(0x0001, pci_ioaddr + GENCTL);
+		outl(0x0001, ioaddr + GENCTL);
 
 		/* Activate the card: fix for brain-damaged Win98 BIOSes. */
 		pcibios_read_config_word(pci_bus, pci_device_fn,
 								 PCI_COMMAND, &pci_command);
-		new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
+		new_command = pci_command | (pci_flags & 7);
 		if (pci_command != new_command) {
 			printk(KERN_INFO "  The PCI BIOS has not enabled Ethernet"
 				   " device %4.4x-%4.4x."
@@ -356,9 +353,8 @@
 									  PCI_COMMAND, new_command);
 		}
 
-		dev = chip_tbl[chip_idx].probe1(pci_bus, pci_device_fn, dev, pci_ioaddr,
-									   irq, chip_idx, cards_found);
-
+		dev = chip_tbl[chip_idx].probe1(pci_bus, pci_device_fn, dev, ioaddr,
+										irq, chip_idx, cards_found);
 		/* Check the latency timer. */
 		if (dev) {
 			u8 pci_latency;
@@ -402,9 +398,12 @@
 
 	dev->base_addr = ioaddr;
 	dev->irq = irq;
-	printk(KERN_INFO "%s: SMC EPIC/100 at %#lx, IRQ %d, ",
-		   dev->name, ioaddr, dev->irq);
+	printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ",
+		   dev->name, chip_tbl[chip_idx].name, ioaddr, dev->irq);
 
+#if defined(HAS_PCI_NETIF)
+	acpi_set_pwr_state(pci_bus, pci_devfn, ACPI_D0);
+#endif
 	/* Bring the chip out of low-power mode. */
 	outl(0x4200, ioaddr + GENCTL);
 	/* Magic?!  If we don't set this bit the MII interface won't work. */
@@ -418,13 +417,13 @@
 
 	/* This could also be read from the EEPROM. */
 	for (i = 0; i < 3; i++)
-		((u16 *)dev->dev_addr)[i] = inw(ioaddr + LAN0 + i*4);
+		((u16 *)dev->dev_addr)[i] = le16_to_cpu(inw(ioaddr + LAN0 + i*4));
 
 	for (i = 0; i < 5; i++)
 		printk("%2.2x:", dev->dev_addr[i]);
 	printk("%2.2x.\n", dev->dev_addr[i]);
 
-	if (epic_debug > 1) {
+	if (epic_debug > 2) {
 		printk(KERN_DEBUG "%s: EEPROM contents\n", dev->name);
 		for (i = 0; i < 64; i++)
 			printk(" %4.4x%s", read_eeprom(ioaddr, i),
@@ -444,11 +443,7 @@
 
 	ep->pci_bus = pci_bus;
 	ep->pci_dev_fn = pci_devfn;
-#if defined(PCI_SUPPORT_VER2)
-	ep->chip_id = pci_find_slot(pci_bus, pci_devfn)->device;
-#else
-	ep->chip_id = chip_tbl[chip_idx].device_id;
-#endif
+	ep->chip_flags = chip_features[chip_idx];
 
 	/* Find the connected MII xcvrs.
 	   Doing this in open() would allow detecting external xcvrs later, but
@@ -469,6 +464,7 @@
 					   mdio_read(ioaddr, phy, 5));
 			}
 		}
+		ep->mii_phy_cnt = phy_idx;
 		if (phy_idx == 0) {
 			printk(KERN_WARNING "%s: ***WARNING***: No MII transceiver found!\n",
 				   dev->name);
@@ -478,13 +474,13 @@
 	}
 
 	/* Turn off the MII xcvr (175 only!), leave the chip in low-power mode. */
-	if (ep->chip_id == 6)
+	if (ep->chip_flags & MII_PWRDWN)
 		outl(inl(ioaddr + NVCTL) & ~0x483C, ioaddr + NVCTL);
 	outl(0x0008, ioaddr + GENCTL);
 
 	/* The lower four bits are the media type. */
 	ep->force_fd = duplex;
-	ep->default_port = option;
+	dev->if_port = ep->default_port = option;
 	if (ep->default_port)
 		ep->medialock = 1;
 
@@ -514,11 +510,7 @@
    No extra delay is needed with 33Mhz PCI, but 66Mhz is untested.
  */
 
-#ifdef _LINUX_DELAY_H
-#define eeprom_delay(nanosec)	udelay(1)
-#else
-#define eeprom_delay(nanosec)	do { ; } while (0)
-#endif
+#define eeprom_delay()	inl(ee_addr)
 
 /* The EEPROM commands include the alway-set leading bit. */
 #define EE_WRITE_CMD	(5 << 6)
@@ -532,7 +524,7 @@
 	int retval = 0;
 	long ee_addr = ioaddr + EECTL;
 	int read_cmd = location |
-		(inl(ee_addr) & 0x40) ? EE_READ64_CMD : EE_READ256_CMD;
+		(inl(ee_addr) & 0x40 ? EE_READ64_CMD : EE_READ256_CMD);
 
 	outl(EE_ENB & ~EE_CS, ee_addr);
 	outl(EE_ENB, ee_addr);
@@ -541,18 +533,18 @@
 	for (i = 12; i >= 0; i--) {
 		short dataval = (read_cmd & (1 << i)) ? EE_WRITE_1 : EE_WRITE_0;
 		outl(EE_ENB | dataval, ee_addr);
-		eeprom_delay(100);
+		eeprom_delay();
 		outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
-		eeprom_delay(150);
+		eeprom_delay();
 	}
 	outl(EE_ENB, ee_addr);
 
 	for (i = 16; i > 0; i--) {
 		outl(EE_ENB | EE_SHIFT_CLK, ee_addr);
-		eeprom_delay(100);
+		eeprom_delay();
 		retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);
 		outl(EE_ENB, ee_addr);
-		eeprom_delay(100);
+		eeprom_delay();
 	}
 
 	/* Terminate the EEPROM access. */
@@ -594,13 +586,13 @@
 	struct epic_private *ep = (struct epic_private *)dev->priv;
 	long ioaddr = dev->base_addr;
 	int i;
-	int mii_reg5;
+
 	ep->full_duplex = ep->force_fd;
 
 	/* Soft reset the chip. */
 	outl(0x4001, ioaddr + GENCTL);
 
-	if (request_irq(dev->irq, &epic_interrupt, SA_SHIRQ, "SMC EPIC/100", dev))
+	if (request_irq(dev->irq, &epic_interrupt, SA_SHIRQ, dev->name, dev))
 		return -EAGAIN;
 
 	MOD_INC_USE_COUNT;
@@ -617,30 +609,49 @@
 	   wiring on the Ositech CardBus card.
 	*/
 	outl(0x12, ioaddr + MIICfg);
-	if (ep->chip_id == 6)
+	if (ep->chip_flags & MII_PWRDWN)
 		outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
 
 #if defined(__powerpc__) || defined(__sparc__)		/* Big endian */
+	outl(0x4432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
+	inl(ioaddr + GENCTL);
 	outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
 #else
+	outl(0x4412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
+	inl(ioaddr + GENCTL);
 	outl(0x0412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
 #endif
 
 	for (i = 0; i < 3; i++)
-		outl(((u16*)dev->dev_addr)[i], ioaddr + LAN0 + i*4);
+		outl(cpu_to_le16(((u16*)dev->dev_addr)[i]), ioaddr + LAN0 + i*4);
 
-	outl(TX_FIFO_THRESH, ioaddr + TxThresh);
+	
+	ep->tx_threshold = TX_FIFO_THRESH;
+	outl(ep->tx_threshold, ioaddr + TxThresh);
 
-	mii_reg5 = mdio_read(ioaddr, ep->phys[0], 5);
-	if (mii_reg5 != 0xffff) {
-		if ((mii_reg5 & 0x0100) || (mii_reg5 & 0x01C0) == 0x0040)
-			ep->full_duplex = 1;
-		else if (! (mii_reg5 & 0x4000))
-			mdio_write(ioaddr, ep->phys[0], 0, 0x1200);
-		if (epic_debug > 1)
-			printk(KERN_INFO "%s: Setting %s-duplex based on MII xcvr %d"
-				   " register read of %4.4x.\n", dev->name,
-				   ep->full_duplex ? "full" : "half", ep->phys[0], mii_reg5);
+	if (media2miictl[dev->if_port & 15]) {
+		if (ep->mii_phy_cnt)
+			mdio_write(ioaddr, ep->phys[0], 0, media2miictl[dev->if_port&15]);
+		if (dev->if_port == 1) {
+			if (epic_debug > 1)
+				printk(KERN_INFO "%s: Using the 10base2 transceiver, MII "
+					   "status %4.4x.\n",
+					   dev->name, mdio_read(ioaddr, ep->phys[0], 1));
+			outl(0x13, ioaddr + MIICfg);
+		}
+	} else {
+		int mii_reg5 = mdio_read(ioaddr, ep->phys[0], 5);
+		if (mii_reg5 != 0xffff) {
+			if ((mii_reg5 & 0x0100) || (mii_reg5 & 0x01C0) == 0x0040)
+				ep->full_duplex = 1;
+			else if (! (mii_reg5 & 0x4000))
+				mdio_write(ioaddr, ep->phys[0], 0, 0x1200);
+			if (epic_debug > 1)
+				printk(KERN_INFO "%s: Setting %s-duplex based on MII xcvr %d"
+					   " register read of %4.4x.\n", dev->name,
+					   ep->full_duplex ? "full" : "half",
+					   ep->phys[0], mii_reg5);
+		}
 	}
 
 	outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
@@ -649,15 +660,15 @@
 
 	/* Start the chip's Rx process. */
 	set_rx_mode(dev);
-	outl(0x000A, ioaddr + COMMAND);
+	outl(StartRx | RxQueued, ioaddr + COMMAND);
 
 	dev->tbusy = 0;
 	dev->interrupt = 0;
 	dev->start = 1;
 
 	/* Enable interrupts by setting the interrupt mask. */
-	outl((ep->chip_id == 6 ? PCIBusErr175 : PCIBusErr170)
-		 | CntFull | TxUnderrun | TxDone
+	outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170)
+		 | CntFull | TxUnderrun | TxDone | TxEmpty
 		 | RxError | RxOverflow | RxFull | RxHeader | RxDone,
 		 ioaddr + INTMASK);
 
@@ -688,7 +699,7 @@
 	/* Disable interrupts by clearing the interrupt mask. */
 	outl(0x00000000, ioaddr + INTMASK);
 	/* Stop the chip's Tx and Rx DMA processes. */
-	outw(0x0061, ioaddr + COMMAND);
+	outw(StopRx | StopTxDMA | StopRxDMA, ioaddr + COMMAND);
 
 	/* Update the error counts. */
 	if (inw(ioaddr + COMMAND) != 0xffff) {
@@ -716,19 +727,20 @@
 	/* Duplicate code from epic_open(). */
 	outl(0x0008, ioaddr + TEST1);
 
-#if defined(__powerpc__)		/* Big endian */
+#if defined(__powerpc__) || defined(__sparc__)		/* Big endian */
 	outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
 #else
 	outl(0x0412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
 #endif
-	outl(0x12, ioaddr + MIICfg);
-	if (ep->chip_id == 6)
+	outl(dev->if_port == 1 ? 0x13 : 0x12, ioaddr + MIICfg);
+	if (ep->chip_flags & MII_PWRDWN)
 		outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
 
 	for (i = 0; i < 3; i++)
-		outl(((u16*)dev->dev_addr)[i], ioaddr + LAN0 + i*4);
+		outl(cpu_to_le16(((u16*)dev->dev_addr)[i]), ioaddr + LAN0 + i*4);
 
-	outl(TX_FIFO_THRESH, ioaddr + TxThresh);
+	ep->tx_threshold = TX_FIFO_THRESH;
+	outl(ep->tx_threshold, ioaddr + TxThresh);
 	outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
 	outl(virt_to_bus(&ep->rx_ring[ep->cur_rx%RX_RING_SIZE]), ioaddr + PRxCDAR);
 	outl(virt_to_bus(&ep->tx_ring[ep->dirty_tx%TX_RING_SIZE]),
@@ -736,11 +748,11 @@
 
 	/* Start the chip's Rx process. */
 	set_rx_mode(dev);
-	outl(0x000A, ioaddr + COMMAND);
+	outl(StartRx | RxQueued, ioaddr + COMMAND);
 
 	/* Enable interrupts by setting the interrupt mask. */
-	outl((ep->chip_id == 6 ? PCIBusErr175 : PCIBusErr170)
-		 | CntFull | TxUnderrun | TxDone
+	outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170)
+		 | CntFull | TxUnderrun | TxDone | TxEmpty
 		 | RxError | RxOverflow | RxFull | RxHeader | RxDone,
 		 ioaddr + INTMASK);
 	printk(KERN_DEBUG "%s: epic_restart() done, cmd status %4.4x, ctl %4.4x"
@@ -755,17 +767,25 @@
 	struct device *dev = (struct device *)data;
 	struct epic_private *ep = (struct epic_private *)dev->priv;
 	long ioaddr = dev->base_addr;
-	int next_tick = 0;
-	int mii_reg5 = mdio_read(ioaddr, ep->phys[0], 5);
+	int next_tick = 60*HZ;
+	int mii_reg5 = ep->mii_phy_cnt ? mdio_read(ioaddr, ep->phys[0], 5) : 0;
 
 	if (epic_debug > 3) {
-		printk(KERN_DEBUG "%s: Media selection tick, Tx status %8.8x.\n",
+		printk(KERN_DEBUG "%s: Media monitor tick, Tx status %8.8x.\n",
 			   dev->name, inl(ioaddr + TxSTAT));
 		printk(KERN_DEBUG "%s: Other registers are IntMask %4.4x "
 			   "IntStatus %4.4x RxStatus %4.4x.\n",
 			   dev->name, inl(ioaddr + INTMASK), inl(ioaddr + INTSTAT),
 			   inl(ioaddr + RxSTAT));
 	}
+
+	if (ep->cur_tx - ep->dirty_tx > TX_RING_SIZE/2  &&
+		jiffies - dev->trans_start > TX_TIMEOUT) {
+		printk(KERN_WARNING "%s: Tx hung, %d vs. %d.\n",
+			   dev->name, ep->cur_tx, ep->dirty_tx);
+		epic_tx_timeout(dev);
+	}
+
 	if (! ep->force_fd  &&  mii_reg5 != 0xffff) {
 		int duplex = (mii_reg5&0x0100) || (mii_reg5 & 0x01C0) == 0x0040;
 		if (ep->full_duplex != duplex) {
@@ -775,13 +795,10 @@
 				   ep->full_duplex ? "full" : "half", ep->phys[0], mii_reg5);
 			outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
 		}
-		next_tick = 60*HZ;
 	}
 
-	if (next_tick) {
-		ep->timer.expires = RUN_AT(next_tick);
-		add_timer(&ep->timer);
-	}
+	ep->timer.expires = RUN_AT(next_tick);
+	add_timer(&ep->timer);
 }
 
 static void epic_tx_timeout(struct device *dev)
@@ -795,19 +812,17 @@
 			   dev->name, inw(ioaddr + TxSTAT));
 		if (epic_debug > 1) {
 			printk(KERN_DEBUG "%s: Tx indices: dirty_tx %d, cur_tx %d.\n",
-			 dev->name, ep->dirty_tx, ep->cur_tx);
+				   dev->name, ep->dirty_tx, ep->cur_tx);
 		}
 	}
 	if (inw(ioaddr + TxSTAT) & 0x10) {		/* Tx FIFO underflow. */
 		ep->stats.tx_fifo_errors++;
-		/* Restart the transmit process. */
-		outl(0x0080, ioaddr + COMMAND);
+		outl(RestartTx, ioaddr + COMMAND);
+	} else {
+		epic_restart(dev);
+		outl(TxQueued, dev->base_addr + COMMAND);
 	}
 
-	/* Perhaps stop and restart the chip's Tx processes . */
-	/* Trigger a transmit demand. */
-	outl(0x0004, dev->base_addr + COMMAND);
-
 	dev->trans_start = jiffies;
 	ep->stats.tx_errors++;
 	return;
@@ -821,8 +836,10 @@
 	int i;
 
 	ep->tx_full = 0;
-	ep->cur_rx = ep->cur_tx = 0;
-	ep->dirty_rx = ep->dirty_tx = 0;
+	ep->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
+	ep->dirty_tx = ep->cur_tx = 0;
+	ep->cur_rx = ep->dirty_rx = 0;
+	ep->last_rx_time = jiffies;
 
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		ep->rx_ring[i].status = 0x8000;		/* Owned by Epic chip */
@@ -859,15 +876,15 @@
 epic_start_xmit(struct sk_buff *skb, struct device *dev)
 {
 	struct epic_private *ep = (struct epic_private *)dev->priv;
-	int entry;
-	u32 flag;
+	int entry, free_count;
+	u32 ctrl_word;
+	long flags;
 
 	/* Block a timer-based transmit from overlapping.  This could better be
 	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
 	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-		if (jiffies - dev->trans_start < TX_TIMEOUT)
-			return 1;
-		epic_tx_timeout(dev);
+		if (jiffies - dev->trans_start > TX_TIMEOUT)
+			epic_tx_timeout(dev);
 		return 1;
 	}
 
@@ -875,42 +892,41 @@
 	   with the "ownership" bits last. */
 
 	/* Calculate the next Tx descriptor entry. */
-	entry = ep->cur_tx % TX_RING_SIZE;
+	spin_lock_irqsave(&ep->lock, flags);
+	free_count = ep->cur_tx - ep->dirty_tx;
+	entry = ep->cur_tx++ % TX_RING_SIZE;
 
 	ep->tx_skbuff[entry] = skb;
 	ep->tx_ring[entry].txlength = (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN);
 	ep->tx_ring[entry].bufaddr = virt_to_bus(skb->data);
 	ep->tx_ring[entry].buflength = skb->len;
 
-	/* tx_bytes counting -- Nolan Leake */	
-	ep->stats.tx_bytes += ep->tx_ring[entry].txlength;
-	
-	if (ep->cur_tx - ep->dirty_tx < TX_RING_SIZE/2) {/* Typical path */
-	  flag = 0x10; /* No interrupt */
-	  clear_bit(0, (void*)&dev->tbusy);
-	} else if (ep->cur_tx - ep->dirty_tx == TX_RING_SIZE/2) {
-	  flag = 0x14; /* Tx-done intr. */
-	  clear_bit(0, (void*)&dev->tbusy);
-	} else if (ep->cur_tx - ep->dirty_tx < TX_RING_SIZE - 2) {
-	  flag = 0x10; /* No Tx-done intr. */
-	  clear_bit(0, (void*)&dev->tbusy);
+	if (free_count < TX_RING_SIZE/2) {/* Typical path */
+		ctrl_word = 0x10; /* No interrupt */
+	} else if (free_count == TX_RING_SIZE/2) {
+		ctrl_word = 0x14; /* Tx-done intr. */
+	} else if (free_count < TX_RING_SIZE - 1) {
+		ctrl_word = 0x10; /* No Tx-done intr. */
 	} else {
-	  /* Leave room for two additional entries. */
-	  flag = 0x14; /* Tx-done intr. */
-	  ep->tx_full = 1;
+		/* Leave room for an additional entry. */
+		ctrl_word = 0x14; /* Tx-done intr. */
+		ep->tx_full = 1;
 	}
 
-	ep->tx_ring[entry].control = flag;
+	ep->tx_ring[entry].control = ctrl_word;
 	ep->tx_ring[entry].status = 0x8000;	/* Pass ownership to the chip. */
-	ep->cur_tx++;
+
+	if ( ! ep->tx_full)
+		clear_bit(0, (void*)&dev->tbusy);
+	spin_unlock_irqrestore(&ep->lock, flags);
 	/* Trigger an immediate transmit demand. */
-	outl(0x0004, dev->base_addr + COMMAND);
+	outl(TxQueued, dev->base_addr + COMMAND);
 
 	dev->trans_start = jiffies;
 	if (epic_debug > 4)
 		printk(KERN_DEBUG "%s: Queued Tx packet size %d to slot %d, "
 			   "flag %2.2x Tx status %8.8x.\n",
-			   dev->name, (int)skb->len, entry, flag,
+			   dev->name, (int)skb->len, entry, ctrl_word,
 			   inl(dev->base_addr + TxSTAT));
 
 	return 0;
@@ -947,19 +963,26 @@
 		outl(status & 0x00007fff, ioaddr + INTSTAT);
 
 		if (epic_debug > 4)
-			printk("%s: interrupt  interrupt=%#8.8x new intstat=%#8.8x.\n",
+			printk(KERN_DEBUG "%s: interrupt  interrupt=%#8.8x new "
+				   "intstat=%#8.8x.\n",
 				   dev->name, status, inl(ioaddr + INTSTAT));
 
 		if ((status & IntrSummary) == 0)
 			break;
 
-		if (status & (RxDone | RxStarted | RxEarlyWarn))
+		if (status & (RxDone | RxStarted | RxEarlyWarn | RxOverflow))
 			epic_rx(dev);
 
 		if (status & (TxEmpty | TxDone)) {
-			int dirty_tx;
+			unsigned int dirty_tx, cur_tx;
 
-			for (dirty_tx = ep->dirty_tx; dirty_tx < ep->cur_tx; dirty_tx++) {
+			/* Note: if this lock becomes a problem we can narrow the locked
+			   region at the cost of occasionally grabbing the lock more
+			   times. */
+			spin_lock(&ep->lock);
+			cur_tx = ep->cur_tx;
+			dirty_tx = ep->dirty_tx;
+			for (; cur_tx - dirty_tx > 0; dirty_tx++) {
 				int entry = dirty_tx % TX_RING_SIZE;
 				int txstatus = ep->tx_ring[entry].status;
 
@@ -987,34 +1010,35 @@
 #endif
 					ep->stats.collisions += (txstatus >> 8) & 15;
 					ep->stats.tx_packets++;
+					ep->stats.tx_bytes += ep->tx_ring[entry].txlength;
 				}
 
 				/* Free the original skb. */
-				DEV_FREE_SKB(ep->tx_skbuff[entry]);
+				dev_kfree_skb(ep->tx_skbuff[entry]);
 				ep->tx_skbuff[entry] = 0;
 			}
 
 #ifndef final_version
-			if (ep->cur_tx - dirty_tx > TX_RING_SIZE) {
+			if (cur_tx - dirty_tx > TX_RING_SIZE) {
 				printk("%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
-					   dev->name, dirty_tx, ep->cur_tx, ep->tx_full);
+					   dev->name, dirty_tx, cur_tx, ep->tx_full);
 				dirty_tx += TX_RING_SIZE;
 			}
 #endif
-
-			if (ep->tx_full && dev->tbusy
-				&& dirty_tx > ep->cur_tx - TX_RING_SIZE + 2) {
+			ep->dirty_tx = dirty_tx;
+			if (ep->tx_full
+				&& cur_tx - dirty_tx < TX_RING_SIZE + 2) {
 				/* The ring is no longer full, clear tbusy. */
 				ep->tx_full = 0;
 				clear_bit(0, (void*)&dev->tbusy);
+				spin_unlock(&ep->lock);
 				mark_bh(NET_BH);
-			}
-
-			ep->dirty_tx = dirty_tx;
+			} else
+				spin_unlock(&ep->lock);
 		}
 
 		/* Check uncommon events all at once. */
-		if (status & (CntFull | TxUnderrun | RxOverflow |
+		if (status & (CntFull | TxUnderrun | RxOverflow | RxFull |
 					  PCIBusErr170 | PCIBusErr175)) {
 			if (status == 0xffffffff) /* Chip failed or removed (CardBus). */
 				break;
@@ -1025,13 +1049,15 @@
 
 			if (status & TxUnderrun) { /* Tx FIFO underflow. */
 				ep->stats.tx_fifo_errors++;
-				outl(1536, ioaddr + TxThresh);
+				outl(ep->tx_threshold += 128, ioaddr + TxThresh);
 				/* Restart the transmit process. */
-				outl(0x0080, ioaddr + COMMAND);
+				outl(RestartTx, ioaddr + COMMAND);
 			}
 			if (status & RxOverflow) {		/* Missed a Rx frame. */
 				ep->stats.rx_errors++;
 			}
+			if (status & (RxOverflow | RxFull))
+				outw(RxQueued, ioaddr + COMMAND);
 			if (status & PCIBusErr170) {
 				printk(KERN_ERR "%s: PCI Bus Error!  EPIC status %4.4x.\n",
 					   dev->name, status);
@@ -1067,17 +1093,20 @@
 {
 	struct epic_private *ep = (struct epic_private *)dev->priv;
 	int entry = ep->cur_rx % RX_RING_SIZE;
+	int rx_work_limit = ep->dirty_rx + RX_RING_SIZE - ep->cur_rx;
 	int work_done = 0;
 
 	if (epic_debug > 4)
 		printk(KERN_DEBUG " In epic_rx(), entry %d %8.8x.\n", entry,
 			   ep->rx_ring[entry].status);
 	/* If we own the next entry, it's a new packet. Send it up. */
-	while (ep->rx_ring[entry].status >= 0  &&  ep->rx_skbuff[entry]) {
+	while (ep->rx_ring[entry].status >= 0) {
 		int status = ep->rx_ring[entry].status;
 
 		if (epic_debug > 4)
 			printk(KERN_DEBUG "  epic_rx() status was %8.8x.\n", status);
+		if (--rx_work_limit < 0)
+			break;
 		if (status & 0x2006) {
 			if (status & 0x2000) {
 				printk(KERN_WARNING "%s: Oversized Ethernet frame spanned "
@@ -1092,6 +1121,12 @@
 			short pkt_len = ep->rx_ring[entry].rxlength - 4;
 			struct sk_buff *skb;
 
+			if (pkt_len > PKT_BUF_SZ - 4) {
+				printk(KERN_ERR "%s: Oversized Ethernet frame, status %x "
+					   "%d bytes.\n",
+					   dev->name, pkt_len, status);
+				pkt_len = 1514;
+			}
 			/* Check if the packet is long enough to accept without copying
 			   to a minimally-sized skbuff. */
 			if (pkt_len < rx_copybreak
@@ -1106,7 +1141,6 @@
 				memcpy(skb_put(skb, pkt_len),
 					   bus_to_virt(ep->rx_ring[entry].bufaddr), pkt_len);
 #endif
-				ep->rx_ring[entry].status = 0x8000;
 			} else {
 				skb_put(skb = ep->rx_skbuff[entry], pkt_len);
 				ep->rx_skbuff[entry] = NULL;
@@ -1114,8 +1148,9 @@
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);
 			ep->stats.rx_packets++;
-			/* rx_bytes counting -- Nolan Leake */
+#if LINUX_VERSION_CODE > 0x20127
 			ep->stats.rx_bytes += pkt_len;
+#endif
 		}
 		work_done++;
 		entry = (++ep->cur_rx) % RX_RING_SIZE;
@@ -1152,18 +1187,8 @@
 		printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
 			   dev->name, inl(ioaddr + INTSTAT));
 
-	/* Disable interrupts by clearing the interrupt mask. */
-	outl(0x00000000, ioaddr + INTMASK);
-	/* Stop the chip's Tx and Rx DMA processes. */
-	outw(0x0061, ioaddr + COMMAND);
-
-	/* Update the error counts. */
-	ep->stats.rx_missed_errors += inb(ioaddr + MPCNT);
-	ep->stats.rx_frame_errors += inb(ioaddr + ALICNT);
-	ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
-
+	epic_pause(dev);
 	del_timer(&ep->timer);
-
 	free_irq(dev->irq, dev);
 
 	/* Free all the skbuffs in the Rx queue. */
@@ -1177,21 +1202,19 @@
 #if LINUX_VERSION_CODE < 0x20100
 			skb->free = 1;
 #endif
-			DEV_FREE_SKB(skb);
+			dev_kfree_skb(skb);
 		}
 	}
 	for (i = 0; i < TX_RING_SIZE; i++) {
 		if (ep->tx_skbuff[i])
-			DEV_FREE_SKB(ep->tx_skbuff[i]);
+			dev_kfree_skb(ep->tx_skbuff[i]);
 		ep->tx_skbuff[i] = 0;
 	}
 
-
 	/* Green! Leave the chip in low-power mode. */
 	outl(0x0008, ioaddr + GENCTL);
 
 	MOD_DEC_USE_COUNT;
-
 	return 0;
 }
 
@@ -1292,14 +1315,14 @@
 		}
 		data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
 		if (! dev->start) {
-#ifdef notdef
+#ifdef notdef					/* Leave on if the ioctl() is used. */
 			outl(0x0008, ioaddr + GENCTL);
 			outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
 #endif
 		}
 		return 0;
 	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
-		if (!suser())
+		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 		if (! dev->start) {
 			outl(0x0200, ioaddr + GENCTL);
@@ -1307,7 +1330,7 @@
 		}
 		mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]);
 		if (! dev->start) {
-#ifdef notdef
+#ifdef notdef					/* Leave on if the ioctl() is used. */
 			outl(0x0008, ioaddr + GENCTL);
 			outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
 #endif
@@ -1319,122 +1342,29 @@
 }
 
 
-#ifdef CARDBUS
-
-#include <pcmcia/driver_ops.h>
-
-static dev_node_t *epic_attach(dev_locator_t *loc)
-{
-	struct device *dev;
-	u16 dev_id;
-	u32 io;
-	u8 bus, devfn, irq;
-
-	if (loc->bus != LOC_PCI) return NULL;
-	bus = loc->b.pci.bus; devfn = loc->b.pci.devfn;
-	printk(KERN_DEBUG "epic_attach(bus %d, function %d)\n", bus, devfn);
-	pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io);
-	pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq);
-	pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id);
-	io &= ~3;
-	if (io == 0 || irq == 0) {
-		printk(KERN_ERR "The EPIC/C CardBus Ethernet interface was not "
-			   "assigned an %s.\n" KERN_ERR "  It will not be activated.\n",
-			   io == 0 ? "I/O address" : "IRQ");
-		return NULL;
-	}
-	dev = epic_probe1(bus, devfn, NULL, io, irq, 2, -1);
-	if (dev) {
-		dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);
-		strcpy(node->dev_name, dev->name);
-		node->major = node->minor = 0;
-		node->next = NULL;
-		MOD_INC_USE_COUNT;
-		return node;
-	}
-	return NULL;
-}
-
-static void epic_suspend(dev_node_t *node)
-{
-	struct device **devp, **next;
-	printk(KERN_INFO "epic_suspend(%s)\n", node->dev_name);
-	for (devp = &root_epic_dev; *devp; devp = next) {
-		next = &((struct epic_private *)(*devp)->priv)->next_module;
-		if (strcmp((*devp)->name, node->dev_name) == 0) break;
-	}
-	if (*devp) {
-		long ioaddr = (*devp)->base_addr;
-		epic_pause(*devp);
-		/* Put the chip into low-power mode. */
-		outl(0x0008, ioaddr + GENCTL);
-	}
-}
-static void epic_resume(dev_node_t *node)
-{
-	struct device **devp, **next;
-	printk(KERN_INFO "epic_resume(%s)\n", node->dev_name);
-	for (devp = &root_epic_dev; *devp; devp = next) {
-		next = &((struct epic_private *)(*devp)->priv)->next_module;
-		if (strcmp((*devp)->name, node->dev_name) == 0) break;
-	}
-	if (*devp) {
-		epic_restart(*devp);
-	}
-}
-static void epic_detach(dev_node_t *node)
-{
-	struct device **devp, **next;
-	printk(KERN_INFO "epic_detach(%s)\n", node->dev_name);
-	for (devp = &root_epic_dev; *devp; devp = next) {
-		next = &((struct epic_private *)(*devp)->priv)->next_module;
-		if (strcmp((*devp)->name, node->dev_name) == 0) break;
-	}
-	if (*devp) {
-		unregister_netdev(*devp);
-		kfree(*devp);
-		*devp = *next;
-		kfree(node);
-		MOD_DEC_USE_COUNT;
-	}
-}
-
-struct driver_operations epic_ops = {
-	"epic_cb", epic_attach, epic_suspend, epic_resume, epic_detach
-};
-
-#endif  /* Cardbus support */
-
-
 #ifdef MODULE
 
 int init_module(void)
 {
 	if (epic_debug)
 		printk(KERN_INFO "%s", version);
-
-#ifdef CARDBUS
-	register_driver(&epic_ops);
-	return 0;
-#else
 	return epic100_probe(0);
-#endif
 }
 
 void cleanup_module(void)
 {
 	struct device *next_dev;
 
-#ifdef CARDBUS
-	unregister_driver(&epic_ops);
-#endif
-
 	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
 	while (root_epic_dev) {
 		struct epic_private *ep = (struct epic_private *)root_epic_dev->priv;
 		next_dev = ep->next_module;
 		unregister_netdev(root_epic_dev);
+#ifdef EPIC_USE_IO
 		release_region(root_epic_dev->base_addr, EPIC_TOTAL_SIZE);
+#else
+		iounmap((char *)root_epic_dev->base_addr);
+#endif
 		kfree(root_epic_dev);
 		root_epic_dev = next_dev;
 		kfree(ep);
@@ -1446,7 +1376,7 @@
 /*
  * Local variables:
  *  compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c epic100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
- *  cardbus-compile-command: "gcc -DCARDBUS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c epic100.c -o epic_cb.o -I/usr/src/pcmcia-cs-3.0.5/include/"
+ *  cardbus-compile-command: "gcc -DCARDBUS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c epic100.c -o epic_cb.o -I/usr/src/pcmcia-cs-3.0.13/include/"
  *  c-indent-level: 4
  *  c-basic-offset: 4
  *  tab-width: 4
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/eql.c linux.15p9/drivers/net/eql.c
--- linux.vanilla/drivers/net/eql.c	Sat Aug 14 02:27:28 1999
+++ linux.15p9/drivers/net/eql.c	Wed Feb 16 18:25:44 2000
@@ -1030,6 +1030,8 @@
 
 void cleanup_module(void)
 {
+	kfree(((equalizer_t *)dev_eql.priv)->stats );
+	kfree(dev_eql.priv);
 	unregister_netdev(&dev_eql);
 }
 #endif /* MODULE */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/irda/Config.in linux.15p9/drivers/net/irda/Config.in
--- linux.vanilla/drivers/net/irda/Config.in	Sat Aug 14 02:26:48 1999
+++ linux.15p9/drivers/net/irda/Config.in	Fri Jan 21 18:25:23 2000
@@ -6,20 +6,22 @@
 dep_tristate 'IrPORT (IrDA serial driver)' CONFIG_IRPORT_SIR $CONFIG_IRDA
 
 comment 'FIR device drivers'
-dep_tristate 'NSC PC87108' CONFIG_NSC_FIR  $CONFIG_IRDA
+dep_tristate 'NSC PC87108/PC87338' CONFIG_NSC_FIR  $CONFIG_IRDA
 dep_tristate 'Winbond W83977AF (IR)' CONFIG_WINBOND_FIR $CONFIG_IRDA
-dep_tristate 'Sharp UIRCC' CONFIG_SHARP_FIR $CONFIG_IRDA
 dep_tristate 'Toshiba Type-O IR Port' CONFIG_TOSHIBA_FIR $CONFIG_IRDA
-dep_tristate 'SMC IrCC' CONFIG_SMC_IRCC_FIR $CONFIG_IRDA
+if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
+dep_tristate 'SMC IrCC (Experimental)' CONFIG_SMC_IRCC_FIR $CONFIG_IRDA
+fi
 
 comment 'Dongle support' 
 bool 'Serial dongle support' CONFIG_DONGLE
 if [ "$CONFIG_DONGLE" != "n" ]; then
-  dep_tristate '   ESI JetEye PC dongle' CONFIG_ESI_DONGLE $CONFIG_IRDA
-  dep_tristate '   ACTiSYS IR-220L and IR220L+ dongle' CONFIG_ACTISYS_DONGLE $CONFIG_IRDA
-  dep_tristate '   Tekram IrMate 210B dongle' CONFIG_TEKRAM_DONGLE $CONFIG_IRDA
-  dep_tristate '   Greenwich GIrBIL dongle' CONFIG_GIRBIL_DONGLE $CONFIG_IRDA
-  dep_tristate '   Parallax LiteLink dongle' CONFIG_LITELINK_DONGLE $CONFIG_IRDA
+   dep_tristate '  ESI JetEye PC dongle' CONFIG_ESI_DONGLE $CONFIG_IRDA
+   dep_tristate '  ACTiSYS IR-220L and IR220L+ dongle' CONFIG_ACTISYS_DONGLE $CONFIG_IRDA
+   dep_tristate '  Tekram IrMate 210B dongle' CONFIG_TEKRAM_DONGLE $CONFIG_IRDA
+   dep_tristate '  Greenwich GIrBIL dongle' CONFIG_GIRBIL_DONGLE $CONFIG_IRDA
+   dep_tristate '  Parallax LiteLink dongle' CONFIG_LITELINK_DONGLE $CONFIG_IRDA
+   dep_tristate '  Old Belkin dongle' CONFIG_OLD_BELKIN_DONGLE $CONFIG_IRDA   
 fi
 
 endmenu
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/irda/Makefile linux.15p9/drivers/net/irda/Makefile
--- linux.vanilla/drivers/net/irda/Makefile	Wed Oct 20 01:12:39 1999
+++ linux.15p9/drivers/net/irda/Makefile	Tue Jan 18 01:08:17 2000
@@ -21,34 +21,18 @@
 endif
 
 ifeq ($(CONFIG_IRPORT_SIR),y)
-L_OBJS += irport.o
+LX_OBJS += irport.o
 else
   ifeq ($(CONFIG_IRPORT_SIR),m)
-  M_OBJS += irport.o
-  endif
-endif
-
-ifeq ($(CONFIG_IRPORT_SIR),y)
-L_OBJS += irport.o
-else
-  ifeq ($(CONFIG_IRPORT_SIR),m)
-  M_OBJS += irport.o
-  endif
-endif
-
-ifeq ($(CONFIG_IRPORT_SIR),y)
-L_OBJS += irport.o
-else
-  ifeq ($(CONFIG_IRPORT_SIR),m)
-  M_OBJS += irport.o
+  MX_OBJS += irport.o
   endif
 endif
 
 ifeq ($(CONFIG_NSC_FIR),y)
-L_OBJS += pc87108.o
+L_OBJS += nsc-ircc.o
 else
   ifeq ($(CONFIG_NSC_FIR),m)
-  M_OBJS += pc87108.o
+  M_OBJS += nsc-ircc.o
   endif
 endif
 
@@ -60,14 +44,6 @@
   endif
 endif
 
-ifeq ($(CONFIG_SHARP_FIR),y)
-L_OBJS += uircc.o irport.o
-else
-  ifeq ($(CONFIG_SHARP_FIR),m)
-  M_OBJS += uircc.o irport.o
-  endif
-endif
-
 ifeq ($(CONFIG_TOSHIBA_FIR),y)
 L_OBJS += toshoboe.o
 else
@@ -93,10 +69,12 @@
 endif
 
 ifeq ($(CONFIG_SMC_IRCC_FIR),y)
-L_OBJS += irport.o smc-ircc.o
+L_OBJS += smc-ircc.o
+LX_OBJS += irport.o
 else
   ifeq ($(CONFIG_SMC_IRCC_FIR),m)
-  M_OBJS += irport.o smc-ircc.o
+  M_OBJS += smc-ircc.o
+  MX_OBJS += irport.o
   endif
 endif
 
@@ -137,6 +115,14 @@
 else
   ifeq ($(CONFIG_LITELINK_DONGLE),m)
   M_OBJS += litelink.o
+  endif
+endif
+
+ifeq ($(CONFIG_OLD_BELKIN_DONGLE),y)
+L_OBJS += old_belkin.o
+else
+  ifeq ($(CONFIG_OLD_BELKIN_DONGLE),m)
+  M_OBJS += old_belkin.o
   endif
 endif
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/irda/actisys.c linux.15p9/drivers/net/irda/actisys.c
--- linux.vanilla/drivers/net/irda/actisys.c	Sat Aug 14 02:26:48 1999
+++ linux.15p9/drivers/net/irda/actisys.c	Tue Jan 18 01:08:17 2000
@@ -1,16 +1,18 @@
 /*********************************************************************
  *                
  * Filename:      actisys.c
- * Version:       0.8
+ * Version:       1.0
  * Description:   Implementation for the ACTiSYS IR-220L and IR-220L+ 
  *                dongles
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Status:        Beta.
+ * Authors:       Dag Brattli <dagb@cs.uit.no> (initially)
+ *		  Jean Tourrilhes <jt@hpl.hp.com> (new version)
  * Created at:    Wed Oct 21 20:02:35 1998
- * Modified at:   Sun May 16 14:35:11 1999
+ * Modified at:   Fri Dec 17 09:10:43 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1999 Jean Tourrilhes
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -23,6 +25,16 @@
  *     
  ********************************************************************/
 
+/*
+ * Changelog
+ *
+ * 0.8 -> 0.9999 - Jean
+ *	o New initialisation procedure : much safer and correct
+ *	o New procedure the change speed : much faster and simpler
+ *	o Other cleanups & comments
+ *	Thanks to Lichen Wang @ Actisys for his excellent help...
+ */
+
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/tty.h>
@@ -32,42 +44,64 @@
 #include <net/irda/irda.h>
 #include <net/irda/irmod.h>
 #include <net/irda/irda_device.h>
-#include <net/irda/dongle.h>
-
-static void actisys_reset(struct irda_device *dev);
-static void actisys_open(struct irda_device *idev, int type);
-static void actisys_close(struct irda_device *dev);
-static void actisys_change_speed( struct irda_device *dev, int baudrate);
-static void actisys_init_qos(struct irda_device *idev, struct qos_info *qos);
 
-/* These are the baudrates supported */
-static int baud_rates[] = { 9600, 19200, 57600, 115200, 38400};
+/* 
+ * Define the timing of the pulses we send to the dongle (to reset it, and
+ * to toggle speeds). Basically, the limit here is the propagation speed of
+ * the signals through the serial port, the dongle being much faster.  Any
+ * serial port support 115 kb/s, so we are sure that pulses 8.5 us wide can
+ * go through cleanly . If you are on the wild side, you can try to lower
+ * this value (Actisys recommended me 2 us, and 0 us work for me on a P233!)
+ */
+#define MIN_DELAY 10	/* 10 us to be on the conservative side */
 
-static struct dongle dongle = {
-	ACTISYS_DONGLE,
+static int  actisys_change_speed(struct irda_task *task);
+static int  actisys_reset(struct irda_task *task);
+static void actisys_open(dongle_t *self, struct qos_info *qos);
+static void actisys_close(dongle_t *self);
+
+/* These are the baudrates supported, in the order available */
+/* Note : the 220L doesn't support 38400, but we will fix that below */
+static __u32 baud_rates[] = { 9600, 19200, 57600, 115200, 38400 };
+#define MAX_SPEEDS 5
+
+static struct dongle_reg dongle = {
+	Q_NULL,
+	IRDA_ACTISYS_DONGLE,
 	actisys_open,
 	actisys_close,
 	actisys_reset,
 	actisys_change_speed,
-	actisys_init_qos,
 };
 
-static struct dongle dongle_plus = {
-	ACTISYS_PLUS_DONGLE,
+static struct dongle_reg dongle_plus = {
+	Q_NULL,
+	IRDA_ACTISYS_PLUS_DONGLE,
 	actisys_open,
 	actisys_close,
 	actisys_reset,
 	actisys_change_speed,
-	actisys_init_qos,
 };
 
-__initfunc(int actisys_init(void))
+/*
+ * Function actisys_change_speed (task)
+ *
+ *	There is two model of Actisys dongle we are dealing with,
+ * the 220L and 220L+. At this point, only irattach knows with
+ * kind the user has requested (it was an argument on irattach
+ * command line).
+ *	So, we register a dongle of each sort and let irattach
+ * pick the right one...
+ */
+int __init actisys_init(void)
 {
 	int ret;
 
+	/* First, register an Actisys 220L dongle */
 	ret = irda_device_register_dongle(&dongle);
 	if (ret < 0)
 		return ret;
+	/* Now, register an Actisys 220L+ dongle */
 	ret = irda_device_register_dongle(&dongle_plus);
 	if (ret < 0) {
 		irda_device_unregister_dongle(&dongle);
@@ -78,130 +112,165 @@
 
 void actisys_cleanup(void)
 {
+	/* We have to remove both dongles */
 	irda_device_unregister_dongle(&dongle);
 	irda_device_unregister_dongle(&dongle_plus);
 }
 
-static void actisys_open(struct irda_device *idev, int type)
+static void actisys_open(dongle_t *self, struct qos_info *qos)
 {
-	strcat(idev->description, " <-> actisys");
+	/* Power on the dongle */
+	self->set_dtr_rts(self->dev, TRUE, TRUE);
+
+	/* Set the speeds we can accept */
+	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
 
-        idev->io.dongle_id = type;
-	idev->flags |= IFF_DONGLE;
+	/* Remove support for 38400 if this is not a 220L+ dongle */
+	if (self->issue->type == IRDA_ACTISYS_DONGLE)
+		qos->baud_rate.bits &= ~IR_38400;
+	
+	qos->min_turn_time.bits = 0x7f; /* Needs 0.01 ms */
 
 	MOD_INC_USE_COUNT;
 }
 
-static void actisys_close(struct irda_device *idev)
+static void actisys_close(dongle_t *self)
 {
-	/* Power off dongle */
-	irda_device_set_dtr_rts(idev, FALSE, FALSE);
+	/* Power off the dongle */
+	self->set_dtr_rts(self->dev, FALSE, FALSE);
 
 	MOD_DEC_USE_COUNT;
 }
 
 /*
- * Function actisys_change_speed (tty, baud)
+ * Function actisys_change_speed (task)
  *
  *    Change speed of the ACTiSYS IR-220L and IR-220L+ type IrDA dongles.
- *    To cycle through the available baud rates, pulse RTS low for a few
- *    ms.  
+ *    To cycle through the available baud rates, pulse RTS low for a few us.
+ *
+ *	First, we reset the dongle to always start from a known state.
+ *	Then, we cycle through the speeds by pulsing RTS low and then up.
+ *	The dongle allow us to pulse quite fast, se we can set speed in one go,
+ * which is must faster ( < 100 us) and less complex than what is found
+ * in some other dongle drivers...
+ *	Note that even if the new speed is the same as the current speed,
+ * we reassert the speed. This make sure that things are all right,
+ * and it's fast anyway...
+ *	By the way, this function will work for both type of dongles,
+ * because the additional speed is at the end of the sequence...
  */
-static void actisys_change_speed(struct irda_device *idev, int baudrate)
+static int actisys_change_speed(struct irda_task *task)
 {
-        int current_baudrate;
-        int index = 0;
-	
-	DEBUG(4, __FUNCTION__ "()\n");
-
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-	
-	current_baudrate = idev->qos.baud_rate.value;
+	dongle_t *self = (dongle_t *) task->instance;
+	__u32 speed = (__u32) task->param;	/* Target speed */
+	int ret = 0;
+	int i = 0;
+
+        IRDA_DEBUG(4, __FUNCTION__ "(), speed=%d (was %d)\n", speed, 
+		   self->speed);
+
+	/* Go to a known state by reseting the dongle */
+
+	/* Reset the dongle : set DTR low for 10 us */
+	self->set_dtr_rts(self->dev, FALSE, TRUE);
+	udelay(MIN_DELAY);
+
+	/* Go back to normal mode (we are now at 9600 b/s) */
+	self->set_dtr_rts(self->dev, TRUE, TRUE);
+ 
+	/* 
+	 * Now, we can set the speed requested. Send RTS pulses until we
+         * reach the target speed 
+	 */
+	for (i=0; i<MAX_SPEEDS; i++) {
+		if (speed == baud_rates[i]) {
+			self->speed = baud_rates[i];
+			break;
+		}
+		/* Make sure previous pulse is finished */
+		udelay(MIN_DELAY);
+
+		/* Set RTS low for 10 us */
+		self->set_dtr_rts(self->dev, TRUE, FALSE);
+		udelay(MIN_DELAY);
+
+		/* Set RTS high for 10 us */
+		self->set_dtr_rts(self->dev, TRUE, TRUE);
+	}
+
+	/* Check if life is sweet... */
+	if (i >= MAX_SPEEDS)
+		ret = -1;  /* This should not happen */
 
-	/* Find the correct baudrate index for the currently used baudrate */
-	while (current_baudrate != baud_rates[index])
-		index++;
-
-        DEBUG( 4, __FUNCTION__ "(), index=%d\n", index);
-
-	/* Cycle through avaiable baudrates until we reach the correct one */
-        while (current_baudrate != baudrate) {	
-                DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n",
-		      baud_rates[index]);
-		
-		/* Set DTR, clear RTS */
-		irda_device_set_dtr_rts(idev, TRUE, FALSE);
-		
-		/* Wait at a few ms */
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(2);
+	/* Basta lavoro, on se casse d'ici... */
+	irda_task_next_state(task, IRDA_TASK_DONE);
 
-		/* Set DTR, Set RTS */
-		irda_device_set_dtr_rts(idev, TRUE, TRUE);
-		
-		/* Wait at a few ms again */
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(2);
-
-                /* Go to next baudrate */
-		if (idev->io.dongle_id == ACTISYS_DONGLE)
-                        index = (index+1) % 4; /* IR-220L */
-		else
-                        index = (index+1) % 5; /* IR-220L+ */
-
-                current_baudrate = baud_rates[index];
-        }
-	DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n",baud_rates[index]);
+	return ret;
 }
 
 /*
- * Function actisys_reset (dev)
+ * Function actisys_reset (task)
  *
  *      Reset the Actisys type dongle. Warning, this function must only be
  *      called with a process context!
  *
- *    	1. Clear DTR for a few ms.
+ * We need to do two things in this function :
+ *	o first make sure that the dongle is in a state where it can operate
+ *	o second put the dongle in a know state
  *
+ *	The dongle is powered of the RTS and DTR lines. In the dongle, there
+ * is a big capacitor to accomodate the current spikes. This capacitor
+ * takes a least 50 ms to be charged. In theory, the Bios set those lines
+ * up, so by the time we arrive here we should be set. It doesn't hurt
+ * to be on the conservative side, so we will wait...
+ *	Then, we set the speed to 9600 b/s to get in a known state (see in
+ * change_speed for details). It is needed because the IrDA stack
+ * has tried to set the speed immediately after our first return,
+ * so before we can be sure the dongle is up and running.
  */
-static void actisys_reset(struct irda_device *idev)
+static int actisys_reset(struct irda_task *task)
 {
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-	
-	/* Clear DTR */
-	irda_device_set_dtr_rts(idev, FALSE, TRUE);
+	dongle_t *self = (dongle_t *) task->instance;
+	int ret = 0;
 
-	/* Sleep 10-20 ms*/
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(2);
-	
-	/* Go back to normal mode */
-	irda_device_set_dtr_rts(idev, TRUE, TRUE);
-	
-	idev->qos.baud_rate.value = 9600;
-}
+	ASSERT(task != NULL, return -1;);
 
-/*
- * Function actisys_init_qos (qos)
- *
- *    Initialize QoS capabilities
- *
- */
-static void actisys_init_qos(struct irda_device *idev, struct qos_info *qos)
-{
-	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+	self->reset_task = task;
 
-	/* Remove support for 38400 if this is not a 220L+ dongle */
-	if (idev->io.dongle_id == ACTISYS_DONGLE)
-		qos->baud_rate.bits &= ~IR_38400;
+	switch (task->state) {
+	case IRDA_TASK_INIT:
+		/* Set both DTR & RTS to power up the dongle */
+		/* In theory redundant with power up in actisys_open() */
+		self->set_dtr_rts(self->dev, TRUE, TRUE);
+		
+		/* Sleep 50 ms to make sure capacitor is charged */
+		ret = MSECS_TO_JIFFIES(50);
+		irda_task_next_state(task, IRDA_TASK_WAIT);
+		break;
+	case IRDA_TASK_WAIT:			
+		/* Reset the dongle : set DTR low for 10 us */
+		self->set_dtr_rts(self->dev, FALSE, TRUE);
+		udelay(MIN_DELAY);
+
+		/* Go back to normal mode */
+		self->set_dtr_rts(self->dev, TRUE, TRUE);
 	
-	qos->min_turn_time.bits &= 0x40; /* Needs 0.01 ms */
+		irda_task_next_state(task, IRDA_TASK_DONE);
+		self->reset_task = NULL;
+		self->speed = 9600;	/* That's the default */
+		break;
+	default:
+		ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
+		irda_task_next_state(task, IRDA_TASK_DONE);
+		self->reset_task = NULL;
+		ret = -1;
+		break;
+	}
+	return ret;
 }
 
 #ifdef MODULE
-
-MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
+MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no> - Jean Tourrilhes <jt@hpl.hp.com>");
 MODULE_DESCRIPTION("ACTiSYS IR-220L and IR-220L+ dongle driver");	
 		
 /*
@@ -225,5 +294,4 @@
 {
 	actisys_cleanup();
 }
-
-#endif
+#endif /* MODULE */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/irda/esi.c linux.15p9/drivers/net/irda/esi.c
--- linux.vanilla/drivers/net/irda/esi.c	Sat Aug 14 02:26:48 1999
+++ linux.15p9/drivers/net/irda/esi.c	Tue Jan 18 01:08:17 2000
@@ -1,27 +1,33 @@
 /*********************************************************************
  *                
  * Filename:      esi.c
- * Version:       1.4
+ * Version:       1.5
  * Description:   Driver for the Extended Systems JetEye PC dongle
  * Status:        Experimental.
- * Author:        Thomas Davis, <ratbert@radiks.net>
+ * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Feb 21 18:54:38 1998
- * Modified at:   Sun May 16 14:35:21 1999
+ * Modified at:   Fri Dec 17 09:14:04 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * Sources:	  esi.c
- *
- *     Copyright (c) 1998-1999, Dag Brattli, <dagb@cs.uit.no>
- *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>,
+ * 
+ *     Copyright (c) 1999 Dag Brattli, <dagb@cs.uit.no>,
+ *     Copyright (c) 1998 Thomas Davis, <ratbert@radiks.net>,
  *     All Rights Reserved.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
- *
- *     I, Thomas Davis, provide no warranty for any of this software.
- *     This material is provided "AS-IS" and at no charge.
- *
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
  ********************************************************************/
 
 #include <linux/module.h>
@@ -34,25 +40,22 @@
 #include <net/irda/irda.h>
 #include <net/irda/irmod.h>
 #include <net/irda/irda_device.h>
-#include <net/irda/irtty.h>
-#include <net/irda/dongle.h>
 
-static void esi_open(struct irda_device *idev, int type);
-static void esi_close(struct irda_device *driver);
-static void esi_change_speed(struct irda_device *idev, int baud);
-static void esi_reset(struct irda_device *idev);
-static void esi_qos_init(struct irda_device *idev, struct qos_info *qos);
-
-static struct dongle dongle = {
-	ESI_DONGLE,
+static void esi_open(dongle_t *self, struct qos_info *qos);
+static void esi_close(dongle_t *self);
+static int  esi_change_speed(struct irda_task *task);
+static int  esi_reset(struct irda_task *task);
+
+static struct dongle_reg dongle = {
+	Q_NULL,
+	IRDA_ESI_DONGLE,
 	esi_open,
 	esi_close,
 	esi_reset,
 	esi_change_speed,
-	esi_qos_init,
 };
 
-__initfunc(int esi_init(void))
+int __init esi_init(void)
 {
 	return irda_device_register_dongle(&dongle);
 }
@@ -62,38 +65,35 @@
 	irda_device_unregister_dongle(&dongle);
 }
 
-static void esi_open(struct irda_device *idev, int type)
+static void esi_open(dongle_t *self, struct qos_info *qos)
 {
-	strcat(idev->description, " <-> esi");
-
-	idev->io.dongle_id = type;
-	idev->flags |= IFF_DONGLE;
+	qos->baud_rate.bits &= IR_9600|IR_19200|IR_115200;
+	qos->min_turn_time.bits = 0x01; /* Needs at least 10 ms */
 
 	MOD_INC_USE_COUNT;
 }
 
-static void esi_close(struct irda_device *idev)
+static void esi_close(dongle_t *dongle)
 {		
 	/* Power off dongle */
-	irda_device_set_dtr_rts(idev, FALSE, FALSE);
+	dongle->set_dtr_rts(dongle->dev, FALSE, FALSE);
 
 	MOD_DEC_USE_COUNT;
 }
 
 /*
- * Function esi_change_speed (tty, baud)
+ * Function esi_change_speed (task)
  *
  *    Set the speed for the Extended Systems JetEye PC ESI-9680 type dongle
  *
  */
-static void esi_change_speed(struct irda_device *idev, int baud)
+static int esi_change_speed(struct irda_task *task)
 {
+	dongle_t *self = (dongle_t *) task->instance;
+	__u32 speed = (__u32) task->param;
 	int dtr, rts;
 	
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-	
-	switch (baud) {
+	switch (speed) {
 	case 19200:
 		dtr = TRUE;
 		rts = FALSE;
@@ -109,28 +109,31 @@
 	}
 
 	/* Change speed of dongle */
-	irda_device_set_dtr_rts(idev, dtr, rts);
-}
+	self->set_dtr_rts(self->dev, dtr, rts);
+	self->speed = speed;
 
-static void esi_reset( struct irda_device *idev)
-{
-	/* Empty */
+	irda_task_next_state(task, IRDA_TASK_DONE);
+
+	return 0;
 }
 
 /*
- * Function esi_qos_init (qos)
+ * Function esi_reset (task)
  *
- *    Init QoS capabilities for the dongle
+ *    Reset dongle;
  *
  */
-static void esi_qos_init(struct irda_device *idev, struct qos_info *qos)
+static int esi_reset(struct irda_task *task)
 {
-	qos->baud_rate.bits &= IR_9600|IR_19200|IR_115200;
-	qos->min_turn_time.bits &= 0x01; /* Needs at least 10 ms */
+	dongle_t *self = (dongle_t *) task->instance;
+	
+	self->set_dtr_rts(self->dev, FALSE, FALSE);
+	irda_task_next_state(task, IRDA_TASK_DONE);
+
+	return 0;
 }
 
 #ifdef MODULE
-
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
 MODULE_DESCRIPTION("Extended Systems JetEye PC dongle driver");
 
@@ -155,6 +158,5 @@
 {
         esi_cleanup();
 }
-
-#endif
+#endif /* MODULE */
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/irda/girbil.c linux.15p9/drivers/net/irda/girbil.c
--- linux.vanilla/drivers/net/irda/girbil.c	Sat Aug 14 02:26:48 1999
+++ linux.15p9/drivers/net/irda/girbil.c	Tue Jan 18 01:08:18 2000
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      girbil.c
- * Version:       1.1
+ * Version:       1.2
  * Description:   Implementation for the Greenwich GIrBIL dongle
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Feb  6 21:02:33 1999
- * Modified at:   Tue Jun  1 08:47:41 1999
+ * Modified at:   Fri Dec 17 09:13:20 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -32,13 +32,11 @@
 #include <net/irda/irmod.h>
 #include <net/irda/irda_device.h>
 #include <net/irda/irtty.h>
-#include <net/irda/dongle.h>
 
-static void girbil_reset(struct irda_device *dev);
-static void girbil_open(struct irda_device *dev, int type);
-static void girbil_close(struct irda_device *dev);
-static void girbil_change_speed(struct irda_device *dev, int baud);
-static void girbil_init_qos(struct irda_device *idev, struct qos_info *qos);
+static int  girbil_reset(struct irda_task *task);
+static void girbil_open(dongle_t *self, struct qos_info *qos);
+static void girbil_close(dongle_t *self);
+static int  girbil_change_speed(struct irda_task *task);
 
 /* Control register 1 */
 #define GIRBIL_TXEN    0x01 /* Enable transmitter */
@@ -67,16 +65,16 @@
 /* Control register 2 (0x5) */
 #define GIRBIL_LOAD    0x51 /* Load the new baud rate value */
 
-static struct dongle dongle = {
-	GIRBIL_DONGLE,
+static struct dongle_reg dongle = {
+	Q_NULL,
+	IRDA_GIRBIL_DONGLE,
 	girbil_open,
 	girbil_close,
 	girbil_reset,
 	girbil_change_speed,
-	girbil_init_qos,
 };
 
-__initfunc(int girbil_init(void))
+int __init girbil_init(void)
 {
 	return irda_device_register_dongle(&dongle);
 }
@@ -86,20 +84,18 @@
 	irda_device_unregister_dongle(&dongle);
 }
 
-static void girbil_open(struct irda_device *idev, int type)
+static void girbil_open(dongle_t *self, struct qos_info *qos)
 {
-	strcat(idev->description, " <-> girbil");
+	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+	qos->min_turn_time.bits = 0x03;
 
-	idev->io.dongle_id = type;
-	idev->flags |= IFF_DONGLE;
-	
 	MOD_INC_USE_COUNT;
 }
 
-static void girbil_close(struct irda_device *idev)
+static void girbil_close(dongle_t *self)
 {
 	/* Power off dongle */
-	irda_device_set_dtr_rts(idev, FALSE, FALSE);
+	self->set_dtr_rts(self->dev, FALSE, FALSE);
 
 	MOD_DEC_USE_COUNT;
 }
@@ -107,108 +103,135 @@
 /*
  * Function girbil_change_speed (dev, speed)
  *
- *    Set the speed for the Girbil type dongle. Warning, this 
- *    function must be called with a process context!
+ *    Set the speed for the Girbil type dongle.
  *
  */
-static void girbil_change_speed(struct irda_device *idev, int speed)
+static int girbil_change_speed(struct irda_task *task)
 {
+	dongle_t *self = (dongle_t *) task->instance;
+	__u32 speed = (__u32) task->param;
 	__u8 control[2];
-	
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-	
-	switch (speed) {
-	case 9600:
-	default:
-		control[0] = GIRBIL_9600;
+	int ret = 0;
+
+	self->speed_task = task;
+
+	switch (task->state) {
+	case IRDA_TASK_INIT:
+		/* Need to reset the dongle and go to 9600 bps before
+                   programming */
+		if (irda_task_execute(self, girbil_reset, NULL, task, 
+				      (void *) speed))
+		{
+			/* Dongle need more time to reset */
+			irda_task_next_state(task, IRDA_TASK_CHILD_WAIT);
+
+			/* Give reset 1 sec to finish */
+			ret = MSECS_TO_JIFFIES(1000);
+		}
 		break;
-	case 19200:
-		control[0] = GIRBIL_19200;
+	case IRDA_TASK_CHILD_WAIT:
+		WARNING(__FUNCTION__ "(), resetting dongle timed out!\n");
+		ret = -1;
 		break;
-	case 34800:
-		control[0] = GIRBIL_38400;
+	case IRDA_TASK_CHILD_DONE:
+		/* Set DTR and Clear RTS to enter command mode */
+		self->set_dtr_rts(self->dev, FALSE, TRUE);
+
+		switch (speed) {
+		case 9600:
+		default:
+			control[0] = GIRBIL_9600;
+			break;
+		case 19200:
+			control[0] = GIRBIL_19200;
+			break;
+		case 34800:
+			control[0] = GIRBIL_38400;
+			break;
+		case 57600:
+			control[0] = GIRBIL_57600;
+			break;
+		case 115200:
+			control[0] = GIRBIL_115200;
+			break;
+		}
+		control[1] = GIRBIL_LOAD;
+		
+		/* Write control bytes */
+		self->write(self->dev, control, 2);
+		irda_task_next_state(task, IRDA_TASK_WAIT);
+		ret = MSECS_TO_JIFFIES(100);
 		break;
-	case 57600:
-		control[0] = GIRBIL_57600;
+	case IRDA_TASK_WAIT:
+		/* Go back to normal mode */
+		self->set_dtr_rts(self->dev, TRUE, TRUE);
+		irda_task_next_state(task, IRDA_TASK_DONE);
+		self->speed_task = NULL;
 		break;
-	case 115200:
-		control[0] = GIRBIL_115200;
+	default:
+		ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
+		irda_task_next_state(task, IRDA_TASK_DONE);
+		self->speed_task = NULL;
+		ret = -1;
 		break;
 	}
-	control[1] = GIRBIL_LOAD;
-
-	/* Set DTR and Clear RTS to enter command mode */
-	irda_device_set_dtr_rts(idev, FALSE, TRUE);
-
-	/* Write control bytes */
-	irda_device_raw_write(idev, control, 2);
-
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(2);
-	
-	/* Go back to normal mode */
-	irda_device_set_dtr_rts(idev, TRUE, TRUE);
+	return ret;
 }
 
 /*
  * Function girbil_reset (driver)
  *
- *      This function resets the girbil dongle. Warning, this function 
- *      must be called with a process context!! 
+ *      This function resets the girbil dongle.
  *
  *      Algorithm:
  *    	  0. set RTS, and wait at least 5 ms 
  *        1. clear RTS 
  */
-void girbil_reset(struct irda_device *idev)
+static int girbil_reset(struct irda_task *task)
 {
+	dongle_t *self = (dongle_t *) task->instance;
 	__u8 control = GIRBIL_TXEN | GIRBIL_RXEN;
+	int ret = 0;
 
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-	
-	/* Reset dongle */
-	irda_device_set_dtr_rts(idev, TRUE, FALSE);
-
-	/* Sleep at least 5 ms */
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(MSECS_TO_JIFFIES(20));
-	
-	/* Set DTR and clear RTS to enter command mode */
-	irda_device_set_dtr_rts(idev, FALSE, TRUE);
-
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(MSECS_TO_JIFFIES(20));
-
-	/* Write control byte */
-	irda_device_raw_write(idev, &control, 1);
-
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(MSECS_TO_JIFFIES(20));
+	self->reset_task = task;
 
-	/* Go back to normal mode */
-	irda_device_set_dtr_rts(idev, TRUE, TRUE);
-
-       	/* Make sure the IrDA chip also goes to defalt speed */
-	if (idev->change_speed)
-		idev->change_speed(idev, 9600);
-}
-
-/*
- * Function girbil_init_qos (qos)
- *
- *    Initialize QoS capabilities
- *
- */
-static void girbil_init_qos(struct irda_device *idev, struct qos_info *qos)
-{
-	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
-	qos->min_turn_time.bits &= 0x03;
+	switch (task->state) {
+	case IRDA_TASK_INIT:
+		/* Reset dongle */
+		self->set_dtr_rts(self->dev, TRUE, FALSE);
+		irda_task_next_state(task, IRDA_TASK_WAIT1);
+		/* Sleep at least 5 ms */
+		ret = MSECS_TO_JIFFIES(10);
+		break;
+	case IRDA_TASK_WAIT1:
+		/* Set DTR and clear RTS to enter command mode */
+		self->set_dtr_rts(self->dev, FALSE, TRUE);
+		irda_task_next_state(task, IRDA_TASK_WAIT2);
+		ret = MSECS_TO_JIFFIES(10);
+		break;
+	case IRDA_TASK_WAIT2:
+		/* Write control byte */
+		self->write(self->dev, &control, 1);
+		irda_task_next_state(task, IRDA_TASK_WAIT3);
+		ret = MSECS_TO_JIFFIES(20);
+		break;
+	case IRDA_TASK_WAIT3:
+		/* Go back to normal mode */
+		self->set_dtr_rts(self->dev, TRUE, TRUE);
+		irda_task_next_state(task, IRDA_TASK_DONE);
+		self->reset_task = NULL;
+		break;
+	default:
+		ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
+		irda_task_next_state(task, IRDA_TASK_DONE);
+		self->reset_task = NULL;
+		ret = -1;
+		break;
+	}
+	return ret;
 }
 
 #ifdef MODULE
-
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
 MODULE_DESCRIPTION("Greenwich GIrBIL dongle driver");
 	
@@ -233,5 +256,4 @@
 {
         girbil_cleanup();
 }
-
 #endif /* MODULE */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/irda/irport.c linux.15p9/drivers/net/irda/irport.c
--- linux.vanilla/drivers/net/irda/irport.c	Sat Aug 14 02:26:48 1999
+++ linux.15p9/drivers/net/irda/irport.c	Tue Jan 18 01:08:18 2000
@@ -6,11 +6,11 @@
  * Status:	  Experimental.
  * Author:	  Dag Brattli <dagb@cs.uit.no>
  * Created at:	  Sun Aug  3 13:49:59 1997
- * Modified at:   Tue Jun  1 10:02:42 1999
+ * Modified at:   Fri Jan 14 21:07:20 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:	  serial.c by Linus Torvalds 
  * 
- *     Copyright (c) 1997, 1998, 1999 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1997, 1998, 1999-2000 Dag Brattli, All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -47,11 +47,12 @@
 #include <linux/serial_reg.h>
 #include <linux/errno.h>
 #include <linux/init.h>
+#include <asm/spinlock.h>
+#include <linux/rtnetlink.h>
 
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
-#include <asm/spinlock.h>
 
 #include <net/irda/irda.h>
 #include <net/irda/irmod.h>
@@ -69,24 +70,33 @@
 
 static unsigned int qos_mtt_bits = 0x03;
 
-static struct irda_device *dev_self[] = { NULL, NULL, NULL, NULL};
+static struct irport_cb *dev_self[] = { NULL, NULL, NULL, NULL};
 static char *driver_name = "irport";
 
-static int irport_open(int i, unsigned int iobase, unsigned int irq);
-static int irport_close(struct irda_device *idev);
-
-static void irport_write_wakeup(struct irda_device *idev);
+static void irport_write_wakeup(struct irport_cb *self);
 static int  irport_write(int iobase, int fifo_size, __u8 *buf, int len);
-static void irport_receive(struct irda_device *idev);
+static void irport_receive(struct irport_cb *self);
 
 static int  irport_net_init(struct device *dev);
-static int  irport_net_open(struct device *dev);
-static int  irport_net_close(struct device *dev);
-static int  irport_is_receiving(struct irda_device *idev);
-static void irport_set_dtr_rts(struct irda_device *idev, int dtr, int rts);
-static int  irport_raw_write(struct irda_device *idev, __u8 *buf, int len);
+static int  irport_net_ioctl(struct device *dev, struct ifreq *rq, 
+			     int cmd);
+static int  irport_is_receiving(struct irport_cb *self);
+static int  irport_set_dtr_rts(struct device *dev, int dtr, int rts);
+static int  irport_raw_write(struct device *dev, __u8 *buf, int len);
+static struct net_device_stats *irport_net_get_stats(struct device *dev);
+static int irport_change_speed_complete(struct irda_task *task);
+
+EXPORT_SYMBOL(irport_open);
+EXPORT_SYMBOL(irport_close);
+EXPORT_SYMBOL(irport_start);
+EXPORT_SYMBOL(irport_stop);
+EXPORT_SYMBOL(irport_interrupt);
+EXPORT_SYMBOL(irport_hard_xmit);
+EXPORT_SYMBOL(irport_change_speed);
+EXPORT_SYMBOL(irport_net_open);
+EXPORT_SYMBOL(irport_net_close);
 
-__initfunc(int irport_init(void))
+int __init irport_init(void)
 {
  	int i;
 
@@ -94,7 +104,7 @@
  		int ioaddr = io[i];
  		if (check_region(ioaddr, IO_EXTENT))
  			continue;
- 		if (irport_open(i, io[i], irq[i]) == 0)
+ 		if (irport_open(i, io[i], irq[i]) != NULL)
  			return 0;
  	}
 	/* 
@@ -114,7 +124,7 @@
 {
  	int i;
 
-        DEBUG( 4, __FUNCTION__ "()\n");
+        IRDA_DEBUG( 4, __FUNCTION__ "()\n");
 
 	for (i=0; i < 4; i++) {
  		if (dev_self[i])
@@ -123,110 +133,170 @@
 }
 #endif /* MODULE */
 
-static int irport_open(int i, unsigned int iobase, unsigned int irq)
+struct irport_cb *
+irport_open(int i, unsigned int iobase, unsigned int irq)
 {
-	struct irda_device *idev;
+	struct device *dev;
+	struct irport_cb *self;
 	int ret;
+	int err;
 
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-/* 	if (irport_probe(iobase, irq) == -1) */
-/* 		return -1; */
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
 	/*
 	 *  Allocate new instance of the driver
 	 */
-	idev = kmalloc(sizeof(struct irda_device), GFP_KERNEL);
-	if (idev == NULL) {
-		printk( KERN_ERR "IrDA: Can't allocate memory for "
-			"IrDA control block!\n");
-		return -ENOMEM;
+	self = kmalloc(sizeof(struct irport_cb), GFP_KERNEL);
+	if (!self) {
+		ERROR(__FUNCTION__ "(), can't allocate memory for "
+		      "control block!\n");
+		return NULL;
 	}
-	memset(idev, 0, sizeof(struct irda_device));
-   
+	memset(self, 0, sizeof(struct irport_cb));
+	spin_lock_init(&self->lock);
+
 	/* Need to store self somewhere */
-	dev_self[i] = idev;
+	dev_self[i] = self;
+	self->priv = self;
+	self->index = i;
 
 	/* Initialize IO */
-	idev->io.iobase2   = iobase;
-        idev->io.irq2      = irq;
-        idev->io.io_ext    = IO_EXTENT;
-        idev->io.fifo_size = 16;
-
-	idev->netdev.base_addr = iobase;
-	idev->netdev.irq = irq;
+	self->io.sir_base  = iobase;
+        self->io.sir_ext   = IO_EXTENT;
+        self->io.irq       = irq;
+        self->io.fifo_size = 16;
 
 	/* Lock the port that we need */
-	ret = check_region(idev->io.iobase2, idev->io.io_ext);
+	ret = check_region(self->io.sir_base, self->io.sir_ext);
 	if (ret < 0) { 
-		DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
-		      idev->io.iobase2);
-		/* irport_cleanup(self->idev);  */
-		return -ENODEV;
+		IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+			   self->io.sir_base);
+		return NULL;
 	}
-	request_region(idev->io.iobase2, idev->io.io_ext, idev->name);
+	request_region(self->io.sir_base, self->io.sir_ext, driver_name);
 
 	/* Initialize QoS for this device */
-	irda_init_max_qos_capabilies(&idev->qos);
+	irda_init_max_qos_capabilies(&self->qos);
 	
-	idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+	self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
 		IR_115200;
 
-	idev->qos.min_turn_time.bits = qos_mtt_bits;
-	irda_qos_bits_to_value(&idev->qos);
+	self->qos.min_turn_time.bits = qos_mtt_bits;
+	irda_qos_bits_to_value(&self->qos);
 	
-	idev->flags = IFF_SIR|IFF_PIO;
+	self->flags = IFF_SIR|IFF_PIO;
 
-	/* Specify which buffer allocation policy we need */
-	idev->rx_buff.flags = GFP_KERNEL;
-	idev->tx_buff.flags = GFP_KERNEL;
-
-	idev->rx_buff.truesize = 4000; 
-	idev->tx_buff.truesize = 4000;
-	
-	/* Initialize callbacks */
-	idev->change_speed    = irport_change_speed;
-	idev->wait_until_sent = irport_wait_until_sent;
-        idev->is_receiving    = irport_is_receiving;
-	idev->set_dtr_rts     = irport_set_dtr_rts;
-	idev->raw_write       = irport_raw_write;
+	/* Specify how much memory we want */
+	self->rx_buff.truesize = 4000; 
+	self->tx_buff.truesize = 4000;
+	
+	/* Allocate memory if needed */
+	if (self->rx_buff.truesize > 0) {
+		self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
+						      GFP_KERNEL);
+		if (self->rx_buff.head == NULL)
+			return NULL;
+		memset(self->rx_buff.head, 0, self->rx_buff.truesize);
+	}
+	if (self->tx_buff.truesize > 0) {
+		self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
+						      GFP_KERNEL);
+		if (self->tx_buff.head == NULL) {
+			kfree(self->rx_buff.head);
+			return NULL;
+		}
+		memset(self->tx_buff.head, 0, self->tx_buff.truesize);
+	}	
+	self->rx_buff.in_frame = FALSE;
+	self->rx_buff.state = OUTSIDE_FRAME;
+	self->tx_buff.data = self->tx_buff.head;
+	self->rx_buff.data = self->rx_buff.head;
+	self->mode = IRDA_IRLAP;
+
+	if (!(dev = dev_alloc("irda%d", &err))) {
+		ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
+		return NULL;
+	}
+	/* dev_alloc doesn't clear the struct */
+	memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct device)-sizeof(char*));
+
+	self->netdev = dev;
+
+	/* May be overridden by piggyback drivers */
+ 	dev->priv = (void *) self;
+	self->interrupt    = irport_interrupt;
+	self->change_speed = irport_change_speed;
 
 	/* Override the network functions we need to use */
-	idev->netdev.init            = irport_net_init;
-	idev->netdev.hard_start_xmit = irport_hard_xmit;
-	idev->netdev.open            = irport_net_open;
-	idev->netdev.stop            = irport_net_close;
-
-	/* Open the IrDA device */
-	irda_device_open(idev, driver_name, NULL);
-	
-	return 0;
-}
-
-static int irport_close(struct irda_device *idev)
-{
-	ASSERT(idev != NULL, return -1;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+	dev->init            = irport_net_init;
+	dev->hard_start_xmit = irport_hard_xmit;
+	dev->open            = irport_net_open;
+	dev->stop            = irport_net_close;
+	dev->get_stats	     = irport_net_get_stats;
+	dev->do_ioctl        = irport_net_ioctl;
+
+	/* Make ifconfig display some details */
+	dev->base_addr = iobase;
+	dev->irq = irq;
+
+	rtnl_lock();
+	err = register_netdevice(dev);
+	rtnl_unlock();
+	if (err) {
+		ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
+		return NULL;
+	}
+	MESSAGE("IrDA: Registered device %s\n", dev->name);
+
+	return self;
+}
+
+int irport_close(struct irport_cb *self)
+{
+	ASSERT(self != NULL, return -1;);
+
+	/* We are not using any dongle anymore! */
+	if (self->dongle)
+		irda_device_dongle_cleanup(self->dongle);
+	self->dongle = NULL;
+	
+	/* Remove netdevice */
+	if (self->netdev) {
+		rtnl_lock();
+		unregister_netdevice(self->netdev);
+		rtnl_unlock();
+		/* Must free the old-style 2.2.x device */
+		kfree(self->netdev);
+	}
 
 	/* Release the IO-port that this driver is using */
-	DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n", 
-	      idev->io.iobase2);
-	release_region(idev->io.iobase2, idev->io.io_ext);
-
-	irda_device_close(idev);
-
-	kfree(idev);
-
+	IRDA_DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n", 
+		   self->io.sir_base);
+	release_region(self->io.sir_base, self->io.sir_ext);
+
+	if (self->tx_buff.head)
+		kfree(self->tx_buff.head);
+	
+	if (self->rx_buff.head)
+		kfree(self->rx_buff.head);
+	
+	/* Remove ourselves */
+	dev_self[self->index] = NULL;
+	kfree(self);
+	
 	return 0;
 }
 
-void irport_start(struct irda_device *idev, int iobase)
+void irport_start(struct irport_cb *self)
 {
 	unsigned long flags;
+	int iobase;
+
+	iobase = self->io.sir_base;
 
-	spin_lock_irqsave(&idev->lock, flags);
+	spin_lock_irqsave(&self->lock, flags);
 
-	irport_stop(idev, iobase);
+	irport_stop(self);
 
 	/* Initialize UART */
 	outb(UART_LCR_WLEN8, iobase+UART_LCR);  /* Reset DLAB */
@@ -235,14 +305,17 @@
 	/* Turn on interrups */
 	outb(UART_IER_RLSI | UART_IER_RDI |UART_IER_THRI, iobase+UART_IER);
 
-	spin_unlock_irqrestore(&idev->lock, flags);
+	spin_unlock_irqrestore(&self->lock, flags);
 }
 
-void irport_stop(struct irda_device *idev, int iobase)
+void irport_stop(struct irport_cb *self)
 {
 	unsigned long flags;
+	int iobase;
+
+	iobase = self->io.sir_base;
 
-	spin_lock_irqsave(&idev->lock, flags);
+	spin_lock_irqsave(&self->lock, flags);
 
 	/* Reset UART */
 	outb(0, iobase+UART_MCR);
@@ -250,7 +323,7 @@
 	/* Turn off interrupts */
 	outb(0, iobase+UART_IER);
 
-	spin_unlock_irqrestore(&idev->lock, flags);
+	spin_unlock_irqrestore(&self->lock, flags);
 }
 
 /*
@@ -261,36 +334,36 @@
  */
 int irport_probe(int iobase)
 {
-	DEBUG(4, __FUNCTION__ "(), iobase=%#x\n", iobase);
+	IRDA_DEBUG(4, __FUNCTION__ "(), iobase=%#x\n", iobase);
 
 	return 0;
 }
 
 /*
- * Function irport_change_speed (idev, speed)
+ * Function irport_change_speed (self, speed)
  *
  *    Set speed of IrDA port to specified baudrate
  *
  */
-void irport_change_speed(struct irda_device *idev, int speed)
+void irport_change_speed(void *priv, __u32 speed)
 {
+	struct irport_cb *self = (struct irport_cb *) priv;
 	unsigned long flags;
 	int iobase; 
 	int fcr;    /* FIFO control reg */
 	int lcr;    /* Line control reg */
 	int divisor;
 
-	DEBUG(0, __FUNCTION__ "(), Setting speed to: %d\n", speed);
+	IRDA_DEBUG(2, __FUNCTION__ "(), Setting speed to: %d\n", speed);
 
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+	ASSERT(self != NULL, return;);
 
-	iobase = idev->io.iobase2;
+	iobase = self->io.sir_base;
 	
 	/* Update accounting for new speed */
-	idev->io.baudrate = speed;
+	self->io.speed = speed;
 
-	spin_lock_irqsave(&idev->lock, flags);
+	spin_lock_irqsave(&self->lock, flags);
 
 	/* Turn off interrupts */
 	outb(0, iobase+UART_IER); 
@@ -304,7 +377,7 @@
 	 * almost 1,7 ms at 19200 bps. At speeds above that we can just forget
 	 * about this timeout since it will always be fast enough. 
 	 */
-	if (idev->io.baudrate < 38400)
+	if (self->io.speed < 38400)
 		fcr |= UART_FCR_TRIGGER_1;
 	else 
 		fcr |= UART_FCR_TRIGGER_14;
@@ -319,9 +392,82 @@
 	outb(fcr,		  iobase+UART_FCR); /* Enable FIFO's */
 
 	/* Turn on interrups */
-	outb(UART_IER_RLSI|UART_IER_RDI|UART_IER_THRI, iobase+UART_IER);
+	outb(/*UART_IER_RLSI|*/UART_IER_RDI/*|UART_IER_THRI*/, iobase+UART_IER);
+
+	spin_unlock_irqrestore(&self->lock, flags);
+}
+
+/*
+ * Function __irport_change_speed (instance, state, param)
+ *
+ *    State machine for changing speed of the device. We do it this way since
+ *    we cannot use schedule_timeout() when we are in interrupt context
+ */
+int __irport_change_speed(struct irda_task *task)
+{
+	struct irport_cb *self;
+	__u32 speed = (__u32) task->param;
+	int ret = 0;
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), <%ld>\n", jiffies); 
+
+	self = (struct irport_cb *) task->instance;
 
-	spin_unlock_irqrestore(&idev->lock, flags);
+	ASSERT(self != NULL, return -1;);
+
+	switch (task->state) {
+	case IRDA_TASK_INIT:
+	case IRDA_TASK_WAIT:
+		/* Are we ready to change speed yet? */
+		if (self->tx_buff.len > 0) {
+			task->state = IRDA_TASK_WAIT;
+
+			/* Try again later */
+			ret = MSECS_TO_JIFFIES(20);
+			break;
+		}
+
+		if (self->dongle)
+			irda_task_next_state(task, IRDA_TASK_CHILD_INIT);
+		else
+			irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
+		break;
+	case IRDA_TASK_CHILD_INIT:
+		/* Go to default speed */
+		self->change_speed(self->priv, 9600);
+
+		/* Change speed of dongle */
+		if (irda_task_execute(self->dongle,
+				      self->dongle->issue->change_speed, 
+				      NULL, task, (void *) speed))
+		{
+			/* Dongle need more time to change its speed */
+			irda_task_next_state(task, IRDA_TASK_CHILD_WAIT);
+
+			/* Give dongle 1 sec to finish */
+			ret = MSECS_TO_JIFFIES(1000);
+		} else
+			/* Child finished immediately */
+			irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
+		break;
+	case IRDA_TASK_CHILD_WAIT:
+		WARNING(__FUNCTION__ 
+			"(), changing speed of dongle timed out!\n");
+		ret = -1;		
+		break;
+	case IRDA_TASK_CHILD_DONE:
+		/* Finally we are ready to change the speed */
+		self->change_speed(self->priv, speed);
+		
+		irda_task_next_state(task, IRDA_TASK_DONE);
+		break;
+	default:
+		ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
+		irda_task_next_state(task, IRDA_TASK_DONE);
+		ret = -1;
+		break;
+	}	
+	return ret;
 }
 
 /*
@@ -331,51 +477,63 @@
  *    more packets to send, we send them here.
  *
  */
-static void irport_write_wakeup(struct irda_device *idev)
+static void irport_write_wakeup(struct irport_cb *self)
 {
 	int actual = 0;
 	int iobase;
 	int fcr;
 
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+	ASSERT(self != NULL, return;);
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+	iobase = self->io.sir_base;
 
 	/* Finished with frame?  */
-	if (idev->tx_buff.len > 0)  {
+	if (self->tx_buff.len > 0)  {
 		/* Write data left in transmit buffer */
-		actual = irport_write(idev->io.iobase2, idev->io.fifo_size, 
-				      idev->tx_buff.data, idev->tx_buff.len);
-		idev->tx_buff.data += actual;
-		idev->tx_buff.len  -= actual;
+		actual = irport_write(iobase, self->io.fifo_size, 
+				      self->tx_buff.data, self->tx_buff.len);
+		self->tx_buff.data += actual;
+		self->tx_buff.len  -= actual;
 	} else {
-		iobase = idev->io.iobase2;
+		
 		/* 
 		 *  Now serial buffer is almost free & we can start 
-		 *  transmission of another packet 
+		 *  transmission of another packet. But first we must check
+		 *  if we need to change the speed of the hardware
 		 */
-		idev->netdev.tbusy = 0; /* Unlock */
-		idev->stats.tx_packets++;
+		if (self->new_speed) {
+			IRDA_DEBUG(5, __FUNCTION__ "(), Changing speed!\n");
+			irda_task_execute(self, __irport_change_speed, 
+					  irport_change_speed_complete, 
+					  NULL, (void *) self->new_speed);
+			self->new_speed = 0;
+		} else {
+			self->netdev->tbusy = 0; /* Unlock */
+		
+			/* Tell network layer that we want more frames */
+			mark_bh(NET_BH);
+		}
+		self->stats.tx_packets++;
 
 		/* Schedule network layer, so we can get some more frames */
 		mark_bh(NET_BH);
 
+		/* 
+		 * Reset Rx FIFO to make sure that all reflected transmit data
+		 * is discarded. This is needed for half duplex operation
+		 */
 		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR;
-
-		if (idev->io.baudrate < 38400)
+		if (self->io.speed < 38400)
 			fcr |= UART_FCR_TRIGGER_1;
 		else 
 			fcr |= UART_FCR_TRIGGER_14;
 
-		/* 
-		 * Reset Rx FIFO to make sure that all reflected transmit data
-		 * will be discarded
-		 */
 		outb(fcr, iobase+UART_FCR);
 
 		/* Turn on receive interrupts */
-		outb(UART_IER_RLSI|UART_IER_RDI, iobase+UART_IER); 
+		outb(UART_IER_RDI, iobase+UART_IER);
 	}
 }
 
@@ -391,8 +549,8 @@
 
 	/* Tx FIFO should be empty! */
 	if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
-		DEBUG(0, __FUNCTION__ "(), failed, fifo not empty!\n");
-		return -1;
+		IRDA_DEBUG(0, __FUNCTION__ "(), failed, fifo not empty!\n");
+		return 0;
 	}
         
 	/* Fill FIFO with current frame */
@@ -407,6 +565,32 @@
 }
 
 /*
+ * Function irport_change_speed_complete (task)
+ *
+ *    Called when the change speed operation completes
+ *
+ */
+static int irport_change_speed_complete(struct irda_task *task)
+{
+	struct irport_cb *self;
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	self = (struct irport_cb *) task->instance;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->netdev != NULL, return -1;);
+
+	/* Finished changing speed, so we are not busy any longer */
+	self->netdev->tbusy = 0;
+
+	/* Signal network layer so it can try to send the frame */
+	mark_bh(NET_BH);
+
+	return 0;
+}
+
+/*
  * Function irport_xmit (void)
  *
  *    Transmits the current frame until FIFO is full, then
@@ -415,49 +599,50 @@
  */
 int irport_hard_xmit(struct sk_buff *skb, struct device *dev)
 {
-	struct irda_device *idev;
+	struct irport_cb *self;
 	unsigned long flags;
-	int actual = 0;
 	int iobase;
+	__u32 speed;
 
 	ASSERT(dev != NULL, return 0;);
 	
-	idev = (struct irda_device *) dev->priv;
+	self = (struct irport_cb *) dev->priv;
+	ASSERT(self != NULL, return 0;);
 
-	ASSERT(idev != NULL, return 0;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;);
-
-	iobase = idev->io.iobase2;
+	iobase = self->io.sir_base;
 
 	/* Lock transmit buffer */
 	if (irda_lock((void *) &dev->tbusy) == FALSE) {
 		int tickssofar = jiffies - dev->trans_start;
-		if (tickssofar < 5)
+		if ((tickssofar < 5) || !dev->start)
 			return -EBUSY;
 
 		WARNING("%s: transmit timed out\n", dev->name);
-		irport_start(idev, iobase);
-		irport_change_speed(idev, idev->io.baudrate);
+		irport_start(self);
+		self->change_speed(self->priv, self->io.speed);
 
 		dev->trans_start = jiffies;
 	}
 
-	spin_lock_irqsave(&idev->lock, flags);
-	
+	/* Check if we need to change the speed */
+	if ((speed = irda_get_speed(skb)) != self->io.speed)
+		self->new_speed = speed;
+
+	spin_lock_irqsave(&self->lock, flags);
+
 	/* Init tx buffer */
-	idev->tx_buff.data = idev->tx_buff.head;
+	self->tx_buff.data = self->tx_buff.head;
 
         /* Copy skb to tx_buff while wrapping, stuffing and making CRC */
-	idev->tx_buff.len = async_wrap_skb(skb, idev->tx_buff.data, 
-					   idev->tx_buff.truesize);
+	self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, 
+					   self->tx_buff.truesize);
 	
-	idev->tx_buff.data += actual;
-	idev->tx_buff.len  -= actual;
+	self->stats.tx_bytes += self->tx_buff.len;
 
 	/* Turn on transmit finished interrupt. Will fire immediately!  */
 	outb(UART_IER_THRI, iobase+UART_IER); 
 
-	spin_unlock_irqrestore(&idev->lock, flags);
+	spin_unlock_irqrestore(&self->lock, flags);
 
 	dev_kfree_skb(skb);
 	
@@ -465,30 +650,31 @@
 }
         
 /*
- * Function irport_receive (void)
+ * Function irport_receive (self)
  *
  *    Receive one frame from the infrared port
  *
  */
-static void irport_receive(struct irda_device *idev) 
+static void irport_receive(struct irport_cb *self) 
 {
-	int iobase;
 	int boguscount = 0;
+	int iobase;
 
-	ASSERT(idev != NULL, return;);
+	ASSERT(self != NULL, return;);
 
-	iobase = idev->io.iobase2;
+	iobase = self->io.sir_base;
 
 	/*  
 	 * Receive all characters in Rx FIFO, unwrap and unstuff them. 
          * async_unwrap_char will deliver all found frames  
 	 */
 	do {
-		async_unwrap_char(idev, inb(iobase+UART_RX));
+		async_unwrap_char(self->netdev, &self->stats, &self->rx_buff, 
+				  inb(iobase+UART_RX));
 
 		/* Make sure we don't stay here to long */
 		if (boguscount++ > 32) {
-			DEBUG(0,__FUNCTION__ "(), breaking!\n");
+			IRDA_DEBUG(2,__FUNCTION__ "(), breaking!\n");
 			break;
 		}
 	} while (inb(iobase+UART_LSR) & UART_LSR_DR);	
@@ -501,58 +687,60 @@
  */
 void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs) 
 {
-	struct irda_device *idev = (struct irda_device *) dev_id;
+	struct device *dev = (struct device *) dev_id;
+	struct irport_cb *self;
+	int boguscount = 0;
 	int iobase;
 	int iir, lsr;
-	int boguscount = 0;
 
-	if (!idev) {
+	if (!dev) {
 		WARNING(__FUNCTION__ "() irq %d for unknown device.\n", irq);
 		return;
 	}
+	self = (struct irport_cb *) dev->priv;
 
-	spin_lock(&idev->lock);
+	spin_lock(&self->lock);
 
-	idev->netdev.interrupt = 1;
+	dev->interrupt = 1;
 
-	iobase = idev->io.iobase2;
+	iobase = self->io.sir_base;
 
 	iir = inb(iobase+UART_IIR) & UART_IIR_ID;
 	while (iir) {
 		/* Clear interrupt */
 		lsr = inb(iobase+UART_LSR);
 
-		DEBUG(4, __FUNCTION__ "(), iir=%02x, lsr=%02x, iobase=%#x\n", 
-		      iir, lsr, iobase);
+		IRDA_DEBUG(4, __FUNCTION__ 
+			   "(), iir=%02x, lsr=%02x, iobase=%#x\n", 
+			   iir, lsr, iobase);
 
 		switch (iir) {
 		case UART_IIR_RLSI:
-			DEBUG(0, __FUNCTION__ "(), RLSI\n");
+			IRDA_DEBUG(2, __FUNCTION__ "(), RLSI\n");
 			break;
 		case UART_IIR_RDI:
-			if (lsr & UART_LSR_DR)
-				/* Receive interrupt */
-				irport_receive(idev);
+			/* Receive interrupt */
+			irport_receive(self);
 			break;
 		case UART_IIR_THRI:
 			if (lsr & UART_LSR_THRE)
 				/* Transmitter ready for data */
-				irport_write_wakeup(idev);
+				irport_write_wakeup(self);
 			break;
 		default:
-			DEBUG(0, __FUNCTION__ "(), unhandled IIR=%#x\n", iir);
+			IRDA_DEBUG(0, __FUNCTION__ "(), unhandled IIR=%#x\n", iir);
 			break;
 		} 
 		
 		/* Make sure we don't stay here to long */
-		if (boguscount++ > 32)
+		if (boguscount++ > 100)
 			break;
 
  	        iir = inb(iobase + UART_IIR) & UART_IIR_ID;
 	}
-	idev->netdev.interrupt = 0;
+	dev->interrupt = 0;
 
-	spin_unlock(&idev->lock);
+	spin_unlock(&self->lock);
 }
 
 static int irport_net_init(struct device *dev)
@@ -568,64 +756,75 @@
 /*
  * Function irport_net_open (dev)
  *
- *    
- *
+ *    Network device is taken up. Usually this is done by "ifconfig irda0 up" 
+ *   
  */
-static int irport_net_open(struct device *dev)
+int irport_net_open(struct device *dev)
 {
-	struct irda_device *idev;
+	struct irport_cb *self;
 	int iobase;
 
 	ASSERT(dev != NULL, return -1;);
-	idev = (struct irda_device *) dev->priv;
+	self = (struct irport_cb *) dev->priv;
 
-	iobase = idev->io.iobase2;
+	iobase = self->io.sir_base;
 
-	if (request_irq(idev->io.irq2, irport_interrupt, 0, idev->name, 
-			(void *) idev))
+	if (request_irq(self->io.irq, self->interrupt, 0, dev->name, 
+			(void *) dev))
 		return -EAGAIN;
 
-	irport_start(idev, iobase);
-
-	MOD_INC_USE_COUNT;
+	irport_start(self);
 
 	/* Ready to play! */
 	dev->tbusy = 0;
 	dev->interrupt = 0;
 	dev->start = 1;
 
-	/* Change speed to make sure dongles follow us again */
-	if (idev->change_speed)
-		idev->change_speed(idev, 9600);
+	/* 
+	 * Open new IrLAP layer instance, now that everything should be
+	 * initialized properly 
+	 */
+	self->irlap = irlap_open(dev, &self->qos);
+
+	/* FIXME: change speed of dongle */
+
+	MOD_INC_USE_COUNT;
 
 	return 0;
 }
 
 /*
- * Function irport_net_close (idev)
- *
- *    
+ * Function irport_net_close (self)
  *
+ *    Network device is taken down. Usually this is done by 
+ *    "ifconfig irda0 down" 
  */
-static int irport_net_close(struct device *dev)
+int irport_net_close(struct device *dev)
 {
-	struct irda_device *idev;
+	struct irport_cb *self;
 	int iobase;
 
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
 	ASSERT(dev != NULL, return -1;);
-	idev = (struct irda_device *) dev->priv;
+	self = (struct irport_cb *) dev->priv;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	ASSERT(self != NULL, return -1;);
 
-	iobase = idev->io.iobase2;
+	iobase = self->io.sir_base;
 
 	/* Stop device */
 	dev->tbusy = 1;
 	dev->start = 0;
 
-	irport_stop(idev, iobase);
+	/* Stop and remove instance of IrLAP */
+	if (self->irlap)
+		irlap_close(self->irlap);
+	self->irlap = NULL;
+
+	irport_stop(self);
 
-	free_irq(idev->io.irq2, idev);
+	free_irq(self->io.irq, dev);
 
 	MOD_DEC_USE_COUNT;
 
@@ -633,50 +832,52 @@
 }
 
 /*
- * Function irport_wait_until_sent (idev)
+ * Function irport_wait_until_sent (self)
  *
  *    Delay exectution until finished transmitting
  *
  */
-void irport_wait_until_sent(struct irda_device *idev)
+#if 0
+void irport_wait_until_sent(struct irport_cb *self)
 {
 	int iobase;
 
-	iobase = idev->io.iobase2;
+	iobase = self->io.sir_base;
 
 	/* Wait until Tx FIFO is empty */
 	while (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
-		DEBUG(2, __FUNCTION__ "(), waiting!\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), waiting!\n");
 		current->state = TASK_INTERRUPTIBLE;
 		schedule_timeout(MSECS_TO_JIFFIES(60));
 	}
 }
+#endif
 
 /*
- * Function irport_is_receiving (idev)
+ * Function irport_is_receiving (self)
  *
  *    Returns true is we are currently receiving data
  *
  */
-static int irport_is_receiving(struct irda_device *idev)
+static int irport_is_receiving(struct irport_cb *self)
 {
-	return (idev->rx_buff.state != OUTSIDE_FRAME);
+	return (self->rx_buff.state != OUTSIDE_FRAME);
 }
 
 /*
- * Function irtty_set_dtr_rts (tty, dtr, rts)
+ * Function irport_set_dtr_rts (tty, dtr, rts)
  *
  *    This function can be used by dongles etc. to set or reset the status
  *    of the dtr and rts lines
  */
-static void irport_set_dtr_rts(struct irda_device *idev, int dtr, int rts)
+static int irport_set_dtr_rts(struct device *dev, int dtr, int rts)
 {
+	struct irport_cb *self = dev->priv;
 	int iobase;
 
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+	ASSERT(self != NULL, return -1;);
 
-	iobase = idev->io.iobase2;
+	iobase = self->io.sir_base;
 
 	if (dtr)
 		dtr = UART_MCR_DTR;
@@ -684,21 +885,23 @@
 		rts = UART_MCR_RTS;
 
 	outb(dtr|rts|UART_MCR_OUT2, iobase+UART_MCR);
+
+	return 0;
 }
 
-static int irport_raw_write(struct irda_device *idev, __u8 *buf, int len)
+static int irport_raw_write(struct device *dev, __u8 *buf, int len)
 {
-	int iobase;
+	struct irport_cb *self = (struct irport_cb *) dev->priv;
 	int actual = 0;
+	int iobase;
 
-	ASSERT(idev != NULL, return -1;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+	ASSERT(self != NULL, return -1;);
 
-	iobase = idev->io.iobase2;
+	iobase = self->io.sir_base;
 
 	/* Tx FIFO should be empty! */
 	if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
-		DEBUG( 0, __FUNCTION__ "(), failed, fifo not empty!\n");
+		IRDA_DEBUG( 0, __FUNCTION__ "(), failed, fifo not empty!\n");
 		return -1;
 	}
         
@@ -712,34 +915,97 @@
 	return actual;
 }
 
-#ifdef MODULE
+/*
+ * Function irport_net_ioctl (dev, rq, cmd)
+ *
+ *    Process IOCTL commands for this device
+ *
+ */
+static int irport_net_ioctl(struct device *dev, struct ifreq *rq, int cmd)
+{
+	struct if_irda_req *irq = (struct if_irda_req *) rq;
+	struct irport_cb *self;
+	dongle_t *dongle;
+	unsigned long flags;
+	int ret = 0;
+
+	ASSERT(dev != NULL, return -1;);
+
+	self = dev->priv;
+
+	ASSERT(self != NULL, return -1;);
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
+	
+	/* Disable interrupts & save flags */
+	save_flags(flags);
+	cli();
+	
+	switch (cmd) {
+	case SIOCSBANDWIDTH: /* Set bandwidth */
+		irda_task_execute(self, __irport_change_speed, NULL, NULL, 
+				  (void *) irq->ifr_baudrate);
+		break;
+	case SIOCSDONGLE: /* Set dongle */
+		/* Initialize dongle */
+		dongle = irda_device_dongle_init(dev, irq->ifr_dongle);
+		if (!dongle)
+			break;
+		
+		dongle->set_mode    = NULL;
+		dongle->read        = NULL;
+		dongle->write       = irport_raw_write;
+		dongle->set_dtr_rts = irport_set_dtr_rts;
+		
+		self->dongle = dongle;
+
+		/* Now initialize the dongle!  */
+		dongle->issue->open(dongle, &self->qos);
+		
+		/* Reset dongle */
+		irda_task_execute(dongle, dongle->issue->reset, NULL, NULL, 
+				  NULL);	
+		break;
+	case SIOCSMEDIABUSY: /* Set media busy */
+		irda_device_set_media_busy(self->netdev, TRUE);
+		break;
+	case SIOCGRECEIVING: /* Check if we are receiving right now */
+		irq->ifr_receiving = irport_is_receiving(self);
+		break;
+	case SIOCSDTRRTS:
+		irport_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts);
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+	}
+	
+	restore_flags(flags);
+	
+	return ret;
+}
+
+static struct net_device_stats *irport_net_get_stats(struct device *dev)
+{
+	struct irport_cb *self = (struct irport_cb *) dev->priv;
+	
+	return &self->stats;
+}
 
+#ifdef MODULE
 MODULE_PARM(io, "1-4i");
 MODULE_PARM(irq, "1-4i");
 
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
 MODULE_DESCRIPTION("Half duplex serial driver for IrDA SIR mode");
 
-/*
- * Function cleanup_module (void)
- *
- *    
- *
- */
 void cleanup_module(void)
 {
 	irport_cleanup();
 }
 
-/*
- * Function init_module (void)
- *
- *    
- */
 int init_module(void)
 {
 	return irport_init();
 }
-
 #endif /* MODULE */
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/irda/irtty.c linux.15p9/drivers/net/irda/irtty.c
--- linux.vanilla/drivers/net/irda/irtty.c	Sat Aug 14 02:26:48 1999
+++ linux.15p9/drivers/net/irda/irtty.c	Tue Jan 18 01:08:18 2000
@@ -6,12 +6,12 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Dec  9 21:18:38 1997
- * Modified at:   Mon May 10 15:45:50 1999
+ * Modified at:   Fri Jan 14 21:02:27 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       slip.c by Laurence Culhane,   <loz@holmes.demon.co.uk>
  *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
  * 
- *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1998-2000 Dag Brattli, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -25,46 +25,55 @@
  ********************************************************************/    
 
 #include <linux/module.h>
-#include <asm/uaccess.h>
 #include <linux/kernel.h>
 #include <linux/tty.h>
-#include <asm/segment.h>
 #include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/rtnetlink.h>
+
+#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <net/irda/irda.h>
 #include <net/irda/irtty.h>
 #include <net/irda/wrapper.h>
-#include <net/irda/irlap.h>
 #include <net/irda/timer.h>
 #include <net/irda/irda_device.h>
 
 static hashbin_t *irtty = NULL;
-
 static struct tty_ldisc irda_ldisc;
 
 static int qos_mtt_bits = 0x03;      /* 5 ms or more */
 
+/* Network device fuction prototypes */
 static int  irtty_hard_xmit(struct sk_buff *skb, struct device *dev);
-static void irtty_wait_until_sent(struct irda_device *driver);
-static int  irtty_is_receiving(struct irda_device *idev);
-static void irtty_set_dtr_rts(struct irda_device *idev, int dtr, int rts);
-static int  irtty_raw_write(struct irda_device *idev, __u8 *buf, int len);
 static int  irtty_net_init(struct device *dev);
 static int  irtty_net_open(struct device *dev);
 static int  irtty_net_close(struct device *dev);
+static int  irtty_net_ioctl(struct device *dev, struct ifreq *rq, int cmd);
+static struct net_device_stats *irtty_net_get_stats(struct device *dev);
 
+/* Line discipline function prototypes */
 static int  irtty_open(struct tty_struct *tty);
 static void irtty_close(struct tty_struct *tty);
 static int  irtty_ioctl(struct tty_struct *, void *, int, void *);
 static int  irtty_receive_room(struct tty_struct *tty);
-static void irtty_change_speed(struct irda_device *dev, int baud);
 static void irtty_write_wakeup(struct tty_struct *tty);
-
 static void irtty_receive_buf(struct tty_struct *, const unsigned char *, 
 			      char *, int);
+
+/* IrDA specific function protoctypes */
+static int  irtty_is_receiving(struct irtty_cb *self);
+static int  irtty_set_dtr_rts(struct device *dev, int dtr, int rts);
+static int  irtty_raw_write(struct device *dev, __u8 *buf, int len);
+static int  irtty_raw_read(struct device *dev, __u8 *buf, int len);
+static int  irtty_set_mode(struct device *dev, int mode);
+static int  irtty_change_speed(struct irda_task *task);
+
 char *driver_name = "irtty";
 
-__initfunc(int irtty_init(void))
+int __init irtty_init(void)
 {
 	int status;
 	
@@ -91,10 +100,9 @@
 	irda_ldisc.receive_room = irtty_receive_room;
 	irda_ldisc.write_wakeup = irtty_write_wakeup;
 	
-	if (( status = tty_register_ldisc(N_IRDA, &irda_ldisc)) != 0)  {
-		printk(KERN_ERR 
-		       "IrDA: can't register line discipline (err = %d)\n", 
-		       status);
+	if ((status = tty_register_ldisc(N_IRDA, &irda_ldisc)) != 0) {
+		ERROR("IrDA: can't register line discipline (err = %d)\n", 
+		      status);
 	}
 	
 	return status;
@@ -111,9 +119,7 @@
 {
 	int ret;
 	
-	/*
-	 *  Unregister tty line-discipline
-	 */
+	/* Unregister tty line-discipline */
 	if ((ret = tty_register_ldisc(N_IRDA, NULL))) {
 		ERROR(__FUNCTION__ 
 		      "(), can't unregister line discipline (err = %d)\n",
@@ -138,13 +144,16 @@
  */
 static int irtty_open(struct tty_struct *tty) 
 {
+	struct device *dev;
 	struct irtty_cb *self;
 	char name[16];
+	int err;
 	
 	ASSERT(tty != NULL, return -EEXIST;);
 
 	/* First make sure we're not already connected. */
 	self = (struct irtty_cb *) tty->disc_data;
+
 	if (self != NULL && self->magic == IRTTY_MAGIC)
 		return -EEXIST;
 	
@@ -166,9 +175,8 @@
 	sprintf(name, "%s%d", tty->driver.name,
 		MINOR(tty->device) - tty->driver.minor_start +
 		tty->driver.name_base);
-	
-	/* hashbin_insert( irtty, (QUEUE*) self, 0, self->name); */
-	hashbin_insert(irtty, (QUEUE*) self, (int) self, NULL);
+
+	hashbin_insert(irtty, (queue_t *) self, (int) self, NULL);
 
 	if (tty->driver.flush_buffer)
 		tty->driver.flush_buffer(tty);
@@ -177,11 +185,7 @@
 		tty->ldisc.flush_buffer(tty);
 	
 	self->magic = IRTTY_MAGIC;
-
-	/*
-	 *  Initialize driver
-	 */
-	self->idev.rx_buff.state = OUTSIDE_FRAME;
+	self->mode = IRDA_IRLAP;
 
 	/* 
 	 *  Initialize QoS capabilities, we fill in all the stuff that
@@ -189,38 +193,69 @@
 	 *  that are not device dependent (such as link disconnect time) so
 	 *  this parameter can be set by IrLAP (or the user) instead. DB
 	 */
-	irda_init_max_qos_capabilies(&self->idev.qos);
+	irda_init_max_qos_capabilies(&self->qos);
 
 	/* The only value we must override it the baudrate */
-	self->idev.qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+	self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
 		IR_115200;
-	self->idev.qos.min_turn_time.bits = qos_mtt_bits;
-	self->idev.flags = IFF_SIR | IFF_PIO;
-	irda_qos_bits_to_value(&self->idev.qos);
-
-	/* Specify which buffer allocation policy we need */
-	self->idev.rx_buff.flags = GFP_KERNEL;
-	self->idev.tx_buff.flags = GFP_KERNEL;
+	self->qos.min_turn_time.bits = qos_mtt_bits;
+	self->flags = IFF_SIR | IFF_PIO;
+	irda_qos_bits_to_value(&self->qos);
 
 	/* Specify how much memory we want */
-	self->idev.rx_buff.truesize = 4000; 
-	self->idev.tx_buff.truesize = 4000;
+	self->rx_buff.truesize = 4000; 
+	self->tx_buff.truesize = 4000;
+
+	/* Allocate memory if needed */
+	if (self->rx_buff.truesize > 0) {
+		self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
+						      GFP_KERNEL);
+		if (self->rx_buff.head == NULL)
+			return -ENOMEM;
+		memset(self->rx_buff.head, 0, self->rx_buff.truesize);
+	}
+	if (self->tx_buff.truesize > 0) {
+		self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
+						      GFP_KERNEL);
+		if (self->tx_buff.head == NULL) {
+			kfree(self->rx_buff.head);
+			return -ENOMEM;
+		}
+		memset(self->tx_buff.head, 0, self->tx_buff.truesize);
+	}
+	
+	self->rx_buff.in_frame = FALSE;
+	self->rx_buff.state = OUTSIDE_FRAME;
+	self->tx_buff.data = self->tx_buff.head;
+	self->rx_buff.data = self->rx_buff.head;
+	
+	if (!(dev = dev_alloc("irda%d", &err))) {
+		ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
+		return -ENOMEM;
+	}
+	/* dev_alloc doesn't clear the struct */
+	memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct device)-sizeof(char*));
 
-	/* Initialize callbacks */
-	self->idev.change_speed    = irtty_change_speed;
- 	self->idev.is_receiving    = irtty_is_receiving;
-	self->idev.set_dtr_rts     = irtty_set_dtr_rts;
-	self->idev.raw_write       = irtty_raw_write;
-	self->idev.wait_until_sent = irtty_wait_until_sent;
+	dev->priv = (void *) self;
+	self->netdev = dev;
 
 	/* Override the network functions we need to use */
-	self->idev.netdev.init            = irtty_net_init;
-	self->idev.netdev.hard_start_xmit = irtty_hard_xmit;
-	self->idev.netdev.open            = irtty_net_open;
-	self->idev.netdev.stop            = irtty_net_close;
+	dev->init            = irtty_net_init;
+	dev->hard_start_xmit = irtty_hard_xmit;
+	dev->open            = irtty_net_open;
+	dev->stop            = irtty_net_close;
+	dev->get_stats	     = irtty_net_get_stats;
+	dev->do_ioctl        = irtty_net_ioctl;
+
+	rtnl_lock();
+	err = register_netdevice(dev);
+	rtnl_unlock();
+	if (err) {
+		ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
+		return -1;
+	}
 
-	/* Open the IrDA device */
-	irda_device_open(&self->idev, name, self);
+	MESSAGE("IrDA: Registered device %s\n", dev->name);
 
 	MOD_INC_USE_COUNT;
 
@@ -241,39 +276,56 @@
 	/* First make sure we're connected. */
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRTTY_MAGIC, return;);
-
-	/* Remove driver */
-	irda_device_close(&self->idev);
-
+	
 	/* Stop tty */
 	tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
 	tty->disc_data = 0;
+	
+	/* Remove netdevice */
+	if (self->netdev) {
+		rtnl_lock();
+		unregister_netdevice(self->netdev);
+		rtnl_unlock();
+		/* Must free the old-style 2.2.x device */
+		kfree(self->netdev);
+	}
+	
+	/* We are not using any dongle anymore! */
+	if (self->dongle)
+		irda_device_dongle_cleanup(self->dongle);
+	self->dongle = NULL;
+
+	/* Remove speed changing task if any */
+	if (self->task)
+		irda_task_delete(self->task);
 
 	self->tty = NULL;
 	self->magic = 0;
 	
 	self = hashbin_remove(irtty, (int) self, NULL);
-	
-	if (self != NULL)
-		kfree(self);
 
+	if (self->tx_buff.head)
+		kfree(self->tx_buff.head);
+	
+	if (self->rx_buff.head)
+		kfree(self->rx_buff.head);
+	
+	kfree(self);
+	
  	MOD_DEC_USE_COUNT;
 }
 
 /*
- * Function irtty_stop_receiver (irda_device, stop)
+ * Function irtty_stop_receiver (self, stop)
  *
  *    
  *
  */
-static void irtty_stop_receiver(struct irda_device *idev, int stop)
+static void irtty_stop_receiver(struct irtty_cb *self, int stop)
 {
 	struct termios old_termios;
-	struct irtty_cb *self;
 	int cflag;
 
-	self = (struct irtty_cb *) idev->priv;
-
 	old_termios = *(self->tty->termios);
 	cflag = self->tty->termios->c_cflag;
 	
@@ -287,25 +339,15 @@
 }
 
 /* 
- *  Function irtty_change_speed (self, baud)
+ *  Function irtty_do_change_speed (self, speed)
  *
- *    Change the speed of the serial port. The driver layer must check that
- *    all transmission has finished using the irtty_wait_until_sent() 
- *    function.
+ *    Change the speed of the serial port.
  */
-static void irtty_change_speed(struct irda_device *idev, int baud) 
+static void __irtty_change_speed(struct irtty_cb *self, __u32 speed)
 {
         struct termios old_termios;
-	struct irtty_cb *self;
 	int cflag;
 
-	DEBUG(4,__FUNCTION__ "(), <%ld>\n", jiffies); 
-
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-
-	self = (struct irtty_cb *) idev->priv;
-
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRTTY_MAGIC, return;);
 
@@ -314,9 +356,9 @@
 
 	cflag &= ~CBAUD;
 
-	DEBUG(4, __FUNCTION__ "(), Setting speed to %d\n", baud);
+	IRDA_DEBUG(2, __FUNCTION__ "(), Setting speed to %d\n", speed);
 
-	switch (baud) {
+	switch (speed) {
 	case 1200:
 		cflag |= B1200;
 		break;
@@ -346,6 +388,96 @@
 
 	self->tty->termios->c_cflag = cflag;
 	self->tty->driver.set_termios(self->tty, &old_termios);
+
+	self->io.speed = speed;
+}
+
+/*
+ * Function irtty_change_speed (instance, state, param)
+ *
+ *    State machine for changing speed of the device. We do it this way since
+ *    we cannot use schedule_timeout() when we are in interrupt context
+ */
+static int irtty_change_speed(struct irda_task *task)
+{
+	struct irtty_cb *self;
+	__u32 speed = (__u32) task->param;
+	int ret = 0;
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), <%ld>\n", jiffies); 
+
+	self = (struct irtty_cb *) task->instance;
+	ASSERT(self != NULL, return -1;);
+
+	/* Check if busy */
+	if (self->task && self->task != task) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n");
+		return MSECS_TO_JIFFIES(10);
+	} else
+		self->task = task;
+
+	switch (task->state) {
+	case IRDA_TASK_INIT:
+		/* 
+		 * Make sure all data is sent before changing the speed of the
+		 * serial port.
+		 */
+		if (self->tty->driver.chars_in_buffer(self->tty)) {
+			/* Keep state, and try again later */
+			ret = MSECS_TO_JIFFIES(10);
+			break;
+		} else {
+			/* Transmit buffer is now empty, but it may still
+			 * take over 13 ms for the FIFO to become empty, so
+			 * wait some more to be sure all data is sent
+			 */
+			irda_task_next_state(task, IRDA_TASK_WAIT);
+			ret = MSECS_TO_JIFFIES(13);
+		}
+	case IRDA_TASK_WAIT:
+		if (self->dongle)
+			irda_task_next_state(task, IRDA_TASK_CHILD_INIT);
+		else
+			irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
+		break;
+	case IRDA_TASK_CHILD_INIT:
+		/* Go to default speed */
+		__irtty_change_speed(self, 9600);
+
+		/* Change speed of dongle */
+		if (irda_task_execute(self->dongle,
+				      self->dongle->issue->change_speed, 
+				      NULL, task, (void *) speed))
+		{
+			/* Dongle need more time to change its speed */
+			irda_task_next_state(task, IRDA_TASK_CHILD_WAIT);
+
+			/* Give dongle 1 sec to finish */
+			ret = MSECS_TO_JIFFIES(1000);
+		} else
+			/* Child finished immediately */
+			irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
+		break;
+	case IRDA_TASK_CHILD_WAIT:
+		WARNING(__FUNCTION__ 
+			"(), changing speed of dongle timed out!\n");
+		ret = -1;		
+		break;
+	case IRDA_TASK_CHILD_DONE:
+		/* Finally we are ready to change the speed */
+		__irtty_change_speed(self, speed);
+		
+		irda_task_next_state(task, IRDA_TASK_DONE);
+		self->task = NULL;
+		break;
+	default:
+		ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
+		irda_task_next_state(task, IRDA_TASK_DONE);
+		self->task = NULL;
+		ret = -1;
+		break;
+	}	
+	return ret;
 }
 
 /*
@@ -356,9 +488,11 @@
  */
 static int irtty_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
 {
+	dongle_t *dongle;
+	struct irtty_info info;
 	struct irtty_cb *self;
-	int err = 0;
 	int size = _IOC_SIZE(cmd);
+	int err = 0;
 
 	self = (struct irtty_cb *) tty->disc_data;
 
@@ -366,13 +500,13 @@
 	ASSERT(self->magic == IRTTY_MAGIC, return -EBADR;);
 
 	if (_IOC_DIR(cmd) & _IOC_READ)
-		err = verify_area( VERIFY_WRITE, (void *) arg, size);
+		err = verify_area(VERIFY_WRITE, (void *) arg, size);
 	else if (_IOC_DIR(cmd) & _IOC_WRITE)
-		err = verify_area( VERIFY_READ, (void *) arg, size);
+		err = verify_area(VERIFY_READ, (void *) arg, size);
 	if (err)
 		return err;
 	
-	switch(cmd) {
+	switch (cmd) {
 	case TCGETS:
 	case TCGETA:
 		return n_tty_ioctl(tty, (struct file *) file, cmd, 
@@ -380,7 +514,34 @@
 		break;
 	case IRTTY_IOCTDONGLE:
 		/* Initialize dongle */
-		irda_device_init_dongle(&self->idev, (int) arg);
+		dongle = irda_device_dongle_init(self->netdev, (int) arg);
+		if (!dongle)
+			break;
+		
+		/* Initialize callbacks */
+		dongle->set_mode    = irtty_set_mode;
+		dongle->read        = irtty_raw_read;
+		dongle->write       = irtty_raw_write;
+		dongle->set_dtr_rts = irtty_set_dtr_rts;
+		
+		/* Bind dongle */
+		self->dongle = dongle;
+		
+		/* Now initialize the dongle!  */
+		dongle->issue->open(dongle, &self->qos);
+		
+		/* Reset dongle */
+		irda_task_execute(dongle, dongle->issue->reset, NULL, NULL, 
+				  NULL);		
+		break;
+	case IRTTY_IOCGET:
+		ASSERT(self->netdev != NULL, return -1;);
+
+		memset(&info, 0, sizeof(struct irtty_info)); 
+		strncpy(info.name, self->netdev->name, 5);
+
+		if (copy_to_user(arg, &info, sizeof(struct irtty_info)))
+			return -EFAULT;
 		break;
 	default:
 		return -ENOIOCTLCMD;
@@ -401,27 +562,70 @@
 {
 	struct irtty_cb *self = (struct irtty_cb *) tty->disc_data;
 
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRTTY_MAGIC, return;);
-	
+	if (!self || !self->netdev) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), not ready yet!\n");
+		return;
+	}
+
 	/* Read the characters out of the buffer */
  	while (count--) {
 		/* 
 		 *  Characters received with a parity error, etc?
 		 */
  		if (fp && *fp++) { 
-			DEBUG( 0, "Framing or parity error!\n");
-			irda_device_set_media_busy( &self->idev, TRUE);
-
+			IRDA_DEBUG(0, "Framing or parity error!\n");
+			irda_device_set_media_busy(self->netdev, TRUE);
+			
  			cp++;
  			continue;
  		}
-		/* Unwrap and destuff one byte */
-		async_unwrap_char(&self->idev, *cp++);
+		
+		switch (self->mode) {
+		case IRDA_IRLAP:
+			/* Unwrap and destuff one byte */
+			async_unwrap_char(self->netdev, &self->stats, 
+					  &self->rx_buff, *cp++);
+			break;
+		case IRDA_RAW:
+			/* What should we do when the buffer is full? */
+			if (self->rx_buff.len == self->rx_buff.truesize)
+				self->rx_buff.len = 0;
+			
+			self->rx_buff.data[self->rx_buff.len++] = *cp++;
+			break;
+		default:
+			break;
+		}
 	}
 }
 
 /*
+ * Function irtty_change_speed_complete (task)
+ *
+ *    Called when the change speed operation completes
+ *
+ */
+static int irtty_change_speed_complete(struct irda_task *task)
+{
+	struct irtty_cb *self;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	self = (struct irtty_cb *) task->instance;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->netdev != NULL, return -1;);
+
+	/* Finished changing speed, so we are not busy any longer */
+	self->netdev->tbusy = 0;
+
+	/* Signal network layer so it can try to send the frame */
+	mark_bh(NET_BH);
+
+	return 0;
+}
+
+/*
  * Function irtty_hard_xmit (skb, dev)
  *
  *    Transmit frame
@@ -430,56 +634,40 @@
 static int irtty_hard_xmit(struct sk_buff *skb, struct device *dev)
 {
 	struct irtty_cb *self;
-	struct irda_device *idev;
 	int actual = 0;
+	__u32 speed;
 
-	idev = (struct irda_device *) dev->priv;
-
-	ASSERT(idev != NULL, return 0;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
-	
-	self = (struct irtty_cb *) idev->priv;
-
+	self = (struct irtty_cb *) dev->priv;
 	ASSERT(self != NULL, return 0;);
-	ASSERT(self->magic == IRTTY_MAGIC, return 0;);
 
 	/* Lock transmit buffer */
 	if (irda_lock((void *) &dev->tbusy) == FALSE)
 		return -EBUSY;
-	
+
+	/* Check if we need to change the speed */
+	if ((speed = irda_get_speed(skb)) != self->io.speed)
+		self->new_speed = speed;
+
 	/* Init tx buffer*/
-	idev->tx_buff.data = idev->tx_buff.head;
+	self->tx_buff.data = self->tx_buff.head;
 	
         /* Copy skb to tx_buff while wrapping, stuffing and making CRC */
-        idev->tx_buff.len = async_wrap_skb(skb, idev->tx_buff.data, 
-					   idev->tx_buff.truesize); 
+        self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, 
+					   self->tx_buff.truesize); 
 
 	self->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
 
 	dev->trans_start = jiffies;
+	self->stats.tx_bytes += self->tx_buff.len;
 
 	if (self->tty->driver.write)
 		actual = self->tty->driver.write(self->tty, 0, 
-						 idev->tx_buff.data, 
-						 idev->tx_buff.len);
-
+						 self->tx_buff.data, 
+						 self->tx_buff.len);
 	/* Hide the part we just transmitted */
-	idev->tx_buff.data += actual;
-	idev->tx_buff.len -= actual;
+	self->tx_buff.data += actual;
+	self->tx_buff.len -= actual;
 
-	idev->stats.tx_packets++;
-	idev->stats.tx_bytes += idev->tx_buff.len;
-#if 0
-	/* 
-	 *  Did we transmit the whole frame? Commented out for now since
-	 *  I must check if this optimalization really works. DB.
-	 */
- 	if ((idev->tx_buff.len) == 0) {
- 		DEBUG( 4, "irtty_xmit_buf: finished with frame!\n");
- 		self->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
- 		irda_unlock( &self->tbusy);
- 	}
-#endif
 	dev_kfree_skb(skb);
 
 	return 0;
@@ -493,7 +681,7 @@
 */
 static int irtty_receive_room(struct tty_struct *tty) 
 {
-	DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 	return 65536;  /* We can handle an infinite amount of data. :-) */
 }
 
@@ -507,7 +695,6 @@
 static void irtty_write_wakeup(struct tty_struct *tty) 
 {
 	struct irtty_cb *self = (struct irtty_cb *) tty->disc_data;
-	struct irda_device *idev;
 	int actual = 0;
 	
 	/* 
@@ -516,61 +703,49 @@
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRTTY_MAGIC, return;);
 
-	idev = &self->idev;
-
 	/* Finished with frame?  */
-	if (idev->tx_buff.len > 0)  {
+	if (self->tx_buff.len > 0)  {
 		/* Write data left in transmit buffer */
-		actual = tty->driver.write(tty, 0, idev->tx_buff.data, 
-					   idev->tx_buff.len);
+		actual = tty->driver.write(tty, 0, self->tx_buff.data, 
+					   self->tx_buff.len);
+
+		self->tx_buff.data += actual;
+		self->tx_buff.len  -= actual;
 
-		idev->tx_buff.data += actual;
-		idev->tx_buff.len  -= actual;
+		self->stats.tx_packets++;		      
 	} else {		
 		/* 
 		 *  Now serial buffer is almost free & we can start 
 		 *  transmission of another packet 
 		 */
-		DEBUG(5, __FUNCTION__ "(), finished with frame!\n");
+		IRDA_DEBUG(5, __FUNCTION__ "(), finished with frame!\n");
 		
 		tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
 
-		idev->netdev.tbusy = 0; /* Unlock */
-			
-		/* Tell network layer that we want more frames */
-		mark_bh(NET_BH);
+		if (self->new_speed) {
+			IRDA_DEBUG(5, __FUNCTION__ "(), Changing speed!\n");
+			irda_task_execute(self, irtty_change_speed, 
+					  irtty_change_speed_complete, 
+					  NULL, (void *) self->new_speed);
+			self->new_speed = 0;
+		} else {
+			self->netdev->tbusy = 0; /* Unlock */
+		
+			/* Tell network layer that we want more frames */
+			mark_bh(NET_BH);
+		}
 	}
 }
 
 /*
- * Function irtty_is_receiving (idev)
+ * Function irtty_is_receiving (self)
  *
  *    Return TRUE is we are currently receiving a frame
  *
  */
-static int irtty_is_receiving(struct irda_device *idev)
-{
-	return (idev->rx_buff.state != OUTSIDE_FRAME);
-}
-
-/*
- * Function irtty_change_speed_ready (idev)
- *
- *    Are we completely finished with transmitting frames so its possible
- *    to change the speed of the serial port. Warning this function must
- *    be called with a process context!
- */
-static void irtty_wait_until_sent(struct irda_device *idev)
+static int irtty_is_receiving(struct irtty_cb *self)
 {
-	struct irtty_cb *self = (struct irtty_cb *) idev->priv;
-
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRTTY_MAGIC, return;);
-	
-	DEBUG(4, "Chars in buffer %d\n", 
-	      self->tty->driver.chars_in_buffer(self->tty));
-	
-	tty_wait_until_sent(self->tty, 0);
+	return (self->rx_buff.state != OUTSIDE_FRAME);
 }
 
 /*
@@ -579,15 +754,14 @@
  *    This function can be used by dongles etc. to set or reset the status
  *    of the dtr and rts lines
  */
-static void irtty_set_dtr_rts(struct irda_device *idev, int dtr, int rts)
+static int irtty_set_dtr_rts(struct device *dev, int dtr, int rts)
 {
-	struct tty_struct *tty;
 	struct irtty_cb *self;
+	struct tty_struct *tty;
 	mm_segment_t fs;
 	int arg = 0;
 
-	self = (struct irtty_cb *) idev->priv;
-
+	self = (struct irtty_cb *) dev->priv;
 	tty = self->tty;
 
 #ifdef TIOCM_OUT2 /* Not defined for ARM */
@@ -610,20 +784,93 @@
 	set_fs(get_ds());
 	
 	if (tty->driver.ioctl(tty, NULL, TIOCMSET, (unsigned long) &arg)) { 
-		ERROR(__FUNCTION__ "(), error doing ioctl!\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), error doing ioctl!\n");
 	}
 	set_fs(fs);
+
+	return 0;
 }
 
-static int irtty_raw_write(struct irda_device *idev, __u8 *buf, int len)
+/*
+ * Function irtty_set_mode (self, status)
+ *
+ *    For the airport dongle, we need support for reading raw characters
+ *    from the IrDA device. This function switches between those modes. 
+ *    FALSE is the default mode, and will then treat incoming data as IrDA 
+ *    packets.
+ */
+int irtty_set_mode(struct device *dev, int mode)
 {
 	struct irtty_cb *self;
-	int actual = 0;
 
-	ASSERT(idev != NULL, return 0;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+	self = (struct irtty_cb *) dev->priv;
+
+	ASSERT(self != NULL, return -1;);
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), mode=%s\n", infrared_mode[mode]);
+	
+	/* save status for driver */
+	self->mode = mode;
 	
-	self = (struct irtty_cb *) idev->priv;
+	/* reset the buffer state */
+	self->rx_buff.data = self->rx_buff.head;
+	self->rx_buff.len = 0;
+	self->rx_buff.state = OUTSIDE_FRAME;
+
+	return 0;
+}
+
+/*
+ * Function irtty_raw_read (self, buf, len)
+ *
+ *    Receive incomming data. This function sleeps, so it must only be
+ *    called with a process context. Timeout is currently defined to be
+ *    a multiple of 10 ms.
+ */
+static int irtty_raw_read(struct device *dev, __u8 *buf, int len)
+{
+	struct irtty_cb *self;
+	int count;
+
+	self = (struct irtty_cb *) dev->priv;
+
+	ASSERT(self != NULL, return 0;);
+	ASSERT(self->magic == IRTTY_MAGIC, return 0;);
+
+	return 0;
+#if 0
+	buf = self->rx_buff.data;
+
+	/* Wait for the requested amount of data to arrive */
+	while (len < self->rx_buff.len) {
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(MSECS_TO_JIFFIES(10));
+
+		if (!timeout--)
+			break;
+	}
+	
+	count = self->rx_buff.len < len ? self->rx_buff.len : len;
+
+	/* 
+	 * Reset the state, this mean that a raw read is sort of a 
+	 * datagram read, and _not_ a stream style read. Be aware of the
+	 * difference. Implementing it the other way will just be painful ;-)
+	 */
+	self->rx_buff.data = self->rx_buff.head;
+	self->rx_buff.len = 0;
+	self->rx_buff.state = OUTSIDE_FRAME;
+#endif
+	/* Return the amount we were able to get */
+	return count;
+}
+
+static int irtty_raw_write(struct device *dev, __u8 *buf, int len)
+{
+	struct irtty_cb *self;
+	int actual = 0;
+
+	self = (struct irtty_cb *) dev->priv;
 
 	ASSERT(self != NULL, return 0;);
 	ASSERT(self->magic == IRTTY_MAGIC, return 0;);
@@ -646,13 +893,27 @@
 
 static int irtty_net_open(struct device *dev)
 {
-	ASSERT(dev != NULL, return -1;);
+	struct irtty_cb *self = (struct irtty_cb *) dev->priv;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRTTY_MAGIC, return -1;);
 
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+	
 	/* Ready to play! */
 	dev->tbusy = 0;
 	dev->interrupt = 0;
 	dev->start = 1;
 
+	/* Make sure we can receive more data */
+	irtty_stop_receiver(self, FALSE);
+
+	/* 
+	 * Open new IrLAP layer instance, now that everything should be
+	 * initialized properly 
+	 */
+	self->irlap = irlap_open(dev, &self->qos);
+
 	MOD_INC_USE_COUNT;
 
 	return 0;
@@ -660,17 +921,108 @@
 
 static int irtty_net_close(struct device *dev)
 {
-	ASSERT(dev != NULL, return -1;);
-	
+	struct irtty_cb *self = (struct irtty_cb *) dev->priv;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRTTY_MAGIC, return -1;);
+
+	/* Make sure we don't receive more data */
+	irtty_stop_receiver(self, TRUE);
+
 	/* Stop device */
 	dev->tbusy = 1;
 	dev->start = 0;
 
+	/* Stop and remove instance of IrLAP */
+	if (self->irlap)
+		irlap_close(self->irlap);
+	self->irlap = NULL;
+
 	MOD_DEC_USE_COUNT;
 
 	return 0;
 }
 
+/*
+ * Function irtty_net_ioctl (dev, rq, cmd)
+ *
+ *    Process IOCTL commands for this device
+ *
+ */
+static int irtty_net_ioctl(struct device *dev, struct ifreq *rq, int cmd)
+{
+	struct if_irda_req *irq = (struct if_irda_req *) rq;
+	struct irtty_cb *self;
+	dongle_t *dongle;
+	unsigned long flags;
+	int ret = 0;
+
+	ASSERT(dev != NULL, return -1;);
+
+	self = dev->priv;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRTTY_MAGIC, return -1;);
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
+	
+	/* Disable interrupts & save flags */
+	save_flags(flags);
+	cli();
+	
+	switch (cmd) {
+	case SIOCSBANDWIDTH: /* Set bandwidth */
+		irda_task_execute(self, irtty_change_speed, NULL, NULL, 
+				  (void *) irq->ifr_baudrate);
+		break;
+	case SIOCSDONGLE: /* Set dongle */
+		/* Initialize dongle */
+		dongle = irda_device_dongle_init(dev, irq->ifr_dongle);
+		if (!dongle)
+			break;
+		
+		dongle->set_mode    = irtty_set_mode;
+		dongle->read        = irtty_raw_read;
+		dongle->write       = irtty_raw_write;
+		dongle->set_dtr_rts = irtty_set_dtr_rts;
+		
+		self->dongle = dongle;
+
+		/* Now initialize the dongle!  */
+		dongle->issue->open(dongle, &self->qos);
+		
+		/* Reset dongle */
+		irda_task_execute(dongle, dongle->issue->reset, NULL, NULL, 
+				  NULL);	
+		break;
+	case SIOCSMEDIABUSY: /* Set media busy */
+		irda_device_set_media_busy(self->netdev, TRUE);
+		break;
+	case SIOCGRECEIVING: /* Check if we are receiving right now */
+		irq->ifr_receiving = irtty_is_receiving(self);
+		break;
+	case SIOCSDTRRTS:
+		irtty_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts);
+		break;
+	case SIOCSMODE:
+		irtty_set_mode(dev, irq->ifr_mode);
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+	}
+	
+	restore_flags(flags);
+	
+	return ret;
+}
+
+static struct net_device_stats *irtty_net_get_stats(struct device *dev)
+{
+	struct irtty_cb *self = (struct irtty_cb *) dev->priv;
+
+	return &self->stats;
+}
+
 #ifdef MODULE
 
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
@@ -701,10 +1053,3 @@
 }
 
 #endif /* MODULE */
-
-
-
-
-
-
-
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/irda/litelink.c linux.15p9/drivers/net/irda/litelink.c
--- linux.vanilla/drivers/net/irda/litelink.c	Sat Aug 14 02:26:48 1999
+++ linux.15p9/drivers/net/irda/litelink.c	Tue Jan 18 01:08:18 2000
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      litelink.c
- * Version:       1.0
+ * Version:       1.1
  * Description:   Driver for the Parallax LiteLink dongle
  * Status:        Stable
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Fri May  7 12:50:33 1999
- * Modified at:   Wed May 19 07:25:15 1999
+ * Modified at:   Fri Dec 17 09:14:23 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -37,30 +37,28 @@
 #include <net/irda/irda.h>
 #include <net/irda/irmod.h>
 #include <net/irda/irda_device.h>
-#include <net/irda/dongle.h>
 
 #define MIN_DELAY 25      /* 15 us, but wait a little more to be sure */
 #define MAX_DELAY 10000   /* 1 ms */
 
-static void litelink_open(struct irda_device *idev, int type);
-static void litelink_close(struct irda_device *dev);
-static void litelink_change_speed(struct irda_device *dev, int baudrate);
-static void litelink_reset(struct irda_device *dev);
-static void litelink_init_qos(struct irda_device *idev, struct qos_info *qos);
+static void litelink_open(dongle_t *self, struct qos_info *qos);
+static void litelink_close(dongle_t *self);
+static int  litelink_change_speed(struct irda_task *task);
+static int  litelink_reset(struct irda_task *task);
 
 /* These are the baudrates supported */
-static int baud_rates[] = { 115200, 57600, 38400, 19200, 9600 };
+static __u32 baud_rates[] = { 115200, 57600, 38400, 19200, 9600 };
 
-static struct dongle dongle = {
-	LITELINK_DONGLE,
+static struct dongle_reg dongle = {
+	Q_NULL,
+	IRDA_LITELINK_DONGLE,
 	litelink_open,
 	litelink_close,
 	litelink_reset,
 	litelink_change_speed,
-	litelink_init_qos,
 };
 
-__initfunc(int litelink_init(void))
+int __init litelink_init(void)
 {
 	return irda_device_register_dongle(&dongle);
 }
@@ -70,114 +68,102 @@
 	irda_device_unregister_dongle(&dongle);
 }
 
-static void litelink_open(struct irda_device *idev, int type)
+static void litelink_open(dongle_t *self, struct qos_info *qos)
 {
-	strcat(idev->description, " <-> litelink");
-
-        idev->io.dongle_id = type;
-	idev->flags |= IFF_DONGLE;
+	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+	qos->min_turn_time.bits = 0x7f; /* Needs 0.01 ms */
 
 	MOD_INC_USE_COUNT;
 }
 
-static void litelink_close(struct irda_device *idev)
+static void litelink_close(dongle_t *self)
 {
 	/* Power off dongle */
-	irda_device_set_dtr_rts(idev, FALSE, FALSE);
+	self->set_dtr_rts(self->dev, FALSE, FALSE);
 
 	MOD_DEC_USE_COUNT;
 }
 
 /*
- * Function litelink_change_speed (tty, baud)
+ * Function litelink_change_speed (task)
  *
  *    Change speed of the Litelink dongle. To cycle through the available 
  *    baud rates, pulse RTS low for a few ms.  
  */
-static void litelink_change_speed(struct irda_device *idev, int baudrate)
+static int litelink_change_speed(struct irda_task *task)
 {
+	dongle_t *self = (dongle_t *) task->instance;
+	__u32 speed = (__u32) task->param;
         int i;
 	
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-	
 	/* Clear RTS to reset dongle */
-	irda_device_set_dtr_rts(idev, TRUE, FALSE);
+	self->set_dtr_rts(self->dev, TRUE, FALSE);
 
 	/* Sleep a minimum of 15 us */
 	udelay(MIN_DELAY);
 
 	/* Go back to normal mode */
-	irda_device_set_dtr_rts(idev, TRUE, TRUE);
+	self->set_dtr_rts(self->dev, TRUE, TRUE);
 	
 	/* Sleep a minimum of 15 us */
 	udelay(MIN_DELAY);
 	
 	/* Cycle through avaiable baudrates until we reach the correct one */
-	for (i=0; i<5 && baud_rates[i] != baudrate; i++) {
-
+	for (i=0; i<5 && baud_rates[i] != speed; i++) {
 		/* Set DTR, clear RTS */
-		irda_device_set_dtr_rts(idev, FALSE, TRUE);
+		self->set_dtr_rts(self->dev, FALSE, TRUE);
 		
 		/* Sleep a minimum of 15 us */
 		udelay(MIN_DELAY);
 		
 		/* Set DTR, Set RTS */
-		irda_device_set_dtr_rts(idev, TRUE, TRUE);
+		self->set_dtr_rts(self->dev, TRUE, TRUE);
 		
 		/* Sleep a minimum of 15 us */
 		udelay(MIN_DELAY);
         }
+	irda_task_next_state(task, IRDA_TASK_DONE);
+
+	return 0;
 }
 
 /*
- * Function litelink_reset (dev)
+ * Function litelink_reset (task)
  *
- *      Reset the Litelink type dongle. Warning, this function must only be
- *      called with a process context!
+ *      Reset the Litelink type dongle.
  *
  */
-static void litelink_reset(struct irda_device *idev)
+static int litelink_reset(struct irda_task *task)
 {
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-	
+	dongle_t *self = (dongle_t *) task->instance;
+
 	/* Power on dongle */
-	irda_device_set_dtr_rts(idev, TRUE, TRUE);
+	self->set_dtr_rts(self->dev, TRUE, TRUE);
 
 	/* Sleep a minimum of 15 us */
 	udelay(MIN_DELAY);
 
 	/* Clear RTS to reset dongle */
-	irda_device_set_dtr_rts(idev, TRUE, FALSE);
+	self->set_dtr_rts(self->dev, TRUE, FALSE);
 
 	/* Sleep a minimum of 15 us */
 	udelay(MIN_DELAY);
 
 	/* Go back to normal mode */
-	irda_device_set_dtr_rts(idev, TRUE, TRUE);
+	self->set_dtr_rts(self->dev, TRUE, TRUE);
 	
 	/* Sleep a minimum of 15 us */
 	udelay(MIN_DELAY);
 
 	/* This dongles speed defaults to 115200 bps */
-	idev->qos.baud_rate.value = 115200;
-}
+	self->speed = 115200;
 
-/*
- * Function litelink_init_qos (qos)
- *
- *    Initialize QoS capabilities
- *
- */
-static void litelink_init_qos(struct irda_device *idev, struct qos_info *qos)
-{
-	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
-	qos->min_turn_time.bits &= 0x40; /* Needs 0.01 ms */
+	irda_task_next_state(task, IRDA_TASK_DONE);
+
+	return 0;
 }
 
 #ifdef MODULE
-
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
 MODULE_DESCRIPTION("Parallax Litelink dongle driver");	
 		
@@ -202,5 +188,4 @@
 {
 	litelink_cleanup();
 }
-
-#endif
+#endif /* MODULE */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/irda/nsc-ircc.c linux.15p9/drivers/net/irda/nsc-ircc.c
--- linux.vanilla/drivers/net/irda/nsc-ircc.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/net/irda/nsc-ircc.c	Wed Jan 26 23:13:17 2000
@@ -0,0 +1,2076 @@
+/*********************************************************************
+ *                
+ * Filename:      nsc-ircc.c
+ * Version:       1.0
+ * Description:   Driver for the NSC PC'108 and PC'338 IrDA chipsets
+ * Status:        Stable.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sat Nov  7 21:43:15 1998
+ * Modified at:   Wed Jan 26 13:00:29 2000
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>
+ *     Copyright (c) 1998 Lichen Wang, <lwang@actisys.com>
+ *     Copyright (c) 1998 Actisys Corp., www.actisys.com
+ *     All Rights Reserved
+ *      
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ *  
+ *     Neither Dag Brattli nor University of Tromsř admit liability nor
+ *     provide warranty for any of this software. This material is 
+ *     provided "AS-IS" and at no charge.
+ *
+ *     Notice that all functions that needs to access the chip in _any_
+ *     way, must save BSR register on entry, and restore it on exit. 
+ *     It is _very_ important to follow this policy!
+ *
+ *         __u8 bank;
+ *     
+ *         bank = inb(iobase+BSR);
+ *  
+ *         do_your_stuff_here();
+ *
+ *         outb(bank, iobase+BSR);
+ *
+ *    If you find bugs in this file, its very likely that the same bug
+ *    will also be in w83977af_ir.c since the implementations are quite
+ *    similar.
+ *     
+ ********************************************************************/
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/malloc.h>
+#include <linux/init.h>
+#include <linux/rtnetlink.h>
+
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/byteorder.h>
+
+#ifdef CONFIG_APM
+#include <linux/apm_bios.h>
+#endif
+
+#include <net/irda/wrapper.h>
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irlap_frame.h>
+#include <net/irda/irda_device.h>
+
+#include <net/irda/nsc-ircc.h>
+
+#define CHIP_IO_EXTENT 8
+#define BROKEN_DONGLE_ID
+
+static char *driver_name = "nsc-ircc";
+
+/* Module parameters */
+static int qos_mtt_bits = 0x07;  /* 1 ms or more */
+static int dongle_id = 0;
+
+/* Use BIOS settions by default, but user may supply module parameters */
+static unsigned int io[]  = { ~0, ~0, ~0, ~0 };
+static unsigned int irq[] = { 0, 0, 0, 0, 0 };
+static unsigned int dma[] = { 0, 0, 0, 0, 0 };
+
+static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info);
+static int nsc_ircc_probe_338(nsc_chip_t *chip, chipio_t *info);
+static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info);
+static int nsc_ircc_init_338(nsc_chip_t *chip, chipio_t *info);
+
+/* These are the known NSC chips */
+static nsc_chip_t chips[] = {
+	{ "PC87108", { 0x150, 0x398, 0xea }, 0x05, 0x10, 0xf0, 
+	  nsc_ircc_probe_108, nsc_ircc_init_108 },
+	{ "PC87338", { 0x398, 0x15c, 0x2e }, 0x08, 0xb0, 0xf0, 
+	  nsc_ircc_probe_338, nsc_ircc_init_338 },
+	{ NULL }
+};
+
+/* Max 4 instances for now */
+static struct nsc_ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL };
+
+static char *dongle_types[] = {
+	"Differential serial interface",
+	"Differential serial interface",
+	"Reserved",
+	"Reserved",
+	"Sharp RY5HD01",
+	"Reserved",
+	"Single-ended serial interface",
+	"Consumer-IR only",
+	"HP HSDL-2300, HP HSDL-3600/HSDL-3610",
+	"IBM31T1100 or Temic TFDS6000/TFDS6500",
+	"Reserved",
+	"Reserved",
+	"HP HSDL-1100/HSDL-2100",
+	"HP HSDL-1100/HSDL-2100"
+	"Supports SIR Mode only",
+	"No dongle connected",
+};
+
+/* Some prototypes */
+static int  nsc_ircc_open(int i, chipio_t *info);
+#ifdef MODULE
+static int  nsc_ircc_close(struct nsc_ircc_cb *self);
+#endif /* MODULE */
+static int  nsc_ircc_setup(chipio_t *info);
+static void nsc_ircc_pio_receive(struct nsc_ircc_cb *self);
+static int  nsc_ircc_dma_receive(struct nsc_ircc_cb *self); 
+static int  nsc_ircc_dma_receive_complete(struct nsc_ircc_cb *self, int iobase);
+static int  nsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct device *dev);
+static int  nsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct device *dev);
+static int  nsc_ircc_pio_write(int iobase, __u8 *buf, int len, int fifo_size);
+static void nsc_ircc_dma_xmit(struct nsc_ircc_cb *self, int iobase);
+static void nsc_ircc_change_speed(struct nsc_ircc_cb *self, __u32 baud);
+static void nsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static int  nsc_ircc_is_receiving(struct nsc_ircc_cb *self);
+static int  nsc_ircc_read_dongle_id (int iobase);
+static void nsc_ircc_init_dongle_interface (int iobase, int dongle_id);
+
+static int  nsc_ircc_net_init(struct device *dev);
+static int  nsc_ircc_net_open(struct device *dev);
+static int  nsc_ircc_net_close(struct device *dev);
+static int  nsc_ircc_net_ioctl(struct device *dev, struct ifreq *rq, int cmd);
+static struct net_device_stats *nsc_ircc_net_get_stats(struct device *dev);
+#ifdef CONFIG_APM
+static int nsc_ircc_apmproc(apm_event_t event);
+#endif /* CONFIG_APM */
+
+/*
+ * Function nsc_ircc_init ()
+ *
+ *    Initialize chip. Just try to find out how many chips we are dealing with
+ *    and where they are
+ */
+int __init nsc_ircc_init(void)
+{
+	chipio_t info;
+	nsc_chip_t *chip;
+	int ret = -ENODEV;
+	int cfg_base;
+	int cfg, id;
+	int reg;
+	int i = 0;
+
+	/* Probe for all the NSC chipsets we know about */
+	for (chip=chips; chip->name ; chip++,i++) {
+		IRDA_DEBUG(2, __FUNCTION__"(), Probing for %s ...\n", 
+			   chip->name);
+		
+		/* Try all config registers for this chip */
+		for (cfg=0; cfg<3; cfg++) {
+			cfg_base = chip->cfg[cfg];
+			if (!cfg_base)
+				continue;
+			
+			memset(&info, 0, sizeof(chipio_t));
+			info.cfg_base = cfg_base;
+			info.fir_base = io[i];
+			info.dma = dma[i];
+			info.irq = irq[i];
+
+			/* Read index register */
+			reg = inb(cfg_base);
+			if (reg == 0xff) {
+				IRDA_DEBUG(2, __FUNCTION__ 
+					   "() no chip at 0x%03x\n", cfg_base);
+				continue;
+			}
+			
+			/* Read chip identification register */
+			outb(chip->cid_index, cfg_base);
+			id = inb(cfg_base+1);
+			if ((id & chip->cid_mask) == chip->cid_value) {
+				IRDA_DEBUG(2, __FUNCTION__ 
+					   "() Found %s chip, revision=%d\n",
+					   chip->name, id & ~chip->cid_mask);
+				/* 
+				 * If the user supplies the base address, then
+				 * we init the chip, if not we probe the values
+				 * set by the BIOS
+				 */				
+				if (io[i] < 2000) {
+					chip->init(chip, &info);
+				} else
+					chip->probe(chip, &info);
+
+				if (nsc_ircc_open(i, &info) == 0)
+					ret = 0;
+				i++;
+			} else {
+				IRDA_DEBUG(2, __FUNCTION__ 
+					   "(), Wrong chip id=0x%02x\n", id);
+			}
+		} 
+		
+	}
+#ifdef CONFIG_APM
+	/* Make sure at least one chip was found before enabling APM */
+	if (ret == 0)
+		apm_register_callback(nsc_ircc_apmproc);
+#endif /* CONFIG_APM */
+
+	return ret;
+}
+
+/*
+ * Function nsc_ircc_cleanup ()
+ *
+ *    Close all configured chips
+ *
+ */
+#ifdef MODULE
+static void nsc_ircc_cleanup(void)
+{
+	int i;
+
+#ifdef CONFIG_APM
+	apm_unregister_callback(nsc_ircc_apmproc);
+#endif /* CONFIG_APM */
+
+	for (i=0; i < 4; i++) {
+		if (dev_self[i])
+			nsc_ircc_close(dev_self[i]);
+	}
+}
+#endif /* MODULE */
+
+/*
+ * Function nsc_ircc_open (iobase, irq)
+ *
+ *    Open driver instance
+ *
+ */
+static int nsc_ircc_open(int i, chipio_t *info)
+{
+	struct device *dev;
+	struct nsc_ircc_cb *self;
+	int ret;
+	int err;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	if ((nsc_ircc_setup(info)) == -1)
+		return -1;
+
+	/* Allocate new instance of the driver */
+	self = kmalloc(sizeof(struct nsc_ircc_cb), GFP_KERNEL);
+	if (self == NULL) {
+		ERROR(__FUNCTION__ "(), can't allocate memory for "
+		       "control block!\n");
+		return -ENOMEM;
+	}
+	memset(self, 0, sizeof(struct nsc_ircc_cb));
+	spin_lock_init(&self->lock);
+   
+	/* Need to store self somewhere */
+	dev_self[i] = self;
+	self->index = i;
+
+	/* Initialize IO */
+	self->io.cfg_base  = info->cfg_base;
+	self->io.fir_base  = info->fir_base;
+        self->io.irq       = info->irq;
+        self->io.fir_ext   = CHIP_IO_EXTENT;
+        self->io.dma       = info->dma;
+        self->io.fifo_size = 32;
+	
+	/* Reserve the ioports that we need */
+	ret = check_region(self->io.fir_base, self->io.fir_ext);
+	if (ret < 0) { 
+		WARNING(__FUNCTION__ "(), can't get iobase of 0x%03x\n",
+			self->io.fir_base);
+		dev_self[i] = NULL;
+		kfree(self);
+		return -ENODEV;
+	}
+	request_region(self->io.fir_base, self->io.fir_ext, driver_name);
+
+	/* Initialize QoS for this device */
+	irda_init_max_qos_capabilies(&self->qos);
+	
+	/* The only value we must override it the baudrate */
+	self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+		IR_115200|IR_576000|IR_1152000 |(IR_4000000 << 8);
+	
+	self->qos.min_turn_time.bits = qos_mtt_bits;
+	irda_qos_bits_to_value(&self->qos);
+	
+	self->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO|IFF_DONGLE;
+
+	/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
+	self->rx_buff.truesize = 14384; 
+	self->tx_buff.truesize = 14384;
+
+	/* Allocate memory if needed */
+	self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
+					      GFP_KERNEL|GFP_DMA);
+	if (self->rx_buff.head == NULL) {
+		kfree(self);
+		return -ENOMEM;
+	}
+	memset(self->rx_buff.head, 0, self->rx_buff.truesize);
+	
+	self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
+					      GFP_KERNEL|GFP_DMA);
+	if (self->tx_buff.head == NULL) {
+		kfree(self);
+		kfree(self->rx_buff.head);
+		return -ENOMEM;
+	}
+	memset(self->tx_buff.head, 0, self->tx_buff.truesize);
+
+	self->rx_buff.in_frame = FALSE;
+	self->rx_buff.state = OUTSIDE_FRAME;
+	self->tx_buff.data = self->tx_buff.head;
+	self->rx_buff.data = self->rx_buff.head;
+	
+	/* Reset Tx queue info */
+	self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0;
+	self->tx_fifo.tail = self->tx_buff.head;
+
+	if (!(dev = dev_alloc("irda%d", &err))) {
+		ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
+		return -ENOMEM;
+	}
+	/* dev_alloc doesn't clear the struct, so lets do a little hack */
+	memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct device)-sizeof(char*));
+
+	dev->priv = (void *) self;
+	self->netdev = dev;
+
+	/* Override the network functions we need to use */
+	dev->init            = nsc_ircc_net_init;
+	dev->hard_start_xmit = nsc_ircc_hard_xmit_sir;
+	dev->open            = nsc_ircc_net_open;
+	dev->stop            = nsc_ircc_net_close;
+	dev->do_ioctl        = nsc_ircc_net_ioctl;
+	dev->get_stats	     = nsc_ircc_net_get_stats;
+
+	rtnl_lock();
+	err = register_netdevice(dev);
+	rtnl_unlock();
+	if (err) {
+		ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
+		return -1;
+	}
+	MESSAGE("IrDA: Registered device %s\n", dev->name);
+
+	/* Check if user has supplied the dongle id or not */
+	if (!dongle_id) {
+		dongle_id = nsc_ircc_read_dongle_id(self->io.fir_base);
+		
+		MESSAGE("%s, Found dongle: %s\n", driver_name,
+			dongle_types[dongle_id]);
+	} else {
+		MESSAGE("%s, Using dongle: %s\n", driver_name,
+			dongle_types[dongle_id]);
+	}
+	
+	self->io.dongle_id = dongle_id;
+	nsc_ircc_init_dongle_interface(self->io.fir_base, dongle_id);
+
+	return 0;
+}
+
+#ifdef MODULE
+/*
+ * Function nsc_ircc_close (self)
+ *
+ *    Close driver instance
+ *
+ */
+static int nsc_ircc_close(struct nsc_ircc_cb *self)
+{
+	int iobase;
+
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return -1;);
+
+        iobase = self->io.fir_base;
+
+	/* Remove netdevice */
+	if (self->netdev) {
+		rtnl_lock();
+		unregister_netdevice(self->netdev);
+		rtnl_unlock();
+		/* Must free the old-style 2.2.x device */
+		kfree(self->netdev);
+	}
+
+	/* Release the PORT that this driver is using */
+	IRDA_DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", 
+		   self->io.fir_base);
+	release_region(self->io.fir_base, self->io.fir_ext);
+
+	if (self->tx_buff.head)
+		kfree(self->tx_buff.head);
+	
+	if (self->rx_buff.head)
+		kfree(self->rx_buff.head);
+
+	dev_self[self->index] = NULL;
+	kfree(self);
+	
+	return 0;
+}
+#endif /* MODULE */
+
+/*
+ * Function nsc_ircc_init_108 (iobase, cfg_base, irq, dma)
+ *
+ *    Initialize the NSC '108 chip
+ *
+ */
+static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info)
+{
+	int cfg_base = info->cfg_base;
+	__u8 temp=0;
+
+	outb(2, cfg_base);      /* Mode Control Register (MCTL) */
+	outb(0x00, cfg_base+1); /* Disable device */
+	
+	/* Base Address and Interrupt Control Register (BAIC) */
+	outb(0, cfg_base);
+	switch (info->fir_base) {
+	case 0x3e8: outb(0x14, cfg_base+1); break;
+	case 0x2e8: outb(0x15, cfg_base+1); break;
+	case 0x3f8: outb(0x16, cfg_base+1); break;
+	case 0x2f8: outb(0x17, cfg_base+1); break;
+	default: ERROR(__FUNCTION__ "(), invalid base_address");
+	}
+	
+	/* Control Signal Routing Register (CSRT) */
+	switch (info->irq) {
+	case 3:  temp = 0x01; break;
+	case 4:  temp = 0x02; break;
+	case 5:  temp = 0x03; break;
+	case 7:  temp = 0x04; break;
+	case 9:  temp = 0x05; break;
+	case 11: temp = 0x06; break;
+	case 15: temp = 0x07; break;
+	default: ERROR(__FUNCTION__ "(), invalid irq");
+	}
+	outb(1, cfg_base);
+	
+	switch (info->dma) {	
+	case 0: outb(0x08+temp, cfg_base+1); break;
+	case 1: outb(0x10+temp, cfg_base+1); break;
+	case 3: outb(0x18+temp, cfg_base+1); break;
+	default: ERROR(__FUNCTION__ "(), invalid dma");
+	}
+	
+	outb(2, cfg_base);      /* Mode Control Register (MCTL) */
+	outb(0x03, cfg_base+1); /* Enable device */
+
+	return 0;
+}
+
+/*
+ * Function nsc_ircc_probe_108 (chip, info)
+ *
+ *    
+ *
+ */
+static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info) 
+{
+	int cfg_base = info->cfg_base;
+	int reg;
+
+	/* Read address and interrupt control register (BAIC) */
+	outb(CFG_BAIC, cfg_base);
+	reg = inb(cfg_base+1);
+	
+	switch (reg & 0x03) {
+	case 0:
+		info->fir_base = 0x3e8;
+		break;
+	case 1:
+		info->fir_base = 0x2e8;
+		break;
+	case 2:
+		info->fir_base = 0x3f8;
+		break;
+	case 3:
+		info->fir_base = 0x2f8;
+		break;
+	}
+	info->sir_base = info->fir_base;
+	IRDA_DEBUG(2, __FUNCTION__ "(), probing fir_base=0x%03x\n", 
+		   info->fir_base);
+
+	/* Read control signals routing register (CSRT) */
+	outb(CFG_CSRT, cfg_base);
+	reg = inb(cfg_base+1);
+
+	switch (reg & 0x07) {
+	case 0:
+		info->irq = -1;
+		break;
+	case 1:
+		info->irq = 3;
+		break;
+	case 2:
+		info->irq = 4;
+		break;
+	case 3:
+		info->irq = 5;
+		break;
+	case 4:
+		info->irq = 7;
+		break;
+	case 5:
+		info->irq = 9;
+		break;
+	case 6:
+		info->irq = 11;
+		break;
+	case 7:
+		info->irq = 15;
+		break;
+	}
+	IRDA_DEBUG(2, __FUNCTION__ "(), probing irq=%d\n", info->irq);
+
+	/* Currently we only read Rx DMA but it will also be used for Tx */
+	switch ((reg >> 3) & 0x03) {
+	case 0:
+		info->dma = -1;
+		break;
+	case 1:
+		info->dma = 0;
+		break;
+	case 2:
+		info->dma = 1;
+		break;
+	case 3:
+		info->dma = 3;
+		break;
+	}
+	IRDA_DEBUG(2, __FUNCTION__ "(), probing dma=%d\n", info->dma);
+
+	/* Read mode control register (MCTL) */
+	outb(CFG_MCTL, cfg_base);
+	reg = inb(cfg_base+1);
+
+	info->enabled = reg & 0x01;
+	info->suspended = !((reg >> 1) & 0x01);
+
+	return 0;
+}
+
+/*
+ * Function nsc_ircc_init_338 (chip, info)
+ *
+ *    Initialize the NSC '338 chip. Remember that the 87338 needs two 
+ *    consecutive writes to the data registers while CPU interrupts are
+ *    disabled. The 97338 does not require this, but shouldn't be any
+ *    harm if we do it anyway.
+ */
+static int nsc_ircc_init_338(nsc_chip_t *chip, chipio_t *info) 
+{
+	/* No init yet */
+	
+	return 0;
+}
+
+/*
+ * Function nsc_ircc_probe_338 (chip, info)
+ *
+ *    
+ *
+ */
+static int nsc_ircc_probe_338(nsc_chip_t *chip, chipio_t *info) 
+{
+	int cfg_base = info->cfg_base;
+	int reg, com = 0;
+	int pnp;
+
+	/* Read funtion enable register (FER) */
+	outb(CFG_FER, cfg_base);
+	reg = inb(cfg_base+1);
+
+	info->enabled = (reg >> 2) & 0x01;
+
+	/* Check if we are in Legacy or PnP mode */
+	outb(CFG_PNP0, cfg_base);
+	reg = inb(cfg_base+1);
+	
+	pnp = (reg >> 4) & 0x01;
+	if (pnp) {
+		IRDA_DEBUG(2, "(), Chip is in PnP mode\n");
+		outb(0x46, cfg_base);
+		reg = (inb(cfg_base+1) & 0xfe) << 2;
+
+		outb(0x47, cfg_base);
+		reg |= ((inb(cfg_base+1) & 0xfc) << 8);
+
+		info->fir_base = reg;
+	} else {
+		/* Read function address register (FAR) */
+		outb(CFG_FAR, cfg_base);
+		reg = inb(cfg_base+1);
+		
+		switch ((reg >> 4) & 0x03) {
+		case 0:
+			info->fir_base = 0x3f8;
+			break;
+		case 1:
+			info->fir_base = 0x2f8;
+			break;
+		case 2:
+			com = 3;
+			break;
+		case 3:
+			com = 4;
+			break;
+		}
+		
+		if (com) {
+			switch ((reg >> 6) & 0x03) {
+			case 0:
+				if (com == 3)
+					info->fir_base = 0x3e8;
+				else
+					info->fir_base = 0x2e8;
+				break;
+			case 1:
+				if (com == 3)
+					info->fir_base = 0x338;
+				else
+					info->fir_base = 0x238;
+				break;
+			case 2:
+				if (com == 3)
+					info->fir_base = 0x2e8;
+				else
+					info->fir_base = 0x2e0;
+				break;
+			case 3:
+				if (com == 3)
+					info->fir_base = 0x220;
+				else
+					info->fir_base = 0x228;
+				break;
+			}
+		}
+	}
+	info->sir_base = info->fir_base;
+
+	/* Read PnP register 1 (PNP1) */
+	outb(CFG_PNP1, cfg_base);
+	reg = inb(cfg_base+1);
+	
+	info->irq = reg >> 4;
+	
+	/* Read PnP register 3 (PNP3) */
+	outb(CFG_PNP3, cfg_base);
+	reg = inb(cfg_base+1);
+
+	info->dma = (reg & 0x07) - 1;
+
+	/* Read power and test register (PTR) */
+	outb(CFG_PTR, cfg_base);
+	reg = inb(cfg_base+1);
+
+	info->suspended = reg & 0x01;
+
+	return 0;
+}
+
+/*
+ * Function nsc_ircc_setup (info)
+ *
+ *    Returns non-negative on success.
+ *
+ */
+static int nsc_ircc_setup(chipio_t *info)
+{
+	int version;
+	int iobase = info->fir_base;
+
+	/* Read the Module ID */
+	switch_bank(iobase, BANK3);
+	version = inb(iobase+MID);
+
+	/* Should be 0x2? */
+	if (0x20 != (version & 0xf0)) {
+		ERROR("%s, Wrong chip version %02x\n", driver_name, version);
+		return -1;
+	}
+	MESSAGE("%s, Found chip at base=0x%03x\n", driver_name, 
+		info->cfg_base);
+
+	/* Switch to advanced mode */
+	switch_bank(iobase, BANK2);
+	outb(ECR1_EXT_SL, iobase+ECR1);
+	switch_bank(iobase, BANK0);
+	
+	/* Set FIFO threshold to TX17, RX16, reset and enable FIFO's */
+	switch_bank(iobase, BANK0);	
+	outb(FCR_RXTH|FCR_TXTH|FCR_TXSR|FCR_RXSR|FCR_FIFO_EN, iobase+FCR);
+	
+	/* Set FIFO size to 32 */
+	switch_bank(iobase, BANK2);
+	outb(EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2);
+
+	/* IRCR2: FEND_MD is set */
+	switch_bank(iobase, BANK5);
+ 	outb(0x2a, iobase+4);
+
+	/* Make sure that some defaults are OK */
+	switch_bank(iobase, BANK6);
+	outb(0x20, iobase+0); /* Set 32 bits FIR CRC */
+	outb(0x0a, iobase+1); /* Set MIR pulse width */
+	outb(0x0d, iobase+2); /* Set SIR pulse width */
+	outb(0x2a, iobase+4); /* Set beginning frag, and preamble length */
+
+	MESSAGE("%s, driver loaded (Dag Brattli)\n", driver_name);
+
+	/* Enable receive interrupts */
+	switch_bank(iobase, BANK0);
+	outb(IER_RXHDL_IE, iobase+IER);
+
+	return 0;
+}
+
+/*
+ * Function nsc_ircc_read_dongle_id (void)
+ *
+ * Try to read dongle indentification. This procedure needs to be executed
+ * once after power-on/reset. It also needs to be used whenever you suspect
+ * that the user may have plugged/unplugged the IrDA Dongle.
+ */
+static int nsc_ircc_read_dongle_id (int iobase)
+{
+	int dongle_id;
+	__u8 bank;
+
+	bank = inb(iobase+BSR);
+
+	/* Select Bank 7 */
+	switch_bank(iobase, BANK7);
+	
+	/* IRCFG4: IRSL0_DS and IRSL21_DS are cleared */
+	outb(0x00, iobase+7);
+	
+	/* ID0, 1, and 2 are pulled up/down very slowly */
+	udelay(50);
+	
+	/* IRCFG1: read the ID bits */
+	dongle_id = inb(iobase+4) & 0x0f;
+
+#ifdef BROKEN_DONGLE_ID
+	if (dongle_id == 0x0a)
+		dongle_id = 0x09;
+#endif	
+	/* Go back to  bank 0 before returning */
+	switch_bank(iobase, BANK0);
+
+	outb(bank, iobase+BSR);
+
+	return dongle_id;
+}
+
+/*
+ * Function nsc_ircc_init_dongle_interface (iobase, dongle_id)
+ *
+ *     This function initializes the dongle for the transceiver that is
+ *     used. This procedure needs to be executed once after
+ *     power-on/reset. It also needs to be used whenever you suspect that
+ *     the dongle is changed. 
+ */
+static void nsc_ircc_init_dongle_interface (int iobase, int dongle_id)
+{
+	int bank;
+
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+
+	/* Select Bank 7 */
+	switch_bank(iobase, BANK7);
+	
+	/* IRCFG4: set according to dongle_id */
+	switch (dongle_id) {
+	case 0x00: /* same as */
+	case 0x01: /* Differential serial interface */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x02: /* same as */
+	case 0x03: /* Reserved */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x04: /* Sharp RY5HD01 */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x05: /* Reserved, but this is what the Thinkpad reports */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x06: /* Single-ended serial interface */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x07: /* Consumer-IR only */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s\n",
+			   dongle_types[dongle_id]);
+		break;
+	case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */
+		outb(0x28, iobase+7); /* Set irsl[0-2] as output */
+		break;
+	case 0x0A: /* same as */
+	case 0x0B: /* Reserved */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x0C: /* same as */
+	case 0x0D: /* HP HSDL-1100/HSDL-2100 */
+		/* 
+		 * Set irsl0 as input, irsl[1-2] as output, and separate 
+		 * inputs are used for SIR and MIR/FIR 
+		 */
+		outb(0x48, iobase+7); 
+		break;
+	case 0x0E: /* Supports SIR Mode only */
+		outb(0x28, iobase+7); /* Set irsl[0-2] as output */
+		break;
+	case 0x0F: /* No dongle connected */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s\n",
+			   dongle_types[dongle_id]); 
+
+		switch_bank(iobase, BANK0);
+		outb(0x62, iobase+MCR);
+		break;
+	default: 
+		IRDA_DEBUG(0, __FUNCTION__ "(), invalid dongle_id %#x", 
+			   dongle_id);
+	}
+	
+	/* IRCFG1: IRSL1 and 2 are set to IrDA mode */
+	outb(0x00, iobase+4);
+
+	/* Restore bank register */
+	outb(bank, iobase+BSR);
+	
+} /* set_up_dongle_interface */
+
+/*
+ * Function nsc_ircc_change_dongle_speed (iobase, speed, dongle_id)
+ *
+ *    Change speed of the attach dongle
+ *
+ */
+static void nsc_ircc_change_dongle_speed(int iobase, int speed, int dongle_id)
+{
+	unsigned long flags;
+	__u8 bank;
+
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+
+	/* Select Bank 7 */
+	switch_bank(iobase, BANK7);
+	
+	/* IRCFG1: set according to dongle_id */
+	switch (dongle_id) {
+	case 0x00: /* same as */
+	case 0x01: /* Differential serial interface */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x02: /* same as */
+	case 0x03: /* Reserved */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x04: /* Sharp RY5HD01 */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
+			   dongle_types[dongle_id]); 
+	case 0x05: /* Reserved */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x06: /* Single-ended serial interface */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x07: /* Consumer-IR only */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s\n", 
+			   dongle_types[dongle_id]); 
+		outb(0x00, iobase+4);
+		if (speed > 115200)
+			outb(0x01, iobase+4);
+		break;
+	case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */
+		outb(0x01, iobase+4);
+
+		if (speed == 4000000) {
+			save_flags(flags);
+			cli();
+			outb(0x81, iobase+4);
+			outb(0x80, iobase+4);
+			restore_flags(flags);
+		} else
+			outb(0x00, iobase+4);
+		break;
+	case 0x0A: /* same as */
+	case 0x0B: /* Reserved */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x0C: /* same as */
+	case 0x0D: /* HP HSDL-1100/HSDL-2100 */
+		break;
+	case 0x0E: /* Supports SIR Mode only */
+		break;
+	case 0x0F: /* No dongle connected */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n",
+			   dongle_types[dongle_id]);
+
+		switch_bank(iobase, BANK0); 
+		outb(0x62, iobase+MCR);
+		break;
+	default: 
+		IRDA_DEBUG(0, __FUNCTION__ "(), invalid data_rate\n");
+	}
+	/* Restore bank register */
+	outb(bank, iobase+BSR);
+}
+
+/*
+ * Function nsc_ircc_change_speed (self, baud)
+ *
+ *    Change the speed of the device
+ *
+ */
+static void nsc_ircc_change_speed(struct nsc_ircc_cb *self, __u32 speed)
+{
+	struct device *dev = self->netdev;
+	__u8 mcr = MCR_SIR;
+	int iobase; 
+	__u8 bank;
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), speed=%d\n", speed);
+
+	ASSERT(self != NULL, return;);
+
+	iobase = self->io.fir_base;
+
+	/* Update accounting for new speed */
+	self->io.speed = speed;
+
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+
+	/* Disable interrupts */
+	switch_bank(iobase, BANK0);
+	outb(0, iobase+IER);
+
+	/* Select Bank 2 */
+	switch_bank(iobase, BANK2);
+
+	outb(0x00, iobase+BGDH);
+	switch (speed) {
+	case 9600:   outb(0x0c, iobase+BGDL); break;
+	case 19200:  outb(0x06, iobase+BGDL); break;
+	case 38400:  outb(0x03, iobase+BGDL); break;
+	case 57600:  outb(0x02, iobase+BGDL); break;
+	case 115200: outb(0x01, iobase+BGDL); break;
+	case 576000:
+		switch_bank(iobase, BANK5);
+		
+		/* IRCR2: MDRS is set */
+		outb(inb(iobase+4) | 0x04, iobase+4);
+	       
+		mcr = MCR_MIR;
+		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
+		break;
+	case 1152000:
+		mcr = MCR_MIR;
+		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
+		break;
+	case 4000000:
+		mcr = MCR_FIR;
+		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
+		break;
+	default:
+		mcr = MCR_FIR;
+		IRDA_DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", 
+			   speed);
+		break;
+	}
+
+	/* Set appropriate speed mode */
+	switch_bank(iobase, BANK0);
+	outb(mcr | MCR_TX_DFR, iobase+MCR);
+
+	/* Give some hits to the transceiver */
+	nsc_ircc_change_dongle_speed(iobase, speed, self->io.dongle_id);
+
+	/* Set FIFO threshold to TX17, RX16 */
+	switch_bank(iobase, BANK0);
+	outb(0x00, iobase+FCR);
+	outb(FCR_FIFO_EN, iobase+FCR);
+	outb(FCR_RXTH|     /* Set Rx FIFO threshold */
+	     FCR_TXTH|     /* Set Tx FIFO threshold */
+	     FCR_TXSR|     /* Reset Tx FIFO */
+	     FCR_RXSR|     /* Reset Rx FIFO */
+	     FCR_FIFO_EN,  /* Enable FIFOs */
+	     iobase+FCR);
+	
+	/* Set FIFO size to 32 */
+	switch_bank(iobase, BANK2);
+	outb(EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2);
+	
+	self->netdev->tbusy = 0;
+	
+	/* Enable some interrupts so we can receive frames */
+	switch_bank(iobase, BANK0); 
+	if (speed > 115200) {
+		/* Install FIR xmit handler */
+		dev->hard_start_xmit = nsc_ircc_hard_xmit_fir;
+		outb(IER_SFIF_IE, iobase+IER);
+		nsc_ircc_dma_receive(self);
+	} else {
+		/* Install SIR xmit handler */
+		dev->hard_start_xmit = nsc_ircc_hard_xmit_sir;
+		outb(IER_RXHDL_IE, iobase+IER);
+	}
+    	
+	/* Restore BSR */
+	outb(bank, iobase+BSR);
+}
+
+/*
+ * Function nsc_ircc_hard_xmit (skb, dev)
+ *
+ *    Transmit the frame!
+ *
+ */
+static int nsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct device *dev)
+{
+	struct nsc_ircc_cb *self;
+	unsigned long flags;
+	int iobase;
+	__u32 speed;
+	__u8 bank;
+	
+	self = (struct nsc_ircc_cb *) dev->priv;
+
+	ASSERT(self != NULL, return 0;);
+
+	iobase = self->io.fir_base;
+
+	/* Lock transmit buffer */
+	if (irda_lock((void *) &dev->tbusy) == FALSE)
+		return -EBUSY;
+	
+	/* Check if we need to change the speed */
+	if ((speed = irda_get_speed(skb)) != self->io.speed)
+		self->new_speed = speed;
+	
+	spin_lock_irqsave(&self->lock, flags);
+	
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+	
+	self->tx_buff.data = self->tx_buff.head;
+	
+	self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, 
+					   self->tx_buff.truesize);
+
+	self->stats.tx_bytes += self->tx_buff.len;
+	
+	/* Add interrupt on tx low level (will fire immediately) */
+	switch_bank(iobase, BANK0);
+	outb(IER_TXLDL_IE, iobase+IER);
+	
+	/* Restore bank register */
+	outb(bank, iobase+BSR);
+
+	spin_unlock_irqrestore(&self->lock, flags);
+
+	dev_kfree_skb(skb);
+
+	return 0;
+}
+
+static int nsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct device *dev)
+{
+	struct nsc_ircc_cb *self;
+	unsigned long flags;
+	int iobase;
+	__u32 speed;
+	__u8 bank;
+	int mtt, diff;
+	
+	self = (struct nsc_ircc_cb *) dev->priv;
+	iobase = self->io.fir_base;
+
+	/* Lock transmit buffer */
+	if (irda_lock((void *) &dev->tbusy) == FALSE)
+		return -EBUSY;
+
+	/* Check if we need to change the speed */
+	if ((speed = irda_get_speed(skb)) != self->io.speed)
+		self->new_speed = speed;
+
+	spin_lock_irqsave(&self->lock, flags);
+
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+
+	/* Register and copy this frame to DMA memory */
+	self->tx_fifo.queue[self->tx_fifo.free].start = self->tx_fifo.tail;
+	self->tx_fifo.queue[self->tx_fifo.free].len = skb->len;
+	self->tx_fifo.tail += skb->len;
+
+	self->stats.tx_bytes += skb->len;
+
+	memcpy(self->tx_fifo.queue[self->tx_fifo.free].start, skb->data, 
+	       skb->len);
+	
+	self->tx_fifo.len++;
+	self->tx_fifo.free++;
+
+	/* Start transmit only if there is currently no transmit going on */
+	if (self->tx_fifo.len == 1) {
+		/* Check if we must wait the min turn time or not */
+		mtt = irda_get_mtt(skb);
+		if (mtt) {
+			/* Check how much time we have used already */
+			get_fast_time(&self->now);
+			diff = self->now.tv_usec - self->stamp.tv_usec;
+			if (diff < 0) 
+				diff += 1000000;
+			
+			/* Check if the mtt is larger than the time we have
+			 * already used by all the protocol processing
+			 */
+			if (mtt > diff) {
+				mtt -= diff;
+
+				/* 
+				 * Use timer if delay larger than 125 us, and
+				 * use udelay for smaller values which should
+				 * be acceptable
+				 */
+				if (mtt > 125) {
+					/* Adjust for timer resolution */
+					mtt = mtt / 125;
+					
+					/* Setup timer */
+					switch_bank(iobase, BANK4);
+					outb(mtt & 0xff, iobase+TMRL);
+					outb((mtt >> 8) & 0x0f, iobase+TMRH);
+					
+					/* Start timer */
+					outb(IRCR1_TMR_EN, iobase+IRCR1);
+					self->io.direction = IO_XMIT;
+					
+					/* Enable timer interrupt */
+					switch_bank(iobase, BANK0);
+					outb(IER_TMR_IE, iobase+IER);
+					
+					/* Timer will take care of the rest */
+					goto out; 
+				} else
+					udelay(mtt);
+			}
+		}		
+		/* Enable DMA interrupt */
+		switch_bank(iobase, BANK0);
+		outb(IER_DMA_IE, iobase+IER);
+
+		/* Transmit frame */
+		nsc_ircc_dma_xmit(self, iobase);
+	}
+ out:
+	/* Not busy transmitting anymore if window is not full */
+	if (self->tx_fifo.free < MAX_TX_WINDOW)
+		dev->tbusy = 0;
+
+	/* Restore bank register */
+	outb(bank, iobase+BSR);
+
+	spin_unlock_irqrestore(&self->lock, flags);
+	dev_kfree_skb(skb);
+
+	return 0;
+}
+
+/*
+ * Function nsc_ircc_dma_xmit (self, iobase)
+ *
+ *    Transmit data using DMA
+ *
+ */
+static void nsc_ircc_dma_xmit(struct nsc_ircc_cb *self, int iobase)
+{
+	int bsr;
+
+	/* Save current bank */
+	bsr = inb(iobase+BSR);
+
+	/* Disable DMA */
+	switch_bank(iobase, BANK0);
+	outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
+	
+	self->io.direction = IO_XMIT;
+	
+	/* Choose transmit DMA channel  */ 
+	switch_bank(iobase, BANK2);
+	outb(ECR1_DMASWP|ECR1_DMANF|ECR1_EXT_SL, iobase+ECR1);
+	
+	setup_dma(self->io.dma, 
+		  self->tx_fifo.queue[self->tx_fifo.ptr].start, 
+		  self->tx_fifo.queue[self->tx_fifo.ptr].len, 
+		  DMA_TX_MODE);
+
+	/* Enable DMA and SIR interaction pulse */
+ 	switch_bank(iobase, BANK0);	
+	outb(inb(iobase+MCR)|MCR_TX_DFR|MCR_DMA_EN|MCR_IR_PLS, iobase+MCR);
+
+	/* Restore bank register */
+	outb(bsr, iobase+BSR);
+}
+
+/*
+ * Function nsc_ircc_pio_xmit (self, iobase)
+ *
+ *    Transmit data using PIO. Returns the number of bytes that actually
+ *    got transfered
+ *
+ */
+static int nsc_ircc_pio_write(int iobase, __u8 *buf, int len, int fifo_size)
+{
+	int actual = 0;
+	__u8 bank;
+	
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+
+	switch_bank(iobase, BANK0);
+	if (!(inb_p(iobase+LSR) & LSR_TXEMP)) {
+		IRDA_DEBUG(4, __FUNCTION__ 
+			   "(), warning, FIFO not empty yet!\n");
+
+		/* FIFO may still be filled to the Tx interrupt threshold */
+		fifo_size -= 17;
+	}
+
+	/* Fill FIFO with current frame */
+	while ((fifo_size-- > 0) && (actual < len)) {
+		/* Transmit next byte */
+		outb(buf[actual++], iobase+TXD);
+	}
+        
+	IRDA_DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", 
+		   fifo_size, actual, len);
+	
+	/* Restore bank */
+	outb(bank, iobase+BSR);
+
+	return actual;
+}
+
+/*
+ * Function nsc_ircc_dma_xmit_complete (self)
+ *
+ *    The transfer of a frame in finished. This function will only be called 
+ *    by the interrupt handler
+ *
+ */
+static int nsc_ircc_dma_xmit_complete(struct nsc_ircc_cb *self)
+{
+	int iobase;
+	__u8 bank;
+	int ret = TRUE;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	iobase = self->io.fir_base;
+
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+
+	/* Disable DMA */
+	switch_bank(iobase, BANK0);
+        outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
+	
+	/* Check for underrrun! */
+	if (inb(iobase+ASCR) & ASCR_TXUR) {
+		self->stats.tx_errors++;
+		self->stats.tx_fifo_errors++;
+		
+		/* Clear bit, by writing 1 into it */
+		outb(ASCR_TXUR, iobase+ASCR);
+	} else {
+		self->stats.tx_packets++;
+	}
+
+	/* Check if we need to change the speed */
+	if (self->new_speed) {
+		nsc_ircc_change_speed(self, self->new_speed);
+		self->new_speed = 0;
+	}
+
+	/* Finished with this frame, so prepare for next */
+	self->tx_fifo.ptr++;
+	self->tx_fifo.len--;
+
+	/* Any frames to be sent back-to-back? */
+	if (self->tx_fifo.len) {
+		nsc_ircc_dma_xmit(self, iobase);
+		
+		/* Not finished yet! */
+		ret = FALSE;
+	} else {
+		/* Reset Tx FIFO info */
+		self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0;
+		self->tx_fifo.tail = self->tx_buff.head;
+	}
+
+	/* Make sure we have room for more frames */
+	if (self->tx_fifo.free < MAX_TX_WINDOW) {
+		/* Not busy transmitting anymore */
+		self->netdev->tbusy = 0;
+
+		/* Tell the network layer, that we can accept more frames */
+		mark_bh(NET_BH);
+	}
+
+	/* Restore bank */
+	outb(bank, iobase+BSR);
+	
+	return ret;
+}
+
+/*
+ * Function nsc_ircc_dma_receive (self)
+ *
+ *    Get ready for receiving a frame. The device will initiate a DMA
+ *    if it starts to receive a frame.
+ *
+ */
+static int nsc_ircc_dma_receive(struct nsc_ircc_cb *self) 
+{
+	int iobase;
+	__u8 bsr;
+
+	iobase = self->io.fir_base;
+
+	/* Reset Tx FIFO info */
+	self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0;
+	self->tx_fifo.tail = self->tx_buff.head;
+
+	/* Save current bank */
+	bsr = inb(iobase+BSR);
+
+	/* Disable DMA */
+	switch_bank(iobase, BANK0);
+	outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
+
+	/* Choose DMA Rx, DMA Fairness, and Advanced mode */
+	switch_bank(iobase, BANK2);
+	outb(ECR1_DMANF|ECR1_EXT_SL, iobase+ECR1);
+
+	self->io.direction = IO_RECV;
+	self->rx_buff.data = self->rx_buff.head;
+	
+	/* Reset Rx FIFO. This will also flush the ST_FIFO */
+	switch_bank(iobase, BANK0);
+	outb(FCR_RXSR|FCR_FIFO_EN, iobase+FCR);
+
+	self->st_fifo.len = self->st_fifo.pending_bytes = 0;
+	self->st_fifo.tail = self->st_fifo.head = 0;
+	
+	setup_dma(self->io.dma, self->rx_buff.data, self->rx_buff.truesize, 
+		  DMA_RX_MODE);
+
+	/* Enable DMA */
+	switch_bank(iobase, BANK0);
+	outb(inb(iobase+MCR)|MCR_DMA_EN, iobase+MCR);
+
+	/* Restore bank register */
+	outb(bsr, iobase+BSR);
+	
+	return 0;
+}
+
+/*
+ * Function nsc_ircc_dma_receive_complete (self)
+ *
+ *    Finished with receiving frames
+ *
+ *    
+ */
+static int nsc_ircc_dma_receive_complete(struct nsc_ircc_cb *self, int iobase)
+{
+	struct st_fifo *st_fifo;
+	struct sk_buff *skb;
+	__u8 status;
+	__u8 bank;
+	int len;
+
+	st_fifo = &self->st_fifo;
+
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+	
+	/* Read all entries in status FIFO */
+	switch_bank(iobase, BANK5);
+	while ((status = inb(iobase+FRM_ST)) & FRM_ST_VLD) {
+		/* We must empty the status FIFO no matter what */
+		len = inb(iobase+RFLFL) | ((inb(iobase+RFLFH) & 0x1f) << 8);
+
+		if (st_fifo->tail >= MAX_RX_WINDOW)
+			continue;
+			
+		st_fifo->entries[st_fifo->tail].status = status;
+		st_fifo->entries[st_fifo->tail].len = len;
+		st_fifo->pending_bytes += len;
+		st_fifo->tail++;
+		st_fifo->len++;
+	}
+	/* Try to process all entries in status FIFO */
+	while (st_fifo->len > 0) {
+		/* Get first entry */
+		status = st_fifo->entries[st_fifo->head].status;
+		len    = st_fifo->entries[st_fifo->head].len;
+		st_fifo->pending_bytes -= len;
+		st_fifo->head++;
+		st_fifo->len--;
+
+		/* Check for errors */
+		if (status & FRM_ST_ERR_MSK) {
+			if (status & FRM_ST_LOST_FR) {
+				/* Add number of lost frames to stats */
+				self->stats.rx_errors += len;	
+			} else {
+				/* Skip frame */
+				self->stats.rx_errors++;
+				
+				self->rx_buff.data += len;
+			
+				if (status & FRM_ST_MAX_LEN)
+					self->stats.rx_length_errors++;
+				
+				if (status & FRM_ST_PHY_ERR) 
+					self->stats.rx_frame_errors++;
+				
+				if (status & FRM_ST_BAD_CRC) 
+					self->stats.rx_crc_errors++;
+			}
+			/* The errors below can be reported in both cases */
+			if (status & FRM_ST_OVR1)
+				self->stats.rx_fifo_errors++;		       
+			
+			if (status & FRM_ST_OVR2)
+				self->stats.rx_fifo_errors++;
+		} else {
+			/*  
+			 * First we must make sure that the frame we
+			 * want to deliver is all in main memory. If we
+			 * cannot tell, then we check if the Rx FIFO is
+			 * empty. If not then we will have to take a nap
+			 * and try again later.  
+			 */
+			if (st_fifo->pending_bytes < self->io.fifo_size) {
+				switch_bank(iobase, BANK0);
+				if (inb(iobase+LSR) & LSR_RXDA) {
+					/* Put this entry back in fifo */
+					st_fifo->head--;
+					st_fifo->len++;
+					st_fifo->pending_bytes += len;
+					st_fifo->entries[st_fifo->head].status = status;
+					st_fifo->entries[st_fifo->head].len = len;
+				
+					/* Restore bank register */
+					outb(bank, iobase+BSR);
+					
+					return FALSE; /* I'll be back! */
+				}
+			}
+
+			/* 
+			 * Remember the time we received this frame, so we can
+			 * reduce the min turn time a bit since we will know
+			 * how much time we have used for protocol processing
+			 */
+			get_fast_time(&self->stamp);
+
+			skb = dev_alloc_skb(len+1);
+			if (skb == NULL)  {
+				WARNING(__FUNCTION__ "(), memory squeeze, "
+					"dropping frame.\n");
+				self->stats.rx_dropped++;
+
+				/* Restore bank register */
+				outb(bank, iobase+BSR);
+
+				return FALSE;
+			}
+			
+			/* Make sure IP header gets aligned */
+			skb_reserve(skb, 1); 
+
+			/* Copy frame without CRC */
+			if (self->io.speed < 4000000) {
+				skb_put(skb, len-2);
+				memcpy(skb->data, self->rx_buff.data, len-2);
+			} else {
+				skb_put(skb, len-4);
+				memcpy(skb->data, self->rx_buff.data, len-4);
+			}
+
+			/* Move to next frame */
+			self->rx_buff.data += len;
+			self->stats.rx_bytes += len;
+			self->stats.rx_packets++;
+
+			skb->dev = self->netdev;
+			skb->mac.raw  = skb->data;
+			skb->protocol = htons(ETH_P_IRDA);
+			netif_rx(skb);
+		}
+	}
+	/* Restore bank register */
+	outb(bank, iobase+BSR);
+
+	return TRUE;
+}
+
+/*
+ * Function nsc_ircc_pio_receive (self)
+ *
+ *    Receive all data in receiver FIFO
+ *
+ */
+static void nsc_ircc_pio_receive(struct nsc_ircc_cb *self) 
+{
+	__u8 byte;
+	int iobase;
+
+	iobase = self->io.fir_base;
+	
+	/*  Receive all characters in Rx FIFO */
+	do {
+		byte = inb(iobase+RXD);
+		async_unwrap_char(self->netdev, &self->stats, &self->rx_buff, 
+				  byte);
+	} while (inb(iobase+LSR) & LSR_RXDA); /* Data available */	
+}
+
+/*
+ * Function nsc_ircc_sir_interrupt (self, eir)
+ *
+ *    Handle SIR interrupt
+ *
+ */
+static void nsc_ircc_sir_interrupt(struct nsc_ircc_cb *self, int eir)
+{
+	int actual;
+
+	/* Check if transmit FIFO is low on data */
+	if (eir & EIR_TXLDL_EV) {
+		/* Write data left in transmit buffer */
+		actual = nsc_ircc_pio_write(self->io.fir_base, 
+					   self->tx_buff.data, 
+					   self->tx_buff.len, 
+					   self->io.fifo_size);
+		self->tx_buff.data += actual;
+		self->tx_buff.len  -= actual;
+		
+		self->io.direction = IO_XMIT;
+
+		/* Check if finished */
+		if (self->tx_buff.len > 0)
+			self->ier = IER_TXLDL_IE;
+		else { 
+			self->netdev->tbusy = 0; /* Unlock */
+			self->stats.tx_packets++;
+			
+		        mark_bh(NET_BH);	
+
+			self->ier = IER_TXEMP_IE;
+		}
+			
+	}
+	/* Check if transmission has completed */
+	if (eir & EIR_TXEMP_EV) {
+		/* Check if we need to change the speed? */
+		if (self->new_speed) {
+			IRDA_DEBUG(2, __FUNCTION__ "(), Changing speed!\n");
+			nsc_ircc_change_speed(self, self->new_speed);
+			self->new_speed = 0;
+
+			/* Check if we are going to FIR */
+			if (self->io.speed > 115200) {
+				/* Should wait for status FIFO interrupt */
+				self->ier = IER_SFIF_IE;
+
+				/* No need to do anymore SIR stuff */
+				return;
+			}
+		}
+		/* Turn around and get ready to receive some data */
+		self->io.direction = IO_RECV;
+		self->ier = IER_RXHDL_IE;
+	}
+
+	/* Rx FIFO threshold or timeout */
+	if (eir & EIR_RXHDL_EV) {
+		nsc_ircc_pio_receive(self);
+
+		/* Keep receiving */
+		self->ier = IER_RXHDL_IE;
+	}
+}
+
+/*
+ * Function nsc_ircc_fir_interrupt (self, eir)
+ *
+ *    Handle MIR/FIR interrupt
+ *
+ */
+static void nsc_ircc_fir_interrupt(struct nsc_ircc_cb *self, int iobase, 
+				   int eir)
+{
+	__u8 bank;
+
+	bank = inb(iobase+BSR);
+	
+	/* Status FIFO event*/
+	if (eir & EIR_SFIF_EV) {
+		if (nsc_ircc_dma_receive_complete(self, iobase)) {
+			/* Wait for next status FIFO interrupt */
+			self->ier = IER_SFIF_IE;
+		} else {
+			/* 
+			 * DMA not finished yet, so try again later, set 
+			 * timer value, resolution 125 us 
+			 */
+			switch_bank(iobase, BANK4);
+			outb(0x02, iobase+TMRL); /* 2 * 125 us */
+			outb(0x00, iobase+TMRH);
+
+			/* Start timer */
+			outb(IRCR1_TMR_EN, iobase+IRCR1);
+			self->ier = IER_TMR_IE | IER_SFIF_IE;
+		}
+	} else if (eir & EIR_TMR_EV) { /* Timer finished */
+		/* Disable timer */
+		switch_bank(iobase, BANK4);
+		outb(0, iobase+IRCR1);
+
+		/* Clear timer event */
+		switch_bank(iobase, BANK0);
+		outb(ASCR_CTE, iobase+ASCR);
+
+		/* Check if this is a Tx timer interrupt */
+		if (self->io.direction == IO_XMIT) {
+			nsc_ircc_dma_xmit(self, iobase);
+
+			/*  Interrupt on DMA */
+			self->ier = IER_DMA_IE;
+		} else {
+			/* Check if DMA has now finished */
+			nsc_ircc_dma_receive_complete(self, iobase);
+
+			self->ier = IER_SFIF_IE;
+		}
+	} else if (eir & EIR_DMA_EV) { 
+		/* Finished with all transmissions? */
+		if (nsc_ircc_dma_xmit_complete(self)) {		
+			/* Check if there are more frames to be transmitted */
+			if (irda_device_txqueue_empty(self->netdev)) {
+				/* Prepare for receive */
+				nsc_ircc_dma_receive(self);
+			
+				self->ier = IER_SFIF_IE;
+			}
+		} else {
+			/*  Not finished yet, so interrupt on DMA again */
+			self->ier = IER_DMA_IE;
+		}
+	}
+	outb(bank, iobase+BSR);
+}
+
+/*
+ * Function nsc_ircc_interrupt (irq, dev_id, regs)
+ *
+ *    An interrupt from the chip has arrived. Time to do some work
+ *
+ */
+static void nsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct device *dev = (struct device *) dev_id;
+	struct nsc_ircc_cb *self;
+	__u8 bsr, eir;
+	int iobase;
+
+	if (!dev) {
+		WARNING("%s: irq %d for unknown device.\n", driver_name, irq);
+		return;
+	}
+	self = (struct nsc_ircc_cb *) dev->priv;
+
+	spin_lock(&self->lock);	
+	dev->interrupt = 1;
+
+	iobase = self->io.fir_base;
+
+	bsr = inb(iobase+BSR); 	/* Save current bank */
+
+	switch_bank(iobase, BANK0);	
+	self->ier = inb(iobase+IER); 
+	eir = inb(iobase+EIR) & self->ier; /* Mask out the interesting ones */ 
+
+	outb(0, iobase+IER); /* Disable interrupts */
+	
+	if (eir) {
+		/* Dispatch interrupt handler for the current speed */
+		if (self->io.speed > 115200)
+			nsc_ircc_fir_interrupt(self, iobase, eir);
+		else
+			nsc_ircc_sir_interrupt(self, eir);
+	}
+	
+	outb(self->ier, iobase+IER); /* Restore interrupts */
+	outb(bsr, iobase+BSR);       /* Restore bank register */
+
+	dev->interrupt = 0;
+	spin_unlock(&self->lock);
+}
+
+/*
+ * Function nsc_ircc_is_receiving (self)
+ *
+ *    Return TRUE is we are currently receiving a frame
+ *
+ */
+static int nsc_ircc_is_receiving(struct nsc_ircc_cb *self)
+{
+	unsigned long flags;
+	int status = FALSE;
+	int iobase;
+	__u8 bank;
+
+	ASSERT(self != NULL, return FALSE;);
+
+	spin_lock_irqsave(&self->lock, flags);
+
+	if (self->io.speed > 115200) {
+		iobase = self->io.fir_base;
+
+		/* Check if rx FIFO is not empty */
+		bank = inb(iobase+BSR);
+		switch_bank(iobase, BANK2);
+		if ((inb(iobase+RXFLV) & 0x3f) != 0) {
+			/* We are receiving something */
+			status =  TRUE;
+		}
+		outb(bank, iobase+BSR);
+	} else 
+		status = (self->rx_buff.state != OUTSIDE_FRAME);
+	
+	spin_unlock_irqrestore(&self->lock, flags);
+
+	return status;
+}
+
+/*
+ * Function nsc_ircc_net_init (dev)
+ *
+ *    Initialize network device
+ *
+ */
+static int nsc_ircc_net_init(struct device *dev)
+{
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+	/* Setup to be a normal IrDA network device driver */
+	irda_device_setup(dev);
+
+	/* Insert overrides below this line! */
+
+	return 0;
+}
+
+/*
+ * Function nsc_ircc_net_open (dev)
+ *
+ *    Start the device
+ *
+ */
+static int nsc_ircc_net_open(struct device *dev)
+{
+	struct nsc_ircc_cb *self;
+	int iobase;
+	__u8 bank;
+	
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+	
+	ASSERT(dev != NULL, return -1;);
+	self = (struct nsc_ircc_cb *) dev->priv;
+	
+	ASSERT(self != NULL, return 0;);
+	
+	iobase = self->io.fir_base;
+	
+	if (request_irq(self->io.irq, nsc_ircc_interrupt, 0, dev->name, dev)) {
+		WARNING("%s, unable to allocate irq=%d\n", driver_name, 
+			self->io.irq);
+		return -EAGAIN;
+	}
+	/*
+	 * Always allocate the DMA channel after the IRQ, and clean up on 
+	 * failure.
+	 */
+	if (request_dma(self->io.dma, dev->name)) {
+		WARNING("%s, unable to allocate dma=%d\n", driver_name, 
+			self->io.dma);
+		free_irq(self->io.irq, self);
+		return -EAGAIN;
+	}
+	
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+	
+	/* turn on interrupts */
+	switch_bank(iobase, BANK0);
+	outb(IER_LS_IE | IER_RXHDL_IE, iobase+IER);
+
+	/* Restore bank register */
+	outb(bank, iobase+BSR);
+
+	/* Ready to play! */
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	dev->start = 1;
+
+	/* 
+	 * Open new IrLAP layer instance, now that everything should be
+	 * initialized properly 
+	 */
+	self->irlap = irlap_open(dev, &self->qos);
+
+	MOD_INC_USE_COUNT;
+
+	return 0;
+}
+
+/*
+ * Function nsc_ircc_net_close (dev)
+ *
+ *    Stop the device
+ *
+ */
+static int nsc_ircc_net_close(struct device *dev)
+{
+	struct nsc_ircc_cb *self;
+	int iobase;
+	__u8 bank;
+
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+	
+	ASSERT(dev != NULL, return -1;);
+
+	self = (struct nsc_ircc_cb *) dev->priv;
+	ASSERT(self != NULL, return 0;);
+
+	/* Stop device */
+	dev->tbusy = 1;
+	dev->start = 0;
+
+	/* Stop and remove instance of IrLAP */
+	if (self->irlap)
+		irlap_close(self->irlap);
+	self->irlap = NULL;
+	
+	iobase = self->io.fir_base;
+
+	disable_dma(self->io.dma);
+
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+
+	/* Disable interrupts */
+	switch_bank(iobase, BANK0);
+	outb(0, iobase+IER); 
+       
+	free_irq(self->io.irq, dev);
+	free_dma(self->io.dma);
+
+	/* Restore bank register */
+	outb(bank, iobase+BSR);
+
+	MOD_DEC_USE_COUNT;
+
+	return 0;
+}
+
+/*
+ * Function nsc_ircc_net_ioctl (dev, rq, cmd)
+ *
+ *    Process IOCTL commands for this device
+ *
+ */
+static int nsc_ircc_net_ioctl(struct device *dev, struct ifreq *rq, int cmd)
+{
+	struct if_irda_req *irq = (struct if_irda_req *) rq;
+	struct nsc_ircc_cb *self;
+	unsigned long flags;
+	int ret = 0;
+
+	ASSERT(dev != NULL, return -1;);
+
+	self = dev->priv;
+
+	ASSERT(self != NULL, return -1;);
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
+	
+	/* Disable interrupts & save flags */
+	save_flags(flags);
+	cli();
+	
+	switch (cmd) {
+	case SIOCSBANDWIDTH: /* Set bandwidth */
+		nsc_ircc_change_speed(self, irq->ifr_baudrate);
+		break;
+	case SIOCSMEDIABUSY: /* Set media busy */
+		irda_device_set_media_busy(self->netdev, TRUE);
+		break;
+	case SIOCGRECEIVING: /* Check if we are receiving right now */
+		irq->ifr_receiving = nsc_ircc_is_receiving(self);
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+	}
+	
+	restore_flags(flags);
+	
+	return ret;
+}
+
+static struct net_device_stats *nsc_ircc_net_get_stats(struct device *dev)
+{
+	struct nsc_ircc_cb *self = (struct nsc_ircc_cb *) dev->priv;
+	
+	return &self->stats;
+}
+
+#ifdef CONFIG_APM
+static void nsc_ircc_suspend(struct nsc_ircc_cb *self)
+{
+	MESSAGE("%s, Suspending\n", driver_name);
+
+	if (self->io.suspended)
+		return;
+
+	nsc_ircc_net_close(self->netdev);
+
+	self->io.suspended = 1;
+}
+
+static void nsc_ircc_wakeup(struct nsc_ircc_cb *self)
+{
+	struct device *dev = self->netdev;
+	int iobase;
+
+	if (!self->io.suspended)
+		return;
+
+	iobase = self->io.fir_base;
+
+	/* Switch to advanced mode */
+	switch_bank(iobase, BANK2);
+	outb(ECR1_EXT_SL, iobase+ECR1);
+	switch_bank(iobase, BANK0);
+
+	nsc_ircc_net_open(self->netdev);
+	
+	MESSAGE("%s, Waking up\n", driver_name);
+
+	self->io.suspended = 0;
+}
+
+static int nsc_ircc_apmproc(apm_event_t event)
+{
+	static int down = 0; /* Filter out double events */
+	int i;
+
+	switch (event) {
+	case APM_SYS_SUSPEND:
+	case APM_USER_SUSPEND:
+		if (!down) {			
+			for (i=0; i<4; i++) {
+				if (dev_self[i])
+					nsc_ircc_suspend(dev_self[i]);
+			}
+		}
+		down = 1;
+		break;
+	case APM_NORMAL_RESUME:
+	case APM_CRITICAL_RESUME:
+		if (down) {
+			for (i=0; i<4; i++) {
+				if (dev_self[i])
+					nsc_ircc_wakeup(dev_self[i]);
+			}
+		}
+		down = 0;
+		break;
+	}
+	return 0;
+}
+#endif /* CONFIG_APM */
+
+#ifdef MODULE
+MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
+MODULE_DESCRIPTION("NSC IrDA Device Driver");
+
+MODULE_PARM(qos_mtt_bits, "i");
+MODULE_PARM(io,  "1-4i");
+MODULE_PARM(irq, "1-4i");
+MODULE_PARM(dma, "1-4i");
+MODULE_PARM(dongle_id, "i");
+
+int init_module(void)
+{
+	return nsc_ircc_init();
+}
+
+void cleanup_module(void)
+{
+	nsc_ircc_cleanup();
+}
+#endif /* MODULE */
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/irda/nsc_fir.c linux.15p9/drivers/net/irda/nsc_fir.c
--- linux.vanilla/drivers/net/irda/nsc_fir.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/net/irda/nsc_fir.c	Tue Jan 18 01:08:18 2000
@@ -0,0 +1,1856 @@
+/*********************************************************************
+ *                
+ * Filename:      nsc_fir.c
+ * Version:       1.0
+ * Description:   Driver for the NSC PC'108 and PC'338 IrDA chipsets
+ * Status:        Stable.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sat Nov  7 21:43:15 1998
+ * Modified at:   Tue Jan 11 10:17:04 2000
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>
+ *     Copyright (c) 1998 Lichen Wang, <lwang@actisys.com>
+ *     Copyright (c) 1998 Actisys Corp., www.actisys.com
+ *     All Rights Reserved
+ *      
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ *  
+ *     Neither Dag Brattli nor University of Tromsř admit liability nor
+ *     provide warranty for any of this software. This material is 
+ *     provided "AS-IS" and at no charge.
+ *
+ *     Notice that all functions that needs to access the chip in _any_
+ *     way, must save BSR register on entry, and restore it on exit. 
+ *     It is _very_ important to follow this policy!
+ *
+ *         __u8 bank;
+ *     
+ *         bank = inb(iobase+BSR);
+ *  
+ *         do_your_stuff_here();
+ *
+ *         outb(bank, iobase+BSR);
+ *
+ *    If you find bugs in this file, its very likely that the same bug
+ *    will also be in w83977af_ir.c since the implementations are quite
+ *    similar.
+ *     
+ ********************************************************************/
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/malloc.h>
+#include <linux/init.h>
+#include <linux/rtnetlink.h>
+
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/byteorder.h>
+
+#ifdef CONFIG_APM
+#include <linux/apm_bios.h>
+#endif
+
+#include <net/irda/wrapper.h>
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irlap_frame.h>
+#include <net/irda/irda_device.h>
+
+#include <net/irda/nsc_ircc.h>
+
+#define CHIP_IO_EXTENT 8
+#define BROKEN_DONGLE_ID
+
+/* 
+ * Define if you have multiple NSC IrDA controllers in your machine. Not
+ * enabled by default since some single chips detects at multiple addresses
+ */
+#undef  CONFIG_NSC_IRCC_MULTIPLE 
+
+static char *driver_name = "nsc_ircc";
+
+/* Module parameters */
+static int qos_mtt_bits = 0x07;  /* 1 ms or more */
+static int dongle_id = 0;
+
+static unsigned int io[]  = { 0x2f8, 0x2f8, 0x2f8, 0x2f8, 0x2f8 };
+static unsigned int io2[] = { 0x150, 0x398, 0xea, 0x15c, 0x2e };
+static unsigned int irq[] = { 3, 3, 3, 3, 3 };
+static unsigned int dma[] = { 0, 0, 0, 0, 3 };
+
+static struct nsc_ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL, NULL };
+
+static char *dongle_types[] = {
+	"Differential serial interface",
+	"Differential serial interface",
+	"Reserved",
+	"Reserved",
+	"Sharp RY5HD01",
+	"Reserved",
+	"Single-ended serial interface",
+	"Consumer-IR only",
+	"HP HSDL-2300, HP HSDL-3600/HSDL-3610",
+	"IBM31T1100 or Temic TFDS6000/TFDS6500",
+	"Reserved",
+	"Reserved",
+	"HP HSDL-1100/HSDL-2100",
+	"HP HSDL-1100/HSDL-2100"
+	"Supports SIR Mode only",
+	"No dongle connected",
+};
+
+/* Some prototypes */
+static int  nsc_ircc_open(int i, unsigned int iobase, unsigned int board_addr, 
+			 unsigned int irq, unsigned int dma);
+#ifdef MODULE
+static int  nsc_ircc_close(struct nsc_ircc_cb *self);
+#endif /* MODULE */
+static int  nsc_ircc_probe(int iobase, int board_addr, int irq, int dma);
+static void nsc_ircc_pio_receive(struct nsc_ircc_cb *self);
+static int  nsc_ircc_dma_receive(struct nsc_ircc_cb *self); 
+static int  nsc_ircc_dma_receive_complete(struct nsc_ircc_cb *self, int iobase);
+static int  nsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct device *dev);
+static int  nsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct device *dev);
+static int  nsc_ircc_pio_write(int iobase, __u8 *buf, int len, int fifo_size);
+static void nsc_ircc_dma_xmit(struct nsc_ircc_cb *self, int iobase);
+static void nsc_ircc_change_speed(struct nsc_ircc_cb *self, __u32 baud);
+static void nsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static int  nsc_ircc_is_receiving(struct nsc_ircc_cb *self);
+static int  nsc_ircc_read_dongle_id (int iobase);
+static void nsc_ircc_init_dongle_interface (int iobase, int dongle_id);
+
+static int  nsc_ircc_net_init(struct device *dev);
+static int  nsc_ircc_net_open(struct device *dev);
+static int  nsc_ircc_net_close(struct device *dev);
+static int  nsc_ircc_net_ioctl(struct device *dev, struct ifreq *rq, int cmd);
+static struct net_device_stats *nsc_ircc_net_get_stats(struct device *dev);
+#ifdef CONFIG_APM
+static int nsc_ircc_apmproc(apm_event_t event);
+#endif /* CONFIG_APM */
+/*
+ * Function nsc_ircc_init ()
+ *
+ *    Initialize chip. Just try to find out how many chips we are dealing with
+ *    and where they are
+ */
+int __init nsc_ircc_init(void)
+{
+	int ret = -ENODEV;
+	int ioaddr;
+	int i;
+
+#ifdef CONFIG_APM
+	apm_register_callback(nsc_ircc_apmproc);
+#endif /* CONFIG_APM */
+
+	for (i=0; (io[i] < 2000) && (i < 5); i++) {
+		ioaddr = io[i];
+		if (check_region(ioaddr, CHIP_IO_EXTENT) < 0)
+			continue;
+		if (nsc_ircc_open(i, io[i], io2[i], irq[i], dma[i]) == 0)
+		{
+#ifdef CONFIG_NSC_IRCC_MULTIPLE
+			ret = 0;
+#else
+		        return 0;
+#endif
+		}
+	}
+	return ret;
+}
+
+/*
+ * Function nsc_ircc_cleanup ()
+ *
+ *    Close all configured chips
+ *
+ */
+#ifdef MODULE
+static void nsc_ircc_cleanup(void)
+{
+	int i;
+
+        IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+#ifdef CONFIG_APM
+	apm_unregister_callback(nsc_ircc_apmproc);
+#endif /* CONFIG_APM */
+
+
+	for (i=0; i < 5; i++) {
+		if (dev_self[i])
+			nsc_ircc_close(dev_self[i]);
+	}
+}
+#endif /* MODULE */
+
+/*
+ * Function nsc_ircc_open (iobase, irq)
+ *
+ *    Open driver instance
+ *
+ */
+static int 
+nsc_ircc_open(int i, unsigned int iobase, unsigned int board_addr, 
+	     unsigned int irq, unsigned int dma)
+{
+	struct device *dev;
+	struct nsc_ircc_cb *self;
+	int dongle_id;
+	int ret;
+	int err;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	if ((dongle_id = nsc_ircc_probe(iobase, board_addr, irq, dma)) == -1)
+		return -1;
+
+	/*
+	 *  Allocate new instance of the driver
+	 */
+	self = kmalloc(sizeof(struct nsc_ircc_cb), GFP_KERNEL);
+	if (self == NULL) {
+		ERROR(__FUNCTION__ "(), can't allocate memory for "
+		       "control block!\n");
+		return -ENOMEM;
+	}
+	memset(self, 0, sizeof(struct nsc_ircc_cb));
+	spin_lock_init(&self->lock);
+   
+	/* Need to store self somewhere */
+	dev_self[i] = self;
+
+	/* Initialize IO */
+	self->io.iobase    = iobase;
+        self->io.irq       = irq;
+        self->io.io_ext    = CHIP_IO_EXTENT;
+        self->io.dma       = dma;
+        self->io.fifo_size = 32;
+
+	/* Lock the port that we need */
+	ret = check_region(self->io.iobase, self->io.io_ext);
+	if (ret < 0) { 
+		IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+		      self->io.iobase);
+		/* nsc_ircc_cleanup(self->self);  */
+		return -ENODEV;
+	}
+	request_region(self->io.iobase, self->io.io_ext, driver_name);
+
+	/* Initialize QoS for this device */
+	irda_init_max_qos_capabilies(&self->qos);
+	
+	/* The only value we must override it the baudrate */
+	self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+		IR_115200|IR_576000|IR_1152000 |(IR_4000000 << 8);
+	
+	self->qos.min_turn_time.bits = qos_mtt_bits;
+	irda_qos_bits_to_value(&self->qos);
+	
+	self->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO|IFF_DONGLE;
+
+	/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
+	self->rx_buff.truesize = 14384; 
+	self->tx_buff.truesize = 14384;
+
+	/* Allocate memory if needed */
+	self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
+					      GFP_KERNEL|GFP_DMA);
+	if (self->rx_buff.head == NULL)
+		return -ENOMEM;
+	memset(self->rx_buff.head, 0, self->rx_buff.truesize);
+	
+	self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
+					      GFP_KERNEL|GFP_DMA);
+	if (self->tx_buff.head == NULL) {
+		kfree(self->rx_buff.head);
+		return -ENOMEM;
+	}
+	memset(self->tx_buff.head, 0, self->tx_buff.truesize);
+
+	self->rx_buff.in_frame = FALSE;
+	self->rx_buff.state = OUTSIDE_FRAME;
+	self->tx_buff.data = self->tx_buff.head;
+	self->rx_buff.data = self->rx_buff.head;
+	
+	/* Reset Tx queue info */
+	self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0;
+	self->tx_fifo.tail = self->tx_buff.head;
+
+	if (!(dev = dev_alloc("irda%d", &err))) {
+		ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
+		return -ENOMEM;
+	}
+	/* dev_alloc doesn't clear the struct, so lets do a little hack */
+	memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct device)-sizeof(char*));
+
+	dev->priv = (void *) self;
+	self->netdev = dev;
+
+	/* Override the network functions we need to use */
+	dev->init            = nsc_ircc_net_init;
+	dev->hard_start_xmit = nsc_ircc_hard_xmit_sir;
+	dev->open            = nsc_ircc_net_open;
+	dev->stop            = nsc_ircc_net_close;
+	dev->do_ioctl        = nsc_ircc_net_ioctl;
+	dev->get_stats	     = nsc_ircc_net_get_stats;
+
+	rtnl_lock();
+	err = register_netdevice(dev);
+	rtnl_unlock();
+	if (err) {
+		ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
+		return -1;
+	}
+
+	MESSAGE("IrDA: Registered device %s\n", dev->name);
+	
+	self->io.dongle_id = dongle_id;
+	nsc_ircc_init_dongle_interface(iobase, dongle_id);
+
+	return 0;
+}
+
+#ifdef MODULE
+/*
+ * Function nsc_ircc_close (self)
+ *
+ *    Close driver instance
+ *
+ */
+static int nsc_ircc_close(struct nsc_ircc_cb *self)
+{
+	int iobase;
+
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return -1;);
+
+        iobase = self->io.iobase;
+
+	/* Remove netdevice */
+	if (self->netdev) {
+		rtnl_lock();
+		unregister_netdevice(self->netdev);
+		rtnl_unlock();
+		/* Must free the old-style 2.2.x device */
+		kfree(self->netdev);
+	}
+
+	/* Release the PORT that this driver is using */
+	IRDA_DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", 
+		   self->io.iobase);
+	release_region(self->io.iobase, self->io.io_ext);
+
+	if (self->tx_buff.head)
+		kfree(self->tx_buff.head);
+	
+	if (self->rx_buff.head)
+		kfree(self->rx_buff.head);
+
+	kfree(self);
+
+	return 0;
+}
+#endif /* MODULE */
+
+/*
+ * Function nsc_ircc_init_807 (iobase, board_addr, irq, dma)
+ *
+ *    Initialize the NSC '108 chip
+ *
+ */
+static void nsc_ircc_init_807(int iobase, int board_addr, int irq, int dma)
+{
+	__u8 temp=0;
+
+	outb(2, board_addr);      /* Mode Control Register (MCTL) */
+	outb(0x00, board_addr+1); /* Disable device */
+	
+	/* Base Address and Interrupt Control Register (BAIC) */
+	outb(0, board_addr);
+	switch (iobase) {
+	case 0x3e8: outb(0x14, board_addr+1); break;
+	case 0x2e8: outb(0x15, board_addr+1); break;
+		case 0x3f8: outb(0x16, board_addr+1); break;
+	case 0x2f8: outb(0x17, board_addr+1); break;
+	default: ERROR(__FUNCTION__ "(), invalid base_address");
+	}
+	
+	/* Control Signal Routing Register (CSRT) */
+	switch (irq) {
+	case 3:  temp = 0x01; break;
+	case 4:  temp = 0x02; break;
+	case 5:  temp = 0x03; break;
+	case 7:  temp = 0x04; break;
+	case 9:  temp = 0x05; break;
+	case 11: temp = 0x06; break;
+	case 15: temp = 0x07; break;
+	default: ERROR(__FUNCTION__ "(), invalid irq");
+	}
+	outb(1, board_addr);
+	
+	switch (dma) {	
+	case 0: outb(0x08+temp, board_addr+1); break;
+	case 1: outb(0x10+temp, board_addr+1); break;
+	case 3: outb(0x18+temp, board_addr+1); break;
+	default: ERROR(__FUNCTION__ "(), invalid dma");
+	}
+	
+	outb(2, board_addr);      /* Mode Control Register (MCTL) */
+	outb(0x03, board_addr+1); /* Enable device */
+}
+
+/*
+ * Function nsc_ircc_init_338 (iobase, board_addr, irq, dma)
+ *
+ *    Initialize the NSC '338 chip. Remember that the 87338 needs two 
+ *    consecutive writes to the data registers while CPU interrupts are
+ *    disabled. The 97338 does not require this, but shouldn't be any
+ *    harm if we do it anyway.
+ */
+static void nsc_ircc_init_338(int iobase, int board_addr, int irq, int dma)
+{
+	/* No init yet */
+}
+
+static int nsc_ircc_find_chip(int board_addr)
+{
+	__u8 index, id;
+
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+	/* Read index register */
+	index = inb(board_addr);
+	if (index == 0xff) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), no chip at 0x%03x\n", 
+			   board_addr);
+		return -1;
+	}
+
+	/* Read chip identification register (SID) for the PC97338 */
+	outb(8, board_addr);
+	id = inb(board_addr+1);
+	if ((id & 0xf0) == PC97338) {
+		MESSAGE("%s, Found NSC PC97338 chip, revision=%d\n", 
+			driver_name, id & 0x0f);
+		return PC97338;		
+	} 
+
+	/* Read device identification (DID) for the PC87108 */
+	outb(5, board_addr);
+	id = inb(board_addr+1);
+	if ((id & 0xf0) == PC87108) {
+		MESSAGE("%s, Found NSC PC87108 chip, revision=%d\n", 
+			driver_name, id & 0x0f);
+		return PC87108;
+	}
+
+	return -1;
+}
+
+/*
+ * Function nsc_ircc_probe (iobase, board_addr, irq, dma)
+ *
+ *    Returns non-negative on success.
+ *
+ */
+static int nsc_ircc_probe(int iobase, int board_addr, int irq, int dma)
+{
+	int version;
+	__u8 chip;
+
+	chip = nsc_ircc_find_chip(board_addr);
+	switch (chip) {
+	case PC87108:
+		nsc_ircc_init_807(iobase, board_addr, irq, dma);
+		break;
+	case PC97338:
+		nsc_ircc_init_338(iobase, board_addr, irq, dma);
+		break;
+	default:
+		/* Found no chip */
+		return -1;
+	}
+
+	/* Read the Module ID */
+	switch_bank(iobase, BANK3);
+	version = inb(iobase+MID);
+
+	/* Should be 0x2? */
+	if (0x20 != (version & 0xf0)) {
+		ERROR("%s, Wrong chip version %02x\n", driver_name, version);
+		return -1;
+	}
+	MESSAGE("%s, Found chip at base=0x%03x\n", driver_name, board_addr);
+
+	/* Switch to advanced mode */
+	switch_bank(iobase, BANK2);
+	outb(ECR1_EXT_SL, iobase+ECR1);
+	switch_bank(iobase, BANK0);
+
+	/* Check if user has supplied the dongle id or not */
+	if (!dongle_id) {
+		dongle_id = nsc_ircc_read_dongle_id(iobase);
+		
+		MESSAGE("%s, Found dongle: %s\n", driver_name,
+			dongle_types[dongle_id]);
+	} else {
+		MESSAGE("%s, Using dongle: %s\n", driver_name,
+			dongle_types[dongle_id]);
+	}
+	
+	/* Set FIFO threshold to TX17, RX16, reset and enable FIFO's */
+	switch_bank(iobase, BANK0);	
+	outb(FCR_RXTH|FCR_TXTH|FCR_TXSR|FCR_RXSR|FCR_FIFO_EN, iobase+FCR);
+	
+	/* Set FIFO size to 32 */
+	switch_bank(iobase, BANK2);
+	outb(EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2);
+
+	/* IRCR2: FEND_MD is set */
+	switch_bank(iobase, BANK5);
+ 	outb(0x2a, iobase+4);
+
+	/* Make sure that some defaults are OK */
+	switch_bank(iobase, BANK6);
+	outb(0x20, iobase+0); /* Set 32 bits FIR CRC */
+	outb(0x0a, iobase+1); /* Set MIR pulse width */
+	outb(0x0d, iobase+2); /* Set SIR pulse width */
+	outb(0x2a, iobase+4); /* Set beginning frag, and preamble length */
+
+	MESSAGE("%s, driver loaded (Dag Brattli)\n", driver_name);
+
+	/* Enable receive interrupts */
+	switch_bank(iobase, BANK0);
+	outb(IER_RXHDL_IE, iobase+IER);
+
+	return dongle_id;
+}
+
+/*
+ * Function nsc_ircc_read_dongle_id (void)
+ *
+ * Try to read dongle indentification. This procedure needs to be executed
+ * once after power-on/reset. It also needs to be used whenever you suspect
+ * that the user may have plugged/unplugged the IrDA Dongle.
+ * 
+ */
+static int nsc_ircc_read_dongle_id (int iobase)
+{
+	int dongle_id;
+	__u8 bank;
+
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+	bank = inb(iobase+BSR);
+
+	/* Select Bank 7 */
+	switch_bank(iobase, BANK7);
+	
+	/* IRCFG4: IRSL0_DS and IRSL21_DS are cleared */
+	outb(0x00, iobase+7);
+	
+	/* ID0, 1, and 2 are pulled up/down very slowly */
+	udelay(50);
+	
+	/* IRCFG1: read the ID bits */
+	dongle_id = inb(iobase+4) & 0x0f;
+
+#ifdef BROKEN_DONGLE_ID
+	if (dongle_id == 0x0a)
+		dongle_id = 0x09;
+#endif
+	
+	/* Go back to  bank 0 before returning */
+	switch_bank(iobase, BANK0);
+
+	outb(bank, iobase+BSR);
+
+	return dongle_id;
+}
+
+/*
+ * Function nsc_ircc_init_dongle_interface (iobase, dongle_id)
+ *
+ *     This function initializes the dongle for the transceiver that is
+ *     used. This procedure needs to be executed once after
+ *     power-on/reset. It also needs to be used whenever you suspect that
+ *     the dongle is changed. 
+ */
+static void nsc_ircc_init_dongle_interface (int iobase, int dongle_id)
+{
+	int bank;
+
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+
+	/* Select Bank 7 */
+	switch_bank(iobase, BANK7);
+	
+	/* IRCFG4: set according to dongle_id */
+	switch (dongle_id) {
+	case 0x00: /* same as */
+	case 0x01: /* Differential serial interface */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x02: /* same as */
+	case 0x03: /* Reserved */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x04: /* Sharp RY5HD01 */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x05: /* Reserved, but this is what the Thinkpad reports */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x06: /* Single-ended serial interface */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x07: /* Consumer-IR only */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */
+		outb_p(0x28, iobase+7); /* Set irsl[0-2] as output */
+		break;
+	case 0x0A: /* same as */
+	case 0x0B: /* Reserved */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x0C: /* same as */
+	case 0x0D: /* HP HSDL-1100/HSDL-2100 */
+		/* 
+		 * Set irsl0 as input, irsl[1-2] as output, and separate 
+		 * inputs are used for SIR and MIR/FIR 
+		 */
+		outb(0x48, iobase+7); 
+		break;
+	case 0x0E: /* Supports SIR Mode only */
+		outb(0x28, iobase+7); /* Set irsl[0-2] as output */
+		break;
+	case 0x0F: /* No dongle connected */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s\n",
+			   dongle_types[dongle_id]); 
+
+		switch_bank(iobase, BANK0);
+		outb(0x62, iobase+MCR);
+		break;
+	default: 
+		IRDA_DEBUG(0, __FUNCTION__ "(), invalid dongle_id %#x", 
+			   dongle_id);
+	}
+	
+	/* IRCFG1: IRSL1 and 2 are set to IrDA mode */
+	outb(0x00, iobase+4);
+
+	/* Restore bank register */
+	outb(bank, iobase+BSR);
+	
+} /* set_up_dongle_interface */
+
+/*
+ * Function nsc_ircc_change_dongle_speed (iobase, speed, dongle_id)
+ *
+ *    Change speed of the attach dongle
+ *
+ */
+static void nsc_ircc_change_dongle_speed(int iobase, int speed, int dongle_id)
+{
+	unsigned long flags;
+	__u8 bank;
+
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+
+	/* Select Bank 7 */
+	switch_bank(iobase, BANK7);
+	
+	/* IRCFG1: set according to dongle_id */
+	switch (dongle_id) {
+	case 0x00: /* same as */
+	case 0x01: /* Differential serial interface */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x02: /* same as */
+	case 0x03: /* Reserved */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x04: /* Sharp RY5HD01 */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
+			   dongle_types[dongle_id]); 
+	case 0x05: /* Reserved */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x06: /* Single-ended serial interface */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x07: /* Consumer-IR only */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
+			   dongle_types[dongle_id]); 
+	case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */
+		switch_bank(iobase, BANK7);
+		outb_p(0x01, iobase+4);
+
+		if (speed == 4000000) {
+			save_flags(flags);
+			cli();
+			outb(0x81, iobase+4);
+			outb(0x80, iobase+4);
+			restore_flags(flags);
+		} else
+			outb_p(0x00, iobase+4);
+		break;
+	case 0x0A: /* same as */
+	case 0x0B: /* Reserved */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x0C: /* same as */
+	case 0x0D: /* HP HSDL-1100/HSDL-2100 */
+		break;
+	case 0x0E: /* Supports SIR Mode only */
+		break;
+	case 0x0F: /* No dongle connected */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n",
+			   dongle_types[dongle_id]);
+
+		switch_bank(iobase, BANK0); 
+		outb(0x62, iobase+MCR);
+		break;
+	default: 
+		IRDA_DEBUG(0, __FUNCTION__ "(), invalid data_rate\n");
+	}
+	/* Restore bank register */
+	outb(bank, iobase+BSR);
+}
+
+/*
+ * Function nsc_ircc_change_speed (self, baud)
+ *
+ *    Change the speed of the device
+ *
+ */
+static void nsc_ircc_change_speed(struct nsc_ircc_cb *self, __u32 speed)
+{
+	struct device *dev = self->netdev;
+	__u8 mcr = MCR_SIR;
+	int iobase; 
+	__u8 bank;
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), speed=%d\n", speed);
+
+	ASSERT(self != NULL, return;);
+
+	iobase = self->io.iobase;
+
+	/* Update accounting for new speed */
+	self->io.speed = speed;
+
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+
+	/* Disable interrupts */
+	switch_bank(iobase, BANK0);
+	outb(0, iobase+IER);
+
+	/* Select Bank 2 */
+	switch_bank(iobase, BANK2);
+
+	outb(0x00, iobase+BGDH);
+	switch (speed) {
+	case 9600:   outb(0x0c, iobase+BGDL); break;
+	case 19200:  outb(0x06, iobase+BGDL); break;
+	case 38400:  outb(0x03, iobase+BGDL); break;
+	case 57600:  outb(0x02, iobase+BGDL); break;
+	case 115200: outb(0x01, iobase+BGDL); break;
+	case 576000:
+		switch_bank(iobase, BANK5);
+		
+		/* IRCR2: MDRS is set */
+		outb(inb(iobase+4) | 0x04, iobase+4);
+	       
+		mcr = MCR_MIR;
+		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
+		break;
+	case 1152000:
+		mcr = MCR_MIR;
+		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
+		break;
+	case 4000000:
+		mcr = MCR_FIR;
+		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
+		break;
+	default:
+		mcr = MCR_FIR;
+		IRDA_DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", 
+			   speed);
+		break;
+	}
+
+	/* Set appropriate speed mode */
+	switch_bank(iobase, BANK0);
+	outb(mcr | MCR_TX_DFR, iobase+MCR);
+
+	/* Give some hits to the transceiver */
+	nsc_ircc_change_dongle_speed(iobase, speed, self->io.dongle_id);
+
+	/* Set FIFO threshold to TX17, RX16 */
+	switch_bank(iobase, BANK0);
+	outb(0x00, iobase+FCR);
+	outb(FCR_FIFO_EN, iobase+FCR);
+	outb(FCR_RXTH|     /* Set Rx FIFO threshold */
+	     FCR_TXTH|     /* Set Tx FIFO threshold */
+	     FCR_TXSR|     /* Reset Tx FIFO */
+	     FCR_RXSR|     /* Reset Rx FIFO */
+	     FCR_FIFO_EN,  /* Enable FIFOs */
+	     iobase+FCR);
+	
+	/* Set FIFO size to 32 */
+	switch_bank(iobase, BANK2);
+	outb(EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2);
+	
+	self->netdev->tbusy = 0;
+	
+	/* Enable some interrupts so we can receive frames */
+	switch_bank(iobase, BANK0); 
+	if (speed > 115200) {
+		/* Install FIR xmit handler */
+		dev->hard_start_xmit = nsc_ircc_hard_xmit_fir;
+		outb(IER_SFIF_IE, iobase+IER);
+		nsc_ircc_dma_receive(self);
+	} else {
+		/* Install SIR xmit handler */
+		dev->hard_start_xmit = nsc_ircc_hard_xmit_sir;
+		outb(IER_RXHDL_IE, iobase+IER);
+	}
+    	
+	/* Restore BSR */
+	outb(bank, iobase+BSR);
+}
+
+/*
+ * Function nsc_ircc_hard_xmit (skb, dev)
+ *
+ *    Transmit the frame!
+ *
+ */
+static int nsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct device *dev)
+{
+	struct nsc_ircc_cb *self;
+	unsigned long flags;
+	int iobase;
+	__u32 speed;
+	__u8 bank;
+	
+	self = (struct nsc_ircc_cb *) dev->priv;
+
+	ASSERT(self != NULL, return 0;);
+
+	iobase = self->io.iobase;
+
+	/* Lock transmit buffer */
+	if (irda_lock((void *) &dev->tbusy) == FALSE)
+		return -EBUSY;
+	
+	/* Check if we need to change the speed */
+	if ((speed = irda_get_speed(skb)) != self->io.speed)
+		self->new_speed = speed;
+	
+	spin_lock_irqsave(&self->lock, flags);
+	
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+	
+	self->tx_buff.data = self->tx_buff.head;
+	
+	self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, 
+					   self->tx_buff.truesize);
+	
+	/* Add interrupt on tx low level (will fire immediately) */
+	switch_bank(iobase, BANK0);
+	outb(IER_TXLDL_IE, iobase+IER);
+	
+	/* Restore bank register */
+	outb(bank, iobase+BSR);
+
+	spin_unlock_irqrestore(&self->lock, flags);
+
+	dev_kfree_skb(skb);
+
+	return 0;
+}
+
+static int nsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct device *dev)
+{
+	struct nsc_ircc_cb *self;
+	unsigned long flags;
+	int iobase;
+	__u32 speed;
+	__u8 bank;
+	int mtt, diff;
+	
+	self = (struct nsc_ircc_cb *) dev->priv;
+
+	ASSERT(self != NULL, return 0;);
+
+	iobase = self->io.iobase;
+
+	/* Lock transmit buffer */
+	if (irda_lock((void *) &dev->tbusy) == FALSE)
+		return -EBUSY;
+
+	/* Check if we need to change the speed */
+	if ((speed = irda_get_speed(skb)) != self->io.speed)
+		self->new_speed = speed;
+
+	spin_lock_irqsave(&self->lock, flags);
+
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+
+	/* Register and copy this frame to DMA memory */
+	self->tx_fifo.queue[self->tx_fifo.free].start = self->tx_fifo.tail;
+	self->tx_fifo.queue[self->tx_fifo.free].len = skb->len;
+	self->tx_fifo.tail += skb->len;
+
+	memcpy(self->tx_fifo.queue[self->tx_fifo.free].start, skb->data, 
+	       skb->len);
+	
+	self->tx_fifo.len++;
+	self->tx_fifo.free++;
+
+	/* Start transmit only if there is currently no transmit going on */
+	if (self->tx_fifo.len == 1) {
+		/* Check if we must wait the min turn time or not */
+		mtt = irda_get_mtt(skb);
+		if (mtt) {
+			/* Check how much time we have used already */
+			get_fast_time(&self->now);
+			diff = self->now.tv_usec - self->stamp.tv_usec;
+			if (diff < 0) 
+				diff += 1000000;
+			
+			/* Check if the mtt is larger than the time we have
+			 * already used by all the protocol processing
+			 */
+			if (mtt > diff) {
+				mtt -= diff;
+
+				/* 
+				 * Use timer if delay larger than 125 us, and
+				 * use udelay for smaller values which should
+				 * be acceptable
+				 */
+				if (mtt > 125) {
+					/* Adjust for timer resolution */
+					mtt = mtt / 125;
+					
+					/* Setup timer */
+					switch_bank(iobase, BANK4);
+					outb(mtt & 0xff, iobase+TMRL);
+					outb((mtt >> 8) & 0x0f, iobase+TMRH);
+					
+					/* Start timer */
+					outb(IRCR1_TMR_EN, iobase+IRCR1);
+					self->io.direction = IO_XMIT;
+					
+					/* Enable timer interrupt */
+					switch_bank(iobase, BANK0);
+					outb(IER_TMR_IE, iobase+IER);
+					
+					/* Timer will take care of the rest */
+					goto out; 
+				} else
+					udelay(mtt);
+			}
+		}		
+		/* Enable DMA interrupt */
+		switch_bank(iobase, BANK0);
+		outb(IER_DMA_IE, iobase+IER);
+
+		/* Transmit frame */
+		nsc_ircc_dma_xmit(self, iobase);
+	}
+ out:
+	/* Not busy transmitting anymore if window is not full */
+	if (self->tx_fifo.free < MAX_WINDOW)
+		dev->tbusy = 0;
+
+	/* Restore bank register */
+	outb(bank, iobase+BSR);
+
+	spin_unlock_irqrestore(&self->lock, flags);
+
+	dev_kfree_skb(skb);
+
+	return 0;
+}
+
+/*
+ * Function nsc_ircc_dma_xmit (self, iobase)
+ *
+ *    Transmit data using DMA
+ *
+ */
+static void nsc_ircc_dma_xmit(struct nsc_ircc_cb *self, int iobase)
+{
+	int bsr;
+
+	/* Save current bank */
+	bsr = inb(iobase+BSR);
+
+	/* Disable DMA */
+	switch_bank(iobase, BANK0);
+	outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
+	
+	self->io.direction = IO_XMIT;
+	
+	/* Choose transmit DMA channel  */ 
+	switch_bank(iobase, BANK2);
+	outb(ECR1_DMASWP|ECR1_DMANF|ECR1_EXT_SL, iobase+ECR1);
+	
+	setup_dma(self->io.dma, 
+		  self->tx_fifo.queue[self->tx_fifo.ptr].start, 
+		  self->tx_fifo.queue[self->tx_fifo.ptr].len, 
+		  DMA_TX_MODE);
+
+	/* Enable DMA and SIR interaction pulse */
+ 	switch_bank(iobase, BANK0);	
+	outb(inb(iobase+MCR)|MCR_TX_DFR|MCR_DMA_EN|MCR_IR_PLS, iobase+MCR);
+
+	/* Restore bank register */
+	outb(bsr, iobase+BSR);
+}
+
+/*
+ * Function nsc_ircc_pio_xmit (self, iobase)
+ *
+ *    Transmit data using PIO. Returns the number of bytes that actually
+ *    got transfered
+ *
+ */
+static int nsc_ircc_pio_write(int iobase, __u8 *buf, int len, int fifo_size)
+{
+	int actual = 0;
+	__u8 bank;
+	
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+
+	switch_bank(iobase, BANK0);
+	if (!(inb_p(iobase+LSR) & LSR_TXEMP)) {
+		IRDA_DEBUG(4, __FUNCTION__ 
+			   "(), warning, FIFO not empty yet!\n");
+
+		fifo_size -= 17;
+	}
+
+	/* Fill FIFO with current frame */
+	while ((fifo_size-- > 0) && (actual < len)) {
+		/* Transmit next byte */
+		outb(buf[actual++], iobase+TXD);
+	}
+        
+	IRDA_DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", 
+		   fifo_size, actual, len);
+	
+	/* Restore bank */
+	outb(bank, iobase+BSR);
+
+	return actual;
+}
+
+/*
+ * Function nsc_ircc_dma_xmit_complete (self)
+ *
+ *    The transfer of a frame in finished. This function will only be called 
+ *    by the interrupt handler
+ *
+ */
+static int nsc_ircc_dma_xmit_complete(struct nsc_ircc_cb *self)
+{
+	int iobase;
+	__u8 bank;
+	int ret = TRUE;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	iobase = self->io.iobase;
+
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+
+	/* Disable DMA */
+	switch_bank(iobase, BANK0);
+        outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
+	
+	/* Check for underrrun! */
+	if (inb(iobase+ASCR) & ASCR_TXUR) {
+		self->stats.tx_errors++;
+		self->stats.tx_fifo_errors++;
+		
+		/* Clear bit, by writing 1 into it */
+		outb(ASCR_TXUR, iobase+ASCR);
+	} else {
+		self->stats.tx_packets++;
+		self->stats.tx_bytes += self->tx_buff.len;
+	}
+	
+	if (self->new_speed) {
+		nsc_ircc_change_speed(self, self->new_speed);
+		self->new_speed = 0;
+	}
+
+	/* Finished with this frame, so prepare for next */
+	self->tx_fifo.ptr++;
+	self->tx_fifo.len--;
+
+	/* Any frames to be sent back-to-back? */
+	if (self->tx_fifo.len) {
+		nsc_ircc_dma_xmit(self, iobase);
+		
+		/* Not finished yet! */
+		ret = FALSE;
+	} else {
+		/* Reset Tx FIFO info */
+		self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0;
+		self->tx_fifo.tail = self->tx_buff.head;
+	}
+
+	/* Make sure we have room for more frames */
+	if (self->tx_fifo.free < MAX_WINDOW) {
+		/* Not busy transmitting anymore */
+		self->netdev->tbusy = 0;
+
+		/* Tell the network layer, that we can accept more frames */
+		mark_bh(NET_BH);
+	}
+
+	/* Restore bank */
+	outb(bank, iobase+BSR);
+	
+	return ret;
+}
+
+/*
+ * Function nsc_ircc_dma_receive (self)
+ *
+ *    Get ready for receiving a frame. The device will initiate a DMA
+ *    if it starts to receive a frame.
+ *
+ */
+static int nsc_ircc_dma_receive(struct nsc_ircc_cb *self) 
+{
+	int iobase;
+	__u8 bsr;
+
+	ASSERT(self != NULL, return -1;);
+
+	iobase = self->io.iobase;
+
+	/* Reset Tx FIFO info */
+	self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0;
+	self->tx_fifo.tail = self->tx_buff.head;
+
+	/* Save current bank */
+	bsr = inb(iobase+BSR);
+
+	/* Disable DMA */
+	switch_bank(iobase, BANK0);
+	outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
+
+	/* Choose DMA Rx, DMA Fairness, and Advanced mode */
+	switch_bank(iobase, BANK2);
+	outb(ECR1_DMANF|ECR1_EXT_SL, iobase+ECR1);
+
+	self->io.direction = IO_RECV;
+	self->rx_buff.data = self->rx_buff.head;
+	
+	/* Reset Rx FIFO. This will also flush the ST_FIFO */
+	switch_bank(iobase, BANK0);
+	outb(FCR_RXSR|FCR_FIFO_EN, iobase+FCR);
+	self->st_fifo.len = self->st_fifo.tail = self->st_fifo.head = 0;
+	
+	setup_dma(self->io.dma, self->rx_buff.data, self->rx_buff.truesize, 
+		  DMA_RX_MODE);
+
+	/* Enable DMA */
+	switch_bank(iobase, BANK0);
+	outb(inb(iobase+MCR)|MCR_DMA_EN, iobase+MCR);
+
+	/* Restore bank register */
+	outb(bsr, iobase+BSR);
+	
+	return 0;
+}
+
+/*
+ * Function nsc_ircc_dma_receive_complete (self)
+ *
+ *    Finished with receiving frames
+ *
+ *    
+ */
+static int nsc_ircc_dma_receive_complete(struct nsc_ircc_cb *self, int iobase)
+{
+	struct sk_buff *skb;
+	struct st_fifo *st_fifo;
+	__u8 bank;
+	__u8 status;
+	int len;
+
+	st_fifo = &self->st_fifo;
+
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+	
+	/* Read status FIFO */
+	switch_bank(iobase, BANK5);
+	while ((status = inb(iobase+FRM_ST)) & FRM_ST_VLD) {
+		st_fifo->entries[st_fifo->tail].status = status;
+
+		st_fifo->entries[st_fifo->tail].len  = inb(iobase+RFLFL);
+		st_fifo->entries[st_fifo->tail].len |= inb(iobase+RFLFH) << 8;
+		
+		st_fifo->tail++;
+		st_fifo->len++;
+	}
+	/* Try to process all entries in status FIFO */
+	while (st_fifo->len) {
+		/* Get first entry */
+		status = st_fifo->entries[st_fifo->head].status;
+		len    = st_fifo->entries[st_fifo->head].len;
+		st_fifo->head++;
+		st_fifo->len--;
+
+		/* Check for errors */
+		if (status & FRM_ST_ERR_MSK) {
+			if (status & FRM_ST_LOST_FR) {
+				/* Add number of lost frames to stats */
+				self->stats.rx_errors += len;	
+			} else {
+				/* Skip frame */
+				self->stats.rx_errors++;
+				
+				self->rx_buff.data += len;
+			
+				if (status & FRM_ST_MAX_LEN)
+					self->stats.rx_length_errors++;
+				
+				if (status & FRM_ST_PHY_ERR) 
+					self->stats.rx_frame_errors++;
+				
+				if (status & FRM_ST_BAD_CRC) 
+					self->stats.rx_crc_errors++;
+			}
+			/* The errors below can be reported in both cases */
+			if (status & FRM_ST_OVR1)
+				self->stats.rx_fifo_errors++;		       
+			
+			if (status & FRM_ST_OVR2)
+				self->stats.rx_fifo_errors++;
+		} else {
+			/* Check if we have transfered all data to memory */
+			switch_bank(iobase, BANK0);
+			if (inb(iobase+LSR) & LSR_RXDA) {
+				/* Put this entry back in fifo */
+				st_fifo->head--;
+				st_fifo->len++;
+				st_fifo->entries[st_fifo->head].status = status;
+				st_fifo->entries[st_fifo->head].len = len;
+				
+				/* Restore bank register */
+				outb(bank, iobase+BSR);
+				
+				return FALSE; 	/* I'll be back! */
+			}
+
+			/* 
+			 * Remember when we received this frame, so we can
+			 * reduce the min turn time a bit since we will know
+			 * how much time we have used for protocol processing
+			 */
+			get_fast_time(&self->stamp);
+
+			skb = dev_alloc_skb(len+1);
+			if (skb == NULL)  {
+				WARNING(__FUNCTION__ "(), memory squeeze, "
+					"dropping frame.\n");
+				
+				/* Restore bank register */
+				outb(bank, iobase+BSR);
+				
+				return FALSE;
+			}
+			
+			/* Make sure IP header gets aligned */
+			skb_reserve(skb, 1); 
+
+			/* Copy frame without CRC */
+			if (self->io.speed < 4000000) {
+				skb_put(skb, len-2);
+				memcpy(skb->data, self->rx_buff.data, len-2);
+			} else {
+				skb_put(skb, len-4);
+				memcpy(skb->data, self->rx_buff.data, len-4);
+			}
+
+			/* Move to next frame */
+			self->rx_buff.data += len;
+			self->stats.rx_packets++;
+
+			skb->dev = self->netdev;
+			skb->mac.raw  = skb->data;
+			skb->protocol = htons(ETH_P_IRDA);
+			netif_rx(skb);
+		}
+	}
+	/* Restore bank register */
+	outb(bank, iobase+BSR);
+
+	return TRUE;
+}
+
+/*
+ * Function nsc_ircc_pio_receive (self)
+ *
+ *    Receive all data in receiver FIFO
+ *
+ */
+static void nsc_ircc_pio_receive(struct nsc_ircc_cb *self) 
+{
+	__u8 byte = 0x00;
+	int iobase;
+
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	
+	iobase = self->io.iobase;
+	
+	/*  Receive all characters in Rx FIFO */
+	do {
+		byte = inb(iobase+RXD);
+		async_unwrap_char(self->netdev, &self->stats, &self->rx_buff, 
+				  byte);
+	} while (inb(iobase+LSR) & LSR_RXDA); /* Data available */	
+}
+
+/*
+ * Function nsc_ircc_sir_interrupt (self, eir)
+ *
+ *    Handle SIR interrupt
+ *
+ */
+static __u8 nsc_ircc_sir_interrupt(struct nsc_ircc_cb *self, int eir)
+{
+	int actual;
+	__u8 new_ier = 0;
+
+	/* Check if transmit FIFO is low on data */
+	if (eir & EIR_TXLDL_EV) {
+		/* Write data left in transmit buffer */
+		actual = nsc_ircc_pio_write(self->io.iobase, 
+					   self->tx_buff.data, 
+					   self->tx_buff.len, 
+					   self->io.fifo_size);
+		self->tx_buff.data += actual;
+		self->tx_buff.len  -= actual;
+		
+		self->io.direction = IO_XMIT;
+
+		/* Check if finished */
+		if (self->tx_buff.len > 0)
+			new_ier |= IER_TXLDL_IE;
+		else { 
+			self->netdev->tbusy = 0; /* Unlock */
+			self->stats.tx_packets++;
+			
+		        mark_bh(NET_BH);	
+
+			new_ier |= IER_TXEMP_IE;
+		}
+			
+	}
+	/* Check if transmission has completed */
+	if (eir & EIR_TXEMP_EV) {
+		/* Check if we need to change the speed? */
+		if (self->new_speed) {
+			IRDA_DEBUG(2, __FUNCTION__ "(), Changing speed!\n");
+			nsc_ircc_change_speed(self, self->new_speed);
+			self->new_speed = 0;
+
+			/* Check if we are going to FIR */
+			if (self->io.speed > 115200) {
+				/* Should wait for status FIFO interrupt */
+				new_ier = IER_SFIF_IE;
+
+				/* No need to do anymore SIR stuff */
+				return;
+			}
+		}
+
+		/* Turn around and get ready to receive some data */
+		self->io.direction = IO_RECV;
+		new_ier |= IER_RXHDL_IE;
+	}
+
+	/* Rx FIFO threshold or timeout */
+	if (eir & EIR_RXHDL_EV) {
+		nsc_ircc_pio_receive(self);
+
+		/* Keep receiving */
+		new_ier |= IER_RXHDL_IE;
+	}
+	return new_ier;
+}
+
+/*
+ * Function nsc_ircc_fir_interrupt (self, eir)
+ *
+ *    Handle MIR/FIR interrupt
+ *
+ */
+static __u8 nsc_ircc_fir_interrupt(struct nsc_ircc_cb *self, int iobase, 
+				   int eir)
+{
+	__u8 new_ier = 0;
+	__u8 bank;
+
+	bank = inb(iobase+BSR);
+	
+	/* Status event, or end of frame detected in FIFO */
+	if (eir & (EIR_SFIF_EV|EIR_LS_EV)) {
+		if (nsc_ircc_dma_receive_complete(self, iobase)) {
+
+			/* Wait for next status FIFO interrupt */
+			new_ier |= IER_SFIF_IE;
+		} else {
+			/* 
+			 * DMA not finished yet, so try again later, set 
+			 * timer value, resolution 125 us 
+			 */
+			switch_bank(iobase, BANK4);
+			outb(0x07, iobase+TMRL); /* 125 us * 7 = 875 us */
+			outb(0x00, iobase+TMRH);
+
+			/* Start timer */
+			outb(IRCR1_TMR_EN, iobase+IRCR1);
+
+			new_ier |= IER_TMR_IE;
+		}
+	} else if (eir & EIR_TMR_EV) { /* Timer finished */
+		/* Disable timer */
+		switch_bank(iobase, BANK4);
+		outb(0, iobase+IRCR1);
+
+		/* Clear timer event */
+		switch_bank(iobase, BANK0);
+		outb(ASCR_CTE, iobase+ASCR);
+
+		/* Check if this is a TX timer interrupt */
+		if (self->io.direction == IO_XMIT) {
+			nsc_ircc_dma_xmit(self, iobase);
+
+			/*  Interrupt on DMA */
+			new_ier |= IER_DMA_IE;
+		} else {
+			/* Check if DMA has now finished */
+			nsc_ircc_dma_receive_complete(self, iobase);
+
+			new_ier |= IER_SFIF_IE;
+		}
+	} else if (eir & EIR_DMA_EV) { /* Finished with transmission */
+		if (nsc_ircc_dma_xmit_complete(self)) {		
+			/* Check if there are more frames to be transmitted */
+			if (irda_device_txqueue_empty(self->netdev)) {
+				/* Prepare for receive */
+				nsc_ircc_dma_receive(self);
+			
+				new_ier = IER_LS_IE|IER_SFIF_IE;
+			}
+		} else {
+			/*  Not finished yet, so interrupt on DMA again */
+			new_ier |= IER_DMA_IE;
+		}
+	}
+	outb(bank, iobase+BSR);
+
+	return new_ier;
+}
+
+/*
+ * Function nsc_ircc_interrupt (irq, dev_id, regs)
+ *
+ *    An interrupt from the chip has arrived. Time to do some work
+ *
+ */
+static void nsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct device *dev = (struct device *) dev_id;
+	struct nsc_ircc_cb *self;
+	__u8 bsr, eir, ier;
+	int iobase;
+
+	if (!dev) {
+		printk(KERN_WARNING "%s: irq %d for unknown device.\n", 
+		       driver_name, irq);
+		return;
+	}
+	self = (struct nsc_ircc_cb *) dev->priv;
+
+	spin_lock(&self->lock);	
+	dev->interrupt = 1;
+
+	iobase = self->io.iobase;
+
+	bsr = inb(iobase+BSR); 	/* Save current bank */
+
+	switch_bank(iobase, BANK0);	
+	ier = inb(iobase+IER); 
+	eir = inb(iobase+EIR) & ier; /* Mask out the interesting ones */ 
+
+	outb(0, iobase+IER); /* Disable interrupts */
+	
+	if (eir) {
+		/* Dispatch interrupt handler for the current speed */
+		if (self->io.speed > 115200)
+			ier = nsc_ircc_fir_interrupt(self, iobase, eir);
+		else
+			ier = nsc_ircc_sir_interrupt(self, eir);
+	}
+
+	outb(ier, iobase+IER);   /* Restore interrupts */
+	outb(bsr, iobase+BSR);   /* Restore bank register */
+
+	dev->interrupt = 0;
+	spin_unlock(&self->lock);
+}
+
+/*
+ * Function nsc_ircc_is_receiving (self)
+ *
+ *    Return TRUE is we are currently receiving a frame
+ *
+ */
+static int nsc_ircc_is_receiving(struct nsc_ircc_cb *self)
+{
+	int status = FALSE;
+	int iobase;
+	__u8 bank;
+
+	ASSERT(self != NULL, return FALSE;);
+
+	if (self->io.speed > 115200) {
+		iobase = self->io.iobase;
+
+		/* Check if rx FIFO is not empty */
+		bank = inb(iobase+BSR);
+		switch_bank(iobase, BANK2);
+		if ((inb(iobase+RXFLV) & 0x3f) != 0) {
+			/* We are receiving something */
+			status =  TRUE;
+		}
+		outb(bank, iobase+BSR);
+	} else 
+		status = (self->rx_buff.state != OUTSIDE_FRAME);
+	
+	return status;
+}
+
+/*
+ * Function nsc_ircc_net_init (dev)
+ *
+ *    Initialize network device
+ *
+ */
+static int nsc_ircc_net_init(struct device *dev)
+{
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+	/* Setup to be a normal IrDA network device driver */
+	irda_device_setup(dev);
+
+	/* Insert overrides below this line! */
+
+	return 0;
+}
+
+/*
+ * Function nsc_ircc_net_open (dev)
+ *
+ *    Start the device
+ *
+ */
+static int nsc_ircc_net_open(struct device *dev)
+{
+	struct nsc_ircc_cb *self;
+	int iobase;
+	__u8 bank;
+	
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+	
+	ASSERT(dev != NULL, return -1;);
+	self = (struct nsc_ircc_cb *) dev->priv;
+	
+	ASSERT(self != NULL, return 0;);
+	
+	iobase = self->io.iobase;
+	
+	if (request_irq(self->io.irq, nsc_ircc_interrupt, 0, dev->name, 
+			(void *) dev)) 
+	{
+		return -EAGAIN;
+	}
+	/*
+	 * Always allocate the DMA channel after the IRQ, and clean up on 
+	 * failure.
+	 */
+	if (request_dma(self->io.dma, dev->name)) {
+		free_irq(self->io.irq, self);
+		return -EAGAIN;
+	}
+	
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+	
+	/* turn on interrupts */
+	switch_bank(iobase, BANK0);
+	outb(IER_LS_IE | IER_RXHDL_IE, iobase+IER);
+
+	/* Restore bank register */
+	outb(bank, iobase+BSR);
+
+	/* Ready to play! */
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	dev->start = 1;
+
+	/* 
+	 * Open new IrLAP layer instance, now that everything should be
+	 * initialized properly 
+	 */
+	self->irlap = irlap_open(dev, &self->qos);
+
+	MOD_INC_USE_COUNT;
+
+	return 0;
+}
+
+/*
+ * Function nsc_ircc_net_close (dev)
+ *
+ *    Stop the device
+ *
+ */
+static int nsc_ircc_net_close(struct device *dev)
+{
+	struct nsc_ircc_cb *self;
+	int iobase;
+	__u8 bank;
+
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+	
+	ASSERT(dev != NULL, return -1;);
+	self = (struct nsc_ircc_cb *) dev->priv;
+	
+	ASSERT(self != NULL, return 0;);
+
+	/* Stop device */
+	dev->tbusy = 1;
+	dev->start = 0;
+
+	/* Stop and remove instance of IrLAP */
+	if (self->irlap)
+		irlap_close(self->irlap);
+	self->irlap = NULL;
+	
+	iobase = self->io.iobase;
+
+	disable_dma(self->io.dma);
+
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+
+	/* Disable interrupts */
+	switch_bank(iobase, BANK0);
+	outb(0, iobase+IER); 
+       
+	free_irq(self->io.irq, dev);
+	free_dma(self->io.dma);
+
+	/* Restore bank register */
+	outb(bank, iobase+BSR);
+
+	MOD_DEC_USE_COUNT;
+
+	return 0;
+}
+
+/*
+ * Function nsc_ircc_net_ioctl (dev, rq, cmd)
+ *
+ *    Process IOCTL commands for this device
+ *
+ */
+static int nsc_ircc_net_ioctl(struct device *dev, struct ifreq *rq, int cmd)
+{
+	struct if_irda_req *irq = (struct if_irda_req *) rq;
+	struct nsc_ircc_cb *self;
+	unsigned long flags;
+	int ret = 0;
+
+	ASSERT(dev != NULL, return -1;);
+
+	self = dev->priv;
+
+	ASSERT(self != NULL, return -1;);
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
+	
+	/* Disable interrupts & save flags */
+	save_flags(flags);
+	cli();
+	
+	switch (cmd) {
+	case SIOCSBANDWIDTH: /* Set bandwidth */
+		nsc_ircc_change_speed(self, irq->ifr_baudrate);
+		break;
+	case SIOCSMEDIABUSY: /* Set media busy */
+		irda_device_set_media_busy(self->netdev, TRUE);
+		break;
+	case SIOCGRECEIVING: /* Check if we are receiving right now */
+		irq->ifr_receiving = nsc_ircc_is_receiving(self);
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+	}
+	
+	restore_flags(flags);
+	
+	return ret;
+}
+
+static struct net_device_stats *nsc_ircc_net_get_stats(struct device *dev)
+{
+	struct nsc_ircc_cb *self = (struct nsc_ircc_cb *) dev->priv;
+	
+	return &self->stats;
+}
+
+#ifdef CONFIG_APM
+static void nsc_ircc_suspend(struct nsc_ircc_cb *self)
+{
+	int i = 10;
+
+	MESSAGE("%s, Suspending\n", driver_name);
+
+	if (self->suspend)
+		return;
+
+	self->suspend = 1;
+}
+
+
+static void nsc_ircc_wakeup(struct nsc_ircc_cb *self)
+{
+	struct device *dev = self->netdev;
+	unsigned long flags;
+
+	if (!self->suspend)
+		return;
+
+	save_flags(flags);
+	cli();
+
+	
+	restore_flags(flags);
+	MESSAGE("%s, Waking up\n", driver_name);
+}
+
+static int nsc_ircc_apmproc(apm_event_t event)
+{
+	static int down = 0;          /* Filter out double events */
+	int i;
+
+	switch (event) {
+	case APM_SYS_SUSPEND:
+	case APM_USER_SUSPEND:
+		if (!down) {			
+			for (i = 0; i < 4; i++) {
+				if (dev_self[i])
+					nsc_ircc_suspend(dev_self[i]);
+			}
+		}
+		down = 1;
+		break;
+	case APM_NORMAL_RESUME:
+	case APM_CRITICAL_RESUME:
+		if (down) {
+			for (i = 0; i < 4; i++) {
+				if (dev_self[i])
+					nsc_ircc_wakeup(dev_self[i]);
+			}
+		}
+		down = 0;
+		break;
+	}
+	return 0;
+}
+#endif /* CONFIG_APM */
+
+#ifdef MODULE
+MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
+MODULE_DESCRIPTION("NSC FIR IrDA Device Driver");
+
+MODULE_PARM(qos_mtt_bits, "i");
+MODULE_PARM(io, "1-4i");
+MODULE_PARM(io2, "1-4i");
+MODULE_PARM(irq, "1-4i");
+MODULE_PARM(dongle_id, "i");
+
+int init_module(void)
+{
+	return nsc_ircc_init();
+}
+
+void cleanup_module(void)
+{
+	nsc_ircc_cleanup();
+}
+#endif /* MODULE */
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/irda/old_belkin.c linux.15p9/drivers/net/irda/old_belkin.c
--- linux.vanilla/drivers/net/irda/old_belkin.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/net/irda/old_belkin.c	Tue Jan 18 01:08:18 2000
@@ -0,0 +1,178 @@
+/*********************************************************************
+ *                
+ * Filename:      old_belkin.c
+ * Version:       1.1
+ * Description:   Driver for the Belkin (old) SmartBeam dongle
+ * Status:        Experimental...
+ * Author:        Jean Tourrilhes <jt@hpl.hp.com>
+ * Created at:    22/11/99
+ * Modified at:   Fri Dec 17 09:13:32 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Jean Tourrilhes, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/tty.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/irda.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irda_device.h>
+
+/*
+ * Belkin is selling a dongle called the SmartBeam.
+ * In fact, there is two hardware version of this dongle, of course with
+ * the same name and looking the exactly same (grrr...).
+ * I guess that I've got the old one, because inside I don't have
+ * a jumper for IrDA/ASK...
+ *
+ * As far as I can make it from info on their web site, the old dongle 
+ * support only 9600 b/s, which make our life much simpler as far as
+ * the driver is concerned, but you might not like it very much ;-)
+ * The new SmartBeam does 115 kb/s, and I've not tested it...
+ *
+ * Belkin claim that the correct driver for the old dongle (in Windows)
+ * is the generic Parallax 9500a driver, but the Linux LiteLink driver
+ * fails for me (probably because Linux-IrDA doesn't rate fallback),
+ * so I created this really dumb driver...
+ *
+ * In fact, this driver doesn't do much. The only thing it does is to
+ * prevent Linux-IrDA to use any other speed than 9600 b/s ;-) This
+ * driver is called "old_belkin" so that when the new SmartBeam is supported
+ * its driver can be called "belkin" instead of "new_belkin".
+ *
+ * Note : this driver was written without any info/help from Belkin,
+ * so a lot of info here might be totally wrong. Blame me ;-)
+ */
+
+/* Let's guess */
+#define MIN_DELAY 25      /* 15 us, but wait a little more to be sure */
+
+static void old_belkin_open(dongle_t *self, struct qos_info *qos);
+static void old_belkin_close(dongle_t *self);
+static int  old_belkin_change_speed(struct irda_task *task);
+static int  old_belkin_reset(struct irda_task *task);
+
+/* These are the baudrates supported */
+/* static __u32 baud_rates[] = { 9600 }; */
+
+static struct dongle_reg dongle = {
+	Q_NULL,
+	IRDA_OLD_BELKIN_DONGLE,
+	old_belkin_open,
+	old_belkin_close,
+	old_belkin_reset,
+	old_belkin_change_speed,
+};
+
+int __init old_belkin_init(void)
+{
+	return irda_device_register_dongle(&dongle);
+}
+
+void old_belkin_cleanup(void)
+{
+	irda_device_unregister_dongle(&dongle);
+}
+
+static void old_belkin_open(dongle_t *self, struct qos_info *qos)
+{
+	/* Not too fast, please... */
+	qos->baud_rate.bits &= IR_9600;
+	/* Needs at least 10 ms (totally wild guess, can do probably better) */
+	qos->min_turn_time.bits = 0x01;
+
+	MOD_INC_USE_COUNT;
+}
+
+static void old_belkin_close(dongle_t *self)
+{
+	/* Power off dongle */
+	self->set_dtr_rts(self->dev, FALSE, FALSE);
+
+	MOD_DEC_USE_COUNT;
+}
+
+/*
+ * Function old_belkin_change_speed (task)
+ *
+ *    With only one speed available, not much to do...
+ */
+static int old_belkin_change_speed(struct irda_task *task)
+{
+	irda_task_next_state(task, IRDA_TASK_DONE);
+
+	return 0;
+}
+
+/*
+ * Function old_belkin_reset (task)
+ *
+ *      Reset the Old-Belkin type dongle.
+ *
+ */
+static int old_belkin_reset(struct irda_task *task)
+{
+	dongle_t *self = (dongle_t *) task->instance;
+
+	/* Power on dongle */
+	self->set_dtr_rts(self->dev, TRUE, TRUE);
+
+	/* Sleep a minimum of 15 us */
+	udelay(MIN_DELAY);
+
+	/* This dongles speed "defaults" to 9600 bps ;-) */
+	self->speed = 9600;
+
+	irda_task_next_state(task, IRDA_TASK_DONE);
+
+	return 0;
+}
+
+#ifdef MODULE
+MODULE_AUTHOR("Jean Tourrilhes <jt@hpl.hp.com>");
+MODULE_DESCRIPTION("Belkin (old) SmartBeam dongle driver");	
+
+/*
+ * Function init_module (void)
+ *
+ *    Initialize Old-Belkin module
+ *
+ */
+int init_module(void)
+{
+	return old_belkin_init();
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ *    Cleanup Old-Belkin module
+ *
+ */
+void cleanup_module(void)
+{
+	old_belkin_cleanup();
+}
+#endif /* MODULE */
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/irda/pc87108.c linux.15p9/drivers/net/irda/pc87108.c
--- linux.vanilla/drivers/net/irda/pc87108.c	Sat Aug 14 02:26:48 1999
+++ linux.15p9/drivers/net/irda/pc87108.c	Thu Jan  1 01:00:00 1970
@@ -1,1493 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      pc87108.c
- * Version:       0.8
- * Description:   FIR/MIR driver for the NS PC87108 chip
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Sat Nov  7 21:43:15 1998
- * Modified at:   Mon May 24 15:19:21 1999
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>
- *     Copyright (c) 1998 Lichen Wang, <lwang@actisys.com>
- *     Copyright (c) 1998 Actisys Corp., www.actisys.com
- *     All Rights Reserved
- *      
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
- *     the License, or (at your option) any later version.
- *  
- *     Neither Dag Brattli nor University of Tromsř admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
- *
- *     Notice that all functions that needs to access the chip in _any_
- *     way, must save BSR register on entry, and restore it on exit. 
- *     It is _very_ important to follow this policy!
- *
- *         __u8 bank;
- *     
- *         bank = inb( iobase+BSR);
- *  
- *         do_your_stuff_here();
- *
- *         outb( bank, iobase+BSR);
- *
- *    If you find bugs in this file, its very likely that the same bug
- *    will also be in w83977af_ir.c since the implementations is quite
- *    similar.
- *     
- ********************************************************************/
-
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/malloc.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/byteorder.h>
-
-#include <net/irda/wrapper.h>
-#include <net/irda/irda.h>
-#include <net/irda/irmod.h>
-#include <net/irda/irlap_frame.h>
-#include <net/irda/irda_device.h>
-
-#include <net/irda/pc87108.h>
-
-#define BROKEN_DONGLE_ID
-
-static char *driver_name = "pc87108";
-static int qos_mtt_bits = 0x07;  /* 1 ms or more */
-
-#define CHIP_IO_EXTENT 8
-
-static unsigned int io[]  = { 0x2f8, ~0, ~0, ~0 };
-static unsigned int io2[] = { 0x150, 0, 0, 0 };
-static unsigned int irq[] = { 3, 0, 0, 0 };
-static unsigned int dma[] = { 0, 0, 0, 0 };
-
-static struct pc87108 *dev_self[] = { NULL, NULL, NULL, NULL};
-
-static char *dongle_types[] = {
-	"Differential serial interface",
-	"Differential serial interface",
-	"Reserved",
-	"Reserved",
-	"Sharp RY5HD01",
-	"Reserved",
-	"Single-ended serial interface",
-	"Consumer-IR only",
-	"HP HSDL-2300, HP HSDL-3600/HSDL-3610",
-	"IBM31T1100 or Temic TFDS6000/TFDS6500",
-	"Reserved",
-	"Reserved",
-	"HP HSDL-1100/HSDL-2100",
-	"HP HSDL-1100/HSDL-2100"
-	"Supports SIR Mode only",
-	"No dongle connected",
-};
-
-/* Some prototypes */
-static int  pc87108_open(int i, unsigned int iobase, unsigned int board_addr, 
-			 unsigned int irq, unsigned int dma);
-#ifdef MODULE
-static int  pc87108_close(struct irda_device *idev);
-#endif /* MODULE */
-static int  pc87108_probe(int iobase, int board_addr, int irq, int dma);
-static void pc87108_pio_receive(struct irda_device *idev);
-static int  pc87108_dma_receive(struct irda_device *idev); 
-static int  pc87108_dma_receive_complete(struct irda_device *idev, int iobase);
-static int  pc87108_hard_xmit(struct sk_buff *skb, struct device *dev);
-static int  pc87108_pio_write(int iobase, __u8 *buf, int len, int fifo_size);
-static void pc87108_dma_write(struct irda_device *idev, int iobase);
-static void pc87108_change_speed(struct irda_device *idev, int baud);
-static void pc87108_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void pc87108_wait_until_sent(struct irda_device *idev);
-static int  pc87108_is_receiving(struct irda_device *idev);
-static int  pc87108_read_dongle_id (int iobase);
-static void pc87108_init_dongle_interface (int iobase, int dongle_id);
-
-static int  pc87108_net_init(struct device *dev);
-static int  pc87108_net_open(struct device *dev);
-static int  pc87108_net_close(struct device *dev);
-
-/*
- * Function pc87108_init ()
- *
- *    Initialize chip. Just try to find out how many chips we are dealing with
- *    and where they are
- */
-__initfunc(int pc87108_init(void))
-{
-	int i;
-
-	for (i=0; (io[i] < 2000) && (i < 4); i++) {
-		int ioaddr = io[i];
-		if (check_region(ioaddr, CHIP_IO_EXTENT) < 0)
-			continue;
-		if (pc87108_open(i, io[i], io2[i], irq[i], dma[i]) == 0)
-			return 0;
-	}
-	return -ENODEV;
-}
-
-/*
- * Function pc87108_cleanup ()
- *
- *    Close all configured chips
- *
- */
-#ifdef MODULE
-static void pc87108_cleanup(void)
-{
-	int i;
-
-        DEBUG(4, __FUNCTION__ "()\n");
-
-	for (i=0; i < 4; i++) {
-		if (dev_self[i])
-			pc87108_close(&(dev_self[i]->idev));
-	}
-}
-#endif /* MODULE */
-
-/*
- * Function pc87108_open (iobase, irq)
- *
- *    Open driver instance
- *
- */
-static int pc87108_open(int i, unsigned int iobase, unsigned int board_addr, 
-			unsigned int irq, unsigned int dma)
-{
-	struct pc87108 *self;
-	struct irda_device *idev;
-	int ret;
-	int dongle_id;
-
-	DEBUG(0, __FUNCTION__ "()\n");
-
-	if ((dongle_id = pc87108_probe(iobase, board_addr, irq, dma)) == -1)
-		return -1;
-
-	/*
-	 *  Allocate new instance of the driver
-	 */
-	self = kmalloc(sizeof(struct pc87108), GFP_KERNEL);
-	if (self == NULL) {
-		printk(KERN_ERR "IrDA: Can't allocate memory for "
-		       "IrDA control block!\n");
-		return -ENOMEM;
-	}
-	memset(self, 0, sizeof(struct pc87108));
-   
-	/* Need to store self somewhere */
-	dev_self[i] = self;
-
-	idev = &self->idev;
-
-	/* Initialize IO */
-	idev->io.iobase    = iobase;
-        idev->io.irq       = irq;
-        idev->io.io_ext    = CHIP_IO_EXTENT;
-        idev->io.dma       = dma;
-        idev->io.fifo_size = 32;
-
-	/* Lock the port that we need */
-	ret = check_region(idev->io.iobase, idev->io.io_ext);
-	if (ret < 0) { 
-		DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
-		      idev->io.iobase);
-		/* pc87108_cleanup( self->idev);  */
-		return -ENODEV;
-	}
-	request_region(idev->io.iobase, idev->io.io_ext, idev->name);
-
-	/* Initialize QoS for this device */
-	irda_init_max_qos_capabilies(&idev->qos);
-	
-	/* The only value we must override it the baudrate */
-	idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
-		IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
-	
-	idev->qos.min_turn_time.bits = qos_mtt_bits;
-	irda_qos_bits_to_value(&idev->qos);
-	
-	idev->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO|IFF_DONGLE;
-
-	/* Specify which buffer allocation policy we need */
-	idev->rx_buff.flags = GFP_KERNEL | GFP_DMA;
-	idev->tx_buff.flags = GFP_KERNEL | GFP_DMA;
-
-	/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
-	idev->rx_buff.truesize = 14384; 
-	idev->tx_buff.truesize = 4000;
-	
-	/* Initialize callbacks */
-	idev->change_speed    = pc87108_change_speed;
-	idev->wait_until_sent = pc87108_wait_until_sent;
-	idev->is_receiving    = pc87108_is_receiving;
-     
-	/* Override the network functions we need to use */
-	idev->netdev.init            = pc87108_net_init;
-	idev->netdev.hard_start_xmit = pc87108_hard_xmit;
-	idev->netdev.open            = pc87108_net_open;
-	idev->netdev.stop            = pc87108_net_close;
-
-	idev->io.dongle_id = dongle_id;
-	pc87108_init_dongle_interface(iobase, dongle_id);
-
-	/* Open the IrDA device */
-	irda_device_open(idev, driver_name, self);
-	
-	return 0;
-}
-
-#ifdef MODULE
-/*
- * Function pc87108_close (idev)
- *
- *    Close driver instance
- *
- */
-static int pc87108_close(struct irda_device *idev)
-{
-	struct pc87108 *self;
-	int iobase;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT(idev != NULL, return -1;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
-
-        iobase = idev->io.iobase;
-	self = (struct pc87108 *) idev->priv;
-
-	/* Release the PORT that this driver is using */
-	DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", idev->io.iobase);
-	release_region(idev->io.iobase, idev->io.io_ext);
-
-	irda_device_close(idev);
-
-	kfree(self);
-
-	return 0;
-}
-#endif /* MODULE */
-
-/*
- * Function pc87108_probe (iobase, board_addr, irq, dma)
- *
- *    Returns non-negative on success.
- *
- */
-static int pc87108_probe(int iobase, int board_addr, int irq, int dma) 
-{
-	int version;
-	__u8 temp=0;
-	int dongle_id;
-	
-	DEBUG(4, __FUNCTION__ "()\n");
-
-	/* Base Address and Interrupt Control Register BAIC */
-	outb(0, board_addr);
-	switch (iobase) {
-	case 0x3E8: outb(0x14, board_addr+1); break;
-	case 0x2E8: outb(0x15, board_addr+1); break;
-	case 0x3F8: outb(0x16, board_addr+1); break;
-	case 0x2F8: outb(0x17, board_addr+1); break;
-	default:    ERROR(__FUNCTION__ "(), invalid base_address");
-	}
-	
-	/* Control Signal Routing Register CSRT */
-	switch (irq) {
-	case 3:  temp = 0x01; break;
-	case 4:  temp = 0x02; break;
-	case 5:  temp = 0x03; break;
-	case 7:  temp = 0x04; break;
-	case 9:  temp = 0x05; break;
-	case 11: temp = 0x06; break;
-	case 15: temp = 0x07; break;
-	default: ERROR(__FUNCTION__ "(), invalid irq");
-	}
-	outb(1, board_addr);
-	
-	switch (dma) {	
-	case 0: outb(0x08+temp, board_addr+1); break;
-	case 1: outb(0x10+temp, board_addr+1); break;
-	case 3: outb(0x18+temp, board_addr+1); break;
-	default: DEBUG( 0, __FUNCTION__ "(), invalid dma");
-	}
-
-	/* Mode Control Register MCTL */
-	outb(2, board_addr);
-	outb(0x03, board_addr+1);
-		
-	/* read the Module ID */
-	switch_bank(iobase, BANK3);
-	version = inb(iobase+MID);
-	
-	/* should be 0x2? */
-	if (0x20 != (version & 0xf0)) {
-		ERROR(__FUNCTION__ "(), Wrong chip version %02x\n", version);
-		return -1;
-	}
-	
-	/* Switch to advanced mode */
-	switch_bank( iobase, BANK2);
-	outb(ECR1_EXT_SL, iobase+ECR1);
-	switch_bank(iobase, BANK0);
-
-	dongle_id = pc87108_read_dongle_id(iobase);
-	DEBUG(0, __FUNCTION__ "(), Found dongle: %s\n", 
-	      dongle_types[ dongle_id]);
-	
-	/* Set FIFO threshold to TX17, RX16, reset and enable FIFO's */
-	switch_bank(iobase, BANK0);	
-	outb(FCR_RXTH|FCR_TXTH|FCR_TXSR|FCR_RXSR|FCR_FIFO_EN, iobase+FCR);
-	
-	/* Set FIFO size to 32 */
-	switch_bank(iobase, BANK2);
-	outb(EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2);	
-
-	/* IRCR2: FEND_MD is set */
-	switch_bank(iobase, BANK5);
-	outb(0x2a, iobase+4);
-
-	/* Make sure that some defaults are OK */
-	switch_bank(iobase, BANK6);
-	outb(0x20, iobase+0); /* Set 32 bits FIR CRC */
-	outb(0x0a, iobase+1); /* Set MIR pulse width */
-	outb(0x0d, iobase+2); /* Set SIR pulse width */
-	outb(0x2a, iobase+4); /* Set beginning frag, and preamble length */
-
-	/* Receiver frame length */
-	switch_bank(iobase, BANK4);
-	outb(2048 & 0xff, iobase+6);
-	outb((2048 >> 8) & 0x1f, iobase+7);
-
-	/* Transmitter frame length */
-	outb(2048 & 0xff, iobase+4);
-	outb((2048 >> 8) & 0x1f, iobase+5);
-	
-	DEBUG(0, "PC87108 driver loaded. Version: 0x%02x\n", version);
-
-	/* Enable receive interrupts */
-	switch_bank(iobase, BANK0);
-	outb(IER_RXHDL_IE, iobase+IER);
-
-	return dongle_id;
-}
-
-/*
- * Function pc87108_read_dongle_id (void)
- *
- * Try to read dongle indentification. This procedure needs to be executed
- * once after power-on/reset. It also needs to be used whenever you suspect
- * that the user may have plugged/unplugged the IrDA Dongle.
- * 
- */
-static int pc87108_read_dongle_id ( int iobase)
-{
-	int dongle_id;
-	__u8 bank;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	bank = inb( iobase+BSR);
-
-	/* Select Bank 7 */
-	switch_bank(iobase, BANK7);
-	
-	/* IRCFG4: IRSL0_DS and IRSL21_DS are cleared */
-	outb(0x00, iobase+7);
-	
-	/* ID0, 1, and 2 are pulled up/down very slowly */
-	udelay(50);
-	
-	/* IRCFG1: read the ID bits */
-	dongle_id = inb( iobase+4) & 0x0f;
-
-#ifdef BROKEN_DONGLE_ID
-	if (dongle_id == 0x0a)
-		dongle_id = 0x09;
-#endif
-	
-	/* Go back to  bank 0 before returning */
-	switch_bank(iobase, BANK0);
-
-	DEBUG(0, __FUNCTION__ "(), Dongle = %#x\n", dongle_id);
-
-	outb(bank, iobase+BSR);
-
-	return dongle_id;
-}
-
-/*
- * Function pc87108_init_dongle_interface (iobase, dongle_id)
- *
- *     This function initializes the dongle for the transceiver that is
- *     used. This procedure needs to be executed once after
- *     power-on/reset. It also needs to be used whenever you suspect that
- *     the dongle is changed. 
- */
-static void pc87108_init_dongle_interface (int iobase, int dongle_id)
-{
-	int bank;
-
-	/* Save current bank */
-	bank = inb( iobase+BSR);
-
-	/* Select Bank 7 */
-	switch_bank( iobase, BANK7);
-	
-	/* IRCFG4: set according to dongle_id */
-	switch (dongle_id) {
-	case 0x00: /* same as */
-	case 0x01: /* Differential serial interface */
-		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
-		       dongle_types[dongle_id]); 
-		break;
-	case 0x02: /* same as */
-	case 0x03: /* Reserved */
-		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
-		       dongle_types[dongle_id]); 
-		break;
-	case 0x04: /* Sharp RY5HD01 */
-		DEBUG( 0, __FUNCTION__ "(), %s not supported yet\n",
-		       dongle_types[dongle_id]); 
-		break;
-	case 0x05: /* Reserved */
-		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet",
-		       dongle_types[dongle_id]); 
-		break;
-	case 0x06: /* Single-ended serial interface */
-		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
-		       dongle_types[dongle_id]); 
-		break;
-	case 0x07: /* Consumer-IR only */
-		DEBUG( 0, __FUNCTION__ "(), %s is not for IrDA mode\n",
-		       dongle_types[dongle_id]); 
-		break;
-	case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */
-		DEBUG( 0, __FUNCTION__ "(), %s not supported yet\n",
-		       dongle_types[dongle_id]); 
-		break;
-	case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */
-		outb_p( 0x28, iobase+7); /* Set irsl[0-2] as output */
-		break;
-	case 0x0A: /* same as */
-	case 0x0B: /* Reserved */
-		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
-		       dongle_types[dongle_id]); 
-		break;
-	case 0x0C: /* same as */
-	case 0x0D: /* HP HSDL-1100/HSDL-2100 */
-		/* 
-		 * Set irsl0 as input, irsl[1-2] as output, and separate 
-		 * inputs are used for SIR and MIR/FIR 
-		 */
-		outb( 0x48, iobase+7); 
-		break;
-	case 0x0E: /* Supports SIR Mode only */
-		outb( 0x28, iobase+7); /* Set irsl[0-2] as output */
-		break;
-	case 0x0F: /* No dongle connected */
-		DEBUG( 0, __FUNCTION__ "(), %s\n",
-		       dongle_types[dongle_id]); 
-		DEBUG( 0, "***\n");
-
-		switch_bank( iobase, BANK0);
-		outb( 0x62, iobase+MCR);
-		break;
-	default: 
-		DEBUG( 0, __FUNCTION__ "(), invalid dongle_id %#x", dongle_id);
-	}
-	
-	/* IRCFG1: IRSL1 and 2 are set to IrDA mode */
-	outb( 0x00, iobase+4);
-
-	/* Restore bank register */
-	outb( bank, iobase+BSR);
-	
-} /* set_up_dongle_interface */
-
-/*
- * Function pc87108_change_dongle_speed (iobase, speed, dongle_id)
- *
- *    Change speed of the attach dongle
- *
- */
-static void pc87108_change_dongle_speed( int iobase, int speed, int dongle_id)
-{
-	unsigned long flags;
-	__u8 bank;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	/* Save current bank */
-	bank = inb( iobase+BSR);
-
-	/* Select Bank 7 */
-	switch_bank( iobase, BANK7);
-	
-	/* IRCFG1: set according to dongle_id */
-	switch (dongle_id) {
-	case 0x00: /* same as */
-	case 0x01: /* Differential serial interface */
-		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
-		       dongle_types[dongle_id]); 
-		break;
-	case 0x02: /* same as */
-	case 0x03: /* Reserved */
-		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
-		       dongle_types[dongle_id]); 
-		break;
-	case 0x04: /* Sharp RY5HD01 */
-		DEBUG( 0, __FUNCTION__ "(), %s not supported yet\n",
-		       dongle_types[dongle_id]); 
-	case 0x05: /* Reserved */
-		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
-		       dongle_types[dongle_id]); 
-		break;
-	case 0x06: /* Single-ended serial interface */
-		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
-		       dongle_types[dongle_id]); 
-		break;
-	case 0x07: /* Consumer-IR only */
-		DEBUG( 0, __FUNCTION__ "(), %s is not for IrDA mode\n",
-		       dongle_types[dongle_id]); 
-		break;
-	case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */
-		DEBUG( 0, __FUNCTION__ "(), %s not supported yet\n",
-		       dongle_types[dongle_id]); 
-	case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */
-		switch_bank( iobase, BANK7);
-		outb_p( 0x01, iobase+4);
-
-		if ( speed == 4000000) {
-			save_flags(flags);
-			cli();
-			outb( 0x81, iobase+4);
-			outb( 0x80, iobase+4);
-			restore_flags(flags);
-		}
-		else
-			outb_p( 0x00, iobase+4);
-		break;
-	case 0x0A: /* same as */
-	case 0x0B: /* Reserved */
-		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
-		       dongle_types[dongle_id]); 
-		break;
-	case 0x0C: /* same as */
-	case 0x0D: /* HP HSDL-1100/HSDL-2100 */
-		break;
-	case 0x0E: /* Supports SIR Mode only */
-		break;
-	case 0x0F: /* No dongle connected */
-		DEBUG( 0, __FUNCTION__ "(), %s is not for IrDA mode\n",
-		       dongle_types[dongle_id]);
-
-		switch_bank( iobase, BANK0); 
-		outb( 0x62, iobase+MCR);
-		break;
-	default: 
-		DEBUG( 0, __FUNCTION__ "(), invalid data_rate\n");
-	}
-	/* Restore bank register */
-	outb( bank, iobase+BSR);
-}
-
-/*
- * Function pc87108_change_speed (idev, baud)
- *
- *    Change the speed of the device
- *
- */
-static void pc87108_change_speed( struct irda_device *idev, int speed)
-{
-	__u8 mcr = MCR_SIR;
-	__u8 bank;
-	int iobase; 
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( idev != NULL, return;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
-
-	iobase = idev->io.iobase;
-
-	/* Update accounting for new speed */
-	idev->io.baudrate = speed;
-
-	/* Save current bank */
-	bank = inb( iobase+BSR);
-
-	/* Disable interrupts */
-	switch_bank( iobase, BANK0);
-	outb( 0, iobase+IER);
-
-	  /* Select Bank 2 */
-	switch_bank( iobase, BANK2);
-
-	outb( 0x00, iobase+BGDH);
-	switch ( speed) {
-	case 9600:   outb( 0x0c, iobase+BGDL); break;
-	case 19200:  outb( 0x06, iobase+BGDL); break;
-	case 37600:  outb( 0x03, iobase+BGDL); break;
-	case 57600:  outb( 0x02, iobase+BGDL); break;
-	case 115200: outb( 0x01, iobase+BGDL); break;
-	case 576000:
-		switch_bank( iobase, BANK5);
-		
-		/* IRCR2: MDRS is set */
-		outb( inb( iobase+4) | 0x04, iobase+4);
-	       
-		mcr = MCR_MIR;
-		DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
-		break;
-	case 1152000:
-		mcr = MCR_MIR;
-		DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
-		break;
-	case 4000000:
-		mcr = MCR_FIR;
-		DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
-		break;
-	default:
-		mcr = MCR_FIR;
-		DEBUG( 0, __FUNCTION__ "(), unknown baud rate of %d\n", speed);
-		break;
-	}
-
-	/* Set appropriate speed mode */
-	switch_bank(iobase, BANK0);
-	outb(mcr | MCR_TX_DFR, iobase+MCR);
-
-	/* Give some hits to the transceiver */
-	pc87108_change_dongle_speed( iobase, speed, idev->io.dongle_id);
-
-	/* Set FIFO threshold to TX17, RX16 */
-	switch_bank( iobase, BANK0);
-	outb( FCR_RXTH|     /* Set Rx FIFO threshold */
-	      FCR_TXTH|     /* Set Tx FIFO threshold */
-	      FCR_TXSR|     /* Reset Tx FIFO */
-	      FCR_RXSR|     /* Reset Rx FIFO */
-	      FCR_FIFO_EN,  /* Enable FIFOs */
-	      iobase+FCR);
-	/* outb( 0xa7, iobase+FCR); */
-	
-	/* Set FIFO size to 32 */
-	switch_bank( iobase, BANK2);
-	outb( EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2);	
-	
-	idev->netdev.tbusy = 0;
-	
-	/* Enable some interrupts so we can receive frames */
-	switch_bank( iobase, BANK0); 
-	if ( speed > 115200) {
-		outb( IER_SFIF_IE, iobase+IER);
-		pc87108_dma_receive( idev);
-	} else
-		outb( IER_RXHDL_IE, iobase+IER);
-    	
-	/* Restore BSR */
-	outb( bank, iobase+BSR);
-}
-
-/*
- * Function pc87108_hard_xmit (skb, dev)
- *
- *    Transmit the frame!
- *
- */
-static int pc87108_hard_xmit( struct sk_buff *skb, struct device *dev)
-{
-	struct irda_device *idev;
-	int iobase;
-	__u8 bank;
-	int mtt;
-	
-	idev = (struct irda_device *) dev->priv;
-
-	ASSERT( idev != NULL, return 0;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
-
-	iobase = idev->io.iobase;
-
-	DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
-	
-	/* Lock transmit buffer */
-	if ( irda_lock( (void *) &dev->tbusy) == FALSE)
-		return -EBUSY;
-
-	/* Save current bank */
-	bank = inb( iobase+BSR);
-
-	/* Decide if we should use PIO or DMA transfer */
-	if ( idev->io.baudrate > 115200) {
-		idev->tx_buff.data = idev->tx_buff.head;
-		memcpy(idev->tx_buff.data, skb->data, skb->len);
-		idev->tx_buff.len = skb->len;
-
-		mtt = irda_get_mtt( skb);
-	        if ( mtt > 50) {
-			/* Adjust for timer resolution */
-			mtt = mtt / 125 + 1;
-
-			/* Setup timer */
-			switch_bank( iobase, BANK4);
-			outb( mtt & 0xff, iobase+TMRL);
-			outb(( mtt >> 8) & 0x0f, iobase+TMRH);
-			
-			/* Start timer */
-			outb( IRCR1_TMR_EN, iobase+IRCR1);
-			idev->io.direction = IO_XMIT;
-			
-			/* Enable timer interrupt */
-			switch_bank( iobase, BANK0);
-			outb( IER_TMR_IE, iobase+IER);
-		} else {
-			/* Use udelay for delays less than 50 us. */
-			if (mtt)
-				udelay( mtt);
-
-			/* Enable DMA interrupt */
-			switch_bank( iobase, BANK0);
-	 		outb( IER_DMA_IE, iobase+IER);
-	     		pc87108_dma_write( idev, iobase);
-		}
-        } else {
-	        idev->tx_buff.len = async_wrap_skb(skb, idev->tx_buff.data, 
-						   idev->tx_buff.truesize);
-		
-		idev->tx_buff.data = idev->tx_buff.head;
-		
-		/* Add interrupt on tx low level (will fire immediately) */
-		switch_bank( iobase, BANK0);
-		outb( IER_TXLDL_IE, iobase+IER);
-	}
-	dev_kfree_skb( skb);
-
-	/* Restore bank register */
-	outb( bank, iobase+BSR);
-
-	return 0;
-}
-
-/*
- * Function pc87108_dma_xmit (idev, iobase)
- *
- *    Transmit data using DMA
- *
- */
-static void pc87108_dma_write( struct irda_device *idev, int iobase)
-{
-	int bsr;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	/* Save current bank */
-	bsr = inb( iobase+BSR);
-
-	/* Disable DMA */
-	switch_bank(iobase, BANK0);
-	outb( inb( iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
-
-	setup_dma(idev->io.dma, idev->tx_buff.data, idev->tx_buff.len, 
-		  DMA_MODE_WRITE);
-	
-	idev->io.direction = IO_XMIT;
-	
-	/* Choose transmit DMA channel  */ 
-	switch_bank(iobase, BANK2);
-	outb( inb( iobase+ECR1) | ECR1_DMASWP|ECR1_DMANF|ECR1_EXT_SL, 
-	      iobase+ECR1);
-	
-	/* Enable DMA */
- 	switch_bank(iobase, BANK0);	
-	outb(inb(iobase+MCR)|MCR_DMA_EN, iobase+MCR);
-
-	/* Restore bank register */
-	outb(bsr, iobase+BSR);
-}
-
-/*
- * Function pc87108_pio_xmit (idev, iobase)
- *
- *    Transmit data using PIO. Returns the number of bytes that actually
- *    got transfered
- *
- */
-static int pc87108_pio_write(int iobase, __u8 *buf, int len, int fifo_size)
-{
-	int actual = 0;
-	__u8 bank;
-	
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	/* Save current bank */
-	bank = inb( iobase+BSR);
-
-	switch_bank( iobase, BANK0);
-	if (!(inb_p( iobase+LSR) & LSR_TXEMP)) {
-		DEBUG( 4, __FUNCTION__ "(), warning, FIFO not empty yet!\n");
-
-		fifo_size -= 17;
-		DEBUG( 4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size);
-	}
-
-	/* Fill FIFO with current frame */
-	while ((fifo_size-- > 0) && (actual < len)) {
-		/* Transmit next byte */
-		outb(buf[actual++], iobase+TXD);
-	}
-        
-	DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", 
-	      fifo_size, actual, len);
-
-	/* Restore bank */
-	outb(bank, iobase+BSR);
-
-	return actual;
-}
-
-/*
- * Function pc87108_dma_xmit_complete (idev)
- *
- *    The transfer of a frame in finished. This function will only be called 
- *    by the interrupt handler
- *
- */
-static void pc87108_dma_xmit_complete( struct irda_device *idev)
-{
-	int iobase;
-	__u8 bank;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( idev != NULL, return;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
-
-	iobase = idev->io.iobase;
-
-	/* Save current bank */
-	bank = inb( iobase+BSR);
-
-	/* Disable DMA */
-	switch_bank( iobase, BANK0);
-	outb( inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
-	
-	/* Check for underrrun! */
-	if ( inb( iobase+ASCR) & ASCR_TXUR) {
-		idev->stats.tx_errors++;
-		idev->stats.tx_fifo_errors++;
-		
-		/* Clear bit, by writing 1 into it */
-		outb( ASCR_TXUR, iobase+ASCR);
-	} else {
-		idev->stats.tx_packets++;
-		idev->stats.tx_bytes +=  idev->tx_buff.len;
-	}
-	
-	/* Unlock tx_buff and request another frame */
-	idev->netdev.tbusy = 0; /* Unlock */
-	idev->media_busy = FALSE;
-	
-	/* Tell the network layer, that we can accept more frames */
-	mark_bh( NET_BH);
-
-	/* Restore bank */
-	outb( bank, iobase+BSR);
-}
-
-/*
- * Function pc87108_dma_receive (idev)
- *
- *    Get ready for receiving a frame. The device will initiate a DMA
- *    if it starts to receive a frame.
- *
- */
-static int pc87108_dma_receive(struct irda_device *idev) 
-{
-	struct pc87108 *self;
-	int iobase;
-	__u8 bsr;
-
-	ASSERT(idev != NULL, return -1;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
-
-	DEBUG(4, __FUNCTION__ "\n");
-
-	self = idev->priv;
-	iobase = idev->io.iobase;
-
-	/* Save current bank */
-	bsr = inb(iobase+BSR);
-
-	/* Disable DMA */
-	switch_bank(iobase, BANK0);
-	outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
-
-	setup_dma(idev->io.dma, idev->rx_buff.data, 
-		  idev->rx_buff.truesize, DMA_MODE_READ);
-	
-	/* driver->media_busy = FALSE; */
-	idev->io.direction = IO_RECV;
-	idev->rx_buff.data = idev->rx_buff.head;
-
-	/* Reset Rx FIFO. This will also flush the ST_FIFO */
-	outb(FCR_RXTH|FCR_TXTH|FCR_RXSR|FCR_FIFO_EN, iobase+FCR);
-	self->st_fifo.len = self->st_fifo.tail = self->st_fifo.head = 0;
-
-	/* Choose DMA Rx, DMA Fairness, and Advanced mode */
-	switch_bank(iobase, BANK2);
-	outb((inb( iobase+ECR1) & ~ECR1_DMASWP)|ECR1_DMANF|ECR1_EXT_SL, 
-	     iobase+ECR1);
-	
-	/* enable DMA */
-	switch_bank(iobase, BANK0);
-	outb(inb(iobase+MCR)|MCR_DMA_EN, iobase+MCR);
-
-	/* Restore bank register */
-	outb(bsr, iobase+BSR);
-	
-	DEBUG(4, __FUNCTION__ "(), done!\n");	
-	
-	return 0;
-}
-
-/*
- * Function pc87108_dma_receive_complete (idev)
- *
- *    Finished with receiving frames
- *
- *    
- */
-static int pc87108_dma_receive_complete(struct irda_device *idev, int iobase)
-{
-	struct sk_buff *skb;
-	struct pc87108 *self;
-	struct st_fifo *st_fifo;
-	int len;
-	__u8 bank;
-	__u8 status;
-
-	self = idev->priv;
-	st_fifo = &self->st_fifo;
-
-	/* Save current bank */
-	bank = inb( iobase+BSR);
-	
-	/* Read status FIFO */
-	switch_bank(iobase, BANK5);
-	while (( status = inb( iobase+FRM_ST)) & FRM_ST_VLD) {
-		st_fifo->entries[ st_fifo->tail].status = status;
-
-		st_fifo->entries[ st_fifo->tail].len  = inb(iobase+RFLFL);
-		st_fifo->entries[ st_fifo->tail].len |= inb(iobase+RFLFH) << 8;
-		
-		st_fifo->tail++;
-		st_fifo->len++;
-	}
-	
-	/* Try to process all entries in status FIFO */
-	switch_bank(iobase, BANK0);
-	while (st_fifo->len) {
-      
-		/* Get first entry */
-		status = st_fifo->entries[st_fifo->head].status;
-		len    = st_fifo->entries[st_fifo->head].len;
-		st_fifo->head++;
-		st_fifo->len--;
-
-		/* Check for errors */
-		if (status & FRM_ST_ERR_MSK) {
-			if (status & FRM_ST_LOST_FR) {
-				/* Add number of lost frames to stats */
-				idev->stats.rx_errors += len;	
-			} else {
-				/* Skip frame */
-				idev->stats.rx_errors++;
-				
-				idev->rx_buff.data += len;
-			
-				if (status & FRM_ST_MAX_LEN)
-					idev->stats.rx_length_errors++;
-				
-				if (status & FRM_ST_PHY_ERR) 
-					idev->stats.rx_frame_errors++;
-				
-				if (status & FRM_ST_BAD_CRC) 
-					idev->stats.rx_crc_errors++;
-			}
-			/* The errors below can be reported in both cases */
-			if (status & FRM_ST_OVR1)
-				idev->stats.rx_fifo_errors++;
-			
-			if (status & FRM_ST_OVR2)
-				idev->stats.rx_fifo_errors++;
-			
-		} else {
-			/* Check if we have transfered all data to memory */
-			if (inb(iobase+LSR) & LSR_RXDA) {
-				/* Put this entry back in fifo */
-				st_fifo->head--;
-				st_fifo->len++;
-				st_fifo->entries[st_fifo->head].status = status;
-				st_fifo->entries[st_fifo->head].len = len;
-
-				/* Restore bank register */
-				outb(bank, iobase+BSR);
-			
-				return FALSE; 	/* I'll be back! */
-			}
-
-			/* Should be OK then */			
-			skb = dev_alloc_skb(len+1);
-			if (skb == NULL)  {
-				printk( KERN_INFO __FUNCTION__ 
-					"(), memory squeeze, dropping frame.\n");
-				/* Restore bank register */
-				outb( bank, iobase+BSR);
-
-				return FALSE;
-			}
-			
-			/* Make sure IP header gets aligned */
-			skb_reserve(skb, 1); 
-
-			/* Copy frame without CRC */
-			if (idev->io.baudrate < 4000000) {
-				skb_put(skb, len-2);
-				memcpy(skb->data, idev->rx_buff.data, len-2);
-			} else {
-				skb_put(skb, len-4);
-				memcpy(skb->data, idev->rx_buff.data, len-4);
-			}
-
-			/* Move to next frame */
-			idev->rx_buff.data += len;
-			idev->stats.rx_packets++;
-
-			skb->dev = &idev->netdev;
-			skb->mac.raw  = skb->data;
-			skb->protocol = htons(ETH_P_IRDA);
-			netif_rx( skb);
-		}
-	}
-	/* Restore bank register */
-	outb(bank, iobase+BSR);
-
-	return TRUE;
-}
-
-/*
- * Function pc87108_pio_receive (idev)
- *
- *    Receive all data in receiver FIFO
- *
- */
-static void pc87108_pio_receive( struct irda_device *idev) 
-{
-	__u8 byte = 0x00;
-	int iobase;
-
-	DEBUG(4, __FUNCTION__ "()\n");
-
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-	
-	iobase = idev->io.iobase;
-	
-	/*  Receive all characters in Rx FIFO */
-	do {
-		byte = inb(iobase+RXD);
-		async_unwrap_char(idev, byte);
-
-	} while (inb(iobase+LSR) & LSR_RXDA); /* Data available */	
-}
-
-/*
- * Function pc87108_sir_interrupt (idev, eir)
- *
- *    Handle SIR interrupt
- *
- */
-static __u8 pc87108_sir_interrupt(struct irda_device *idev, int eir)
-{
-	int actual;
-	__u8 new_ier = 0;
-
-	/* Transmit FIFO low on data */
-	if ( eir & EIR_TXLDL_EV) {
-		/* Write data left in transmit buffer */
-		actual = pc87108_pio_write(idev->io.iobase, 
-					   idev->tx_buff.data, 
-					   idev->tx_buff.len, 
-					   idev->io.fifo_size);
-		idev->tx_buff.data += actual;
-		idev->tx_buff.len  -= actual;
-		
-		idev->io.direction = IO_XMIT;
-
-		/* Check if finished */
-		if (idev->tx_buff.len > 0)
-			new_ier |= IER_TXLDL_IE;
-		else { 
-			idev->netdev.tbusy = 0; /* Unlock */
-			idev->stats.tx_packets++;
-			
-		        mark_bh(NET_BH);	
-
-			new_ier |= IER_TXEMP_IE;
-		}
-			
-	}
-	/* Check if transmission has completed */
-	if ( eir & EIR_TXEMP_EV) {
-		
-		/* Turn around and get ready to receive some data */
-		idev->io.direction = IO_RECV;
-		new_ier |= IER_RXHDL_IE;
-	}
-
-	/* Rx FIFO threshold or timeout */
-	if ( eir & EIR_RXHDL_EV) {
-		pc87108_pio_receive( idev);
-
-		/* Keep receiving */
-		new_ier |= IER_RXHDL_IE;
-	}
-	return new_ier;
-}
-
-/*
- * Function pc87108_fir_interrupt (idev, eir)
- *
- *    Handle MIR/FIR interrupt
- *
- */
-static __u8 pc87108_fir_interrupt( struct irda_device *idev, int iobase,
-				   int eir)
-{
-	__u8 new_ier = 0;
-	__u8 bank;
-
-	bank = inb( iobase+BSR);
-	
-	/* Status event, or end of frame detected in FIFO */
-	if (eir & (EIR_SFIF_EV|EIR_LS_EV)) {
-		if (pc87108_dma_receive_complete( idev, iobase)) {
-
-			/* Wait for next status FIFO interrupt */
-			new_ier |= IER_SFIF_IE;
-		} else {
-			/* DMA not finished yet */
-
-			/* Set timer value, resolution 125 us */
-			switch_bank( iobase, BANK4);
-			outb( 0x0f, iobase+TMRL); /* 125 us */
-			outb( 0x00, iobase+TMRH);
-
-			/* Start timer */
-			outb( IRCR1_TMR_EN, iobase+IRCR1);
-
-			new_ier |= IER_TMR_IE;
-		}
-	}
-	/* Timer finished */
-	if ( eir & EIR_TMR_EV) {
-		/* Disable timer */
-		switch_bank( iobase, BANK4);
-		outb( 0, iobase+IRCR1);
-
-		/* Clear timer event */
-		switch_bank(iobase, BANK0);
-		outb( ASCR_CTE, iobase+ASCR);
-
-		/* Check if this is a TX timer interrupt */
-		if ( idev->io.direction == IO_XMIT) {
-			pc87108_dma_write( idev, iobase);
-
-			/*  Interrupt on DMA */
-			new_ier |= IER_DMA_IE;
-		} else {
-			/* Check if DMA has now finished */
-			pc87108_dma_receive_complete( idev, iobase);
-
-			new_ier |= IER_SFIF_IE;
-		}
-	}	
-	/* Finished with transmission */
-	if ( eir & EIR_DMA_EV) {
-		pc87108_dma_xmit_complete( idev);
-		
-		/* Check if there are more frames to be transmitted */
-		if ( irda_device_txqueue_empty( idev)) {
-			/* Prepare for receive */
-			pc87108_dma_receive( idev);
-			
-			new_ier = IER_LS_IE|IER_SFIF_IE;
-		}
-	}
-	outb( bank, iobase+BSR);
-
-	return new_ier;
-}
-
-/*
- * Function pc87108_interrupt (irq, dev_id, regs)
- *
- *    An interrupt from the chip has arrived. Time to do some work
- *
- */
-static void pc87108_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	__u8 bsr, eir, ier;
-	int iobase;
-
-	struct irda_device *idev = (struct irda_device *) dev_id;
-
-	if (idev == NULL) {
-		printk( KERN_WARNING "%s: irq %d for unknown device.\n", 
-			driver_name, irq);
-		return;
-	}
-
-	idev->netdev.interrupt = 1;
-
-	iobase = idev->io.iobase;
-
-	/* Save current bank */
-	bsr = inb( iobase+BSR);
-
-	switch_bank( iobase, BANK0);	
-	ier = inb( iobase+IER); 
-	eir = inb( iobase+EIR) & ier; /* Mask out the interesting ones */ 
-
-	outb( 0, iobase+IER); /* Disable interrupts */
-	
-	if ( eir) {
-		/* Dispatch interrupt handler for the current speed */
-		if ( idev->io.baudrate > 115200)
-			ier = pc87108_fir_interrupt( idev, iobase, eir);
-		else
-			ier = pc87108_sir_interrupt( idev, eir);
-	}
-
-	outb( ier, iobase+IER);   /* Restore interrupts */
-	outb( bsr, iobase+BSR);   /* Restore bank register */
-
-	idev->netdev.interrupt = 0;
-}
-
-/*
- * Function pc87108_wait_until_sent (idev)
- *
- *    This function should put the current thread to sleep until all data 
- *    have been sent, so it is safe to f.eks. change the speed.
- */
-static void pc87108_wait_until_sent( struct irda_device *idev)
-{
-	/* Just delay 60 ms */
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(6);
-}
-
-/*
- * Function pc87108_is_receiving (idev)
- *
- *    Return TRUE is we are currently receiving a frame
- *
- */
-static int pc87108_is_receiving( struct irda_device *idev)
-{
-	int status = FALSE;
-	int iobase;
-	__u8 bank;
-
-	ASSERT( idev != NULL, return FALSE;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return FALSE;);
-
-	if ( idev->io.baudrate > 115200) {
-		iobase = idev->io.iobase;
-
-		/* Check if rx FIFO is not empty */
-		bank = inb( iobase+BSR);
-		switch_bank( iobase, BANK2);
-		if (( inb( iobase+RXFLV) & 0x3f) != 0) {
-			/* We are receiving something */
-			status =  TRUE;
-		}
-		outb( bank, iobase+BSR);
-	} else 
-		status = ( idev->rx_buff.state != OUTSIDE_FRAME);
-	
-	return status;
-}
-
-/*
- * Function pc87108_net_init (dev)
- *
- *    Initialize network device
- *
- */
-static int pc87108_net_init( struct device *dev)
-{
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	/* Setup to be a normal IrDA network device driver */
-	irda_device_setup( dev);
-
-	/* Insert overrides below this line! */
-
-	return 0;
-}
-
-
-/*
- * Function pc87108_net_open (dev)
- *
- *    Start the device
- *
- */
-static int pc87108_net_open( struct device *dev)
-{
-	struct irda_device *idev;
-	int iobase;
-	__u8 bank;
-	
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	ASSERT( dev != NULL, return -1;);
-	idev = (struct irda_device *) dev->priv;
-	
-	ASSERT( idev != NULL, return 0;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
-	
-	iobase = idev->io.iobase;
-
-	if (request_irq( idev->io.irq, pc87108_interrupt, 0, idev->name, 
-			 (void *) idev)) {
-		return -EAGAIN;
-	}
-	/*
-	 * Always allocate the DMA channel after the IRQ,
-	 * and clean up on failure.
-	 */
-	if (request_dma(idev->io.dma, idev->name)) {
-		free_irq( idev->io.irq, idev);
-		return -EAGAIN;
-	}
-		
-	/* Ready to play! */
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
-
-	/* Save current bank */
-	bank = inb( iobase+BSR);
-	
-	/* turn on interrupts */
-	switch_bank( iobase, BANK0);
-	outb( IER_LS_IE | IER_RXHDL_IE, iobase+IER);
-
-	/* Restore bank register */
-	outb( bank, iobase+BSR);
-
-	MOD_INC_USE_COUNT;
-
-	return 0;
-}
-
-/*
- * Function pc87108_net_close (dev)
- *
- *    Stop the device
- *
- */
-static int pc87108_net_close(struct device *dev)
-{
-	struct irda_device *idev;
-	int iobase;
-	__u8 bank;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	/* Stop device */
-	dev->tbusy = 1;
-	dev->start = 0;
-
-	ASSERT( dev != NULL, return -1;);
-	idev = (struct irda_device *) dev->priv;
-	
-	ASSERT( idev != NULL, return 0;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
-	
-	iobase = idev->io.iobase;
-
-	disable_dma( idev->io.dma);
-
-	/* Save current bank */
-	bank = inb( iobase+BSR);
-
-	/* Disable interrupts */
-	switch_bank( iobase, BANK0);
-	outb( 0, iobase+IER); 
-       
-	free_irq( idev->io.irq, idev);
-	free_dma( idev->io.dma);
-
-	/* Restore bank register */
-	outb( bank, iobase+BSR);
-
-	MOD_DEC_USE_COUNT;
-
-	return 0;
-}
-
-#ifdef MODULE
-
-MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
-MODULE_DESCRIPTION("NSC PC87108 IrDA Device Driver");
-
-MODULE_PARM(qos_mtt_bits, "i");
-MODULE_PARM(io, "1-4i");
-MODULE_PARM(io2, "1-4i");
-MODULE_PARM(irq, "1-4i");
-
-/*
- * Function init_module (void)
- *
- *    
- *
- */
-int init_module(void)
-{
-	return pc87108_init();
-}
-
-/*
- * Function cleanup_module (void)
- *
- *    
- *
- */
-void cleanup_module(void)
-{
-	pc87108_cleanup();
-}
-#endif /* MODULE */
-
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/irda/smc-ircc.c linux.15p9/drivers/net/irda/smc-ircc.c
--- linux.vanilla/drivers/net/irda/smc-ircc.c	Sat Aug 14 02:26:48 1999
+++ linux.15p9/drivers/net/irda/smc-ircc.c	Fri Jan 21 18:25:23 2000
@@ -1,26 +1,35 @@
 /*********************************************************************
  *                
  * Filename:      smc-ircc.c
- * Version:       0.1
- * Description:   Driver for the SMC Infrared Communications Controller (SMC)
+ * Version:       0.4
+ * Description:   Driver for the SMC Infrared Communications Controller
  * Status:        Experimental.
  * Author:        Thomas Davis (tadavis@jps.net)
  * Created at:    
- * Modified at:   Wed May 19 15:30:08 1999
+ * Modified at:   Fri Jan 21 09:41:08 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998-1999 Thomas Davis, All Rights Reserved.
+ *     Copyright (c) 1999-2000 Dag Brattli
+ *     Copyright (c) 1998-1999 Thomas Davis, 
+ *     All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
- *  
- *     I, Thomas Davis, admit no liability nor provide warranty for any
- *     of this software. This material is provided "AS-IS" and at no charge.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
  *
- *     Applicable Models : Fujitsu Lifebook 635t
- *			   Sony PCG-505TX (gets DMA wrong.)
+ *     SIO's: SMC FDC37N869, FDC37C669, FDC37N958
+ *     Applicable Models : Fujitsu Lifebook 635t, Sony PCG-505TX
  *
  ********************************************************************/
 
@@ -33,14 +42,18 @@
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/malloc.h>
-#include <linux/delay.h>
-#include <linux/init.h>
 #include <linux/init.h>
+#include <linux/rtnetlink.h>
+#include <linux/serial_reg.h>
 
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/byteorder.h>
 
+#ifdef CONFIG_APM
+#include <linux/apm_bios.h>
+#endif
+
 #include <net/irda/wrapper.h>
 #include <net/irda/irda.h>
 #include <net/irda/irmod.h>
@@ -54,46 +67,49 @@
 
 #define CHIP_IO_EXTENT 8
 
-static unsigned int io[]  = { 0x2e8, 0x140, ~0, ~0 };
-static unsigned int io2[] = { 0x2f8, 0x3e8, 0, 0};
+static unsigned int io[]  = { ~0, ~0 }; 
+static unsigned int io2[] = { 0, 0 };
 
-static struct ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL};
+static struct ircc_cb *dev_self[] = { NULL, NULL};
 
 /* Some prototypes */
-static int  ircc_open( int i, unsigned int iobase, unsigned int board_addr);
-static int  ircc_close( struct irda_device *idev);
-static int  ircc_probe( int iobase, int board_addr);
-static int  ircc_dma_receive( struct irda_device *idev); 
-static int  ircc_dma_receive_complete(struct irda_device *idev, int iobase);
-static int  ircc_hard_xmit( struct sk_buff *skb, struct device *dev);
-static void ircc_dma_write( struct irda_device *idev, int iobase);
-static void ircc_change_speed( struct irda_device *idev, int baud);
+static int  ircc_open(int i, unsigned int iobase, unsigned int board_addr);
+#ifdef MODULE
+static int  ircc_close(struct ircc_cb *self);
+#endif /* MODULE */
+static int  ircc_probe(int iobase, int board_addr);
+static int  ircc_probe_58(smc_chip_t *chip, chipio_t *info);
+static int  ircc_probe_69(smc_chip_t *chip, chipio_t *info);
+static int  ircc_dma_receive(struct ircc_cb *self, int iobase); 
+static void ircc_dma_receive_complete(struct ircc_cb *self, int iobase);
+static int  ircc_hard_xmit(struct sk_buff *skb, struct device *dev);
+static void ircc_dma_xmit(struct ircc_cb *self, int iobase, int bofs);
+static void ircc_change_speed(void *priv, __u32 speed);
 static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void ircc_wait_until_sent( struct irda_device *idev);
-static int  ircc_is_receiving( struct irda_device *idev);
+static int  ircc_is_receiving(struct ircc_cb *self);
 
-static int  ircc_net_init( struct device *dev);
-static int  ircc_net_open( struct device *dev);
-static int  ircc_net_close( struct device *dev);
+static int  ircc_net_open(struct device *dev);
+static int  ircc_net_close(struct device *dev);
+#ifdef CONFIG_APM
+static int  ircc_apmproc(apm_event_t event);
+#endif /* CONFIG_APM */
+
+/* These are the currently known SMC chipsets */
+static smc_chip_t chips[] =
+{
+	{ "FDC37C669", 0x55, 0x55, 0x0d, 0x04, ircc_probe_69 },
+	{ "FDC37N869", 0x55, 0x00, 0x0d, 0x29, ircc_probe_69 },
+	{ "FDC37N958", 0x55, 0x55, 0x20, 0x09, ircc_probe_58 },
+	{ NULL }
+};
 
-static int ircc_debug=3;
 static int ircc_irq=255;
 static int ircc_dma=255;
 
-static inline void register_bank(int port, int bank)
+static inline void register_bank(int iobase, int bank)
 {
-        outb(((inb(port+UART_MASTER) & 0xF0) | (bank & 0x07)),
-             port+UART_MASTER);
-}
-
-static inline unsigned int serial_in(int port, int offset)
-{
-        return inb(port+offset);
-}
-
-static inline void serial_out(int port, int offset, int value)
-{
-        outb(value, port+offset);
+        outb(((inb(iobase+IRCC_MASTER) & 0xf0) | (bank & 0x07)),
+               iobase+IRCC_MASTER);
 }
 
 /*
@@ -102,21 +118,40 @@
  *    Initialize chip. Just try to find out how many chips we are dealing with
  *    and where they are
  */
-__initfunc(int ircc_init(void))
+int __init ircc_init(void)
 {
+	static int smcreg[] = { 0x3f0, 0x370 };
+	smc_chip_t *chip;
+	chipio_t info;
+	int ret = -ENODEV;
 	int i;
 
-	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
-	for ( i=0; (io[i] < 2000) && (i < 4); i++) {
-		int ioaddr = io[i];
-		if (check_region(ioaddr, CHIP_IO_EXTENT))
-			continue;
-		if (ircc_open( i, io[i], io2[i]) == 0)
-			return 0;
-	}
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+	IRDA_DEBUG(0, __FUNCTION__ "\n");
 
-	return -ENODEV;
+	/* Probe for all the NSC chipsets we know about */
+	for (chip=chips; chip->name ; chip++,i++) {
+		for (i=0; i<2; i++) {
+			info.cfg_base = smcreg[i];
+			
+			/* 
+			 * First we check if the user has supplied any
+                         * parameters which we should use instead of probed
+			 * values
+			 */
+			if (io[i] < 2000) {
+				info.fir_base = io[i];
+				info.sir_base = io2[i];
+			} else if (chip->probe(chip, &info) < 0)
+				continue;
+			if (check_region(info.fir_base, CHIP_IO_EXTENT) < 0)
+				continue;
+			if (check_region(info.sir_base, CHIP_IO_EXTENT) < 0)
+				continue;
+			if (ircc_open(i, info.fir_base, info.sir_base) == 0)
+				ret = 0; 
+		}
+	}
+	return ret;
 }
 
 /*
@@ -130,13 +165,12 @@
 {
 	int i;
 
-	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(0, __FUNCTION__ "\n");
 
-	for ( i=0; i < 4; i++) {
-		if ( dev_self[i])
-			ircc_close( &(dev_self[i]->idev));
+	for (i=0; i < 2; i++) {
+		if (dev_self[i])
+			ircc_close(dev_self[i]);
 	}
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
 }
 #endif /* MODULE */
 
@@ -146,166 +180,270 @@
  *    Open driver instance
  *
  */
-static int ircc_open( int i, unsigned int iobase, unsigned int iobase2)
+static int ircc_open(int i, unsigned int fir_base, unsigned int sir_base)
 {
 	struct ircc_cb *self;
-	struct irda_device *idev;
-	int ret;
+        struct irport_cb *irport;
 	int config;
+	int ret;
 
-	DEBUG( ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(0, __FUNCTION__ "\n");
 
-	if ((config = ircc_probe( iobase, iobase2)) == -1) {
-	        DEBUG(ircc_debug, 
-		      __FUNCTION__ ": addr 0x%04x - no device found!\n", iobase);
+	if ((config = ircc_probe(fir_base, sir_base)) == -1) {
+	        IRDA_DEBUG(0, __FUNCTION__ 
+			   "(), addr 0x%04x - no device found!\n", fir_base);
 		return -1;
 	}
 	
 	/*
 	 *  Allocate new instance of the driver
 	 */
-	self = kmalloc( sizeof(struct ircc_cb), GFP_KERNEL);
-	if ( self == NULL) {
-		printk( KERN_ERR "IrDA: Can't allocate memory for "
-			"IrDA control block!\n");
+	self = kmalloc(sizeof(struct ircc_cb), GFP_KERNEL);
+	if (self == NULL) {
+		ERROR("%s, Can't allocate memory for control block!\n",
+                      driver_name);
 		return -ENOMEM;
 	}
 	memset(self, 0, sizeof(struct ircc_cb));
+	spin_lock_init(&self->lock);
    
 	/* Need to store self somewhere */
 	dev_self[i] = self;
 
-	idev = &self->idev;
+	irport = irport_open(i, sir_base, config >> 4 & 0x0f);
+	if (!irport)
+		return -ENODEV;
+
+	/* Steal the network device from irport */
+	self->netdev = irport->netdev;
+	self->irport = irport;
+	irport->priv = self;
 
 	/* Initialize IO */
-	idev->io.iobase    = iobase;
-        idev->io.iobase2   = iobase2; /* Used by irport */
-        idev->io.irq       = config >> 4 & 0x0f;
+	self->io.fir_base  = fir_base;
+        self->io.sir_base  = sir_base; /* Used by irport */
+        self->io.irq       = config >> 4 & 0x0f;
 	if (ircc_irq < 255) {
-	        printk(KERN_INFO "smc: Overriding IRQ - chip says %d, using %d\n",
-		      idev->io.irq, ircc_irq);
-		idev->io.irq = ircc_irq;
-	}
-        idev->io.io_ext    = CHIP_IO_EXTENT;
-        idev->io.io_ext2   = 8;       /* Used by irport */
-        idev->io.dma       = config & 0x0f;
+	        MESSAGE("%s, Overriding IRQ - chip says %d, using %d\n",
+			driver_name, self->io.irq, ircc_irq);
+		self->io.irq = ircc_irq;
+	}
+        self->io.fir_ext   = CHIP_IO_EXTENT;
+        self->io.sir_ext   = 8;       /* Used by irport */
+        self->io.dma       = config & 0x0f;
 	if (ircc_dma < 255) {
-	        printk(KERN_INFO "smc: Overriding DMA - chip says %d, using %d\n",
-		      idev->io.dma, ircc_dma);
-		idev->io.dma = ircc_dma;
+	        MESSAGE("%s, Overriding DMA - chip says %d, using %d\n",
+			driver_name, self->io.dma, ircc_dma);
+		self->io.dma = ircc_dma;
 	}
-        idev->io.fifo_size = 16;
 
 	/* Lock the port that we need */
-	ret = check_region( idev->io.iobase, idev->io.io_ext);
-	if ( ret < 0) { 
-		DEBUG( 0, __FUNCTION__ ": can't get iobase of 0x%03x\n",
-		       idev->io.iobase);
-		/* ircc_cleanup( self->idev);  */
+	ret = check_region(self->io.fir_base, self->io.fir_ext);
+	if (ret < 0) { 
+		IRDA_DEBUG(0, __FUNCTION__ ": can't get fir_base of 0x%03x\n",
+			   self->io.fir_base);
+                kfree(self);
 		return -ENODEV;
 	}
-	ret = check_region( idev->io.iobase2, idev->io.io_ext2);
-	if ( ret < 0) { 
-		DEBUG( 0, __FUNCTION__ ": can't get iobase of 0x%03x\n",
-		       idev->io.iobase2);
-		/* ircc_cleanup( self->idev);  */
-		return -ENODEV;
-	}
-	request_region( idev->io.iobase, idev->io.io_ext, idev->name);
-        request_region( idev->io.iobase2, idev->io.io_ext2, idev->name);
+	request_region(self->io.fir_base, self->io.fir_ext, driver_name);
 
 	/* Initialize QoS for this device */
-	irda_init_max_qos_capabilies( &idev->qos);
+	irda_init_max_qos_capabilies(&irport->qos);
 	
-#if 1
 	/* The only value we must override it the baudrate */
-	idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+	irport->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
 		IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
-#else
-	/* The only value we must override it the baudrate */
-	idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
-		IR_115200;
-#endif
 
-	idev->qos.min_turn_time.bits = 0x07;
-	irda_qos_bits_to_value( &idev->qos);
+	irport->qos.min_turn_time.bits = 0x07;
+	irda_qos_bits_to_value(&irport->qos);
 
-	idev->flags = IFF_FIR|IFF_SIR|IFF_DMA|IFF_PIO;
+	irport->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO;
 	
-	/* Specify which buffer allocation policy we need */
-	idev->rx_buff.flags = GFP_KERNEL | GFP_DMA;
-	idev->tx_buff.flags = GFP_KERNEL | GFP_DMA;
-
 	/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
-	idev->rx_buff.truesize = 4000; 
-	idev->tx_buff.truesize = 4000;
+	self->rx_buff.truesize = 4000; 
+	self->tx_buff.truesize = 4000;
+
+	self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
+					      GFP_KERNEL|GFP_DMA);
+	if (self->rx_buff.head == NULL)
+		return -ENOMEM;
+	memset(self->rx_buff.head, 0, self->rx_buff.truesize);
 	
-	/* Initialize callbacks */
-	idev->change_speed    = ircc_change_speed;
-	idev->wait_until_sent = ircc_wait_until_sent;
-	idev->is_receiving    = ircc_is_receiving;
-     
-	/* Override the network functions we need to use */
-	idev->netdev.init            = ircc_net_init;
-	idev->netdev.hard_start_xmit = ircc_hard_xmit;
-	idev->netdev.open            = ircc_net_open;
-	idev->netdev.stop            = ircc_net_close;
+	self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
+					      GFP_KERNEL|GFP_DMA);
+	if (self->tx_buff.head == NULL) {
+		kfree(self->rx_buff.head);
+		return -ENOMEM;
+	}
+	memset(self->tx_buff.head, 0, self->tx_buff.truesize);
 
-	irport_start(idev, iobase2);
+	self->rx_buff.in_frame = FALSE;
+	self->rx_buff.state = OUTSIDE_FRAME;
+	self->tx_buff.data = self->tx_buff.head;
+	self->rx_buff.data = self->rx_buff.head;
+	
+	/* Override the speed change function, since we must control it now */
+	irport->change_speed = &ircc_change_speed;
+	irport->interrupt    = &ircc_interrupt;
+	self->netdev->open   = &ircc_net_open;
+	self->netdev->stop   = &ircc_net_close;
+
+	irport_start(self->irport);
 
-	/* Open the IrDA device */
-	irda_device_open( idev, driver_name, self);
-	
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
 	return 0;
 }
 
 /*
- * Function ircc_close (idev)
+ * Function ircc_close (self)
  *
  *    Close driver instance
  *
  */
-static int ircc_close( struct irda_device *idev)
+#ifdef MODULE
+static int ircc_close(struct ircc_cb *self)
 {
 	int iobase;
 
-	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(0, __FUNCTION__ "\n");
 
-	ASSERT( idev != NULL, return -1;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+	ASSERT(self != NULL, return -1;);
 
-        iobase = idev->io.iobase;
+        iobase = self->io.fir_base;
 
-	irport_stop(idev, idev->io.iobase2);
+	irport_close(self->irport);
 
+	/* Stop interrupts */
 	register_bank(iobase, 0);
-	serial_out(iobase, UART_IER, 0);
-	serial_out(iobase, UART_MASTER, UART_MASTER_RESET);
-
+	outb(0, iobase+IRCC_IER);
+	outb(IRCC_MASTER_RESET, iobase+IRCC_MASTER);
+	outb(0x00, iobase+IRCC_MASTER);
+#if 0
+	/* Reset to SIR mode */
 	register_bank(iobase, 1);
-
-        serial_out(iobase, UART_SCE_CFGA, 
-		   UART_CFGA_IRDA_SIR_A | UART_CFGA_TX_POLARITY);
-        serial_out(iobase, UART_SCE_CFGB, UART_CFGB_IR);
- 
+        outb(IRCC_CFGA_IRDA_SIR_A|IRCC_CFGA_TX_POLARITY, iobase+IRCC_SCE_CFGA);
+        outb(IRCC_CFGB_IR, iobase+IRCC_SCE_CFGB);
+#endif
 	/* Release the PORT that this driver is using */
-	DEBUG( ircc_debug, 
-	       __FUNCTION__ ": releasing 0x%03x\n", idev->io.iobase);
+	IRDA_DEBUG(0, __FUNCTION__ "(), releasing 0x%03x\n", 
+		   self->io.fir_base);
 
-	release_region( idev->io.iobase, idev->io.io_ext);
+	release_region(self->io.fir_base, self->io.fir_ext);
 
-	if ( idev->io.iobase2) {
-		DEBUG( ircc_debug, __FUNCTION__ ": releasing 0x%03x\n", 
-		       idev->io.iobase2);
-		release_region( idev->io.iobase2, idev->io.io_ext2);
-	}
+	if (self->tx_buff.head)
+		kfree(self->tx_buff.head);
+	
+	if (self->rx_buff.head)
+		kfree(self->rx_buff.head);
 
-	irda_device_close( idev);
+	kfree(self);
 
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
 	return 0;
 }
+#endif /* MODULE */
+
+/*
+ * Function ircc_probe_69 (chip, info)
+ *
+ *    Probes for the SMC FDC37C669 and FDC37N869
+ *
+ */
+static int ircc_probe_69(smc_chip_t *chip, chipio_t *info)
+{
+	int cfg_base = info->cfg_base;
+	__u8 devid, mode;
+	int ret = -ENODEV;
+	int fir_io;
+	
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	/* Enter configuration */
+	outb(chip->entr1, cfg_base);
+	outb(chip->entr2, cfg_base);
+	
+	outb(chip->cid_index, cfg_base);
+	devid = inb(cfg_base+1);
+	IRDA_DEBUG(0, __FUNCTION__ "(), devid=0x%02x\n",devid);
+	
+	/* Check for expected device ID; are there others? */
+	if (devid == chip->cid_value) {
+		outb(0x0c, cfg_base);
+		mode = inb(cfg_base+1);
+		mode = (mode & 0x38) >> 3;
+		
+		/* Value for IR port */
+		if (mode && mode < 4) {
+			/* SIR iobase */
+			outb(0x25, cfg_base);
+			info->sir_base = inb(cfg_base+1) << 2;
+
+		       	/* FIR iobase */
+			outb(0x2b, cfg_base);
+			fir_io = inb(cfg_base+1) << 3;
+			if (fir_io) {
+				ret = 0;
+				info->fir_base = fir_io;
+			}
+		}
+	}
+	
+	/* Exit configuration */
+	outb(0xaa, cfg_base);
+
+	return ret;
+}
+
+/*
+ * Function ircc_probe_58 (chip, info)
+ *
+ *    Probes for the SMC FDC37N958
+ *
+ */
+static int ircc_probe_58(smc_chip_t *chip, chipio_t *info)
+{
+	int cfg_base = info->cfg_base;
+	__u8 devid;
+	int ret = -ENODEV;
+	int fir_io;
+	
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	/* Enter configuration */
+	outb(chip->entr1, cfg_base);
+	outb(chip->entr2, cfg_base);
+	
+	outb(chip->cid_index, cfg_base);
+	devid = inb(cfg_base+1);
+	IRDA_DEBUG(0, __FUNCTION__ "(), devid=0x%02x\n",devid);
+	
+	/* Check for expected device ID; are there others? */
+	if (devid == chip->cid_value) {
+		/* Select logical device (UART2) */
+		outb(0x07, cfg_base);
+		outb(0x05, cfg_base + 1);
+		
+		/* SIR iobase */
+		outb(0x60, cfg_base);
+		info->sir_base = inb(cfg_base + 1) << 8;
+		outb(0x61, cfg_base);
+		info->sir_base |= inb(cfg_base + 1);
+		
+		/* Read FIR base */
+		outb(0x62, cfg_base);
+		fir_io = inb(cfg_base + 1) << 8;
+		outb(0x63, cfg_base);
+		fir_io |= inb(cfg_base + 1);
+		outb(0x2b, cfg_base);
+		if (fir_io) {
+			ret = 0;
+			info->fir_base = fir_io;
+		}
+	}
+	
+	/* Exit configuration */
+	outb(0xaa, cfg_base);
+
+	return ret;
+}
 
 /*
  * Function ircc_probe (iobase, board_addr, irq, dma)
@@ -313,135 +451,144 @@
  *    Returns non-negative on success.
  *
  */
-static int ircc_probe( int iobase, int iobase2) 
+static int ircc_probe(int fir_base, int sir_base) 
 {
-	int version = 1;
 	int low, high, chip, config, dma, irq;
-	
-	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	int iobase = fir_base;
+	int version = 1;
 
-	register_bank(iobase, 3);
-	high = serial_in(iobase, UART_ID_HIGH);
-	low = serial_in(iobase, UART_ID_LOW);
-	chip = serial_in(iobase, UART_CHIP_ID);
-	version = serial_in(iobase, UART_VERSION);
-	config = serial_in(iobase, UART_INTERFACE);
-	irq = config >> 4 & 0x0f;
-	dma = config & 0x0f;
-
-	if (high == 0x10 && low == 0xb8 && chip == 0xf1) {
-		DEBUG(0, "SMC IrDA Controller found; version = %d, "
-		      "port 0x%04x, dma %d, interrupt %d\n",
-		      version, iobase, dma, irq);
-	} else {
-		return -1;
-	}
+	IRDA_DEBUG(0, __FUNCTION__ "\n");
 
-	serial_out(iobase, UART_MASTER, 0);
+	register_bank(iobase, 3);
+	high    = inb(iobase+IRCC_ID_HIGH);
+	low     = inb(iobase+IRCC_ID_LOW);
+	chip    = inb(iobase+IRCC_CHIP_ID);
+	version = inb(iobase+IRCC_VERSION);
+	config  = inb(iobase+IRCC_INTERFACE);
+	irq     = config >> 4 & 0x0f;
+	dma     = config & 0x0f;
+
+        if (high == 0x10 && low == 0xb8 && (chip == 0xf1 || chip == 0xf2)) { 
+                MESSAGE("SMC IrDA Controller found; IrCC version %d.%d, "
+			"port 0x%03x, dma=%d, irq=%d\n",
+			chip & 0x0f, version, iobase, dma, irq);
+	} else
+		return -ENODEV;
 
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+	/* Power on device */
+	outb(0x00, iobase+IRCC_MASTER);
 
 	return config;
 }
 
 /*
- * Function ircc_change_speed (idev, baud)
+ * Function ircc_change_speed (self, baud)
  *
  *    Change the speed of the device
  *
  */
-static void ircc_change_speed( struct irda_device *idev, int speed)
+static void ircc_change_speed(void *priv, __u32 speed)
 {
-	struct ircc_cb *self;
-	int iobase, ir_mode, select, fast; 
+	int iobase, ir_mode, ctrl, fast; 
+	struct ircc_cb *self = (struct ircc_cb *) priv;
+	struct device *dev;
 
-	DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(0, __FUNCTION__ "\n");
 
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+	ASSERT(self != NULL, return;);
 
-	self = idev->priv;
-	iobase = idev->io.iobase;
+	dev = self->netdev;
+	iobase = self->io.fir_base;
 
 	/* Update accounting for new speed */
-	idev->io.baudrate = speed;
+	self->io.speed = speed;
 
-	switch ( speed) {
+	outb(IRCC_MASTER_RESET, iobase+IRCC_MASTER);
+	outb(0x00, iobase+IRCC_MASTER);
+
+	switch (speed) {
 	case 9600:
 	case 19200:
-	case 37600:
+	case 38400:
 	case 57600:
-	case 115200:
-	        DEBUG(ircc_debug+1, 
-		      __FUNCTION__ ": using irport to change speed to %d\n",
-		      speed);
-		register_bank(iobase, 0);
-		serial_out(iobase, UART_IER, 0);
-		serial_out(iobase, UART_MASTER, UART_MASTER_RESET);
-		serial_out(iobase, UART_MASTER, UART_MASTER_INT_EN);
-		irport_start(idev, idev->io.iobase2);
-		irport_change_speed( idev, speed);
-		return;
+	case 115200:		
+		ir_mode = IRCC_CFGA_IRDA_SIR_A;
+		ctrl = 0;
+		fast = 0;
 		break;
-
 	case 576000:		
-		ir_mode = UART_CFGA_IRDA_HDLC;
-		select = 0;
+		ir_mode = IRCC_CFGA_IRDA_HDLC;
+		ctrl = IRCC_CRC;
 		fast = 0;
-		DEBUG( ircc_debug, __FUNCTION__ ": handling baud of 576000\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
 		break;
 	case 1152000:
-		ir_mode = UART_CFGA_IRDA_HDLC;
-		select = UART_1152;
+		ir_mode = IRCC_CFGA_IRDA_HDLC;
+		ctrl = IRCC_1152 | IRCC_CRC;
 		fast = 0;
-		DEBUG(ircc_debug, __FUNCTION__ ": handling baud of 1152000\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
 		break;
 	case 4000000:
-		ir_mode = UART_CFGA_IRDA_4PPM;
-		select = 0;
-		fast = UART_LCR_A_FAST;
-		DEBUG(ircc_debug, __FUNCTION__ ": handling baud of 4000000\n");
+		ir_mode = IRCC_CFGA_IRDA_4PPM;
+		ctrl = IRCC_CRC;
+		fast = IRCC_LCR_A_FAST;
+		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ ": unknown baud rate of %d\n", speed);
+		IRDA_DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", 
+			   speed);
 		return;
 	}
-
-#if 0
-	serial_out(idev->io.iobase2, 4, 0x08);
-#endif
-
-	serial_out(iobase, UART_MASTER, UART_MASTER_RESET);
-
-	register_bank(iobase, 0);
-	serial_out(iobase, UART_IER, 0);
-	
-       	irport_stop(idev, idev->io.iobase2);
-
-	idev->netdev.tbusy = 0;
 	
-	register_bank(iobase, 1);
+	register_bank(iobase, 0);
+	outb(0, iobase+IRCC_IER);
+	outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER);
 
-	serial_out(iobase, UART_SCE_CFGA, 
-		   ((serial_in(iobase, UART_SCE_CFGA) & 0x87) | ir_mode));
+	/* Make special FIR init if necessary */
+	if (speed > 115200) {
+		irport_stop(self->irport);
+
+		/* Install FIR transmit handler */
+		dev->hard_start_xmit = &ircc_hard_xmit;
+
+		/* 
+		 * Don't know why we have to do this, but FIR interrupts 
+		 * stops working if we remove it.
+		 */
+		/* outb(UART_MCR_OUT2, self->io.sir_base + UART_MCR); */
 
-	serial_out(iobase, UART_SCE_CFGB,
-		   ((serial_in(iobase, UART_SCE_CFGB) & 0x3f) | UART_CFGB_IR));
+		/* Be ready for incomming frames */
+		ircc_dma_receive(self, iobase);
+	} else {
+		/* Install SIR transmit handler */
+		dev->hard_start_xmit = &irport_hard_xmit;
+		irport_start(self->irport);
+		
+	        IRDA_DEBUG(0, __FUNCTION__ 
+			   "(), using irport to change speed to %d\n", speed);
+		irport_change_speed(self->irport, speed);
+	}	
+	dev->tbusy = 0;
 
-	(void) serial_in(iobase, UART_FIFO_THRESHOLD);
-	serial_out(iobase, UART_FIFO_THRESHOLD, 64);
+	register_bank(iobase, 1);
+	outb(((inb(iobase+IRCC_SCE_CFGA) & 0x87) | ir_mode), 
+	     iobase+IRCC_SCE_CFGA);
 
+#ifdef SMC_669 /* Uses pin 88/89 for Rx/Tx */
+	outb(((inb(iobase+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_COM), 
+	     iobase+IRCC_SCE_CFGB);
+#else	
+	outb(((inb(iobase+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_IR),
+	     iobase+IRCC_SCE_CFGB);
+#endif	
+	(void) inb(iobase+IRCC_FIFO_THRESHOLD);
+	outb(64, iobase+IRCC_FIFO_THRESHOLD);
+	
 	register_bank(iobase, 4);
-
-	serial_out(iobase, UART_CONTROL,
-		   (serial_in(iobase, UART_CONTROL) & 0x30) 
-		   | select | UART_CRC );
-
+	outb((inb(iobase+IRCC_CONTROL) & 0x30) | ctrl, iobase+IRCC_CONTROL);
+	
 	register_bank(iobase, 0);
-
-	serial_out(iobase, UART_LCR_A, fast);
-
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+	outb(fast, iobase+IRCC_LCR_A);
 }
 
 /*
@@ -450,271 +597,252 @@
  *    Transmit the frame!
  *
  */
-static int ircc_hard_xmit( struct sk_buff *skb, struct device *dev)
+static int ircc_hard_xmit(struct sk_buff *skb, struct device *dev)
 {
-	struct irda_device *idev;
+	struct irport_cb *irport;
+	struct ircc_cb *self;
+	unsigned long flags;
+	__u32 speed;
 	int iobase;
 	int mtt;
 
-	DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
-	idev = (struct irda_device *) dev->priv;
-
-	ASSERT( idev != NULL, return 0;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+	irport = (struct irport_cb *) dev->priv;
+	self = (struct ircc_cb *) irport->priv;
+	ASSERT(self != NULL, return 0;);
 
-	iobase = idev->io.iobase;
+	iobase = self->io.fir_base;
 
-	DEBUG(ircc_debug+1, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
+	spin_lock_irqsave(&self->lock, flags);
 
-	/* Use irport for SIR speeds */
-	if (idev->io.baudrate <= 115200) {
-		DEBUG(ircc_debug+1, __FUNCTION__ ": calling irport_hard_xmit\n");
-		return irport_hard_xmit(skb, dev);
-	}
+	/* Check if we need to change the speed after this frame */
+	if ((speed = irda_get_speed(skb)) != self->io.speed)
+		self->new_speed = speed;
 	
-	DEBUG(ircc_debug, __FUNCTION__ ": using dma; len=%d\n", skb->len);
-
 	/* Lock transmit buffer */
 	if (irda_lock((void *) &dev->tbusy) == FALSE)
 		return -EBUSY;
 
-	memcpy( idev->tx_buff.head, skb->data, skb->len);
-
-	/* Make sure that the length is a multiple of 16 bits */
-	if ( skb->len & 0x01)
-		skb->len++;
+	memcpy(self->tx_buff.head, skb->data, skb->len);
 
-	idev->tx_buff.len = skb->len;
-	idev->tx_buff.data = idev->tx_buff.head;
-#if 0
-	idev->tx_buff.offset = 0;
-#endif
-	
-	mtt = irda_get_mtt( skb);
-	
-	/* Use udelay for delays less than 50 us. */
-	if (mtt)
-		udelay( mtt);
+	self->tx_buff.len = skb->len;
+	self->tx_buff.data = self->tx_buff.head;
 	
-	ircc_dma_write( idev, iobase);
+	mtt = irda_get_mtt(skb);	
+	if (mtt) {
+		int bofs;
+
+		/* 
+		 * Compute who many BOFS (STA or PA's) we need to waste the
+		 * min turn time given the speed of the link.
+		 */
+		bofs = mtt * (self->io.speed / 1000) / 8000;
+		if (bofs > 4095)
+			bofs = 4095;
+
+		ircc_dma_xmit(self, iobase, bofs);
+	} else {
+		/* Transmit frame */
+		ircc_dma_xmit(self, iobase, 0);
+	}
 	
-	dev_kfree_skb( skb);
+	spin_unlock_irqrestore(&self->lock, flags);
+	dev_kfree_skb(skb);
 
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
 	return 0;
 }
 
 /*
- * Function ircc_dma_xmit (idev, iobase)
+ * Function ircc_dma_xmit (self, iobase)
  *
  *    Transmit data using DMA
  *
  */
-static void ircc_dma_write( struct irda_device *idev, int iobase)
+static void ircc_dma_xmit(struct ircc_cb *self, int iobase, int bofs)
 {
-	struct ircc_cb *self;
+	__u8 ctrl;
 
-	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
-
-	ASSERT( idev != NULL, return;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
-
-	self = idev->priv;
-	iobase = idev->io.iobase;
-
-	setup_dma( idev->io.dma, idev->tx_buff.data, idev->tx_buff.len, 
-		   DMA_MODE_WRITE);
-	
-	idev->io.direction = IO_XMIT;
+	IRDA_DEBUG(2, __FUNCTION__ "\n");
+#if 0	
+	/* Disable Rx */
+	register_bank(iobase, 0);
+	outb(0x00, iobase+IRCC_LCR_B);
+#endif
+	register_bank(iobase, 1);
+	outb(inb(iobase+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE, 
+	     iobase+IRCC_SCE_CFGB);
 
-	serial_out(idev->io.iobase2, 4, 0x08);
+	self->io.direction = IO_XMIT;
 
+	/* Set BOF additional count for generating the min turn time */
 	register_bank(iobase, 4);
-	serial_out(iobase, UART_CONTROL, 
-		   (serial_in(iobase, UART_CONTROL) & 0xF0));
-
-	serial_out(iobase, UART_BOF_COUNT_LO, 2);
-	serial_out(iobase, UART_BRICKWALL_CNT_LO, 0);
-#if 1
-	serial_out(iobase, UART_BRICKWALL_TX_CNT_HI, idev->tx_buff.len >> 8);
-	serial_out(iobase, UART_TX_SIZE_LO, idev->tx_buff.len & 0xff);
-#else
-	serial_out(iobase, UART_BRICKWALL_TX_CNT_HI, 0);
-	serial_out(iobase, UART_TX_SIZE_LO, 0);
-#endif
+	outb(bofs & 0xff, iobase+IRCC_BOF_COUNT_LO);
+	ctrl = inb(iobase+IRCC_CONTROL) & 0xf0;
+	outb(ctrl | ((bofs >> 8) & 0x0f), iobase+IRCC_BOF_COUNT_HI);
+
+	/* Set max Tx frame size */
+	outb(self->tx_buff.len >> 8, iobase+IRCC_TX_SIZE_HI);
+	outb(self->tx_buff.len & 0xff, iobase+IRCC_TX_SIZE_LO);
+
+	/* Setup DMA controller (must be done after enabling chip DMA) */
+	setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len, 
+		  DMA_TX_MODE);
 
+	outb(UART_MCR_OUT2, self->io.sir_base + UART_MCR);
+	/* Enable burst mode chip Tx DMA */
 	register_bank(iobase, 1);
-	serial_out(iobase, UART_SCE_CFGB,
-		   serial_in(iobase, UART_SCE_CFGB) | UART_CFGB_DMA_ENABLE);
+	outb(inb(iobase+IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE |
+	     IRCC_CFGB_DMA_BURST, iobase+IRCC_SCE_CFGB);
 
+	/* Enable interrupt */
+	outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER);
 	register_bank(iobase, 0);
+	outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase+IRCC_IER);
 
-	serial_out(iobase, UART_IER, UART_IER_ACTIVE_FRAME | UART_IER_EOM);
-	serial_out(iobase, UART_LCR_B,
-		   UART_LCR_B_SCE_TRANSMIT|UART_LCR_B_SIP_ENABLE);
-
-	serial_out(iobase, UART_MASTER, UART_MASTER_INT_EN);
-
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+	/* Enable transmit */
+	outb(IRCC_LCR_B_SCE_TRANSMIT|IRCC_LCR_B_SIP_ENABLE, iobase+IRCC_LCR_B);
 }
 
 /*
- * Function ircc_dma_xmit_complete (idev)
+ * Function ircc_dma_xmit_complete (self)
  *
  *    The transfer of a frame in finished. This function will only be called 
  *    by the interrupt handler
  *
  */
-static void ircc_dma_xmit_complete( struct irda_device *idev, int underrun)
+static void ircc_dma_xmit_complete(struct ircc_cb *self, int iobase)
 {
-	struct ircc_cb *self;
-	int iobase, d;
-
-	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
-
-	ASSERT( idev != NULL, return;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
-
-	register_bank(idev->io.iobase, 1);
-
-	serial_out(idev->io.iobase, UART_SCE_CFGB,
-		   serial_in(idev->io.iobase, UART_SCE_CFGB) &
-		   ~UART_CFGB_DMA_ENABLE);
-
-	d = get_dma_residue(idev->io.dma);
-
-	DEBUG(ircc_debug, __FUNCTION__ ": dma residue = %d, len=%d, sent=%d\n", 
-	      d, idev->tx_buff.len, idev->tx_buff.len - d);
-
-	self = idev->priv;
-
-	iobase = idev->io.iobase;
+	IRDA_DEBUG(2, __FUNCTION__ "\n");
+#if 0
+	/* Disable Tx */
+	register_bank(iobase, 0);
+	outb(0x00, iobase+IRCC_LCR_B);
+#endif
+	register_bank(self->io.fir_base, 1);
+	outb(inb(self->io.fir_base+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
+	     self->io.fir_base+IRCC_SCE_CFGB);
 
 	/* Check for underrrun! */
-	if ( underrun) {
-		idev->stats.tx_errors++;
-		idev->stats.tx_fifo_errors++;		
+	register_bank(iobase, 0);
+	if (inb(iobase+IRCC_LSR) & IRCC_LSR_UNDERRUN) {
+		self->irport->stats.tx_errors++;
+		self->irport->stats.tx_fifo_errors++;
+
+		/* Reset error condition */
+		register_bank(iobase, 0);
+		outb(IRCC_MASTER_ERROR_RESET, iobase+IRCC_MASTER);
+		outb(0x00, iobase+IRCC_MASTER);
 	} else {
-		idev->stats.tx_packets++;
-		idev->stats.tx_bytes +=  idev->tx_buff.len;
+		self->irport->stats.tx_packets++;
+		self->irport->stats.tx_bytes +=  self->tx_buff.len;
+	}
+
+	/* Check if it's time to change the speed */
+	if (self->new_speed) {
+		ircc_change_speed(self, self->new_speed);		
+		self->new_speed = 0;
 	}
 
 	/* Unlock tx_buff and request another frame */
-	idev->netdev.tbusy = 0; /* Unlock */
-	idev->media_busy = FALSE;
+	self->netdev->tbusy = 0; /* Unlock */
 	
 	/* Tell the network layer, that we can accept more frames */
-	mark_bh( NET_BH);
-
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+	mark_bh(NET_BH);
 }
 
 /*
- * Function ircc_dma_receive (idev)
+ * Function ircc_dma_receive (self)
  *
  *    Get ready for receiving a frame. The device will initiate a DMA
  *    if it starts to receive a frame.
  *
  */
-static int ircc_dma_receive( struct irda_device *idev) 
-{
-	struct ircc_cb *self;
-	int iobase;
-
-	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
-
-	ASSERT( idev != NULL, return -1;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+static int ircc_dma_receive(struct ircc_cb *self, int iobase) 
+{	
+	/* Turn off chip DMA */
+	//register_bank(iobase, 1);
+	//outb(inb(iobase+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE, 
+	//     iobase+IRCC_SCE_CFGB);
+
+	setup_dma(self->io.dma, self->rx_buff.data, self->rx_buff.truesize, 
+		  DMA_RX_MODE);
+	/* Set max Rx frame size */
+	register_bank(iobase, 4);
+	outb((2050 >> 8) & 0x0f, iobase+IRCC_RX_SIZE_HI);
+	outb(2050 & 0xff, iobase+IRCC_RX_SIZE_LO);
 
-	self = idev->priv;
-	iobase= idev->io.iobase;
+	self->io.direction = IO_RECV;
+	self->rx_buff.data = self->rx_buff.head;
 
-	setup_dma( idev->io.dma, idev->rx_buff.data, idev->rx_buff.truesize, 
-		   DMA_MODE_READ);
+	/* Setup DMA controller */
 	
-	/* driver->media_busy = FALSE; */
-	idev->io.direction = IO_RECV;
-	idev->rx_buff.data = idev->rx_buff.head;
-#if 0
-	idev->rx_buff.offset = 0;
-#endif
-
-	register_bank(iobase, 4);
-	serial_out(iobase, UART_CONTROL, 
-		   (serial_in(iobase, UART_CONTROL) &0xF0));
-	serial_out(iobase, UART_BOF_COUNT_LO, 2);
-	serial_out(iobase, UART_BRICKWALL_CNT_LO, 0);
-	serial_out(iobase, UART_BRICKWALL_TX_CNT_HI, 0);
-	serial_out(iobase, UART_TX_SIZE_LO, 0);
-	serial_out(iobase, UART_RX_SIZE_HI, 0);
-	serial_out(iobase, UART_RX_SIZE_LO, 0);
-
+	/* Enable receiver */
 	register_bank(iobase, 0);
-	serial_out(iobase, 
-		   UART_LCR_B, UART_LCR_B_SCE_RECEIVE | UART_LCR_B_SIP_ENABLE);
+	outb(IRCC_LCR_B_SCE_RECEIVE | IRCC_LCR_B_SIP_ENABLE, 
+	     iobase+IRCC_LCR_B);
 	
+	/* Enable burst mode chip Rx DMA */
 	register_bank(iobase, 1);
-	serial_out(iobase, UART_SCE_CFGB,
-		   serial_in(iobase, UART_SCE_CFGB) | 
-		   UART_CFGB_DMA_ENABLE | UART_CFGB_DMA_BURST);
+	outb(inb(iobase+IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE | 
+	     IRCC_CFGB_DMA_BURST, iobase+IRCC_SCE_CFGB);
 
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
 	return 0;
 }
 
 /*
- * Function ircc_dma_receive_complete (idev)
+ * Function ircc_dma_receive_complete (self)
  *
  *    Finished with receiving frames
  *
  *    
  */
-static int ircc_dma_receive_complete( struct irda_device *idev, int iobase)
+static void ircc_dma_receive_complete(struct ircc_cb *self, int iobase)
 {
+	unsigned long flags;
 	struct sk_buff *skb;
-	struct ircc_cb *self;
 	int len, msgcnt;
 
-	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
-
-	self = idev->priv;
-
-	msgcnt = serial_in(idev->io.iobase, UART_LCR_B) & 0x08;
-
-	DEBUG(ircc_debug, __FUNCTION__ ": dma count = %d\n",
-	      get_dma_residue(idev->io.dma));
-
-	len = idev->rx_buff.truesize - get_dma_residue(idev->io.dma) - 4;
+	IRDA_DEBUG(2, __FUNCTION__ "\n");
+#if 0
+	/* Disable Rx */
+	register_bank(iobase, 0);
+	outb(0x00, iobase+IRCC_LCR_B);
+#endif
+	register_bank(iobase, 0);
+	msgcnt = inb(iobase+IRCC_LCR_B) & 0x08;
 
-	DEBUG(ircc_debug, __FUNCTION__ ": msgcnt = %d, len=%d\n", msgcnt, len);
+	IRDA_DEBUG(2, __FUNCTION__ ": dma count = %d\n",
+		   get_dma_residue(self->io.dma));
 
-	skb = dev_alloc_skb( len+1);
+	len = self->rx_buff.truesize - get_dma_residue(self->io.dma);
+	
+	/* Remove CRC */
+	if (self->io.speed < 4000000)
+		len -= 2;
+	else
+		len -= 4;
 
-	if (skb == NULL)  {
-		printk( KERN_INFO __FUNCTION__ 
-			": memory squeeze, dropping frame.\n");
-		return FALSE;
+	if ((len < 2) && (len > 2050)) {
+		WARNING(__FUNCTION__ "(), bogus len=%d\n", len);
+		return;
 	}
-			
+	IRDA_DEBUG(2, __FUNCTION__ ": msgcnt = %d, len=%d\n", msgcnt, len);
+
+	skb = dev_alloc_skb(len+1);
+	if (!skb)  {
+		WARNING(__FUNCTION__ "(), memory squeeze, dropping frame.\n");
+		return;
+	}			
 	/* Make sure IP header gets aligned */
-	skb_reserve( skb, 1); 
-	skb_put( skb, len);
+	skb_reserve(skb, 1); 
 
-	memcpy(skb->data, idev->rx_buff.data, len);
-	idev->stats.rx_packets++;
+	memcpy(skb_put(skb, len), self->rx_buff.data, len);
+	self->irport->stats.rx_packets++;
+	self->irport->stats.rx_bytes += len;
 
-	skb->dev = &idev->netdev;
+	skb->dev = self->netdev;
 	skb->mac.raw  = skb->data;
 	skb->protocol = htons(ETH_P_IRDA);
-	netif_rx( skb);
-
-	register_bank(idev->io.iobase, 1);
-	serial_out(idev->io.iobase, UART_SCE_CFGB,
-		   serial_in(idev->io.iobase, UART_SCE_CFGB) &
-		   ~UART_CFGB_DMA_ENABLE);
-
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
-	return TRUE;
+	netif_rx(skb);
 }
 
 /*
@@ -725,176 +853,115 @@
  */
 static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
+	struct device *dev = (struct device *) dev_id;
+	struct irport_cb *irport;
+	struct ircc_cb *self;
 	int iobase, iir;
 
-	struct irda_device *idev = (struct irda_device *) dev_id;
-
-	DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
-
-	if (idev == NULL) {
-		printk( KERN_WARNING "%s: irq %d for unknown device.\n", 
-			driver_name, irq);
+	if (dev == NULL) {
+		printk(KERN_WARNING "%s: irq %d for unknown device.\n", 
+		       driver_name, irq);
 		return;
 	}
-	
-	if (idev->io.baudrate <= 115200) {
-		DEBUG(ircc_debug+1, __FUNCTION__ 
-		      ": routing interrupt to irport_interrupt\n");
-		return irport_interrupt( irq, dev_id, regs);
+	irport = (struct irport_cb *) dev->priv;
+	ASSERT(irport != NULL, return;);
+	self = (struct ircc_cb *) irport->priv;
+	ASSERT(self != NULL, return;);
+
+	/* Check if we should use the SIR interrupt handler */
+	if (self->io.speed < 576000) {
+		irport_interrupt(irq, dev_id, regs);
+		return;
 	}
+	iobase = self->io.fir_base;
 
-	iobase = idev->io.iobase;
-
-	idev->netdev.interrupt = 1;
-
-	serial_out(iobase, UART_MASTER, 0);
+	spin_lock(&self->lock);	
+	dev->interrupt = 1;
 
 	register_bank(iobase, 0);
+	iir = inb(iobase+IRCC_IIR);
 
-	iir = serial_in(iobase, UART_IIR);
-
-	serial_out(iobase, UART_IER, 0);
-
-	DEBUG(ircc_debug, __FUNCTION__ ": iir = 0x%02x\n", iir);
+	/* Disable interrupts */
+	outb(0, iobase+IRCC_IER);
 
-	if (iir & UART_IIR_EOM) {
-	        DEBUG(ircc_debug, __FUNCTION__ ": UART_IIR_EOM\n");
-		if (idev->io.direction == IO_RECV) {
-			ircc_dma_receive_complete(idev, iobase);
-		} else {
-			ircc_dma_xmit_complete(idev, iobase);
-		}
-		ircc_dma_receive(idev);
-	}
+	IRDA_DEBUG(2, __FUNCTION__ "(), iir = 0x%02x\n", iir);
 
-	if (iir & UART_IIR_ACTIVE_FRAME) {
-	        DEBUG(ircc_debug, __FUNCTION__ ": UART_IIR_ACTIVE_FRAME\n");
-		idev->rx_buff.state = INSIDE_FRAME;
-#if 0
-		ircc_dma_receive(idev);
-#endif
-	}
-
-	if (iir & UART_IIR_RAW_MODE) {
-		DEBUG(ircc_debug, __FUNCTION__ ": IIR RAW mode interrupt.\n");
+	if (iir & IRCC_IIR_EOM) {
+		if (self->io.direction == IO_RECV)
+			ircc_dma_receive_complete(self, iobase);
+		else
+			ircc_dma_xmit_complete(self, iobase);
+		
+		ircc_dma_receive(self, iobase);
 	}
 
-	idev->netdev.interrupt = 0;
-
+	/* Enable interrupts again */
 	register_bank(iobase, 0);
-	serial_out(iobase, UART_IER, UART_IER_ACTIVE_FRAME|UART_IER_EOM);
-	serial_out(iobase, UART_MASTER, UART_MASTER_INT_EN);
-
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
-}
-
-/*
- * Function ircc_wait_until_sent (idev)
- *
- *    This function should put the current thread to sleep until all data 
- *    have been sent, so it is safe to change the speed.
- */
-static void ircc_wait_until_sent( struct irda_device *idev)
-{
-	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, iobase+IRCC_IER);
 
-	/* Just delay 60 ms */
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(6);
-
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+	dev->interrupt = 0;
+	spin_unlock(&self->lock);
 }
 
 /*
- * Function ircc_is_receiving (idev)
+ * Function ircc_is_receiving (self)
  *
  *    Return TRUE is we are currently receiving a frame
  *
  */
-static int ircc_is_receiving( struct irda_device *idev)
+static int ircc_is_receiving(struct ircc_cb *self)
 {
 	int status = FALSE;
 	/* int iobase; */
 
-	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(0, __FUNCTION__ "\n");
 
-	ASSERT( idev != NULL, return FALSE;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return FALSE;);
+	ASSERT(self != NULL, return FALSE;);
 
-	DEBUG(ircc_debug, __FUNCTION__ ": dma count = %d\n",
-	      get_dma_residue(idev->io.dma));
+	IRDA_DEBUG(0, __FUNCTION__ ": dma count = %d\n",
+		   get_dma_residue(self->io.dma));
 
-	status = ( idev->rx_buff.state != OUTSIDE_FRAME);
+	status = (self->rx_buff.state != OUTSIDE_FRAME);
 	
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
-
 	return status;
 }
 
 /*
- * Function ircc_net_init (dev)
- *
- *    Initialize network device
- *
- */
-static int ircc_net_init( struct device *dev)
-{
-	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
-
-	/* Setup to be a normal IrDA network device driver */
-	irda_device_setup( dev);
-
-	/* Insert overrides below this line! */
-
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
-	return 0;
-}
-
-
-/*
  * Function ircc_net_open (dev)
  *
  *    Start the device
  *
  */
-static int ircc_net_open( struct device *dev)
+static int ircc_net_open(struct device *dev)
 {
-	struct irda_device *idev;
+	struct irport_cb *irport;
+	struct ircc_cb *self;
 	int iobase;
+
+	IRDA_DEBUG(0, __FUNCTION__ "\n");
 	
-	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
-	
-	ASSERT( dev != NULL, return -1;);
-	idev = (struct irda_device *) dev->priv;
-	
-	ASSERT( idev != NULL, return 0;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+	ASSERT(dev != NULL, return -1;);
+	irport = (struct irport_cb *) dev->priv;
+	self = (struct ircc_cb *) irport->priv;
+
+	ASSERT(self != NULL, return 0;);
 	
-	iobase = idev->io.iobase;
+	iobase = self->io.fir_base;
+
+	irport_net_open(dev); /* irport allocates the irq */
 
-	if (request_irq( idev->io.irq, ircc_interrupt, 0, idev->name, 
-			 (void *) idev)) {
-		return -EAGAIN;
-	}
 	/*
 	 * Always allocate the DMA channel after the IRQ,
 	 * and clean up on failure.
 	 */
-	if (request_dma(idev->io.dma, idev->name)) {
-		free_irq( idev->io.irq, idev);
+	if (request_dma(self->io.dma, dev->name)) {
+		irport_net_close(dev);
+
 		return -EAGAIN;
 	}
-		
-	/* Ready to play! */
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
-
-	/* turn on interrupts */
 	
 	MOD_INC_USE_COUNT;
 
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
 	return 0;
 }
 
@@ -906,64 +973,108 @@
  */
 static int ircc_net_close(struct device *dev)
 {
-	struct irda_device *idev;
+	struct irport_cb *irport;
+	struct ircc_cb *self;
 	int iobase;
 
-	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(0, __FUNCTION__ "\n");
 	
-	/* Stop device */
-	dev->tbusy = 1;
-	dev->start = 0;
-
-	ASSERT( dev != NULL, return -1;);
-	idev = (struct irda_device *) dev->priv;
+	ASSERT(dev != NULL, return -1;);
+	irport = (struct irport_cb *) dev->priv;
+	self = (struct ircc_cb *) irport->priv;
 	
-	ASSERT( idev != NULL, return 0;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+	ASSERT(self != NULL, return 0;);
 	
-	iobase = idev->io.iobase;
+	iobase = self->io.fir_base;
 
-	disable_dma( idev->io.dma);
+	irport_net_close(dev);
 
-	/* Disable interrupts */
-       
-	free_irq( idev->io.irq, idev);
-	free_dma( idev->io.dma);
+	disable_dma(self->io.dma);
+
+	free_dma(self->io.dma);
 
 	MOD_DEC_USE_COUNT;
 
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
 	return 0;
 }
 
-#ifdef MODULE
+#ifdef CONFIG_APM
+static void ircc_suspend(struct ircc_cb *self)
+{
+	int i = 10;
+
+	MESSAGE("%s, Suspending\n", driver_name);
+
+	if (self->io.suspended)
+		return;
+
+	ircc_net_close(self->netdev);
+
+	self->io.suspended = 1;
+}
+
+static void ircc_wakeup(struct ircc_cb *self)
+{
+	struct device *dev = self->netdev;
+	unsigned long flags;
+
+	if (!self->io.suspended)
+		return;
+
+	save_flags(flags);
+	cli();
+
+	ircc_net_open(self->netdev);
+	
+	restore_flags(flags);
+	MESSAGE("%s, Waking up\n", driver_name);
+}
 
+static int ircc_apmproc(apm_event_t event)
+{
+	static int down = 0;          /* Filter out double events */
+	int i;
+
+	switch (event) {
+	case APM_SYS_SUSPEND:
+	case APM_USER_SUSPEND:
+		if (!down) {			
+			for (i=0; i<4; i++) {
+				if (dev_self[i])
+					ircc_suspend(dev_self[i]);
+			}
+		}
+		down = 1;
+		break;
+	case APM_NORMAL_RESUME:
+	case APM_CRITICAL_RESUME:
+		if (down) {
+			for (i=0; i<4; i++) {
+				if (dev_self[i])
+					ircc_wakeup(dev_self[i]);
+			}
+		}
+		down = 0;
+		break;
+	}
+	return 0;
+}
+#endif /* CONFIG_APM */
+
+#ifdef MODULE
 MODULE_AUTHOR("Thomas Davis <tadavis@jps.net>");
 MODULE_DESCRIPTION("SMC IrCC controller driver");
-MODULE_PARM(ircc_debug,"1i");
 MODULE_PARM(ircc_dma, "1i");
 MODULE_PARM(ircc_irq, "1i");
 
-/*
- * Function init_module (void)
- *
- *    
- *
- */
 int init_module(void)
 {
 	return ircc_init();
 }
 
-/*
- * Function cleanup_module (void)
- *
- *    
- *
- */
 void cleanup_module(void)
 {
 	ircc_cleanup();
 }
 
-#endif
+#endif /* MODULE */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/irda/tekram.c linux.15p9/drivers/net/irda/tekram.c
--- linux.vanilla/drivers/net/irda/tekram.c	Sat Aug 14 02:26:48 1999
+++ linux.15p9/drivers/net/irda/tekram.c	Tue Jan 18 01:08:18 2000
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Wed Oct 21 20:02:35 1998
- * Modified at:   Sun May 16 14:33:42 1999
+ * Modified at:   Fri Dec 17 09:13:09 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -29,15 +29,14 @@
 #include <linux/init.h>
 
 #include <net/irda/irda.h>
+#include <net/irda/irmod.h>
 #include <net/irda/irda_device.h>
 #include <net/irda/irtty.h>
-#include <net/irda/dongle.h>
 
-static void tekram_reset(struct irda_device *dev);
-static void tekram_open(struct irda_device *dev, int type);
-static void tekram_close(struct irda_device *dev);
-static void tekram_change_speed(struct irda_device *dev, int baud);
-static void tekram_init_qos(struct irda_device *idev, struct qos_info *qos);
+static void tekram_open(dongle_t *self, struct qos_info *qos);
+static void tekram_close(dongle_t *self);
+static int  tekram_change_speed(struct irda_task *task);
+static int  tekram_reset(struct irda_task *task);
 
 #define TEKRAM_115200 0x00
 #define TEKRAM_57600  0x01
@@ -47,16 +46,16 @@
 
 #define TEKRAM_PW     0x10 /* Pulse select bit */
 
-static struct dongle dongle = {
-	TEKRAM_DONGLE,
+static struct dongle_reg dongle = {
+	Q_NULL,
+	IRDA_TEKRAM_DONGLE,
 	tekram_open,
 	tekram_close,
 	tekram_reset,
 	tekram_change_speed,
-	tekram_init_qos,
 };
 
-__initfunc(int tekram_init(void))
+int __init tekram_init(void)
 {
 	return irda_device_register_dongle(&dongle);
 }
@@ -66,26 +65,34 @@
 	irda_device_unregister_dongle(&dongle);
 }
 
-static void tekram_open(struct irda_device *idev, int type)
+static void tekram_open(dongle_t *self, struct qos_info *qos)
 {
-	strcat(idev->description, " <-> tekram");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+	qos->min_turn_time.bits = 0x01; /* Needs at least 10 ms */	
+	irda_qos_bits_to_value(qos);
 
-	idev->io.dongle_id = type;
-	idev->flags |= IFF_DONGLE;
-	
 	MOD_INC_USE_COUNT;
 }
 
-static void tekram_close(struct irda_device *idev)
-{		
+static void tekram_close(dongle_t *self)
+{
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
 	/* Power off dongle */
-	irda_device_set_dtr_rts(idev, FALSE, FALSE);
+	self->set_dtr_rts(self->dev, FALSE, FALSE);
+
+	if (self->reset_task)
+		irda_task_delete(self->reset_task);
+	if (self->speed_task)
+		irda_task_delete(self->speed_task);
 
 	MOD_DEC_USE_COUNT;
 }
 
 /*
- * Function tekram_change_speed (tty, baud)
+ * Function tekram_change_speed (dev, state, speed)
  *
  *    Set the speed for the Tekram IRMate 210 type dongle. Warning, this 
  *    function must be called with a process context!
@@ -100,16 +107,24 @@
  *    6. wait at least 50 us, new setting (baud rate, etc) takes effect here 
  *       after
  */
-static void tekram_change_speed(struct irda_device *idev, int baud)
+static int tekram_change_speed(struct irda_task *task)
 {
+	dongle_t *self = (dongle_t *) task->instance;
+	__u32 speed = (__u32) task->param;
 	__u8 byte;
+	int ret = 0;
 	
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(task != NULL, return -1;);
 
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+	if (self->speed_task && self->speed_task != task) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n");
+		return MSECS_TO_JIFFIES(10);
+	} else
+		self->speed_task = task;
 
-	switch (baud) {
+	switch (speed) {
 	default:
 	case 9600:
 		byte = TEKRAM_PW|TEKRAM_9600;
@@ -124,28 +139,62 @@
 		byte = TEKRAM_PW|TEKRAM_57600;
 		break;
 	case 115200:
-		byte = TEKRAM_PW|TEKRAM_115200;
+		byte = TEKRAM_115200;
 		break;
 	}
 
-	/* Need to reset the dongle and go to 9600 bps before programming */
-	tekram_reset(idev);
-	
-	/* Set DTR, Clear RTS */
-	irda_device_set_dtr_rts(idev, TRUE, FALSE);
+	switch (task->state) {
+	case IRDA_TASK_INIT:
+	case IRDA_TASK_CHILD_INIT:		
+		/* 
+		 * Need to reset the dongle and go to 9600 bps before
+                 * programming 
+		 */
+		if (irda_task_execute(self, tekram_reset, NULL, task, 
+				      (void *) speed))
+		{
+			/* Dongle need more time to reset */
+			irda_task_next_state(task, IRDA_TASK_CHILD_WAIT);
+
+			/* Give reset 1 sec to finish */
+			ret = MSECS_TO_JIFFIES(1000);
+		} else
+			irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
+		break;
+	case IRDA_TASK_CHILD_WAIT:
+		WARNING(__FUNCTION__ "(), resetting dongle timed out!\n");
+		ret = -1;
+		break;
+	case IRDA_TASK_CHILD_DONE:
+		/* Set DTR, Clear RTS */
+		self->set_dtr_rts(self->dev, TRUE, FALSE);
 	
-	/* Wait at least 7us */
-	udelay(7);
+		/* Wait at least 7us */
+		udelay(14);
 
-	/* Write control byte */
-	irda_device_raw_write(idev, &byte, 1);
-	
-	/* Wait at least 100 ms */
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(MSECS_TO_JIFFIES(100));
-        
-	/* Set DTR, Set RTS */
-	irda_device_set_dtr_rts(idev, TRUE, TRUE);
+		/* Write control byte */
+		self->write(self->dev, &byte, 1);
+		
+		irda_task_next_state(task, IRDA_TASK_WAIT);
+
+		/* Wait at least 100 ms */
+		ret = MSECS_TO_JIFFIES(150);
+		break;
+	case IRDA_TASK_WAIT:
+		/* Set DTR, Set RTS */
+		self->set_dtr_rts(self->dev, TRUE, TRUE);
+
+		irda_task_next_state(task, IRDA_TASK_DONE);
+		self->speed_task = NULL;
+		break;
+	default:
+		ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
+		irda_task_next_state(task, IRDA_TASK_DONE);
+		self->speed_task = NULL;
+		ret = -1;
+		break;
+	}
+	return ret;
 }
 
 /*
@@ -161,50 +210,61 @@
  *        3. clear DTR to SPACE state, wait at least 50 us for further 
  *         operation
  */
-void tekram_reset(struct irda_device *idev)
+int tekram_reset(struct irda_task *task)
 {
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+	dongle_t *self = (dongle_t *) task->instance;
+	int ret = 0;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(task != NULL, return -1;);
+
+	if (self->reset_task && self->reset_task != task) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n");
+		return MSECS_TO_JIFFIES(10);
+	} else
+		self->reset_task = task;
 	
 	/* Power off dongle */
-	irda_device_set_dtr_rts(idev, FALSE, FALSE);
-
-	/* Sleep 50 ms */
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(MSECS_TO_JIFFIES(50));
+	//self->set_dtr_rts(self->dev, FALSE, FALSE);
+	self->set_dtr_rts(self->dev, TRUE, TRUE);
 
-	/* Clear DTR, Set RTS */
-	irda_device_set_dtr_rts(idev, FALSE, TRUE); 
+	switch (task->state) {
+	case IRDA_TASK_INIT:
+		irda_task_next_state(task, IRDA_TASK_WAIT1);
 
-	/* Should sleep 1 ms, but 10-20 should not do any harm */
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(MSECS_TO_JIFFIES(20));
+		/* Sleep 50 ms */
+		ret = MSECS_TO_JIFFIES(50);
+		break;
+	case IRDA_TASK_WAIT1:
+		/* Clear DTR, Set RTS */
+		self->set_dtr_rts(self->dev, FALSE, TRUE); 
 
-	/* Set DTR, Set RTS */
-	irda_device_set_dtr_rts(idev, TRUE, TRUE);
-	
-	udelay(50);
+		irda_task_next_state(task, IRDA_TASK_WAIT2);
+		
+		/* Should sleep 1 ms */
+		ret = MSECS_TO_JIFFIES(1);
+		break;
+	case IRDA_TASK_WAIT2:
+		/* Set DTR, Set RTS */
+		self->set_dtr_rts(self->dev, TRUE, TRUE);
 	
-	/* Make sure the IrDA chip also goes to defalt speed */
-	if (idev->change_speed)
-		idev->change_speed(idev, 9600);
-}
+		/* Wait at least 50 us */
+		udelay(75);
 
-/*
- * Function tekram_init_qos (qos)
- *
- *    Initialize QoS capabilities
- *
- */
-static void tekram_init_qos(struct irda_device *idev, struct qos_info *qos)
-{
-	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
-	qos->min_turn_time.bits &= 0x01; /* Needs at least 10 ms */
-	irda_qos_bits_to_value(qos);
+		irda_task_next_state(task, IRDA_TASK_DONE);
+		self->reset_task = NULL;
+		break;
+	default:
+		ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
+		irda_task_next_state(task, IRDA_TASK_DONE);		
+		self->reset_task = NULL;
+		ret = -1;
+	}
+	return ret;
 }
 
 #ifdef MODULE
-
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
 MODULE_DESCRIPTION("Tekram IrMate IR-210B dongle driver");
 		
@@ -229,5 +289,4 @@
 {
         tekram_cleanup();
 }
-
 #endif /* MODULE */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/irda/toshoboe.c linux.15p9/drivers/net/irda/toshoboe.c
--- linux.vanilla/drivers/net/irda/toshoboe.c	Sat Aug 14 02:27:29 1999
+++ linux.15p9/drivers/net/irda/toshoboe.c	Tue Jan 18 01:08:18 2000
@@ -7,8 +7,10 @@
  * Status:        Experimental.
  * Author:        James McKenzie <james@fishsoup.dhs.org>
  * Created at:    Sat May 8  12:35:27 1999
+ * Modified:      Paul Bristow <paul.bristow@technologist.com>
+ * Modified:      Mon Nov 11 19:10:05 1999
  * 
- *     Copyright (c) 1999 James McKenzie, All Rights Reserved.
+ *     Copyright (c) 1999-2000 James McKenzie, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -28,32 +30,13 @@
 /* an olivetti notebook which doesn't have FIR, a toshiba libretto, and */
 /* an hp printer, this works fine at 4MBPS with my HP printer */
 
-static char *rcsid = "$Id: toshoboe.c,v 1.5 1999/05/12 12:24:39 root Exp root $";
-
-/* 
- * $Log: toshoboe.c,v $
- * Revision 1.5  1999/05/12 12:24:39  root
- * *** empty log message ***
- *
- * Revision 1.4  1999/05/12 11:55:08  root
- * *** empty log message ***
- *
- * Revision 1.3  1999/05/09 01:33:12  root
- * *** empty log message ***
- *
- * Revision 1.2  1999/05/09 01:30:38  root
- * *** empty log message ***
- *
- * Revision 1.1  1999/05/09 01:25:04  root
- * Initial revision
- * 
- */
+static char *rcsid = "$Id: toshoboe.c,v 1.91 1999/06/29 14:21:06 root Exp $";
 
 /* Define this to have only one frame in the XMIT or RECV queue */
 /* Toshiba's drivers do this, but it disables back to back tansfers */
 /* I think that the chip may have some problems certainly, I have */
 /* seen it jump over tasks in the taskfile->xmit with this turned on */
-#define ONETASK
+#define ONETASK 
 
 /* To adjust the number of tasks in use edit toshoboe.h */
 
@@ -83,6 +66,7 @@
 #include <linux/malloc.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/rtnetlink.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -93,6 +77,10 @@
 #include <net/irda/irlap_frame.h>
 #include <net/irda/irda_device.h>
 
+#ifdef CONFIG_APM
+#include <linux/apm_bios.h>
+#endif
+
 #include <net/irda/toshoboe.h>
 
 static char *driver_name = "toshoboe";
@@ -100,11 +88,13 @@
 static struct toshoboe_cb *dev_self[NSELFS + 1] =
 {NULL, NULL, NULL, NULL, NULL};
 
+static int max_baud = 4000000;
+
 /* Shutdown the chip and point the taskfile reg somewhere else */
-static void 
+static void
 toshoboe_stopchip (struct toshoboe_cb *self)
 {
-  DEBUG (4, __FUNCTION__ "()\n");
+  IRDA_DEBUG (4, __FUNCTION__ "()\n");
 
   outb_p (0x0e, OBOE_REG_11);
 
@@ -117,16 +107,19 @@
   outb_p (0x00, OBOE_ISR);      /*FIXME: should i do this to disbale ints */
   outb_p (0x80, OBOE_RST);
   outb_p (0xe, OBOE_LOCK);
+
 }
 
 /*Set the baud rate */
-static void 
+static void
 toshoboe_setbaud (struct toshoboe_cb *self, int baud)
 {
-  DEBUG (4, __FUNCTION__ "()\n");
+  unsigned long flags;
+  IRDA_DEBUG (4, __FUNCTION__ "()\n");
 
-  printk (KERN_WARNING "ToshOboe: seting baud to %d\n", baud);
+  printk (KERN_WARNING "ToshOboe: setting baud to %d\n", baud);
 
+  save_flags (flags);
   cli ();
   switch (baud)
     {
@@ -177,21 +170,22 @@
       break;
     }
 
-  sti ();
+  restore_flags (flags);
 
   outb_p (0x00, OBOE_RST);
   outb_p (0x80, OBOE_RST);
   outb_p (0x01, OBOE_REG_9);
 
+  self->io.speed = baud;
 }
 
 /* Wake the chip up and get it looking at the taskfile */
-static void 
+static void
 toshoboe_startchip (struct toshoboe_cb *self)
 {
   __u32 physaddr;
 
-  DEBUG (4, __FUNCTION__ "()\n");
+  IRDA_DEBUG (4, __FUNCTION__ "()\n");
 
 
   outb_p (0, OBOE_LOCK);
@@ -217,19 +211,19 @@
 }
 
 /*Let the chip look at memory */
-static void 
+static void
 toshoboe_enablebm (struct toshoboe_cb *self)
 {
-  DEBUG (4, __FUNCTION__ "()\n");
+  IRDA_DEBUG (4, __FUNCTION__ "()\n");
   pci_set_master (self->pdev);
 }
 
 /*Don't let the chip look at memory */
-static void 
+static void
 toshoboe_disablebm (struct toshoboe_cb *self)
 {
   __u8 command;
-  DEBUG (4, __FUNCTION__ "()\n");
+  IRDA_DEBUG (4, __FUNCTION__ "()\n");
 
   pci_read_config_byte (self->pdev, PCI_COMMAND, &command);
   command &= ~PCI_COMMAND_MASTER;
@@ -238,13 +232,15 @@
 }
 
 /*setup the taskfile */
-static void 
+static void
 toshoboe_initbuffs (struct toshoboe_cb *self)
 {
   int i;
+  unsigned long flags;
 
-  DEBUG (4, __FUNCTION__ "()\n");
+  IRDA_DEBUG (4, __FUNCTION__ "()\n");
 
+  save_flags (flags);
   cli ();
 
   for (i = 0; i < TX_SLOTS; ++i)
@@ -261,25 +257,30 @@
       self->taskfile->recv[i].buffer = virt_to_bus (self->recv_bufs[i]);
     }
 
-  sti ();
+  restore_flags (flags);
 }
 
-
 /*Transmit something */
-static int 
+static int
 toshoboe_hard_xmit (struct sk_buff *skb, struct device *dev)
 {
-  struct irda_device *idev;
   struct toshoboe_cb *self;
+  __u32 speed;
   int mtt, len;
 
-  idev = (struct irda_device *) dev->priv;
-  ASSERT (idev != NULL, return 0;);
-  ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+  self = (struct toshoboe_cb *) dev->priv;
+
+  ASSERT (self != NULL, return 0;
+    );
 
-  self = idev->priv;
-  ASSERT (self != NULL, return 0;);
+  /* Check if we need to change the speed */
+  if ((speed = irda_get_speed(skb)) != self->io.speed)
+	  self->new_speed = speed;
 
+  if (self->stopped) {
+	  dev_kfree_skb(skb);
+    return 0;
+  }
 
 #ifdef ONETASK
   if (self->txpending)
@@ -343,27 +344,21 @@
 }
 
 /*interrupt handler */
-static void 
+static void
 toshoboe_interrupt (int irq, void *dev_id, struct pt_regs *regs)
 {
-  struct irda_device *idev = (struct irda_device *) dev_id;
-  struct toshoboe_cb *self;
+  struct toshoboe_cb *self = (struct toshoboe_cb *) dev_id;
   __u8 irqstat;
   struct sk_buff *skb;
 
-  if (idev == NULL)
+  if (self == NULL)
     {
       printk (KERN_WARNING "%s: irq %d for unknown device.\n",
               driver_name, irq);
       return;
     }
 
-  self = idev->priv;
-
-  if (!self)
-    return;
-
-  DEBUG (4, __FUNCTION__ "()\n");
+  IRDA_DEBUG (4, __FUNCTION__ "()\n");
 
   irqstat = inb_p (OBOE_ISR);
 
@@ -379,12 +374,17 @@
     {
       self->txpending--;
 
-      idev->stats.tx_packets++;
+      self->stats.tx_packets++;
 
-      idev->media_busy = FALSE;
-      idev->netdev.tbusy = 0;
+      if (self->new_speed) {
+	      toshoboe_setbaud(self, self->new_speed);
 
-      mark_bh (NET_BH);
+	      self->new_speed = 0;
+      }
+      self->netdev->tbusy = 0; /* Unlock */
+      
+      /* Tell network layer that we want more frames */
+      mark_bh(NET_BH);
     }
 
   if (irqstat & OBOE_ISR_RXDONE)
@@ -399,8 +399,9 @@
 #endif
         {
           int len = self->taskfile->recv[self->rxs].len;
-	
-	  if (len>2) len-=2;
+
+          if (len > 2)
+            len -= 2;
 
           skb = dev_alloc_skb (len + 1);
           if (skb)
@@ -410,8 +411,8 @@
               skb_put (skb, len);
               memcpy (skb->data, self->recv_bufs[self->rxs], len);
 
-              idev->stats.rx_packets++;
-              skb->dev = &idev->netdev;
+              self->stats.rx_packets++;
+              skb->dev = self->netdev;
               skb->mac.raw = skb->data;
               skb->protocol = htons (ETH_P_IRDA);
             }
@@ -421,8 +422,6 @@
                       "(), memory squeeze, dropping frame.\n");
             }
 
-
-
           self->taskfile->recv[self->rxs].control = 0x83;
           self->taskfile->recv[self->rxs].len = 0x0;
 
@@ -448,76 +447,18 @@
     {
       /*FIXME: I think this is a TX or RX error of some sort */
 
-      idev->stats.tx_errors++;
-      idev->stats.rx_errors++;
+      self->stats.tx_errors++;
+      self->stats.rx_errors++;
 
     }
 
 
 }
 
-
-
-/* Change the baud rate */
-static void 
-toshoboe_change_speed (struct irda_device *idev, int speed)
-{
-  struct toshoboe_cb *self;
-  DEBUG (4, __FUNCTION__ "()\n");
-
-  ASSERT (idev != NULL, return;);
-  ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return;);
-
-  self = idev->priv;
-  ASSERT (self != NULL, return;);
-
-  idev->io.baudrate = speed;
-
-  toshoboe_setbaud (self, speed);
-
-}
-
-
-/* Check all xmit_tasks finished */
-static void 
-toshoboe_wait_until_sent (struct irda_device *idev)
-{
-  struct toshoboe_cb *self;
-  int i;
-
-  DEBUG (4, __FUNCTION__ "()\n");
-
-  ASSERT (idev != NULL, return;);
-  ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return;);
-
-  self = idev->priv;
-  ASSERT (self != NULL, return;);
-
-  for (i = 0; i < TX_SLOTS; ++i)
-    {
-      while (self->taskfile->xmit[i].control)
-        {
-          current->state = TASK_INTERRUPTIBLE;
-          schedule_timeout (6);
-        }
-    }
-
-}
-
-static int 
-toshoboe_is_receiving (struct irda_device *idev)
-{
-  DEBUG (4, __FUNCTION__ "()\n");
-
-/*FIXME Can't tell! */
-  return (FALSE);
-}
-
-
-static int 
+static int
 toshoboe_net_init (struct device *dev)
 {
-  DEBUG (4, __FUNCTION__ "()\n");
+  IRDA_DEBUG (4, __FUNCTION__ "()\n");
 
   /* Setup to be a normal IrDA network device driver */
   irda_device_setup (dev);
@@ -527,37 +468,12 @@
 }
 
 
-
-
-static int 
-toshoboe_net_open (struct device *dev)
+static void 
+toshoboe_initptrs (struct toshoboe_cb *self)
 {
-  struct irda_device *idev;
-  struct toshoboe_cb *self;
-
-  DEBUG (4, __FUNCTION__ "()\n");
-
-  ASSERT (dev != NULL, return -1;);
-  idev = (struct irda_device *) dev->priv;
-
-  ASSERT (idev != NULL, return 0;);
-  ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return 0;);
-
-  self = idev->priv;
-  ASSERT (self != NULL, return 0;);
-
-  if (request_irq (idev->io.irq, toshoboe_interrupt,
-                   SA_SHIRQ | SA_INTERRUPT, idev->name, (void *) idev))
-    {
-
-      return -EAGAIN;
-    }
-
-  toshoboe_initbuffs (self);
-  toshoboe_enablebm (self);
-  toshoboe_startchip (self);
-
 
+  unsigned long flags;
+  save_flags (flags);
   cli ();
 
   /*FIXME: need to test this carefully to check which one */
@@ -580,45 +496,88 @@
 
   self->txpending = 0;
 
-  sti ();
+  restore_flags (flags);
+
+}
 
 
+static int
+toshoboe_net_open (struct device *dev)
+{
+  struct toshoboe_cb *self;
+
+  IRDA_DEBUG (4, __FUNCTION__ "()\n");
+
+  ASSERT (dev != NULL, return -1;
+    );
+  self = (struct toshoboe_cb *) dev->priv;
+
+  ASSERT (self != NULL, return 0;
+    );
+
+  if (self->stopped)
+    return 0;
+
+  if (request_irq (self->io.irq, toshoboe_interrupt,
+                   SA_SHIRQ | SA_INTERRUPT, dev->name, (void *) self))
+    {
+
+      return -EAGAIN;
+    }
+
+  toshoboe_initbuffs (self);
+  toshoboe_enablebm (self);
+  toshoboe_startchip (self);
+  toshoboe_initptrs (self);
+
+  /* Ready to play! */
   dev->tbusy = 0;
   dev->interrupt = 0;
   dev->start = 1;
+  
+  /* 
+   * Open new IrLAP layer instance, now that everything should be
+   * initialized properly 
+   */
+  self->irlap = irlap_open(dev, &self->qos);	
 
+  self->open = 1;
+	
   MOD_INC_USE_COUNT;
 
   return 0;
 
 }
 
-static int 
+static int
 toshoboe_net_close (struct device *dev)
 {
-  struct irda_device *idev;
   struct toshoboe_cb *self;
 
-  DEBUG (4, __FUNCTION__ "()\n");
+  IRDA_DEBUG (4, __FUNCTION__ "()\n");
 
-  ASSERT (dev != NULL, return -1;);
-  idev = (struct irda_device *) dev->priv;
-
-  ASSERT (idev != NULL, return 0;);
-  ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+  ASSERT (dev != NULL, return -1;
+    );
+  self = (struct toshoboe_cb *) dev->priv;
 
+  /* Stop device */
   dev->tbusy = 1;
   dev->start = 0;
+  
+  /* Stop and remove instance of IrLAP */
+  if (self->irlap)
+	  irlap_close(self->irlap);
+  self->irlap = NULL;
 
+  self->open = 0;
 
-  self = idev->priv;
-
-  ASSERT (self != NULL, return 0;);
+  free_irq (self->io.irq, (void *) self);
 
-  free_irq (idev->io.irq, (void *) idev);
-
-  toshoboe_stopchip (self);
-  toshoboe_disablebm (self);
+  if (!self->stopped)
+    {
+      toshoboe_stopchip (self);
+      toshoboe_disablebm (self);
+    }
 
   MOD_DEC_USE_COUNT;
 
@@ -626,28 +585,73 @@
 
 }
 
+/*
+ * Function toshoboe_net_ioctl (dev, rq, cmd)
+ *
+ *    Process IOCTL commands for this device
+ *
+ */
+static int toshoboe_net_ioctl(struct device *dev, struct ifreq *rq, int cmd)
+{
+	struct if_irda_req *irq = (struct if_irda_req *) rq;
+	struct toshoboe_cb *self;
+	unsigned long flags;
+	int ret = 0;
+
+	ASSERT(dev != NULL, return -1;);
+
+	self = dev->priv;
 
+	ASSERT(self != NULL, return -1;);
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
+	
+	/* Disable interrupts & save flags */
+	save_flags(flags);
+	cli();
+	
+	switch (cmd) {
+	case SIOCSBANDWIDTH: /* Set bandwidth */
+		/* toshoboe_setbaud(self, irq->ifr_baudrate); */
+                /* Just change speed once - inserted by Paul Bristow */
+	        self->new_speed = irq->ifr_baudrate;
+		break;
+	case SIOCSMEDIABUSY: /* Set media busy */
+		irda_device_set_media_busy(self->netdev, TRUE);
+		break;
+	case SIOCGRECEIVING: /* Check if we are receiving right now */
+		irq->ifr_receiving = 0; /* Can't tell */
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+	}
+	
+	restore_flags(flags);
+	
+	return ret;
+}
 
 #ifdef MODULE
 
-static int 
-toshoboe_close (struct irda_device *idev)
+MODULE_PARM (max_baud, "i");
+
+static int
+toshoboe_close (struct toshoboe_cb *self)
 {
-  struct toshoboe_cb *self;
   int i;
 
-  DEBUG (4, __FUNCTION__ "()\n");
-
-  ASSERT (idev != NULL, return -1;);
-  ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+  IRDA_DEBUG (4, __FUNCTION__ "()\n");
 
-  self = idev->priv;
+  ASSERT (self != NULL, return -1;
+    );
 
-  ASSERT (self != NULL, return -1;);
-
-  toshoboe_stopchip (self);
+  if (!self->stopped)
+    {
+      toshoboe_stopchip (self);
+      toshoboe_disablebm (self);
+    }
 
-  release_region (idev->io.iobase, idev->io.io_ext);
+  release_region (self->io.sir_base, self->io.sir_ext);
 
 
   for (i = 0; i < TX_SLOTS; ++i)
@@ -662,14 +666,19 @@
       self->recv_bufs[i] = NULL;
     }
 
+  if (self->netdev) {
+	  /* Remove netdevice */
+	  rtnl_lock();
+	  unregister_netdevice(self->netdev);
+	  rtnl_unlock();
+	  /* Must free the old-style 2.2.x device */
+	  kfree(self->netdev);
+  }
 
   kfree (self->taskfilebuf);
   self->taskfilebuf = NULL;
   self->taskfile = NULL;
 
-
-  irda_device_close (idev);
-
   return (0);
 
 }
@@ -678,16 +687,16 @@
 
 
 
-static int 
+static int
 toshoboe_open (struct pci_dev *pci_dev)
 {
   struct toshoboe_cb *self;
-  struct irda_device *idev;
+  struct device *dev;
   int i = 0;
-  int ok=0;
+  int ok = 0;
+  int err;
 
-
-  DEBUG (4, __FUNCTION__ "()\n");
+  IRDA_DEBUG (4, __FUNCTION__ "()\n");
 
   while (dev_self[i])
     i++;
@@ -709,26 +718,24 @@
 
   memset (self, 0, sizeof (struct toshoboe_cb));
 
+  dev_self[i] = self;           /*This needs moving if we ever get more than one chip */
 
-  dev_self[i] = self;
-
+  self->open = 0;
+  self->stopped = 0;
   self->pdev = pci_dev;
   self->base = pci_dev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
 
-  idev = &self->idev;
-
-  /*Setup idev */
-
-  idev->io.iobase = self->base;
-  idev->io.irq = pci_dev->irq;
-  idev->io.io_ext = CHIP_IO_EXTENT;
+  self->io.sir_base = self->base;
+  self->io.irq = pci_dev->irq;
+  self->io.sir_ext = CHIP_IO_EXTENT;
+  self->io.speed = 9600;
 
   /* Lock the port that we need */
-  i = check_region (idev->io.iobase, idev->io.io_ext);
+  i = check_region (self->io.sir_base, self->io.sir_ext);
   if (i < 0)
     {
-      DEBUG (0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
-             idev->io.iobase);
+      IRDA_DEBUG (0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+             self->io.sir_base);
 
       dev_self[i] = NULL;
       kfree (self);
@@ -736,55 +743,52 @@
       return -ENODEV;
     }
 
-  request_region (idev->io.iobase, idev->io.io_ext, driver_name);
 
-  irda_init_max_qos_capabilies (&idev->qos);
+  irda_init_max_qos_capabilies (&self->qos);
+  self->qos.baud_rate.bits = 0;
 
-  idev->qos.baud_rate.bits = IR_2400 | /*IR_4800 | */ IR_9600 | IR_19200 |
-    IR_115200;
+  if (max_baud >= 2400)
+    self->qos.baud_rate.bits |= IR_2400;
+  /*if (max_baud>=4800) idev->qos.baud_rate.bits|=IR_4800; */
+  if (max_baud >= 9600)
+    self->qos.baud_rate.bits |= IR_9600;
+  if (max_baud >= 19200)
+    self->qos.baud_rate.bits |= IR_19200;
+  if (max_baud >= 115200)
+    self->qos.baud_rate.bits |= IR_115200;
 #ifdef ENABLE_FAST
- idev->qos.baud_rate.bits|= IR_576000 | IR_1152000 | (IR_4000000 << 8);
+  if (max_baud >= 576000)
+    self->qos.baud_rate.bits |= IR_576000;
+  if (max_baud >= 1152000)
+    self->qos.baud_rate.bits |= IR_1152000;
+  if (max_baud >= 4000000)
+    self->qos.baud_rate.bits |= (IR_4000000 << 8);
 #endif
 
-  idev->qos.min_turn_time.bits = 0xff;  /*FIXME: what does this do? */
 
-  irda_qos_bits_to_value (&idev->qos);
+  self->qos.min_turn_time.bits = 0xff;  /*FIXME: what does this do? */
 
-  idev->flags = IFF_SIR | IFF_DMA | IFF_PIO;
+  irda_qos_bits_to_value (&self->qos);
+
+  self->flags = IFF_SIR | IFF_DMA | IFF_PIO;
 
 #ifdef ENABLE_FAST
-  idev->flags |= IFF_FIR;
+  if (max_baud >= 576000)
+    self->flags |= IFF_FIR;
 #endif
 
-  /* These aren't much use as we need to have a whole panoply of
-   * buffers running */
-
-  idev->rx_buff.flags = 0;
-  idev->tx_buff.flags = 0;
-  idev->rx_buff.truesize = 0;
-  idev->rx_buff.truesize = 0;
-
-  idev->change_speed = toshoboe_change_speed;
-  idev->wait_until_sent = toshoboe_wait_until_sent;
-  idev->is_receiving = toshoboe_is_receiving;
-
-  idev->netdev.init = toshoboe_net_init;
-  idev->netdev.hard_start_xmit = toshoboe_hard_xmit;
-  idev->netdev.open = toshoboe_net_open;
-  idev->netdev.stop = toshoboe_net_close;
-
-
   /* Now setup the endless buffers we need */
 
   self->txs = 0;
   self->rxs = 0;
 
-  self->taskfilebuf = kmalloc (OBOE_TASK_BUF_LEN, GFP_KERNEL | GFP_DMA);
-  if (!self->taskfilebuf) {
-	printk(KERN_ERR "toshoboe: kmalloc for DMA failed()\n");
-	kfree(self);
-	return -ENOMEM;
-  }
+  self->taskfilebuf = kmalloc (OBOE_TASK_BUF_LEN, GFP_KERNEL);
+  if (!self->taskfilebuf)
+    {
+      printk (KERN_ERR "toshoboe: kmalloc for DMA failed()\n");
+      kfree (self);
+      return -ENOMEM;
+    }
 
 
   memset (self->taskfilebuf, 0, OBOE_TASK_BUF_LEN);
@@ -803,29 +807,61 @@
   for (i = 0; i < TX_SLOTS; ++i)
     {
       self->xmit_bufs[i] = kmalloc (TX_BUF_SZ, GFP_KERNEL | GFP_DMA);
-      if (self->xmit_bufs[i]) ok++;
+      if (self->xmit_bufs[i])
+        ok++;
     }
 
   for (i = 0; i < RX_SLOTS; ++i)
     {
       self->recv_bufs[i] = kmalloc (TX_BUF_SZ, GFP_KERNEL | GFP_DMA);
-      if (self->recv_bufs[i]) ok++;
+      if (self->recv_bufs[i])
+        ok++;
     }
 
-  if (ok!=RX_SLOTS+TX_SLOTS) {
-	printk(KERN_ERR  "toshoboe: kmalloc for buffers failed()\n");
+  if (ok != RX_SLOTS + TX_SLOTS)
+    {
+      printk (KERN_ERR "toshoboe: kmalloc for buffers failed()\n");
+
 
+      for (i = 0; i < TX_SLOTS; ++i)
+        if (self->xmit_bufs[i])
+          kfree (self->xmit_bufs[i]);
+      for (i = 0; i < RX_SLOTS; ++i)
+        if (self->recv_bufs[i])
+          kfree (self->recv_bufs[i]);
 
-  for (i = 0; i < TX_SLOTS; ++i) if (self->xmit_bufs[i]) kfree(self->xmit_bufs[i]);
-  for (i = 0; i < RX_SLOTS; ++i) if (self->recv_bufs[i]) kfree(self->recv_bufs[i]);
+      kfree (self);
+      return -ENOMEM;
 
-	kfree(self);
-	return -ENOMEM;
+    }
 
-  }
+  request_region (self->io.sir_base, self->io.sir_ext, driver_name);
 
+  if (!(dev = dev_alloc("irda%d", &err))) {
+	  ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
+	  return -ENOMEM;
+  }
+  /* dev_alloc doesn't clear the struct, so lets do a little hack */
+  memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct device)-sizeof(char*));
 
-  irda_device_open (idev, driver_name, self);
+  dev->priv = (void *) self;
+  self->netdev = dev;
+  
+  MESSAGE("IrDA: Registered device %s\n", dev->name);
+
+  dev->init = toshoboe_net_init;
+  dev->hard_start_xmit = toshoboe_hard_xmit;
+  dev->open = toshoboe_net_open;
+  dev->stop = toshoboe_net_close;
+  dev->do_ioctl = toshoboe_net_ioctl;
+
+  rtnl_lock();
+  err = register_netdevice(dev);
+  rtnl_unlock();
+  if (err) {
+	  ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
+	  return -1;
+  }
 
   printk (KERN_WARNING "ToshOboe: Using ");
 #ifdef ONETASK
@@ -838,7 +874,119 @@
   return (0);
 }
 
-__initfunc (int toshoboe_init (void))
+#ifdef CONFIG_APM
+static void 
+toshoboe_gotosleep (struct toshoboe_cb *self)
+{
+  int i = 10;
+
+  printk (KERN_WARNING "ToshOboe: suspending\n");
+
+  if (self->stopped)
+    return;
+
+  self->stopped = 1;
+
+  if (!self->open)
+    return;
+
+/*FIXME: can't sleep here wait one second */
+
+  while ((i--) && (self->txpending))
+    udelay (100000);
+
+  toshoboe_stopchip (self);
+  toshoboe_disablebm (self);
+
+  self->txpending = 0;
+
+}
+
+
+static void 
+toshoboe_wakeup (struct toshoboe_cb *self)
+{
+  struct device *dev = self->netdev;
+  unsigned long flags;
+
+  if (!self->stopped)
+    return;
+
+  if (!self->open)
+    {
+      self->stopped = 0;
+      return;
+    }
+
+  save_flags (flags);
+  cli ();
+
+  toshoboe_initbuffs (self);
+  toshoboe_enablebm (self);
+  toshoboe_startchip (self);
+
+  toshoboe_setbaud (self, self->io.speed);
+
+  toshoboe_initptrs (self);
+
+  dev->tbusy = 0;
+  dev->interrupt = 0;
+  dev->start = 1;
+  self->stopped = 0;
+
+  restore_flags (flags);
+  printk (KERN_WARNING "ToshOboe: waking up\n");
+
+}
+
+static int 
+toshoboe_apmproc (apm_event_t event)
+{
+  static int down = 0;          /*Filter out double events */
+  int i;
+
+  switch (event)
+    {
+    case APM_SYS_SUSPEND:
+    case APM_USER_SUSPEND:
+      if (!down)
+        {
+
+          for (i = 0; i < 4; i++)
+            {
+              if (dev_self[i])
+                toshoboe_gotosleep (dev_self[i]);
+            }
+
+        }
+      down = 1;
+      break;
+    case APM_NORMAL_RESUME:
+    case APM_CRITICAL_RESUME:
+      if (down)
+        {
+
+
+
+          for (i = 0; i < 4; i++)
+            {
+              if (dev_self[i])
+                toshoboe_wakeup (dev_self[i]);
+            }
+
+
+
+        }
+      down = 0;
+      break;
+    }
+  return 0;
+}
+
+
+#endif
+
+int __init toshoboe_init (void)
 {
   struct pci_dev *pci_dev = NULL;
   int found = 0;
@@ -860,38 +1008,49 @@
     }
   while (pci_dev);
 
+
   if (found)
-    return 0;
+    {
+#ifdef CONFIG_APM
+      apm_register_callback (toshoboe_apmproc);
+#endif
+      return 0;
+    }
 
   return -ENODEV;
 }
 
 #ifdef MODULE
 
-static void 
+static void
 toshoboe_cleanup (void)
 {
   int i;
 
-  DEBUG (4, __FUNCTION__ "()\n");
+  IRDA_DEBUG (4, __FUNCTION__ "()\n");
 
   for (i = 0; i < 4; i++)
     {
       if (dev_self[i])
-        toshoboe_close (&(dev_self[i]->idev));
+        toshoboe_close (dev_self[i]);
     }
+
+#ifdef CONFIG_APM
+  apm_unregister_callback (toshoboe_apmproc);
+#endif
+
 }
 
 
 
-int 
+int
 init_module (void)
 {
   return toshoboe_init ();
 }
 
 
-void 
+void
 cleanup_module (void)
 {
   toshoboe_cleanup ();
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/irda/uircc.c linux.15p9/drivers/net/irda/uircc.c
--- linux.vanilla/drivers/net/irda/uircc.c	Sat Aug 14 02:26:48 1999
+++ linux.15p9/drivers/net/irda/uircc.c	Thu Jan  1 01:00:00 1970
@@ -1,953 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      uircc.c
- * Version:       0.3
- * Description:   Driver for the Sharp Universal Infrared 
- *                Communications Controller (UIRCC v 1.3)
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Sat Dec 26 10:59:03 1998
- * Modified at:   Wed May 19 15:29:56 1999
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
- *      
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
- *     the License, or (at your option) any later version.
- *  
- *     Neither Dag Brattli nor University of Tromsř admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
- *
- *     Applicable Models : Tecra 510CDT, 500C Series, 530CDT, 520CDT,
- *     740CDT, Portege 300CT, 660CDT, Satellite 220C Series, 
- *     Satellite Pro, 440C Series, 470CDT, 460C Series, 480C Series
- *
- ********************************************************************/
-
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/malloc.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/byteorder.h>
-
-#include <net/irda/wrapper.h>
-#include <net/irda/irda.h>
-#include <net/irda/irmod.h>
-#include <net/irda/irlap_frame.h>
-#include <net/irda/irda_device.h>
-
-#include <net/irda/uircc.h>
-#include <net/irda/irport.h>
-
-static char *driver_name = "uircc";
-
-#define CHIP_IO_EXTENT 16
-
-static unsigned int io[]  = { 0x300, ~0, ~0, ~0 };
-static unsigned int io2[] = { 0x3e8, 0, 0, 0};
-static unsigned int irq[] = { 11, 0, 0, 0 };
-static unsigned int dma[] = { 5, 0, 0, 0 };
-
-static struct uircc_cb *dev_self[] = { NULL, NULL, NULL, NULL};
-
-/* Some prototypes */
-static int  uircc_open(int i, unsigned int iobase, unsigned int board_addr, 
-		       unsigned int irq, unsigned int dma);
-#ifdef MODULE
-static int  uircc_close(struct irda_device *idev);
-#endif /* MODULE */
-static int  uircc_probe(int iobase, int board_addr, int irq, int dma);
-static int  uircc_dma_receive(struct irda_device *idev); 
-static int  uircc_dma_receive_complete(struct irda_device *idev, int iobase);
-static int  uircc_hard_xmit(struct sk_buff *skb, struct device *dev);
-static void uircc_dma_write(struct irda_device *idev, int iobase);
-static void uircc_change_speed(struct irda_device *idev, int baud);
-static void uircc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void uircc_wait_until_sent(struct irda_device *idev);
-static int  uircc_is_receiving(struct irda_device *idev);
-static int uircc_toshiba_cmd(int *retval, int arg0, int arg1, int arg2);
-static int  uircc_net_init(struct device *dev);
-static int  uircc_net_open(struct device *dev);
-static int  uircc_net_close(struct device *dev);
-
-/*
- * Function uircc_init ()
- *
- *    Initialize chip. Just try to find out how many chips we are dealing with
- *    and where they are
- */
-__initfunc(int uircc_init(void))
-{
-	int i;
-
-	for ( i=0; (io[i] < 2000) && (i < 4); i++) {
-		int ioaddr = io[i];
-		if (check_region(ioaddr, CHIP_IO_EXTENT) < 0)
-			continue;
-		if (uircc_open(i, io[i], io2[i], irq[i], dma[i]) == 0)
-			return 0;
-	}
-	return -ENODEV;
-}
-
-/*
- * Function uircc_cleanup ()
- *
- *    Close all configured chips
- *
- */
-#ifdef MODULE
-static void uircc_cleanup(void)
-{
-	int i;
-
-        DEBUG(4, __FUNCTION__ "()\n");
-
-	for (i=0; i < 4; i++) {
-		if (dev_self[i])
-			uircc_close(&(dev_self[i]->idev));
-	}
-}
-#endif /* MODULE */
-
-/*
- * Function uircc_open (iobase, irq)
- *
- *    Open driver instance
- *
- */
-static int uircc_open(int i, unsigned int iobase, unsigned int iobase2, 
-		      unsigned int irq, unsigned int dma)
-{
-	struct uircc_cb *self;
-	struct irda_device *idev;
-	int ret;
-
-	DEBUG(4, __FUNCTION__ "()\n");
-
-	if ((uircc_probe(iobase, iobase2, irq, dma)) == -1)
-		return -1;
-	
-	/*
-	 *  Allocate new instance of the driver
-	 */
-	self = kmalloc( sizeof(struct uircc_cb), GFP_KERNEL);
-	if (self == NULL) {
-		printk(KERN_ERR "IrDA: Can't allocate memory for "
-		       "IrDA control block!\n");
-		return -ENOMEM;
-	}
-	memset(self, 0, sizeof(struct uircc_cb));
-   
-	/* Need to store self somewhere */
-	dev_self[i] = self;
-
-	idev = &self->idev;
-
-	/* Initialize IO */
-	idev->io.iobase    = iobase;
-        idev->io.iobase2   = iobase2; /* Used by irport */
-        idev->io.irq       = irq;
-        idev->io.io_ext    = CHIP_IO_EXTENT;
-        idev->io.io_ext2   = 8;       /* Used by irport */
-        idev->io.dma       = dma;
-        idev->io.fifo_size = 16;
-
-	/* Lock the port that we need */
-	ret = check_region(idev->io.iobase, idev->io.io_ext);
-	if (ret < 0) { 
-		DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
-		      idev->io.iobase);
-		/* uircc_cleanup( self->idev);  */
-		return -ENODEV;
-	}
-	ret = check_region(idev->io.iobase2, idev->io.io_ext2);
-	if (ret < 0) { 
-		DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
-		      idev->io.iobase2);
-		/* uircc_cleanup( self->idev);  */
-		return -ENODEV;
-	}
-	request_region(idev->io.iobase, idev->io.io_ext, idev->name);
-        request_region(idev->io.iobase2, idev->io.io_ext2, idev->name);
-
-	/* Initialize QoS for this device */
-	irda_init_max_qos_capabilies(&idev->qos);
-	
-	/* The only value we must override it the baudrate */
-	idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
-		IR_115200/*IR_576000|IR_1152000 |(IR_4000000 << 8)*/;
-
-	idev->qos.min_turn_time.bits = 0x0f;
-	irda_qos_bits_to_value(&idev->qos);
-
-	idev->flags = IFF_FIR|IFF_SIR|IFF_DMA|IFF_PIO;
-	
-	/* Specify which buffer allocation policy we need */
-	idev->rx_buff.flags = GFP_KERNEL | GFP_DMA;
-	idev->tx_buff.flags = GFP_KERNEL | GFP_DMA;
-
-	/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
-	idev->rx_buff.truesize = 4000; 
-	idev->tx_buff.truesize = 4000;
-	
-	/* Initialize callbacks */
-	idev->change_speed    = uircc_change_speed;
-	idev->wait_until_sent = uircc_wait_until_sent;
-	idev->is_receiving    = uircc_is_receiving;
-     
-	/* Override the network functions we need to use */
-	idev->netdev.init            = uircc_net_init;
-	idev->netdev.hard_start_xmit = uircc_hard_xmit;
-	idev->netdev.open            = uircc_net_open;
-	idev->netdev.stop            = uircc_net_close;
-
-	irport_start(idev, iobase2);
-
-	/* Open the IrDA device */
-	irda_device_open(idev, driver_name, self);
-	
-	return 0;
-}
-
-/*
- * Function uircc_close (idev)
- *
- *    Close driver instance
- *
- */
-#ifdef MODULE
-static int uircc_close(struct irda_device *idev)
-{
-	struct uircc_cb *self;
-	int iobase;
-	int status;
-
-	DEBUG(4, __FUNCTION__ "()\n");
-
-	ASSERT(idev != NULL, return -1;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
-
-        iobase = idev->io.iobase;
-	self = (struct uircc_cb *) idev->priv;
-
-	/* Some magic to disable FIR and enable SIR */
-	uircc_toshiba_cmd(&status, 0xffff, 0x001b, 0x0000);
-
-	/* Disable modem */
-	outb(0x00, iobase+UIRCC_CR10);
-
-	irport_stop(idev, idev->io.iobase2);
-
-	/* Release the PORT that this driver is using */
-	DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", idev->io.iobase);
-	release_region(idev->io.iobase, idev->io.io_ext);
-
-	if (idev->io.iobase2) {
-		DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", 
-		      idev->io.iobase2);
-		release_region(idev->io.iobase2, idev->io.io_ext2);
-	}
-	irda_device_close(idev);
-
-	kfree(self);
-
-	return 0;
-}
-#endif /* MODULE */
-
-/*
- * Function uircc_probe (iobase, board_addr, irq, dma)
- *
- *    Returns non-negative on success.
- *
- */
-static int uircc_probe(int iobase, int iobase2, int irq, int dma) 
-{
-	int version;
-	
-	DEBUG(4, __FUNCTION__ "()\n");
-
-	/* read the chip version, should be 0x03 */
-	version = inb(iobase+UIRCC_SR8);
-
-	if (version != 0x03) {
-		DEBUG(0, __FUNCTION__ "(), Wrong chip version");	
-		return -1;
-	}
-        printk(KERN_INFO "Sharp UIRCC IrDA driver loaded. Version: 0x%02x\n",
-	       version);
-
-	/* Reset chip */
-	outb(UIRCC_CR0_SYS_RST, iobase+UIRCC_CR0);
-
-	/* Initialize some registers */
-	outb(0x03, iobase+UIRCC_CR15);
-	outb(0, iobase+UIRCC_CR11);
-	outb(0, iobase+UIRCC_CR9);
-
-	DEBUG(0, __FUNCTION__ "(), sr15=%#x\n", inb(iobase+UIRCC_SR15));
-
-	/* Enable DMA single mode */
-	outb(UIRCC_CR1_RX_DMA|UIRCC_CR1_TX_DMA|UIRCC_CR1_MUST_SET, 
-	     iobase+UIRCC_CR1);
-
-	/* Disable interrupts */
-	outb(0xff, iobase+UIRCC_CR2); 
-
-	/* Set self poll address */
-
-	return 0;
-}
-
-/*
- * Function uircc_change_speed (idev, baud)
- *
- *    Change the speed of the device
- *
- */
-static void uircc_change_speed(struct irda_device *idev, int speed)
-{
-	struct uircc_cb *self;
-	int iobase; 
-	int modem = UIRCC_CR10_SIR;
-	int status;
-
-	DEBUG(0, __FUNCTION__ "()\n");
-
-	/* Just test the high speed stuff */
-	/*speed = 4000000;*/
-
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-
-	self = idev->priv;
-	iobase = idev->io.iobase;
-
-	/* Update accounting for new speed */
-	idev->io.baudrate = speed;
-
-	/* Disable interrupts */	
-	outb(0xff, iobase+UIRCC_CR2);
-
-	switch (speed) {
-	case 9600:
-	case 19200:
-	case 37600:
-	case 57600:
-	case 115200:
- 		irport_start(idev, idev->io.iobase2);
-		irport_change_speed(idev, speed);
-
-		/* Some magic to disable FIR and enable SIR */
-		uircc_toshiba_cmd(&status, 0xffff, 0x001b, 0x0000);
-
-		modem = UIRCC_CR10_SIR;
-		break;
-	case 576000:		
-		
-		DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
-		break;
-	case 1152000:
-
-		DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
-		break;
-	case 4000000:
-		irport_stop(idev, idev->io.iobase2);
-
-		/* Some magic to disable SIR and enable FIR */
-		uircc_toshiba_cmd(&status, 0xffff, 0x001b, 0x0001);
-
-		modem = UIRCC_CR10_FIR;
-		DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
-
-		/* Set self pole address */
-		//outb(0xfe, iobase+UIRCC_CR8);
-
-	 	/* outb(0x10, iobase+UIRCC_CR11); */
-		break;
-	default:
-		DEBUG( 0, __FUNCTION__ "(), unknown baud rate of %d\n", speed);
-		break;
-	}
-
-	/* Set appropriate speed mode */
-	outb(modem, iobase+UIRCC_CR10);
-
-	idev->netdev.tbusy = 0;
-	
-	/* Enable some interrupts so we can receive frames */
-	if (speed > 115200) {
-		/* Enable DMA single mode */
-		outb(UIRCC_CR1_RX_DMA|UIRCC_CR1_TX_DMA|UIRCC_CR1_MUST_SET, 
-		     iobase+UIRCC_CR1);
-
- 		/* Enable all interrupts  */
-		outb(0, iobase+UIRCC_CR2); 
- 		uircc_dma_receive(idev);
- 	}    	
-}
-
-/*
- * Function uircc_hard_xmit (skb, dev)
- *
- *    Transmit the frame!
- *
- */
-static int uircc_hard_xmit(struct sk_buff *skb, struct device *dev)
-{
-	struct irda_device *idev;
-	int iobase;
-	int mtt;
-	
-	idev = (struct irda_device *) dev->priv;
-
-	ASSERT(idev != NULL, return 0;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;);
-
-	iobase = idev->io.iobase;
-
-	DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
-	
-	/* Reset carrier latch */
-	/*outb(0x02, iobase+UIRCC_CR0);*/
-
-	/* Use irport for SIR speeds */
-	if (idev->io.baudrate <= 115200) {
-		return irport_hard_xmit(skb, dev);
-	}
-	
-	DEBUG(0, __FUNCTION__ "(), sr0=%#x, sr1=%#x, sr2=%#x, sr3=%#x, sr10=%#x, sr11=%#x\n",
-	      inb(iobase+UIRCC_SR0), inb(iobase+UIRCC_SR3),
-	      inb(iobase+UIRCC_SR2), inb(iobase+UIRCC_SR3), 
-	      inb(iobase+UIRCC_SR10), inb(iobase+UIRCC_SR11));
-
-	/* Lock transmit buffer */
-	if (irda_lock((void *) &dev->tbusy) == FALSE)
-		return -EBUSY;
-
-	memcpy(idev->tx_buff.data, skb->data, skb->len);
-
-	/* Make sure that the length is a multiple of 16 bits */
-	if (skb->len & 0x01)
-		skb->len++;
-
-	idev->tx_buff.len = skb->len;
-	idev->tx_buff.data = idev->tx_buff.head;
-	
-	mtt = irda_get_mtt(skb);
-	
-	/* Use udelay for delays less than 50 us. */
-	if (mtt)
-		udelay(mtt);
-	
-	/* Enable transmit interrupts */
- 	outb(0, iobase+UIRCC_CR2);
-
-	uircc_dma_write(idev, iobase);
-	
-	dev_kfree_skb(skb);
-
-	return 0;
-}
-
-/*
- * Function uircc_dma_write (idev, iobase)
- *
- *    Transmit data using DMA
- *
- */
-static void uircc_dma_write(struct irda_device *idev, int iobase)
-{
-	struct uircc_cb *self;
-
-	DEBUG(4, __FUNCTION__ "()\n");
-
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-
-	self = idev->priv;
-
-	/* Receiving disable */
-	self->cr3 &= ~UIRCC_CR3_RECV_EN;
-	outb(self->cr3, iobase+UIRCC_CR3);
-
-	/* Set modem */
-	outb(0x80, iobase+UIRCC_CR10);
-
-	/* Enable transmit DMA */
-	outb(UIRCC_CR1_TX_DMA|UIRCC_CR1_MUST_SET, iobase+UIRCC_CR1);
-
-	ASSERT((((__u32)(idev->tx_buff.data)) & 0x01) != 0x01, return;);
-
-	setup_dma(idev->io.dma, idev->tx_buff.data, idev->tx_buff.len, 
-		  DMA_MODE_WRITE);
-	
-	idev->io.direction = IO_XMIT;
-
-	/* Set frame length (should be the real length without padding */
-	outb(idev->tx_buff.len & 0xff, iobase+UIRCC_CR4); /* Low byte */
-	outb(idev->tx_buff.len >> 8, iobase+UIRCC_CR5);   /* High byte */
-
-	/* Enable transmit and transmit CRC */
-	self->cr3 |= (UIRCC_CR3_XMIT_EN|UIRCC_CR3_TX_CRC_EN);
-	outb(self->cr3, iobase+UIRCC_CR3);
-}
-
-/*
- * Function uircc_dma_xmit_complete (idev)
- *
- *    The transfer of a frame in finished. This function will only be called 
- *    by the interrupt handler
- *
- */
-static void uircc_dma_xmit_complete( struct irda_device *idev, int underrun)
-{
-	struct uircc_cb *self;
-	int iobase;
-	int len;
-
-	DEBUG(4, __FUNCTION__ "()\n");
-
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-
-	self = idev->priv;
-
-	iobase = idev->io.iobase;
-
-	/* Select TX counter */
-	outb(UIRCC_CR0_CNT_SWT, iobase+UIRCC_CR0);
-
-	/* Read TX length counter */
-	len  = inb(iobase+UIRCC_SR4);      /* Low byte */
-	len |= inb(iobase+UIRCC_SR5) << 8; /* High byte */
-
-	DEBUG(4, __FUNCTION__ "(), sent %d bytes\n", len);
-
-	/* Disable transmit */
-	self->cr3 &= ~UIRCC_CR3_XMIT_EN;
-	outb(self->cr3, iobase+UIRCC_CR3);
-
-	/* Transmit reset (just to be sure) */
-	outb(UIRCC_CR0_XMIT_RST, iobase+UIRCC_CR0);
-	
-	/* Check for underrrun! */
-	if (underrun) {
-		idev->stats.tx_errors++;
-		idev->stats.tx_fifo_errors++;		
-	} else {
-		idev->stats.tx_packets++;
-		idev->stats.tx_bytes += idev->tx_buff.len;
-	}
-
-	/* Unlock tx_buff and request another frame */
-	idev->netdev.tbusy = 0; /* Unlock */
-	idev->media_busy = FALSE;
-	
-	/* Tell the network layer, that we can accept more frames */
-	mark_bh(NET_BH);
-}
-
-/*
- * Function uircc_dma_receive (idev)
- *
- *    Get ready for receiving a frame. The device will initiate a DMA
- *    if it starts to receive a frame.
- *
- */
-static int uircc_dma_receive(struct irda_device *idev) 
-{
-	struct uircc_cb *self;
-	int iobase;
-
-	ASSERT(idev != NULL, return -1;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
-
-	DEBUG(4, __FUNCTION__ "\n");
-
-	self = idev->priv;
-	iobase= idev->io.iobase;
-
-	/* Transmit disable */
-	/* self->cr3 &= ~UIRCC_CR3_XMIT_EN; */
-	self->cr3 = 0;
-	outb(self->cr3, iobase+UIRCC_CR3);
-
-	/* Transmit reset (just in case) */
-	outb(UIRCC_CR0_XMIT_RST|0x17, iobase+UIRCC_CR0);
-
-	/* Set modem */
-	outb(0x08, iobase+UIRCC_CR10);
-
-	/* Enable receiving with CRC */
-	self->cr3 = (UIRCC_CR3_RECV_EN|UIRCC_CR3_RX_CRC_EN);
-	outb(self->cr3, iobase+UIRCC_CR3);
-
-	/* Make sure Rx DMA is set */
- 	outb(UIRCC_CR1_RX_DMA|UIRCC_CR1_MUST_SET, iobase+UIRCC_CR1);
-
-	/* Rx reset */
-	/* outb(UIRCC_CR0_RECV_RST, iobase+UIRCC_CR0); */
-
-	setup_dma(idev->io.dma, idev->rx_buff.data, 
-		  idev->rx_buff.truesize, DMA_MODE_READ);
-	
-	/* driver->media_busy = FALSE; */
-	idev->io.direction = IO_RECV;
-	idev->rx_buff.data = idev->rx_buff.head;
-
-#if 0
-	/* Enable receiving with CRC */
-	self->cr3 = (UIRCC_CR3_RECV_EN|UIRCC_CR3_RX_CRC_EN);
-	outb(self->cr3, iobase+UIRCC_CR3);
-#endif
-	DEBUG(4, __FUNCTION__ "(), cr3=%#x\n", self->cr3);
-	
-	/* Address check? */
-
-	return 0;
-}
-
-/*
- * Function uircc_dma_receive_complete (idev)
- *
- *    Finished with receiving frames
- *
- *    
- */
-static int uircc_dma_receive_complete(struct irda_device *idev, int iobase)
-{
-	struct sk_buff *skb;
-	struct uircc_cb *self;
-	int len;
-
-	self = idev->priv;
-
-	DEBUG(0, __FUNCTION__ "()\n");
-
-	/* Check for CRC or framing error */
-	if (inb(iobase+UIRCC_SR0) & UIRCC_SR0_RX_CRCFRM) {
-		DEBUG(0, __FUNCTION__ "(), CRC or FRAME error\n");
-		return -1;
-	}
-
-	/* Select receive length counter */
-	outb(0x00, iobase+UIRCC_CR0);
-
-	/* Read frame length */
-	len = inb(iobase+UIRCC_SR4);       /* Low byte */
-	len |= inb(iobase+UIRCC_SR5) << 8; /* High byte */
-
-	DEBUG(0, __FUNCTION__ "(), len=%d\n", len);
-
-	/* Receiving disable */
-	self->cr3 &= ~UIRCC_CR3_RECV_EN;
-	outb(self->cr3, iobase+UIRCC_CR3);
-
-	skb = dev_alloc_skb(len+1);
-	if (skb == NULL)  {
-		printk(KERN_INFO __FUNCTION__ 
-		       "(), memory squeeze, dropping frame.\n");
-				/* Restore bank register */
-		return FALSE;
-	}
-			
-	/* Make sure IP header gets aligned */
-	skb_reserve(skb, 1);
-
-	/* Copy frame without CRC */
-	/* if ( idev->io.baudrate < 4000000) { */
-/* 		skb_put( skb, len-2); */
-/* 		memcpy( skb->data, idev->rx_buff.head, len-2); */
-/* 	} else { */
-/* 		skb_put( skb, len-4); */
-/* 		memcpy( skb->data, idev->rx_buff.head, len-4); */
-/* 	} */
-
-	skb_put(skb, len);
-	memcpy(skb->data, idev->rx_buff.data, len);
-	idev->stats.rx_packets++;
-
-	skb->dev = &idev->netdev;
-	skb->mac.raw  = skb->data;
-	skb->protocol = htons(ETH_P_IRDA);
-	netif_rx(skb);
-
-	return TRUE;
-}
-
-/*
- * Function uircc_interrupt (irq, dev_id, regs)
- *
- *    An interrupt from the chip has arrived. Time to do some work
- *
- */
-static void uircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	__u8 sr3;
-	int iobase;
-
-	struct irda_device *idev = (struct irda_device *) dev_id;
-
-	if (idev == NULL) {
-		printk( KERN_WARNING "%s: irq %d for unknown device.\n", 
-			driver_name, irq);
-		return;
-	}
-	
-	if (idev->io.baudrate <= 115200)
-		return irport_interrupt( irq, dev_id, regs);
-
-	iobase = idev->io.iobase;
-
-	/* Read interrupt status */
-	sr3 = inb( iobase+UIRCC_SR3); 
-	if (!sr3) {
-		DEBUG(4,"**\n");
-		return;
-	}
-	idev->netdev.interrupt = 1;
-
-	DEBUG(4, __FUNCTION__ "(), sr3=%#x, sr2=%#x, sr10=%#x\n", 
-	      inb( iobase+UIRCC_SR3), inb( iobase+UIRCC_SR2), 
-	      inb( iobase+UIRCC_SR10));
-
-	/*
-	 *  Check what interrupt this is. The UIRCC will not report two
-	 *  different interrupts at the same time!
-	 */
-	switch(sr3) {
-	case UIRCC_SR3_RX_EOF: /* Check for end of frame */
-		uircc_dma_receive_complete(idev, iobase);
-		break;
-	case UIRCC_SR3_TXUR:   /* Check for transmit underrun */
-		uircc_dma_xmit_complete(idev, TRUE);
-		uircc_dma_receive(idev);
-		outb(0, iobase+UIRCC_CR2); 
-		break;
-	case UIRCC_SR3_TX_DONE:
-		uircc_dma_xmit_complete(idev, FALSE);
-		uircc_dma_receive(idev);
-
-		outb(0x0d, iobase+UIRCC_CR2);
-		break;
-	case UIRCC_SR3_TMR_OUT:
-		/* Disable timer */
-		outb(inb(iobase+UIRCC_CR11) & ~UIRCC_CR11_TMR_EN, 
-		     iobase+UIRCC_CR11);
-		break;
-	default:
-		DEBUG(0, __FUNCTION__ "(), unknown interrupt status=%#x\n",
-		      sr3);
-		break;
-	}	
-	idev->netdev.interrupt = 0;
-}
-
-/*
- * Function uircc_wait_until_sent (idev)
- *
- *    This function should put the current thread to sleep until all data 
- *    have been sent, so it is safe to change the speed.
- */
-static void uircc_wait_until_sent( struct irda_device *idev)
-{
-	/* Just delay 60 ms */
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(6);
-}
-
-/*
- * Function uircc_is_receiving (idev)
- *
- *    Return TRUE is we are currently receiving a frame
- *
- */
-static int uircc_is_receiving( struct irda_device *idev)
-{
-	int status = FALSE;
-	/* int iobase; */
-
-	ASSERT(idev != NULL, return FALSE;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return FALSE;);
-
-	if (idev->io.baudrate > 115200) {
-		
-	} else 
-		status = (idev->rx_buff.state != OUTSIDE_FRAME);
-	
-	return status;
-}
-
-/*
- * Function uircc_net_init (dev)
- *
- *    Initialize network device
- *
- */
-static int uircc_net_init( struct device *dev)
-{
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	/* Setup to be a normal IrDA network device driver */
-	irda_device_setup(dev);
-
-	/* Insert overrides below this line! */
-
-	return 0;
-}
-
-
-/*
- * Function uircc_net_open (dev)
- *
- *    Start the device
- *
- */
-static int uircc_net_open(struct device *dev)
-{
-	struct irda_device *idev;
-	int iobase;
-	
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	ASSERT(dev != NULL, return -1;);
-	idev = (struct irda_device *) dev->priv;
-	
-	ASSERT(idev != NULL, return 0;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;);
-	
-	iobase = idev->io.iobase;
-
-	if (request_irq(idev->io.irq, uircc_interrupt, 0, idev->name, 
-			(void *) idev)) {
-		return -EAGAIN;
-	}
-	/*
-	 * Always allocate the DMA channel after the IRQ,
-	 * and clean up on failure.
-	 */
-	if (request_dma(idev->io.dma, idev->name)) {
-		free_irq(idev->io.irq, idev);
-		return -EAGAIN;
-	}
-		
-	/* Ready to play! */
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
-
-	/* turn on interrupts */
-	
-	MOD_INC_USE_COUNT;
-
-	return 0;
-}
-
-/*
- * Function uircc_net_close (dev)
- *
- *    Stop the device
- *
- */
-static int uircc_net_close(struct device *dev)
-{
-	struct irda_device *idev;
-	int iobase;
-
-	DEBUG(4, __FUNCTION__ "()\n");
-	
-	/* Stop device */
-	dev->tbusy = 1;
-	dev->start = 0;
-
-	ASSERT(dev != NULL, return -1;);
-	idev = (struct irda_device *) dev->priv;
-	
-	ASSERT(idev != NULL, return 0;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;);
-	
-	iobase = idev->io.iobase;
-
-	disable_dma(idev->io.dma);
-
-	/* Disable interrupts */
-       
-	free_irq(idev->io.irq, idev);
-	free_dma(idev->io.dma);
-
-	MOD_DEC_USE_COUNT;
-
-	return 0;
-}
-
-/*
- * Function uircc_toshiba_cmd (arg0, arg1, arg2)
- *
- *    disable FIR: uircc_toshiba_cmd(&status, 0xffff, 0x001b, 0x0000);
- *    enable  FIR: uircc_toshiba_cmd(&status, 0xffff, 0x001b, 0x0001);
- *    IRDA status: uircc_toshiba_cmd(&status, 0xfefe, 0x001b, 0x0000);
- */
-static int uircc_toshiba_cmd(int *retval, int arg0, int arg1, int arg2)
-{
-	char return_code = 0;
-
-	__asm__ volatile ("inb   $0xb2,%%al; "
-			  "movb  %%ah,%%al;  "
-			  : /* Output */
-			  "=al"  (return_code),
-			  "=ecx" (*retval)
-			  : /* Input */
-			  "ax" (arg0),
-			  "bx" (arg1),
-			  "cx" (arg2)
-		);
-	/*
-	 * Return
-	 * 0x00 = OK
-	 * 0x80 = Function not supported by system
-	 * 0x83 = Input data error
-	 */
-	return (int) return_code;
-}
-
-#ifdef MODULE
-
-/*
- * Function init_module (void)
- *
- *    
- *
- */
-int init_module(void)
-{
-	return uircc_init();
-}
-
-/*
- * Function cleanup_module (void)
- *
- *    
- *
- */
-void cleanup_module(void)
-{
-	uircc_cleanup();
-}
-#endif /* MODULE */
-
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/irda/w83977af_ir.c linux.15p9/drivers/net/irda/w83977af_ir.c
--- linux.vanilla/drivers/net/irda/w83977af_ir.c	Sat Aug 14 02:26:48 1999
+++ linux.15p9/drivers/net/irda/w83977af_ir.c	Tue Jan 18 01:08:18 2000
@@ -6,23 +6,23 @@
  * Status:        Experimental.
  * Author:        Paul VanderSpek
  * Created at:    Wed Nov  4 11:46:16 1998
- * Modified at:   Fri May 21 22:18:19 1999
+ * Modified at:   Tue Jan 11 13:09:48 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>
- *     Copyright (c) 1998 Corel Computer Corp.
+ *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>
+ *     Copyright (c) 1998-1999 Rebel.com
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
  *  
- *     Neither Paul VanderSpek nor Corel Computer Corp. admit liability
- *     nor provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
+ *     Neither Paul VanderSpek nor Rebel.com admit liability nor provide
+ *     warranty for any of this software. This material is provided "AS-IS"
+ *     and at no charge.
  *     
  *     If you find bugs in this file, its very likely that the same bug
- *     will also be in pc87108.c since the implementations is quite
+ *     will also be in pc87108.c since the implementations are quite
  *     similar.
  *
  *     Notice that all functions that needs to access the chip in _any_
@@ -49,6 +49,7 @@
 #include <linux/delay.h>
 #include <linux/malloc.h>
 #include <linux/init.h>
+#include <linux/rtnetlink.h>
 
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -61,43 +62,50 @@
 #include <net/irda/w83977af.h>
 #include <net/irda/w83977af_ir.h>
 
-#define CONFIG_NETWINDER                 /* Adjust to NetWinder differences */
-#undef  CONFIG_NETWINDER_TX_DMA_PROBLEMS /* Not needed */
-#define CONFIG_NETWINDER_RX_DMA_PROBLEMS /* Must have this one! */
-#undef  CONFIG_USE_INTERNAL_TIMER        /* Just cannot make that timer work */
-#define CONFIG_USE_W977_PNP              /* Currently needed */
+#ifdef  CONFIG_ARCH_VNC            /* Adjust to NetWinder differences */
+#undef  CONFIG_VNC_TX_DMA_PROBLEMS /* Not needed */
+#define CONFIG_VNC_RX_DMA_PROBLEMS /* Must have this one! */
+#endif
+#undef  CONFIG_USE_INTERNAL_TIMER  /* Just cannot make that timer work */
+#define CONFIG_USE_W977_PNP        /* Currently needed */
 #define PIO_MAX_SPEED       115200 
 
 static char *driver_name = "w83977af_ir";
-static int  qos_mtt_bits = 0x07;           /* 1 ms or more */
+static int  qos_mtt_bits = 0x07;   /* 1 ms or more */
 
 #define CHIP_IO_EXTENT 8
 
 static unsigned int io[] = { 0x180, ~0, ~0, ~0 };
+#ifdef CONFIG_ARCH_VNC             /* Adjust to NetWinder differences */
 static unsigned int irq[] = { 6, 0, 0, 0 };
-static unsigned int dma[] = 
-{ 1, 0, 0, 0 };
+#else
+static unsigned int irq[] = { 11, 0, 0, 0 };
+#endif
+static unsigned int dma[] = { 1, 0, 0, 0 };
+static unsigned int efbase[] = { W977_EFIO_BASE, W977_EFIO2_BASE };
+static unsigned int efio = W977_EFIO_BASE;
 
 static struct w83977af_ir *dev_self[] = { NULL, NULL, NULL, NULL};
 
 /* Some prototypes */
 static int  w83977af_open(int i, unsigned int iobase, unsigned int irq, 
                           unsigned int dma);
-static int  w83977af_close(struct irda_device *idev);
+static int  w83977af_close(struct w83977af_ir *self);
 static int  w83977af_probe(int iobase, int irq, int dma);
-static int  w83977af_dma_receive(struct irda_device *idev); 
-static int  w83977af_dma_receive_complete(struct irda_device *idev);
+static int  w83977af_dma_receive(struct w83977af_ir *self); 
+static int  w83977af_dma_receive_complete(struct w83977af_ir *self);
 static int  w83977af_hard_xmit(struct sk_buff *skb, struct device *dev);
 static int  w83977af_pio_write(int iobase, __u8 *buf, int len, int fifo_size);
-static void w83977af_dma_write(struct irda_device *idev, int iobase);
-static void w83977af_change_speed(struct irda_device *idev, int baud);
+static void w83977af_dma_write(struct w83977af_ir *self, int iobase);
+static void w83977af_change_speed(struct w83977af_ir *self, __u32 speed);
 static void w83977af_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void w83977af_wait_until_sent(struct irda_device *idev);
-static int  w83977af_is_receiving(struct irda_device *idev);
+static int  w83977af_is_receiving(struct w83977af_ir *self);
 
 static int  w83977af_net_init(struct device *dev);
 static int  w83977af_net_open(struct device *dev);
 static int  w83977af_net_close(struct device *dev);
+static int  w83977af_net_ioctl(struct device *dev, struct ifreq *rq, int cmd);
+static struct net_device_stats *w83977af_net_get_stats(struct device *dev);
 
 /*
  * Function w83977af_init ()
@@ -105,17 +113,17 @@
  *    Initialize chip. Just try to find out how many chips we are dealing with
  *    and where they are
  */
-__initfunc(int w83977af_init(void))
+int __init w83977af_init(void)
 {
         int i;
 
-	DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
 	for (i=0; (io[i] < 2000) && (i < 4); i++) { 
 		int ioaddr = io[i];
 		if (check_region(ioaddr, CHIP_IO_EXTENT) < 0)
 			continue;
-		if (w83977af_open( i, io[i], irq[i], dma[i]) == 0)
+		if (w83977af_open(i, io[i], irq[i], dma[i]) == 0)
 			return 0;
 	}
 	return -ENODEV;
@@ -132,11 +140,11 @@
 {
 	int i;
 
-        DEBUG(4, __FUNCTION__ "()\n");
+        IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	for (i=0; i < 4; i++) {
 		if (dev_self[i])
-			w83977af_close(&(dev_self[i]->idev));
+			w83977af_close(dev_self[i]);
 	}
 }
 #endif /* MODULE */
@@ -147,14 +155,15 @@
  *    Open driver instance
  *
  */
-int w83977af_open( int i, unsigned int iobase, unsigned int irq, 
-		   unsigned int dma)
+int w83977af_open(int i, unsigned int iobase, unsigned int irq, 
+		  unsigned int dma)
 {
-	struct irda_device *idev;
+	struct device *dev;
         struct w83977af_ir *self;
 	int ret;
+	int err;
 
-	DEBUG( 0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
 	if (w83977af_probe(iobase, irq, dma) == -1)
 		return -1;
@@ -173,222 +182,254 @@
 	/* Need to store self somewhere */
 	dev_self[i] = self;
 
-	idev = &self->idev;
-
 	/* Initialize IO */
-	idev->io.iobase    = iobase;
-        idev->io.irq       = irq;
-        idev->io.io_ext    = CHIP_IO_EXTENT;
-        idev->io.dma       = dma;
-        idev->io.fifo_size = 32;
+	self->io.fir_base   = iobase;
+        self->io.irq       = irq;
+        self->io.fir_ext   = CHIP_IO_EXTENT;
+        self->io.dma       = dma;
+        self->io.fifo_size = 32;
 
 	/* Lock the port that we need */
-	ret = check_region(idev->io.iobase, idev->io.io_ext);
+	ret = check_region(self->io.fir_base, self->io.fir_ext);
 	if (ret < 0) { 
-		DEBUG( 0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
-		       idev->io.iobase);
-		/* w83977af_cleanup( self->idev);  */
+		IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+		      self->io.fir_base);
+		/* w83977af_cleanup( self);  */
 		return -ENODEV;
 	}
-	request_region(idev->io.iobase, idev->io.io_ext, idev->name);
+	request_region(self->io.fir_base, self->io.fir_ext, driver_name);
 
 	/* Initialize QoS for this device */
-	irda_init_max_qos_capabilies(&idev->qos);
+	irda_init_max_qos_capabilies(&self->qos);
 	
 	/* The only value we must override it the baudrate */
 
 	/* FIXME: The HP HDLS-1100 does not support 1152000! */
-	idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+	self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
 		IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
 
 	/* The HP HDLS-1100 needs 1 ms according to the specs */
-	idev->qos.min_turn_time.bits = qos_mtt_bits;
-	irda_qos_bits_to_value(&idev->qos);
+	self->qos.min_turn_time.bits = qos_mtt_bits;
+	irda_qos_bits_to_value(&self->qos);
 	
-	idev->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO;
-
-	/* Specify which buffer allocation policy we need */
-	idev->rx_buff.flags = GFP_KERNEL | GFP_DMA;
-	idev->tx_buff.flags = GFP_KERNEL | GFP_DMA;
+	self->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO;
 
 	/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
-	idev->rx_buff.truesize = 14384; 
-	idev->tx_buff.truesize = 4000;
+	self->rx_buff.truesize = 14384; 
+	self->tx_buff.truesize = 4000;
+	
+	/* Allocate memory if needed */
+	self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
+					      GFP_KERNEL|GFP_DMA);
+	if (self->rx_buff.head == NULL)
+		return -ENOMEM;
+
+	memset(self->rx_buff.head, 0, self->rx_buff.truesize);
+	
+	self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
+					      GFP_KERNEL|GFP_DMA);
+	if (self->tx_buff.head == NULL) {
+		kfree(self->rx_buff.head);
+		return -ENOMEM;
+	}
+	memset(self->tx_buff.head, 0, self->tx_buff.truesize);
+
+	self->rx_buff.in_frame = FALSE;
+	self->rx_buff.state = OUTSIDE_FRAME;
+	self->tx_buff.data = self->tx_buff.head;
+	self->rx_buff.data = self->rx_buff.head;
 	
-	/* Initialize callbacks */
-	idev->change_speed    = w83977af_change_speed;
-	idev->wait_until_sent = w83977af_wait_until_sent;
-        idev->is_receiving    = w83977af_is_receiving;
+	if (!(dev = dev_alloc("irda%d", &err))) {
+		ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
+		return -ENOMEM;
+	}
+	/* dev_alloc doesn't clear the struct, so lets do a little hack */
+	memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct device)-sizeof(char*));
+
+	dev->priv = (void *) self;
+	self->netdev = dev;
 
 	/* Override the network functions we need to use */
-	idev->netdev.init            = w83977af_net_init;
-	idev->netdev.hard_start_xmit = w83977af_hard_xmit;
-	idev->netdev.open            = w83977af_net_open;
-	idev->netdev.stop            = w83977af_net_close;
+	dev->init            = w83977af_net_init;
+	dev->hard_start_xmit = w83977af_hard_xmit;
+	dev->open            = w83977af_net_open;
+	dev->stop            = w83977af_net_close;
+	dev->do_ioctl        = w83977af_net_ioctl;
+	dev->get_stats	     = w83977af_net_get_stats;
+
+	rtnl_lock();
+	err = register_netdev(dev);
+	rtnl_unlock();
+	if (err) {
+		ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
+		return -1;
+	}
 
-	/* Open the IrDA device */
-	irda_device_open(idev, driver_name, self);
+	MESSAGE("IrDA: Registered device %s\n", dev->name);
 	
 	return 0;
 }
 
 /*
- * Function w83977af_close (idev)
+ * Function w83977af_close (self)
  *
  *    Close driver instance
  *
  */
-static int w83977af_close( struct irda_device *idev)
+static int w83977af_close(struct w83977af_ir *self)
 {
-	struct w83977af_ir *self;
 	int iobase;
 
-	DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
-	ASSERT(idev != NULL, return -1;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
-
-        iobase = idev->io.iobase;
-	self = (struct w83977af_ir *) idev->priv;
+        iobase = self->io.fir_base;
 
 #ifdef CONFIG_USE_W977_PNP
 	/* enter PnP configuration mode */
-	w977_efm_enter();
+	w977_efm_enter(efio);
 
-	w977_select_device(W977_DEVICE_IR);
+	w977_select_device(W977_DEVICE_IR, efio);
 
 	/* Deactivate device */
-	w977_write_reg(0x30, 0x00);
+	w977_write_reg(0x30, 0x00, efio);
 
-	w977_efm_exit();
+	w977_efm_exit(efio);
 #endif /* CONFIG_USE_W977_PNP */
+
+	/* Remove netdevice */
+	if (self->netdev) {
+		rtnl_lock();
+		unregister_netdevice(self->netdev);
+		rtnl_unlock();
+		/* Must free the old-style 2.2.x device */
+		kfree(self->netdev);
+	}
+
 	/* Release the PORT that this driver is using */
-	DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n", 
-	      idev->io.iobase);
-	release_region(idev->io.iobase, idev->io.io_ext);
+	IRDA_DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n", 
+	      self->io.fir_base);
+	release_region(self->io.fir_base, self->io.fir_ext);
 
-	irda_device_close(idev);
+	if (self->tx_buff.head)
+		kfree(self->tx_buff.head);
+	
+	if (self->rx_buff.head)
+		kfree(self->rx_buff.head);
 
 	kfree(self);
 
 	return 0;
 }
 
-/*
- * Function w83977af_probe (iobase, irq, dma)
- *
- *    Returns non-negative on success.
- *
- */
 int w83977af_probe( int iobase, int irq, int dma)
 {
-	int version;
-	
-	DEBUG( 0, __FUNCTION__ "()\n");
+  	int version;
+	int i;
+  	
+ 	for (i=0; i < 2; i++) {
+ 		IRDA_DEBUG( 0, __FUNCTION__ "()\n");
 #ifdef CONFIG_USE_W977_PNP
-	/* Enter PnP configuration mode */
-	w977_efm_enter();
-
-	w977_select_device(W977_DEVICE_IR);
-
-	/* Configure PnP port, IRQ, and DMA channel */
-	w977_write_reg(0x60, (iobase >> 8) & 0xff);
-	w977_write_reg(0x61, (iobase) & 0xff);
-
-	w977_write_reg(0x70, irq);
-#ifdef CONFIG_NETWINDER
-	w977_write_reg(0x74, dma+1); /* Netwinder uses 1 higher than Linux */
+ 		/* Enter PnP configuration mode */
+		w977_efm_enter(efbase[i]);
+  
+ 		w977_select_device(W977_DEVICE_IR, efbase[i]);
+  
+ 		/* Configure PnP port, IRQ, and DMA channel */
+ 		w977_write_reg(0x60, (iobase >> 8) & 0xff, efbase[i]);
+ 		w977_write_reg(0x61, (iobase) & 0xff, efbase[i]);
+  
+ 		w977_write_reg(0x70, irq, efbase[i]);
+#ifdef CONFIG_ARCH_VNC
+		/* Netwinder uses 1 higher than Linux */
+ 		w977_write_reg(0x74, dma+1, efbase[i]);
 #else
-	w977_write_reg(0x74, dma);   
-#endif
-	w977_write_reg(0x75, 0x04);  /* Disable Tx DMA */
-	
-	/* Set append hardware CRC, enable IR bank selection */	
-	w977_write_reg(0xf0, APEDCRC|ENBNKSEL);
-
-	/* Activate device */
-	w977_write_reg(0x30, 0x01);
-
-	w977_efm_exit();
-#endif
- 	/* Disable Advanced mode */
- 	switch_bank(iobase, SET2);
- 	outb(iobase+2, 0x00);  
-
-	/* Turn on UART (global) interrupts */
-	switch_bank(iobase, SET0);
-	outb(HCR_EN_IRQ, iobase+HCR);
-	
-	/* Switch to advanced mode */
-	switch_bank(iobase, SET2);
-	outb(inb(iobase+ADCR1) | ADCR1_ADV_SL, iobase+ADCR1);
-
-	/* Set default IR-mode */
-	switch_bank(iobase, SET0);
-	outb(HCR_SIR, iobase+HCR);
-
-	/* Read the Advanced IR ID */
-	switch_bank(iobase, SET3);
-	version = inb(iobase+AUID);
-	
-	/* Should be 0x1? */
-	if (0x10 != (version & 0xf0)) {
-		DEBUG( 0, __FUNCTION__ "(), Wrong chip version");	
-		return -1;
-	}
-	
-	/* Set FIFO size to 32 */
-	switch_bank(iobase, SET2);
-	outb(ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2);	
-	
-	/* Set FIFO threshold to TX17, RX16 */
-	switch_bank(iobase, SET0);	
-	outb(UFR_RXTL|UFR_TXTL|UFR_TXF_RST|UFR_RXF_RST|UFR_EN_FIFO,iobase+UFR);
-
-	/* Receiver frame length */
-	switch_bank(iobase, SET4);
-	outb(2048 & 0xff, iobase+6);
-	outb((2048 >> 8) & 0x1f, iobase+7);
-
-	/* 
-	 * Init HP HSDL-1100 transceiver. 
-	 * 
-	 * Set IRX_MSL since we have 2 * receive paths IRRX, and
-	 * IRRXH. Clear IRSL0D since we want IRSL0 * to be a input pin used
-	 * for IRRXH 
-	 *
-	 *   IRRX  pin 37 connected to receiver 
-	 *   IRTX  pin 38 connected to transmitter
-	 *   FIRRX pin 39 connected to receiver      (IRSL0) 
-	 *   CIRRX pin 40 connected to pin 37
-	 */
-	switch_bank(iobase, SET7);
-	outb(0x40, iobase+7);
-		
-	DEBUG(0, "W83977AF (IR) driver loaded. Version: 0x%02x\n", version);
-	
-	return 0;
+ 		w977_write_reg(0x74, dma, efbase[i]);   
+#endif /*CONFIG_ARCH_VNC */
+ 		w977_write_reg(0x75, 0x04, efbase[i]);  /* Disable Tx DMA */
+  	
+ 		/* Set append hardware CRC, enable IR bank selection */	
+ 		w977_write_reg(0xf0, APEDCRC|ENBNKSEL, efbase[i]);
+  
+ 		/* Activate device */
+ 		w977_write_reg(0x30, 0x01, efbase[i]);
+  
+ 		w977_efm_exit(efbase[i]);
+#endif /* CONFIG_USE_W977_PNP */
+  		/* Disable Advanced mode */
+  		switch_bank(iobase, SET2);
+  		outb(iobase+2, 0x00);  
+ 
+ 		/* Turn on UART (global) interrupts */
+ 		switch_bank(iobase, SET0);
+  		outb(HCR_EN_IRQ, iobase+HCR);
+  	
+  		/* Switch to advanced mode */
+  		switch_bank(iobase, SET2);
+  		outb(inb(iobase+ADCR1) | ADCR1_ADV_SL, iobase+ADCR1);
+  
+  		/* Set default IR-mode */
+  		switch_bank(iobase, SET0);
+  		outb(HCR_SIR, iobase+HCR);
+  
+  		/* Read the Advanced IR ID */
+  		switch_bank(iobase, SET3);
+  		version = inb(iobase+AUID);
+  	
+  		/* Should be 0x1? */
+  		if (0x10 == (version & 0xf0)) {
+ 			efio = efbase[i];
+ 
+ 			/* Set FIFO size to 32 */
+ 			switch_bank(iobase, SET2);
+ 			outb(ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2);	
+ 	
+ 			/* Set FIFO threshold to TX17, RX16 */
+ 			switch_bank(iobase, SET0);	
+ 			outb(UFR_RXTL|UFR_TXTL|UFR_TXF_RST|UFR_RXF_RST|
+			     UFR_EN_FIFO,iobase+UFR);
+ 
+ 			/* Receiver frame length */
+ 			switch_bank(iobase, SET4);
+			outb(2048 & 0xff, iobase+6);
+			outb((2048 >> 8) & 0x1f, iobase+7);
+
+			/* 
+			 * Init HP HSDL-1100 transceiver. 
+			 * 
+			 * Set IRX_MSL since we have 2 * receive paths IRRX, 
+			 * and IRRXH. Clear IRSL0D since we want IRSL0 * to 
+			 * be a input pin used for IRRXH 
+			 *
+			 *   IRRX  pin 37 connected to receiver 
+			 *   IRTX  pin 38 connected to transmitter
+			 *   FIRRX pin 39 connected to receiver      (IRSL0) 
+			 *   CIRRX pin 40 connected to pin 37
+			 */
+			switch_bank(iobase, SET7);
+			outb(0x40, iobase+7);
+			
+			MESSAGE("W83977AF (IR) driver loaded. "
+				"Version: 0x%02x\n", version);
+			
+			return 0;
+		} else {
+			/* Try next extented function register address */
+			IRDA_DEBUG( 0, __FUNCTION__ "(), Wrong chip version");
+		}
+  	}   	
+	return -1;
 }
 
-/*
- * Function w83977af_change_speed (idev, baud)
- *
- *    Change the speed of the device
- *
- */
-void w83977af_change_speed(struct irda_device *idev, int speed)
+void w83977af_change_speed(struct w83977af_ir *self, __u32 speed)
 {
 	int ir_mode = HCR_SIR;
 	int iobase; 
 	__u8 set;
 
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-
-	iobase = idev->io.iobase;
+	iobase = self->io.fir_base;
 
 	/* Update accounting for new speed */
-	idev->io.baudrate = speed;
+	self->io.speed = speed;
 
 	/* Save current bank */
 	set = inb(iobase+SSR);
@@ -404,24 +445,24 @@
 	switch (speed) {
 	case 9600:   outb(0x0c, iobase+ABLL); break;
 	case 19200:  outb(0x06, iobase+ABLL); break;
-	case 37600:  outb(0x03, iobase+ABLL); break;
+	case 38400:  outb(0x03, iobase+ABLL); break;
 	case 57600:  outb(0x02, iobase+ABLL); break;
 	case 115200: outb(0x01, iobase+ABLL); break;
 	case 576000:
 		ir_mode = HCR_MIR_576;
-		DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
 		break;
 	case 1152000:
 		ir_mode = HCR_MIR_1152;
-		DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
 		break;
 	case 4000000:
 		ir_mode = HCR_FIR;
-		DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
 		break;
 	default:
 		ir_mode = HCR_FIR;
-		DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", speed);
+		IRDA_DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", speed);
 		break;
 	}
 
@@ -435,18 +476,17 @@
 	
 	/* set FIFO threshold to TX17, RX16 */
 	switch_bank(iobase, SET0);
-
 	outb(0x00, iobase+UFR);        /* Reset */
 	outb(UFR_EN_FIFO, iobase+UFR); /* First we must enable FIFO */
 	outb(0xa7, iobase+UFR);
 
-	idev->netdev.tbusy = 0;
+	self->netdev->tbusy = 0;
 	
 	/* Enable some interrupts so we can receive frames */
 	switch_bank(iobase, SET0);
 	if (speed > PIO_MAX_SPEED) {
 		outb(ICR_EFSFI, iobase+ICR);
-		w83977af_dma_receive(idev);
+		w83977af_dma_receive(self);
 	} else
 		outb(ICR_ERBRI, iobase+ICR);
     	
@@ -462,32 +502,35 @@
  */
 int w83977af_hard_xmit(struct sk_buff *skb, struct device *dev)
 {
-	struct irda_device *idev;
+	struct w83977af_ir *self;
+	__u32 speed;
 	int iobase;
 	__u8 set;
 	int mtt;
 	
-	idev = (struct irda_device *) dev->priv;
-
-	ASSERT(idev != NULL, return 0;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+	self = (struct w83977af_ir *) dev->priv;
 
-	iobase = idev->io.iobase;
+	iobase = self->io.fir_base;
 
-	DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
+	IRDA_DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, 
+		   (int) skb->len);
 	
 	/* Lock transmit buffer */
 	if (irda_lock((void *) &dev->tbusy) == FALSE)
 		return -EBUSY;
 
+	/* Check if we need to change the speed */
+	if ((speed = irda_get_speed(skb)) != self->io.speed)
+		self->new_speed = speed;
+
 	/* Save current set */
 	set = inb(iobase+SSR);
 	
 	/* Decide if we should use PIO or DMA transfer */
-	if (idev->io.baudrate > PIO_MAX_SPEED) {
-		idev->tx_buff.data = idev->tx_buff.head;
-		memcpy(idev->tx_buff.data, skb->data, skb->len);
-		idev->tx_buff.len = skb->len;
+	if (self->io.speed > PIO_MAX_SPEED) {
+		self->tx_buff.data = self->tx_buff.head;
+		memcpy(self->tx_buff.data, skb->data, skb->len);
+		self->tx_buff.len = skb->len;
 		
 		mtt = irda_get_mtt(skb);
 #ifdef CONFIG_USE_INTERNAL_TIMER
@@ -502,28 +545,28 @@
 			
 			/* Start timer */
 			outb(IR_MSL_EN_TMR, iobase+IR_MSL);
-			idev->io.direction = IO_XMIT;
+			self->io.direction = IO_XMIT;
 			
 			/* Enable timer interrupt */
 			switch_bank(iobase, SET0);
 			outb(ICR_ETMRI, iobase+ICR);
 		} else {
 #endif
-			DEBUG(4,__FUNCTION__ "(%ld), mtt=%d\n", jiffies, mtt);
+			IRDA_DEBUG(4,__FUNCTION__ "(%ld), mtt=%d\n", jiffies, mtt);
 			if (mtt)
 				udelay(mtt);
 
 			/* Enable DMA interrupt */
 			switch_bank(iobase, SET0);
 	 		outb(ICR_EDMAI, iobase+ICR);
-	     		w83977af_dma_write(idev, iobase);
+	     		w83977af_dma_write(self, iobase);
 #ifdef CONFIG_USE_INTERNAL_TIMER
 		}
 #endif
 	} else {
-		idev->tx_buff.data = idev->tx_buff.head;
-		idev->tx_buff.len = async_wrap_skb(skb, idev->tx_buff.data, 
-						   idev->tx_buff.truesize);
+		self->tx_buff.data = self->tx_buff.head;
+		self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, 
+						   self->tx_buff.truesize);
 		
 		/* Add interrupt on tx low level (will fire immediately) */
 		switch_bank(iobase, SET0);
@@ -538,19 +581,19 @@
 }
 
 /*
- * Function w83977af_dma_write (idev, iobase)
+ * Function w83977af_dma_write (self, iobase)
  *
  *    Send frame using DMA
  *
  */
-static void w83977af_dma_write(struct irda_device *idev, int iobase)
+static void w83977af_dma_write(struct w83977af_ir *self, int iobase)
 {
 	__u8 set;
-#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS
+#ifdef CONFIG_VNC_TX_DMA_PROBLEMS
 	unsigned long flags;
 	__u8 hcr;
 #endif
-        DEBUG(4, __FUNCTION__ "(), len=%d\n", idev->tx_buff.len);
+        IRDA_DEBUG(4, __FUNCTION__ "(), len=%d\n", self->tx_buff.len);
 
 	/* Save current set */
 	set = inb(iobase+SSR);
@@ -562,27 +605,27 @@
 	/* Choose transmit DMA channel  */ 
 	switch_bank(iobase, SET2);
 	outb(ADCR1_D_CHSW|/*ADCR1_DMA_F|*/ADCR1_ADV_SL, iobase+ADCR1);
-#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS
+#ifdef CONFIG_VNC_TX_DMA_PROBLEMS
 	save_flags(flags);
 	cli();
 
-	disable_dma(idev->io.dma);
-	clear_dma_ff(idev->io.dma);
-	set_dma_mode(idev->io.dma, DMA_MODE_READ);
-	set_dma_addr(idev->io.dma, virt_to_bus(idev->tx_buff.data));
-	set_dma_count(idev->io.dma, idev->tx_buff.len);
+	disable_dma(self->io.dma);
+	clear_dma_ff(self->io.dma);
+	set_dma_mode(self->io.dma, DMA_MODE_READ);
+	set_dma_addr(self->io.dma, virt_to_bus(self->tx_buff.data));
+	set_dma_count(self->io.dma, self->tx_buff.len);
 #else
-	setup_dma(idev->io.dma, idev->tx_buff.data, idev->tx_buff.len, 
+	setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len, 
 		  DMA_MODE_WRITE);	
 #endif
-	idev->io.direction = IO_XMIT;
+	self->io.direction = IO_XMIT;
 	
 	/* Enable DMA */
  	switch_bank(iobase, SET0);
-#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS
+#ifdef CONFIG_VNC_TX_DMA_PROBLEMS
 	hcr = inb(iobase+HCR);
 	outb(hcr | HCR_EN_DMA, iobase+HCR);
-	enable_dma(idev->io.dma);
+	enable_dma(self->io.dma);
 	restore_flags(flags);
 #else	
 	outb(inb(iobase+HCR) | HCR_EN_DMA | HCR_TX_WT, iobase+HCR);
@@ -603,17 +646,19 @@
 	int actual = 0;
 	__u8 set;
 	
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	/* Save current bank */
 	set = inb(iobase+SSR);
 
 	switch_bank(iobase, SET0);
 	if (!(inb_p(iobase+USR) & USR_TSRE)) {
-		DEBUG(4, __FUNCTION__ "(), warning, FIFO not empty yet!\n");
+		IRDA_DEBUG(4, __FUNCTION__ 
+			   "(), warning, FIFO not empty yet!\n");
 
 		fifo_size -= 17;
-		DEBUG(4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size);
+		IRDA_DEBUG(4, __FUNCTION__ "%d bytes left in tx fifo\n", 
+			   fifo_size);
 	}
 
 	/* Fill FIFO with current frame */
@@ -622,8 +667,8 @@
 		outb(buf[actual++], iobase+TBR);
 	}
         
-	DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", 
-	       fifo_size, actual, len);
+	IRDA_DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", 
+		   fifo_size, actual, len);
 
 	/* Restore bank */
 	outb(set, iobase+SSR);
@@ -632,23 +677,22 @@
 }
 
 /*
- * Function w83977af_dma_xmit_complete (idev)
+ * Function w83977af_dma_xmit_complete (self)
  *
  *    The transfer of a frame in finished. So do the necessary things
  *
  *    
  */
-void w83977af_dma_xmit_complete(struct irda_device *idev)
+void w83977af_dma_xmit_complete(struct w83977af_ir *self)
 {
 	int iobase;
 	__u8 set;
 
-	DEBUG(4, __FUNCTION__ "(%ld)\n", jiffies);
+	IRDA_DEBUG(4, __FUNCTION__ "(%ld)\n", jiffies);
 
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+	ASSERT(self != NULL, return;);
 
-	iobase = idev->io.iobase;
+	iobase = self->io.fir_base;
 
 	/* Save current set */
 	set = inb(iobase+SSR);
@@ -659,19 +703,24 @@
 	
 	/* Check for underrrun! */
 	if (inb(iobase+AUDR) & AUDR_UNDR) {
-		DEBUG(0, __FUNCTION__ "(), Transmit underrun!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), Transmit underrun!\n");
 		
-		idev->stats.tx_errors++;
-		idev->stats.tx_fifo_errors++;
+		self->stats.tx_errors++;
+		self->stats.tx_fifo_errors++;
 
 		/* Clear bit, by writing 1 to it */
 		outb(AUDR_UNDR, iobase+AUDR);
 	} else
-		idev->stats.tx_packets++;
+		self->stats.tx_packets++;
+
+	
+	if (self->new_speed) {
+		w83977af_change_speed(self, self->new_speed);
+		self->new_speed = 0;
+	}
 
 	/* Unlock tx_buff and request another frame */
-	idev->netdev.tbusy = 0; /* Unlock */
-	idev->media_busy = FALSE;
+	self->netdev->tbusy = 0; /* Unlock */
 	
 	/* Tell the network layer, that we want more frames */
 	mark_bh(NET_BH);
@@ -681,29 +730,25 @@
 }
 
 /*
- * Function w83977af_dma_receive (idev)
+ * Function w83977af_dma_receive (self)
  *
  *    Get ready for receiving a frame. The device will initiate a DMA
  *    if it starts to receive a frame.
  *
  */
-int w83977af_dma_receive(struct irda_device *idev) 
+int w83977af_dma_receive(struct w83977af_ir *self) 
 {
-	struct w83977af_ir *self;
 	int iobase;
 	__u8 set;
-#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS
+#ifdef CONFIG_VNC_RX_DMA_PROBLEMS
 	unsigned long flags;
 	__u8 hcr;
 #endif
+	ASSERT(self != NULL, return -1;);
 
-	ASSERT(idev != NULL, return -1;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+	IRDA_DEBUG(4, __FUNCTION__ "\n");
 
-	DEBUG(4, __FUNCTION__ "\n");
-
-	self = idev->priv;
-	iobase= idev->io.iobase;
+	iobase= self->io.fir_base;
 
 	/* Save current set */
 	set = inb(iobase+SSR);
@@ -717,20 +762,20 @@
 	outb((inb(iobase+ADCR1) & ~ADCR1_D_CHSW)/*|ADCR1_DMA_F*/|ADCR1_ADV_SL,
 	     iobase+ADCR1);
 
-	idev->io.direction = IO_RECV;
-	idev->rx_buff.data = idev->rx_buff.head;
+	self->io.direction = IO_RECV;
+	self->rx_buff.data = self->rx_buff.head;
 
-#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS
+#ifdef CONFIG_VNC_RX_DMA_PROBLEMS
 	save_flags(flags);
 	cli();
 
-	disable_dma(idev->io.dma);
-	clear_dma_ff(idev->io.dma);
-	set_dma_mode(idev->io.dma, DMA_MODE_READ);
-	set_dma_addr(idev->io.dma, virt_to_bus(idev->rx_buff.data));
-	set_dma_count(idev->io.dma, idev->rx_buff.truesize);
+	disable_dma(self->io.dma);
+	clear_dma_ff(self->io.dma);
+	set_dma_mode(self->io.dma, DMA_MODE_READ);
+	set_dma_addr(self->io.dma, virt_to_bus(self->rx_buff.data));
+	set_dma_count(self->io.dma, self->rx_buff.truesize);
 #else
-	setup_dma(idev->io.dma, idev->rx_buff.data, idev->rx_buff.truesize, 
+	setup_dma(self->io.dma, self->rx_buff.data, self->rx_buff.truesize, 
 		  DMA_MODE_READ);
 #endif
 	/* 
@@ -744,10 +789,10 @@
 	
 	/* Enable DMA */
 	switch_bank(iobase, SET0);
-#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS
+#ifdef CONFIG_VNC_RX_DMA_PROBLEMS
 	hcr = inb(iobase+HCR);
 	outb(hcr | HCR_EN_DMA, iobase+HCR);
-	enable_dma(idev->io.dma);
+	enable_dma(self->io.dma);
 	restore_flags(flags);
 #else	
 	outb(inb(iobase+HCR) | HCR_EN_DMA, iobase+HCR);
@@ -759,32 +804,30 @@
 }
 
 /*
- * Function w83977af_receive_complete (idev)
+ * Function w83977af_receive_complete (self)
  *
  *    Finished with receiving a frame
  *
  */
-int w83977af_dma_receive_complete(struct irda_device *idev)
+int w83977af_dma_receive_complete(struct w83977af_ir *self)
 {
 	struct sk_buff *skb;
-	struct w83977af_ir *self;
 	struct st_fifo *st_fifo;
 	int len;
 	int iobase;
 	__u8 set;
 	__u8 status;
 
-	DEBUG(4, __FUNCTION__ "\n");
+	IRDA_DEBUG(4, __FUNCTION__ "\n");
 
-	self = idev->priv;
 	st_fifo = &self->st_fifo;
 
-	iobase = idev->io.iobase;
+	iobase = self->io.fir_base;
 
 	/* Save current set */
 	set = inb(iobase+SSR);
 	
-	iobase = idev->io.iobase;
+	iobase = self->io.fir_base;
 
 	/* Read status FIFO */
 	switch_bank(iobase, SET5);
@@ -809,28 +852,28 @@
 		if (status & FS_FO_ERR_MSK) {
 			if (status & FS_FO_LST_FR) {
 				/* Add number of lost frames to stats */
-				idev->stats.rx_errors += len;	
+				self->stats.rx_errors += len;	
 			} else {
 				/* Skip frame */
-				idev->stats.rx_errors++;
+				self->stats.rx_errors++;
 				
-				idev->rx_buff.data += len;
+				self->rx_buff.data += len;
 				
 				if (status & FS_FO_MX_LEX)
-					idev->stats.rx_length_errors++;
+					self->stats.rx_length_errors++;
 				
 				if (status & FS_FO_PHY_ERR) 
-					idev->stats.rx_frame_errors++;
+					self->stats.rx_frame_errors++;
 				
 				if (status & FS_FO_CRC_ERR) 
-					idev->stats.rx_crc_errors++;
+					self->stats.rx_crc_errors++;
 			}
 			/* The errors below can be reported in both cases */
 			if (status & FS_FO_RX_OV)
-				idev->stats.rx_fifo_errors++;
+				self->stats.rx_fifo_errors++;
 			
 			if (status & FS_FO_FSF_OV)
-				idev->stats.rx_fifo_errors++;
+				self->stats.rx_fifo_errors++;
 			
 		} else {
 			/* Check if we have transfered all data to memory */
@@ -866,19 +909,19 @@
 			skb_reserve(skb, 1); 
 			
 			/* Copy frame without CRC */
-			if (idev->io.baudrate < 4000000) {
+			if (self->io.speed < 4000000) {
 				skb_put(skb, len-2);
-				memcpy(skb->data, idev->rx_buff.data, len-2);
+				memcpy(skb->data, self->rx_buff.data, len-2);
 			} else {
 				skb_put(skb, len-4);
-				memcpy(skb->data, idev->rx_buff.data, len-4);
+				memcpy(skb->data, self->rx_buff.data, len-4);
 			}
 
 			/* Move to next frame */
-			idev->rx_buff.data += len;
-			idev->stats.rx_packets++;
+			self->rx_buff.data += len;
+			self->stats.rx_packets++;
 			
-			skb->dev = &idev->netdev;
+			skb->dev = self->netdev;
 			skb->mac.raw  = skb->data;
 			skb->protocol = htons(ETH_P_IRDA);
 			netif_rx(skb);
@@ -891,61 +934,61 @@
 }
 
 /*
- * Function pc87108_pio_receive (idev)
+ * Function pc87108_pio_receive (self)
  *
  *    Receive all data in receiver FIFO
  *
  */
-static void w83977af_pio_receive(struct irda_device *idev) 
+static void w83977af_pio_receive(struct w83977af_ir *self) 
 {
 	__u8 byte = 0x00;
 	int iobase;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+	ASSERT(self != NULL, return;);
 	
-	iobase = idev->io.iobase;
+	iobase = self->io.fir_base;
 	
 	/*  Receive all characters in Rx FIFO */
 	do {
 		byte = inb(iobase+RBR);
-		async_unwrap_char(idev, byte);
+		async_unwrap_char(self->netdev, &self->stats, &self->rx_buff, 
+				  byte);
 	} while (inb(iobase+USR) & USR_RDR); /* Data available */	
 }
 
 /*
- * Function w83977af_sir_interrupt (idev, eir)
+ * Function w83977af_sir_interrupt (self, eir)
  *
  *    Handle SIR interrupt
  *
  */
-static __u8 w83977af_sir_interrupt(struct irda_device *idev, int isr)
+static __u8 w83977af_sir_interrupt(struct w83977af_ir *self, int isr)
 {
 	int actual;
 	__u8 new_icr = 0;
 	__u8 set;
 	int iobase;
 
-	DEBUG(4, __FUNCTION__ "(), isr=%#x\n", isr);
+	IRDA_DEBUG(4, __FUNCTION__ "(), isr=%#x\n", isr);
 	
-	iobase = idev->io.iobase;
+	iobase = self->io.fir_base;
 	/* Transmit FIFO low on data */
 	if (isr & ISR_TXTH_I) {
 		/* Write data left in transmit buffer */
-		actual = w83977af_pio_write(idev->io.iobase, 
-					    idev->tx_buff.data, 
-					    idev->tx_buff.len, 
-					    idev->io.fifo_size);
+		actual = w83977af_pio_write(self->io.fir_base, 
+					    self->tx_buff.data, 
+					    self->tx_buff.len, 
+					    self->io.fifo_size);
 
-		idev->tx_buff.data += actual;
-		idev->tx_buff.len  -= actual;
+		self->tx_buff.data += actual;
+		self->tx_buff.len  -= actual;
 		
-		idev->io.direction = IO_XMIT;
+		self->io.direction = IO_XMIT;
 
 		/* Check if finished */
-		if (idev->tx_buff.len > 0) {
+		if (self->tx_buff.len > 0) {
 			new_icr |= ICR_ETXTHI;
 		} else {
 			set = inb(iobase+SSR);
@@ -953,8 +996,8 @@
 			outb(AUDR_SFEND, iobase+AUDR);
 			outb(set, iobase+SSR); 
 
-			idev->netdev.tbusy = 0; /* Unlock */
-			idev->stats.tx_packets++;
+			self->netdev->tbusy = 0; /* Unlock */
+			self->stats.tx_packets++;
 
 			/* Schedule network layer */
 		        mark_bh(NET_BH);	
@@ -963,16 +1006,23 @@
 		}
 	}
 	/* Check if transmission has completed */
-	if (isr & ISR_TXEMP_I) {
-		
+	if (isr & ISR_TXEMP_I) {		
+		/* Check if we need to change the speed? */
+		if (self->new_speed) {
+			IRDA_DEBUG(2, __FUNCTION__ 
+				   "(), Changing speed!\n");
+			w83977af_change_speed(self, self->new_speed);
+			self->new_speed = 0;
+		}
+
 		/* Turn around and get ready to receive some data */
-		idev->io.direction = IO_RECV;
+		self->io.direction = IO_RECV;
 		new_icr |= ICR_ERBRI;
 	}
 
 	/* Rx FIFO threshold or timeout */
 	if (isr & ISR_RXTH_I) {
-		w83977af_pio_receive(idev);
+		w83977af_pio_receive(self);
 
 		/* Keep receiving */
 		new_icr |= ICR_ERBRI;
@@ -981,23 +1031,23 @@
 }
 
 /*
- * Function pc87108_fir_interrupt (idev, eir)
+ * Function pc87108_fir_interrupt (self, eir)
  *
  *    Handle MIR/FIR interrupt
  *
  */
-static __u8 w83977af_fir_interrupt(struct irda_device *idev, int isr)
+static __u8 w83977af_fir_interrupt(struct w83977af_ir *self, int isr)
 {
 	__u8 new_icr = 0;
 	__u8 set;
 	int iobase;
 
-	iobase = idev->io.iobase;
+	iobase = self->io.fir_base;
 	set = inb(iobase+SSR);
 	
 	/* End of frame detected in FIFO */
 	if (isr & (ISR_FEND_I|ISR_FSF_I)) {
-		if (w83977af_dma_receive_complete(idev)) {
+		if (w83977af_dma_receive_complete(self)) {
 			
 			/* Wait for next status FIFO interrupt */
 			new_icr |= ICR_EFSFI;
@@ -1026,29 +1076,29 @@
 /* 		outb(ASCR_CTE, iobase+ASCR); */
 
 		/* Check if this is a TX timer interrupt */
-		if (idev->io.direction == IO_XMIT) {
-			w83977af_dma_write(idev, iobase);
+		if (self->io.direction == IO_XMIT) {
+			w83977af_dma_write(self, iobase);
 
 			new_icr |= ICR_EDMAI;
 		} else {
 			/* Check if DMA has now finished */
-			w83977af_dma_receive_complete(idev);
+			w83977af_dma_receive_complete(self);
 
 			new_icr |= ICR_EFSFI;
 		}
 	}	
 	/* Finished with DMA */
 	if (isr & ISR_DMA_I) {
-		w83977af_dma_xmit_complete(idev);
+		w83977af_dma_xmit_complete(self);
 
 		/* Check if there are more frames to be transmitted */
-		/* if (irda_device_txqueue_empty(idev)) { */
+		/* if (irda_device_txqueue_empty(self)) { */
 		
 		/* Prepare for receive 
 		 * 
 		 * ** Netwinder Tx DMA likes that we do this anyway **
 		 */
-		w83977af_dma_receive(idev);
+		w83977af_dma_receive(self);
 		new_icr = ICR_EFSFI;
 	       /* } */
 	}
@@ -1060,27 +1110,28 @@
 }
 
 /*
- * Function pc87108_interrupt (irq, dev_id, regs)
+ * Function w83977af_interrupt (irq, dev_id, regs)
  *
  *    An interrupt from the chip has arrived. Time to do some work
  *
  */
 static void w83977af_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
+	struct device *dev = (struct device *) dev_id;
+	struct w83977af_ir *self;
 	__u8 set, icr, isr;
 	int iobase;
 
-	struct irda_device *idev = (struct irda_device *) dev_id;
-
-	if (idev == NULL) {
+	if (!dev) {
 		printk(KERN_WARNING "%s: irq %d for unknown device.\n", 
 			driver_name, irq);
 		return;
 	}
+	self = (struct w83977af_ir *) dev->priv;
 
-	idev->netdev.interrupt = 1;
+	dev->interrupt = 1;
 
-	iobase = idev->io.iobase;
+	iobase = self->io.fir_base;
 
 	/* Save current bank */
 	set = inb(iobase+SSR);
@@ -1093,47 +1144,34 @@
 	
 	if (isr) {
 		/* Dispatch interrupt handler for the current speed */
-		if (idev->io.baudrate > PIO_MAX_SPEED )
-			icr = w83977af_fir_interrupt(idev, isr);
+		if (self->io.speed > PIO_MAX_SPEED )
+			icr = w83977af_fir_interrupt(self, isr);
 		else
-			icr = w83977af_sir_interrupt(idev, isr);
+			icr = w83977af_sir_interrupt(self, isr);
 	}
 
 	outb(icr, iobase+ICR);    /* Restore (new) interrupts */
 	outb(set, iobase+SSR);    /* Restore bank register */
 
-	idev->netdev.interrupt = 0;
-}
-
-/*
- * Function w83977af_wait_until_sent (idev)
- *
- *    This function should put the current thread to sleep until all data 
- *    have been sent, so it is safe to f.eks. change the speed.
- */
-static void w83977af_wait_until_sent(struct irda_device *idev)
-{
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(60*HZ/1000);
+	self->netdev->interrupt = 0;
 }
 
 /*
- * Function w83977af_is_receiving (idev)
+ * Function w83977af_is_receiving (self)
  *
  *    Return TRUE is we are currently receiving a frame
  *
  */
-static int w83977af_is_receiving(struct irda_device *idev)
+static int w83977af_is_receiving(struct w83977af_ir *self)
 {
 	int status = FALSE;
 	int iobase;
 	__u8 set;
 
-	ASSERT(idev != NULL, return FALSE;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return FALSE;);
+	ASSERT(self != NULL, return FALSE;);
 
-	if (idev->io.baudrate > 115200) {
-		iobase = idev->io.iobase;
+	if (self->io.speed > 115200) {
+		iobase = self->io.fir_base;
 
 		/* Check if rx FIFO is not empty */
 		set = inb(iobase+SSR);
@@ -1144,7 +1182,7 @@
 		}
 		outb(set, iobase+SSR);
 	} else 
-		status = (idev->rx_buff.state != OUTSIDE_FRAME);
+		status = (self->rx_buff.state != OUTSIDE_FRAME);
 	
 	return status;
 }
@@ -1157,7 +1195,7 @@
  */
 static int w83977af_net_init(struct device *dev)
 {
-	DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
 	/* Set up to be a normal IrDA network device driver */
 	irda_device_setup(dev);
@@ -1176,52 +1214,57 @@
  */
 static int w83977af_net_open(struct device *dev)
 {
-	struct irda_device *idev;
+	struct w83977af_ir *self;
 	int iobase;
 	__u8 set;
 	
-	DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 	
 	ASSERT(dev != NULL, return -1;);
-	idev = (struct irda_device *) dev->priv;
+	self = (struct w83977af_ir *) dev->priv;
 	
-	ASSERT(idev != NULL, return 0;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+	ASSERT(self != NULL, return 0;);
 	
-	iobase = idev->io.iobase;
+	iobase = self->io.fir_base;
 
-	if (request_irq(idev->io.irq, w83977af_interrupt, 0, idev->name, 
-			 (void *) idev)) {
+	if (request_irq(self->io.irq, w83977af_interrupt, 0, dev->name, 
+			(void *) dev)) {
 		return -EAGAIN;
 	}
 	/*
 	 * Always allocate the DMA channel after the IRQ,
 	 * and clean up on failure.
 	 */
-	if (request_dma(idev->io.dma, idev->name)) {
-		free_irq(idev->io.irq, idev);
+	if (request_dma(self->io.dma, dev->name)) {
+		free_irq(self->io.irq, self);
 		return -EAGAIN;
 	}
 		
-	/* Ready to play! */
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
-
 	/* Save current set */
 	set = inb(iobase+SSR);
 
  	/* Enable some interrupts so we can receive frames again */
  	switch_bank(iobase, SET0);
- 	if (idev->io.baudrate > 115200) {
+ 	if (self->io.speed > 115200) {
  		outb(ICR_EFSFI, iobase+ICR);
- 		w83977af_dma_receive(idev);
+ 		w83977af_dma_receive(self);
  	} else
  		outb(ICR_ERBRI, iobase+ICR);
 
 	/* Restore bank register */
 	outb(set, iobase+SSR);
 
+	/* Ready to play! */
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	dev->start = 1;
+
+	/* 
+	 * Open new IrLAP layer instance, now that everything should be
+	 * initialized properly 
+	 */
+	self->irlap = irlap_open(dev, &self->qos);
+
 	MOD_INC_USE_COUNT;
 
 	return 0;
@@ -1235,25 +1278,30 @@
  */
 static int w83977af_net_close(struct device *dev)
 {
-	struct irda_device *idev;
+	struct w83977af_ir *self;
 	int iobase;
 	__u8 set;
 
-	DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	ASSERT(dev != NULL, return -1;);
+	
+	self = (struct w83977af_ir *) dev->priv;
 	
+	ASSERT(self != NULL, return 0;);
+	
+	iobase = self->io.fir_base;
+
 	/* Stop device */
 	dev->tbusy = 1;
 	dev->start = 0;
 
-	ASSERT(dev != NULL, return -1;);
-	idev = (struct irda_device *) dev->priv;
-	
-	ASSERT(idev != NULL, return 0;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;);
-	
-	iobase = idev->io.iobase;
+	/* Stop and remove instance of IrLAP */
+	if (self->irlap)
+		irlap_close(self->irlap);
+	self->irlap = NULL;
 
-	disable_dma(idev->io.dma);
+	disable_dma(self->io.dma);
 
 	/* Save current set */
 	set = inb(iobase+SSR);
@@ -1262,8 +1310,8 @@
 	switch_bank(iobase, SET0);
 	outb(0, iobase+ICR); 
 
-	free_irq(idev->io.irq, idev);
-	free_dma(idev->io.dma);
+	free_irq(self->io.irq, dev);
+	free_dma(self->io.dma);
 
 	/* Restore bank register */
 	outb(set, iobase+SSR);
@@ -1273,12 +1321,66 @@
 	return 0;
 }
 
+/*
+ * Function w83977af_net_ioctl (dev, rq, cmd)
+ *
+ *    Process IOCTL commands for this device
+ *
+ */
+static int w83977af_net_ioctl(struct device *dev, struct ifreq *rq, int cmd)
+{
+	struct if_irda_req *irq = (struct if_irda_req *) rq;
+	struct w83977af_ir *self;
+	unsigned long flags;
+	int ret = 0;
+
+	ASSERT(dev != NULL, return -1;);
+
+	self = dev->priv;
+
+	ASSERT(self != NULL, return -1;);
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
+	
+	/* Disable interrupts & save flags */
+	save_flags(flags);
+	cli();
+	
+	switch (cmd) {
+	case SIOCSBANDWIDTH: /* Set bandwidth */
+		w83977af_change_speed(self, irq->ifr_baudrate);
+		break;
+	case SIOCSMEDIABUSY: /* Set media busy */
+		irda_device_set_media_busy(self->netdev, TRUE);
+		break;
+	case SIOCGRECEIVING: /* Check if we are receiving right now */
+		irq->ifr_receiving = w83977af_is_receiving(self);
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+	}
+	
+	restore_flags(flags);
+	
+	return ret;
+}
+
+static struct net_device_stats *w83977af_net_get_stats(struct device *dev)
+{
+	struct w83977af_ir *self = (struct w83977af_ir *) dev->priv;
+	
+	return &self->stats;
+}
+
 #ifdef MODULE
 
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
 MODULE_DESCRIPTION("Winbond W83977AF IrDA Device Driver");
 
 MODULE_PARM(qos_mtt_bits, "i");
+MODULE_PARM(io, "1-4i");
+MODULE_PARM(io2, "1-4i");
+MODULE_PARM(irq, "1-4i");
 
 /*
  * Function init_module (void)
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/lmc/Makefile linux.15p9/drivers/net/lmc/Makefile
--- linux.vanilla/drivers/net/lmc/Makefile	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/net/lmc/Makefile	Wed Jan 26 22:58:51 2000
@@ -0,0 +1,39 @@
+# File: drivers/lmc/Makefile
+#
+# Makefile for the Lan Media 21140 based WAN cards
+# Specifically the 1000,1200,5200,5245
+#
+
+ifeq ($(CONFIG_LANMEDIA),y)
+    O_TARGET := lmc.o
+    O_OBJS = lmc_debug.o lmc_media.o lmc_main.o
+else
+  ifeq ($(CONFIG_LANMEDIA),m)
+    MOD_LIST_NAME := NET_MODULES
+    M_OBJS := lmc.o
+    O_TARGET := lmc.o
+    O_OBJS = lmc_debug.o lmc_media.o lmc_main.o
+  endif
+endif
+
+#
+# Base debugging and event log (doubles lmc.o size)
+#
+# DBGDEF =  \
+# -DDEBUG
+
+#
+# Like above except every packet gets echoed to KERN_DEBUG
+# in hex
+#
+# DBDEF = \
+# -DDEBUG \
+# -DLMC_PACKET_LOG
+
+EXTRA_CFLAGS += -I. $(DBGDEF)
+
+include $(TOPDIR)/Rules.make
+
+clean:
+	rm -f core *.o *.a *.s
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/lmc/lmc.h linux.15p9/drivers/net/lmc/lmc.h
--- linux.vanilla/drivers/net/lmc/lmc.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/net/lmc/lmc.h	Wed Jan 26 22:58:51 2000
@@ -0,0 +1,30 @@
+#ifndef _LMC_H_
+#define _LMC_H_
+
+#include "lmc_var.h"
+
+/*
+ * prototypes for everyone
+ */
+int lmc_probe(struct device * dev);
+unsigned lmc_mii_readreg(lmc_softc_t * const sc, unsigned
+      			  devaddr, unsigned regno);
+void lmc_mii_writereg(lmc_softc_t * const sc, unsigned devaddr,
+			       unsigned regno, unsigned data);
+void lmc_led_on(lmc_softc_t * const, u_int32_t);
+void lmc_led_off(lmc_softc_t * const, u_int32_t);
+unsigned lmc_mii_readreg(lmc_softc_t * const, unsigned, unsigned);
+void lmc_mii_writereg(lmc_softc_t * const, unsigned, unsigned, unsigned);
+void lmc_gpio_mkinput(lmc_softc_t * const sc, u_int32_t bits);
+void lmc_gpio_mkoutput(lmc_softc_t * const sc, u_int32_t bits);
+
+extern lmc_media_t lmc_ds3_media;
+extern lmc_media_t lmc_ssi_media;
+extern lmc_media_t lmc_t1_media;
+extern lmc_media_t lmc_hssi_media;
+
+#ifdef _DBG_EVENTLOG
+static void lmcEventLog( u_int32_t EventNum, u_int32_t arg2, u_int32_t arg3 );
+#endif
+
+#endif
\ No newline at end of file
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/lmc/lmc_debug.c linux.15p9/drivers/net/lmc/lmc_debug.c
--- linux.vanilla/drivers/net/lmc/lmc_debug.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/net/lmc/lmc_debug.c	Wed Jan 26 22:58:51 2000
@@ -0,0 +1,66 @@
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include "lmc_debug.h"
+
+/*
+ * Prints out len, max to 80 octets using printk, 20 per line
+ */
+void lmcConsoleLog(char *type, unsigned char *ucData, int iLen)
+{
+#ifdef DEBUG
+#ifdef LMC_PACKET_LOG
+  int iNewLine = 1;
+  char str[80], *pstr;
+  
+  sprintf(str, KERN_DEBUG "lmc: %s: ", type);
+  pstr = str+strlen(str);
+  
+  if(iLen > 240){
+      printk(KERN_DEBUG "lmc: Printing 240 chars... out of: %d\n", iLen);
+    iLen = 240;
+  }
+  else{
+      printk(KERN_DEBUG "lmc: Printing %d chars\n", iLen);
+  }
+
+  while(iLen > 0) 
+    {
+      sprintf(pstr, "%02x ", *ucData);
+      pstr+=3;
+      ucData++;
+      if( !(iNewLine % 20))
+	{
+	  sprintf(pstr, "\n");
+	  printk(str);
+	  sprintf(str, KERN_DEBUG "lmc: %s: ", type);
+	  pstr=str+strlen(str);
+	}
+      iNewLine++;
+      iLen--;
+    }
+  sprintf(pstr, "\n");
+  printk(str);
+#endif
+#endif
+}
+
+#ifdef DEBUG
+u_int32_t lmcEventLogIndex = 0;
+u_int32_t lmcEventLogBuf[LMC_EVENTLOGSIZE * LMC_EVENTLOGARGS];
+#endif
+
+void lmcEventLog (u_int32_t EventNum, u_int32_t arg2, u_int32_t arg3)
+{
+#ifdef DEBUG
+  lmcEventLogBuf[lmcEventLogIndex++] = EventNum;
+  lmcEventLogBuf[lmcEventLogIndex++] = arg2;
+  lmcEventLogBuf[lmcEventLogIndex++] = arg3;
+  lmcEventLogBuf[lmcEventLogIndex++] = jiffies;
+
+  lmcEventLogIndex &= (LMC_EVENTLOGSIZE * LMC_EVENTLOGARGS) - 1;
+#endif
+}
+
+
+/* --------------------------- end if_lmc_linux.c ------------------------ */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/lmc/lmc_debug.h linux.15p9/drivers/net/lmc/lmc_debug.h
--- linux.vanilla/drivers/net/lmc/lmc_debug.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/net/lmc/lmc_debug.h	Wed Jan 26 22:58:51 2000
@@ -0,0 +1,50 @@
+#ifndef _LMC_DEBUG_H_
+#define _LMC_DEBUG_H_
+
+#ifdef DEBUG
+#ifdef LMC_PACKET_LOG
+#define LMC_CONSOLE_LOG(x,y,z) lmcConsoleLog((x), (y), (z))
+#else
+#define LMC_CONSOLE_LOG(x,y,z)
+#endif
+#else
+#define LMC_CONSOLE_LOG(x,y,z)
+#endif
+
+
+
+/* Debug --- Event log definitions --- */
+/* EVENTLOGSIZE*EVENTLOGARGS needs to be a power of 2 */
+#define LMC_EVENTLOGSIZE 512	/* number of events in eventlog */
+#define LMC_EVENTLOGARGS 4		/* number of args for each event */
+
+/* event indicators */
+#define LMC_EVENT_XMT           1
+#define LMC_EVENT_XMTEND        2
+#define LMC_EVENT_XMTINT        3
+#define LMC_EVENT_RCVINT        4
+#define LMC_EVENT_RCVEND        5
+#define LMC_EVENT_INT           6
+#define LMC_EVENT_XMTINTTMO     7
+#define LMC_EVENT_XMTPRCTMO     8
+#define LMC_EVENT_INTEND        9
+#define LMC_EVENT_RESET1       10
+#define LMC_EVENT_RESET2       11
+#define LMC_EVENT_FORCEDRESET  12
+#define LMC_EVENT_WATCHDOG     13
+#define LMC_EVENT_BADPKTSURGE  14
+
+
+#ifdef DEBUG
+extern u_int32_t lmcEventLogIndex;
+extern u_int32_t lmcEventLogBuf[LMC_EVENTLOGSIZE * LMC_EVENTLOGARGS];
+#define LMC_EVENT_LOG(x, y, z) lmcEventLog((x), (y), (z))
+#else
+#define LMC_EVENT_LOG(x,y,z)
+#endif /* end ifdef _DBG_EVENTLOG */
+
+
+void lmcConsoleLog(char *type, unsigned char *ucData, int iLen);
+void lmcEventLog (u_int32_t EventNum, u_int32_t arg2, u_int32_t arg3);
+
+#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/lmc/lmc_ioctl.h linux.15p9/drivers/net/lmc/lmc_ioctl.h
--- linux.vanilla/drivers/net/lmc/lmc_ioctl.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/net/lmc/lmc_ioctl.h	Wed Jan 26 22:58:51 2000
@@ -0,0 +1,239 @@
+#ifndef _LMC_IOCTL_H_
+#define _LMC_IOCTL_H_
+/*	$Id: lmc_ioctl.h,v 1.9 2000/01/21 13:29:47 asj Exp $	*/
+
+ /*
+  * Copyright (c) 1997-2000 LAN Media Corporation (LMC)
+  * All rights reserved.  www.lanmedia.com
+  *
+  * This code is written by:
+  * Andrew Stanley-Jones (asj@cban.com)
+  * Rob Braun (bbraun@vix.com),
+  * Michael Graff (explorer@vix.com) and
+  * Matt Thomas (matt@3am-software.com).
+  *
+  * This software may be used and distributed according to the terms
+  * of the GNU Public License version 2, incorporated herein by reference.
+  */
+
+#define LMCIOCGINFO         SIOCDEVPRIVATE+3 /* get current state */
+#define LMCIOCSINFO         SIOCDEVPRIVATE+4 /* set state to user values */
+#define LMCIOCSKEEPALIVE    SIOCDEVPRIVATE+5 /* Turn keepalives on/off */
+#ifdef  LMC_DEBUG_FILE
+#define LMCIOCLEARSTATS LMCIOCSINFO + 1 /* Clear debug stats */
+#endif
+#define LMCIOCGETLMCSTATS       LMCIOCSINFO + 3
+#define LMCIOCCLEARLMCSTATS     LMCIOCSINFO + 4
+#define LMCIOCDUMPEVENTLOG      LMCIOCSINFO + 5
+#define LMCIOCGETXINFO          LMCIOCSINFO + 6
+#define LMCIOCSETCIRCUIT        LMCIOCSINFO + 7
+#define LMCIOCUNUSEDATM         LMCIOCSINFO + 8
+#define LMCIOCRESET             LMCIOCSINFO + 9
+#define LMCIOCT1CONTROL         LMCIOCSINFO + 10
+
+#define LMC_CARDTYPE_UNKNOWN    -1
+#define LMC_CARDTYPE_HSSI               1       /* probed card is a HSSI card */
+#define LMC_CARDTYPE_DS3                2       /* probed card is a DS3 card */
+#define LMC_CARDTYPE_SSI                3       /* probed card is a SSI card */
+#define LMC_CARDTYPE_T1                 4       /* probed card is a T1 card */
+
+#define LMC_CTL_CARDTYPE_LMC5200	0	/* HSSI */
+#define LMC_CTL_CARDTYPE_LMC5245	1	/* DS3 */
+#define LMC_CTL_CARDTYPE_LMC1000	2	/* SSI, V.35 */
+#define LMC_CTL_CARDTYPE_LMC1200        3       /* DS1 */
+
+#define LMC_CTL_OFF			0	/* generic OFF value */
+#define LMC_CTL_ON			1	/* generic ON value */
+
+#define LMC_CTL_CLOCK_SOURCE_EXT	0	/* clock off line */
+#define LMC_CTL_CLOCK_SOURCE_INT	1	/* internal clock */
+
+#define LMC_CTL_CRC_LENGTH_16		16
+#define LMC_CTL_CRC_LENGTH_32		32
+#define LMC_CTL_CRC_BYTESIZE_2          2
+#define LMC_CTL_CRC_BYTESIZE_4          4
+
+
+#define LMC_CTL_CABLE_LENGTH_LT_100FT	0	/* DS3 cable < 100 feet */
+#define LMC_CTL_CABLE_LENGTH_GT_100FT	1	/* DS3 cable >= 100 feet */
+
+#define LMC_CTL_CIRCUIT_TYPE_E1 0
+#define LMC_CTL_CIRCUIT_TYPE_T1 1
+
+/*
+ * These are not in the least IOCTL related, but I want them common.
+ */
+/*
+ * assignments for the GPIO register on the DEC chip (common)
+ */
+#define LMC_GEP_INIT		0x01 /* 0: */
+#define LMC_GEP_RESET		0x02 /* 1: */
+#define LMC_GEP_LOAD		0x10 /* 4: */
+#define LMC_GEP_DP		0x20 /* 5: */
+#define LMC_GEP_SERIAL		0x40 /* 6: serial out */
+#define LMC_GEP_SERIALCLK	0x80 /* 7: serial clock */
+
+/*
+ * HSSI GPIO assignments
+ */
+#define LMC_GEP_HSSI_ST		0x04 /* 2: receive timing sense (deprecated) */
+#define LMC_GEP_HSSI_CLOCK	0x08 /* 3: clock source */
+
+/*
+ * T1 GPIO assignments
+ */
+#define LMC_GEP_SSI_GENERATOR	0x04 /* 2: enable prog freq gen serial i/f */
+#define LMC_GEP_SSI_TXCLOCK	0x08 /* 3: provide clock on TXCLOCK output */
+
+/*
+ * Common MII16 bits
+ */
+#define LMC_MII16_LED0         0x0080
+#define LMC_MII16_LED1         0x0100
+#define LMC_MII16_LED2         0x0200
+#define LMC_MII16_LED3         0x0400  /* Error, and the red one */
+#define LMC_MII16_LED_ALL      0x0780  /* LED bit mask */
+#define LMC_MII16_FIFO_RESET   0x0800
+
+/*
+ * definitions for HSSI
+ */
+#define LMC_MII16_HSSI_TA      0x0001
+#define LMC_MII16_HSSI_CA      0x0002
+#define LMC_MII16_HSSI_LA      0x0004
+#define LMC_MII16_HSSI_LB      0x0008
+#define LMC_MII16_HSSI_LC      0x0010
+#define LMC_MII16_HSSI_TM      0x0020
+#define LMC_MII16_HSSI_CRC     0x0040
+
+/*
+ * assignments for the MII register 16 (DS3)
+ */
+#define LMC_MII16_DS3_ZERO	0x0001
+#define LMC_MII16_DS3_TRLBK	0x0002
+#define LMC_MII16_DS3_LNLBK	0x0004
+#define LMC_MII16_DS3_RAIS	0x0008
+#define LMC_MII16_DS3_TAIS	0x0010
+#define LMC_MII16_DS3_BIST	0x0020
+#define LMC_MII16_DS3_DLOS	0x0040
+#define LMC_MII16_DS3_CRC	0x1000
+#define LMC_MII16_DS3_SCRAM	0x2000
+
+/* Note: 2 pairs of LEDs where swapped by mistake
+ * in Xilinx code for DS3 & DS1 adapters */
+#define LMC_DS3_LED0    0x0100          /* bit 08  yellow */
+#define LMC_DS3_LED1    0x0080          /* bit 07  blue   */
+#define LMC_DS3_LED2    0x0400          /* bit 10  green  */
+#define LMC_DS3_LED3    0x0200          /* bit 09  red    */
+
+/*
+ * framer register 0 and 7 (7 is latched and reset on read)
+ */
+#define LMC_FRAMER_REG0_DLOS            0x80    /* digital loss of service */
+#define LMC_FRAMER_REG0_OOFS            0x40    /* out of frame sync */
+#define LMC_FRAMER_REG0_AIS             0x20    /* alarm indication signal */
+#define LMC_FRAMER_REG0_CIS             0x10    /* channel idle */
+#define LMC_FRAMER_REG0_LOC             0x08    /* loss of clock */
+
+/*
+ * Framer register 9 contains the blue alarm signal
+ */
+#define LMC_FRAMER_REG9_RBLUE          0x02     /* Blue alarm failure */
+
+/*
+ * Framer register 0x10 contains xbit error
+ */
+#define LMC_FRAMER_REG10_XBIT          0x01     /* X bit error alarm failure */
+
+/*
+ * And SSI, LMC1000
+ */
+#define LMC_MII16_SSI_DTR	0x0001	/* DTR output RW */
+#define LMC_MII16_SSI_DSR	0x0002	/* DSR input RO */
+#define LMC_MII16_SSI_RTS	0x0004	/* RTS output RW */
+#define LMC_MII16_SSI_CTS	0x0008	/* CTS input RO */
+#define LMC_MII16_SSI_DCD	0x0010	/* DCD input RO */
+#define LMC_MII16_SSI_RI		0x0020	/* RI input RO */
+#define LMC_MII16_SSI_CRC                0x1000  /* CRC select - RW */
+
+/*
+ * bits 0x0080 through 0x0800 are generic, and described
+ * above with LMC_MII16_LED[0123] _LED_ALL, and _FIFO_RESET
+ */
+#define LMC_MII16_SSI_LL		0x1000	/* LL output RW */
+#define LMC_MII16_SSI_RL		0x2000	/* RL output RW */
+#define LMC_MII16_SSI_TM		0x4000	/* TM input RO */
+#define LMC_MII16_SSI_LOOP	0x8000	/* loopback enable RW */
+
+/*
+ * Some of the MII16 bits are mirrored in the MII17 register as well,
+ * but let's keep thing seperate for now, and get only the cable from
+ * the MII17.
+ */
+#define LMC_MII17_SSI_CABLE_MASK	0x0038	/* mask to extract the cable type */
+#define LMC_MII17_SSI_CABLE_SHIFT 3	/* shift to extract the cable type */
+
+/*
+ * And T1, LMC1200
+ */
+#define LMC_MII16_T1_UNUSED1    0x0003
+#define LMC_MII16_T1_XOE                0x0004
+#define LMC_MII16_T1_RST                0x0008  /* T1 chip reset - RW */
+#define LMC_MII16_T1_Z                  0x0010  /* output impedance T1=1, E1=0 output - RW */
+#define LMC_MII16_T1_INTR               0x0020  /* interrupt from 8370 - RO */
+#define LMC_MII16_T1_ONESEC             0x0040  /* one second square wave - ro */
+
+#define LMC_MII16_T1_LED0               0x0100
+#define LMC_MII16_T1_LED1               0x0080
+#define LMC_MII16_T1_LED2               0x0400
+#define LMC_MII16_T1_LED3               0x0200
+#define LMC_MII16_T1_FIFO_RESET 0x0800
+
+#define LMC_MII16_T1_CRC                0x1000  /* CRC select - RW */
+#define LMC_MII16_T1_UNUSED2    0xe000
+
+
+/* 8370 framer registers  */
+
+#define T1FRAMER_ALARM1_STATUS  0x47
+#define T1FRAMER_ALARM2_STATUS  0x48
+#define T1FRAMER_FERR_LSB               0x50
+#define T1FRAMER_FERR_MSB               0x51    /* framing bit error counter */
+#define T1FRAMER_LCV_LSB                0x54
+#define T1FRAMER_LCV_MSB                0x55    /* line code violation counter */
+#define T1FRAMER_AERR                   0x5A
+
+/* mask for the above AERR register */
+#define T1FRAMER_LOF_MASK               (0x0f0) /* receive loss of frame */
+#define T1FRAMER_COFA_MASK              (0x0c0) /* change of frame alignment */
+#define T1FRAMER_SEF_MASK               (0x03)  /* severely errored frame  */
+
+/* 8370 framer register ALM1 (0x47) values
+ * used to determine link status
+ */
+
+#define T1F_SIGFRZ      0x01    /* signaling freeze */
+#define T1F_RLOF        0x02    /* receive loss of frame alignment */
+#define T1F_RLOS        0x04    /* receive loss of signal */
+#define T1F_RALOS       0x08    /* receive analog loss of signal or RCKI loss of clock */
+#define T1F_RAIS        0x10    /* receive alarm indication signal */
+#define T1F_UNUSED      0x20
+#define T1F_RYEL        0x40    /* receive yellow alarm */
+#define T1F_RMYEL       0x80    /* receive multiframe yellow alarm */
+
+#define LMC_T1F_WRITE       0
+#define LMC_T1F_READ        1
+
+typedef struct lmc_st1f_control {
+  int command;
+  int address;
+  int value;
+  char *data;
+} lmc_t1f_control;
+
+/* ------------------ end T1 defs ------------------- */
+
+#define LMC_MII_LedMask                 0x0780
+#define LMC_MII_LedBitPos               7
+
+#endif
\ No newline at end of file
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/lmc/lmc_main.c linux.15p9/drivers/net/lmc/lmc_main.c
--- linux.vanilla/drivers/net/lmc/lmc_main.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/net/lmc/lmc_main.c	Wed Jan 26 22:59:18 2000
@@ -0,0 +1,1882 @@
+ /*
+  * Copyright (c) 1997-2000 LAN Media Corporation (LMC)
+  * All rights reserved.  www.lanmedia.com
+  *
+  * This code is written by:
+  * Andrew Stanley-Jones (asj@cban.com)
+  * Rob Braun (bbraun@vix.com),
+  * Michael Graff (explorer@vix.com) and
+  * Matt Thomas (matt@3am-software.com).
+  *
+  * With Help By:
+  * David Boggs
+  * Ron Crane
+  * Allan Cox
+  *
+  * This software may be used and distributed according to the terms
+  * of the GNU Public License version 2, incorporated herein by reference.
+  *
+  * Driver for the LanMedia LMC5200, LMC5245, LMC1000, LMC1200 cards.
+  *
+  * To control link specific options lmcctl is required.
+  * It can be obtained from ftp.lanmedia.com.
+  *
+  * Linux driver notes:
+  * Linux uses the device struct lmc_private to pass private information
+  * arround.
+  *
+  * The initialization portion of this driver (the lmc_reset() and the
+  * lmc_dec_reset() functions, as well as the led controls and the
+  * lmc_initcsrs() functions.
+  *
+  * The watchdog function runs every second and checks to see if
+  * we still have link, and that the timing source is what we expected
+  * it to be.  If link is lost, the interface is marked down, and
+  * we no longer can transmit.
+  *
+  */
+
+/* $Id: lmc_main.c,v 1.24 2000/01/21 13:29:48 asj Exp $ */
+
+#include <linux/version.h>
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <asm/segment.h>
+#include <asm/smp.h>
+
+#if LINUX_VERSION_CODE < 0x20155
+#include <linux/bios32.h>
+#endif
+
+#include <linux/in.h>
+#include <linux/if_arp.h>
+#include <asm/processor.h>             /* Processor type for cache alignment. */
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include "../syncppp.h"
+#include <linux/inet.h>
+
+#if LINUX_VERSION_CODE >= 0x20200
+#include <asm/uaccess.h>
+#include <asm/spinlock.h>
+#endif
+
+#ifdef MODULE
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+#include <linux/module.h>
+#include <linux/version.h>
+#else
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#endif
+
+#define DRIVER_MAJOR_VERSION     1
+#define DRIVER_MINOR_VERSION    33
+#define DRIVER_SUB_VERSION       1
+
+#define DRIVER_VERSION  ((DRIVER_MAJOR_VERSION << 8) + DRIVER_MINOR_VERSION)
+
+#include "lmc.h"
+#include "lmc_ver.h"
+#include "lmc_var.h"
+#include "lmc_ioctl.h"
+#include "lmc_debug.h"
+
+static int Lmc_Count = 0;
+static struct device *Lmc_root_dev = NULL;
+static u8 cards_found = 0;
+
+static int lmc_first_load = 0;
+
+int lmc_probe_fake(struct device *dev);
+static struct device *lmc_probe1(struct device *dev, int ioaddr, int irq,
+				 int chip_id, int subdevice, int board_idx);
+static int lmc_start_xmit(struct sk_buff *skb, struct device *dev);
+static int lmc_rx(struct device *dev);
+static int lmc_open(struct device *dev);
+static int lmc_close(struct device *dev);
+static struct enet_statistics *lmc_get_stats(struct device *dev);
+static void lmc_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static int lmc_ioctl(struct device *dev, struct ifreq *ifr, int cmd);
+static int lmc_set_config(struct device *dev, struct ifmap *map);
+static void lmc_initcsrs(lmc_softc_t * const, u32, size_t);
+static void lmc_softreset(lmc_softc_t * const);
+static void lmc_running_reset(struct device *dev);
+static int lmc_ifdown(struct device * const);
+static void lmc_watchdog(unsigned long data);
+static int lmc_init(struct device * const);
+static void lmc_reset(lmc_softc_t * const sc);
+static void lmc_dec_reset(lmc_softc_t * const sc);
+static void lmc_initcsrs(lmc_softc_t * const sc, lmc_csrptr_t csr_base,size_t csr_size);
+
+/*
+ * linux reserves 16 device specific IOCTLs.  We call them
+ * LMCIOC* to control various bits of our world.
+ */
+static int lmc_ioctl (struct device *dev, struct ifreq *ifr, int cmd) /*fold00*/
+{
+    lmc_softc_t *sc;
+    lmc_ctl_t ctl;
+    int ret;
+    u_int16_t regVal;
+    unsigned long flags;
+
+    struct sppp *sp;
+
+    ret = -EOPNOTSUPP;
+
+    sc = dev->priv;
+
+    /*
+     * Most functions mess with the structure
+     * Disable interupts while we do the polling
+     */
+    spin_lock_irqsave(&sc->lmc_lock, flags);
+
+    switch (cmd) {
+        /*
+         * Return current driver state.  Since we keep this up
+         * To date internally, just copy this out to the user.
+         */
+    case LMCIOCGINFO:
+        LMC_COPY_TO_USER(ifr->ifr_data, &sc->ictl, sizeof (lmc_ctl_t));
+        ret = 0;
+        break;
+
+    case LMCIOCSINFO:
+        sp = &((struct ppp_device *) dev)->sppp;
+        if (!suser ()) {
+            ret = -EPERM;
+            break;
+        }
+
+        if(dev->flags & IFF_UP){
+            ret = -EBUSY;
+            break;
+        }
+
+        LMC_COPY_FROM_USER(&ctl, ifr->ifr_data, sizeof (lmc_ctl_t));
+
+        sc->lmc_media->set_status (sc, &ctl);
+
+        if(ctl.crc_length != sc->ictl.crc_length) {
+            sc->lmc_media->set_crc_length(sc, ctl.crc_length);
+        }
+
+        if (ctl.keepalive_onoff == LMC_CTL_OFF)
+            sp->pp_flags &= ~PP_KEEPALIVE;	/* Turn off */
+        else
+            sp->pp_flags |= PP_KEEPALIVE;	/* Turn on */
+
+        ret = 0;
+        break;
+    case LMCIOCGETXINFO:
+        sc->lmc_xinfo.Magic0 = 0xBEEFCAFE;
+
+        sc->lmc_xinfo.PciCardType = sc->lmc_cardtype;
+        sc->lmc_xinfo.PciSlotNumber = 0;
+        sc->lmc_xinfo.DriverMajorVersion = DRIVER_MAJOR_VERSION;
+        sc->lmc_xinfo.DriverMinorVersion = DRIVER_MINOR_VERSION;
+        sc->lmc_xinfo.DriverSubVersion = DRIVER_SUB_VERSION;
+        sc->lmc_xinfo.XilinxRevisionNumber =
+            lmc_mii_readreg (sc, 0, 3) & 0xf;
+        sc->lmc_xinfo.MaxFrameSize = PKT_BUF_SZ;
+        sc->lmc_xinfo.link_status = sc->lmc_media->get_link_status (sc);
+        sc->lmc_xinfo.mii_reg16 = lmc_mii_readreg (sc, 0, 16);
+
+        sc->lmc_xinfo.Magic1 = 0xDEADBEEF;
+
+        LMC_COPY_TO_USER(ifr->ifr_data, &sc->lmc_xinfo,
+                         sizeof (struct lmc_xinfo));
+        ret = 0;
+
+        break;
+
+    case LMCIOCGETLMCSTATS:
+        if (sc->lmc_cardtype == LMC_CARDTYPE_T1){
+            lmc_mii_writereg (sc, 0, 17, T1FRAMER_FERR_LSB);
+            sc->stats.framingBitErrorCount +=
+                lmc_mii_readreg (sc, 0, 18) & 0xff;
+            lmc_mii_writereg (sc, 0, 17, T1FRAMER_FERR_MSB);
+            sc->stats.framingBitErrorCount +=
+                (lmc_mii_readreg (sc, 0, 18) & 0xff) << 8;
+            lmc_mii_writereg (sc, 0, 17, T1FRAMER_LCV_LSB);
+            sc->stats.lineCodeViolationCount +=
+                lmc_mii_readreg (sc, 0, 18) & 0xff;
+            lmc_mii_writereg (sc, 0, 17, T1FRAMER_LCV_MSB);
+            sc->stats.lineCodeViolationCount +=
+                (lmc_mii_readreg (sc, 0, 18) & 0xff) << 8;
+            lmc_mii_writereg (sc, 0, 17, T1FRAMER_AERR);
+            regVal = lmc_mii_readreg (sc, 0, 18) & 0xff;
+
+            sc->stats.lossOfFrameCount +=
+                (regVal & T1FRAMER_LOF_MASK) >> 4;
+            sc->stats.changeOfFrameAlignmentCount +=
+                (regVal & T1FRAMER_COFA_MASK) >> 2;
+            sc->stats.severelyErroredFrameCount +=
+                regVal & T1FRAMER_SEF_MASK;
+        }
+
+        LMC_COPY_TO_USER(ifr->ifr_data, &sc->stats,
+                         sizeof (struct lmc_statistics));
+
+        ret = 0;
+        break;
+
+    case LMCIOCCLEARLMCSTATS:
+        if (!suser ()){
+            ret = -EPERM;
+            break;
+        }
+
+        memset (&sc->stats, 0, sizeof (struct lmc_statistics));
+        sc->stats.check = STATCHECK;
+        sc->stats.version_size = (DRIVER_VERSION << 16) +
+            sizeof (struct lmc_statistics);
+        sc->stats.lmc_cardtype = sc->lmc_cardtype;
+        ret = 0;
+        break;
+
+    case LMCIOCSETCIRCUIT:
+        if (!suser ()){
+            ret = -EPERM;
+            break;
+        }
+
+        if(dev->flags & IFF_UP){
+            ret = -EBUSY;
+            break;
+        }
+
+        LMC_COPY_FROM_USER(&ctl, ifr->ifr_data, sizeof (lmc_ctl_t));
+        sc->lmc_media->set_circuit_type(sc, ctl.circuit_type);
+        sc->ictl.circuit_type = ctl.circuit_type;
+        ret = 0;
+
+        break;
+
+    case LMCIOCRESET:
+        if (!suser ()){
+            ret = -EPERM;
+            break;
+        }
+
+        /* Reset driver and bring back to current state */
+        printk (" REG16 before reset +%04x\n", lmc_mii_readreg (sc, 0, 16));
+        lmc_running_reset (dev);
+        printk (" REG16 after reset +%04x\n", lmc_mii_readreg (sc, 0, 16));
+
+        LMC_EVENT_LOG(LMC_EVENT_FORCEDRESET, LMC_CSR_READ (sc, csr_status), lmc_mii_readreg (sc, 0, 16));
+
+        ret = 0;
+        break;
+
+#ifdef DEBUG
+    case LMCIOCDUMPEVENTLOG:
+        LMC_COPY_TO_USER(ifr->ifr_data, &lmcEventLogIndex, sizeof (u32));
+        LMC_COPY_TO_USER(ifr->ifr_data + sizeof (u32), lmcEventLogBuf, sizeof (lmcEventLogBuf));
+
+        ret = 0;
+        break;
+#endif /* end ifdef _DBG_EVENTLOG */
+    case LMCIOCT1CONTROL:
+        if (sc->lmc_cardtype != LMC_CARDTYPE_T1){
+            ret = -EOPNOTSUPP;
+            break;
+        }
+        break;
+    default:
+        /* If we don't know what to do, give syncppp a shot. */
+        ret = sppp_do_ioctl (dev, ifr, cmd);
+    }
+
+    spin_unlock_irqrestore(&sc->lmc_lock, flags);
+
+    return ret;
+}
+
+
+/* the watchdog process that cruises around */
+static void lmc_watchdog (unsigned long data) /*fold00*/
+{
+    struct device *dev = (struct device *) data;
+    lmc_softc_t *sc;
+    int link_status;
+    u_int32_t ticks;
+    LMC_SPIN_FLAGS
+
+    sc = dev->priv;
+
+    spin_lock_irqsave(&sc->lmc_lock, flags);
+
+    /* Make sure the tx jabber and rx watchdog are off,
+     * and the transmit and recieve processes are running.
+     */
+
+    LMC_CSR_WRITE (sc, csr_15, 0x00000011);
+    sc->lmc_cmdmode |= TULIP_CMD_TXRUN | TULIP_CMD_RXRUN;
+    LMC_CSR_WRITE (sc, csr_command, sc->lmc_cmdmode);
+
+    if (sc->lmc_ok == 0)
+        goto kick_timer;
+
+    LMC_EVENT_LOG(LMC_EVENT_WATCHDOG, LMC_CSR_READ (sc, csr_status), lmc_mii_readreg (sc, 0, 16));
+
+    /* --- begin time out check -----------------------------------
+     * check for a transmit interrupt timeout
+     * Has the packet xmt vs xmt serviced threshold been exceeded */
+    if (sc->lmc_taint_tx == sc->lastlmc_taint_tx &&
+        sc->stats.tx_packets > sc->lasttx_packets &&
+        sc->tx_TimeoutInd == 0)
+    {
+
+        /* wait for the watchdog to come around again */
+        sc->tx_TimeoutInd = 1;
+    }
+    else if (sc->lmc_taint_tx == sc->lastlmc_taint_tx &&
+             sc->stats.tx_packets > sc->lasttx_packets &&
+             sc->tx_TimeoutInd)
+    {
+
+        LMC_EVENT_LOG(LMC_EVENT_XMTINTTMO, LMC_CSR_READ (sc, csr_status), 0);
+
+        sc->tx_TimeoutDisplay = 1;
+        sc->stats.tx_TimeoutCnt++;
+
+        /* DEC chip is stuck, hit it with a RESET!!!! */
+        lmc_running_reset (dev);
+
+
+        /* look at receive & transmit process state to make sure they are running */
+        LMC_EVENT_LOG(LMC_EVENT_RESET1, LMC_CSR_READ (sc, csr_status), 0);
+
+        /* look at: DSR - 02  for Reg 16
+         *                  CTS - 08
+         *                  DCD - 10
+         *                  RI  - 20
+         * for Reg 17
+         */
+        LMC_EVENT_LOG(LMC_EVENT_RESET2, lmc_mii_readreg (sc, 0, 16), lmc_mii_readreg (sc, 0, 17));
+
+        /* reset the transmit timeout detection flag */
+        sc->tx_TimeoutInd = 0;
+        sc->lastlmc_taint_tx = sc->lmc_taint_tx;
+        sc->lasttx_packets = sc->stats.tx_packets;
+    }
+    else
+    {
+        sc->tx_TimeoutInd = 0;
+        sc->lastlmc_taint_tx = sc->lmc_taint_tx;
+        sc->lasttx_packets = sc->stats.tx_packets;
+    }
+
+    /* --- end time out check ----------------------------------- */
+
+
+    link_status = sc->lmc_media->get_link_status (sc);
+
+    /*
+     * hardware level link lost, but the interface is marked as up.
+     * Mark it as down.
+     */
+    if ((link_status == 0) && (sc->last_link_status != 0)) {
+        printk(KERN_WARNING "%s: link down\n", dev->name);
+        sc->last_link_status = 0;
+        /* lmc_reset (sc); Why reset??? The link can go down ok */
+
+        /* Inform the world that link has been lost */
+        dev->flags &= ~IFF_RUNNING;
+    }
+
+    /*
+     * hardware link is up, but the interface is marked as down.
+     * Bring it back up again.
+     */
+     if (link_status != 0 && sc->last_link_status == 0) {
+         printk(KERN_WARNING "%s: link up\n", dev->name);
+         sc->last_link_status = 1;
+         /* lmc_reset (sc); Again why reset??? */
+
+         /* Inform the world that link protocol is back up. */
+         dev->flags |= IFF_RUNNING;
+
+         /* Now we have to tell the syncppp that we had an outage
+          * and that it should deal.  Calling sppp_reopen here
+          * should do the trick, but we may have to call sppp_close
+          * when the link goes down, and call sppp_open here.
+          * Subject to more testing.
+          * --bbraun
+          */
+
+         sppp_reopen (dev);
+
+     }
+
+    /* Call media specific watchdog functions */
+    sc->lmc_media->watchdog(sc);
+
+    /*
+     * Poke the transmitter to make sure it
+     * never stops, even if we run out of mem
+     */
+    LMC_CSR_WRITE(sc, csr_rxpoll, 0);
+
+
+    /*
+     * remember the timer value
+     */
+kick_timer:
+
+    ticks = LMC_CSR_READ (sc, csr_gp_timer);
+    LMC_CSR_WRITE (sc, csr_gp_timer, 0xffffffffUL);
+    sc->ictl.ticks = 0x0000ffff - (ticks & 0x0000ffff);
+
+    /*
+     * restart this timer.
+     */
+    sc->timer.expires = jiffies + (HZ);
+    add_timer (&sc->timer);
+
+    spin_unlock_irqrestore(&sc->lmc_lock, flags);
+
+}
+
+static int lmc_init(struct device * const dev) /*fold00*/
+{
+    return 0;
+}
+
+/* This initializes each card from lmc_probe() */
+static struct device *lmc_probe1 (struct device *dev, int ioaddr, int irq, /*fold00*/
+                                  int chip_id, int subdevice, int board_idx)
+{
+    lmc_softc_t *sc = NULL;
+    u_int16_t AdapModelNum;
+
+    /*
+     * Allocate our own device structure
+     */
+
+    dev = kmalloc (sizeof (struct ppp_device)+8, GFP_KERNEL);
+    if (dev == NULL){
+        printk (KERN_ERR "lmc: kmalloc for device failed\n");
+        return NULL;
+    }
+    memset (dev, 0, sizeof (struct ppp_device));
+
+	/*
+	 *	Switch to common hdlc%d naming. We name by type not by vendor
+	 */
+    dev->name = (char *) (((u32) (dev)) + sizeof (struct ppp_device));
+    dev_alloc_name(dev, "hdlc%d");
+
+    Lmc_Count++;
+
+    if(lmc_first_load == 0){
+        printk(KERN_INFO "Lan Media Corporation WAN Driver Version %d.%d.%d\n",DRIVER_MAJOR_VERSION, DRIVER_MINOR_VERSION,DRIVER_SUB_VERSION);
+#ifndef MODULE
+        sync_ppp_init();
+#endif
+        lmc_first_load = 1;
+    }
+
+
+    /* Initialize the sppp layer */
+    sppp_attach ((struct ppp_device *) dev);
+
+    /*
+     * Allocate space for the private data structure
+     */
+
+    sc = kmalloc (sizeof (lmc_softc_t), GFP_KERNEL);
+    if (sc == NULL) {
+        printk (KERN_WARNING "%s: Cannot allocate memory for device state\n",
+                dev->name);
+        return (NULL);
+    }
+    memset (sc, 0, sizeof (lmc_softc_t));
+    dev->priv = sc;
+    sc->lmc_device = dev;
+    sc->name = dev->name;
+
+    /* Just fill in the entries for the device */
+
+    dev->init = lmc_init;
+    dev->hard_start_xmit = lmc_start_xmit;
+    dev->open = lmc_open;
+    dev->stop = lmc_close;
+    dev->get_stats = lmc_get_stats;
+    dev->do_ioctl = lmc_ioctl;
+    dev->set_config = lmc_set_config;
+    /*
+     * Why were we changing this???
+     dev->tx_queue_len = 100;
+     */
+
+    /* Init the spin lock so can call it latter */
+
+    spin_lock_init(&sc->lmc_lock);
+
+    LMC_SETUP_20_DEV;
+
+    printk ("%s: detected at %#3x, irq %d\n", dev->name, ioaddr, irq);
+
+    dev->base_addr = ioaddr;
+    dev->irq = irq;
+
+    if (register_netdev (dev) != 0) {
+        printk (KERN_ERR "%s: register_netdev failed.\n", dev->name);
+        sppp_detach (dev);
+        kfree (dev->priv);
+        kfree (dev);
+        return NULL;
+    }
+
+    /*
+     * Request the region of registers we need, so that
+     * later on, no one else will take our card away from
+     * us.
+     */
+    request_region (ioaddr, LMC_REG_RANGE, dev->name);
+
+    sc->lmc_cardtype = LMC_CARDTYPE_UNKNOWN;
+    sc->lmc_timing = LMC_CTL_CLOCK_SOURCE_EXT;
+
+    switch (subdevice) {
+    case PCI_PRODUCT_LMC_HSSI:
+        printk ("%s: LMC HSSI\n", dev->name);
+        sc->lmc_cardtype = LMC_CARDTYPE_HSSI;
+        sc->lmc_media = &lmc_hssi_media;
+        break;
+    case PCI_PRODUCT_LMC_DS3:
+        printk ("%s: LMC DS3\n", dev->name);
+        sc->lmc_cardtype = LMC_CARDTYPE_DS3;
+        sc->lmc_media = &lmc_ds3_media;
+        break;
+    case PCI_PRODUCT_LMC_SSI:
+        printk ("%s: LMC SSI\n", dev->name);
+        sc->lmc_cardtype = LMC_CARDTYPE_SSI;
+        sc->lmc_media = &lmc_ssi_media;
+        break;
+    case PCI_PRODUCT_LMC_T1:
+        printk ("%s: LMC T1\n", dev->name);
+        sc->lmc_cardtype = LMC_CARDTYPE_T1;
+        sc->lmc_media = &lmc_t1_media;
+        break;
+    default:
+        printk (KERN_WARNING "%s: LMC UNKOWN CARD!\n", dev->name);
+        break;
+    }
+
+    lmc_initcsrs (sc, dev->base_addr, 8);
+
+    lmc_gpio_mkinput (sc, 0xff);
+    sc->lmc_gpio = 0;		/* drive no signals yet */
+
+    sc->lmc_media->defaults (sc);
+
+    sc->lmc_media->set_link_status (sc, LMC_LINK_UP);
+
+    /* verify that the PCI Sub System ID matches the Adapter Model number
+     * from the MII register
+     */
+    AdapModelNum = (lmc_mii_readreg (sc, 0, 3) & 0x3f0) >> 4;
+
+    if ((AdapModelNum == LMC_ADAP_T1
+         && subdevice == PCI_PRODUCT_LMC_T1) ||		/* detect LMC1200 */
+        (AdapModelNum == LMC_ADAP_SSI
+         && subdevice == PCI_PRODUCT_LMC_SSI) ||	/* detect LMC1000 */
+        (AdapModelNum == LMC_ADAP_DS3
+         && subdevice == PCI_PRODUCT_LMC_DS3) ||	/* detect LMC5245 */
+        (AdapModelNum == LMC_ADAP_HSSI
+         && subdevice == PCI_PRODUCT_LMC_HSSI))
+    {				/* detect LMC5200 */
+
+    }
+    else {
+        printk ("%s: Model number (%d) miscompare for PCI Subsystem ID = 0x%04x\n",
+                dev->name, AdapModelNum, subdevice);
+        return (NULL);
+    }
+    /*
+     * reset clock
+     */
+    LMC_CSR_WRITE (sc, csr_gp_timer, 0xFFFFFFFFUL);
+
+    sc->board_idx = board_idx;
+
+    memset (&sc->stats, 0, sizeof (struct lmc_statistics));
+
+    sc->stats.check = STATCHECK;
+    sc->stats.version_size = (DRIVER_VERSION << 16) +
+        sizeof (struct lmc_statistics);
+    sc->stats.lmc_cardtype = sc->lmc_cardtype;
+
+    sc->lmc_ok = 0;
+    sc->last_link_status = 0;
+
+    return dev;
+}
+
+
+/* This is the entry point.  This is what is called immediatly. */
+/* This goes out and finds the card */
+
+int lmc_probe_fake(struct device *dev)
+{
+    lmc_probe(NULL);
+    /* Return 1 to unloaded bogus device */
+    return 1;
+}
+
+int lmc_probe (struct device *dev) /*fold00*/
+{
+    int pci_index = 0;
+    unsigned char pci_irq_line;
+    u16 vendor, subvendor, device, subdevice;
+    u32 pci_ioaddr, foundaddr = 0;
+    unsigned char pci_bus, pci_device_fn;
+    u8 intcf = 0;
+
+    /* The card is only available on PCI, so if we don't have a
+     * PCI bus, we are in trouble.
+     */
+
+    if (!LMC_PCI_PRESENT()) {
+/*        printk ("%s: We really want a pci bios!\n", dev->name);*/
+        return -1;
+    }
+    /* Loop basically until we don't find anymore. */
+    while (pci_index < 0xff){
+        /* The tulip is considered an ethernet class of card... */
+        if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8,
+                                pci_index, &pci_bus,
+                                &pci_device_fn) != PCIBIOS_SUCCESSFUL) {
+            /* No card found on this pass */
+            break;
+        }
+        /* Read the info we need to determine if this is
+         * our card or not
+         */
+#if LINUX_VERSION_CODE >= 0x20155
+        vendor = pci_find_slot (pci_bus, pci_device_fn)->vendor;
+        device = pci_find_slot (pci_bus, pci_device_fn)->device;
+        pci_irq_line = pci_find_slot (pci_bus, pci_device_fn)->irq;
+        pci_ioaddr = pci_find_slot (pci_bus, pci_device_fn)->base_address[0];
+        pci_read_config_word (pci_find_slot (pci_bus, pci_device_fn),
+                              PCI_SUBSYSTEM_VENDOR_ID, &subvendor);
+        pci_read_config_word (pci_find_slot (pci_bus, pci_device_fn),
+                              PCI_SUBSYSTEM_ID, &subdevice);
+#else
+        pcibios_read_config_word (pci_bus, pci_device_fn,
+                                  PCI_VENDOR_ID, &vendor);
+        pcibios_read_config_word (pci_bus, pci_device_fn,
+                                  PCI_DEVICE_ID, &device);
+        pcibios_read_config_byte (pci_bus, pci_device_fn,
+                                  PCI_INTERRUPT_LINE, &pci_irq_line);
+        pcibios_read_config_dword(pci_bus, pci_device_fn,
+                                  PCI_BASE_ADDRESS_0, &pci_ioaddr);
+        pcibios_read_config_word (pci_bus, pci_device_fn,
+                                  PCI_SUBSYSTEM_VENDOR_ID, &subvendor);
+        pcibios_read_config_word (pci_bus, pci_device_fn,
+                                  PCI_SUBSYSTEM_ID, &subdevice);
+#endif
+
+        /* Align the io address on the 32 bit boundry just in case */
+        pci_ioaddr &= ~3;
+
+        /*
+         * Make sure it's the correct card.  CHECK SUBVENDOR ID!
+         * There are lots of tulip's out there.
+         * Also check the region of registers we will soon be
+         * poking, to make sure no one else has reserved them.
+         * This prevents taking someone else's device.
+         *
+         * Check either the subvendor or the subdevice, some systems reverse
+         * the setting in the bois, seems to be version and arch dependant?
+         * Fix the two variables
+         *
+         */
+        if (!(check_region (pci_ioaddr, LMC_REG_RANGE)) &&
+            (vendor == CORRECT_VENDOR_ID) &&
+            (device == CORRECT_DEV_ID) &&
+            ((subvendor == PCI_VENDOR_LMC)  || (subdevice == PCI_VENDOR_LMC))){
+            struct device *cur, *prev = NULL;
+
+            /* Fix the error, exchange the two values */
+            if(subdevice == PCI_VENDOR_LMC){
+                subdevice = subvendor;
+                subvendor = PCI_VENDOR_LMC ;
+            }
+
+            /* Make the call to actually setup this card */
+            dev = lmc_probe1 (dev, pci_ioaddr, pci_irq_line,
+                              device, subdevice, cards_found);
+            if (dev == NULL) {
+                printk ("lmc_probe: lmc_probe1 failed\n");
+                goto lmc_probe_next_card;
+            }
+            /* insert the device into the chain of lmc devices */
+            for (cur = Lmc_root_dev;
+                 cur != NULL;
+                 cur = ((lmc_softc_t *) cur->priv)->next_module) {
+                prev = cur;
+            }
+
+            if (prev == NULL)
+                Lmc_root_dev = dev;
+            else
+                ((lmc_softc_t *) prev->priv)->next_module = dev;
+
+            ((lmc_softc_t *) dev->priv)->next_module = NULL;
+            /* end insert */
+
+            foundaddr = dev->base_addr;
+
+            cards_found++;
+            intcf++;
+        }
+    lmc_probe_next_card:
+        pci_index++;
+    }
+
+    if (cards_found < 1)
+        return -1;
+
+#if LINUX_VERSION_CODE >= 0x20200
+    return foundaddr;
+#else
+    return 0;
+#endif
+}
+
+/* After this is called, packets can be sent.
+ * Does not initialize the addresses
+ */
+static int lmc_open (struct device *dev) /*fold00*/
+{
+    lmc_softc_t *sc = dev->priv;
+    int err;
+
+    lmc_dec_reset (sc);
+    lmc_reset (sc);
+
+    LMC_EVENT_LOG(LMC_EVENT_RESET1, LMC_CSR_READ (sc, csr_status), 0);
+    LMC_EVENT_LOG(LMC_EVENT_RESET2,
+                  lmc_mii_readreg (sc, 0, 16),
+                  lmc_mii_readreg (sc, 0, 17));
+
+
+    if (sc->lmc_ok)
+        return (0);
+
+    lmc_softreset (sc);
+
+    /* Since we have to use PCI bus, this should work on x86,alpha,ppc */
+    if (request_irq (dev->irq, &lmc_interrupt, SA_SHIRQ, dev->name, dev)){
+        printk(KERN_WARNING "%s: could not get irq: %d\n", dev->name, dev->irq);
+        return -EAGAIN;
+    }
+    sc->got_irq = 1;
+
+    /* Assert Terminal Active */
+    sc->lmc_miireg16 |= LMC_MII16_LED_ALL;
+    sc->lmc_media->set_link_status (sc, LMC_LINK_UP);
+
+    /*
+     * reset to last state.
+     */
+    sc->lmc_media->set_status (sc, NULL);
+
+    /* setup default bits to be used in tulip_desc_t transmit descriptor
+     * -baz */
+    sc->TxDescriptControlInit = (
+                                 LMC_TDES_INTERRUPT_ON_COMPLETION
+                                 | LMC_TDES_FIRST_SEGMENT
+                                 | LMC_TDES_LAST_SEGMENT
+                                 | LMC_TDES_SECOND_ADDR_CHAINED
+                                 | LMC_TDES_DISABLE_PADDING
+                                );
+
+    if (sc->ictl.crc_length == LMC_CTL_CRC_LENGTH_16) {
+        /* disable 32 bit CRC generated by ASIC */
+        sc->TxDescriptControlInit |= LMC_TDES_ADD_CRC_DISABLE;
+    }
+    /* Acknoledge the Terminal Active and light LEDs */
+
+    /* dev->flags |= IFF_UP; */
+
+    err = sppp_open (dev);
+    if (err){
+        return err;
+    }
+    dev->do_ioctl = lmc_ioctl;
+    dev->tbusy = 0;
+    dev->start = 1;
+
+    MOD_INC_USE_COUNT;
+
+    /*
+     * select what interrupts we want to get
+     */
+    sc->lmc_intrmask = 0;
+    /* Should be using the default interrupt mask defined in the .h file. */
+    sc->lmc_intrmask |= (TULIP_STS_NORMALINTR
+                         | TULIP_STS_RXINTR
+                         | TULIP_STS_TXINTR
+                         | TULIP_STS_ABNRMLINTR
+                         | TULIP_STS_SYSERROR
+                         | TULIP_STS_TXSTOPPED
+                         | TULIP_STS_TXUNDERFLOW
+                         | TULIP_STS_RXSTOPPED
+                        );
+    LMC_CSR_WRITE (sc, csr_intr, sc->lmc_intrmask);
+
+    sc->lmc_cmdmode |= TULIP_CMD_TXRUN;
+    sc->lmc_cmdmode |= TULIP_CMD_RXRUN;
+    LMC_CSR_WRITE (sc, csr_command, sc->lmc_cmdmode);
+
+    sc->lmc_ok = 1; /* Run watchdog */
+
+    /*
+     * Set the if up now - pfb
+     */
+
+    sc->last_link_status = 1;
+
+    /*
+     * Setup a timer for the watchdog on probe, and start it running.
+     * Since lmc_ok == 0, it will be a NOP for now.
+     */
+    init_timer (&sc->timer);
+    sc->timer.expires = jiffies + HZ;
+    sc->timer.data = (unsigned long) dev;
+    sc->timer.function = &lmc_watchdog;
+    add_timer (&sc->timer);
+
+    return (0);
+}
+
+/* Total reset to compensate for the AdTran DSU doing bad things
+ *  under heavy load
+ */
+
+static void lmc_running_reset (struct device *dev) /*fold00*/
+{
+
+    lmc_softc_t *sc = (lmc_softc_t *) dev->priv;
+
+    /* stop interrupts */
+    /* Clear the interrupt mask */
+    LMC_CSR_WRITE (sc, csr_intr, 0x00000000);
+
+    lmc_dec_reset (sc);
+    lmc_reset (sc);
+    lmc_softreset (sc);
+    /* sc->lmc_miireg16 |= LMC_MII16_LED_ALL; */
+    sc->lmc_media->set_link_status (sc, 1);
+    sc->lmc_media->set_status (sc, NULL);
+
+    dev->flags |= IFF_RUNNING;
+    dev->tbusy = 0;
+    sc->lmc_txfull = 0;
+
+    sc->lmc_intrmask = TULIP_DEFAULT_INTR_MASK;
+    LMC_CSR_WRITE (sc, csr_intr, sc->lmc_intrmask);
+
+    sc->lmc_cmdmode |= (TULIP_CMD_TXRUN | TULIP_CMD_RXRUN);
+    LMC_CSR_WRITE (sc, csr_command, sc->lmc_cmdmode);
+}
+
+
+/* This is what is called when you ifconfig down a device.
+ * This disables the timer for the watchdog and keepalives,
+ * and disables the irq for dev.
+ */
+static int lmc_close (struct device *dev) /*fold00*/
+{
+    /* not calling release_region() as we should */
+    lmc_softc_t *sc;
+
+    sc = dev->priv;
+    sc->lmc_ok = 0;
+    sc->lmc_media->set_link_status (sc, 0);
+    del_timer (&sc->timer);
+    sppp_close (dev);
+    lmc_ifdown (dev);
+
+    return 0;
+}
+
+/* Ends the transfer of packets */
+/* When the interface goes down, this is called */
+static int lmc_ifdown (struct device *dev) /*fold00*/
+{
+    lmc_softc_t *sc = dev->priv;
+    u32 csr6;
+    int i;
+
+    /* Don't let anything else go on right now */
+    dev->start = 0;
+    dev->tbusy = 1;
+
+    /* stop interrupts */
+    /* Clear the interrupt mask */
+    LMC_CSR_WRITE (sc, csr_intr, 0x00000000);
+
+    /* Stop Tx and Rx on the chip */
+    csr6 = LMC_CSR_READ (sc, csr_command);
+    csr6 &= ~LMC_DEC_ST;		/* Turn off the Transmission bit */
+    csr6 &= ~LMC_DEC_SR;		/* Turn off the Recieve bit */
+    LMC_CSR_WRITE (sc, csr_command, csr6);
+
+    dev->flags &= ~IFF_RUNNING;
+
+    sc->stats.rx_missed_errors +=
+        LMC_CSR_READ (sc, csr_missed_frames) & 0xffff;
+
+    /* release the interrupt */
+    if(sc->got_irq == 1){
+        free_irq (dev->irq, dev);
+        sc->got_irq = 0;
+    }
+
+    /* free skbuffs in the Rx queue */
+    for (i = 0; i < LMC_RXDESCS; i++)
+    {
+        struct sk_buff *skb = sc->lmc_rxq[i];
+        sc->lmc_rxq[i] = 0;
+        sc->lmc_rxring[i].status = 0;
+        sc->lmc_rxring[i].length = 0;
+        sc->lmc_rxring[i].buffer1 = 0xDEADBEEF;
+        if (skb != NULL)
+        {
+            LMC_SKB_FREE(skb, 1);
+            LMC_DEV_KFREE_SKB (skb);
+        }
+        sc->lmc_rxq[i] = NULL;
+    }
+
+    for (i = 0; i < LMC_TXDESCS; i++)
+    {
+        if (sc->lmc_txq[i] != NULL)
+            LMC_DEV_KFREE_SKB (sc->lmc_txq[i]);
+        sc->lmc_txq[i] = NULL;
+    }
+
+    lmc_led_off (sc, LMC_MII16_LED_ALL);
+
+    dev->tbusy = 0;
+
+    MOD_DEC_USE_COUNT;
+    return 0;
+}
+
+/* Interrupt handling routine.  This will take an incoming packet, or clean
+ * up after a trasmit.
+ */
+static void lmc_interrupt (int irq, void *dev_instance, struct pt_regs *regs) /*fold00*/
+{
+    struct device *dev = (struct device *) dev_instance;
+    lmc_softc_t *sc;
+    u32 csr;
+    int i;
+    s32 stat;
+    unsigned int badtx;
+    u32 firstcsr;
+
+    sc = dev->priv;
+
+    spin_lock(&sc->lmc_lock);
+
+    if (test_and_set_bit (0, (void *) &dev->interrupt)) {
+        goto lmc_int_fail_out;
+    }
+
+    /*
+     * Read the csr to find what interupts we have (if any)
+     */
+    csr = LMC_CSR_READ (sc, csr_status);
+
+    /*
+     * Make sure this is our interrupt
+     */
+    if ( ! (csr & sc->lmc_intrmask)) {
+        goto lmc_int_fail_out;
+    }
+
+    firstcsr = csr;
+
+    /* always go through this loop at least once */
+    while (csr & sc->lmc_intrmask) {
+
+        /*
+         * Clear interupt bits, we handle all case below
+         */
+        LMC_CSR_WRITE (sc, csr_status, csr);
+
+        /*
+         * One of
+         *  - Transmit process timed out CSR5<1>
+         *  - Transmit jabber timeout    CSR5<3>
+         *  - Transmit underflow         CSR5<5>
+         *  - Transmit Receiver buffer unavailable CSR5<7>
+         *  - Receive process stopped    CSR5<8>
+         *  - Receive watchdog timeout   CSR5<9>
+         *  - Early transmit interrupt   CSR5<10>
+         *
+         * Is this really right? Should we do a running reset for jabber?
+         * (being a WAN card and all)
+         */
+        if (csr & TULIP_STS_ABNRMLINTR){
+            lmc_running_reset (dev);
+            break;
+        }
+
+        
+        if (csr & (TULIP_STS_RXINTR | TULIP_STS_RXNOBUF)) {
+	  lmc_rx (dev);
+        }
+        
+        if (csr & (TULIP_STS_TXINTR | TULIP_STS_TXNOBUF | TULIP_STS_TXSTOPPED)) {
+
+            /* reset the transmit timeout detection flag -baz */
+            sc->stats.tx_NoCompleteCnt = 0;
+
+            badtx = sc->lmc_taint_tx;
+            i = badtx % LMC_TXDESCS;
+
+            while ((badtx < sc->lmc_next_tx)) {
+                stat = sc->lmc_txring[i].status;
+
+                LMC_EVENT_LOG (LMC_EVENT_XMTINT, stat, 0);
+                /*
+                 * If bit 31 is 1 the tulip owns it break out of the loop
+                 */
+                if (stat < 0)
+                    break;
+
+                /*
+                 * If we have no skbuff or have cleared it
+                 * Already continue to the next buffer
+                 */
+                if (sc->lmc_txq[i] == NULL)
+                    continue;
+
+                /*
+                 * Check the total error summary to look for any errors
+                 */
+                if (stat & 0x8000) {
+                    sc->stats.tx_errors++;
+                    if (stat & 0x4104)
+                        sc->stats.tx_aborted_errors++;
+                    if (stat & 0x0C00)
+                        sc->stats.tx_carrier_errors++;
+                    if (stat & 0x0200)
+                        sc->stats.tx_window_errors++;
+                    if (stat & 0x0002)
+                        sc->stats.tx_fifo_errors++;
+                }
+                else {
+                    
+#if LINUX_VERSION_CODE >= 0x20200
+                    sc->stats.tx_bytes += sc->lmc_txring[i].length & 0x7ff;
+#endif
+                    
+                    sc->stats.tx_packets++;
+                }
+                
+                LMC_DEV_KFREE_SKB (sc->lmc_txq[i]);
+                sc->lmc_txq[i] = 0;
+
+                badtx++;
+                i = badtx % LMC_TXDESCS;
+            }
+
+            if (sc->lmc_next_tx - badtx > LMC_TXDESCS)
+            {
+                printk ("%s: out of sync pointer\n", dev->name);
+                badtx += LMC_TXDESCS;
+            }
+            sc->lmc_txfull = 0;
+            dev->tbusy = 0;
+            mark_bh (NET_BH);  /* Tell Linux to give me more packets */
+
+#ifdef DEBUG
+            sc->stats.dirtyTx = badtx;
+            sc->stats.lmc_next_tx = sc->lmc_next_tx;
+            sc->stats.lmc_txfull = sc->lmc_txfull;
+            sc->stats.tbusy = dev->tbusy;
+#endif
+            sc->lmc_taint_tx = badtx;
+
+            /*
+             * Why was there a break here???
+             */
+        }			/* end handle transmit interrupt */
+
+        if (csr & TULIP_STS_SYSERROR) {
+            u32 error;
+            printk (KERN_WARNING "%s: system bus error csr: %#8.8x\n", dev->name, csr);
+            error = csr>>23 & 0x7;
+            switch(error){
+            case 0x000:
+                printk(KERN_WARNING "%s: Parity Fault (bad)\n", dev->name);
+                break;
+            case 0x001:
+                printk(KERN_WARNING "%s: Master Abort (naughty)\n", dev->name);
+                break;
+            case 0x010:
+                printk(KERN_WARNING "%s: Target Abort (not so naughty)\n", dev->name);
+                break;
+            default:
+                printk(KERN_WARNING "%s: This bus error code was supposed to be reserved!\n", dev->name);
+            }
+            lmc_dec_reset (sc);
+            lmc_reset (sc);
+            LMC_EVENT_LOG(LMC_EVENT_RESET1, LMC_CSR_READ (sc, csr_status), 0);
+            LMC_EVENT_LOG(LMC_EVENT_RESET2,
+                          lmc_mii_readreg (sc, 0, 16),
+                          lmc_mii_readreg (sc, 0, 17));
+
+        }
+        /*
+         * Get current csr status to make sure
+         * we've cleared all interupts
+         */
+        csr = LMC_CSR_READ (sc, csr_status);
+    }				/* end interrupt loop */
+    LMC_EVENT_LOG(LMC_EVENT_INT, firstcsr, csr);
+
+    dev->interrupt = 0;
+
+lmc_int_fail_out:
+
+    spin_unlock(&sc->lmc_lock);
+    return;
+}
+
+static int lmc_start_xmit (struct sk_buff *skb, struct device *dev) /*fold00*/
+{
+    lmc_softc_t *sc;
+    u32 flag;
+    int entry;
+    int ret = 0;
+    LMC_SPIN_FLAGS;
+
+    sc = dev->priv;
+
+    /* the interface better be up */
+    if ( ! (dev->flags & IFF_UP))
+        return 1;
+
+    spin_lock_irqsave(&sc->lmc_lock, flags);
+
+    /*
+     * If the transmitter is busy
+     * this must be the 5 second polling
+     * from the kernel which called us.
+     * Poke the chip and try to get it running
+     *
+     */
+    if (dev->tbusy) {
+        u32 csr6;
+
+        if (jiffies - dev->trans_start < TX_TIMEOUT) {
+            ret = 1;
+            goto lmc_start_xmit_bug_out;
+        }
+
+        /*
+         * Chip seems to have locked up
+         * Reset it
+         * This whips out all our decriptor
+         * table and starts from scartch
+         */
+
+        LMC_EVENT_LOG(LMC_EVENT_XMTPRCTMO,
+                      LMC_CSR_READ (sc, csr_status),
+                      sc->stats.tx_ProcTimeout);
+
+        lmc_running_reset (dev);
+
+        LMC_EVENT_LOG(LMC_EVENT_RESET1, LMC_CSR_READ (sc, csr_status), 0);
+        LMC_EVENT_LOG(LMC_EVENT_RESET2,
+                      lmc_mii_readreg (sc, 0, 16),
+                      lmc_mii_readreg (sc, 0, 17));
+
+        /* restart the tx processes */
+        csr6 = LMC_CSR_READ (sc, csr_command);
+        LMC_CSR_WRITE (sc, csr_command, csr6 | 0x0002);
+        LMC_CSR_WRITE (sc, csr_command, csr6 | 0x2002);
+
+        /* immediate transmit */
+        LMC_CSR_WRITE (sc, csr_txpoll, 0);
+
+        sc->stats.tx_errors++;
+        sc->stats.tx_ProcTimeout++;	/* -baz */
+
+        dev->trans_start = jiffies;
+
+        ret = 1;
+        goto lmc_start_xmit_bug_out;
+    }
+    /* normal path */
+
+    entry = sc->lmc_next_tx % LMC_TXDESCS;
+
+    sc->lmc_txq[entry] = skb;
+    sc->lmc_txring[entry].buffer1 = virt_to_bus (skb->data);
+
+    LMC_CONSOLE_LOG("xmit", skb->data, skb->len);
+
+    /* If the queue is less than half full, don't interrupt */
+    if (sc->lmc_next_tx - sc->lmc_taint_tx < LMC_TXDESCS / 2)
+    {
+        /* Do not interrupt on completion of this packet */
+        flag = 0x60000000;
+        dev->tbusy = 0;
+    }
+    else if (sc->lmc_next_tx - sc->lmc_taint_tx == LMC_TXDESCS / 2)
+    {
+        /* This generates an interrupt on completion of this packet */
+        flag = 0xe0000000;
+        dev->tbusy = 0;
+    }
+    else if (sc->lmc_next_tx - sc->lmc_taint_tx < LMC_TXDESCS - 1)
+    {
+        /* Do not interrupt on completion of this packet */
+        flag = 0x60000000;
+        dev->tbusy = 0;
+    }
+    else
+    {
+        /* This generates an interrupt on completion of this packet */
+        flag = 0xe0000000;
+        sc->lmc_txfull = 1;
+        dev->tbusy = 1;
+    }
+
+    if ((entry == LMC_TXDESCS - 1))
+    {
+        flag |= 0xe2000000;
+        dev->tbusy = 1;
+    }
+    /* don't pad small packets either */
+    sc->lmc_txring[entry].length = (skb->len) | flag | sc->TxDescriptControlInit;
+
+    /* Done above through TxDescControlInit */
+    /*
+     sc->lmc_txring[entry].length = (skb->len) | flag | 0x00800000;
+     if(sc->ictl.crc_length == LMC_CTL_CRC_LENGTH_16){
+     sc->lmc_txring[entry].length |= 0x04000000;
+     }
+     */
+
+    /* set the transmit timeout flag to be checked in
+     * the watchdog timer handler. -baz
+     */
+
+    sc->stats.tx_NoCompleteCnt++;
+    sc->lmc_next_tx++;
+
+    /* give ownership to the chip */
+    sc->lmc_txring[entry].status = 0x80000000;
+
+    /* send now! */
+    LMC_CSR_WRITE (sc, csr_txpoll, 0);
+
+    dev->trans_start = jiffies;
+
+lmc_start_xmit_bug_out:
+
+    spin_unlock_irqrestore(&sc->lmc_lock, flags);
+    return ret;
+}
+
+
+static int lmc_rx (struct device *dev) /*fold00*/
+{
+    lmc_softc_t *sc;
+    int i;
+    int rx_work_limit = LMC_RXDESCS;
+    unsigned int next_rx;
+    int rxIntLoopCnt;		/* debug -baz */
+    int localLengthErrCnt = 0;
+    long stat;
+    struct sk_buff *skb, *nsb;
+    u16 len;
+
+    sc = dev->priv;
+
+    if ( ! (dev->flags & IFF_UP))
+        return 1;
+
+    rxIntLoopCnt = 0;		/* debug -baz */
+
+    i = sc->lmc_next_rx % LMC_RXDESCS;
+    next_rx = sc->lmc_next_rx;
+
+    while (((stat = sc->lmc_rxring[i].status) & LMC_RDES_OWN_BIT) != DESC_OWNED_BY_DC21X4)
+    {
+        rxIntLoopCnt++;		/* debug -baz */
+        LMC_EVENT_LOG(LMC_EVENT_RCVINT, stat, 0);
+
+        if ((stat & 0x0300) != 0x0300) {  /* Check first segment and last segment */
+            if ((stat & 0x0000ffff) != 0x7fff) {
+                /* Oversized frame */
+                sc->stats.rx_length_errors++;
+                goto skip_packet;
+            }
+        }
+
+        if(stat & 0x00000008){ /* Catch a dribbling bit error */
+            sc->stats.rx_errors++;
+            sc->stats.rx_frame_errors++;
+            goto skip_packet;
+        }
+
+
+        if(stat & 0x00000004){ /* Catch a CRC error by the Xilinx */
+            sc->stats.rx_errors++;
+            sc->stats.rx_crc_errors++;
+            goto skip_packet;
+        }
+
+
+        len = ((stat & LMC_RDES_FRAME_LENGTH) >> RDES_FRAME_LENGTH_BIT_NUMBER);
+        if (len > PKT_BUF_SZ){
+            sc->stats.rx_length_errors++;
+            localLengthErrCnt++;
+            goto skip_packet;
+        }
+
+        if (len < sc->lmc_crcSize + 2) {
+            sc->stats.rx_length_errors++;
+            sc->stats.rx_SmallPktCnt++;
+            localLengthErrCnt++;
+            goto skip_packet;
+        }
+
+        if(stat & 0x00004000){
+            printk(KERN_WARNING "%s: Receiver descriptor error, receiver out of sync?\n", dev->name);
+        }
+
+        len -= sc->lmc_crcSize;
+
+        skb = sc->lmc_rxq[i];
+
+        /*
+         * We ran out of memory at some point
+         * just allocate an skb buff and continue.
+         */
+        
+        if(skb == 0x0){
+            nsb = dev_alloc_skb (PKT_BUF_SZ + 2);
+            if (nsb) {
+                LMC_SKB_FREE(nsb, 1);
+                sc->lmc_rxq[i] = nsb;
+                nsb->dev = dev;
+                sc->lmc_rxring[i].buffer1 = virt_to_bus (nsb->tail);
+            }
+            goto skip_packet;
+        }
+        
+        dev->last_rx = jiffies;
+        sc->stats.rx_packets++;
+
+        LMC_CONSOLE_LOG("recv", skb->data, len);
+
+        /*
+         * I'm not sure of the sanity of this
+         * Packets could be arriving at a constant
+         * 44.210mbits/sec and we're going to copy
+         * them into a new buffer??
+         */
+        
+        if(len > LMC_MTU * 0.75){
+            /*
+             * If it's a large packet don't copy it just hand it up
+             */
+        give_it_anyways:
+
+            sc->lmc_rxq[i] = 0x0;
+            sc->lmc_rxring[i].buffer1 = 0x0;
+
+            skb_put (skb, len);
+            skb->protocol=htons(ETH_P_WAN_PPP);
+            skb->mac.raw = skb->data;
+            skb->nh.raw = skb->data;
+            skb->dev = dev;
+            netif_rx(skb);
+
+            /*
+             * This skb will be destroyed by the upper layers, make a new one
+             */
+            nsb = dev_alloc_skb (PKT_BUF_SZ + 2);
+            if (nsb) {
+                LMC_SKB_FREE(nsb, 1);
+                sc->lmc_rxq[i] = nsb;
+                nsb->dev = dev;
+                sc->lmc_rxring[i].buffer1 = virt_to_bus (nsb->tail);
+                /* Transfered to 21140 below */
+            }
+            else {
+                /*
+                 * We've run out of memory, stop trying to allocate
+                 * memory and exit the interupt handler
+                 *
+                 * The chip may run out of receivers and stop
+                 * in which care we'll try to allocate the buffer
+                 * again.  (once a second)
+                 */
+                sc->stats.rx_BuffAllocErr++;
+                goto skip_out_of_mem;
+
+            }
+
+        }
+        else {
+            nsb = dev_alloc_skb(len);
+            if(!nsb) {
+                goto give_it_anyways;
+            }
+            memcpy(skb_put(nsb, len), skb->data, len);
+            nsb->protocol=htons(ETH_P_WAN_PPP);
+            nsb->mac.raw = nsb->data;
+            nsb->nh.raw = nsb->data;
+            nsb->dev = dev;
+            netif_rx(nsb);
+        }
+
+    skip_packet:
+        sc->lmc_rxring[i].status = DESC_OWNED_BY_DC21X4;
+
+        sc->lmc_next_rx++;
+        i = sc->lmc_next_rx % LMC_RXDESCS;
+        rx_work_limit--;
+        if (rx_work_limit < 0)
+            break;
+    }
+    
+    /* detect condition for LMC1000 where DSU cable attaches and fills
+     * descriptors with bogus packets
+     */
+    if (localLengthErrCnt > LMC_RXDESCS - 3) {
+        sc->stats.rx_BadPktSurgeCnt++;
+        LMC_EVENT_LOG(LMC_EVENT_BADPKTSURGE,
+                      localLengthErrCnt,
+                      sc->stats.rx_BadPktSurgeCnt);
+    }
+
+    /* save max count of receive descriptors serviced */
+    if (rxIntLoopCnt > sc->stats.rxIntLoopCnt) {
+        sc->stats.rxIntLoopCnt = rxIntLoopCnt;	/* debug -baz */
+    }
+
+#ifdef DEBUG
+    if (rxIntLoopCnt == 0)
+    {
+        for (i = 0; i < LMC_RXDESCS; i++)
+        {
+            if ((sc->lmc_rxring[i].status & LMC_RDES_OWN_BIT)
+                != DESC_OWNED_BY_DC21X4)
+            {
+                rxIntLoopCnt++;
+            }
+        }
+        LMC_EVENT_LOG(LMC_EVENT_RCVEND, rxIntLoopCnt, 0);
+    }
+#endif
+
+skip_out_of_mem:
+
+    return 0;
+}
+
+static struct enet_statistics *lmc_get_stats (struct device *dev) /*fold00*/
+{
+    lmc_softc_t *sc;
+    LMC_SPIN_FLAGS;
+
+    sc = dev->priv;
+
+    spin_lock_irqsave(&sc->lmc_lock, flags);
+
+    if (dev->start)
+        sc->stats.rx_missed_errors += LMC_CSR_READ (sc, csr_missed_frames) & 0xffff;
+
+    spin_unlock_irqrestore(&sc->lmc_lock, flags);
+
+    return (struct enet_statistics *) &sc->stats;
+}
+
+#ifdef MODULE
+
+int init_module (void) /*fold00*/
+{
+    printk ("lmc: module loaded\n");
+
+    /* Have lmc_probe search for all the cards, and allocate devices */
+    if (lmc_probe (NULL) < 0)
+        return -EIO;
+
+    return 0;
+}
+
+void cleanup_module (void) /*fold00*/
+{
+    struct device *dev, *next;
+
+    /* we have no pointer to our devices, since they are all dynamically
+     * allocated.  So, here we loop through all the network devices
+     * looking for ours.  When found, dispose of them properly.
+     */
+
+    for (dev = Lmc_root_dev;
+         dev != NULL;
+         dev = next )
+    {
+
+        next = ((lmc_softc_t *) dev->priv)->next_module; /* get it now before we deallocate it */
+        printk ("%s: removing...\n", dev->name);
+
+        /* close the syncppp stuff, and release irq. Close is run on unreg net */
+        lmc_close (dev);
+        sppp_detach (dev);
+
+        /* Remove the device from the linked list */
+        unregister_netdev (dev);
+
+        /* Let go of the io region */;
+        release_region (dev->base_addr, LMC_REG_RANGE);
+
+        /* free our allocated structures. */
+        kfree (dev->priv);
+        dev->priv = NULL;
+
+        kfree ((struct ppp_device *) dev);
+        dev = NULL;
+    }
+
+
+    Lmc_root_dev = NULL;
+    printk ("lmc module unloaded\n");
+}
+#endif
+
+unsigned lmc_mii_readreg (lmc_softc_t * const sc, unsigned devaddr, unsigned regno) /*fold00*/
+{
+    int i;
+    int command = (0xf6 << 10) | (devaddr << 5) | regno;
+    int retval = 0;
+
+    LMC_MII_SYNC (sc);
+
+    for (i = 15; i >= 0; i--)
+    {
+        int dataval = (command & (1 << i)) ? 0x20000 : 0;
+
+        LMC_CSR_WRITE (sc, csr_9, dataval);
+        lmc_delay ();
+        /* __SLOW_DOWN_IO; */
+        LMC_CSR_WRITE (sc, csr_9, dataval | 0x10000);
+        lmc_delay ();
+        /* __SLOW_DOWN_IO; */
+    }
+
+    for (i = 19; i > 0; i--)
+    {
+        LMC_CSR_WRITE (sc, csr_9, 0x40000);
+        lmc_delay ();
+        /* __SLOW_DOWN_IO; */
+        retval = (retval << 1) | ((LMC_CSR_READ (sc, csr_9) & 0x80000) ? 1 : 0);
+        LMC_CSR_WRITE (sc, csr_9, 0x40000 | 0x10000);
+        lmc_delay ();
+        /* __SLOW_DOWN_IO; */
+    }
+
+    return (retval >> 1) & 0xffff;
+}
+
+void lmc_mii_writereg (lmc_softc_t * const sc, unsigned devaddr, /*fold00*/
+                       unsigned regno, unsigned data)
+{
+    int i = 32;
+    int command = (0x5002 << 16) | (devaddr << 23) | (regno << 18) | data;
+
+    LMC_MII_SYNC (sc);
+
+    i = 31;
+    while (i >= 0)
+    {
+        int datav;
+
+        if (command & (1 << i))
+            datav = 0x20000;
+        else
+            datav = 0x00000;
+
+        LMC_CSR_WRITE (sc, csr_9, datav);
+        lmc_delay ();
+        /* __SLOW_DOWN_IO; */
+        LMC_CSR_WRITE (sc, csr_9, (datav | 0x10000));
+        lmc_delay ();
+        /* __SLOW_DOWN_IO; */
+        i--;
+    }
+
+    i = 2;
+    while (i > 0)
+    {
+        LMC_CSR_WRITE (sc, csr_9, 0x40000);
+        lmc_delay ();
+        /* __SLOW_DOWN_IO; */
+        LMC_CSR_WRITE (sc, csr_9, 0x50000);
+        lmc_delay ();
+        /* __SLOW_DOWN_IO; */
+        i--;
+    }
+}
+
+static void lmc_softreset (lmc_softc_t * const sc) /*fold00*/
+{
+    int i;
+
+    /* Initialize the recieve rings and buffers. */
+    sc->lmc_txfull = 0;
+    sc->lmc_next_rx = 0;
+    sc->lmc_next_tx = 0;
+    sc->lmc_taint_rx = 0;
+    sc->lmc_taint_tx = 0;
+
+    /*
+     * Setup each one of the receiver buffers
+     * allocate an skbuff for each one, setup the the descriptor table
+     * and point each buffer at the next one
+     */
+
+    for (i = 0; i < LMC_RXDESCS; i++)
+    {
+        struct sk_buff *skb;
+
+        if (sc->lmc_rxq[i] == NULL)
+        {
+            skb = dev_alloc_skb (PKT_BUF_SZ + 2);
+            sc->lmc_rxq[i] = skb;
+        }
+        else
+        {
+            skb = sc->lmc_rxq[i];
+        }
+
+        skb->dev = sc->lmc_device;
+        LMC_SKB_FREE(skb, 1);
+
+        /* owned by 21140 */
+        sc->lmc_rxring[i].status = 0x80000000;
+
+        /* used to be PKT_BUF_SZ now uses skb since we loose some to head room */
+        sc->lmc_rxring[i].length = skb->end - skb->data;
+
+        /* use to be tail which is dumb since you're thinking why write
+         * to the end of the packj,et but since there's nothing there tail == data
+         */
+        sc->lmc_rxring[i].buffer1 = virt_to_bus (skb->data);
+
+        /* This is fair since the structure is static and we have the next address */
+        sc->lmc_rxring[i].buffer2 = virt_to_bus (&sc->lmc_rxring[i + 1]);
+
+    }
+
+    /*
+     * Sets end of ring
+     */
+    sc->lmc_rxring[i - 1].length |= 0x02000000; /* Set end of buffers flag */
+    sc->lmc_rxring[i - 1].buffer2 = virt_to_bus (&sc->lmc_rxring[0]); /* Point back to the start */
+    LMC_CSR_WRITE (sc, csr_rxlist, virt_to_bus (sc->lmc_rxring)); /* write base address */
+
+
+    /* Initialize the transmit rings and buffers */
+    for (i = 0; i < LMC_TXDESCS; i++)
+    {
+        sc->lmc_txq[i] = 0;
+        sc->lmc_txring[i].status = 0x00000000;
+        sc->lmc_txring[i].buffer2 = virt_to_bus (&sc->lmc_txring[i + 1]);
+    }
+    sc->lmc_txring[i - 1].buffer2 = virt_to_bus (&sc->lmc_txring[0]);
+    LMC_CSR_WRITE (sc, csr_txlist, virt_to_bus (sc->lmc_txring));
+}
+
+static int lmc_set_config(struct device *dev, struct ifmap *map) /*fold00*/
+{
+    return -EOPNOTSUPP;
+}
+
+void lmc_gpio_mkinput(lmc_softc_t * const sc, u_int32_t bits)
+{
+    sc->lmc_gpio_io &= ~bits;
+    LMC_CSR_WRITE(sc, csr_gp, TULIP_GP_PINSET | (sc->lmc_gpio_io));
+}
+
+void lmc_gpio_mkoutput(lmc_softc_t * const sc, u_int32_t bits)
+{
+    sc->lmc_gpio_io |= bits;
+    LMC_CSR_WRITE(sc, csr_gp, TULIP_GP_PINSET | (sc->lmc_gpio_io));
+}
+
+void lmc_led_on(lmc_softc_t * const sc, u_int32_t led)
+{
+    if((~sc->lmc_miireg16) & led) /* Already on! */
+        return;
+    
+    sc->lmc_miireg16 &= ~led;
+    lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
+}
+
+void lmc_led_off(lmc_softc_t * const sc, u_int32_t led)
+{
+    if(sc->lmc_miireg16 & led) /* Already set don't do anything */
+        return;
+    
+    sc->lmc_miireg16 |= led;
+    lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
+}
+
+static void lmc_reset(lmc_softc_t * const sc)
+{
+    sc->lmc_miireg16 |= LMC_MII16_FIFO_RESET;
+    lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
+
+    sc->lmc_miireg16 &= ~LMC_MII16_FIFO_RESET;
+    lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
+
+    /*
+     * make some of the GPIO pins be outputs
+     */
+    lmc_gpio_mkoutput(sc, LMC_GEP_DP | LMC_GEP_RESET);
+
+    /*
+     * drive DP and RESET low to force configuration.  This also forces
+     * the transmitter clock to be internal, but we expect to reset
+     * that later anyway.
+     */
+    sc->lmc_gpio &= ~(LMC_GEP_DP | LMC_GEP_RESET);
+    LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio);
+
+    /*
+     * hold for more than 10 microseconds
+     */
+    udelay(50);
+
+    /*
+     * stop driving Xilinx-related signals
+     */
+    lmc_gpio_mkinput(sc, LMC_GEP_DP | LMC_GEP_RESET);
+
+    /*
+     * busy wait for the chip to reset
+     */
+    while ((LMC_CSR_READ(sc, csr_gp) & LMC_GEP_DP) == 0)
+        ;
+
+    /*
+     * Call media specific init routine
+     */
+    sc->lmc_media->init(sc);
+
+    sc->stats.resetCount++;
+}
+
+static void lmc_dec_reset(lmc_softc_t * const sc)
+{
+    u_int32_t val;
+
+    /*
+     * disable all interrupts
+     */
+    sc->lmc_intrmask = 0;
+    LMC_CSR_WRITE(sc, csr_intr, sc->lmc_intrmask);
+
+    /*
+     * Reset the chip with a software reset command.
+     * Wait 10 microseconds (actually 50 PCI cycles but at
+     * 33MHz that comes to two microseconds but wait a
+     * bit longer anyways)
+     */
+    LMC_CSR_WRITE(sc, csr_busmode, TULIP_BUSMODE_SWRESET);
+    udelay(25);
+    sc->lmc_cmdmode = LMC_CSR_READ(sc, csr_command);
+
+    /*
+     * We want:
+     *   no ethernet address in frames we write
+     *   disable padding (txdesc, padding disable)
+     *   ignore runt frames (rdes0 bit 15)
+     *   no receiver watchdog or transmitter jabber timer
+     *       (csr15 bit 0,14 == 1)
+     *   if using 16-bit CRC, turn off CRC (trans desc, crc disable)
+     */
+
+    sc->lmc_cmdmode |= ( TULIP_CMD_PROMISCUOUS
+                         | TULIP_CMD_FULLDUPLEX
+                         | TULIP_CMD_PASSBADPKT
+                         | TULIP_CMD_NOHEARTBEAT
+                         | TULIP_CMD_PORTSELECT
+                         | TULIP_CMD_RECEIVEALL
+                         | TULIP_CMD_MUSTBEONE
+                       );
+    sc->lmc_cmdmode &= ~( TULIP_CMD_OPERMODE
+                          | TULIP_CMD_THRESHOLDCTL
+                          | TULIP_CMD_STOREFWD
+                          | TULIP_CMD_TXTHRSHLDCTL
+                        );
+
+    LMC_CSR_WRITE(sc, csr_command, sc->lmc_cmdmode);
+
+    /*
+     * disable receiver watchdog and transmit jabber
+     */
+    val = LMC_CSR_READ(sc, csr_sia_general);
+    val |= (TULIP_WATCHDOG_TXDISABLE | TULIP_WATCHDOG_RXDISABLE);
+    LMC_CSR_WRITE(sc, csr_sia_general, val);
+
+}
+
+static void lmc_initcsrs(lmc_softc_t * const sc, lmc_csrptr_t csr_base,
+                         size_t csr_size)
+{
+    sc->lmc_csrs.csr_busmode	        = csr_base +  0 * csr_size;
+    sc->lmc_csrs.csr_txpoll		= csr_base +  1 * csr_size;
+    sc->lmc_csrs.csr_rxpoll		= csr_base +  2 * csr_size;
+    sc->lmc_csrs.csr_rxlist		= csr_base +  3 * csr_size;
+    sc->lmc_csrs.csr_txlist		= csr_base +  4 * csr_size;
+    sc->lmc_csrs.csr_status		= csr_base +  5 * csr_size;
+    sc->lmc_csrs.csr_command	        = csr_base +  6 * csr_size;
+    sc->lmc_csrs.csr_intr		= csr_base +  7 * csr_size;
+    sc->lmc_csrs.csr_missed_frames	= csr_base +  8 * csr_size;
+    sc->lmc_csrs.csr_9		        = csr_base +  9 * csr_size;
+    sc->lmc_csrs.csr_10		        = csr_base + 10 * csr_size;
+    sc->lmc_csrs.csr_11		        = csr_base + 11 * csr_size;
+    sc->lmc_csrs.csr_12		        = csr_base + 12 * csr_size;
+    sc->lmc_csrs.csr_13		        = csr_base + 13 * csr_size;
+    sc->lmc_csrs.csr_14		        = csr_base + 14 * csr_size;
+    sc->lmc_csrs.csr_15		        = csr_base + 15 * csr_size;
+}
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/lmc/lmc_media.c linux.15p9/drivers/net/lmc/lmc_media.c
--- linux.vanilla/drivers/net/lmc/lmc_media.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/net/lmc/lmc_media.c	Wed Jan 26 22:58:51 2000
@@ -0,0 +1,1248 @@
+/* $Id: lmc_media.c,v 1.9 2000/01/21 13:29:49 asj Exp $ */
+
+#include <linux/version.h>
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <asm/segment.h>
+#include <asm/smp.h>
+
+#if LINUX_VERSION_CODE < 0x20155
+#include <linux/bios32.h>
+#endif
+
+#include <linux/in.h>
+#include <linux/if_arp.h>
+#include <asm/processor.h>             /* Processor type for cache alignment. */
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include "../syncppp.h"
+#include <linux/inet.h>
+
+#if LINUX_VERSION_CODE >= 0x20200
+#include <asm/uaccess.h>
+#include <asm/spinlock.h>
+#endif
+
+#include "lmc.h"
+#include "lmc_ver.h"
+#include "lmc_var.h"
+#include "lmc_ioctl.h"
+
+#define CONFIG_LMC_IGNORE_HARDWARE_HANDSHAKE 1
+
+ /*
+  * Copyright (c) 1997-2000 LAN Media Corporation (LMC)
+  * All rights reserved.  www.lanmedia.com
+  *
+  * This code is written by:
+  * Andrew Stanley-Jones (asj@cban.com)
+  * Rob Braun (bbraun@vix.com),
+  * Michael Graff (explorer@vix.com) and
+  * Matt Thomas (matt@3am-software.com).
+  *
+  * This software may be used and distributed according to the terms
+  * of the GNU Public License version 2, incorporated herein by reference.
+  */
+
+/*
+ * For lack of a better place, put the T1 cable stuff here.
+ */
+char *lmc_t1_cables[] = {
+  "V.10/RS423", "EIA530A", "reserved", "X.21", "V.35",
+  "EIA449/EIA530/V.36", "V.28/EIA232", "none", NULL
+};
+
+/*
+ * protocol independent method.
+ */
+static void lmc_set_protocol (lmc_softc_t * const, lmc_ctl_t *);
+
+/*
+ * media independent methods to check on media status, link, light LEDs,
+ * etc.
+ */
+static void lmc_ds3_init (lmc_softc_t * const);
+static void lmc_ds3_default (lmc_softc_t * const);
+static void lmc_ds3_set_status (lmc_softc_t * const, lmc_ctl_t *);
+static void lmc_ds3_set_100ft (lmc_softc_t * const, int);
+static int lmc_ds3_get_link_status (lmc_softc_t * const);
+static void lmc_ds3_set_crc_length (lmc_softc_t * const, int);
+static void lmc_ds3_set_scram (lmc_softc_t * const, int);
+static void lmc_ds3_watchdog (lmc_softc_t * const);
+
+static void lmc_hssi_init (lmc_softc_t * const);
+static void lmc_hssi_default (lmc_softc_t * const);
+static void lmc_hssi_set_status (lmc_softc_t * const, lmc_ctl_t *);
+static void lmc_hssi_set_clock (lmc_softc_t * const, int);
+static int lmc_hssi_get_link_status (lmc_softc_t * const);
+static void lmc_hssi_set_link_status (lmc_softc_t * const, int);
+static void lmc_hssi_set_crc_length (lmc_softc_t * const, int);
+static void lmc_hssi_watchdog (lmc_softc_t * const);
+
+static void lmc_ssi_init (lmc_softc_t * const);
+static void lmc_ssi_default (lmc_softc_t * const);
+static void lmc_ssi_set_status (lmc_softc_t * const, lmc_ctl_t *);
+static void lmc_ssi_set_clock (lmc_softc_t * const, int);
+static void lmc_ssi_set_speed (lmc_softc_t * const, lmc_ctl_t *);
+static int lmc_ssi_get_link_status (lmc_softc_t * const);
+static void lmc_ssi_set_link_status (lmc_softc_t * const, int);
+static void lmc_ssi_set_crc_length (lmc_softc_t * const, int);
+static void lmc_ssi_watchdog (lmc_softc_t * const);
+
+static void lmc_t1_init (lmc_softc_t * const);
+static void lmc_t1_default (lmc_softc_t * const);
+static void lmc_t1_set_status (lmc_softc_t * const, lmc_ctl_t *);
+static int lmc_t1_get_link_status (lmc_softc_t * const);
+static void lmc_t1_set_circuit_type (lmc_softc_t * const, int);
+static void lmc_t1_set_crc_length (lmc_softc_t * const, int);
+static void lmc_t1_set_clock (lmc_softc_t * const, int);
+static void lmc_t1_watchdog (lmc_softc_t * const);
+
+static void lmc_dummy_set_1 (lmc_softc_t * const, int);
+static void lmc_dummy_set2_1 (lmc_softc_t * const, lmc_ctl_t *);
+
+static inline void write_av9110_bit (lmc_softc_t *, int);
+static void write_av9110 (lmc_softc_t *, u_int32_t, u_int32_t, u_int32_t,
+			  u_int32_t, u_int32_t);
+
+lmc_media_t lmc_ds3_media = {
+  lmc_ds3_init,			/* special media init stuff */
+  lmc_ds3_default,		/* reset to default state */
+  lmc_ds3_set_status,		/* reset status to state provided */
+  lmc_dummy_set_1,		/* set clock source */
+  lmc_dummy_set2_1,		/* set line speed */
+  lmc_ds3_set_100ft,		/* set cable length */
+  lmc_ds3_set_scram,		/* set scrambler */
+  lmc_ds3_get_link_status,	/* get link status */
+  lmc_dummy_set_1,		/* set link status */
+  lmc_ds3_set_crc_length,	/* set CRC length */
+  lmc_dummy_set_1,		/* set T1 or E1 circuit type */
+  lmc_ds3_watchdog
+};
+
+lmc_media_t lmc_hssi_media = {
+  lmc_hssi_init,		/* special media init stuff */
+  lmc_hssi_default,		/* reset to default state */
+  lmc_hssi_set_status,		/* reset status to state provided */
+  lmc_hssi_set_clock,		/* set clock source */
+  lmc_dummy_set2_1,		/* set line speed */
+  lmc_dummy_set_1,		/* set cable length */
+  lmc_dummy_set_1,		/* set scrambler */
+  lmc_hssi_get_link_status,	/* get link status */
+  lmc_hssi_set_link_status,	/* set link status */
+  lmc_hssi_set_crc_length,	/* set CRC length */
+  lmc_dummy_set_1,		/* set T1 or E1 circuit type */
+  lmc_hssi_watchdog
+};
+
+lmc_media_t lmc_ssi_media = { lmc_ssi_init,	/* special media init stuff */
+  lmc_ssi_default,		/* reset to default state */
+  lmc_ssi_set_status,		/* reset status to state provided */
+  lmc_ssi_set_clock,		/* set clock source */
+  lmc_ssi_set_speed,		/* set line speed */
+  lmc_dummy_set_1,		/* set cable length */
+  lmc_dummy_set_1,		/* set scrambler */
+  lmc_ssi_get_link_status,	/* get link status */
+  lmc_ssi_set_link_status,	/* set link status */
+  lmc_ssi_set_crc_length,	/* set CRC length */
+  lmc_dummy_set_1,		/* set T1 or E1 circuit type */
+  lmc_ssi_watchdog
+};
+
+lmc_media_t lmc_t1_media = {
+  lmc_t1_init,			/* special media init stuff */
+  lmc_t1_default,		/* reset to default state */
+  lmc_t1_set_status,		/* reset status to state provided */
+  lmc_t1_set_clock,		/* set clock source */
+  lmc_dummy_set2_1,		/* set line speed */
+  lmc_dummy_set_1,		/* set cable length */
+  lmc_dummy_set_1,		/* set scrambler */
+  lmc_t1_get_link_status,	/* get link status */
+  lmc_dummy_set_1,		/* set link status */
+  lmc_t1_set_crc_length,	/* set CRC length */
+  lmc_t1_set_circuit_type,	/* set T1 or E1 circuit type */
+  lmc_t1_watchdog
+};
+
+static void
+lmc_dummy_set_1 (lmc_softc_t * const sc, int a)
+{
+}
+
+static void
+lmc_dummy_set2_1 (lmc_softc_t * const sc, lmc_ctl_t * a)
+{
+}
+
+/*
+ *  HSSI methods
+ */
+
+static void
+lmc_hssi_init (lmc_softc_t * const sc)
+{
+  sc->ictl.cardtype = LMC_CTL_CARDTYPE_LMC5200;
+
+  lmc_gpio_mkoutput (sc, LMC_GEP_HSSI_CLOCK);
+}
+
+static void
+lmc_hssi_default (lmc_softc_t * const sc)
+{
+  sc->lmc_miireg16 = LMC_MII16_LED_ALL;
+
+  sc->lmc_media->set_link_status (sc, LMC_LINK_DOWN);
+  sc->lmc_media->set_clock_source (sc, LMC_CTL_CLOCK_SOURCE_EXT);
+  sc->lmc_media->set_crc_length (sc, LMC_CTL_CRC_LENGTH_16);
+}
+
+/*
+ * Given a user provided state, set ourselves up to match it.  This will
+ * always reset the card if needed.
+ */
+static void
+lmc_hssi_set_status (lmc_softc_t * const sc, lmc_ctl_t * ctl)
+{
+  if (ctl == NULL)
+    {
+      sc->lmc_media->set_clock_source (sc, sc->ictl.clock_source);
+      lmc_set_protocol (sc, NULL);
+
+      return;
+    }
+
+  /*
+   * check for change in clock source
+   */
+  if (ctl->clock_source && !sc->ictl.clock_source)
+    {
+      sc->lmc_media->set_clock_source (sc, LMC_CTL_CLOCK_SOURCE_INT);
+      sc->lmc_timing = LMC_CTL_CLOCK_SOURCE_INT;
+    }
+  else if (!ctl->clock_source && sc->ictl.clock_source)
+    {
+      sc->lmc_timing = LMC_CTL_CLOCK_SOURCE_EXT;
+      sc->lmc_media->set_clock_source (sc, LMC_CTL_CLOCK_SOURCE_EXT);
+    }
+
+  lmc_set_protocol (sc, ctl);
+}
+
+/*
+ * 1 == internal, 0 == external
+ */
+static void
+lmc_hssi_set_clock (lmc_softc_t * const sc, int ie)
+{
+  if (ie == LMC_CTL_CLOCK_SOURCE_EXT)
+    {
+      sc->lmc_gpio |= LMC_GEP_HSSI_CLOCK;
+      LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
+      sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_EXT;
+      printk (LMC_PRINTF_FMT ": clock external\n", LMC_PRINTF_ARGS);
+    }
+  else
+    {
+      sc->lmc_gpio &= ~(LMC_GEP_HSSI_CLOCK);
+      LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
+      sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_INT;
+      printk (LMC_PRINTF_FMT ": clock internal\n", LMC_PRINTF_ARGS);
+    }
+}
+
+/*
+ * return hardware link status.
+ * 0 == link is down, 1 == link is up.
+ */
+static int
+lmc_hssi_get_link_status (lmc_softc_t * const sc)
+{
+    /*
+     * We're using the same code as SSI since
+     * they're practically the same
+     */
+    return lmc_ssi_get_link_status(sc);
+}
+
+static void
+lmc_hssi_set_link_status (lmc_softc_t * const sc, int state)
+{
+  if (state == LMC_LINK_UP)
+    sc->lmc_miireg16 |= LMC_MII16_HSSI_TA;
+  else
+    sc->lmc_miireg16 &= ~LMC_MII16_HSSI_TA;
+
+  lmc_mii_writereg (sc, 0, 16, sc->lmc_miireg16);
+}
+
+/*
+ * 0 == 16bit, 1 == 32bit
+ */
+static void
+lmc_hssi_set_crc_length (lmc_softc_t * const sc, int state)
+{
+  if (state == LMC_CTL_CRC_LENGTH_32)
+    {
+      /* 32 bit */
+      sc->lmc_miireg16 |= LMC_MII16_HSSI_CRC;
+      sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_32;
+    }
+  else
+    {
+      /* 16 bit */
+      sc->lmc_miireg16 &= ~LMC_MII16_HSSI_CRC;
+      sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_16;
+    }
+
+  lmc_mii_writereg (sc, 0, 16, sc->lmc_miireg16);
+}
+
+static void
+lmc_hssi_watchdog (lmc_softc_t * const sc)
+{
+  /* HSSI is blank */
+}
+
+/*
+ *  DS3 methods
+ */
+
+/*
+ * Set cable length
+ */
+static void
+lmc_ds3_set_100ft (lmc_softc_t * const sc, int ie)
+{
+  if (ie == LMC_CTL_CABLE_LENGTH_GT_100FT)
+    {
+      sc->lmc_miireg16 &= ~LMC_MII16_DS3_ZERO;
+      sc->ictl.cable_length = LMC_CTL_CABLE_LENGTH_GT_100FT;
+    }
+  else if (ie == LMC_CTL_CABLE_LENGTH_LT_100FT)
+    {
+      sc->lmc_miireg16 |= LMC_MII16_DS3_ZERO;
+      sc->ictl.cable_length = LMC_CTL_CABLE_LENGTH_LT_100FT;
+    }
+  lmc_mii_writereg (sc, 0, 16, sc->lmc_miireg16);
+}
+
+static void
+lmc_ds3_default (lmc_softc_t * const sc)
+{
+  sc->lmc_miireg16 = LMC_MII16_LED_ALL;
+
+  sc->lmc_media->set_link_status (sc, LMC_LINK_DOWN);
+  sc->lmc_media->set_cable_length (sc, LMC_CTL_CABLE_LENGTH_LT_100FT);
+  sc->lmc_media->set_scrambler (sc, LMC_CTL_OFF);
+  sc->lmc_media->set_crc_length (sc, LMC_CTL_CRC_LENGTH_16);
+}
+
+/*
+ * Given a user provided state, set ourselves up to match it.  This will
+ * always reset the card if needed.
+ */
+static void
+lmc_ds3_set_status (lmc_softc_t * const sc, lmc_ctl_t * ctl)
+{
+  if (ctl == NULL)
+    {
+      sc->lmc_media->set_cable_length (sc, sc->ictl.cable_length);
+      sc->lmc_media->set_scrambler (sc, sc->ictl.scrambler_onoff);
+      lmc_set_protocol (sc, NULL);
+
+      return;
+    }
+
+  /*
+   * check for change in cable length setting
+   */
+  if (ctl->cable_length && !sc->ictl.cable_length)
+    lmc_ds3_set_100ft (sc, LMC_CTL_CABLE_LENGTH_GT_100FT);
+  else if (!ctl->cable_length && sc->ictl.cable_length)
+    lmc_ds3_set_100ft (sc, LMC_CTL_CABLE_LENGTH_LT_100FT);
+
+  /*
+   * Check for change in scrambler setting (requires reset)
+   */
+  if (ctl->scrambler_onoff && !sc->ictl.scrambler_onoff)
+    lmc_ds3_set_scram (sc, LMC_CTL_ON);
+  else if (!ctl->scrambler_onoff && sc->ictl.scrambler_onoff)
+    lmc_ds3_set_scram (sc, LMC_CTL_OFF);
+
+  lmc_set_protocol (sc, ctl);
+}
+
+static void
+lmc_ds3_init (lmc_softc_t * const sc)
+{
+  int i;
+
+  sc->ictl.cardtype = LMC_CTL_CARDTYPE_LMC5245;
+
+  /* writes zeros everywhere */
+  for (i = 0; i < 21; i++)
+    {
+      lmc_mii_writereg (sc, 0, 17, i);
+      lmc_mii_writereg (sc, 0, 18, 0);
+    }
+
+  /* set some essential bits */
+  lmc_mii_writereg (sc, 0, 17, 1);
+  lmc_mii_writereg (sc, 0, 18, 0x25);	/* ser, xtx */
+
+  lmc_mii_writereg (sc, 0, 17, 5);
+  lmc_mii_writereg (sc, 0, 18, 0x80);	/* emode */
+
+  lmc_mii_writereg (sc, 0, 17, 14);
+  lmc_mii_writereg (sc, 0, 18, 0x30);	/* rcgen, tcgen */
+
+  /* clear counters and latched bits */
+  for (i = 0; i < 21; i++)
+    {
+      lmc_mii_writereg (sc, 0, 17, i);
+      lmc_mii_readreg (sc, 0, 18);
+    }
+}
+
+/*
+ * 1 == DS3 payload scrambled, 0 == not scrambled
+ */
+static void
+lmc_ds3_set_scram (lmc_softc_t * const sc, int ie)
+{
+  if (ie == LMC_CTL_ON)
+    {
+      sc->lmc_miireg16 |= LMC_MII16_DS3_SCRAM;
+      sc->ictl.scrambler_onoff = LMC_CTL_ON;
+    }
+  else
+    {
+      sc->lmc_miireg16 &= ~LMC_MII16_DS3_SCRAM;
+      sc->ictl.scrambler_onoff = LMC_CTL_OFF;
+    }
+  lmc_mii_writereg (sc, 0, 16, sc->lmc_miireg16);
+}
+
+/*
+ * return hardware link status.
+ * 0 == link is down, 1 == link is up.
+ */
+static int
+lmc_ds3_get_link_status (lmc_softc_t * const sc)
+{
+    u_int16_t link_status, link_status_11;
+    int ret = 1;
+
+    lmc_mii_writereg (sc, 0, 17, 7);
+    link_status = lmc_mii_readreg (sc, 0, 18);
+
+    /* LMC5245 (DS3) & LMC1200 (DS1) LED definitions
+     * led0 yellow = far-end adapter is in Red alarm condition
+     * led1 blue   = received an Alarm Indication signal
+     *               (upstream failure)
+     * led2 Green  = power to adapter, Gate Array loaded & driver
+     *               attached
+     * led3 red    = Loss of Signal (LOS) or out of frame (OOF)
+     *               conditions detected on T3 receive signal
+     */
+
+    lmc_led_on(sc, LMC_DS3_LED2);
+
+    if ((link_status & LMC_FRAMER_REG0_DLOS) ||
+        (link_status & LMC_FRAMER_REG0_OOFS)){
+        ret = 0;
+        if(sc->last_led_err[3] != 1){
+            u16 r1;
+            lmc_mii_writereg (sc, 0, 17, 01); /* Turn on Xbit error as our cisco does */
+            r1 = lmc_mii_readreg (sc, 0, 18);
+            r1 &= 0xfe;
+            lmc_mii_writereg(sc, 0, 18, r1);
+            printk(KERN_WARNING "%s: Red Alarm - Loss of Signal or Loss of Framing\n", sc->name);
+        }
+        lmc_led_on(sc, LMC_DS3_LED3);	/* turn on red LED */
+        sc->last_led_err[3] = 1;
+    }
+    else {
+        lmc_led_off(sc, LMC_DS3_LED3);	/* turn on red LED */
+        if(sc->last_led_err[3] == 1){
+            u16 r1;
+            lmc_mii_writereg (sc, 0, 17, 01); /* Turn off Xbit error */
+            r1 = lmc_mii_readreg (sc, 0, 18);
+            r1 |= 0x01;
+            lmc_mii_writereg(sc, 0, 18, r1);
+        }
+        sc->last_led_err[3] = 0;
+    }
+
+    lmc_mii_writereg(sc, 0, 17, 0x10);
+    link_status_11 = lmc_mii_readreg(sc, 0, 18);
+    if((link_status & LMC_FRAMER_REG0_AIS) ||
+       (link_status_11 & LMC_FRAMER_REG10_XBIT)) {
+        ret = 0;
+        if(sc->last_led_err[0] != 1){
+            printk(KERN_WARNING "%s: AIS Alarm or XBit Error\n", sc->name);
+            printk(KERN_WARNING "%s: Remote end has loss of signal or framing\n", sc->name);
+        }
+        lmc_led_on(sc, LMC_DS3_LED0);
+        sc->last_led_err[0] = 1;
+    }
+    else {
+        lmc_led_off(sc, LMC_DS3_LED0);
+        sc->last_led_err[0] = 0;
+    }
+
+    lmc_mii_writereg (sc, 0, 17, 9);
+    link_status = lmc_mii_readreg (sc, 0, 18);
+    
+    if(link_status & LMC_FRAMER_REG9_RBLUE){
+        ret = 0;
+        if(sc->last_led_err[1] != 1){
+            printk(KERN_WARNING "%s: Blue Alarm - Receiving all 1's\n", sc->name);
+        }
+        lmc_led_on(sc, LMC_DS3_LED1);
+        sc->last_led_err[1] = 1;
+    }
+    else {
+        lmc_led_off(sc, LMC_DS3_LED1);
+        sc->last_led_err[1] = 0;
+    }
+
+    return ret;
+}
+
+/*
+ * 0 == 16bit, 1 == 32bit
+ */
+static void
+lmc_ds3_set_crc_length (lmc_softc_t * const sc, int state)
+{
+  if (state == LMC_CTL_CRC_LENGTH_32)
+    {
+      /* 32 bit */
+      sc->lmc_miireg16 |= LMC_MII16_DS3_CRC;
+      sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_32;
+    }
+  else
+    {
+      /* 16 bit */
+      sc->lmc_miireg16 &= ~LMC_MII16_DS3_CRC;
+      sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_16;
+    }
+
+  lmc_mii_writereg (sc, 0, 16, sc->lmc_miireg16);
+}
+
+static void
+lmc_ds3_watchdog (lmc_softc_t * const sc)
+{
+  sc->lmc_miireg16 = lmc_mii_readreg (sc, 0, 16);
+  if (sc->lmc_miireg16 & 0x0018) {
+      printk ("%s: AIS Recieved\n", sc->name);
+      lmc_led_on (sc, LMC_DS3_LED1 | LMC_DS3_LED2);
+  }
+  else{
+  }
+}
+
+
+/*
+ *  SSI methods
+ */
+
+static void
+lmc_ssi_init (lmc_softc_t * const sc)
+{
+  u_int16_t mii17;
+  int cable;
+
+  sc->ictl.cardtype = LMC_CTL_CARDTYPE_LMC1000;
+
+  mii17 = lmc_mii_readreg (sc, 0, 17);
+
+  cable = (mii17 & LMC_MII17_SSI_CABLE_MASK) >> LMC_MII17_SSI_CABLE_SHIFT;
+  sc->ictl.cable_type = cable;
+
+  lmc_gpio_mkoutput (sc, LMC_GEP_SSI_TXCLOCK);
+}
+
+static void
+lmc_ssi_default (lmc_softc_t * const sc)
+{
+  sc->lmc_miireg16 = LMC_MII16_LED_ALL;
+
+  /*
+   * make TXCLOCK always be an output
+   */
+  lmc_gpio_mkoutput (sc, LMC_GEP_SSI_TXCLOCK);
+
+  sc->lmc_media->set_link_status (sc, LMC_LINK_DOWN);
+  sc->lmc_media->set_clock_source (sc, LMC_CTL_CLOCK_SOURCE_EXT);
+  sc->lmc_media->set_speed (sc, NULL);
+  sc->lmc_media->set_crc_length (sc, LMC_CTL_CRC_LENGTH_16);
+}
+
+/*
+ * Given a user provided state, set ourselves up to match it.  This will
+ * always reset the card if needed.
+ */
+static void
+lmc_ssi_set_status (lmc_softc_t * const sc, lmc_ctl_t * ctl)
+{
+  if (ctl == NULL)
+    {
+      sc->lmc_media->set_clock_source (sc, sc->ictl.clock_source);
+      sc->lmc_media->set_speed (sc, &sc->ictl);
+      lmc_set_protocol (sc, NULL);
+
+      return;
+    }
+
+  /*
+   * check for change in clock source
+   */
+  if (ctl->clock_source == LMC_CTL_CLOCK_SOURCE_INT
+      && sc->ictl.clock_source == LMC_CTL_CLOCK_SOURCE_EXT)
+    {
+      sc->lmc_media->set_clock_source (sc, LMC_CTL_CLOCK_SOURCE_INT);
+      sc->lmc_timing = LMC_CTL_CLOCK_SOURCE_INT;
+    }
+  else if (ctl->clock_source == LMC_CTL_CLOCK_SOURCE_EXT
+	   && sc->ictl.clock_source == LMC_CTL_CLOCK_SOURCE_INT)
+    {
+      sc->lmc_media->set_clock_source (sc, LMC_CTL_CLOCK_SOURCE_EXT);
+      sc->lmc_timing = LMC_CTL_CLOCK_SOURCE_EXT;
+    }
+
+  if (ctl->clock_rate != sc->ictl.clock_rate)
+    sc->lmc_media->set_speed (sc, ctl);
+
+  lmc_set_protocol (sc, ctl);
+}
+
+/*
+ * 1 == internal, 0 == external
+ */
+static void
+lmc_ssi_set_clock (lmc_softc_t * const sc, int ie)
+{
+  if (ie == LMC_CTL_CLOCK_SOURCE_EXT)
+    {
+      sc->lmc_gpio &= ~(LMC_GEP_SSI_TXCLOCK);
+      LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
+      sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_EXT;
+      printk (LMC_PRINTF_FMT ": clock external\n", LMC_PRINTF_ARGS);
+    }
+  else
+    {
+      sc->lmc_gpio |= LMC_GEP_SSI_TXCLOCK;
+      LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
+      sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_INT;
+      printk (LMC_PRINTF_FMT ": clock internal\n", LMC_PRINTF_ARGS);
+    }
+}
+
+static void
+lmc_ssi_set_speed (lmc_softc_t * const sc, lmc_ctl_t * ctl)
+{
+  lmc_ctl_t *ictl = &sc->ictl;
+  lmc_av9110_t *av;
+
+  /* original settings for clock rate of:
+   *  100 Khz (8,25,0,0,2) were incorrect
+   *  they should have been 80,125,1,3,3
+   *  There are 17 param combinations to produce this freq.
+   *  For 1.5 Mhz use 120,100,1,1,2 (226 param. combinations)
+   */
+  if (ctl == NULL)
+    {
+      av = &ictl->cardspec.ssi;
+      ictl->clock_rate = 1500000;
+      av->f = ictl->clock_rate;
+      av->n = 120;
+      av->m = 100;
+      av->v = 1;
+      av->x = 1;
+      av->r = 2;
+
+      write_av9110 (sc, av->n, av->m, av->v, av->x, av->r);
+      return;
+    }
+
+  av = &ctl->cardspec.ssi;
+
+  if (av->f == 0)
+    return;
+
+  ictl->clock_rate = av->f;	/* really, this is the rate we are */
+  ictl->cardspec.ssi = *av;
+
+  write_av9110 (sc, av->n, av->m, av->v, av->x, av->r);
+}
+
+/*
+ * return hardware link status.
+ * 0 == link is down, 1 == link is up.
+ */
+static int
+lmc_ssi_get_link_status (lmc_softc_t * const sc)
+{
+  u_int16_t link_status;
+  u_int32_t ticks;
+  int ret = 1;
+  int hw_hdsk = 1;
+  
+  /*
+   * missing CTS?  Hmm.  If we require CTS on, we may never get the
+   * link to come up, so omit it in this test.
+   *
+   * Also, it seems that with a loopback cable, DCD isn't asserted,
+   * so just check for things like this:
+   *      DSR _must_ be asserted.
+   *      One of DCD or CTS must be asserted.
+   */
+
+  /* LMC 1000 (SSI) LED definitions
+   * led0 Green = power to adapter, Gate Array loaded &
+   *              driver attached
+   * led1 Green = DSR and DTR and RTS and CTS are set
+   * led2 Green = Cable detected
+   * led3 red   = No timing is available from the
+   *              cable or the on-board frequency
+   *              generator.
+   */
+
+  link_status = lmc_mii_readreg (sc, 0, 16);
+
+  /* Is the transmit clock still available */
+  ticks = LMC_CSR_READ (sc, csr_gp_timer);
+  ticks = 0x0000ffff - (ticks & 0x0000ffff);
+
+  lmc_led_on (sc, LMC_MII16_LED0);
+
+  /* ====== transmit clock determination ===== */
+  if (sc->lmc_timing == LMC_CTL_CLOCK_SOURCE_INT) {
+      lmc_led_off(sc, LMC_MII16_LED3);
+  }
+  else if (ticks == 0 ) {				/* no clock found ? */
+      ret = 0;
+      if(sc->last_led_err[3] != 1){
+          sc->stats.tx_lossOfClockCnt++;
+          printk(KERN_WARNING "%s: Lost Clock Card Down\n", sc->name);
+      }
+      sc->last_led_err[3] = 1;
+      lmc_led_on (sc, LMC_MII16_LED3);	/* turn ON red LED */
+  }
+  else {
+      if(sc->last_led_err[3] == 1)
+          printk(KERN_WARNING "%s: Clock Returned\n", sc->name);
+      sc->last_led_err[3] = 0;
+      lmc_led_off (sc, LMC_MII16_LED3);		/* turn OFF red LED */
+  }
+
+  if ((link_status & LMC_MII16_SSI_DSR) == 0) { /* Also HSSI CA */
+      ret = 0;
+      hw_hdsk = 0;
+  }
+
+#ifdef CONFIG_LMC_IGNORE_HARDWARE_HANDSHAKE
+  if ((link_status & (LMC_MII16_SSI_CTS | LMC_MII16_SSI_DCD)) == 0){
+      ret = 0;
+      hw_hdsk = 0;
+  }
+#endif
+
+  if(hw_hdsk == 0){
+      if(sc->last_led_err[1] != 1)
+          printk(KERN_WARNING "%s: DSR no asserted\n", sc->name);
+      sc->last_led_err[1] = 1;
+      lmc_led_off(sc, LMC_MII16_LED1);
+  }
+  else {
+      if(sc->last_led_err[1] != 0)
+          printk(KERN_WARNING "%s: DSR now asserted\n", sc->name);
+      sc->last_led_err[1] = 0;
+      lmc_led_on(sc, LMC_MII16_LED1);
+  }
+
+  if(ret == 1) {
+      lmc_led_on(sc, LMC_MII16_LED2); /* Over all good status? */
+  }
+  
+  return ret;
+}
+
+static void
+lmc_ssi_set_link_status (lmc_softc_t * const sc, int state)
+{
+  if (state == LMC_LINK_UP)
+    {
+      sc->lmc_miireg16 |= (LMC_MII16_SSI_DTR | LMC_MII16_SSI_RTS);
+      printk (LMC_PRINTF_FMT ": asserting DTR and RTS\n", LMC_PRINTF_ARGS);
+    }
+  else
+    {
+      sc->lmc_miireg16 &= ~(LMC_MII16_SSI_DTR | LMC_MII16_SSI_RTS);
+      printk (LMC_PRINTF_FMT ": deasserting DTR and RTS\n", LMC_PRINTF_ARGS);
+    }
+
+  lmc_mii_writereg (sc, 0, 16, sc->lmc_miireg16);
+
+}
+
+/*
+ * 0 == 16bit, 1 == 32bit
+ */
+static void
+lmc_ssi_set_crc_length (lmc_softc_t * const sc, int state)
+{
+  if (state == LMC_CTL_CRC_LENGTH_32)
+    {
+      /* 32 bit */
+      sc->lmc_miireg16 |= LMC_MII16_SSI_CRC;
+      sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_32;
+      sc->lmc_crcSize = LMC_CTL_CRC_BYTESIZE_4;
+
+    }
+  else
+    {
+      /* 16 bit */
+      sc->lmc_miireg16 &= ~LMC_MII16_SSI_CRC;
+      sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_16;
+      sc->lmc_crcSize = LMC_CTL_CRC_BYTESIZE_2;
+    }
+
+  lmc_mii_writereg (sc, 0, 16, sc->lmc_miireg16);
+}
+
+/*
+ * These are bits to program the ssi frequency generator
+ */
+static inline void
+write_av9110_bit (lmc_softc_t * sc, int c)
+{
+  /*
+   * set the data bit as we need it.
+   */
+  sc->lmc_gpio &= ~(LMC_GEP_SERIALCLK);
+  if (c & 0x01)
+    sc->lmc_gpio |= LMC_GEP_SERIAL;
+  else
+    sc->lmc_gpio &= ~(LMC_GEP_SERIAL);
+  LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
+
+  /*
+   * set the clock to high
+   */
+  sc->lmc_gpio |= LMC_GEP_SERIALCLK;
+  LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
+
+  /*
+   * set the clock to low again.
+   */
+  sc->lmc_gpio &= ~(LMC_GEP_SERIALCLK);
+  LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
+}
+
+static void
+write_av9110 (lmc_softc_t * sc, u_int32_t n, u_int32_t m, u_int32_t v,
+	      u_int32_t x, u_int32_t r)
+{
+  int i;
+
+#if 0
+  printk (LMC_PRINTF_FMT ": speed %u, %d %d %d %d %d\n",
+	  LMC_PRINTF_ARGS, sc->ictl.clock_rate, n, m, v, x, r);
+#endif
+
+  sc->lmc_gpio |= LMC_GEP_SSI_GENERATOR;
+  sc->lmc_gpio &= ~(LMC_GEP_SERIAL | LMC_GEP_SERIALCLK);
+  LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
+
+  /*
+   * Set the TXCLOCK, GENERATOR, SERIAL, and SERIALCLK
+   * as outputs.
+   */
+  lmc_gpio_mkoutput (sc, (LMC_GEP_SERIAL | LMC_GEP_SERIALCLK
+			  | LMC_GEP_SSI_GENERATOR));
+
+  sc->lmc_gpio &= ~(LMC_GEP_SSI_GENERATOR);
+  LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
+
+  /*
+   * a shifting we will go...
+   */
+  for (i = 0; i < 7; i++)
+    write_av9110_bit (sc, n >> i);
+  for (i = 0; i < 7; i++)
+    write_av9110_bit (sc, m >> i);
+  for (i = 0; i < 1; i++)
+    write_av9110_bit (sc, v >> i);
+  for (i = 0; i < 2; i++)
+    write_av9110_bit (sc, x >> i);
+  for (i = 0; i < 2; i++)
+    write_av9110_bit (sc, r >> i);
+  for (i = 0; i < 5; i++)
+    write_av9110_bit (sc, 0x17 >> i);
+
+  /*
+   * stop driving serial-related signals
+   */
+  lmc_gpio_mkinput (sc,
+		    (LMC_GEP_SERIAL | LMC_GEP_SERIALCLK
+		     | LMC_GEP_SSI_GENERATOR));
+}
+
+static void
+lmc_ssi_watchdog (lmc_softc_t * const sc)
+{
+  u_int16_t mii17;
+  struct ssicsr2
+  {
+    unsigned short dtr:1, dsr:1, rts:1, cable:3, crc:1, led0:1, led1:1,
+      led2:1, led3:1, fifo:1, ll:1, rl:1, tm:1, loop:1;
+  };
+  struct ssicsr2 *ssicsr;
+  mii17 = lmc_mii_readreg (sc, 0, 17);
+  ssicsr = (struct ssicsr2 *) &mii17;
+  if (ssicsr->cable == 7)
+    {
+      lmc_led_off (sc, LMC_MII16_LED2);
+    }
+  else
+    {
+      lmc_led_on (sc, LMC_MII16_LED2);
+    }
+
+}
+
+/*
+ *  T1 methods
+ */
+
+/*
+ * The framer regs are multiplexed through MII regs 17 & 18
+ *  write the register address to MII reg 17 and the *  data to MII reg 18. */
+static void
+lmc_t1_write (lmc_softc_t * const sc, int a, int d)
+{
+  lmc_mii_writereg (sc, 0, 17, a);
+  lmc_mii_writereg (sc, 0, 18, d);
+}
+
+/* Save a warning
+static int
+lmc_t1_read (lmc_softc_t * const sc, int a)
+{
+  lmc_mii_writereg (sc, 0, 17, a);
+  return lmc_mii_readreg (sc, 0, 18);
+}
+*/
+
+
+static void
+lmc_t1_init (lmc_softc_t * const sc)
+{
+  u_int16_t mii16;
+  int i;
+
+  sc->ictl.cardtype = LMC_CTL_CARDTYPE_LMC1200;
+  mii16 = lmc_mii_readreg (sc, 0, 16);
+
+  /* reset 8370 */
+  mii16 &= ~LMC_MII16_T1_RST;
+  lmc_mii_writereg (sc, 0, 16, mii16 | LMC_MII16_T1_RST);
+  lmc_mii_writereg (sc, 0, 16, mii16);
+
+  /* set T1 or E1 line.  Uses sc->lmcmii16 reg in function so update it */
+  sc->lmc_miireg16 = mii16;
+  lmc_t1_set_circuit_type(sc, LMC_CTL_CIRCUIT_TYPE_T1);
+  mii16 = sc->lmc_miireg16;
+
+  lmc_t1_write (sc, 0x01, 0x1B);	/* CR0     - primary control             */
+  lmc_t1_write (sc, 0x02, 0x42);	/* JAT_CR  - jitter atten config         */
+  lmc_t1_write (sc, 0x14, 0x00);	/* LOOP    - loopback config             */
+  lmc_t1_write (sc, 0x15, 0x00);	/* DL3_TS  - external data link timeslot */
+  lmc_t1_write (sc, 0x18, 0xFF);	/* PIO     - programmable I/O            */
+  lmc_t1_write (sc, 0x19, 0x30);	/* POE     - programmable OE             */
+  lmc_t1_write (sc, 0x1A, 0x0F);	/* CMUX    - clock input mux             */
+  lmc_t1_write (sc, 0x20, 0x41);	/* LIU_CR  - RX LIU config               */
+  lmc_t1_write (sc, 0x22, 0x76);	/* RLIU_CR - RX LIU config               */
+  lmc_t1_write (sc, 0x40, 0x03);	/* RCR0    - RX config                   */
+  lmc_t1_write (sc, 0x45, 0x00);	/* RALM    - RX alarm config             */
+  lmc_t1_write (sc, 0x46, 0x05);	/* LATCH   - RX alarm/err/cntr latch     */
+  lmc_t1_write (sc, 0x68, 0x40);	/* TLIU_CR - TX LIU config               */
+  lmc_t1_write (sc, 0x70, 0x0D);	/* TCR0    - TX framer config            */
+  lmc_t1_write (sc, 0x71, 0x05);	/* TCR1    - TX config                   */
+  lmc_t1_write (sc, 0x72, 0x0B);	/* TFRM    - TX frame format             */
+  lmc_t1_write (sc, 0x73, 0x00);	/* TERROR  - TX error insert             */
+  lmc_t1_write (sc, 0x74, 0x00);	/* TMAN    - TX manual Sa/FEBE config    */
+  lmc_t1_write (sc, 0x75, 0x00);	/* TALM    - TX alarm signal config      */
+  lmc_t1_write (sc, 0x76, 0x00);	/* TPATT   - TX test pattern config      */
+  lmc_t1_write (sc, 0x77, 0x00);	/* TLB     - TX inband loopback config   */
+  lmc_t1_write (sc, 0x90, 0x05);	/* CLAD_CR - clock rate adapter config   */
+  lmc_t1_write (sc, 0x91, 0x05);	/* CSEL    - clad freq sel               */
+  lmc_t1_write (sc, 0xA6, 0x00);	/* DL1_CTL - DL1 control                 */
+  lmc_t1_write (sc, 0xB1, 0x00);	/* DL2_CTL - DL2 control                 */
+  lmc_t1_write (sc, 0xD0, 0x47);	/* SBI_CR  - sys bus iface config        */
+  lmc_t1_write (sc, 0xD1, 0x70);	/* RSB_CR  - RX sys bus config           */
+  lmc_t1_write (sc, 0xD4, 0x30);	/* TSB_CR  - TX sys bus config           */
+  for (i = 0; i < 32; i++)
+    {
+      lmc_t1_write (sc, 0x0E0 + i, 0x00);	/* SBCn - sys bus per-channel ctl    */
+      lmc_t1_write (sc, 0x100 + i, 0x00);	/* TPCn - TX per-channel ctl         */
+      lmc_t1_write (sc, 0x180 + i, 0x00);	/* RPCn - RX per-channel ctl         */
+    }
+  for (i = 1; i < 25; i++)
+    {
+      lmc_t1_write (sc, 0x0E0 + i, 0x0D);	/* SBCn - sys bus per-channel ctl    */
+    }
+
+  mii16 |= LMC_MII16_T1_XOE;
+  lmc_mii_writereg (sc, 0, 16, mii16);
+  sc->lmc_miireg16 = mii16;
+}
+
+static void
+lmc_t1_default (lmc_softc_t * const sc)
+{
+  sc->lmc_miireg16 = LMC_MII16_LED_ALL;
+  sc->lmc_media->set_link_status (sc, LMC_LINK_DOWN);
+  sc->lmc_media->set_circuit_type (sc, LMC_CTL_CIRCUIT_TYPE_T1);
+  sc->lmc_media->set_crc_length (sc, LMC_CTL_CRC_LENGTH_16);
+  /* Right now we can only clock from out internal source */
+  sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_INT;
+}
+/* * Given a user provided state, set ourselves up to match it.  This will * always reset the card if needed.
+ */
+static void
+lmc_t1_set_status (lmc_softc_t * const sc, lmc_ctl_t * ctl)
+{
+  if (ctl == NULL)
+    {
+      sc->lmc_media->set_circuit_type (sc, sc->ictl.circuit_type);
+      lmc_set_protocol (sc, NULL);
+
+      return;
+    }
+  /*
+   * check for change in circuit type         */
+  if (ctl->circuit_type == LMC_CTL_CIRCUIT_TYPE_T1
+      && sc->ictl.circuit_type ==
+      LMC_CTL_CIRCUIT_TYPE_E1) sc->lmc_media->set_circuit_type (sc,
+								LMC_CTL_CIRCUIT_TYPE_E1);
+  else if (ctl->circuit_type == LMC_CTL_CIRCUIT_TYPE_E1
+	   && sc->ictl.circuit_type == LMC_CTL_CIRCUIT_TYPE_T1)
+    sc->lmc_media->set_circuit_type (sc, LMC_CTL_CIRCUIT_TYPE_T1);
+  lmc_set_protocol (sc, ctl);
+}
+/*
+ * return hardware link status.
+ * 0 == link is down, 1 == link is up.
+ */ static int
+lmc_t1_get_link_status (lmc_softc_t * const sc)
+{
+    u_int16_t link_status;
+    int ret = 1;
+
+  /* LMC5245 (DS3) & LMC1200 (DS1) LED definitions
+   * led0 yellow = far-end adapter is in Red alarm condition
+   * led1 blue   = received an Alarm Indication signal
+   *               (upstream failure)
+   * led2 Green  = power to adapter, Gate Array loaded & driver
+   *               attached
+   * led3 red    = Loss of Signal (LOS) or out of frame (OOF)
+   *               conditions detected on T3 receive signal
+   */
+    
+    lmc_led_on(sc, LMC_DS3_LED2);
+
+    lmc_mii_writereg (sc, 0, 17, T1FRAMER_ALARM1_STATUS);
+    link_status = lmc_mii_readreg (sc, 0, 18);
+
+
+    if (link_status & T1F_RAIS) {			/* turn on blue LED */
+        ret = 0;
+        if(sc->last_led_err[1] != 1){
+            printk(KERN_WARNING "%s: Receive AIS/Blue Alarm. Far end in RED alarm\n", sc->name);
+        }
+        lmc_led_on(sc, LMC_DS3_LED1);
+        sc->last_led_err[1] = 1;
+    }
+    else {
+        if(sc->last_led_err[1] != 0){
+            printk(KERN_WARNING "%s: End AIS/Blue Alarm\n", sc->name);
+        }
+        lmc_led_off (sc, LMC_DS3_LED1);
+        sc->last_led_err[1] = 0;
+    }
+
+    /*
+     * Yellow Alarm is nasty evil stuff, looks at data patterns
+     * inside the channel and confuses it with HDLC framing
+     * ignore all yellow alarms.
+     *
+     * Do listen to MultiFrame Yellow alarm which while implemented
+     * different ways isn't in the channel and hence somewhat
+     * more reliable
+     */
+
+    if (link_status & T1F_RMYEL) {
+        ret = 0;
+        if(sc->last_led_err[0] != 1){
+            printk(KERN_WARNING "%s: Receive Yellow AIS Alarm\n", sc->name);
+        }
+        lmc_led_on(sc, LMC_DS3_LED0);
+        sc->last_led_err[0] = 1;
+    }
+    else {
+        if(sc->last_led_err[0] != 0){
+            printk(KERN_WARNING "%s: End of Yellow AIS Alarm\n", sc->name);
+        }
+        lmc_led_off(sc, LMC_DS3_LED0);
+        sc->last_led_err[0] = 0;
+    }
+
+    /*
+     * Loss of signal and los of frame
+     * Use the green bit to identify which one lit the led
+     */
+    if(link_status & T1F_RLOF){
+        ret = 0;
+        if(sc->last_led_err[3] != 1){
+            printk(KERN_WARNING "%s: Local Red Alarm: Loss of Framing\n", sc->name);
+        }
+        lmc_led_on(sc, LMC_DS3_LED3);
+        sc->last_led_err[3] = 1;
+
+    }
+    else {
+        if(sc->last_led_err[3] != 0){
+            printk(KERN_WARNING "%s: End Red Alarm (LOF)\n", sc->name);
+        }
+        if( ! (link_status & T1F_RLOS))
+            lmc_led_off(sc, LMC_DS3_LED3);
+        sc->last_led_err[3] = 0;
+    }
+    
+    if(link_status & T1F_RLOS){
+        ret = 0;
+        if(sc->last_led_err[2] != 1){
+            printk(KERN_WARNING "%s: Local Red Alarm: Loss of Signal\n", sc->name);
+        }
+        lmc_led_on(sc, LMC_DS3_LED3);
+        sc->last_led_err[2] = 1;
+
+    }
+    else {
+        if(sc->last_led_err[2] != 0){
+            printk(KERN_WARNING "%s: End Red Alarm (LOS)\n", sc->name);
+        }
+        if( ! (link_status & T1F_RLOF))
+            lmc_led_off(sc, LMC_DS3_LED3);
+        sc->last_led_err[2] = 0;
+    }
+
+    sc->lmc_xinfo.t1_alarm1_status = link_status;
+
+    lmc_mii_writereg (sc, 0, 17, T1FRAMER_ALARM2_STATUS);
+    sc->lmc_xinfo.t1_alarm2_status = lmc_mii_readreg (sc, 0, 18);
+
+    return ret;
+}
+
+/*
+ * 1 == T1 Circuit Type , 0 == E1 Circuit Type
+ */
+static void
+lmc_t1_set_circuit_type (lmc_softc_t * const sc, int ie)
+{
+  if (ie == LMC_CTL_CIRCUIT_TYPE_T1) {
+      sc->lmc_miireg16 |= LMC_MII16_T1_Z;
+      sc->ictl.circuit_type = LMC_CTL_CIRCUIT_TYPE_T1;
+      printk(KERN_INFO "%s: In T1 Mode\n", sc->name);
+  }
+  else {
+      sc->lmc_miireg16 &= ~LMC_MII16_T1_Z;
+      sc->ictl.circuit_type = LMC_CTL_CIRCUIT_TYPE_E1;
+      printk(KERN_INFO "%s: In E1 Mode\n", sc->name);
+  }
+
+  lmc_mii_writereg (sc, 0, 16, sc->lmc_miireg16);
+  
+}
+
+/*
+ * 0 == 16bit, 1 == 32bit */
+static void
+lmc_t1_set_crc_length (lmc_softc_t * const sc, int state)
+{
+  if (state == LMC_CTL_CRC_LENGTH_32)
+    {
+      /* 32 bit */
+      sc->lmc_miireg16 |= LMC_MII16_T1_CRC;
+      sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_32;
+      sc->lmc_crcSize = LMC_CTL_CRC_BYTESIZE_4;
+
+    }
+  else
+    {
+      /* 16 bit */ sc->lmc_miireg16 &= ~LMC_MII16_T1_CRC;
+      sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_16;
+      sc->lmc_crcSize = LMC_CTL_CRC_BYTESIZE_2;
+
+    }
+
+  lmc_mii_writereg (sc, 0, 16, sc->lmc_miireg16);
+}
+
+/*
+ * 1 == internal, 0 == external
+ */
+static void
+lmc_t1_set_clock (lmc_softc_t * const sc, int ie)
+{
+  if (ie == LMC_CTL_CLOCK_SOURCE_EXT)
+    {
+      sc->lmc_gpio &= ~(LMC_GEP_SSI_TXCLOCK);
+      LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
+      sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_EXT;
+      printk (LMC_PRINTF_FMT ": clock external\n", LMC_PRINTF_ARGS);
+    }
+  else
+    {
+      sc->lmc_gpio |= LMC_GEP_SSI_TXCLOCK;
+      LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
+      sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_INT;
+      printk (LMC_PRINTF_FMT ": clock internal\n", LMC_PRINTF_ARGS);
+    }
+}
+
+static void
+lmc_t1_watchdog (lmc_softc_t * const sc)
+{
+}
+
+static void
+lmc_set_protocol (lmc_softc_t * const sc, lmc_ctl_t * ctl)
+{
+  if (ctl == 0)
+    {
+      sc->ictl.keepalive_onoff = LMC_CTL_ON;
+
+      return;
+    }
+}
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/lmc/lmc_media.h linux.15p9/drivers/net/lmc/lmc_media.h
--- linux.vanilla/drivers/net/lmc/lmc_media.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/net/lmc/lmc_media.h	Wed Jan 26 22:58:51 2000
@@ -0,0 +1,64 @@
+#ifndef _LMC_MEDIA_H_
+#define _LMC_MEDIA_H_
+
+lmc_media_t lmc_ds3_media = {
+  lmc_ds3_init,			/* special media init stuff */
+  lmc_ds3_default,		/* reset to default state */
+  lmc_ds3_set_status,		/* reset status to state provided */
+  lmc_dummy_set_1,		/* set clock source */
+  lmc_dummy_set2_1,		/* set line speed */
+  lmc_ds3_set_100ft,		/* set cable length */
+  lmc_ds3_set_scram,		/* set scrambler */
+  lmc_ds3_get_link_status,	/* get link status */
+  lmc_dummy_set_1,		/* set link status */
+  lmc_ds3_set_crc_length,	/* set CRC length */
+  lmc_dummy_set_1,		/* set T1 or E1 circuit type */
+  lmc_ds3_watchdog
+};
+
+lmc_media_t lmc_hssi_media = {
+  lmc_hssi_init,		/* special media init stuff */
+  lmc_hssi_default,		/* reset to default state */
+  lmc_hssi_set_status,		/* reset status to state provided */
+  lmc_hssi_set_clock,		/* set clock source */
+  lmc_dummy_set2_1,		/* set line speed */
+  lmc_dummy_set_1,		/* set cable length */
+  lmc_dummy_set_1,		/* set scrambler */
+  lmc_hssi_get_link_status,	/* get link status */
+  lmc_hssi_set_link_status,	/* set link status */
+  lmc_hssi_set_crc_length,	/* set CRC length */
+  lmc_dummy_set_1,		/* set T1 or E1 circuit type */
+  lmc_hssi_watchdog
+};
+
+lmc_media_t lmc_ssi_media = { lmc_ssi_init,	/* special media init stuff */
+  lmc_ssi_default,		/* reset to default state */
+  lmc_ssi_set_status,		/* reset status to state provided */
+  lmc_ssi_set_clock,		/* set clock source */
+  lmc_ssi_set_speed,		/* set line speed */
+  lmc_dummy_set_1,		/* set cable length */
+  lmc_dummy_set_1,		/* set scrambler */
+  lmc_ssi_get_link_status,	/* get link status */
+  lmc_ssi_set_link_status,	/* set link status */
+  lmc_ssi_set_crc_length,	/* set CRC length */
+  lmc_dummy_set_1,		/* set T1 or E1 circuit type */
+  lmc_ssi_watchdog
+};
+
+lmc_media_t lmc_t1_media = {
+  lmc_t1_init,			/* special media init stuff */
+  lmc_t1_default,		/* reset to default state */
+  lmc_t1_set_status,		/* reset status to state provided */
+  lmc_t1_set_clock,		/* set clock source */
+  lmc_dummy_set2_1,		/* set line speed */
+  lmc_dummy_set_1,		/* set cable length */
+  lmc_dummy_set_1,		/* set scrambler */
+  lmc_t1_get_link_status,	/* get link status */
+  lmc_dummy_set_1,		/* set link status */
+  lmc_t1_set_crc_length,	/* set CRC length */
+  lmc_t1_set_circuit_type,	/* set T1 or E1 circuit type */
+  lmc_t1_watchdog
+};
+
+
+#endif
\ No newline at end of file
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/lmc/lmc_var.h linux.15p9/drivers/net/lmc/lmc_var.h
--- linux.vanilla/drivers/net/lmc/lmc_var.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/net/lmc/lmc_var.h	Wed Jan 26 22:58:51 2000
@@ -0,0 +1,571 @@
+#ifndef _LMC_VAR_H_
+#define _LMC_VAR_H_
+
+/* $Id: lmc_var.h,v 1.14 2000/01/21 13:29:50 asj Exp $ */
+
+ /*
+  * Copyright (c) 1997-2000 LAN Media Corporation (LMC)
+  * All rights reserved.  www.lanmedia.com
+  *
+  * This code is written by:
+  * Andrew Stanley-Jones (asj@cban.com)
+  * Rob Braun (bbraun@vix.com),
+  * Michael Graff (explorer@vix.com) and
+  * Matt Thomas (matt@3am-software.com).
+  *
+  * This software may be used and distributed according to the terms
+  * of the GNU Public License version 2, incorporated herein by reference.
+  */
+
+#include <linux/timer.h>
+
+#ifndef __KERNEL__
+typedef signed char s8;
+typedef unsigned char u8;
+
+typedef signed short s16;
+typedef unsigned short u16;
+
+typedef signed int s32;
+typedef unsigned int u32;
+
+typedef signed long long s64;
+typedef unsigned long long u64;
+
+#define BITS_PER_LONG 32 
+
+#endif
+
+/*
+ * basic definitions used in lmc include files
+ */
+
+typedef struct lmc___softc lmc_softc_t;
+typedef struct lmc___media lmc_media_t;
+typedef struct lmc___ctl lmc_ctl_t;
+
+#define lmc_csrptr_t	u32
+#define u_int16_t	u16
+#define u_int8_t	u8
+#define tulip_uint32_t	u32
+#if LINUX_VERSION_CODE < 0x20155
+#define u_int32_t	u32
+#endif
+
+#define LMC_REG_RANGE 0x80
+
+#define LMC_PRINTF_FMT  "%s"
+#define LMC_PRINTF_ARGS	(sc->lmc_device->name)
+
+#define TX_TIMEOUT (2*HZ)
+
+#define LMC_TXDESCS            32
+#define LMC_RXDESCS            32
+
+#define LMC_LINK_UP            1
+#define LMC_LINK_DOWN          0
+
+/* These macros for generic read and write to and from the dec chip */
+#define LMC_CSR_READ(sc, csr) \
+	inl((sc)->lmc_csrs.csr)
+#define LMC_CSR_WRITE(sc, reg, val) \
+	outl(val, (sc)->lmc_csrs.reg)
+
+#ifdef _LINUX_DELAY_H
+	#define SLOW_DOWN_IO udelay(2);
+	#undef __SLOW_DOWN_IO
+	#define __SLOW_DOWN_IO udelay(2);
+#endif
+
+#define DELAY(n) SLOW_DOWN_IO
+
+#define lmc_delay() inl(sc->lmc_csrs.csr_9)
+
+/* This macro sync's up with the mii so that reads and writes can take place */
+#define LMC_MII_SYNC(sc) do {int n=32; while( n >= 0 ) { \
+		LMC_CSR_WRITE((sc), csr_9, 0x20000); \
+		lmc_delay(); \
+		LMC_CSR_WRITE((sc), csr_9, 0x30000); \
+		lmc_delay(); \
+		n--; }} while(0);
+
+struct lmc_regfile_t {
+    lmc_csrptr_t csr_busmode;                  /* CSR0 */
+    lmc_csrptr_t csr_txpoll;                   /* CSR1 */
+    lmc_csrptr_t csr_rxpoll;                   /* CSR2 */
+    lmc_csrptr_t csr_rxlist;                   /* CSR3 */
+    lmc_csrptr_t csr_txlist;                   /* CSR4 */
+    lmc_csrptr_t csr_status;                   /* CSR5 */
+    lmc_csrptr_t csr_command;                  /* CSR6 */
+    lmc_csrptr_t csr_intr;                     /* CSR7 */
+    lmc_csrptr_t csr_missed_frames;            /* CSR8 */
+    lmc_csrptr_t csr_9;                        /* CSR9 */
+    lmc_csrptr_t csr_10;                       /* CSR10 */
+    lmc_csrptr_t csr_11;                       /* CSR11 */
+    lmc_csrptr_t csr_12;                       /* CSR12 */
+    lmc_csrptr_t csr_13;                       /* CSR13 */
+    lmc_csrptr_t csr_14;                       /* CSR14 */
+    lmc_csrptr_t csr_15;                       /* CSR15 */
+};
+
+#define csr_enetrom             csr_9   /* 21040 */
+#define csr_reserved            csr_10  /* 21040 */
+#define csr_full_duplex         csr_11  /* 21040 */
+#define csr_bootrom             csr_10  /* 21041/21140A/?? */
+#define csr_gp                  csr_12  /* 21140* */
+#define csr_watchdog            csr_15  /* 21140* */
+#define csr_gp_timer            csr_11  /* 21041/21140* */
+#define csr_srom_mii            csr_9   /* 21041/21140* */
+#define csr_sia_status          csr_12  /* 2104x */
+#define csr_sia_connectivity    csr_13  /* 2104x */
+#define csr_sia_tx_rx           csr_14  /* 2104x */
+#define csr_sia_general         csr_15  /* 2104x */
+
+/* tulip length/control transmit descriptor definitions
+ *  used to define bits in the second tulip_desc_t field (length)
+ *  for the transmit descriptor -baz */
+
+#define LMC_TDES_FIRST_BUFFER_SIZE       ((u_int32_t)(0x000007FF))
+#define LMC_TDES_SECOND_BUFFER_SIZE      ((u_int32_t)(0x003FF800))
+#define LMC_TDES_HASH_FILTERING          ((u_int32_t)(0x00400000))
+#define LMC_TDES_DISABLE_PADDING         ((u_int32_t)(0x00800000))
+#define LMC_TDES_SECOND_ADDR_CHAINED     ((u_int32_t)(0x01000000))
+#define LMC_TDES_END_OF_RING             ((u_int32_t)(0x02000000))
+#define LMC_TDES_ADD_CRC_DISABLE         ((u_int32_t)(0x04000000))
+#define LMC_TDES_SETUP_PACKET            ((u_int32_t)(0x08000000))
+#define LMC_TDES_INVERSE_FILTERING       ((u_int32_t)(0x10000000))
+#define LMC_TDES_FIRST_SEGMENT           ((u_int32_t)(0x20000000))
+#define LMC_TDES_LAST_SEGMENT            ((u_int32_t)(0x40000000))
+#define LMC_TDES_INTERRUPT_ON_COMPLETION ((u_int32_t)(0x80000000))
+
+#define TDES_SECOND_BUFFER_SIZE_BIT_NUMBER  11
+#define TDES_COLLISION_COUNT_BIT_NUMBER     3
+
+/* Constants for the RCV descriptor RDES */
+
+#define LMC_RDES_OVERFLOW             ((u_int32_t)(0x00000001))
+#define LMC_RDES_CRC_ERROR            ((u_int32_t)(0x00000002))
+#define LMC_RDES_DRIBBLING_BIT            ((u_int32_t)(0x00000004))
+#define LMC_RDES_REPORT_ON_MII_ERR    ((u_int32_t)(0x00000008))
+#define LMC_RDES_RCV_WATCHDOG_TIMEOUT ((u_int32_t)(0x00000010))
+#define LMC_RDES_FRAME_TYPE           ((u_int32_t)(0x00000020))
+#define LMC_RDES_COLLISION_SEEN       ((u_int32_t)(0x00000040))
+#define LMC_RDES_FRAME_TOO_LONG       ((u_int32_t)(0x00000080))
+#define LMC_RDES_LAST_DESCRIPTOR      ((u_int32_t)(0x00000100))
+#define LMC_RDES_FIRST_DESCRIPTOR     ((u_int32_t)(0x00000200))
+#define LMC_RDES_MULTICAST_FRAME      ((u_int32_t)(0x00000400))
+#define LMC_RDES_RUNT_FRAME           ((u_int32_t)(0x00000800))
+#define LMC_RDES_DATA_TYPE            ((u_int32_t)(0x00003000))
+#define LMC_RDES_LENGTH_ERROR         ((u_int32_t)(0x00004000))
+#define LMC_RDES_ERROR_SUMMARY        ((u_int32_t)(0x00008000))
+#define LMC_RDES_FRAME_LENGTH         ((u_int32_t)(0x3FFF0000))
+#define LMC_RDES_OWN_BIT              ((u_int32_t)(0x80000000))
+
+#define RDES_FRAME_LENGTH_BIT_NUMBER       16
+
+#define LMC_RDES_ERROR_MASK ( (u_int32_t)( \
+	  LMC_RDES_OVERFLOW \
+	| LMC_RDES_DRIBBLING_BIT \
+	| LMC_RDES_REPORT_ON_MII_ERR \
+        | LMC_RDES_COLLISION_SEEN ) )
+
+
+/*
+ * Ioctl info
+ */
+
+typedef struct {
+	u_int32_t	n;
+	u_int32_t	m;
+	u_int32_t	v;
+	u_int32_t	x;
+	u_int32_t	r;
+	u_int32_t	f;
+	u_int32_t	exact;
+} lmc_av9110_t;
+
+/*
+ * Common structure passed to the ioctl code.
+ */
+struct lmc___ctl {
+	u_int32_t	cardtype;
+	u_int32_t	clock_source;		/* HSSI, T1 */
+	u_int32_t	clock_rate;		/* T1 */
+	u_int32_t	crc_length;
+	u_int32_t	cable_length;		/* DS3 */
+	u_int32_t	scrambler_onoff;	/* DS3 */
+	u_int32_t	cable_type;		/* T1 */
+	u_int32_t	keepalive_onoff;	/* protocol */
+	u_int32_t	ticks;			/* ticks/sec */
+	union {
+		lmc_av9110_t	ssi;
+	} cardspec;
+	u_int32_t       circuit_type;   /* T1 or E1 */
+};
+
+
+/*
+ * Carefull, look at the data sheet, there's more to this
+ * structure than meets the eye.  It should probably be:
+ *
+ * struct tulip_desc_t {
+ *         u8  own:1;
+ *         u32 status:31;
+ *         u32 control:10;
+ *         u32 buffer1;
+ *         u32 buffer2;
+ * };
+ * You could also expand status control to provide more bit information
+ */
+
+struct tulip_desc_t {
+	s32 status;
+	s32 length;
+	u32 buffer1;
+	u32 buffer2;
+};
+
+/*
+ * media independent methods to check on media status, link, light LEDs,
+ * etc.
+ */
+struct lmc___media {
+	void	(* init)(lmc_softc_t * const);
+	void	(* defaults)(lmc_softc_t * const);
+	void	(* set_status)(lmc_softc_t * const, lmc_ctl_t *);
+	void	(* set_clock_source)(lmc_softc_t * const, int);
+	void	(* set_speed)(lmc_softc_t * const, lmc_ctl_t *);
+	void	(* set_cable_length)(lmc_softc_t * const, int);
+	void	(* set_scrambler)(lmc_softc_t * const, int);
+	int	(* get_link_status)(lmc_softc_t * const);
+	void	(* set_link_status)(lmc_softc_t * const, int);
+	void	(* set_crc_length)(lmc_softc_t * const, int);
+        void    (* set_circuit_type)(lmc_softc_t * const, int);
+        void	(* watchdog)(lmc_softc_t * const);
+};
+
+
+#define STATCHECK     0xBEEFCAFE
+
+/*  Included in this structure are first
+ *   - standard enet_statistics
+ *   - some other counters used for debug and driver performance
+ *  evaluation -baz
+ */
+struct lmc_statistics
+{
+        int     rx_packets;             /* total packets received       */
+        int     tx_packets;             /* total packets transmitted    */
+	int     rx_bytes;
+        int     tx_bytes;
+        
+        int     rx_errors;              /* bad packets received         */
+        int     tx_errors;              /* packet transmit problems     */
+        int     rx_dropped;             /* no space in linux buffers    */
+        int     tx_dropped;             /* no space available in linux  */
+        int     multicast;              /* multicast packets received   */
+        int     collisions;
+
+        /* detailed rx_errors: */
+        int     rx_length_errors;
+        int     rx_over_errors;         /* receiver ring buff overflow  */
+        int     rx_crc_errors;          /* recved pkt with crc error    */
+        int     rx_frame_errors;        /* recv'd frame alignment error */
+        int     rx_fifo_errors;         /* recv'r fifo overrun          */
+        int     rx_missed_errors;       /* receiver missed packet       */
+
+        /* detailed tx_errors */
+        int     tx_aborted_errors;
+        int     tx_carrier_errors;
+        int     tx_fifo_errors;
+        int     tx_heartbeat_errors;
+        int     tx_window_errors;
+
+        /* for cslip etc */
+        unsigned long rx_compressed;
+        unsigned long tx_compressed;
+
+        /* -------------------------------------
+         * Custom stats & counters follow -baz */
+        u_int32_t       version_size;
+        u_int32_t       lmc_cardtype;
+
+        u_int32_t       tx_ProcTimeout;
+        u_int32_t       tx_IntTimeout;
+        u_int32_t       tx_NoCompleteCnt;
+        u_int32_t       tx_MaxXmtsB4Int;
+        u_int32_t       tx_TimeoutCnt;
+        u_int32_t       tx_OutOfSyncPtr;
+        u_int32_t       resetCount;
+        u_int32_t       lmc_txfull;
+        u_int32_t       tbusy;
+        u_int32_t       dirtyTx;
+        u_int32_t       lmc_next_tx;
+        u_int32_t       otherTypeCnt;
+        u_int32_t       lastType;
+        u_int32_t       lastTypeOK;
+        u_int32_t       txLoopCnt;
+        u_int32_t       usedXmtDescripCnt;
+        u_int32_t       txIndexCnt;
+        u_int32_t       rxIntLoopCnt;
+
+        u_int32_t       rx_SmallPktCnt;
+        u_int32_t       rx_BadPktSurgeCnt;
+        u_int32_t       rx_BuffAllocErr;
+        u_int32_t       tx_lossOfClockCnt;
+
+        /* T1 error counters */
+        u_int32_t       framingBitErrorCount;
+        u_int32_t       lineCodeViolationCount;
+
+        u_int32_t       lossOfFrameCount;
+        u_int32_t       changeOfFrameAlignmentCount;
+        u_int32_t       severelyErroredFrameCount;
+
+        u_int32_t       check;
+};
+
+
+typedef struct lmc_xinfo {
+        u_int32_t       Magic0;                         /* BEEFCAFE */
+
+        u_int32_t       PciCardType;
+        u_int32_t       PciSlotNumber;          /* PCI slot number       */
+
+        u_int16_t       DriverMajorVersion;
+        u_int16_t       DriverMinorVersion;
+        u_int16_t       DriverSubVersion;
+
+        u_int16_t       XilinxRevisionNumber;
+        u_int16_t       MaxFrameSize;
+
+        u_int16_t       t1_alarm1_status;
+        u_int16_t       t1_alarm2_status;
+
+        int                     link_status;
+        u_int32_t       mii_reg16;
+
+        u_int32_t       Magic1;                         /* DEADBEEF */
+} LMC_XINFO;
+
+
+/*
+ * forward decl
+ */
+struct lmc___softc {
+	char                   *name;
+	u8			board_idx;
+	struct lmc_statistics   stats;
+	struct device          *lmc_device;
+
+	int                     hang, rxdesc, bad_packet, some_counter;
+	u_int32_t               txgo;
+	struct lmc_regfile_t	lmc_csrs;
+	volatile u_int32_t	lmc_txtick;
+	volatile u_int32_t	lmc_rxtick;
+	u_int32_t		lmc_flags;
+	u_int32_t		lmc_intrmask;	/* our copy of csr_intr */
+	u_int32_t		lmc_cmdmode;	/* our copy of csr_cmdmode */
+	u_int32_t		lmc_busmode;	/* our copy of csr_busmode */
+	u_int32_t		lmc_gpio_io;	/* state of in/out settings */
+	u_int32_t		lmc_gpio;	/* state of outputs */
+	struct sk_buff*		lmc_txq[LMC_TXDESCS];
+	struct sk_buff*		lmc_rxq[LMC_RXDESCS];
+	struct tulip_desc_t	lmc_rxring[LMC_RXDESCS];
+	struct tulip_desc_t	lmc_txring[LMC_TXDESCS];
+	unsigned int		lmc_next_rx, lmc_next_tx;
+	unsigned int		lmc_taint_tx, lmc_taint_rx;
+	int			lmc_tx_start, lmc_txfull;
+	int			lmc_txbusy;
+	u_int16_t		lmc_miireg16;
+	int			lmc_ok;
+	int			last_link_status;
+	int			lmc_cardtype;
+	u_int32_t               last_frameerr;
+	lmc_media_t	       *lmc_media;
+	struct timer_list	timer;
+	lmc_ctl_t		ictl;
+	u_int32_t		TxDescriptControlInit;  
+	struct device		*next_module;   /* Link to the next module  */
+	int                     tx_TimeoutInd; /* additional driver state */
+	int                     tx_TimeoutDisplay;
+	unsigned int		lastlmc_taint_tx;
+	int                     lasttx_packets;
+	u_int32_t		tx_clockState;
+	u_int32_t		lmc_crcSize;
+	LMC_XINFO		lmc_xinfo; 
+	char                    lmc_yel, lmc_blue, lmc_red; /* for T1 and DS3 */
+        char                    lmc_timing; /* for HSSI and SSI */
+        int                     got_irq;
+
+        char                    last_led_err[4];
+
+#if LINUX_VERSION_CODE >= 0x20200
+	spinlock_t              lmc_lock;
+#endif
+};
+
+#define LMC_PCI_TIME 1
+#define LMC_EXT_TIME 0
+
+#define PKT_BUF_SZ              1542  /* was 1536 */
+
+/* CSR5 settings */
+#define TIMER_INT     0x00000800
+#define TP_LINK_FAIL  0x00001000
+#define TP_LINK_PASS  0x00000010
+#define NORMAL_INT    0x00010000
+#define ABNORMAL_INT  0x00008000
+#define RX_JABBER_INT 0x00000200
+#define RX_DIED       0x00000100
+#define RX_NOBUFF     0x00000080
+#define RX_INT        0x00000040
+#define TX_FIFO_UNDER 0x00000020
+#define TX_JABBER     0x00000008
+#define TX_NOBUFF     0x00000004
+#define TX_DIED       0x00000002
+#define TX_INT        0x00000001
+
+/* CSR6 settings */
+#define OPERATION_MODE  0x00000200 /* Full Duplex      */
+#define PROMISC_MODE    0x00000040 /* Promiscuous Mode */
+#define RECIEVE_ALL     0x40000000 /* Recieve All      */
+#define PASS_BAD_FRAMES 0x00000008 /* Pass Bad Frames  */
+
+/* Dec control registers  CSR6 as well */
+#define LMC_DEC_ST 0x00002000
+#define LMC_DEC_SR 0x00000002
+
+/* CSR15 settings */
+#define RECV_WATCHDOG_DISABLE 0x00000010
+#define JABBER_DISABLE        0x00000001
+
+/* More settings */
+/*
+ * aSR6 -- Command (Operation Mode) Register
+ */
+#define TULIP_CMD_RECEIVEALL    0x40000000L /* (RW)  Receivel all frames? */
+#define TULIP_CMD_MUSTBEONE     0x02000000L /* (RW)  Must Be One (21140) */
+#define TULIP_CMD_TXTHRSHLDCTL  0x00400000L /* (RW)  Transmit Threshold Mode (21140) */
+#define TULIP_CMD_STOREFWD      0x00200000L /* (RW)  Store and Foward (21140) */
+#define TULIP_CMD_NOHEARTBEAT   0x00080000L /* (RW)  No Heartbeat (21140) */
+#define TULIP_CMD_PORTSELECT    0x00040000L /* (RW)  Post Select (100Mb) (21140) */
+#define TULIP_CMD_FULLDUPLEX    0x00000200L /* (RW)  Full Duplex Mode */
+#define TULIP_CMD_OPERMODE      0x00000C00L /* (RW)  Operating Mode */
+#define TULIP_CMD_PROMISCUOUS   0x00000041L /* (RW)  Promiscuous Mode */
+#define TULIP_CMD_PASSBADPKT    0x00000008L /* (RW)  Pass Bad Frames */
+#define TULIP_CMD_THRESHOLDCTL  0x0000C000L /* (RW)  Threshold Control */
+
+#define TULIP_GP_PINSET         0x00000100L
+#define TULIP_BUSMODE_SWRESET   0x00000001L
+#define TULIP_WATCHDOG_TXDISABLE 0x00000001L
+#define TULIP_WATCHDOG_RXDISABLE 0x00000010L
+
+#define TULIP_STS_NORMALINTR    0x00010000L /* (RW)  Normal Interrupt */
+#define TULIP_STS_ABNRMLINTR    0x00008000L /* (RW)  Abnormal Interrupt */
+#define TULIP_STS_ERI           0x00004000L /* (RW)  Early Receive Interupt */
+#define TULIP_STS_SYSERROR      0x00002000L /* (RW)  System Error */
+#define TULIP_STS_GTE           0x00000800L /* (RW)  General Pupose Timer Exp */
+#define TULIP_STS_ETI           0x00000400L /* (RW)  Early Transmit Interupt */
+#define TULIP_STS_RXWT          0x00000200L /* (RW)  Receiver Watchdog Timeout */
+#define TULIP_STS_RXSTOPPED     0x00000100L /* (RW)  Receiver Process Stopped */
+#define TULIP_STS_RXNOBUF       0x00000080L /* (RW)  Receive Buf Unavail */
+#define TULIP_STS_RXINTR        0x00000040L /* (RW)  Receive Interrupt */
+#define TULIP_STS_TXUNDERFLOW   0x00000020L /* (RW)  Transmit Underflow */
+#define TULIP_STS_TXJABER       0x00000008L /* (RW)  Jabber timeout */
+#define TULIP_STS_TXNOBUF       0x00000004L
+#define TULIP_STS_TXSTOPPED     0x00000002L /* (RW)  Transmit Process Stopped */
+#define TULIP_STS_TXINTR        0x00000001L /* (RW)  Transmit Interrupt */
+
+#define TULIP_STS_RXS_STOPPED   0x00000000L /*        000 - Stopped */
+
+#define TULIP_STS_RXSTOPPED     0x00000100L             /* (RW)  Receive Process Stopped */
+#define TULIP_STS_RXNOBUF       0x00000080L
+
+#define TULIP_CMD_TXRUN         0x00002000L /* (RW)  Start/Stop Transmitter */
+#define TULIP_CMD_RXRUN         0x00000002L /* (RW)  Start/Stop Receive Filtering */
+#define TULIP_DSTS_TxDEFERRED   0x00000001      /* Initially Deferred */
+#define TULIP_DSTS_OWNER        0x80000000      /* Owner (1 = 21040) */
+#define TULIP_DSTS_RxMIIERR     0x00000008
+#define LMC_DSTS_ERRSUM         (TULIP_DSTS_RxMIIERR)
+
+#define TULIP_DEFAULT_INTR_MASK  (TULIP_STS_NORMALINTR \
+  | TULIP_STS_RXINTR       \
+  | TULIP_STS_TXINTR     \
+  | TULIP_STS_ABNRMLINTR \
+  | TULIP_STS_SYSERROR   \
+  | TULIP_STS_TXSTOPPED  \
+  | TULIP_STS_TXUNDERFLOW\
+  | TULIP_STS_RXSTOPPED )
+
+#define DESC_OWNED_BY_SYSTEM   ((u_int32_t)(0x00000000))
+#define DESC_OWNED_BY_DC21X4   ((u_int32_t)(0x80000000))
+
+#ifndef TULIP_CMD_RECEIVEALL
+#define TULIP_CMD_RECEIVEALL 0x40000000L
+#endif
+
+
+/* PCI register values */
+#define CORRECT_VENDOR_ID    0x1011
+#define CORRECT_DEV_ID       9
+
+#define PCI_VENDOR_LMC		0x1376
+#define PCI_PRODUCT_LMC_HSSI	0x0003
+#define PCI_PRODUCT_LMC_DS3	0x0004
+#define PCI_PRODUCT_LMC_SSI	0x0005
+#define PCI_PRODUCT_LMC_T1      0x0006
+
+/* Adapcter module number */
+#define LMC_ADAP_HSSI           2
+#define LMC_ADAP_DS3            3
+#define LMC_ADAP_SSI            4
+#define LMC_ADAP_T1             5
+
+#define HDLC_HDR_LEN  4
+#define HDLC_ADDR_LEN 1
+#define HDLC_SLARP    0x8035
+#define LMC_MTU 1500
+#define SLARP_LINECHECK 2
+
+#define LMC_CRC_LEN_16 2  /* 16-bit CRC */
+#define LMC_CRC_LEN_32 4
+
+#if LINUX_VERSION_CODE < 0x20100
+#define test_and_set_bit(val, addr) set_bit(val, addr)
+#endif
+
+#ifdef LMC_HDLC
+/* definition of an hdlc header. */
+struct hdlc_hdr
+{
+	u8  address;
+	u8  control;
+	u16 type;
+};
+
+/* definition of a slarp header. */
+struct slarp
+{
+	long code;
+	union sl
+	{
+		struct
+		{
+			ulong address;
+			ulong mask;
+			ushort unused;
+		} add;
+		struct
+		{
+			ulong mysequence;
+			ulong yoursequence;
+			ushort reliability;
+			ulong time;
+		} chk;
+	} t;
+};
+#endif /* LMC_HDLC */
+
+
+#endif /* _LMC_VAR_H_ */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/lmc/lmc_ver.h linux.15p9/drivers/net/lmc/lmc_ver.h
--- linux.vanilla/drivers/net/lmc/lmc_ver.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/net/lmc/lmc_ver.h	Wed Jan 26 22:58:51 2000
@@ -0,0 +1,107 @@
+#ifndef _IF_LMC_LINUXVER_
+#define _IF_LMC_LINUXVER_
+
+ /*
+  * Copyright (c) 1997-2000 LAN Media Corporation (LMC)
+  * All rights reserved.  www.lanmedia.com
+  *
+  * This code is written by:
+  * Andrew Stanley-Jones (asj@cban.com)
+  * Rob Braun (bbraun@vix.com),
+  * Michael Graff (explorer@vix.com) and
+  * Matt Thomas (matt@3am-software.com).
+  *
+  * This software may be used and distributed according to the terms
+  * of the GNU Public License version 2, incorporated herein by reference.
+  */
+
+ /*
+  * This file defines and controls all linux version
+  * differences.
+  *
+  * This is being done to keep 1 central location where all linux
+  * version differences can be kept and maintained.  as this code was
+  * found version issues where pepered throughout the source code and
+  * made the souce code not only hard to read but version problems hard
+  * to track down.  If I'm overiding a function/etc with something in
+  * this file it will be prefixed by "LMC_" which will mean look
+  * here for the the version dependant change that's been done.
+  *
+  */
+
+#if LINUX_VERSION_CODE < 0x20100
+typedef unsigned int u_int32_t;
+
+#define  LMC_SETUP_20_DEV {\
+                             int indx; \
+                             for (indx = 0; indx < DEV_NUMBUFFS; indx++) \
+                                skb_queue_head_init (&dev->buffs[indx]); \
+                          } \
+                          dev->family = AF_INET; \
+                          dev->pa_addr = 0; \
+                          dev->pa_brdaddr = 0; \
+                          dev->pa_mask = 0xFCFFFFFF; \
+                          dev->pa_alen = 4;		/* IP addr.  sizeof(u32) */
+
+#else
+
+#define LMC_SETUP_20_DEV
+
+#endif
+
+
+#if LINUX_VERSION_CODE < 0x20155 /* basically 2.2 plus */
+
+#define LMC_DEV_KFREE_SKB(skb) dev_kfree_skb((skb), FREE_WRITE)
+#define LMC_PCI_PRESENT() pcibios_present()
+
+#else /* Mostly 2.0 kernels */
+
+#define LMC_DEV_KFREE_SKB(skb) dev_kfree_skb(skb)
+#define LMC_PCI_PRESENT() pci_present()
+
+#endif
+
+#if LINUX_VERSION_CODE < 0x20200
+#else
+
+#endif
+
+#if LINUX_VERSION_CODE < 0x20100
+#define LMC_SKB_FREE(skb, val) (skb->free = val)
+#else
+#define LMC_SKB_FREE(skb, val)
+#endif
+
+#define LMC_SPIN_FLAGS                unsigned long flags;
+
+#if (LINUX_VERSION_CODE >= 0x20200)
+
+#define LMC_SPIN_LOCK_INIT(x)         spin_lock_init(&(x)->lmc_lock);
+#define LMC_SPIN_UNLOCK(x)            ((x)->lmc_lock = SPIN_LOCK_UNLOCKED)
+#define LMC_SPIN_LOCK_IRQSAVE(x)      spin_lock_irqsave (&(x)->lmc_lock, flags);
+#define LMC_SPIN_UNLOCK_IRQRESTORE(x) spin_unlock_irqrestore (&(x)->lmc_lock, flags);
+#else
+#define LMC_SPIN_FLAGS
+#define LMC_SPIN_LOCK_INIT(x)
+#define LMC_SPIN_UNLOCK(x)
+#define LMC_SPIN_LOCK_IRQSAVE(x)
+#define LMC_SPIN_UNLOCK_IRQRESTORE(x)
+#endif
+
+
+#if LINUX_VERSION_CODE >= 0x20100
+#define LMC_COPY_FROM_USER(x, y, z) if(copy_from_user ((x), (y), (z))) return -EFAULT
+#define LMC_COPY_TO_USER(x, y, z) if(copy_to_user ((x), (y), (z))) return -EFAULT
+#else
+#define LMC_COPY_FROM_USER(x, y, z) if(verify_area(VERIFY_READ, (y), (z))) \
+			               return -EFAULT; \
+                                    memcpy_fromfs ((x), (y), (z))
+
+#define LMC_COPY_TO_USER(x, y, z)   if(verify_area(VERIFY_WRITE, (x), (z))) \
+	                               return -EFAULT; \
+                                    memcpy_tofs ((x), (y), (z))
+#endif
+
+
+#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/olympic.c linux.15p9/drivers/net/olympic.c
--- linux.vanilla/drivers/net/olympic.c	Sat Aug 14 02:27:29 1999
+++ linux.15p9/drivers/net/olympic.c	Wed Jan 26 23:02:16 2000
@@ -23,10 +23,11 @@
  *  6/8/99  - Official Release 0.2.0   
  *            Merged into the kernel code 
  *  
- *  To Do:
- *
- *  Sanitize for smp
+ *  1/10/00 - Added Spinlocks for smp.
  *
+ *  To Do:
+ *	IPv6 Multicast 
+ *	
  *  If Problems do Occur
  *  Most problems can be rectified by either closing and opening the interface
  *  (ifconfig down and up) or rmmod and insmod'ing the driver (a bit difficult
@@ -71,6 +72,7 @@
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
+#include <asm/spinlock.h>
 
 #include "olympic.h"
 
@@ -83,7 +85,7 @@
  */
 
 static char *version = 
-"Olympic.c v0.2.0 6/8/99 - Peter De Schrijver & Mike Phillips" ; 
+"Olympic.c v0.2.1 1/10/00 - Peter De Schrijver & Mike Phillips" ; 
 
 static char *open_maj_error[]  = {"No error", "Lobe Media Test", "Physical Insertion",
 				   "Address Verification", "Neighbor Notification (Ring Poll)",
@@ -245,6 +247,8 @@
 		}
 	}
 
+	spin_lock_init(&olympic_priv->olympic_lock) ; 
+
 #if OLYMPIC_DEBUG
 	printk("BCTL: %x\n",readl(olympic_mmio+BCTL));
 	printk("GPR: %x\n",readw(olympic_mmio+GPR));
@@ -751,6 +755,8 @@
 	if (!(sisr & SISR_MI)) /* Interrupt isn't for us */ 
 		return ;
 
+	spin_lock(&olympic_priv->olympic_lock) ; 
+
 	if (dev->interrupt) 
 		printk(KERN_WARNING "%s: Re-entering interrupt \n",dev->name) ; 
 
@@ -829,15 +835,19 @@
 	dev->interrupt = 0 ;  
 
 	writel(SISR_MI,olympic_mmio+SISR_MASK_SUM);
-
+	spin_unlock(&olympic_priv->olympic_lock) ; 
 }	
 
 static int olympic_xmit(struct sk_buff *skb, struct device *dev) 
 {
 	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
-    __u8 *olympic_mmio=olympic_priv->olympic_mmio;
+	__u8 *olympic_mmio=olympic_priv->olympic_mmio;
+	unsigned long flags ; 
+
+	spin_lock_irqsave(&olympic_priv->olympic_lock, flags) ; 
 
 	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
+		spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags) ; 
 		return 1;
 	}
 
@@ -854,10 +864,12 @@
 		writew((((readw(olympic_mmio+TXENQ_1)) & 0x8000) ^ 0x8000) | 1,olympic_mmio+TXENQ_1);
 
 		dev->tbusy=0;		
-
+		spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags) ; 
 		return 0;
-	} else 
+	} else {
+		spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags) ; 
 		return 1;
+	} 
 
 }
 	
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/olympic.h linux.15p9/drivers/net/olympic.h
--- linux.vanilla/drivers/net/olympic.h	Sat Aug 14 02:27:29 1999
+++ linux.15p9/drivers/net/olympic.h	Wed Jan 26 23:02:11 2000
@@ -244,6 +244,8 @@
 	__u8 *olympic_mmio;
 	__u8 *olympic_lap;
 
+	spinlock_t	olympic_lock ; 
+
 	volatile int srb_queued;    /* True if an SRB is still posted */	
 	struct wait_queue *srb_wait;
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/plip.c linux.15p9/drivers/net/plip.c
--- linux.vanilla/drivers/net/plip.c	Tue Jan  4 21:18:51 2000
+++ linux.15p9/drivers/net/plip.c	Thu Jan 13 23:15:09 2000
@@ -507,6 +507,61 @@
 	return OK;
 }
 
+/*
+ *	Determine the packet's protocol ID. The rule here is that we 
+ *	assume 802.3 if the type field is short enough to be a length.
+ *	This is normal practice and works for any 'now in use' protocol.
+ *
+ *	PLIP is ethernet ish but the daddr might not be valid if unicast.
+ *	PLIP fortunately has no bus architecture (its Point-to-point).
+ *
+ *	We can't fix the daddr thing as that quirk (more bug) is embedded
+ *	in far too many old systems not all even running Linux.
+ */
+ 
+static unsigned short plip_type_trans(struct sk_buff *skb, struct device *dev)
+{
+	struct ethhdr *eth;
+	unsigned char *rawp;
+	
+	skb->mac.raw=skb->data;
+	skb_pull(skb,dev->hard_header_len);
+	eth= skb->mac.ethernet;
+	
+	if(*eth->h_dest&1)
+	{
+		if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
+			skb->pkt_type=PACKET_BROADCAST;
+		else
+			skb->pkt_type=PACKET_MULTICAST;
+	}
+	
+	/*
+	 *	This ALLMULTI check should be redundant by 1.4
+	 *	so don't forget to remove it.
+	 */
+	 
+	if (ntohs(eth->h_proto) >= 1536)
+		return eth->h_proto;
+		
+	rawp = skb->data;
+	
+	/*
+	 *	This is a magic hack to spot IPX packets. Older Novell breaks
+	 *	the protocol design and runs IPX over 802.3 without an 802.2 LLC
+	 *	layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
+	 *	won't work for fault tolerant netware but does for the rest.
+	 */
+	if (*(unsigned short *)rawp == 0xFFFF)
+		return htons(ETH_P_802_3);
+		
+	/*
+	 *	Real 802.2 LLC
+	 */
+	return htons(ETH_P_802_2);
+}
+
+
 /* PLIP_RECEIVE_PACKET --- receive a packet */
 static int
 plip_receive_packet(struct device *dev, struct net_local *nl,
@@ -595,7 +650,7 @@
 
 	case PLIP_PK_DONE:
 		/* Inform the upper layer for the arrival of a packet. */
-		rcv->skb->protocol=eth_type_trans(rcv->skb, dev);
+		rcv->skb->protocol=plip_type_trans(rcv->skb, dev);
 		netif_rx(rcv->skb);
 		nl->enet_stats.rx_bytes += rcv->length.h;
 		nl->enet_stats.rx_packets++;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/sdlamain.c linux.15p9/drivers/net/sdlamain.c
--- linux.vanilla/drivers/net/sdlamain.c	Tue Jan  4 21:18:52 2000
+++ linux.15p9/drivers/net/sdlamain.c	Sun Jan 16 19:28:32 2000
@@ -133,7 +133,7 @@
 #ifdef MODULE
 int init_module (void)
 #else
-int wanpipe_init(void)
+int wanpipe_init2(void)
 #endif
 {
 	int cnt, err = 0;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/sk98lin/h/skdrv2nd.h linux.15p9/drivers/net/sk98lin/h/skdrv2nd.h
--- linux.vanilla/drivers/net/sk98lin/h/skdrv2nd.h	Tue Jan  4 21:18:52 2000
+++ linux.15p9/drivers/net/sk98lin/h/skdrv2nd.h	Wed Feb 16 18:29:09 2000
@@ -411,6 +411,7 @@
 	int		RxBufSize;	/* length of receive buffers */
         struct net_device_stats stats;	/* linux 'netstat -i' statistics */
 	int		Index;		/* internal board index number */
+	SK_BOOL		JumboActivated; /* jumbo support ever activated */
 
 	/* adapter RAM sizes for queues of active port */
 	int		RxQueueSize;	/* memory used for receive queue */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/sk98lin/skcsum.c linux.15p9/drivers/net/sk98lin/skcsum.c
--- linux.vanilla/drivers/net/sk98lin/skcsum.c	Tue Jan  4 21:18:52 2000
+++ linux.15p9/drivers/net/sk98lin/skcsum.c	Thu Feb 17 22:03:04 2000
@@ -617,7 +617,6 @@
 	/*
 	 * Calculate the TCP/UDP checksum.
 	 */
-
 	/* Get total length of IP header and data. */
 
 	IpDataLength =
@@ -639,11 +638,10 @@
 			SKCS_OFS_IP_DESTINATION_ADDRESS + 0) +
 		(unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader,
 			SKCS_OFS_IP_DESTINATION_ADDRESS + 2) +
-		(unsigned long) (NextLevelProtocol << 8) +
+		(unsigned long) SKCS_HTON16(NextLevelProtocol) +
 		(unsigned long) SKCS_HTON16(IpDataLength) +
 
 		/* Add the TCP/UDP header checksum. */
-
 		(unsigned long) IpDataChecksum;
 
 	/* Add-in any carries. */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/sk98lin/skge.c linux.15p9/drivers/net/sk98lin/skge.c
--- linux.vanilla/drivers/net/sk98lin/skge.c	Tue Jan  4 21:18:52 2000
+++ linux.15p9/drivers/net/sk98lin/skge.c	Thu Feb 17 22:03:04 2000
@@ -225,7 +225,7 @@
 
 static const char SysKonnectFileId[] = "@(#)" __FILE__ " (C) SysKonnect.";
 static const char SysKonnectBuildNumber[] =
-	"@(#)SK-BUILD: 3.02 (19991111) PL: 01"; 
+	"@(#)SK-BUILD: 3.04 (19991111) PL: 01"; 
 
 #include	<linux/module.h>
 
@@ -234,10 +234,10 @@
 
 /* defines ******************************************************************/
 
-#define BOOT_STRING	"sk98lin: Network Device Driver v3.02\n" \
+#define BOOT_STRING	"sk98lin: Network Device Driver v3.04\n" \
 			"Copyright (C) 1999 SysKonnect"
 
-#define VER_STRING	"3.02"
+#define VER_STRING	"3.04"
 
 
 /* for debuging on x86 only */
@@ -348,6 +348,7 @@
 SK_AC		*pAC;
 struct pci_dev	*pdev = NULL;
 unsigned long	base_address;
+unsigned short	tmp;
 
 	if (probed)
 		return -ENODEV;
@@ -419,6 +420,15 @@
 
 		base_address = pdev->base_address[0];
 
+#ifdef __sparc_v9__
+		/* SPARC machines do not initialize the chache line size */
+                pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 64);
+		/* SPARC machines do not set "Memory write and invalidate" */
+                pci_read_config_word(pdev, PCI_COMMAND, &tmp);
+		tmp |= PCI_COMMAND_INVALIDATE;
+                pci_write_config_word(pdev, PCI_COMMAND, tmp);
+#endif 
+
 #ifdef SK_BIG_ENDIAN
 		/*
 		 * On big endian machines, we use the adapter's aibility of
@@ -437,7 +447,12 @@
 		 */
 
 
+#ifndef __sparc_v9__
 		pAC->IoBase = (char*)ioremap(base_address, 0x4000);
+#else
+		/* workaround for bug in 2.2 kernel for sparcv9 */
+		pAC->IoBase = (char*)base_address;
+#endif
 		if (!pAC->IoBase){
 			printk(KERN_ERR "%s:  Unable to map I/O register, "
 			       "SK 98xx No. %i will be disabled.\n",
@@ -808,6 +823,14 @@
 	ProductStr(pAC);
 	printk("%s: %s\n", dev->name, pAC->DeviceStr);
 
+	/* Print configuration settings */
+	printk("      PrefPort:%c  RlmtMode:%s\n",
+		'A' + pAC->Rlmt.PrefPort,
+		(pAC->RlmtMode==0)  ? "ChkLink" :
+		((pAC->RlmtMode==1) ? "ChkLink" : 
+		((pAC->RlmtMode==3) ? "ChkOth" : 
+		((pAC->RlmtMode==7) ? "ChkSeg" : "Error"))));
+
 	SkGeYellowLED(pAC, pAC->IoBase, 1);
 
 	/*
@@ -1527,10 +1550,13 @@
 
 	Rc = XmitFrame(pAC, &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW], skb);
 
-	if (Rc == 0) {
+	if (Rc <= 0) {
 		/* transmitter out of resources */
 		set_bit(0, (void*) &dev->tbusy);
-		return (0);
+		if (Rc == 0)
+			return (0);
+		else
+			return (-EBUSY);
 	} 
 	dev->trans_start = jiffies;
 	return (0);
@@ -1555,9 +1581,9 @@
  *
  * Returns:
  *	> 0 - on succes: the number of bytes in the message
- *	= 0 - on resource shortage: this frame sent or dropped, now
+ *	= 0 - on resource shortage: this frame was sent, now
  *        the ring is full ( -> set tbusy)
- *	< 0 - on failure: other problems (not used)
+ *	< 0 - on resource shortage: this frame could not be sent
  */
 static int XmitFrame(
 SK_AC 		*pAC,		/* pointer to adapter context */
@@ -1585,7 +1611,7 @@
 				("XmitFrame failed\n"));
 			/* this message can not be sent now */
 			DEV_KFREE_SKB(pMessage);
-			return (0);
+			return (-1);
 		}
 	}
 	/* advance head counter behind descriptor needed for this frame */
@@ -1900,8 +1926,10 @@
 			/* hardware checksum */
 			Type = ntohs(*((short*)&pMsg->data[12]));
 			if (Type == 0x800) {
-				Csum1= pRxd->TcpSums & 0xffff;
-				Csum2=(pRxd->TcpSums >> 16) & 0xffff;
+				/* the hardware calculates the checksums in LITTLE ENDIAN */
+				/* so turn them around for BIG ENDIAN machines */
+				Csum1= le16_to_cpu(pRxd->TcpSums & 0xffff);
+				Csum2= le16_to_cpu((pRxd->TcpSums >> 16) & 0xffff);
 				if ((Csum1 & 0xfffe) && (Csum2 & 0xfffe)) {
 					Result = SkCsGetReceiveInfo(pAC,
 						&pMsg->data[14], 
@@ -2414,6 +2442,7 @@
 	 * enable/disable hardware support for long frames
 	 */
 	if (NewMtu > 1500) {
+		pAC->JumboActivated = SK_TRUE; // is never set back !!!
 		pAC->GIni.GIPortUsage = SK_JUMBO_LINK;
 		for (i=0; i<pAC->GIni.GIMacsFound; i++) {
 			pAC->GIni.GP[i].PRxCmd = 
@@ -2523,7 +2552,13 @@
 	pAC->stats.tx_packets = (SK_U32) pPnmiStat->StatTxOkCts & 0xFFFFFFFF;
 	pAC->stats.rx_bytes = (SK_U32) pPnmiStruct->RxOctetsDeliveredCts;
 	pAC->stats.tx_bytes = (SK_U32) pPnmiStat->StatTxOctetsOkCts;
-	pAC->stats.rx_errors = (SK_U32) pPnmiStruct->InErrorsCts & 0xFFFFFFFF;
+	if (!pAC->JumboActivated) {
+		pAC->stats.rx_errors = (SK_U32) pPnmiStruct->InErrorsCts & 0xFFFFFFFF;
+	}
+	else {
+		pAC->stats.rx_errors = (SK_U32) ((pPnmiStruct->InErrorsCts -
+			pPnmiStat->StatRxTooLongCts) & 0xFFFFFFFF);
+	}
 	pAC->stats.tx_errors = (SK_U32) pPnmiStat->StatTxSingleCollisionCts & 0xFFFFFFFF;
 	pAC->stats.rx_dropped = (SK_U32) pPnmiStruct->RxNoBufCts & 0xFFFFFFFF;
 	pAC->stats.tx_dropped = (SK_U32) pPnmiStruct->TxNoBufCts & 0xFFFFFFFF;
@@ -3467,8 +3502,10 @@
 		pRlmtMbuf = (SK_MBUF*) Param.pParaPtr;
 		pMsg = (struct sk_buff*) pRlmtMbuf->pOs;
 		skb_put(pMsg, pRlmtMbuf->Length);
-		XmitFrame(pAC, &pAC->TxPort[pRlmtMbuf->PortIdx][TX_PRIO_LOW],
-			pMsg);
+		if (XmitFrame(pAC, &pAC->TxPort[pRlmtMbuf->PortIdx][TX_PRIO_LOW],
+			pMsg) < 0) {
+			dev_kfree_skb(pMsg);
+		}
 		break;
 	default:
 		break;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/smc-mca.c linux.15p9/drivers/net/smc-mca.c
--- linux.vanilla/drivers/net/smc-mca.c	Wed Dec 16 21:35:49 1998
+++ linux.15p9/drivers/net/smc-mca.c	Mon Feb  7 12:07:40 2000
@@ -1,4 +1,4 @@
-/* smc-ultra.c: A SMC Ultra ethernet driver for linux. */
+/* smc-mca.c: A SMC Ultra ethernet driver for linux. */
 /*
     Most of this driver, except for ultramca_probe is nearly
     verbatim from smc-ultra.c by Donald Becker. The rest is
@@ -8,7 +8,7 @@
 
     This driver uses the cards in the 8390-compatible, shared memory mode.
     Most of the run-time complexity is handled by the generic code in
-    8390.c.  The code in this file is responsible for
+    8390.c.
 
     This driver enables the shared memory only when doing the actual data
     transfers to avoid a bug in early version of the card that corrupted
@@ -20,9 +20,21 @@
 
     Changelog:
 
-    Paul Gortmaker  : multiple card support for module users.
-    David Weis      : Micro Channel-ized it.
-
+    Paul Gortmaker	 : multiple card support for module users.
+    David Weis		 : Micro Channel-ized it.
+    Tom Sightler	 : Added support for IBM PS/2 Ethernet Adapter/A
+    Christopher Turcksin : Changed MCA-probe so that multiple adapters are
+			   found correctly (Jul 16, 1997)
+    Chris Beauregard	 : Tried to merge the two changes above (Dec 15, 1997)
+    Tom Sightler	 : Fixed minor detection bug caused by above merge
+    Tom Sightler	 : Added support for three more Western Digital
+			   MCA-adapters
+    Tom Sightler	 : Added support for 2.2.x mca_find_unused_adapter
+    Hartmut Schmidt	 : - Modified parameter detection to handle each
+			     card differently depending on a switch-list
+			   - 'card_ver' removed from the adapter list
+			   - Some minor bug fixes
+    David Monro		 : Backport from 2.3 to 2.2, other minor fixes.
 */
 
 
@@ -66,53 +78,183 @@
 #define ULTRA_IO_EXTENT 32
 #define EN0_ERWCNT      0x08  /* Early receive warning count. */
 
+#define _61c8_SMC_Ethercard_PLUS_Elite_A_BNC_AUI_WD8013EP_A            0
+#define _61c9_SMC_Ethercard_PLUS_Elite_A_UTP_AUI_WD8013EP_A            1
+#define _6fc0_WD_Ethercard_PLUS_A_WD8003E_A_OR_WD8003ET_A              2
+#define _6fc1_WD_Starcard_PLUS_A_WD8003ST_A                            3
+#define _6fc2_WD_Ethercard_PLUS_10T_A_WD8003W_A                        4
+#define _efd4_IBM_PS2_Adapter_A_for_Ethernet_UTP_AUI_WD8013WP_A        5
+#define _efd5_IBM_PS2_Adapter_A_for_Ethernet_BNC_AUI_WD8013WP_A        6
+#define _efe5_IBM_PS2_Adapter_A_for_Ethernet                           7
+
+struct smc_mca_adapters_t {
+	unsigned int id;
+	char *name;
+};
+
+const struct smc_mca_adapters_t smc_mca_adapters[] = {
+    { 0x61c8, "SMC Ethercard PLUS Elite/A BNC/AUI (WD8013EP/A)" },
+    { 0x61c9, "SMC Ethercard PLUS Elite/A UTP/AUI (WD8013WP/A)" },
+    { 0x6fc0, "WD Ethercard PLUS/A (WD8003E/A or WD8003ET/A)" },
+    { 0x6fc1, "WD Starcard PLUS/A (WD8003ST/A)" },
+    { 0x6fc2, "WD Ethercard PLUS 10T/A (WD8003W/A)" },
+    { 0xefd4, "IBM PS/2 Adapter/A for Ethernet UTP/AUI (WD8013WP/A)" },
+    { 0xefd5, "IBM PS/2 Adapter/A for Ethernet BNC/AUI (WD8013EP/A)" },
+    { 0xefe5, "IBM PS/2 Adapter/A for Ethernet" },
+    { 0x0000, NULL }
+};
 
-__initfunc(int ultramca_probe(struct device *dev))
+int __init ultramca_probe(struct device *dev)
 {
 	unsigned short ioaddr;
 	unsigned char reg4, num_pages;
-	char slot;
-	unsigned char pos2, pos3, pos4, pos5;
-	int i;
-
-	/* Look for two flavors of SMC Elite/A (3013EP/A) -jeh- */
-	if(( (slot=mca_find_adapter(0x61c8,0)) != MCA_NOTFOUND) ||
-            ((slot=mca_find_adapter(0xefd5,0)) != MCA_NOTFOUND) )
+	char slot = -1;
+	unsigned char pos2 = 0xff, pos3 = 0xff, pos4 = 0xff, pos5 = 0xff;
+	int i, j;
+	int adapter_found = 0;
+	int adapter = 0;
+	int tbase = 0;
+	int tirq = 0;
+	int base_addr = dev ? dev->base_addr : 0;
+	int irq = dev ? dev->irq : 0;
 
-	{
-#ifndef MODULE
-		mca_set_adapter_name( slot, "SMC Elite/A (8013EP/A)" );
-#endif
+	if (!MCA_bus) {
+		return ENODEV;
 	}
-	else if( (slot=mca_find_adapter(0x61c9,0)) != MCA_NOTFOUND)
-	{
-#ifndef MODULE
-		mca_set_adapter_name( slot, "SMC Elite10T/A (8013WP/A)" );
-#endif
+
+	/* This is a hack, snd should go away when the "0xffe0 means
+	 * don't do ISA probe" code goes away. We aren't ISA, and 0xffe0
+	 * is not a possible port for us.
+	 */
+	if (base_addr == 0xffe0) {
+		base_addr = 0;
+	}
+	if (base_addr || irq) {
+		printk(KERN_INFO "Probing for SMC MCA adapter");
+		if (base_addr) {
+			printk(" at I/O address 0x%04x%c",
+			       base_addr, irq ? ' ' : '\n');
+		}
+		if (irq) {
+			printk("using irq %d\n", irq);
+		}
 	}
-	else
-		return -ENODEV;
 
-	pos2 = mca_read_stored_pos(slot, 2);     /* IO range */
-	pos3 = mca_read_stored_pos(slot, 3);     /* shared mem */
-	pos4 = mca_read_stored_pos(slot, 4);     /* bios base */
-	pos5 = mca_read_stored_pos(slot, 5);     /* irq and media */
+        /* proper multicard detection by ZP Gu (zpg@castle.net) */
 
-	dev->base_addr = ioaddr = addr_table[pos2 >> 4].base_addr;
-	dev->irq = irq_table[(pos5 & ~IRQ_MASK) >> 2].irq;
+	for (j = 0; (smc_mca_adapters[j].name != NULL) && !adapter_found; j++) {
+		slot = mca_find_unused_adapter(smc_mca_adapters[j].id, 0);
 
+		while((slot != MCA_NOTFOUND) && !adapter_found) {
+			tirq = 0;
+			tbase = 0;
+
+                        /* If we're trying to match a specificied irq or
+			 * io address, we'll reject the adapter
+			 * found unless it's the one we're looking for
+			 */
+
+			pos2 = mca_read_stored_pos(slot, 2); /* io_addr */
+			pos3 = mca_read_stored_pos(slot, 3); /* shared mem */
+			pos4 = mca_read_stored_pos(slot, 4); /* ROM bios addr
+							      * range */
+			pos5 = mca_read_stored_pos(slot, 5); /* irq, media
+							      * and RIPL */
+
+			/* Test the following conditions:
+			 * - If an irq parameter is supplied, compare it
+			 *   with the irq of the adapter we found
+			 * - If a base_addr paramater is given, compare it
+			 *   with the base_addr of the adapter we found
+			 * - Check that the irq and the base_addr of the
+			 *   adapter we found is not already in use by
+			 *   this driver
+			 */
+			switch (j) { /* j = card-idx (card array above) [hs] */
+				case _61c8_SMC_Ethercard_PLUS_Elite_A_BNC_AUI_WD8013EP_A:
+		                case _61c9_SMC_Ethercard_PLUS_Elite_A_UTP_AUI_WD8013EP_A:
+				case _efd4_IBM_PS2_Adapter_A_for_Ethernet_UTP_AUI_WD8013WP_A:
+				case _efd5_IBM_PS2_Adapter_A_for_Ethernet_BNC_AUI_WD8013WP_A:
+				{
+					tbase = addr_table[(pos2 & 0xf0) >> 4].base_addr;
+					tirq  = irq_table[(pos5 & 0xc) >> 2].new_irq;
+					break;
+				}
+				case _6fc0_WD_Ethercard_PLUS_A_WD8003E_A_OR_WD8003ET_A:
+				case _6fc1_WD_Starcard_PLUS_A_WD8003ST_A:
+				case _6fc2_WD_Ethercard_PLUS_10T_A_WD8003W_A:
+				case _efe5_IBM_PS2_Adapter_A_for_Ethernet:
+				{
+					tbase = ((pos2 & 0x0fe) * 0x10);
+					tirq  = irq_table[(pos5 & 3)].old_irq;
+					break;
+				}
+			}
+
+			if(!tirq || !tbase || (irq && irq != tirq) || (base_addr && tbase != base_addr)) {
+				slot = mca_find_unused_adapter(smc_mca_adapters[j].id, slot + 1);
+			} else {
+				adapter_found = 1;
+				adapter = j;
+			}
+		}
+	}
+	/* Correct j now, before we forget */
+	j--;
+
+	if(!adapter_found) {
+		return ((base_addr || irq) ? ENXIO : ENODEV);
+	}
+
+        /* Adapter found. */
+
+	printk(KERN_INFO "%s: %s found in slot %d\n",
+	       dev->name, smc_mca_adapters[adapter].name, slot + 1);
+
+	mca_set_adapter_name(slot, smc_mca_adapters[adapter].name);
+
+
+	dev->base_addr = ioaddr = tbase;
+	dev->irq       = tirq;
 	dev->mem_start = 0;
-	num_pages = 40;
-	for (i = 0; i < 15; i++)
-	{
-		if (mem_table[i].mem_index == (pos3 & ~MEM_MASK))
+	num_pages      = 40;
+
+	switch (j) {	/* 'j' = card-# in const array above [hs] */
+		case _61c8_SMC_Ethercard_PLUS_Elite_A_BNC_AUI_WD8013EP_A:
+		case _61c9_SMC_Ethercard_PLUS_Elite_A_UTP_AUI_WD8013EP_A:
+		{
+			for (i = 0; i < 16; i++) { /* taking 16 counts
+						    * up to 15 [hs] */
+				if (mem_table[i].mem_index == (pos3 & ~MEM_MASK)) {
+					dev->mem_start = mem_table[i].mem_start;
+					num_pages = mem_table[i].num_pages;
+				}
+			}
+			break;
+		}
+		case _6fc0_WD_Ethercard_PLUS_A_WD8003E_A_OR_WD8003ET_A:
+		case _6fc1_WD_Starcard_PLUS_A_WD8003ST_A:
+		case _6fc2_WD_Ethercard_PLUS_10T_A_WD8003W_A:
+		case _efe5_IBM_PS2_Adapter_A_for_Ethernet:
 		{
-			dev->mem_start = mem_table[i].mem_start;
-			num_pages = mem_table[i].num_pages;
+			dev->mem_start = ((pos3 & 0xfc) * 0x1000);
+			num_pages = 0x40;
+			break;
+		}
+		case _efd4_IBM_PS2_Adapter_A_for_Ethernet_UTP_AUI_WD8013WP_A:
+		case _efd5_IBM_PS2_Adapter_A_for_Ethernet_BNC_AUI_WD8013WP_A:
+		{
+			/* courtesy of gamera@quartz.ocn.ne.jp, pos3 indicates
+			 * the index of the 0x2000 step.
+			 * beware different number of pages [hs]
+			 */
+			dev->mem_start = 0xc0000 + (0x2000 * (pos3 & 0xf));
+			num_pages = 0x20 + (2 * (pos3 & 0x10));
+			break;
 		}
 	}
 
-	if (dev->mem_start == 0)      /* sanity check, shouldn't happen */
+	if (dev->mem_start == 0) /* sanity check, shouldn't happen */
 		return -ENODEV;
 
 	reg4 = inb(ioaddr + 4) & 0x7f;
@@ -121,52 +263,46 @@
 	if (load_8390_module("wd.c"))
 		return -ENOSYS;
 
-	printk("%s: SMC Ultra MCA at %#3x,", dev->name, ioaddr);
+	printk(KERN_INFO "%s: Parameters: %#3x,", dev->name, ioaddr);
 
 	for (i = 0; i < 6; i++)
 		printk(" %2.2X", dev->dev_addr[i] = inb(ioaddr + 8 + i));
 
-	/*
-	 *	Switch from the station address to the alternate register set and
-	 *	read the useful registers there.
+	/* Switch from the station address to the alternate register set
+	 * and read the useful registers there.
 	 */
 
 	outb(0x80 | reg4, ioaddr + 4);
 
-	/*
-	 *	Enable FINE16 mode to avoid BIOS ROM width mismatches @ reboot.
+	/* Enable FINE16 mode to avoid BIOS ROM width mismatches @ reboot.
 	 */
 
 	outb(0x80 | inb(ioaddr + 0x0c), ioaddr + 0x0c);
 
-	/*
-	 *	Switch back to the station address register set so that the MS-DOS driver
-	 *	can find the card after a warm boot.
+	/* Switch back to the station address register set so that
+	 * the MS-DOS driver can find the card after a warm boot.
 	 */
 
 	outb(reg4, ioaddr + 4);
 
-	/*
-	 *	Allocate dev->priv and fill in 8390 specific dev fields.
+	/* Allocate dev->priv and fill in 8390 specific dev fields.
 	 */
 
-	if (ethdev_init(dev))
-	{
+	if (ethdev_init(dev)) {
 		printk (", no memory for dev->priv.\n");
 		return -ENOMEM;
 	}
 
-	/*
-	 *	OK, we are certain this is going to work.  Setup the device.
+	/* OK, we are certain this is going to work.  Setup the device.
 	 */
 
+	mca_mark_as_used(slot);
 	request_region(ioaddr, ULTRA_IO_EXTENT, "smc-mca");
 
-	/*
-	 *	The 8390 isn't at the base address, so fake the offset
+	/* The 8390 isn't at the base address, so fake the offset
 	 */
 
-	dev->base_addr = ioaddr+ULTRA_NIC_OFFSET;
+	dev->base_addr = ioaddr + ULTRA_NIC_OFFSET;
 
 	ei_status.name = "SMC Ultra MCA";
 	ei_status.word16 = 1;
@@ -174,16 +310,20 @@
 	ei_status.rx_start_page = START_PG + TX_PAGES;
 	ei_status.stop_page = num_pages;
 
-	dev->rmem_start = dev->mem_start + TX_PAGES*256;
+	dev->rmem_start = dev->mem_start + TX_PAGES * 256;
 	dev->mem_end = dev->rmem_end =
-	dev->mem_start + (ei_status.stop_page - START_PG)*256;
+	dev->mem_start + (ei_status.stop_page - START_PG) * 256;
 
-	printk(", IRQ %d memory %#lx-%#lx.\n", dev->irq, dev->mem_start, dev->mem_end-1);
+	printk(", IRQ %d memory %#lx-%#lx.\n",
+	dev->irq, dev->mem_start, dev->mem_end - 1);
 
 	ei_status.reset_8390 = &ultramca_reset_8390;
 	ei_status.block_input = &ultramca_block_input;
 	ei_status.block_output = &ultramca_block_output;
 	ei_status.get_8390_hdr = &ultramca_get_8390_hdr;
+
+	ei_status.priv = slot;
+
 	dev->open = &ultramca_open;
 	dev->stop = &ultramca_close_card;
 	NS8390_init(dev, 0);
@@ -196,21 +336,19 @@
 	int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
 
 	if (request_irq(dev->irq, ei_interrupt, 0, ei_status.name, dev))
-	return -EAGAIN;
+		return -EAGAIN;
 
 	outb(ULTRA_MEMENB, ioaddr); /* Enable memory */
 	outb(0x80, ioaddr + 5);     /* ??? */
 	outb(0x01, ioaddr + 6);     /* Enable interrupts and memory. */
 	outb(0x04, ioaddr + 5);     /* ??? */
 
-	/*
-	 *	Set the early receive warning level in window 0 high enough not
-	 *	to receive ERW interrupts.
+	/* Set the early receive warning level in window 0 high enough not
+	 * to receive ERW interrupts.
 	 */
 
-	/*
-	 *	outb_p(E8390_NODMA+E8390_PAGE0, dev->base_addr);
-	 *	outb(0xff, dev->base_addr + EN0_ERWCNT);
+	/* outb_p(E8390_NODMA + E8390_PAGE0, dev->base_addr);
+	 * outb(0xff, dev->base_addr + EN0_ERWCNT);
 	 */
 
 	ei_open(dev);
@@ -223,7 +361,8 @@
 	int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
 
 	outb(ULTRA_RESET, ioaddr);
-	if (ei_debug > 1) printk("resetting Ultra, t=%ld...", jiffies);
+	if (ei_debug > 1)
+		printk("resetting Ultra, t=%ld...", jiffies);
 	ei_status.txing = 0;
 
 	outb(0x80, ioaddr + 5);     /* ??? */
@@ -235,12 +374,13 @@
 }
 
 /* Grab the 8390 specific header. Similar to the block_input routine, but
-   we don't need to be concerned with ring wrap as the header will be at
-   the start of a page, so we optimize accordingly. */
+ * we don't need to be concerned with ring wrap as the header will be at
+ * the start of a page, so we optimize accordingly.
+ */
 
 static void ultramca_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
-	unsigned long hdr_start = dev->mem_start + ((ring_page - START_PG)<<8);
+	unsigned long hdr_start = dev->mem_start + ((ring_page - START_PG) << 8);
 
 #ifdef notdef
 	/* Officially this is what we are doing, but the readl() is faster */
@@ -251,22 +391,20 @@
 }
 
 /* Block input and output are easy on shared memory ethercards, the only
-   complication is when the ring buffer wraps. */
+ * complication is when the ring buffer wraps.
+ */
 
 static void ultramca_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
 {
-	unsigned long xfer_start = dev->mem_start + ring_offset - (START_PG<<8);
+	unsigned long xfer_start = dev->mem_start + ring_offset - (START_PG << 8);
 
-	if (xfer_start + count > dev->rmem_end)
-	{
-        	/* We must wrap the input move. */
+	if (xfer_start + count > dev->rmem_end) {
+		/* We must wrap the input move. */
 		int semi_count = dev->rmem_end - xfer_start;
 		memcpy_fromio(skb->data, xfer_start, semi_count);
 		count -= semi_count;
 		memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
-	}
-	else
-	{
+	} else {
 		/* Packet is in one chunk -- we can copy + cksum. */
 		eth_io_copy_and_sum(skb, xfer_start, count, 0);
 	}
@@ -276,7 +414,7 @@
 static void ultramca_block_output(struct device *dev, int count, const unsigned char *buf,
                 int start_page)
 {
-	unsigned long shmem = dev->mem_start + ((start_page - START_PG)<<8);
+	unsigned long shmem = dev->mem_start + ((start_page - START_PG) << 8);
 
 	memcpy_toio(shmem, buf, count);
 }
@@ -296,7 +434,8 @@
 
 	NS8390_init(dev, 0);
 	/* We should someday disable shared memory and change to 8-bit mode
-       "just in case"... */
+         * "just in case"...
+	 */
 
 	MOD_DEC_USE_COUNT;
 
@@ -307,8 +446,9 @@
 #ifdef MODULE
 #undef MODULE        /* don't want to bother now! */
 
-#define MAX_ULTRAMCA_CARDS  4   /* Max number of Ultra cards per module */
-#define NAMELEN     8   /* # of chars for storing dev->name */
+#define MAX_ULTRAMCA_CARDS 4	/* Max number of Ultra cards per module */
+#define NAMELEN 8		/* # of chars for storing dev->name */
+
 static char namelist[NAMELEN * MAX_ULTRAMCA_CARDS] = { 0, };
 
 static struct device dev_ultra[MAX_ULTRAMCA_CARDS] =
@@ -327,53 +467,41 @@
 MODULE_PARM(io, "1-" __MODULE_STRING(MAX_ULTRAMCA_CARDS) "i");
 MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_ULTRAMCA_CARDS) "i");
 
-/* This is set up so that only a single autoprobe takes place per call.
-ISA device autoprobes on a running machine are not recommended. */
-
 int init_module(void)
 {
 	int this_dev, found = 0;
 
-	for (this_dev = 0; this_dev < MAX_ULTRAMCA_CARDS; this_dev++)
-	{
+	for (this_dev = 0; this_dev < MAX_ULTRAMCA_CARDS; this_dev++) {
 		struct device *dev = &dev_ultra[this_dev];
-		dev->name = namelist+(NAMELEN*this_dev);
+		dev->name = namelist + (NAMELEN * this_dev);
 		dev->irq = irq[this_dev];
 		dev->base_addr = io[this_dev];
 		dev->init = ultramca_probe;
-		if (io[this_dev] == 0)
-		{
-			if (this_dev != 0)
-				break; /* only autoprobe 1st one */
-			printk(KERN_NOTICE "smc-mca.c: Presently autoprobing (not recommended) for a single card.\n");
-		}
-		if (register_netdev(dev) != 0)
-		{
-			printk(KERN_WARNING "smc-mca.c: No SMC Ultra card found (i/o = 0x%x).\n", io[this_dev]);
-			if (found != 0) {	/* Got at least one. */
-				lock_8390_module();
-				return 0;
-			}
-			return -ENXIO;
+
+		if (register_netdev(dev) != 0) {
+			break;
 		}
 		found++;
 	}
-	lock_8390_module();
-	return 0;
+	if (found != 0) {	/* Got at least one. */
+		lock_8390_module();
+		return 0;
+	}
+	printk(KERN_NOTICE "smc-mca.c: No SMC Ultra card found (i/o = 0x%x).\n", io[this_dev]);
+	return -ENXIO;
 }
 
 void cleanup_module(void)
 {
 	int this_dev;
 
-	for (this_dev = 0; this_dev < MAX_ULTRAMCA_CARDS; this_dev++)
-	{
+	for (this_dev = 0; this_dev < MAX_ULTRAMCA_CARDS; this_dev++) {
 		struct device *dev = &dev_ultra[this_dev];
-        	if (dev->priv != NULL)
-        	{
+		if (dev->priv != NULL) {
 			void *priv = dev->priv;
 			/* NB: ultra_close_card() does free_irq */
 			int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET;
+			mca_mark_as_unused(ei_status.priv);
 			release_region(ioaddr, ULTRA_IO_EXTENT);
 			unregister_netdev(dev);
 			kfree(priv);
@@ -382,7 +510,6 @@
 	unlock_8390_module();
 }
 #endif /* MODULE */
-
 
 /*
  * Local variables:
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/smc-mca.h linux.15p9/drivers/net/smc-mca.h
--- linux.vanilla/drivers/net/smc-mca.h	Thu Dec 12 14:51:10 1996
+++ linux.15p9/drivers/net/smc-mca.h	Mon Feb  7 12:07:40 2000
@@ -1,7 +1,7 @@
-/* 
-   djweis weisd3458@uni.edu 
-   most of this file was taken from ps2esdi.h
-*/
+/*
+ * djweis weisd3458@uni.edu
+ * most of this file was taken from ps2esdi.h
+ */
 
 struct {
   unsigned int base_addr;
@@ -25,38 +25,37 @@
 };
 
 #define MEM_MASK 64
+
 struct {
   unsigned char mem_index;
   unsigned long mem_start;
   unsigned char num_pages;
 } mem_table[] = {
-    { 16, 0x0c0000, 40 },
-    { 18, 0x0c4000, 40 },
-    { 20, 0x0c8000, 40 },
-    { 22, 0x0cc000, 40 },
-    { 24, 0x0d0000, 40 },
-    { 26, 0x0d4000, 40 },
-    { 28, 0x0d8000, 40 },
-    { 30, 0x0dc000, 40 },
-    {144, 0xfc0000, 40 },
-    {148, 0xfc8000, 40 },
-    {154, 0xfd0000, 40 },
-    {156, 0xfd8000, 40 },
-    {  0, 0x0c0000, 20 },
-    {  1, 0x0c2000, 20 },
-    {  2, 0x0c4000, 20 },
-    {  3, 0x0c6000, 20 }
+    { 16, 0x0c0000, 0x40 },
+    { 18, 0x0c4000, 0x40 },
+    { 20, 0x0c8000, 0x40 },
+    { 22, 0x0cc000, 0x40 },
+    { 24, 0x0d0000, 0x40 },
+    { 26, 0x0d4000, 0x40 },
+    { 28, 0x0d8000, 0x40 },
+    { 30, 0x0dc000, 0x40 },
+    {144, 0xfc0000, 0x40 },
+    {148, 0xfc8000, 0x40 },
+    {154, 0xfd0000, 0x40 },
+    {156, 0xfd8000, 0x40 },
+    {  0, 0x0c0000, 0x20 },
+    {  1, 0x0c2000, 0x20 },
+    {  2, 0x0c4000, 0x20 },
+    {  3, 0x0c6000, 0x20 }
 };
 
 #define IRQ_MASK 243
 struct {
-   unsigned char irq;
+   unsigned char new_irq;
+   unsigned char old_irq;
 } irq_table[] = {
-   {  3 }, 
-   {  4 },
-   { 10 },
-   { 14 }
+   {  3,  3 },
+   {  4,  4 },
+   { 10, 10 },
+   { 14, 15 }
 };
-
- 
-   
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/tlan.c linux.15p9/drivers/net/tlan.c
--- linux.vanilla/drivers/net/tlan.c	Tue Jan  4 21:18:53 2000
+++ linux.15p9/drivers/net/tlan.c	Wed Feb 16 18:28:31 2000
@@ -1,4 +1,4 @@
-/********************************************************************
+/********************************************************************************
  *
  *  Linux ThunderLAN Driver
  *
@@ -7,6 +7,7 @@
  *
  *  (C) 1997-1998 Caldera, Inc.
  *  (C) 1998 James Banks
+ *  (C) 1999-2000 Torben Mathiasen 
  *
  *  This software may be used and distributed according to the terms
  *  of the GNU Public License, incorporated herein by reference.
@@ -34,7 +35,15 @@
  *
  *	Torben Mathiasen <torben.mathiasen@compaq.com> New Maintainer!
  *
- ********************************************************************/
+ * 	v1.2 Feb 14, 2000	- Fixed a timer bug that would cause
+ * 				  the tlan driver to get stuck if no 
+ * 				  cable/link were present.
+ * 				- We now allow higher priority timers
+ * 				  to overwrite timers like TLAN_TIMER_ACTIVITY
+ * 				  Patch from John Cagle <john.cagle@compaq.com>
+ * 				- Removed dependency of HZ being 100.
+ *
+ ********************************************************************************/
 
 
 #include <linux/module.h>
@@ -76,7 +85,7 @@
 static	u8		*TLanPadBuffer;
 static	char		TLanSignature[] = "TLAN";
 static	int		TLanVersionMajor = 1;
-static	int		TLanVersionMinor = 0;
+static	int		TLanVersionMinor = 2;
 
 
 static	TLanAdapterEntry TLanAdapterList[] = {
@@ -238,7 +247,8 @@
 	TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
 
 	cli();
-	if ( priv->timer.function != NULL ) {
+	if ( priv->timer.function != NULL && 
+		priv->timerType != TLAN_TIMER_ACTIVITY) {
 		return;
 	}
 	priv->timer.function = &TLan_Timer;
@@ -712,6 +722,9 @@
 	int		err;
 
 	priv->tlanRev = TLan_DioRead8( dev->base_addr, TLAN_DEF_REVISION );
+	
+	MOD_INC_USE_COUNT;
+
 	if ( priv->sa_int ) {
 		TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:   Using SA_INTERRUPT\n" ); 
 		err = request_irq( dev->irq, TLan_HandleInterrupt, SA_SHIRQ | SA_INTERRUPT, TLanSignature, dev );
@@ -723,8 +736,6 @@
 		return -EAGAIN;
 	}
 	
-	MOD_INC_USE_COUNT;
-
 	dev->tbusy = 0;
 	dev->interrupt = 0;
 	dev->start = 1;
@@ -735,7 +746,6 @@
 	TLan_ResetLists( dev );
 	TLan_ReadAndClearStats( dev, TLAN_IGNORE );
 	TLan_ResetAdapter( dev );
-
 	TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:  %s: Opened.  TLAN Chip Rev: %x\n", dev->name, priv->tlanRev );
 
 	return 0;
@@ -927,6 +937,7 @@
 	outl( TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD );
 	if ( priv->timer.function != NULL )
 		del_timer( &priv->timer );
+		priv->timer.function = NULL;
 	free_irq( dev->irq, dev );
 	TLan_FreeLists( dev );
 	TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:  Device %s closed.\n", dev->name );
@@ -1132,8 +1143,8 @@
 		printk( "TLAN:  Received interrupt for uncompleted TX frame.\n" );
 	}
 
-#if LINUX_KERNEL_VERSION > 0x20100
-	priv->stats->tx_bytes += head_list->frameSize;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
+	priv->stats.tx_bytes += head_list->frameSize;
 #endif
 
 	head_list->cStat = TLAN_CSTAT_UNUSED;
@@ -1252,8 +1263,8 @@
 			skb_reserve( skb, 2 );
 			t = (void *) skb_put( skb, head_list->frameSize );
 
-#if LINUX_KERNEL_VERSION > 0x20100
-			priv->stats->rx_bytes += head_list->frameSize;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
+			priv->stats.rx_bytes += head_list->frameSize;
 #endif
 
 			memcpy( t, head_buffer, head_list->frameSize );
@@ -1276,8 +1287,8 @@
 			skb = (struct sk_buff *) head_list->buffer[9].address;
 			head_list->buffer[9].address = 0;
 			skb_trim( skb, head_list->frameSize );
-#if LINUX_KERNEL_VERSION > 0x20100
-			priv->stats->rx_bytes += head_list->frameSize;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
+			priv->stats.rx_bytes += head_list->frameSize;
 #endif
 
 			skb->protocol = eth_type_trans( skb, dev );
@@ -1884,7 +1895,7 @@
 	u32		addr;
 	u32		data;
 	u8		data8;
-
+	
 	priv->tlanFullDuplex = FALSE;
 	priv->phyOnline=0;
 /*  1.	Assert reset bit. */
@@ -2015,7 +2026,7 @@
 		outl( TLAN_HC_GO | TLAN_HC_RT, dev->base_addr + TLAN_HOST_CMD );
 	} else {
 		printk( "TLAN:  %s: Link inactive, will retry in 10 secs...\n", dev->name );
-		TLan_SetTimer( dev, 1000, TLAN_TIMER_FINISH_RESET );
+		TLan_SetTimer( dev, (10*HZ), TLAN_TIMER_FINISH_RESET );
 		return;
 	}
 
@@ -2197,11 +2208,11 @@
 		TLan_MiiWriteReg( dev, priv->phy[1], MII_GEN_CTL, value );
 	}
 
-	/* Wait for 5 jiffies (50 ms) and powerup
+	/* Wait for 50 ms and powerup
 	 * This is abitrary.  It is intended to make sure the
 	 * tranceiver settles.
 	 */
-	TLan_SetTimer( dev, 5, TLAN_TIMER_PHY_PUP );
+	TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_PUP );
 
 } /* TLan_PhyPowerDown */
 
@@ -2212,17 +2223,17 @@
 {
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
 	u16		value;
-
+	
 	TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:  %s: Powering up PHY.\n", dev->name );
 	TLan_MiiSync( dev->base_addr );
 	value = MII_GC_LOOPBK;
 	TLan_MiiWriteReg( dev, priv->phy[priv->phyNum], MII_GEN_CTL, value );
 
-	/* Wait for 50 jiffies (500 ms) and reset the
+	/* Wait for 500 ms and reset the
 	 * tranceiver.  The TLAN docs say both 50 ms and
 	 * 500 ms, so do the longer, just in case
 	 */
-	TLan_SetTimer( dev, 50, TLAN_TIMER_PHY_RESET );
+	TLan_SetTimer( dev, (HZ/2), TLAN_TIMER_PHY_RESET );
 
 } /* TLan_PhyPowerUp */
 
@@ -2247,10 +2258,10 @@
 	}
 	TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0 );
 
-	/* Wait for 50 jiffies (500 ms) and initialize.
+	/* Wait for 500 ms and initialize.
 	 * I don't remember why I wait this long.
 	 */
-	TLan_SetTimer( dev, 50, TLAN_TIMER_PHY_START_LINK );
+	TLan_SetTimer( dev, (HZ/2), TLAN_TIMER_PHY_START_LINK );
 
 } /* TLan_PhyReset */
 
@@ -2293,13 +2304,13 @@
        		TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x1000 );
 		TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x1200 );
 
-		/* Wait for 400 jiffies (4 sec) for autonegotiation
+		/* Wait for 4 sec for autonegotiation
 		 * to complete.  The max spec time is less than this
 		 * but the card need additional time to start AN.
 		 * .5 sec should be plenty extra.
 		 */
 		printk( "TLAN:  %s: Starting autonegotiation.\n", dev->name );
-		TLan_SetTimer( dev, 400, TLAN_TIMER_PHY_FINISH_AN );
+		TLan_SetTimer( dev, (4*HZ), TLAN_TIMER_PHY_FINISH_AN );
 		return;
 	}
 
@@ -2307,7 +2318,7 @@
 		priv->phyNum = 0;
 		data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN;
 		TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, data );
-		TLan_SetTimer( dev, 4, TLAN_TIMER_PHY_PDOWN );
+		TLan_SetTimer( dev, (4*(HZ/1000)), TLAN_TIMER_PHY_PDOWN );
 		return;
 	} else if ( priv->phyNum == 0 ) {
         	TLan_MiiReadReg( dev, phy, TLAN_TLPHY_CTL, &tctl );
@@ -2328,10 +2339,10 @@
         	TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tctl );
 	}
 
-	/* Wait for 100 jiffies (1 sec) to give the tranceiver time
+	/* Wait for 1 sec to give the tranceiver time
 	 * to establish link.
 	 */
-	TLan_SetTimer( dev, 100, TLAN_TIMER_FINISH_RESET );
+	TLan_SetTimer( dev, HZ, TLAN_TIMER_FINISH_RESET );
 
 } /* TLan_PhyStartLink */
 
@@ -2352,11 +2363,11 @@
 
 	TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );
 	if ( ! ( status & MII_GS_AUTOCMPLT ) ) {
-		/* Wait for 800 jiffies (8 sec) to give the process
+		/* Wait for 8 sec to give the process
 		 * more time.  Perhaps we should fail after a while.
 		 */
 		printk( "TLAN:  Giving autonegotiation more time.\n" );
-		TLan_SetTimer( dev, 800, TLAN_TIMER_PHY_FINISH_AN );
+		TLan_SetTimer( dev, (8*HZ), TLAN_TIMER_PHY_FINISH_AN );
 		return;
 	}
 
@@ -2374,7 +2385,7 @@
 		priv->phyNum = 0;
 		data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN;
 		TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, data );
-		TLan_SetTimer( dev, 40, TLAN_TIMER_PHY_PDOWN );
+		TLan_SetTimer( dev, (400*(HZ/1000)), TLAN_TIMER_PHY_PDOWN );
 		return;
 	}
 
@@ -2388,9 +2399,9 @@
 		}
 	}
 
-	/* Wait for 10 jiffies (100 ms).  No reason in partiticular.
+	/* Wait for 100 ms.  No reason in partiticular.
 	 */
-	TLan_SetTimer( dev, 10, TLAN_TIMER_FINISH_RESET );
+	TLan_SetTimer( dev, (HZ/10), TLAN_TIMER_FINISH_RESET );
 		
 } /* TLan_PhyFinishAutoNeg */
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/tlan.h linux.15p9/drivers/net/tlan.h
--- linux.vanilla/drivers/net/tlan.h	Tue Jan  4 21:18:53 2000
+++ linux.15p9/drivers/net/tlan.h	Wed Feb 16 18:28:31 2000
@@ -8,7 +8,8 @@
  *  by James Banks
  *
  *  (C) 1997-1998 Caldera, Inc.
- *
+ *  (C) 1999-2000 Torben Mathiasen 
+ *  
  *  This software may be used and distributed according to the terms
  *  of the GNU Public License, incorporated herein by reference.
  *
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/net/tulip.c linux.15p9/drivers/net/tulip.c
--- linux.vanilla/drivers/net/tulip.c	Tue Jan  4 21:18:53 2000
+++ linux.15p9/drivers/net/tulip.c	Sat Jan 22 02:08:16 2000
@@ -15,6 +15,10 @@
 
 	Support and updates available at
 	http://cesdis.gsfc.nasa.gov/linux/drivers/tulip.html
+	
+	This driver also contains updates by Wolfgang Walter and others.
+	For this specific driver variant please use linux-kernel for 
+	bug reports.
 */
 
 #define SMP_CHECK
@@ -577,7 +581,7 @@
 		return -ENODEV;
 
 	for (;pci_index < 0xff; pci_index++) {
-		u16 vendor, device, pci_command, new_command;
+		u16 vendor, device, pci_command, new_command, subvendor;
 		int chip_idx;
 		int irq;
 		long ioaddr;
@@ -595,6 +599,13 @@
 								 PCI_VENDOR_ID, &vendor);
 		pcibios_read_config_word(pci_bus, pci_device_fn,
 								 PCI_DEVICE_ID, &device);
+		pcibios_read_config_word(pci_bus, pci_device_fn,
+								 PCI_SUBSYSTEM_VENDOR_ID, &subvendor);
+		
+	        if( subvendor == 0x1376 ){
+			printk("tulip: skipping LMC card.\n");
+			continue;
+		}	
 
 		for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
 			if (vendor == pci_tbl[chip_idx].vendor_id
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/pci/oldproc.c linux.15p9/drivers/pci/oldproc.c
--- linux.vanilla/drivers/pci/oldproc.c	Tue Jan  4 21:18:53 2000
+++ linux.15p9/drivers/pci/oldproc.c	Wed Feb 16 18:32:54 2000
@@ -36,6 +36,7 @@
  */
 struct pci_dev_info dev_info[] = {
 	DEVICE( COMPAQ,		COMPAQ_1280,	"QVision 1280/p"),
+	DEVICE(	COMPAQ,		COMPAQ_6010,	"Hot Plug PCI Bridge"),
 	DEVICE( COMPAQ,		COMPAQ_SMART2P,	"Smart-2/P RAID Controller"),
 	DEVICE( COMPAQ,		COMPAQ_NETEL100,"Netelligent 10/100"),
 	DEVICE( COMPAQ,		COMPAQ_NETEL10,	"Netelligent 10"),
@@ -411,6 +412,8 @@
 	DEVICE( MUTECH,		MUTECH_MV1000,	"MV-1000"),
 	DEVICE( RENDITION,	RENDITION_VERITE,"Verite 1000"),
 	DEVICE( RENDITION,	RENDITION_VERITE2100,"Verite 2100"),
+	DEVICE(	RCC,		RCC_HE,		"CNB20HE PCI Bridge"),
+	DEVICE(	RCC,		RCC_LE,		"CNB30LE PCI Bridge"),
 	DEVICE( TOSHIBA,	TOSHIBA_601,	"Laptop"),
 	DEVICE( TOSHIBA,	TOSHIBA_TOPIC95,"ToPIC95"),
 	DEVICE( TOSHIBA,	TOSHIBA_TOPIC97,"ToPIC97"),
@@ -423,6 +426,7 @@
 	DEVICE( LITEON,		LITEON_LNE100TX,"LNE100TX"),
 	DEVICE( NP,		NP_PCI_FDDI,	"NP-PCI"),       
 	DEVICE( ATT,		ATT_L56XMF,	"L56xMF"),
+	DEVICE( ATT,		ATT_L56DVP,	"L56DV+P"),
 	DEVICE( SPECIALIX,	SPECIALIX_IO8,	"IO8+/PCI"),
 	DEVICE( SPECIALIX,	SPECIALIX_XIO,	"XIO/SIO host"),
 	DEVICE( SPECIALIX,	SPECIALIX_RIO,	"RIO host"),
@@ -515,6 +519,7 @@
 	DEVICE( INTEL,		INTEL_82430,	"82430ZX Aries"),
 	DEVICE( INTEL,		INTEL_82434,	"82434LX Mercury/Neptune"),
 	DEVICE( INTEL,		INTEL_I960,	"i960"),
+	DEVICE( INTEL,		INTEL_82559ER,	"82559ER"),
 	DEVICE( INTEL,		INTEL_82092AA_0,"82092AA PCMCIA bridge"),
 	DEVICE( INTEL,		INTEL_82092AA_1,"82092AA EIDE"),
 	DEVICE( INTEL,		INTEL_7116,	"SAA7116"),
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/pci/pci.c linux.15p9/drivers/pci/pci.c
--- linux.vanilla/drivers/pci/pci.c	Wed Oct 20 01:12:39 1999
+++ linux.15p9/drivers/pci/pci.c	Wed Feb 16 18:32:54 2000
@@ -282,6 +282,14 @@
 	 * all PCI-to-PCI bridges on this bus.
 	 */
 	pcibios_fixup_bus(bus);
+	/*
+	 * The fixup code may have just found some peer pci bridges on this
+	 * machine.  Update the max variable if that happened so we don't
+	 * get duplicate bus numbers.
+	 */
+	for(child=&pci_root; child; child=child->next)
+		max=((max > child->subordinate) ? max : child->subordinate);
+
 	for(dev=bus->devices; dev; dev=dev->sibling)
 		/*
 		 * If it's a bridge, scan the bus behind it.
@@ -292,6 +300,37 @@
 			unsigned short cr;
 
 			/*
+			 * Check for a duplicate bus.  If we already scanned
+			 * this bus number as a peer bus, don't also scan it
+			 * as a child bus
+			 */
+			if(
+			   ((dev->vendor == PCI_VENDOR_ID_RCC) &&
+			    ((dev->device == PCI_DEVICE_ID_RCC_HE) ||
+			     (dev->device == PCI_DEVICE_ID_RCC_LE))) ||
+			   ((dev->vendor == PCI_VENDOR_ID_COMPAQ) &&
+			    (dev->device == PCI_DEVICE_ID_COMPAQ_6010)) ||
+			   ((dev->vendor == PCI_VENDOR_ID_INTEL) &&
+			    ((dev->device == PCI_DEVICE_ID_INTEL_82454NX) ||
+			     (dev->device == PCI_DEVICE_ID_INTEL_82451NX)))
+			  )
+				goto skip_it;
+			/*
+			 * Read the existing primary/secondary/subordinate bus
+			 * number configuration to determine if the PCI bridge
+			 * has already been configured by the system.  If so,
+			 * check to see if we've already scanned this bus as
+			 * a result of peer bus scanning, if so, skip this.
+			 */
+			pcibios_read_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, &buses);
+			if ((buses & 0xFFFFFF) != 0)
+			  {
+			    for(child=pci_root.next;child;child=child->next)
+				if(child->number == ((buses >> 8) & 0xff))
+				    goto skip_it;
+			  }
+			
+			/*
 			 * Insert it into the tree of buses.
 			 */
 			child = kmalloc(sizeof(*child), GFP_ATOMIC);
@@ -363,6 +402,7 @@
 			    pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses);
 			  }
 			pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, cr);
+skip_it:
 		}
 
 	/*
@@ -380,6 +420,12 @@
 {
 	struct pci_bus *b;
 
+	b = &pci_root;
+	while((b != NULL) && (bus != 0)) {
+		if(b->number == bus)
+			return(b);
+		b = b->next;
+	}
 	b = kmalloc(sizeof(*b), GFP_KERNEL);
 	memset(b, 0, sizeof(*b));
 	b->next = pci_root.next;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/pnp/parport_probe.c linux.15p9/drivers/pnp/parport_probe.c
--- linux.vanilla/drivers/pnp/parport_probe.c	Wed Jan 20 21:29:18 1999
+++ linux.15p9/drivers/pnp/parport_probe.c	Wed Jan 26 23:06:16 2000
@@ -96,6 +96,7 @@
 	struct pardevice *dev = parport_register_device(port, "IEEE 1284 probe", NULL, NULL, NULL, 0, &dev);
 
 	int result = 0;
+	int lives = 1;
 
 	if (!dev) {
 		printk("%s: unable to register for probe.\n", port->name);
@@ -104,6 +105,7 @@
 
 	parport_claim_or_block(dev);
 
+ try_again:
 	switch (parport_ieee1284_nibble_mode_ok(port, 4)) {
 	case 2:
 		current->state=TASK_INTERRUPTIBLE;
@@ -115,6 +117,20 @@
 		result = -EIO;
 		break;
 	}
+
+	if (result < 1 && lives--) {
+		/* Reset the peripherals and try again. */
+		parport_pc_write_control(port, 0x8);
+		parport_pc_write_data(port, 0);
+		udelay (50);
+		parport_pc_write_control(port, 0xc);
+		udelay (500);
+		goto try_again;
+	}
+
+	printk (KERN_DEBUG "parport_probe: %s%s\n",
+		lives ? "" : "after reset: ",
+		result < 1 ? "failed" : "succeeded");
 
 	parport_release(dev);
 	parport_unregister_device(dev);
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/s390/block/dasd.c linux.15p9/drivers/s390/block/dasd.c
--- linux.vanilla/drivers/s390/block/dasd.c	Tue Jan  4 21:18:53 2000
+++ linux.15p9/drivers/s390/block/dasd.c	Thu Feb 17 13:35:21 2000
@@ -3,7 +3,7 @@
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  *                : Utz Bacher <utz.bacher@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
- * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999
+ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  */
 
 #include <linux/stddef.h>
@@ -26,7 +26,7 @@
 #include <asm/ebcdic.h>
 #include <asm/uaccess.h>
 
-#include "../../../arch/s390/kernel/irq.h"
+#include <asm/irq.h>
 
 #include "dasd.h"
 #include <linux/blk.h>
@@ -38,12 +38,12 @@
 
 #define CCW_READ_DEVICE_CHARACTERISTICS  0x64
 
-#define DASD_SSCH_RETRIES 5
+#define DASD_SSCH_RETRIES 2
 
 /* This macro is a little tricky, but makes the code more easy to read... */
 #define MATCH(info,ct,cm,dt,dm) ( \
-( info -> sid_data.cu_type  ct ) && ( info -> sid_data.cu_model cm ) && \
-( info -> sid_data.dev_type dt ) && ( info -> sid_data.dev_model dm ) )
+(( info -> sid_data.cu_type  ct ) && ( info -> sid_data.cu_model cm )) && \
+(( info -> sid_data.dev_type dt ) && ( info -> sid_data.dev_model dm )) )
 
 /* Prototypes for the functions called from external */
 static ssize_t dasd_read (struct file *, char *, size_t, loff_t *);
@@ -344,14 +344,12 @@
 	dasd_blks[minor] = dasd_info[di]->sizes.kbytes;
 	dasd_secsize[minor] = dasd_info[di]->sizes.bp_sector;
 	dasd_blksize[minor] = dasd_info[di]->sizes.bp_block;
-	dasd_maxsecs[minor] = 
-                ((PAGE_SIZE/sizeof(ccw1_t))-4)<<dasd_info[di]->sizes.s2b_shift;
+	dasd_maxsecs[minor] = 252<<dasd_info[di]->sizes.s2b_shift;
 	dasd_blks[minor + 1] = dasd_info[di]->sizes.kbytes -
 	    (dasd_info[di]->sizes.first_sector >> 1);
 	dasd_secsize[minor + 1] = dasd_info[di]->sizes.bp_sector;
 	dasd_blksize[minor + 1] = dasd_info[di]->sizes.bp_block;
-	dasd_maxsecs[minor+1] = 
-                ((PAGE_SIZE/sizeof(ccw1_t))-4)<<dasd_info[di]->sizes.s2b_shift;
+	dasd_maxsecs[minor+1] = 252<<dasd_info[di]->sizes.s2b_shift;
 }
 
 int
@@ -554,6 +552,7 @@
 	FUNCTION_ENTRY ("check_type");
 #ifdef CONFIG_DASD_ECKD
 	if (MATCH (info, == 0x3990, ||1, == 0x3390, ||1) ||
+	    MATCH (info, == 0x9343, ||1, == 0x9345, ||1) ||
 	    MATCH (info, == 0x3990, ||1, == 0x3380, ||1)) {
 		type = dasd_eckd;
 	} else
@@ -695,6 +694,8 @@
 	int retries = DASD_SSCH_RETRIES;
 	int di, irq;
 
+	dasd_debug (cqr);	/* cqr */
+
 	if (!cqr) {
 		PRINT_WARN ("(start_IO) no cqr passed\n");
 		return -EINVAL;
@@ -773,7 +774,7 @@
 {
 	int sl, sct;
 	printk (KERN_INFO PRINTK_HEADER
-		"-------------------I/O Error-----------------------------\n");
+		"-------------------I/O resulted in unit check:-----------\n");
 	for (sl = 0; sl < 4; sl++) {
 		printk (KERN_INFO PRINTK_HEADER "Sense:");
 		for (sct = 0; sct < 8; sct++) {
@@ -790,17 +791,17 @@
 	dasd_chanq_t *qp = NULL;
 	cqr_t *cqr;
         long flags;
-        int irq,di;
+        int irq;
         int tasks;
 	atomic_set (&bh_scheduled, 0);
-	dasd_debug (0x44445f69);	/* DD_i */
+	dasd_debug (0xc4c40000);	/* DD */
 	while ((tasks = atomic_read(&chanq_tasks)) != 0) {
 /* initialization and wraparound */
 		if (qp == NULL) {
-			dasd_debug (0x44445f68);        /* DD_h */
+			dasd_debug (0xc4c46df0);        /* DD_0 */
 			qp = cq_head;
 			if (!qp) {
-                          dasd_debug (0x44445f45);        /* DD_E */
+                          dasd_debug (0xc4c46ff1);        /* DD?1 */
                           dasd_debug (tasks);      
                           PRINT_ERR("Mismatch of NULL queue pointer and "
                                     "still %d chanq_tasks to do!!\n"
@@ -810,18 +811,9 @@
                           break;
 			}
 		}
-/* Get the irq number: Ouch, FIXME!!!!! */
-#if 0
-                di =(((unsigned long)qp)-
-                     ((unsigned long)&(dasd_info[0]->queue)))
-                        / sizeof(dasd_information_t);
-                dasd_debug(di);
-                irq = dasd_info[di]->info.irq;
-                dasd_debug(irq);
-#endif
 /* Get first request */
+		dasd_debug (qp);        /* qp */
 		cqr = (cqr_t *) (qp->head);
-		dasd_debug ((unsigned long) cqr);	/* cqr */
 /* empty queue -> dequeue and proceed */
 		if (!cqr) {
 			dasd_chanq_t *nqp = qp->next_q;
@@ -832,33 +824,35 @@
 /* process all requests on that queue */
 		do {
 			cqr_t *next;
-			dasd_debug (0x44445f64);	/* DD_d */
 			dasd_debug ((unsigned long) cqr);	/* cqr */
 			if (cqr->magic != DASD_MAGIC) {
-				dasd_debug (0x44445f65);	/* DD_e */
-				PRINT_WARN ("do_cq:magic mismatch %p\n", cqr);
+				dasd_debug (0xc4c46ff2);	/* DD?2 */
+				panic ( PRINTK_HEADER "do_cq:"
+					"magic mismatch %p -> %x\n", 
+					cqr, cqr -> magic);
                                 break;
 			}
                         irq = dasd_info[cqr->devindex]->info.irq;
                         s390irq_spin_lock_irqsave (irq, flags);
 			switch (atomic_read (&cqr->status)) {
 			case CQR_STATUS_IN_IO:
-                                dasd_debug (0x44445f48);	/* DD_I */
+                                dasd_debug (0xc4c4c9d6);	/* DDIO */
                                 cqr = NULL;
                                 break;
 			case CQR_STATUS_QUEUED:
-                                dasd_debug (0x44445f53);	/* DD_S */
+                                dasd_debug (0xc4c4e2e3);	/* DDST */
                                 if (dasd_start_IO (cqr) == 0) {
                                         atomic_dec (&chanq_tasks);
                                         cqr = NULL;
                                 }
                                 break;
 			case CQR_STATUS_ERROR:
-                                dasd_debug (0x44445f54);	/* DD_E */
+                                dasd_debug (0xc4c4c5d9);	/* DDER */
                                 dasd_dump_sense (cqr->dstat);
-                                if (cqr->retries++ < 5) {
+                                if ( ++ cqr->retries  < 2 ) {
                                         atomic_set (&cqr->status,
                                                     CQR_STATUS_QUEUED);
+	                                dasd_debug (0xc4c4e2e3); /* DDST */
                                         if (dasd_start_IO (cqr) == 0) {
                                                 atomic_dec (&chanq_tasks);
                                                 cqr = NULL;
@@ -870,14 +864,14 @@
                                 break;
 			case CQR_STATUS_DONE:
                                 next = cqr->next;
-                                dasd_debug (0x44445f44);	/* DD_D */
+                                dasd_debug (0xc4c49692);	/* DDok */
                                 dasd_end_cqr (cqr, 1);
                                 atomic_dec (&chanq_tasks);
                                 cqr = next;
                                 break;
 			case CQR_STATUS_FAILED:
                                 next = cqr->next;
-                                dasd_debug (0x44445f45);	/* DD_F */
+                                dasd_debug (0xc4c47a7a);	/* DD:: */
                                 dasd_end_cqr (cqr, 0);
                                 atomic_dec (&chanq_tasks);
                                 cqr = next;
@@ -893,7 +887,7 @@
 	spin_lock (&io_request_lock);
 	do_dasd_request ();
 	spin_unlock (&io_request_lock);
-	dasd_debug (0x44445f6f);	/* DD_o */
+	dasd_debug (0xc4c46d6d);	/* DD__ */
 }
 
 /* 
@@ -901,6 +895,9 @@
    We use it to feed the chanqs.
    This implementation assumes we are serialized by the io_request_lock.
  */
+
+#define QUEUE_THRESHOLD 5
+
 void
 do_dasd_request (void)
 {
@@ -916,23 +913,25 @@
 	long flags;
         int irq;
         
-	__asm__ ("lr %0,14":"=d" (caller)); 
-	dasd_debug (0x44525f69);	/* DR_i */
-	dasd_debug ((unsigned long) caller);	/* calleraddres */
+	dasd_debug (0xc4d90000);	/* DR */
+	dasd_debug (__builtin_return_address(0));	/* calleraddres */
 	prev = NULL;
 	for (req = CURRENT; req != NULL; req = next) {
 		next = req->next;
 		di = DEVICE_NR (req->rq_dev);
 		dasd_debug ((unsigned long) req);	/* req */
-		dasd_debug (0x44520000 +	/* DR## */
-                            ((((di/16)<9?(di/16)+'0':(di/16)+'a'))<<8) +
-                            (((di%16)<9?(di%16)+'0':(di%16)+'a')));
+		dasd_debug (0xc4d90000 +	/* DR## */
+                            ((((di/16)<9?(di/16)+0xf0:(di/16)+0xc1))<<8) +
+                            (((di%16)<9?(di%16)+0xf0:(di%16)+0xc1)));
                 irq = dasd_info[di]->info.irq;
                 s390irq_spin_lock_irqsave (irq, flags);
                 q = &dasd_info[di]->queue;
                 busy[di] = busy[di]||(atomic_read(&q->flags)&DASD_CHANQ_BUSY);
                 if ( !busy[di] ||
                      ((!broken[di]) && (req->nr_sectors >= QUEUE_SECTORS))) {
+#if 0
+			if ( q -> queued_requests < QUEUE_THRESHOLD ) {
+#endif
                         if (prev) {
                                 prev->next = next;
                         } else {
@@ -940,39 +939,41 @@
                         }
 			req->next = NULL;
 			if (req == &blk_dev[MAJOR_NR].plug) {
-				dasd_debug (0x44525f75);	/* DR_u */
+					dasd_debug (0xc4d99787); /* DRpg */
 				goto cont;
 			}
 			cqr = dasd_cqr_from_req (req);
 			if (!cqr) {
-				dasd_debug (0x44525f65);	/* DR_e */
+					dasd_debug (0xc4d96ff1); /* DR?1 */
 				dasd_end_request (req, 0);
 				goto cont;
                         }
-                        dasd_debug (0x44525f71);	/* DR_q */
                         dasd_debug ((unsigned long) cqr);	/* cqr */
                         dasd_chanq_enq (q, cqr);
-                        if (!(atomic_read (&q->flags) & DASD_CHANQ_ACTIVE)) {
+                	        if (!(atomic_read (&q->flags) & 
+					DASD_CHANQ_ACTIVE)) {
                                 cql_enq_head (q);
                         }
                         if (!busy[di]) {
-                                if (dasd_start_IO (cqr) == 0)
-                                        dasd_debug (0x44525f73); /* DR_s */
-                                else {
+                        	        dasd_debug (0xc4d9e2e3); /* DRST */
+	                                if (dasd_start_IO (cqr) != 0) {
                                         atomic_inc (&chanq_tasks);
 					schedule_bh (dasd_do_chanq);
                                         busy[di] = 1;
                                 }
                         }
+#if 0
+			}
+#endif
                 } else {
-                        dasd_debug (0x44525f62);	/* DR_b */
+                        dasd_debug (0xc4d9c2d9);	/* DRBR */
                         broken[di] = 1;
 			prev = req;
 		}
         cont:
                 s390irq_spin_unlock_irqrestore (irq, flags);
 	}
-	dasd_debug (0x44525f6f);	/* DR_o */
+	dasd_debug (0xc4d96d6d);	/* DR__ */
 }
 
 void
@@ -983,34 +984,35 @@
 	cqr_t *cqr;
 	int done_fast_io = 0;
 
-	dasd_debug (0x44485f69);	/* DH_i */
+	dasd_debug (0xc4c80000);	/* DH */
 	if (!stat)
 		PRINT_ERR ("handler called without devstat");
 	ip = stat->intparm;
 	dasd_debug (ip);	/* intparm */
 	switch (ip) {		/* filter special intparms... */
 	case 0x00000000:	/* no intparm: unsolicited interrupt */
-		dasd_debug (0x44485f30);	/* DH_0 */
+		dasd_debug (0xc4c8a489);	/* DHui */
 		PRINT_INFO ("Unsolicited interrupt on device %04X\n",
 			    stat->devno);
 		dasd_dump_sense (stat);
 		return;
 	default:
 		if (ip & 0x80000001) {
+			dasd_debug (0xc4c8a489);	/* DHui */
 			PRINT_INFO ("Spurious interrupt %08x on device %04X\n",
 				    ip, stat->devno);
 			return;
 		}
 		cqr = (cqr_t *) ip;
 		if (cqr->magic != DASD_MAGIC) {
-			dasd_debug (0x44485f65);	/* DH_e */
-			PRINT_WARN ("handler:magic mismatch on %p %08x\n",
+			dasd_debug (0xc4c86ff1);	/* DH?1 */
+			PRINT_ERR ("handler:magic mismatch on %p %08x\n",
 				    cqr, cqr->magic);
 			return;
 		}
 		asm volatile ("STCK %0":"=m" (cqr->stopclk));
 		if (stat->cstat == 0x00 && stat->dstat == 0x0c) {
-			dasd_debug (0x44486f6b);	/* DHok */
+			dasd_debug (0xc4c89692);	/* DHok */
 			if (atomic_compare_and_swap (CQR_STATUS_IN_IO,
 						     CQR_STATUS_DONE,
 						     &cqr->status)) {
@@ -1018,31 +1020,23 @@
 					    atomic_read (&cqr->status));
 			}
 			if (cqr->next) {
-				dasd_debug (0x44485f6e);	/* DH_n */
+				dasd_debug (0xc4c8e2e3);	/* DHST */
 				if (dasd_start_IO (cqr->next) == 0)
 					done_fast_io = 1;
 			}
  			break;
 		}
-		dasd_debug (0x44482121);	/* DH!! */
+		dasd_debug (0xc4c8c5d9);	/* DHER */
 		if (!cqr->dstat)
 			cqr->dstat = kmalloc (sizeof (devstat_t),
 					      GFP_ATOMIC);
 		if (cqr->dstat) {
 			memcpy (cqr->dstat, stat, sizeof (devstat_t));
-			dasd_dump_sense (cqr->dstat);
 		} else {
 			PRINT_ERR ("no memory for dtstat\n");
 		}
 		/* errorprocessing */
-		if (cqr->retries < DASD_MAX_RETRIES) {
-			dasd_debug (0x44485f72);	/* DH_r */
 			atomic_set (&cqr->status, CQR_STATUS_ERROR);
-		} else {
-			dasd_debug (0x44485f6e);	/* DH_f */
-			atomic_set (&cqr->status, CQR_STATUS_FAILED);
-		}
-
 	}
 	if (done_fast_io == 0)
 		atomic_clear_mask (DASD_CHANQ_BUSY,
@@ -1050,16 +1044,17 @@
 				   queue.flags);
         
 	if (cqr->flags & DASD_DO_IO_SLEEP) {
-		dasd_debug (0x44485f77);	/* DH_w */
+		dasd_debug (0xc4c8a6a4);	/* DHwu */
 		dasd_wakeup ();
 	} else if (! (cqr->options & DOIO_WAIT_FOR_INTERRUPT) ){
-                dasd_debug (0x44485f73);	/* DH_s */
+                dasd_debug (0xc4c8a293);	/* DHsl */
                 atomic_inc (&chanq_tasks);
                 schedule_bh (dasd_do_chanq);
 	} else {
+                dasd_debug (0x64686f6f);	/* DH_g */
                 dasd_debug (cqr->flags);	/* DH_g */
-                dasd_debug (0x44485f6f);	/* DH_g */
         }
+	dasd_debug (0xc4c86d6d);	/* DHwu */
 }
 
 static int
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/s390/block/dasd_ccwstuff.c linux.15p9/drivers/s390/block/dasd_ccwstuff.c
--- linux.vanilla/drivers/s390/block/dasd_ccwstuff.c	Tue Jan  4 21:18:53 2000
+++ linux.15p9/drivers/s390/block/dasd_ccwstuff.c	Thu Feb 17 13:35:21 2000
@@ -2,7 +2,7 @@
  * File...........: linux/drivers/s390/block/dasd_ccwstuff.c
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
- * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999
+ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  */
 
 #include <linux/stddef.h>
@@ -337,6 +337,7 @@
 		q->head = cqr;
 	cqr->next = NULL;
 	q->tail = cqr;
+	q->queued_requests ++;
 	if (atomic_compare_and_swap(CQR_STATUS_FILLED,
 				    CQR_STATUS_QUEUED,
 				    &cqr->status)) {
@@ -368,6 +369,7 @@
 			q->tail = prev;
 	}
 	cqr->next = NULL;
+	q->queued_requests --;
 	return release_cqr(cqr);
 }
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/s390/block/dasd_eckd.c linux.15p9/drivers/s390/block/dasd_eckd.c
--- linux.vanilla/drivers/s390/block/dasd_eckd.c	Tue Jan  4 21:18:53 2000
+++ linux.15p9/drivers/s390/block/dasd_eckd.c	Thu Feb 17 13:35:29 2000
@@ -2,7 +2,7 @@
  * File...........: linux/drivers/s390/block/dasd_eckd.c
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
- * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999
+ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  */
 
 #include <linux/stddef.h>
@@ -15,7 +15,7 @@
 #include <linux/malloc.h>
 #include <asm/io.h>
 
-#include "../../../arch/s390/kernel/irq.h"
+#include <asm/irq.h>
 
 #include "dasd_types.h"
 #include "dasd_ccwstuff.h"
@@ -347,17 +347,17 @@
 		unsigned int kl, unsigned int dl)
 {
 	int rpt = 0;
-	if (rdc->formula == 0x01) {
+	int dn;
+        switch ( rdc -> dev_type ) {
+	case 0x3380: 
 		if (kl)
 			return 1499 / (15 +
 				       7 + ceil_quot (kl + 12, 32) +
 				       ceil_quot (dl + 12, 32));
 		else
 			return 1499 / (15 + ceil_quot (dl + 12, 32));
-
-	}
-	if (rdc->formula == 0x02) {
-		int dn = ceil_quot (dl + 6, 232) + 1;
+	case 0x3390: 
+		dn = ceil_quot (dl + 6, 232) + 1;
 		if (kl) {
 			int kn = ceil_quot (kl + 6, 232) + 1;
 			return 1729 / (10 +
@@ -366,6 +366,16 @@
 		} else
 			return 1729 / (10 +
 				       9 + ceil_quot (dl + 6 * dn, 34));
+	case 0x9345: 
+	        dn = ceil_quot (dl + 6, 232) + 1;
+                if (kl) {
+                        int kn = ceil_quot (kl + 6, 232) + 1;
+                        return 1420 / (18 +
+                                       7 + ceil_quot (kl + 6 * kn, 34) +
+                                       ceil_quot (dl + 6 * dn, 34));
+                } else
+                        return 1420 / (18 +
+                                       7 + ceil_quot (dl + 6 * dn, 34));
 	}
 	return rpt;
 }
@@ -403,9 +413,11 @@
 	case DASD_ECKD_CCW_READ_CKD_MT:
 	case DASD_ECKD_CCW_READ_COUNT:
 		data->mask.perm = 0x1;
+                data->attributes.operation = 0x3; /* enable seq. caching */
 		break;
 	case DASD_ECKD_CCW_WRITE:
 	case DASD_ECKD_CCW_WRITE_MT:
+                data->attributes.operation = 0x3; /* enable seq. caching */
 		break;
 	case DASD_ECKD_CCW_WRITE_CKD:
 	case DASD_ECKD_CCW_WRITE_CKD_MT:
@@ -914,8 +926,11 @@
                 rc = dasd_start_IO ( rw_cp );
                 s390irq_spin_unlock_irqrestore (irq, flags);
                 retries --;
-	} while ( ( ( (cs=atomic_read(&rw_cp->status)) != CQR_STATUS_DONE) || 
-                    rc ) &&  retries );
+                cs = atomic_read(&rw_cp->status);
+		if ( cs != CQR_STATUS_DONE && retries == 5 ) {
+			dasd_eckd_print_error(rw_cp->dstat);
+		}
+	} while ( ( ( cs != CQR_STATUS_DONE) || rc ) &&  retries );
         if ( ( rc || cs != CQR_STATUS_DONE) ) {
                 if ( ( cs == CQR_STATUS_ERROR ) &&
                      ( rw_cp -> dstat -> ii.sense.data[1] == 0x08 ) ) {
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/s390/block/dasd_proc.c linux.15p9/drivers/s390/block/dasd_proc.c
--- linux.vanilla/drivers/s390/block/dasd_proc.c	Tue Jan  4 21:18:53 2000
+++ linux.15p9/drivers/s390/block/dasd_proc.c	Thu Feb 17 13:35:29 2000
@@ -92,11 +92,11 @@
 		if ( len >= PAGE_SIZE - 80 )
 			len += sprintf ( buf + len, "terminated...\n");
 		len += sprintf ( buf + len,
-				 "%04X %3d %5d /dev/dd%04X",
+				 "%04X %3d %5d /dev/dasd%c",
 				 dasd_info[i]->info.devno,
 				 DASD_MAJOR,
 				 i << PARTN_BITS,
-				 i );
+				 'a' + i );
                 if (info->flags == DASD_NOT_FORMATTED) {
 			len += sprintf ( buf + len, "    n/a");
 		} else {
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/s390/block/dasd_profile.c linux.15p9/drivers/s390/block/dasd_profile.c
--- linux.vanilla/drivers/s390/block/dasd_profile.c	Tue Jan  4 21:18:53 2000
+++ linux.15p9/drivers/s390/block/dasd_profile.c	Thu Feb 17 13:35:45 2000
@@ -167,15 +167,14 @@
 	dasd_debug_actual = (dasd_debug_entry *)
 		( (unsigned long) dasd_debug_area +
 		  ( ( (unsigned long)dasd_debug_actual -
-		      (unsigned long)dasd_debug_area ) % 1808 ) );
+		      (unsigned long)dasd_debug_area ) % PAGE_SIZE ) );
 	d = dasd_debug_actual ++;
 	spin_unlock_irqrestore(&debug_lock,flags);
 	/* write CPUID to lowest 12 bits of clock... */
-	__asm__ __volatile__ ( "STCK  %0\n"
-			       "ST    14,%1\n"
-			       :"=m" (d->u.clock),
-			       "=m" (d->caller_address));
+	__asm__ __volatile__ ( "STCK  %0"
+			       :"=m" (d->u.clock));
 	d->tag = tag;
+	d -> caller_address = __builtin_return_address(0);
 	d->u.s.cpu = smp_processor_id();
 }
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/s390/block/dasd_types.h linux.15p9/drivers/s390/block/dasd_types.h
--- linux.vanilla/drivers/s390/block/dasd_types.h	Tue Jan  4 21:18:53 2000
+++ linux.15p9/drivers/s390/block/dasd_types.h	Thu Feb 17 13:35:45 2000
@@ -1,10 +1,9 @@
-/* 456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.
- * IBM CONFIDENTIAL
+/*
  * File...........: linux/drivers/s390/block/dasd_types.h
  * Author.........: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  * Created........: 08/31/1999
  * Last Modified..: 09/29/1999
- * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999
+ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
 
  * List of Changes:
  - Initial Release as of 09/29/1999
@@ -26,7 +25,7 @@
 
 #include <linux/blkdev.h>
 
-#include "../../../arch/s390/kernel/irq.h"
+#include <asm/irq.h>
 
 #define CCW_DEFINE_EXTENT 0x63
 #define CCW_LOCATE_RECORD 0x43
@@ -65,9 +64,8 @@
 			unsigned char removable:1;
 			unsigned char shared:1;
 			unsigned char zero1:1;
-			unsigned char bam:1;
-			unsigned char hpsa:1;
-			unsigned char zeros:2;
+			unsigned char mam:1;
+			unsigned char zeros:3;
 		} __attribute__ ((packed)) bits;
 	} __attribute__ ((packed)) features;
 	__u8 dev_class;
@@ -76,7 +74,7 @@
 	__u32 blk_per_cycl;
 	__u32 blk_per_bound;
 	__u32 blk_bdsa;
-	__u32 blk_hpsa;
+	__u32 reserved0;
 	__u16 reserved1;
 	__u16 blk_ce;
 	__u32 reserved2;
@@ -248,7 +246,7 @@
 	volatile cqr_t *tail;
 	spinlock_t q_lock;	/* lock for queue operations */
 	spinlock_t f_lock;	/* lock for flag operations */
-	long lockflags;
+	int queued_requests;
 	atomic_t flags;
 	struct dasd_chanq_t *next_q;	/* pointer to next queue */
 } __attribute__ ((packed, aligned (16))) 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/s390/block/mdisk.c linux.15p9/drivers/s390/block/mdisk.c
--- linux.vanilla/drivers/s390/block/mdisk.c	Tue Jan  4 21:18:53 2000
+++ linux.15p9/drivers/s390/block/mdisk.c	Thu Feb 17 13:35:45 2000
@@ -3,7 +3,7 @@
  *    VM minidisk device driver.
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Hartmut Penner (hp@de.ibm.com)
  */
 
@@ -37,7 +37,7 @@
 #include <asm/io.h>                    /* virt_to_phys                     */
 
 	 /* Added statement HSM 12/03/99 */
-#include "../../../arch/s390/kernel/irq.h"
+#include <asm/irq.h>
 
 #define MAJOR_NR MDISK_MAJOR /* force definitions on in blk.h */
 
@@ -125,6 +125,7 @@
 		vdev = size = offset = 0;
 		if (!isxdigit(*cur)) goto syntax_error;
 		vdev = simple_strtoul(cur,&cur,16);
+		if (*cur != 0 && *cur != ',') { 
 		if (*cur++ != ':') goto syntax_error;
 		if (!isxdigit(*cur)) goto syntax_error;
 		size = simple_strtoul(cur,&cur,16);
@@ -139,6 +140,7 @@
 			}
 		}
 		if (*cur != ',' && *cur != 0) goto syntax_error;
+		} 
 		if (*cur == ',') cur++;
 		if (i >= MDISK_DEVS) {
 			printk(KERN_WARNING "mnd: too many devices\n");
@@ -159,6 +161,8 @@
 	return;
 }
 
+
+
 /*
  * Open and close
  */
@@ -298,6 +302,101 @@
 }
 
 /*
+ * The device characteristics function
+ */
+
+static __inline__ int
+dia210(void* devchar)
+{
+	int rc;
+
+	devchar = (void*) virt_to_phys(devchar);
+
+	asm volatile ("    lr    2,%1\n"
+		      "    .long 0x83200210\n"
+		      "    ipm   %0\n"
+		      "    srl   %0,28"
+		      : "=d" (rc)
+		      : "d" (devchar)
+		      : "2" );
+	return rc;
+}
+/*
+ * read the label of a minidisk and extract its characteristics
+ */
+
+static __inline__ int
+mdisk_read_label (mdisk_Dev *dev, int i)
+{
+	static mdisk_dev_char_t devchar;
+	static long label[1024];
+	int block, b;
+	int rc;
+	mdisk_bio_t *bio;
+
+	devchar.dev_nr = dev -> vdev;
+	devchar.rdc_len = sizeof(mdisk_dev_char_t);
+
+	if (dia210(&devchar) == 0) {
+		if (devchar.vdev_class == DEV_CLASS_FBA) {
+			block = 2;
+		}
+		else {
+			block = 3;
+		}
+		bio = dev->bio;
+		rc = mdisk_term_io(dev);
+		for (b=512;b<4097;b=b*2) {
+			rc = mdisk_init_io(dev, b, 0, 64);
+			if (rc > 4) {
+				continue;
+			}
+			memset(&bio[0], 0, sizeof(mdisk_bio_t));
+			bio[0].type = MDISK_READ_REQ;
+			bio[0].block_number = block;
+			bio[0].buffer = virt_to_phys(&label);
+			dev->nr_bhs = 1;
+			if (mdisk_rw_io_clustered(dev,
+			                          &bio[0],
+			                          1,
+			                          (unsigned long) dev,
+			                          MDISK_SYNC)
+			    == 0 ) {
+				if (label[0] != 0xc3d4e2f1) { /* CMS1 */
+					printk ( KERN_WARNING "mnd: %4lX "
+					         "is not CMS format\n",
+					         mdisk_setup_data.vdev[i]);
+					rc = mdisk_term_io(dev);
+					return 1;
+				}
+				if (label[13] == 0) {
+					printk ( KERN_WARNING "mnd: %4lX "
+		   		         "is not reserved\n",
+					         mdisk_setup_data.vdev[i]);
+					rc = mdisk_term_io(dev);
+					return 2;
+				}
+				mdisk_setup_data.size[i] =
+				   (label[7] - 1 - label[13]) *
+				   (label[3] >> 9) >> 1;
+				mdisk_setup_data.blksize[i] = label[3];
+				mdisk_setup_data.offset[i] = label[13] + 1;
+				rc = mdisk_term_io(dev);
+				return rc;
+			}
+			rc = mdisk_term_io(dev);
+		}
+		printk ( KERN_WARNING "mnd: Cannot read label of %4lX "
+			 "- is it formatted?\n",
+			 mdisk_setup_data.vdev[i]);
+		return 3;
+	}
+	return 4;
+}
+
+
+
+/*
  * Init of minidisk device
  */
 
@@ -365,11 +464,11 @@
 	iob->bio_list     = virt_to_phys(bio_array);
 	
 	rc = dia250(iob,RW_BIO);
-	rc = (rc == 8) ? 0 : rc;
 	return rc;
 }
 
 
+
 /*
  * this handles a clustered request in success case
  * all buffers are detach and marked uptodate to the kernel
@@ -507,7 +606,7 @@
 #else
 						 MDISK_ASYNC
 #endif
-			)) != 0 ) {
+			)) > 8 ) {
 			printk(KERN_WARNING "mnd%c: %s request failed rc %d"
 			       " sector %ld nr_sectors %ld \n",
 			       DEVICE_NR(CURRENT_DEV),
@@ -524,6 +623,9 @@
 #ifdef CONFIG_MDISK_SYNC
 		mdisk_end_request(dev->nr_bhs);
 #else
+		if (rc == 0)
+		        mdisk_end_request(dev->nr_bhs);
+		else
 		return;
 #endif	
 	}
@@ -627,8 +729,7 @@
 	max_sectors[MAJOR_NR]   = mdisk_maxsectors;
 	
 	for (i=0;i<MDISK_DEVS;i++) {
-		mdisk_sizes[i] = mdisk_setup_data.size[i];
-		if (mdisk_sizes[i] == 0) {
+		if (mdisk_setup_data.vdev[i] == 0) {
 			continue;
 		}
 		/* Added block HSM 12/03/99 */
@@ -636,7 +737,7 @@
 				 mdisk_handler, 0, "mnd",
 				 &(mdisk_devices[i].dev_status)) ){
 			printk ( KERN_WARNING "mnd: Cannot acquire I/O irq of"
-				 " %4X for paranoia reasons, skipping\n",
+				 " %4lX for paranoia reasons, skipping\n",
 				 mdisk_setup_data.vdev[i]);
 			continue;
 		}
@@ -647,6 +748,9 @@
 		dev->bio=mdisk_bio[i];
 		dev->iob=&mdisk_iob[i];
 		dev->vdev = mdisk_setup_data.vdev[i];
+
+		if ( mdisk_setup_data.size[i] == 0 )
+	 		rc = mdisk_read_label(dev, i);
 		dev->size = mdisk_setup_data.size[i] * 2; /* buffer 512 b */
 		dev->blksize = mdisk_setup_data.blksize[i]; 
 		dev->tqueue.routine = do_mdisk_bh;
@@ -658,6 +762,7 @@
 		  dev->blkmult==4?2:
 		  dev->blkmult==8?3:-1;
 
+		mdisk_sizes[i] = mdisk_setup_data.size[i];
 		mdisk_blksizes[i]  = mdisk_setup_data.blksize[i];
 		mdisk_hardsects[i] = mdisk_setup_data.blksize[i];
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/s390/block/mdisk.h linux.15p9/drivers/s390/block/mdisk.h
--- linux.vanilla/drivers/s390/block/mdisk.h	Tue Jan  4 21:18:53 2000
+++ linux.15p9/drivers/s390/block/mdisk.h	Thu Feb 17 13:35:45 2000
@@ -3,14 +3,14 @@
  *    VM minidisk device driver.
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Hartmut Penner (hp@de.ibm.com)
  */
 
 #include <linux/ioctl.h>
 #include <linux/types.h>
 
-#define MDISK_DEVS 4                   /* for disks                        */
+#define MDISK_DEVS 8                   /* for disks                        */
 #define MDISK_RAHEAD 8                 /* read ahead                       */
 #define MDISK_BLKSIZE 1024             /* 1k blocks                        */
 #define MDISK_HARDSECT 512             /* FIXME -- 512 byte blocks         */
@@ -25,8 +25,8 @@
 #define MDISK_WRITE_REQ 0x01                                                 
 #define MDISK_READ_REQ  0x02                                                   
 
-#define MDISK_SYNC      0x01
-#define MDISK_ASYNC     0x03
+#define MDISK_SYNC      0x00
+#define MDISK_ASYNC     0x02
 #define INIT_BIO        0x00
 #define RW_BIO          0x01
 #define TERM_BIO        0x02
@@ -67,5 +67,28 @@
         u32     interrupt_params;
         u32     spare3[5];
 } mdisk_rw_io_t;
+
+/*
+ * low level definitions for Diagnose 210
+ */
+
+#define DEV_CLASS_FBA   0x01
+
+/*
+ * Data structures for Diagnose 210
+ */
+
+typedef struct {
+        u16     dev_nr;
+        u16     rdc_len;
+        u8      vdev_class;
+        u8      vdev_type;
+        u8      vdev_status;
+        u8      vdev_flags;
+        u8      rdev_class;
+        u8      rdev_type;
+        u8      rdev_model;
+        u8      rdev_features;
+} mdisk_dev_char_t;
 
                                                                                
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/s390/char/con3215.c linux.15p9/drivers/s390/char/con3215.c
--- linux.vanilla/drivers/s390/char/con3215.c	Tue Jan  4 21:18:53 2000
+++ linux.15p9/drivers/s390/char/con3215.c	Thu Feb 17 13:36:12 2000
@@ -3,7 +3,7 @@
  *    3215 line mode terminal driver.
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  */
 
@@ -22,7 +22,7 @@
 #include <asm/uaccess.h>
 
 #include "../../../arch/s390/kernel/cpcmd.h"
-#include "../../../arch/s390/kernel/irq.h"
+#include <asm/irq.h>
 
 #define NR_3215		    1
 #define NR_3215_REQ	    (4*NR_3215)
@@ -42,14 +42,17 @@
 #define RAW3215_CLOSING	    32	      /* set while in close process */
 #define RAW3215_TIMER_RUNS  64	      /* set if the output delay timer is on */
 #define RAW3215_FLUSHING    128	      /* set to flush buffer (no delay) */
+#define RAW3215_BH_PENDING  256       /* indication for bh scheduling */
 
 struct _raw3215_info;		      /* forward declaration ... */
 
+int raw3215_condevice = -1;           /* preset console device */
+
 /*
  * Request types for a 3215 device
  */
 typedef enum {
-	RAW3215_READ, RAW3215_WRITE
+	RAW3215_FREE, RAW3215_READ, RAW3215_WRITE
 } raw3215_type;
 
 /*
@@ -97,6 +100,16 @@
 #define MIN(a,b)	((a) < (b) ? (a) : (b))
 #endif
 
+__initfunc(void con3215_setup(char *str, char *ints))
+{
+        int vdev;
+
+        vdev = simple_strtoul(str,&str,16);
+        if (vdev >= 0 && vdev < 65536)
+                raw3215_condevice = vdev;
+        return;
+}
+
 /*
  * Get a request structure from the free list
  */
@@ -117,6 +130,9 @@
 extern inline void raw3215_free_req(raw3215_req *req) {
 	unsigned long flags;
 
+        if (req->type == RAW3215_FREE)
+                return;         /* don't free a free request */
+        req->type = RAW3215_FREE;
 	spin_lock_irqsave(&raw3215_freelist_lock, flags);
 	req->next = raw3215_freelist;
 	raw3215_freelist = req;
@@ -196,12 +212,6 @@
 		ix = (ix + count) & (RAW3215_BUFFER_SIZE - 1);
 		ccw++;
 	}
-	if (ccw > req->ccws)
-		ccw[-1].flags |= 0x40;	/* use command chaining */
-	ccw->cmd_code = 0x03; /* nop at the end */
-	ccw->flags = 0x20;    /* ignore incorrect length */
-	ccw->cda = NULL;      /* no data address for nop */
-	ccw->count = 0;	      /* no count for nop */
 	return len;
 }
 
@@ -214,14 +224,9 @@
 
 	ccw = req->ccws;
 	ccw->cmd_code = 0x0A; /* read inquiry */
-	ccw->flags = 0x60;    /* ignore incorrect length & command chaining */
+	ccw->flags = 0x20;    /* ignore incorrect length */
 	ccw->count = 160;
 	ccw->cda = (void *) virt_to_phys(raw->inbuf);
-	ccw++;
-	ccw->cmd_code = 0x03; /* nop at the end */
-	ccw->flags = 0x20;    /* ignore incorrect length ind. */
-	ccw->cda = NULL;      /* no data address for nop */
-	ccw->count = 0;	      /* no count for nop */
 }
 
 /*
@@ -323,6 +328,7 @@
 	raw = (raw3215_info *) data;
 	s390irq_spin_lock_irqsave(raw->irq, flags);
 	raw3215_try_io((raw3215_info *) data);
+        raw->flags &= ~RAW3215_BH_PENDING;
 	s390irq_spin_unlock_irqrestore(raw->irq, flags);
 	/* Check for pending message from raw3215_irq */
 	if (raw->message != NULL) {
@@ -340,6 +346,21 @@
 }
 
 /*
+ * Function to safely add raw3215_softint to tq_immediate.
+ * The s390irq spinlock must be held.
+ */
+static inline void raw3215_sched_bh(raw3215_info *raw)
+{
+        if (raw->flags & RAW3215_BH_PENDING)
+                return;       /* already pending */
+        raw->flags |= RAW3215_BH_PENDING;
+        raw->tqueue.routine = raw3215_softint;
+        raw->tqueue.data = raw;
+        queue_task(&raw->tqueue, &tq_immediate);
+        mark_bh(IMMEDIATE_BH);
+}
+
+/*
  * Find the raw3215_info structure associated with irq
  */
 static inline raw3215_info *raw3215_find_info(int irq) {
@@ -365,7 +386,7 @@
 	struct tty_struct *tty;
 	devstat_t *stat;
         int cstat, dstat;
-	int count;
+	int count, slen;
 
 	stat = (devstat_t *) int_parm;
 	req = (raw3215_req *) stat->intparm;
@@ -379,22 +400,11 @@
 				"(dev %i, dev sts 0x%2x, sch sts 0x%2x)";
 			raw->msg_dstat = dstat;
 			raw->msg_cstat = cstat;
-			queue_task(&raw->tqueue, &tq_immediate);
-			mark_bh(IMMEDIATE_BH);
+                        raw3215_sched_bh(raw);
 		}
 	}
         if (dstat & 0x01) { /* we got a unit exception */
-		raw = raw3215_find_info(irq);
-		if (raw != NULL) {
-                        raw->message = KERN_WARNING
-                                "Got a unit exception in raw3215_irq "
-                                "(dev %i, dev sts 0x%2x, sch sts 0x%2x)";
-                        raw->msg_dstat = dstat;
-                        raw->msg_cstat = cstat;
-                        queue_task(&raw->tqueue, &tq_immediate);
-                        mark_bh(IMMEDIATE_BH);
-		}
-		dstat &= ~0x01;
+		dstat &= ~0x01;  /* we can ignore it */
         }
 	switch (dstat) {
 	case 0x80:
@@ -407,8 +417,9 @@
 		req = raw3215_mk_read_req(raw);
 		raw3215_mk_read_ccw(raw, req);
 		raw->queued_read = req;
-		queue_task(&raw->tqueue, &tq_immediate);
-		mark_bh(IMMEDIATE_BH);
+                if (MACHINE_IS_P390)
+                        memset(raw->inbuf, 0, RAW3215_INBUF_SIZE);
+                raw3215_sched_bh(raw);
 		break;
 	case 0x08:
 	case 0x0C:
@@ -426,6 +437,11 @@
 		if (req->type == RAW3215_READ && raw->tty != NULL) {
 			tty = raw->tty;
 			count = 160 - req->residual;
+                        if (MACHINE_IS_P390) {
+                                slen = strnlen(raw->inbuf, RAW3215_INBUF_SIZE);
+                                if (count > slen)
+                                        count = slen;
+                        } else
 			if (count >= TTY_FLIPBUF_SIZE - tty->flip.count)
 				count = TTY_FLIPBUF_SIZE - tty->flip.count - 1;
 			EBCASC(raw->inbuf, count);
@@ -480,28 +496,26 @@
 			wake_up_interruptible(&raw->empty_wait);
 			raw->empty_wait = NULL;
 		}
-		queue_task(&raw->tqueue, &tq_immediate);
-		mark_bh(IMMEDIATE_BH);
+                raw3215_sched_bh(raw);
 		break;
 	default:
-		if (dstat & 0x04) {
 			/* Strange interrupt, I'll do my best to clean up */
-			if (req != NULL && req->info != NULL &&
-			    req->type == RAW3215_WRITE) {
-				req->info->count -= ((req->end - req->start) &
+                if ((raw = raw3215_find_info(irq)) == NULL)
+                        return;              /* That shouldn't happen ... */
+                if (raw == NULL) break;
+		if (req != NULL && req->type != RAW3215_FREE) {
+		        if (req->type == RAW3215_WRITE) 
+			        raw->count -= ((req->end - req->start) &
 					            (RAW3215_BUFFER_SIZE-1))+1;
+                        raw->flags &= ~RAW3215_WORKING;
+                        raw3215_free_req(req);
 			}
-		}
-		raw = raw3215_find_info(irq);
-		if (raw != NULL) {
 			raw->message = KERN_WARNING
 				"Spurious interrupt in in raw3215_irq "
 				"(dev %i, dev sts 0x%2x, sch sts 0x%2x)";
 			raw->msg_dstat = dstat;
 			raw->msg_cstat = cstat;
-			queue_task(&raw->tqueue, &tq_immediate);
-			mark_bh(IMMEDIATE_BH);
-		}
+                raw3215_sched_bh(raw);
 	}
 	return;
 }
@@ -687,19 +701,21 @@
 	int irq;
 	int count;
 
-	irq = 0;
+	irq = get_irq_first();
 	count = 0;
-	while (count <= number && get_dev_info(irq, &dinfo) != -ENODEV) {
-		if (dinfo.sid_data.cu_type == 0x3215)
+        while (count <= number && irq != -ENODEV) {
+                if (get_dev_info(irq, &dinfo) == -ENODEV)
+                        break;
+		if (dinfo.devno == raw3215_condevice ||
+                    dinfo.sid_data.cu_type == 0x3215) {
 			count++;
-		irq++;
-	}
-	if (count <= number)
-		irq = -1;     /* console not found */
-	else
-		irq--;
+                    if (count > number)
 	return irq;
 }
+                irq = get_irq_next(irq);
+        }
+        return -1;            /* console not found */
+}
 
 #ifdef CONFIG_3215_CONSOLE
 
@@ -710,7 +726,7 @@
 {
 	raw3215_info *raw;
 
-        if (!MACHINE_IS_VM)
+        if (!MACHINE_IS_VM && !MACHINE_IS_P390)
                 return 0;
 	raw = raw3215[0];  /* 3215 console is the first one */
 	if (raw->irq == -1) /* now console device found in con3215_init */
@@ -748,7 +764,7 @@
 
 	raw = raw3215[0];  /* console 3215 is the first one */
 	s390irq_spin_lock_irqsave(raw->irq, flags);
-	while (RAW3215_BUFFER_SIZE > raw->count) {
+	while (raw->count > 0) {
 		/* there might be a request pending */
 		raw->flags |= RAW3215_FLUSHING;
 		raw3215_try_io(raw);
@@ -761,7 +777,7 @@
 	s390irq_spin_unlock_irqrestore(raw->irq, flags);
 }
 
-__initfunc(static int con3215_setup(struct console *co, char *options))
+__initfunc(static int con3215_consetup(struct console *co, char *options))
 {
 	return 0;
 }
@@ -776,7 +792,7 @@
 	con3215_device,
 	NULL,
 	con3215_unblank,
-	con3215_setup,
+	con3215_consetup,
 	CON_PRINTBUFFER,
 	0,
 	0,
@@ -1008,12 +1024,14 @@
 	raw3215_req *req;
 	int i;
 
-	if (!MACHINE_IS_VM)
+	if (!MACHINE_IS_VM && !MACHINE_IS_P390)
                 return kmem_start;
+        if (MACHINE_IS_VM) {
 	cpcmd("TERM CONMODE 3215", NULL, 0);
 	cpcmd("TERM AUTOCR OFF", NULL, 0);
 	cpcmd("TERM HOLD OFF", NULL, 0);
 	cpcmd("TERM MORE 5 5", NULL, 0);
+        }
 
 	kmem_start = (kmem_start + 7) & -8L;
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/s390/char/hwc.h linux.15p9/drivers/s390/char/hwc.h
--- linux.vanilla/drivers/s390/char/hwc.h	Tue Jan  4 21:18:53 2000
+++ linux.15p9/drivers/s390/char/hwc.h	Thu Feb 17 13:38:35 2000
@@ -13,54 +13,53 @@
 #ifndef __HWC_H__
 #define __HWC_H__
 
-
 #define ET_OpCmd		0x01
 #define ET_Msg		0x02
 #define ET_StateChange	0x08
 #define ET_PMsgCmd		0x09
 #define ET_CntlProgOpCmd	0x20
 
-
 #define ET_OpCmd_Mask	0x80000000
 #define ET_Msg_Mask		0x40000000
 #define ET_StateChange_Mask	0x01000000
 #define ET_PMsgCmd_Mask	0x00800000
 #define ET_CtlProgOpCmd_Mask	0x00000001
 
-
 #define GMF_DOM		0x8000
 #define GMF_SndAlrm	0x4000
 #define GMF_HoldMsg	0x2000
 
-
 #define LTF_CntlText	0x8000
 #define LTF_LabelText	0x4000
 #define LTF_DataText	0x2000
 #define LTF_EndText	0x1000
 #define LTF_PromptText	0x0800
 
-
 #define HWC_COMMAND_INITIATED	0
 #define HWC_BUSY		2
 #define HWC_NOT_OPERATIONAL	3
 
-
 #define HWC_CMDW_READDATA 0x00770005
 
 #define HWC_CMDW_WRITEDATA 0x00760005
 
 #define HWC_CMDW_WRITEMASK 0x00780005
 
-
 #define GDS_ID_MDSMU		0x1310
+
 #define GDS_ID_MDSRouteInfo	0x1311
+
 #define GDS_ID_AgUnWrkCorr	0x1549
+
 #define GDS_ID_SNACondReport	0x1532
+
 #define GDS_ID_CPMSU		0x1212
+
 #define GDS_ID_RoutTargInstr	0x154D
+
 #define GDS_ID_OpReq		0x8070
-#define GDS_ID_TextCmd		0x1320
 
+#define GDS_ID_TextCmd		0x1320
 
 #define GDS_KEY_SelfDefTextMsg	0x31
 
@@ -76,9 +75,9 @@
 
 typedef struct {
 	_EBUF_HEADER
-} __attribute__((packed))	evbuf_t;
-
+} __attribute__ ((packed)) 
 
+evbuf_t;
 
 #define _MDB_HEADER	u16	length; \
 			u16	type; \
@@ -106,32 +105,45 @@
 
 typedef struct {
 	_GO_HEADER
-} __attribute__((packed))	go_t;
+} __attribute__ ((packed)) 
+
+go_t;
 
 typedef	struct {
 	go_t	go;
-} __attribute__((packed))	mdb_body_t;
+} __attribute__ ((packed)) 
+
+mdb_body_t;
 
 typedef struct {
 	_MDB_HEADER
 	mdb_body_t	mdb_body;
-} __attribute__((packed))	mdb_t;
+} __attribute__ ((packed)) 
+
+mdb_t;
 
 typedef struct {
 	_EBUF_HEADER
 	mdb_t		mdb;
-} __attribute__((packed))	msgbuf_t;
+} __attribute__ ((packed)) 
+
+msgbuf_t;
 
 typedef struct {
 	_HWCB_HEADER
 	msgbuf_t	msgbuf;
-} __attribute__((packed))	write_hwcb_t;
+} __attribute__ ((packed)) 
+
+write_hwcb_t;
 
 typedef struct {
 	_MTO_HEADER
-} __attribute__((packed))	mto_t;
+} __attribute__ ((packed)) 
+
+mto_t;
 
-static write_hwcb_t write_hwcb_template = {
+static write_hwcb_t write_hwcb_template =
+{
 	sizeof(write_hwcb_t),				
 	0x00,						
 	{
@@ -154,20 +166,21 @@
 				{ 	
 					sizeof(go_t),	
 					0x0001
+
 				}
 			}
 		}
 	}
 };
 
-static mto_t mto_template = {
+static mto_t mto_template =
+{
 	sizeof(mto_t),
 	0x0004,
 	LTF_EndText,	
 	0x00			
 };
 
- 
 typedef u32 _hwcb_mask_t;
 
 typedef struct {
@@ -178,9 +191,12 @@
 	_hwcb_mask_t	cp_send_mask;
 	_hwcb_mask_t	hwc_receive_mask;
 	_hwcb_mask_t	hwc_send_mask;
-} __attribute__((packed))	init_hwcb_t;
+} __attribute__ ((packed)) 
+
+init_hwcb_t;
 
-static init_hwcb_t init_hwcb_template = {
+static init_hwcb_t init_hwcb_template =
+{
 	sizeof(init_hwcb_t),
 	0x00,
 	{
@@ -195,7 +211,6 @@
 	ET_Msg_Mask
 };
 
-
 #define _GDS_VECTOR_HEADER	u16	length; \
 				u16	gds_id;
 
@@ -204,17 +219,24 @@
 
 typedef struct {
 	_GDS_VECTOR_HEADER
-} __attribute__((packed))	gds_vector_t;
+} __attribute__ ((packed)) 
+
+gds_vector_t;
 
 typedef struct {
 	_GDS_SUBVECTOR_HEADER
-} __attribute__((packed))	gds_subvector_t;
+} __attribute__ ((packed)) 
+
+gds_subvector_t;
 
 typedef struct {
 	_HWCB_HEADER
-} __attribute__((packed))	read_hwcb_t;
+} __attribute__ ((packed)) 
+
+read_hwcb_t;
 
-static read_hwcb_t read_hwcb_template = {
+static read_hwcb_t read_hwcb_template =
+{
 	PAGE_SIZE,
 	0x00,		
 	{
@@ -225,4 +247,3 @@
 };
 
 #endif   /* __HWC_H__ */ 
-
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/s390/char/hwc_con.c linux.15p9/drivers/s390/char/hwc_con.c
--- linux.vanilla/drivers/s390/char/hwc_con.c	Tue Jan  4 21:18:53 2000
+++ linux.15p9/drivers/s390/char/hwc_con.c	Thu Feb 17 13:39:22 2000
@@ -20,7 +20,6 @@
 
 extern void hwc_tty_init(void);
 
-
 #ifdef CONFIG_HWC_CONSOLE
 
 #define  hwc_console_major 4 
@@ -32,7 +31,9 @@
 
 #define  HWC_CON_PRINT_HEADER "hwc console driver: "
 
-struct console hwc_console = {
+struct console hwc_console =
+{
+
 	hwc_console_name,
 	hwc_console_write,
 	NULL,
@@ -46,13 +47,15 @@
 	NULL
 };
  
-void hwc_console_write(
+void 
+hwc_console_write (
 	struct console *console,
 	const char *message,
 	unsigned int count)
 {
-	if (console->device(console) != hwc_console.device(&hwc_console)) 
-	{
+
+	if (console->device (console) != hwc_console.device (&hwc_console)) {
+
 		hwc_printk(KERN_WARNING HWC_CON_PRINT_HEADER
 				"hwc_console_write() called with wrong "
 				"device number");
@@ -61,8 +64,8 @@
 	hwc_write(0, message, count);
 }
 
-
-kdev_t hwc_console_device(struct console *c)
+kdev_t 
+hwc_console_device (struct console * c)
 {
 	return  MKDEV(hwc_console_major, hwc_console_minor);
 }
@@ -76,12 +79,19 @@
         if (MACHINE_IS_VM)
                 return kmem_start;
 #endif
+	if (MACHINE_IS_P390)
+		return kmem_start;
+
 	if (hwc_init(&kmem_start) == 0) {
+
 #ifdef CONFIG_HWC_CONSOLE
+
 		register_console(&hwc_console);
 #endif	
+
 		hwc_tty_init();
-	}
-	else panic(HWC_CON_PRINT_HEADER "hwc initialisation failed !");
+	} else
+		panic (HWC_CON_PRINT_HEADER "hwc initialisation failed !");
+
 	return kmem_start;
 }
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/s390/char/hwc_rw.c linux.15p9/drivers/s390/char/hwc_rw.c
--- linux.vanilla/drivers/s390/char/hwc_rw.c	Tue Jan  4 21:18:53 2000
+++ linux.15p9/drivers/s390/char/hwc_rw.c	Thu Feb 17 13:38:52 2000
@@ -32,14 +32,21 @@
 #endif
 
 #define HWC_RW_PRINT_HEADER "hwc low level driver: "
+
 #define  USE_VM_DETECTION
+
 #define  DEFAULT_CASE_DELIMITER '%'
 
 #define DUMP_HWC_INIT_ERROR
+
 #define DUMP_HWC_WRITE_ERROR
+
 #define DUMP_HWC_WRITE_LIST_ERROR
+
 #define DUMP_HWC_READ_ERROR
+
 #undef DUMP_HWCB_INPUT
+
 #undef BUFFER_STRESS_TEST
 
 typedef struct {
@@ -49,9 +56,12 @@
 	unsigned char times_lost;
 	unsigned short int mto_number_lost;
 	unsigned long int mto_char_sum_lost;
-} __attribute__((packed))	hwcb_list_t;
+} __attribute__ ((packed)) 
+
+hwcb_list_t;
 
 #define MAX_HWCB_ROOM (PAGE_SIZE - sizeof(hwcb_list_t))
+
 #define MAX_MESSAGE_SIZE (MAX_HWCB_ROOM - sizeof(write_hwcb_t))
 
 #define BUF_HWCB hwc_data.hwcb_list_tail
@@ -60,24 +70,40 @@
 #define ALL_HWCB_CHAR hwc_data.mto_char_sum
 
 #define _LIST(hwcb) ((hwcb_list_t*)(&(hwcb)[PAGE_SIZE-sizeof(hwcb_list_t)]))
+
 #define _HWCB_CHAR(hwcb) (_LIST(hwcb)->mto_char_sum)
+
 #define _HWCB_MTO(hwcb) (_LIST(hwcb)->mto_number)
+
 #define _HWCB_CHAR_LOST(hwcb) (_LIST(hwcb)->mto_char_sum_lost)
+
 #define _HWCB_MTO_LOST(hwcb) (_LIST(hwcb)->mto_number_lost)
+
 #define _HWCB_TIMES_LOST(hwcb) (_LIST(hwcb)->times_lost)
+
 #define _HWCB_NEXT(hwcb) (_LIST(hwcb)->next)
+
 #define BUF_HWCB_CHAR _HWCB_CHAR(BUF_HWCB)
+
 #define BUF_HWCB_MTO _HWCB_MTO(BUF_HWCB)
+
 #define BUF_HWCB_NEXT _HWCB_NEXT(BUF_HWCB)
+
 #define OUT_HWCB_CHAR _HWCB_CHAR(OUT_HWCB)
+
 #define OUT_HWCB_MTO _HWCB_MTO(OUT_HWCB)
+
 #define OUT_HWCB_NEXT _HWCB_NEXT(OUT_HWCB)
+
 #define BUF_HWCB_CHAR_LOST _HWCB_CHAR_LOST(BUF_HWCB)
+
 #define BUF_HWCB_MTO_LOST _HWCB_MTO_LOST(BUF_HWCB)
+
 #define OUT_HWCB_CHAR_LOST _HWCB_CHAR_LOST(OUT_HWCB)
+
 #define OUT_HWCB_MTO_LOST _HWCB_MTO_LOST(OUT_HWCB)
-#define BUF_HWCB_TIMES_LOST _HWCB_TIMES_LOST(BUF_HWCB)
 
+#define BUF_HWCB_TIMES_LOST _HWCB_TIMES_LOST(BUF_HWCB)
 
 #include  "hwc.h"
 
@@ -93,36 +119,60 @@
 typedef u32 kmem_pages_t;
 
 #define MAX_KMEM_PAGES (sizeof(kmem_pages_t) << 3)
+
 #define HWC_TIMER_RUNS	1
 #define FLUSH_HWCBS	2
 
 static struct {
+
 	hwc_ioctls_t ioctls;
+
 	hwc_ioctls_t init_ioctls;
+
 	unsigned char *hwcb_list_head;
+
 	unsigned char *hwcb_list_tail;
+
 	unsigned short int mto_number;
+
 	unsigned int mto_char_sum;
+
 	unsigned char hwcb_count;
+
 	unsigned long kmem_start;
+
 	unsigned long kmem_end;
+
 	kmem_pages_t kmem_pages;
+
 	unsigned char *obuf;
+
 	unsigned short int obuf_cursor;
+
 	unsigned short int obuf_count;
+
 	unsigned short int obuf_start;
+
 	unsigned char *page;
+
 	u32 current_servc;
+
 	unsigned char *current_hwcb;
+
 	unsigned char write_nonprio:1;
 	unsigned char write_prio:1;
 	unsigned char read_nonprio:1;
 	unsigned char read_prio:1;
+
 	unsigned char flags;
+
 	spinlock_t lock;
+
 	struct timer_list write_timer;
-} hwc_data = {
-	{ },		
+} hwc_data =
+{
+	{
+	},
 	{		
 		8,		
 		0,		
@@ -131,8 +181,11 @@
 		1,		
 		50,		
 		MAX_KMEM_PAGES,	
+
 		0,		
+
 		0x6c		
+
 	},
 	NULL,		
 	NULL,		
@@ -154,6 +207,7 @@
 	0,		
 	0,		
 	0		
+
 };
 
 #define DELAYED_WRITE 0
@@ -164,8 +218,8 @@
 					unsigned char,
 					unsigned char);
 
-
-static asmlinkage int internal_print(char write_time, const char *fmt, ...)
+static asmlinkage int 
+internal_print (char write_time, const char *fmt,...)
 {
 	va_list args;
 	int i;
@@ -177,8 +231,8 @@
 	return do_hwc_write(0, buf, i, CODE_ASCII, write_time);
 }
 
-
-int hwc_printk(const char *fmt, ...)
+int 
+hwc_printk (const char *fmt,...)
 {
 	va_list args;
 	int i;
@@ -199,7 +253,8 @@
 	
 #ifdef DUMP_HWCB_INPUT
 
-static void dump_storage_area(unsigned char *area, unsigned short int count)
+static void 
+dump_storage_area (unsigned char *area, unsigned short int count)
 {
 	unsigned short int index;
 	ioctl_nl_t old_final_nl;
@@ -212,27 +267,28 @@
 	
 	internal_print(DELAYED_WRITE, "\n%8x   ", area);
 
-	
 	for (index = 0; index < count; index++) {
 		
 		if (area[index] <= 0xF)
 			internal_print(DELAYED_WRITE, "0%x", area[index]);
-		else	internal_print(DELAYED_WRITE, "%x", area[index]);
+		else
+			internal_print (DELAYED_WRITE, "%x", area[index]);
 		
 		if ((index & 0xF) == 0xF)
 			internal_print(DELAYED_WRITE, "\n%8x   ",
 						 &area[index + 1]);
 		else	if ((index & 3) == 3)
-				
 				internal_print(DELAYED_WRITE, " ");
 	}
 	
 	internal_print(IMMEDIATE_WRITE, "\n"); 
+
 	hwc_data.ioctls.final_nl = old_final_nl;
 }
 #endif	
 
-static inline u32 service_call(
+static inline u32 
+service_call (
 	u32 hwc_command_word,
 	unsigned char hwcb[])
 {
@@ -248,12 +304,12 @@
 	__asm__ __volatile__("IPM %0 \n\t"
 			     "SRL %0, 28 \n\t"
 			     :"=r"(condition_code));
+
 	return condition_code;
 }
 
-
-
-static inline unsigned char * ext_int_param(void)
+static inline unsigned char *
+ext_int_param (void)
 {
 	u32 param;
 
@@ -263,7 +319,8 @@
 	return ((unsigned char *) param);
 }
 
-static int prepare_write_hwcb(void)
+static int 
+prepare_write_hwcb (void)
 {
 	write_hwcb_t *hwcb;
 
@@ -272,7 +329,9 @@
 	
 	BUF_HWCB_MTO = 0;
 	BUF_HWCB_CHAR = 0;
+
 	hwcb = (write_hwcb_t *) BUF_HWCB;
+
 	memcpy(hwcb, &write_hwcb_template, sizeof(write_hwcb_t));
 	
 	if (!hwc_data.write_nonprio && hwc_data.write_prio)
@@ -281,7 +340,8 @@
 	return 0;
 }
 
-static int sane_write_hwcb(void)
+static int 
+sane_write_hwcb (void)
 {
 	unsigned short int lost_msg;
 	unsigned int lost_char;
@@ -294,7 +354,9 @@
 		return -ENOMEM;
 	
 	if ((unsigned long)OUT_HWCB & 0xFFF) {
+
 		bad_addr = OUT_HWCB;
+
 #ifdef DUMP_HWC_WRITE_LIST_ERROR
 		__asm__("LHI 1,0xe30\n\t"
 			"LRA 2,0(0,%0) \n\t"
@@ -306,6 +368,7 @@
 		
 		hwc_data.kmem_pages = 0;
 		if ((unsigned long)BUF_HWCB & 0xFFF) {
+
 			lost_hwcb = hwc_data.hwcb_count;
 			lost_msg = ALL_HWCB_MTO;
 			lost_char = ALL_HWCB_CHAR;
@@ -316,6 +379,7 @@
 			ALL_HWCB_CHAR = 0;
 			hwc_data.hwcb_count = 0;
 		} else {
+
 			lost_hwcb = hwc_data.hwcb_count - 1;
 			lost_msg = ALL_HWCB_MTO - BUF_HWCB_MTO;
 			lost_char = ALL_HWCB_CHAR - BUF_HWCB_CHAR;
@@ -325,7 +389,6 @@
 			hwc_data.hwcb_count = 1;
 			page = (unsigned long) BUF_HWCB;
 			
-			
 			if (page >= hwc_data.kmem_start &&
 			    page < hwc_data.kmem_end) {
 				
@@ -350,7 +413,8 @@
 	return 0;
 }
 
-static int reuse_write_hwcb(void)
+static int 
+reuse_write_hwcb (void)
 {
 	int retval;
 
@@ -368,18 +432,28 @@
 #endif	
 	
 	if (hwc_data.current_hwcb == OUT_HWCB) {
+
 		if (hwc_data.hwcb_count > 2) {
+
 			BUF_HWCB_NEXT = OUT_HWCB_NEXT;
+
 			BUF_HWCB = OUT_HWCB_NEXT;
+
 			OUT_HWCB_NEXT = BUF_HWCB_NEXT;
+
 			BUF_HWCB_NEXT = NULL;
 		}
 	} else {
+
 		BUF_HWCB_NEXT = OUT_HWCB;
+
 		BUF_HWCB = OUT_HWCB;
+
 		OUT_HWCB = OUT_HWCB_NEXT;
+
 		BUF_HWCB_NEXT = NULL;
 	}
+
 	BUF_HWCB_TIMES_LOST += 1;
 	BUF_HWCB_CHAR_LOST += BUF_HWCB_CHAR;
 	BUF_HWCB_MTO_LOST += BUF_HWCB_MTO;
@@ -401,7 +475,8 @@
 			BUF_HWCB_TIMES_LOST,
 			BUF_HWCB_MTO_LOST,
 			BUF_HWCB_CHAR_LOST);
-	else	internal_print(
+	else
+		internal_print (
 			DELAYED_WRITE,
 			HWC_RW_PRINT_HEADER
 			"page allocation failed, "
@@ -417,7 +492,8 @@
 	return retval;
 }
 
-static int allocate_write_hwcb(void)
+static int 
+allocate_write_hwcb (void)
 {
 	unsigned char *page;
 	int page_nr;
@@ -427,10 +503,13 @@
 	
 	page_nr = find_first_zero_bit(&hwc_data.kmem_pages, MAX_KMEM_PAGES);
 	if (page_nr < hwc_data.ioctls.kmem_hwcb) {
+
 		page = (unsigned char *)
 				(hwc_data.kmem_start + (page_nr << 12));
 		set_bit(page_nr, &hwc_data.kmem_pages);
-	} else	page = (unsigned char *) __get_free_page(GFP_ATOMIC);
+	} else
+		page = (unsigned char *) __get_free_page (GFP_ATOMIC);
+
 	if (!page)
 		return -ENOMEM;
 
@@ -440,14 +519,19 @@
 		BUF_HWCB_NEXT = page;
 
 	BUF_HWCB = page;
+
 	BUF_HWCB_NEXT = NULL;
+
 	hwc_data.hwcb_count++;
+
 	prepare_write_hwcb();
+
 	BUF_HWCB_TIMES_LOST = 0;
 	BUF_HWCB_MTO_LOST = 0;
 	BUF_HWCB_CHAR_LOST = 0;
 
 #ifdef BUFFER_STRESS_TEST
+
 	internal_print(
 		DELAYED_WRITE,
 		"*** " HWC_RW_PRINT_HEADER
@@ -455,10 +539,12 @@
 		hwc_data.hwcb_count, page);
 
 #endif	
+
 	return 0;
 }
 
-static int release_write_hwcb(void)
+static int 
+release_write_hwcb (void)
 {
 	unsigned long page;
 	int page_nr;
@@ -467,6 +553,7 @@
                 return -ENODATA;
         
         if (hwc_data.hwcb_count == 1) {
+
                 prepare_write_hwcb();
                 
                 ALL_HWCB_CHAR = 0;
@@ -474,8 +561,7 @@
                 BUF_HWCB_TIMES_LOST = 0;
                 BUF_HWCB_MTO_LOST = 0;
                 BUF_HWCB_CHAR_LOST = 0;
-        }
-        else {  
+	} else {
                 page = (unsigned long) OUT_HWCB;
                 
                 ALL_HWCB_MTO -= OUT_HWCB_MTO;
@@ -486,13 +572,15 @@
                 
                 if (page >= hwc_data.kmem_start &&
                     page < hwc_data.kmem_end) {
+
 			memset((void *) page, 0, PAGE_SIZE);
+
                         page_nr = (int) ((page - hwc_data.kmem_start) >> 12);
                         clear_bit(page_nr, &hwc_data.kmem_pages);
-                }
-                else 
+		} else
                 	free_page(page);
 #ifdef BUFFER_STRESS_TEST
+
 	        internal_print(
 			DELAYED_WRITE,
 			"*** " HWC_RW_PRINT_HEADER
@@ -504,7 +592,8 @@
 	return 0;
 }
 
-static int add_mto(
+static int 
+add_mto (
 	unsigned char *message,
 	unsigned short int count)
 {
@@ -520,15 +609,20 @@
 		return -ENOMEM;
 
 	mto_size = sizeof(mto_t) + count;
+
 	hwcb = (write_hwcb_t *) BUF_HWCB;
 	
 	if ((MAX_HWCB_ROOM - hwcb->length) < mto_size)
 		return -ENOMEM;
 
 	mto = (mto_t *) (((unsigned long) hwcb) + hwcb->length);
+
 	memcpy(mto, &mto_template, sizeof(mto_t));
+
 	dest = (void *) (((unsigned long) mto) + sizeof(mto_t));
+
 	memcpy(dest, message, count);
+
 	mto->length += count;
 	
 	hwcb->length		+= mto_size;
@@ -543,7 +637,8 @@
 	return count;
 }
 
-static int write_event_data_1(void)
+static int 
+write_event_data_1 (void)
 {
 	unsigned short int condition_code;
 	int retval;
@@ -557,9 +652,12 @@
 	retval = sane_write_hwcb();
 	if (retval < 0)
 		return retval;
+
 	if (!OUT_HWCB_MTO)
 		return -ENODATA;
+
 	condition_code = service_call(HWC_CMDW_WRITEDATA, OUT_HWCB);
+
 #ifdef DUMP_HWC_WRITE_ERROR 
 	if (condition_code != HWC_COMMAND_INITIATED)
 		__asm__("LHI 1,0xe20\n\t"
@@ -570,6 +668,7 @@
 			:"a"(&condition_code), "a"(OUT_HWCB)
 			:"1", "2", "3");
 #endif	
+
 	switch (condition_code) {
 		case HWC_COMMAND_INITIATED :
 			hwc_data.current_servc = HWC_CMDW_WRITEDATA;
@@ -582,18 +681,23 @@
 		default :
 			retval = -EIO;
 	}
+
 	return retval;
 }
 
-static void flush_hwcbs(void)
+static void 
+flush_hwcbs (void)
 {
 	while (hwc_data.hwcb_count > 1)
 		release_write_hwcb();
+
 	release_write_hwcb();
+
 	hwc_data.flags &= ~FLUSH_HWCBS;
 }
 
-static int write_event_data_2(void)
+static int 
+write_event_data_2 (void)
 {
 	write_hwcb_t *hwcb;
 	int retval;
@@ -659,11 +763,12 @@
 			:"1", "2", "3", "4", "5");
 #endif	
 
-	
 	if (hwcb->response_code == 0x0020) {
+
 		retval = OUT_HWCB_CHAR;
 		release_write_hwcb();
-	} else retval = -EIO;	
+	} else
+		retval = -EIO;
 
 	hwc_data.current_servc = 0;
 	hwc_data.current_hwcb = NULL;
@@ -674,11 +779,14 @@
 	return retval;
 }
 
-static void do_put_line(
+static void 
+do_put_line (
 	unsigned char * message,
 	unsigned short count)
 {
+
 	if (add_mto(message, count) != count) {
+
 		if (allocate_write_hwcb() < 0)
 			reuse_write_hwcb();
 		
@@ -700,7 +808,8 @@
 	}
 }
 
-static void put_line(
+static void 
+put_line (
 	unsigned char * message,
 	unsigned short count)
 {
@@ -709,15 +818,18 @@
 		del_timer(&hwc_data.write_timer);
 		hwc_data.flags &= ~HWC_TIMER_RUNS;
 	}
-
 	hwc_data.obuf_start += count;
+
 	do_put_line(message, count);
+
 	hwc_data.obuf_start -= count;
 }
 
-static void set_alarm(void)
+static void 
+set_alarm (void)
 {
 	write_hwcb_t *hwcb;
+
 	if ((!BUF_HWCB) || (BUF_HWCB == hwc_data.current_hwcb))
 		allocate_write_hwcb();
 
@@ -725,7 +837,8 @@
 	hwcb->msgbuf.mdb.mdb_body.go.general_msg_flags |= GMF_SndAlrm;
 } 
 
-static void hwc_write_timeout(unsigned long data)
+static void 
+hwc_write_timeout (unsigned long data)
 {
 	unsigned long flags;
 	
@@ -735,14 +848,17 @@
 	if (hwc_data.obuf_count)
 		put_line(hwc_data.obuf, hwc_data.obuf_count);
 	hwc_data.obuf_start = 0;
+
 	hwc_data.obuf_cursor = 0;
 	hwc_data.obuf_count = 0;
 	
 	write_event_data_1(); 
+
 	spin_unlock_irqrestore(&hwc_data.lock, flags);
 }
 
-static int do_hwc_write(
+static int 
+do_hwc_write (
 	int from_user,
 	const unsigned char *msg,
 	unsigned int count,
@@ -769,27 +885,32 @@
 	}
 	
 	for (i_msg = 0; i_msg < count; i_msg++) {
+
 		if (from_user)
 			get_user(orig_ch, msg + i_msg);
 		else
 			orig_ch = msg[i_msg];
 		if (code == CODE_EBCDIC)
 			ch = _ebcasc[orig_ch];
-		else	ch = orig_ch;
+		else
+			ch = orig_ch;
 
 		processed_characters++;
 		
 		if ((obuf_cursor == obuf_columns) &&
+
 		    (ch != '\n') &&
+
 		    (ch != '\t')) {
 			put_line(&hwc_data.obuf[hwc_data.obuf_start],
 				 obuf_columns);
 			obuf_cursor = 0;
 			obuf_count = 0;
 		}
-		
 		switch (ch) {
+
 		   case '\n' :  
+
 			put_line(&hwc_data.obuf[hwc_data.obuf_start],
 				 obuf_count);
 			obuf_cursor = 0;
@@ -797,26 +918,30 @@
 			break;
 
 		   case '\a' :  
+
 			hwc_data.obuf_start += obuf_count;
 			set_alarm();
 			hwc_data.obuf_start -= obuf_count;
+
 			break;
 
 		   case '\t' :  
-			do
-			{			
+
+			do {
 				if (obuf_cursor < obuf_columns) {
 					hwc_data.obuf[hwc_data.obuf_start +
 								obuf_cursor]
 						= 0x20;  
 					obuf_cursor++;
-				}
-				else break;
+				} else
+					break;
 			} while (obuf_cursor % hwc_data.ioctls.width_htab);
+
 			break;
 
 		   case '\f' :  
 		   case '\v' :  
+
 			spaces = obuf_cursor;
 			put_line(&hwc_data.obuf[hwc_data.obuf_start],
 				 obuf_count);
@@ -827,18 +952,22 @@
 					= 0x20;  
 				spaces--;
 			}
+
 			break;
 
 		   case '\b' :  
+
 			if (obuf_cursor)
 				obuf_cursor--;
 			break;
 
 		   case '\r' :  
+
 			obuf_cursor = 0;
 			break;
 
 		   case 0x00 :  
+
 			put_line(&hwc_data.obuf[hwc_data.obuf_start],
 				 obuf_count);
 			obuf_cursor = 0;
@@ -846,6 +975,7 @@
 			goto out;
 
 		   default:  
+
 			if (isprint(ch))
 				hwc_data.obuf[hwc_data.obuf_start +
 						obuf_cursor++]
@@ -856,8 +986,8 @@
 			obuf_count = obuf_cursor;
 	}
 
-	
 	if (obuf_cursor) {
+
 		if (hwc_data.obuf_start ||
 		    (hwc_data.ioctls.final_nl == 0)) {
 			
@@ -865,15 +995,17 @@
 				 obuf_count);
 			obuf_cursor = 0;
 			obuf_count = 0;
-		}
-		else {
+		} else {
+
 			if (hwc_data.ioctls.final_nl > 0) {
+
 				if (hwc_data.flags & HWC_TIMER_RUNS) {
+
 					hwc_data.write_timer.expires =
 						jiffies +
 						hwc_data.ioctls.final_nl*HZ/10;
-				}
-				else {
+				} else {
+
 					init_timer(&hwc_data.write_timer);
 					hwc_data.write_timer.function =
 						hwc_write_timeout;
@@ -885,49 +1017,47 @@
 					add_timer(&hwc_data.write_timer);
 					hwc_data.flags |= HWC_TIMER_RUNS;
 				}
+			} else;
+
 			}
-			else ;	
-		}
-	}
-	else ;	
+	} else;
+
 out :
+
 	if (!hwc_data.obuf_start) {
 		hwc_data.obuf_cursor = obuf_cursor;
 		hwc_data.obuf_count = obuf_count;
 	}
-
 	if (write_time == IMMEDIATE_WRITE)
 		write_event_data_1();
 
 	return processed_characters;
 }
 
-
-
-
-
-signed int hwc_write(int from_user, const unsigned char *msg, unsigned int count)
+signed int 
+hwc_write (int from_user, const unsigned char *msg, unsigned int count)
 {
 	unsigned long flags;
 	int retval;
 	
 	spin_lock_irqsave(&hwc_data.lock, flags);
+
 	retval = do_hwc_write(from_user, msg, count, hwc_data.ioctls.code,
 							 IMMEDIATE_WRITE);
+
 	spin_unlock_irqrestore(&hwc_data.lock, flags);
+
 	return retval;
 }
 
-
-
-
-
-unsigned int hwc_chars_in_buffer(unsigned char flag)
+unsigned int 
+hwc_chars_in_buffer (unsigned char flag)
 {
 	unsigned short int number = 0;
 	unsigned long flags;
 
 	spin_lock_irqsave(&hwc_data.lock, flags);
+
 	if (flag & IN_HWCB)
 		number += ALL_HWCB_CHAR;
 	
@@ -935,10 +1065,12 @@
 		number += hwc_data.obuf_cursor;
 	
 	spin_unlock_irqrestore(&hwc_data.lock, flags);
+
 	return number;
 }
 
-static inline int nr_setbits(kmem_pages_t arg)
+static inline int 
+nr_setbits (kmem_pages_t arg)
 {
 	int i;
 	int nr = 0;
@@ -948,17 +1080,21 @@
 			nr++;
 		arg >>= 1;
 	}
+
 	return nr;
 }
 
-unsigned int hwc_write_room(unsigned char flag)
+unsigned int 
+hwc_write_room (unsigned char flag)
 {
 	unsigned int number = 0;
 	unsigned long flags;
 	write_hwcb_t *hwcb;
 	
 	spin_lock_irqsave(&hwc_data.lock, flags);
+
         if (flag & IN_HWCB) {
+
 		if (BUF_HWCB) {
 			hwcb = (write_hwcb_t *) BUF_HWCB;
                 	number += MAX_HWCB_ROOM - hwcb->length;
@@ -970,18 +1106,24 @@
 	}
         if (flag & IN_WRITE_BUF)
                 number += MAX_HWCB_ROOM - hwc_data.obuf_cursor;
+
 	spin_unlock_irqrestore(&hwc_data.lock, flags);
+
 	return number;
 }
 
-void hwc_flush_buffer(unsigned char flag)
+void 
+hwc_flush_buffer (unsigned char flag)
 {
 	unsigned long flags;
+
 	spin_lock_irqsave(&hwc_data.lock, flags);
+
 	if (flag & IN_HWCB) {
 		if (hwc_data.current_servc != HWC_CMDW_WRITEDATA)
 			flush_hwcbs();
-		else	hwc_data.flags |= FLUSH_HWCBS;
+		else
+			hwc_data.flags |= FLUSH_HWCBS;
 	}
 	if (flag & IN_WRITE_BUF) {
 		hwc_data.obuf_cursor = 0;	
@@ -990,37 +1132,56 @@
 	spin_unlock_irqrestore(&hwc_data.lock, flags);
 }
 
-unsigned short int seperate_cases(unsigned char *buf, unsigned short int count)
+unsigned short int 
+seperate_cases (unsigned char *buf, unsigned short int count)
 {
+
 	unsigned short int i_in;
+
 	unsigned short int i_out = 0;
+
 	unsigned char _case = 0;
 
 	for (i_in = 0; i_in < count; i_in++) {
+
 		if (buf[i_in] == hwc_data.ioctls.delim) {
+
 			if ((i_in + 1 < count) &&
 			    (buf[i_in + 1] == hwc_data.ioctls.delim)) {
+
 				buf[i_out] = hwc_data.ioctls.delim;
+
 				i_out++;
+
 				i_in++; 
-			} else	_case = ~_case;
+
+			} else
+				_case = ~_case;
+
 		} else {
+
 			if (_case) {
+
 				if (hwc_data.ioctls.tolower) 
 					buf[i_out] = _ebc_toupper[buf[i_in]];
-				else	buf[i_out] = _ebc_tolower[buf[i_in]];
-			} else	buf[i_out] = buf[i_in];
+
+				else
+					buf[i_out] = _ebc_tolower[buf[i_in]];
+
+			} else
+				buf[i_out] = buf[i_in];
+
 			i_out++;
 		}
 	}
+
 	return i_out;
 }
 
-
-
 #ifdef DUMP_HWCB_INPUT
 
-static int gds_vector_name(u16 id, unsigned char name[])
+static int 
+gds_vector_name (u16 id, unsigned char name[])
 {
 	int retval = 0;
 
@@ -1059,9 +1220,8 @@
 }
 #endif	
 
-
-
-inline static gds_vector_t * find_gds_vector(
+inline static gds_vector_t *
+find_gds_vector (
 	gds_vector_t *start, void *end, u16 id)
 {
 	gds_vector_t *vec;
@@ -1090,22 +1250,23 @@
 					IMMEDIATE_WRITE,
 					", id: 0x%x\n",
 					vec->gds_id);
-			else	internal_print(
+			else
+				internal_print (
 					IMMEDIATE_WRITE,
 					"\n");
 #endif	
+
 			retval = vec;
 			break;
 		}
-
 		vec = (gds_vector_t *) (((unsigned long) vec) + vec->length);
 	}
 
 	return retval;
 }
 
-
-inline static gds_subvector_t * find_gds_subvector(
+inline static gds_subvector_t *
+find_gds_subvector (
 	gds_subvector_t *start, void *end, u8 key)
 {
 	gds_subvector_t *subvec;
@@ -1121,11 +1282,12 @@
 		subvec = (gds_subvector_t *)
 				(((unsigned long) subvec) + subvec->length);
 	}
+
 	return retval;
 }
 
-
-inline static int get_input(void *start, void *end)
+inline static int 
+get_input (void *start, void *end)
 {
 	int count;
 
@@ -1133,18 +1295,23 @@
 
 	if (hwc_data.ioctls.tolower)
 		EBC_TOLOWER(start, count);
+
 	if (hwc_data.ioctls.delim)
 		count = seperate_cases(start, count);
+
 	if (hwc_data.ioctls.echo)
 		do_hwc_write(0, start, count, CODE_EBCDIC, IMMEDIATE_WRITE);
+
 	if (hwc_data.ioctls.code == CODE_ASCII)
 		EBCASC(start, count);
+
 	store_hwc_input(start, count);
+
 	return count;
 }
 
-
-inline static int eval_selfdeftextmsg(gds_subvector_t *start, void *end)
+inline static int 
+eval_selfdeftextmsg (gds_subvector_t * start, void *end)
 {
 	gds_subvector_t *subvec;
 	void *subvec_data;
@@ -1165,11 +1332,12 @@
 		retval += get_input(subvec_data, subvec_end);
 		subvec = (gds_subvector_t *) subvec_end;
 	}
+
 	return retval;
 }
 
-
-inline static int eval_textcmd(gds_subvector_t *start, void *end)
+inline static int 
+eval_textcmd (gds_subvector_t * start, void *end)
 {
 	gds_subvector_t *subvec;
 	gds_subvector_t *subvec_data;
@@ -1195,8 +1363,8 @@
 	return retval;
 }
 
-
-inline static int eval_cpmsu(gds_vector_t *start, void *end)
+inline static int 
+eval_cpmsu (gds_vector_t * start, void *end)
 {
 	gds_vector_t *vec;
 	gds_subvector_t *vec_data;
@@ -1219,8 +1387,8 @@
 	return retval;
 }
 
-
-inline static int eval_mdsmu(gds_vector_t *start, void *end)
+inline static int 
+eval_mdsmu (gds_vector_t * start, void *end)
 {
 	gds_vector_t *vec;
 	gds_vector_t *vec_data;
@@ -1234,12 +1402,11 @@
 		vec_end = (void *) (((unsigned long) vec) + vec->length);
 		retval = eval_cpmsu(vec_data, vec_end);
 	}
-
 	return retval;
 }
 
-
-inline static int eval_evbuf(gds_vector_t *start, void *end)
+inline static int 
+eval_evbuf (gds_vector_t * start, void *end)
 {
 	gds_vector_t *vec;
 	gds_vector_t *vec_data;
@@ -1253,12 +1420,11 @@
 		vec_end = (void *) (((unsigned long) vec) + vec->length);
 		retval = eval_mdsmu(vec_data, vec_end);
 	}
-
 	return retval;
 }
 
-
-static int process_evbufs(void *start, void *end)
+static int 
+process_evbufs (void *start, void *end)
 {
 	int retval = 0;
 	evbuf_t *evbuf;
@@ -1307,7 +1473,8 @@
 	return retval;
 }
 
-static int unconditional_read_1(void)
+static int 
+unconditional_read_1 (void)
 {
 	unsigned short int condition_code;
 	read_hwcb_t *hwcb = (read_hwcb_t *) hwc_data.page;
@@ -1315,6 +1482,7 @@
 	
 	if ((!hwc_data.read_prio) && (!hwc_data.read_nonprio))
 		return -EOPNOTSUPP;
+
 	if (hwc_data.current_servc)
 		return -EBUSY;
 	
@@ -1350,7 +1518,8 @@
 	return retval;
 }
 
-static int unconditional_read_2(void)
+static int 
+unconditional_read_2 (void)
 {
 	read_hwcb_t *hwcb = (read_hwcb_t *) hwc_data.page;
 
@@ -1372,14 +1541,17 @@
 	hwc_data.current_hwcb = NULL;
 
 	switch (hwcb->response_code) {
+
 	   case 0x0020 :
 	   case 0x0220 : 
 		return process_evbufs(
 			(void *) (((unsigned long) hwcb) + sizeof(read_hwcb_t)),
 			(void *) (((unsigned long) hwcb) + hwcb->length));
+
 	   case 0x60F0 :
 	   case 0x62F0 : 
 		return 0;
+
 	   case 0x0100 :
 		internal_print(
 			IMMEDIATE_WRITE,
@@ -1445,14 +1617,18 @@
 	}
 }
 
-static int write_event_mask_1(void)
+static int 
+write_event_mask_1 (void)
 {
 	unsigned int condition_code;
 	int retval;
 	
 	memcpy(hwc_data.page, &init_hwcb_template, sizeof(init_hwcb_t));
+
 	condition_code = service_call(HWC_CMDW_WRITEMASK, hwc_data.page);
+
 #ifdef DUMP_HWC_INIT_ERROR
+
 	if (condition_code != HWC_COMMAND_INITIATED)
 		__asm__("LHI 1,0xe10\n\t"
 			"L 2,0(0,%0)\n\t"
@@ -1475,19 +1651,16 @@
 		default :
 			retval = -EIO;
 	}
+
 	return retval;
 }
 
-
-
-
-
-static int write_event_mask_2(void)
+static int 
+write_event_mask_2 (void)
 {
 	init_hwcb_t *hwcb = (init_hwcb_t *) hwc_data.page;
 	int retval = 0;
 
-	
 	if (hwcb->hwc_receive_mask & ET_Msg_Mask)
 		hwc_data.write_nonprio = 1;
 	
@@ -1521,7 +1694,8 @@
 	return retval;
 }
 
-static int set_hwc_ioctls(hwc_ioctls_t *ioctls, char correct)
+static int 
+set_hwc_ioctls (hwc_ioctls_t * ioctls, char correct)
 {
 	int retval = 0;
 	hwc_ioctls_t tmp;
@@ -1529,17 +1703,20 @@
 	if (ioctls->width_htab > MAX_MESSAGE_SIZE) {
 		if (correct)
 			tmp.width_htab = MAX_MESSAGE_SIZE;
-		else	retval = -EINVAL;
-	} else	tmp.width_htab = ioctls->width_htab;
+		else
+			retval = -EINVAL;
+	} else
+		tmp.width_htab = ioctls->width_htab;
 
 	tmp.echo = ioctls->echo;
 	
 	if (ioctls->columns > MAX_MESSAGE_SIZE) {
 		if (correct)
 			tmp.columns = MAX_MESSAGE_SIZE;
-		else	retval = -EINVAL;
-	} else	tmp.columns = ioctls->columns;
-
+		else
+			retval = -EINVAL;
+	} else
+		tmp.columns = ioctls->columns;
 	
 	switch (ioctls->code) {
 		case CODE_EBCDIC :
@@ -1549,7 +1726,8 @@
 		default :
 			if (correct)
 				tmp.code = CODE_ASCII;
-			else	retval = -EINVAL;
+		else
+			retval = -EINVAL;
 	}
 				
 	tmp.final_nl = ioctls->final_nl;
@@ -1557,40 +1735,43 @@
 	if (ioctls->max_hwcb < 2) {
 		if (correct)
 			tmp.max_hwcb = 2;
-		else	retval = -EINVAL;
-	} else	tmp.max_hwcb = ioctls->max_hwcb;
+		else
+			retval = -EINVAL;
+	} else
+		tmp.max_hwcb = ioctls->max_hwcb;
 	
 	tmp.tolower = ioctls->tolower;
 	
 	if (ioctls->kmem_hwcb > ioctls->max_hwcb) {
 		if (correct)
 			tmp.kmem_hwcb = ioctls->max_hwcb;
-		else	retval = -EINVAL;
-	} else	tmp.kmem_hwcb = ioctls->kmem_hwcb;
-	
+		else
+			retval = -EINVAL;
+	} else
+		tmp.kmem_hwcb = ioctls->kmem_hwcb;
 	
 	if (ioctls->kmem_hwcb > MAX_KMEM_PAGES) {
 		if (correct)
 			ioctls->kmem_hwcb = MAX_KMEM_PAGES;
-		else	retval = -EINVAL;
+		else
+			retval = -EINVAL;
 	}
-	
 	if (ioctls->kmem_hwcb < 2) {
 		if (correct)
 			ioctls->kmem_hwcb = 2;
-		else	retval = -EINVAL;
+		else
+			retval = -EINVAL;
 	}
-	
 	tmp.delim = ioctls->delim;
 
-	
 	if (!(retval < 0))
 		hwc_data.ioctls = tmp;
 
 	return retval;
 }
 
-int hwc_init(unsigned long *kmem_start)
+int 
+hwc_init (unsigned long *kmem_start)
 {
 	int retval;
 #ifdef BUFFER_STRESS_TEST
@@ -1599,16 +1780,22 @@
 	int i;
 
 #endif
+
 #ifdef CONFIG_3215
         if (MACHINE_IS_VM)
                 return kmem_start;
 #endif
+
 	spin_lock_init(&hwc_data.lock);
+
 	retval = write_event_mask_1();
 	if (retval < 0)
 		return retval;
+
 #ifdef USE_VM_DETECTION
+
 	if (MACHINE_IS_VM) {
+
 		if (hwc_data.init_ioctls.columns > 76)
 			hwc_data.init_ioctls.columns = 76;
 		hwc_data.init_ioctls.tolower = 1;
@@ -1627,7 +1814,9 @@
 	hwc_data.kmem_end = *kmem_start - 1;
 
         ctl_set_bit(0, 9);
+
 #ifdef BUFFER_STRESS_TEST 
+
 	internal_print(
 		DELAYED_WRITE,
 		HWC_RW_PRINT_HEADER 
@@ -1644,36 +1833,50 @@
 	}
 
 #endif	
+
 	return retval;
 }
 
-void do_hwc_interrupt(void)
+void 
+do_hwc_interrupt (void)
 {
+
 	spin_lock(&hwc_data.lock);
+
 	if (!hwc_data.current_servc) {
+
 		unconditional_read_1();
+
 	} else {
+
 		switch (hwc_data.current_servc) {
+
 			case HWC_CMDW_WRITEMASK :
+
 				write_event_mask_2();
 				break;
 			
 			case HWC_CMDW_WRITEDATA :
+
 				write_event_data_2();
 				break;
 
 			case HWC_CMDW_READDATA :
+
 				unconditional_read_2();
 				break;
 		}		
+
 		write_event_data_1();
 	}
+
 	wake_up_hwc_tty();
+
 	spin_unlock(&hwc_data.lock);
 }
 
-
-int hwc_ioctl(unsigned int cmd, unsigned long arg)
+int 
+hwc_ioctl (unsigned int cmd, unsigned long arg)
 {
 	hwc_ioctls_t tmp = hwc_data.ioctls;
 	int retval = 0;
@@ -1683,6 +1886,7 @@
 	spin_lock_irqsave(&hwc_data.lock, flags);
 	
 	switch (cmd) {
+
 	   case TIOCHWCSHTAB :
 		if (get_user(tmp.width_htab, (ioctl_htab_t *) arg))
 			goto fault;
@@ -1714,10 +1918,10 @@
 			goto fault;
 		if (obuf & 0xFFF)
 			tmp.max_hwcb = (((obuf | 0xFFF) + 1) >> 12);
-		else	tmp.max_hwcb = (obuf >> 12);
+		else
+			tmp.max_hwcb = (obuf >> 12);
 		break;
 
-	   
 	   case TIOCHWCSCASE :
                 if (get_user(tmp.tolower, (ioctl_case_t *) arg))
 			goto fault;
@@ -1728,55 +1932,46 @@
 			goto fault;
 		break;
 
-	   
 	   case TIOCHWCSINIT :
 		retval = set_hwc_ioctls(&hwc_data.init_ioctls, 1);
 		break;
 
-	   
 	   case TIOCHWCGHTAB :
 		if (put_user(tmp.width_htab, (ioctl_htab_t *) arg))
 			goto fault;
 		break;
 
-	   
 	   case TIOCHWCGECHO :
                 if (put_user(tmp.echo, (ioctl_echo_t *) arg))
 			goto fault;
 		break;
 
-	   
 	   case TIOCHWCGCOLS :
                 if (put_user(tmp.columns, (ioctl_cols_t *) arg))
 			goto fault;
 		break;
 
-	   
 	   case TIOCHWCGCODE :
                 if (put_user(tmp.code, (ioctl_code_t *) arg))
 			goto fault;
 
 		break;
 
-	   
 	   case TIOCHWCGNL :
                 if (put_user(tmp.final_nl, (ioctl_nl_t *) arg))
 			goto fault;
 		break;
 
-	   
 	   case TIOCHWCGOBUF :
                 if (put_user(tmp.max_hwcb, (ioctl_obuf_t *) arg))
 			goto fault;
 		break;
 
-	   
 	   case TIOCHWCGKBUF :
                 if (put_user(tmp.kmem_hwcb, (ioctl_obuf_t *) arg))
 			goto fault;
 		break;
 
-	   
 	   case TIOCHWCGCASE :
                 if (put_user(tmp.tolower, (ioctl_case_t *) arg))
 			goto fault;
@@ -1793,7 +1988,6 @@
 			goto fault;
 		break;
 
-	   
 	   case TIOCHWCGCURR :
 		if (put_user(&hwc_data.ioctls, (hwc_ioctls_t *) arg))
 			goto fault;
@@ -1804,7 +1998,6 @@
 		goto noioctlcmd;
 	}
 
-	
 	if (_IOC_DIR(cmd) == _IOC_WRITE)
 		retval = set_hwc_ioctls(&tmp, 0);
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/s390/char/hwc_rw.h linux.15p9/drivers/s390/char/hwc_rw.h
--- linux.vanilla/drivers/s390/char/hwc_rw.h	Tue Jan  4 21:18:53 2000
+++ linux.15p9/drivers/s390/char/hwc_rw.h	Thu Feb 17 13:38:52 2000
@@ -10,115 +10,38 @@
 #ifndef __HWC_RW_H__
 #define __HWC_RW_H__
 
-
 #include <linux/ioctl.h>
 
-
-
-
-
-
-
 #ifndef __HWC_RW_C__
 
-
-
-
-
-
-
 extern int hwc_init(unsigned long *);
 
-
-
-
-
-
 extern int hwc_write(int from_user, const unsigned char *, unsigned int);
 
-
-
-
-
-
-
 extern unsigned int hwc_chars_in_buffer(unsigned char);
 
-
-
-
-
-
-
 extern unsigned int hwc_write_room(unsigned char);
 
-
-
-
-
-
-
 extern void hwc_flush_buffer(unsigned char);
 
-
-
-
-
-
 extern signed int hwc_ioctl(unsigned int, unsigned long);
 
-
-
-
-
-
-
-
-
 extern void do_hwc_interrupt(void);
 
-
-
-
-
-
 extern int hwc_printk(const char *, ...);
 
 #else	
 
-
-
-
-
 extern void store_hwc_input(unsigned char*, unsigned int);
 
-
-
-
 extern void wake_up_hwc_tty(void);
 
 #endif
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 #define IN_HWCB      1
 #define IN_WRITE_BUF 2
 #define IN_BUFS_TOTAL        (IN_HWCB | IN_WRITE_BUF)
 
-
-
 typedef unsigned short int ioctl_htab_t;
 typedef unsigned char ioctl_echo_t;
 typedef unsigned short int ioctl_cols_t;
@@ -128,7 +51,6 @@
 typedef unsigned char ioctl_case_t;
 typedef unsigned char ioctl_delim_t;
 
-
 typedef struct {
 	ioctl_htab_t width_htab;
 	ioctl_echo_t echo;
@@ -141,22 +63,10 @@
 	ioctl_delim_t delim;
 } hwc_ioctls_t;
 
-
-
-
-
-
 static hwc_ioctls_t _hwc_ioctls;
 
-
-
-
-
-
-
 #define HWC_IOCTL_LETTER 'B'
 
-
 #define TIOCHWCSHTAB	_IOW(HWC_IOCTL_LETTER, 0, _hwc_ioctls.width_htab)
 
 #define TIOCHWCSECHO	_IOW(HWC_IOCTL_LETTER, 1, _hwc_ioctls.echo)
@@ -173,10 +83,8 @@
 
 #define TIOCHWCSCASE	_IOW(HWC_IOCTL_LETTER, 7, _hwc_ioctls.tolower)
 
-
 #define TIOCHWCSDELIM	_IOW(HWC_IOCTL_LETTER, 9, _hwc_ioctls.delim)
 
-
 #define TIOCHWCGHTAB	_IOR(HWC_IOCTL_LETTER, 10, _hwc_ioctls.width_htab)
 
 #define TIOCHWCGECHO	_IOR(HWC_IOCTL_LETTER, 11, _hwc_ioctls.echo)
@@ -193,18 +101,13 @@
 
 #define TIOCHWCGCASE	_IOR(HWC_IOCTL_LETTER, 17, _hwc_ioctls.tolower)
 
-
 #define TIOCHWCGDELIM	_IOR(HWC_IOCTL_LETTER, 19, _hwc_ioctls.delim)
 
 #define TIOCHWCGKBUF	_IOR(HWC_IOCTL_LETTER, 20, _hwc_ioctls.max_hwcb)
 
 #define TIOCHWCGCURR	_IOR(HWC_IOCTL_LETTER, 21, _hwc_ioctls)
 
-
-
-
 #define CODE_ASCII              0x0
 #define CODE_EBCDIC             0x1
-
 
 #endif   
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/s390/char/hwc_tty.c linux.15p9/drivers/s390/char/hwc_tty.c
--- linux.vanilla/drivers/s390/char/hwc_tty.c	Tue Jan  4 21:18:53 2000
+++ linux.15p9/drivers/s390/char/hwc_tty.c	Thu Feb 17 13:38:52 2000
@@ -21,12 +21,17 @@
 #include "hwc_rw.h"
 
 #define HWC_TTY_PRINT_HEADER "hwc tty driver: "
+
 #define HWC_TTY_BUF_SIZE 512
 
 typedef struct {
+
 	struct tty_struct *tty;
+
 	unsigned char buf[HWC_TTY_BUF_SIZE];
+
 	unsigned short int buf_count;
+
 	spinlock_t lock;
 } hwc_tty_data_struct;
 
@@ -39,9 +44,11 @@
 
 extern struct termios  tty_std_termios;
 
-static int hwc_tty_open(struct tty_struct *tty,
+static int 
+hwc_tty_open (struct tty_struct *tty,
                          struct file       *filp)
 {
+
 	if (MINOR(tty->device) - tty->driver.minor_start)
 		return -ENODEV;
 
@@ -53,7 +60,8 @@
 	return 0;
 }
 
-void wake_up_hwc_tty(void)
+void 
+wake_up_hwc_tty (void)
 {
 	if ((hwc_tty_data.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
 			hwc_tty_data.tty->ldisc.write_wakeup)
@@ -61,7 +69,8 @@
 	wake_up_interruptible(&hwc_tty_data.tty->write_wait);
 }
 
-static void hwc_tty_close(struct tty_struct *tty,
+static void 
+hwc_tty_close (struct tty_struct *tty,
                            struct file *filp)
 {
 	if (MINOR(tty->device) != tty->driver.minor_start) {
@@ -69,11 +78,11 @@
 			"do not close hwc tty because of wrong device number");
 		return;
 	}
-
 	hwc_tty_data.tty = NULL;
 }
 
-static int hwc_tty_write_room (struct tty_struct *tty)
+static int 
+hwc_tty_write_room (struct tty_struct *tty)
 {
 	int retval;
 
@@ -81,15 +90,15 @@
 	return retval;
 }
 
-static int hwc_tty_write(struct tty_struct   *tty,
+static int 
+hwc_tty_write (struct tty_struct *tty,
 			  int                  from_user,
 	                  const unsigned char *buf,
        		          int                  count)
 {
 	int retval;
 
-	if (hwc_tty_data.buf_count > 0)
-	{
+	if (hwc_tty_data.buf_count > 0) {
 		hwc_write(0, hwc_tty_data.buf, hwc_tty_data.buf_count);
 		hwc_tty_data.buf_count = 0;
 	}
@@ -97,14 +106,14 @@
 	return retval;
 }
 
-static void hwc_tty_put_char(struct tty_struct *tty,
+static void 
+hwc_tty_put_char (struct tty_struct *tty,
                               unsigned char ch)
 {
 	unsigned long flags;
 
 	spin_lock_irqsave(&hwc_tty_data.lock, flags);
-	if (hwc_tty_data.buf_count >= HWC_TTY_BUF_SIZE)
-	{
+	if (hwc_tty_data.buf_count >= HWC_TTY_BUF_SIZE) {
 		hwc_write(0, hwc_tty_data.buf, hwc_tty_data.buf_count);
 		hwc_tty_data.buf_count = 0;
 	}
@@ -113,7 +122,8 @@
 	spin_unlock_irqrestore(&hwc_tty_data.lock, flags);
 }
 
-static void hwc_tty_flush_chars(struct tty_struct *tty)
+static void 
+hwc_tty_flush_chars (struct tty_struct *tty)
 {
 	unsigned long flags;
 
@@ -123,8 +133,8 @@
 	spin_unlock_irqrestore(&hwc_tty_data.lock, flags);
 }
 
-
-static int hwc_tty_chars_in_buffer(struct tty_struct *tty)
+static int 
+hwc_tty_chars_in_buffer (struct tty_struct *tty)
 {
 	int retval;
 
@@ -132,12 +142,14 @@
 	return retval;
 }
 
-static void hwc_tty_flush_buffer(struct tty_struct *tty)
+static void 
+hwc_tty_flush_buffer (struct tty_struct *tty)
 {
 	wake_up_hwc_tty();
 }
 
-static int hwc_tty_ioctl(
+static int 
+hwc_tty_ioctl (
 	struct tty_struct *tty,
 	struct file * file,
 	unsigned int cmd,
@@ -149,11 +161,13 @@
 	return hwc_ioctl(cmd, arg);
 }
 
-void store_hwc_input(unsigned char* buf, unsigned int count)
+void 
+store_hwc_input (unsigned char *buf, unsigned int count)
 {
 	struct tty_struct *tty = hwc_tty_data.tty;
 
 	if (tty != NULL) {
+
 		if (count == 2 && strncmp(buf, "^c", 2) == 0) {
 			tty->flip.count++;
 			*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
@@ -167,12 +181,14 @@
 			*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
 			*tty->flip.char_buf_ptr++ = SUSP_CHAR(tty);
 		} else {
+
 			memcpy(tty->flip.char_buf_ptr, buf, count);
 			if (count < 2 ||
 			    strncmp(buf + count - 2, "^n", 2)) {
 				tty->flip.char_buf_ptr[count] = '\n';
 				count++;
-			} else	count -= 2;
+			} else
+				count -= 2;
 			memset(tty->flip.flag_buf_ptr, TTY_NORMAL, count);
 			tty->flip.char_buf_ptr += count;
 			tty->flip.flag_buf_ptr += count;
@@ -183,7 +199,8 @@
 	}
 }
 
-void hwc_tty_init(void)
+void 
+hwc_tty_init (void)
 {
 	memset (&hwc_tty_driver, 0, sizeof(struct tty_driver));
 	hwc_tty_driver.magic = TTY_DRIVER_MAGIC;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/s390/net/ctc.c linux.15p9/drivers/s390/net/ctc.c
--- linux.vanilla/drivers/s390/net/ctc.c	Tue Jan  4 21:18:53 2000
+++ linux.15p9/drivers/s390/net/ctc.c	Thu Feb 17 13:38:52 2000
@@ -3,8 +3,42 @@
  *    CTC / ESCON network driver
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Dieter Wellerdiek (wel@de.ibm.com)
+ *
+ *
+ *  Description of the Kernel Parameter
+ *    Normally the CTC driver selects the channels in order (automatic channel 
+ *    selection). If your installation needs to use the channels in a different 
+ *    order or doesn't want to have automatic channel selection on, you can do 
+ *    this with the "ctc= kernel keyword". 
+ *
+ *       ctc=0,0xrrrr,0xwwww,ddddd
+ *
+ *     Where:
+ *
+ *       "rrrr" is the read channel address
+ *       "wwww" is the write channel address
+ *       "dddd" is the network device (ctc0 to ctc7 for a parallel channel, escon0
+ *              to escon7 for ESCON channels).
+ *
+ *     To switch the automatic channel selection off use the ctc= keyword with 
+ *     parameter "noauto". This may be necessary if you 3271 devices or other devices 
+ *     which use the ctc device type and model, but operate with a different protocol. 
+ *     
+ *       ctc=noauto
+ *
+ *  Change History
+ *    0.50  Initial release shipped
+ *    0.51  Bug fixes
+ *          - CTC / ESCON network device can now handle up to 64 channels 
+ *          - 3088-61 info message supperssed - CISCO 7206 - CLAW - ESCON 
+ *          - 3088-62 info message suppressed - OSA/D   
+ *          - channel: def ffffffed ... error message suppressed 
+ *          - CTC / ESCON device was not recoverable after a lost connection with 
+ *            IFCONFIG dev DOWN and IFCONFIG dev UP 
+ *          - Possibility to switch the automatic selection off
+ *          - Minor bug fixes 
  */
 
 #include <linux/kernel.h>
@@ -28,12 +62,12 @@
 #include <asm/io.h>
 #include <asm/bitops.h>
  
-#include "../../../arch/s390/kernel/irq.h"
+#include <asm/irq.h>
 
 
 //#define DEBUG 
 
-/* Redefine message level, so that all messages occure on 3215 console in DEBUG mode */
+/* Redefine message level, so that all messages occur on 3215 console in DEBUG mode */
 #ifdef DEBUG                
         #undef  KERN_INFO
         #undef  KERN_WARNING
@@ -49,8 +83,8 @@
 #define CCW_CMD_SET_EXTENDED    0xc3
 #define CCW_CMD_PREPARE         0xe3
 
-#define MAX_DEVICES             16 
-#define MAX_ADAPTERS            MAX_DEVICES / 2
+#define MAX_CHANNEL_DEVICES     64 
+#define MAX_ADAPTERS            8
 #define CTC_DEFAULT_MTU_SIZE    1500
 #define READ                    0
 #define WRITE                   1
@@ -77,7 +111,7 @@
 
 typedef enum { 
         channel_type_none,           /* Device is not a channel */
-        channel_type_undefined,      /* Device is a channel but we dont know anything about it */
+        channel_type_undefined,      /* Device is a channel but we don't know anything about it */
         channel_type_ctca,           /* Device is a CTC/A and we can deal with it */
         channel_type_escon,          /* Device is a ESCON channel and we can deal with it */
         channel_type_unsupported     /* Device is a unsupported model */
@@ -99,7 +133,7 @@
 }; 
 
 static struct {
-        struct devicelist  list[MAX_DEVICES]; 
+        struct devicelist  list[MAX_CHANNEL_DEVICES]; 
         int                count;
         int                left;
 } channel[CHANNEL_MEDIA];
@@ -113,7 +147,7 @@
         __u16              protocol;
 };
 
-static struct adapterlist ctc_adapter[CHANNEL_MEDIA][MAX_ADAPTERS];
+static struct adapterlist ctc_adapter[CHANNEL_MEDIA][MAX_ADAPTERS];  /* 0 = CTC  / 1 = ESCON */
 
 
 /* 
@@ -131,7 +165,7 @@
 struct channel {
         unsigned int        devno;
         int                 irq;
-        int                 IO_active;
+        unsigned long       IO_active;
         ccw1_t              ccw[3];
         __u32               state; 
         int                 buffer_count;
@@ -152,7 +186,7 @@
 
 
 struct ctc_priv {                                                                    
-        struct net_device_stats  stats;
+        struct enet_statistics   stats;
         struct channel           channel[2]; 
         __u16                    protocol;
 };  
@@ -224,7 +258,7 @@
         if (!test_and_set_bit(0, (void *)& channel_tab_initialized)){
                 channel_scan(); 
                 for (m = 0; m < CHANNEL_MEDIA; m++) { 
-                        channel_sort (channel[m].list, MAX_DEVICES); 
+                        channel_sort (channel[m].list, MAX_CHANNEL_DEVICES); 
                         channel[m].left = channel[m].count;   
                 }
                 if (channel[CTC].count == 0 && channel[ESCON].count == 0) 
@@ -234,7 +268,7 @@
                             channel[CTC].count, channel[ESCON].count);  
 #ifdef DEBUG 
                 for (m = 0; m < CHANNEL_MEDIA;  m++) { 
-                        for (c = 0; c < MAX_DEVICES; c++){
+                        for (c = 0; c < MAX_CHANNEL_DEVICES; c++){
                                 printk(KERN_DEBUG "channel: Adapter=%x Entry=%x devno=%04x\n", 
                                      m, c, channel[m].list[c].devno);
                         }
@@ -255,14 +289,14 @@
         dev_info_t temp;
         
         for (m = 0; m < CHANNEL_MEDIA;  m++) { 
-                for (c = 0; c < MAX_DEVICES; c++){
+                for (c = 0; c < MAX_CHANNEL_DEVICES; c++){
                         channel[m].list[c].devno = -ENODEV;
                 }
         }
         
         for (irq = 0; irq < NR_IRQS; irq++) {
                 /* CTC/A */
-                if (channel[CTC].count < MAX_DEVICES ) {
+                if (channel[CTC].count < MAX_CHANNEL_DEVICES ) {
                         if (get_dev_info(irq, &temp) == 0 && 
                             channel_check_for_type(&temp.sid_data) == channel_type_ctca) {
                                 channel[CTC].list[channel[CTC].count].devno = temp.devno; 
@@ -271,7 +305,7 @@
                 }
 
                 /* ESCON */
-                if (channel[ESCON].count < MAX_DEVICES ) {
+                if (channel[ESCON].count < MAX_CHANNEL_DEVICES ) {
                         if (get_dev_info(irq, &temp) == 0 && 
                             channel_check_for_type(&temp.sid_data) == channel_type_escon) {
                                 channel[ESCON].list[channel[ESCON].count].devno = temp.devno; 
@@ -363,21 +397,23 @@
 
                         switch (id->cu_model) {
                                 case 0x08:    
-                                        type = channel_type_ctca;  /* 3088/08  ==> CTCA */
+                                        type = channel_type_ctca;  /* 3088-08  ==> CTCA */
                                         break; 
 
                                 case 0x1F:   
-                                        type = channel_type_escon; /* 3088/1F  ==> ESCON channel */
+                                        type = channel_type_escon; /* 3088-1F  ==> ESCON channel */
                                         break;
  
-                                case 0x01:                         /* 3088/01  ==> P390 OSA emulation */
-                                case 0x60:                         /* 3088/60  ==> OSA/2 Adapter */
+                                case 0x01:                         /* 3088-01  ==> P390 OSA emulation */
+                                case 0x60:                         /* 3088-60  ==> OSA/2 adapter */
+                                case 0x61:                         /* 3088-61  ==> CISCO 7206 CLAW protocol ESCON connected */
+                                case 0x62:                         /* 3088-62  ==> OSA/D device */ 
                                         type = channel_type_unsupported;
                                          break; 
 
                                 default:
                                         type = channel_type_undefined;
-                                        printk(KERN_INFO "channel: Unknown model found 3088/%02x\n",id->cu_model);
+                                        printk(KERN_INFO "channel: Unknown model found 3088-%02x\n",id->cu_model);
                         }
                         break;
 
@@ -545,6 +581,11 @@
         
         ctc_no_auto = 1;
 
+        if (!strcmp(dev_name,"noauto")) { 
+                printk(KERN_INFO "ctc: automatic channel selection deactivated\n");
+                return;
+        }
+
         tmp.devno[WRITE] = -ENODEV;
         tmp.devno[READ] = -ENODEV; 
 
@@ -556,7 +597,7 @@
                 case 2: /* read channel passed */
                         tmp.devno[READ] = ints[2];
                         if (tmp.devno[WRITE] == -ENODEV)
-                                tmp.devno[WRITE] = tmp.devno[READ]++; 
+                                tmp.devno[WRITE] = tmp.devno[READ] + 1; 
 
                 case 1: /* protocol type passed */
                         tmp.protocol    = ints[1];
@@ -566,9 +607,10 @@
                                 printk(KERN_WARNING "%s: wrong Channel protocol type passed\n", dev_name);
                                 return;
                         }
+                        break;
 
                 default: 
-                        printk(KERN_WARNING "%s: wrong number of parameter passed\n", dev_name);
+                        printk(KERN_WARNING "ctc: wrong number of parameter passed\n");
                         return;
         }
         ctc_adapter[extract_channel_media(dev_name)][extract_channel_id(dev_name)] = tmp; 
@@ -610,6 +652,9 @@
         if (channel_left(m) <=1) 
                 return -ENODEV;
 
+        if (ctc_no_auto == 1 && (ctc_adapter[m][i].devno[READ] == -ENODEV || ctc_adapter[m][i].devno[WRITE] == -ENODEV))
+                return -ENODEV;
+
         dev->priv = kmalloc(sizeof(struct ctc_priv), GFP_KERNEL);
         if (dev->priv == NULL)
                 return -ENOMEM;
@@ -618,6 +663,7 @@
 
         
         for (c = 0; c < 2; c++) {
+
                 privptr->channel[c].devstat = kmalloc(sizeof(devstat_t), GFP_KERNEL);
                 if (privptr->channel[c].devstat == NULL){
                         if (i == WRITE)
@@ -1031,7 +1077,7 @@
                                 skb->mac.raw = skb->data;
                                 skb->dev = dev;
                                 skb->protocol = htons(ETH_P_IP);
-                                skb->ip_summed = CHECKSUM_UNNECESSARY; /* no UC happend!!! */
+                                skb->ip_summed = CHECKSUM_UNNECESSARY; /* no UC happened!!! */
                                 netif_rx(skb);
                                 privptr->stats.rx_packets++;
                         } else {
@@ -1150,6 +1196,7 @@
                 privptr->channel[i].dev = dev;
                 
                 privptr->channel[i].flag_a = 0;
+                privptr->channel[i].IO_active = 0;
 
                 privptr->channel[i].ccw[0].cmd_code  = CCW_CMD_PREPARE;
                 privptr->channel[i].ccw[0].flags     = CCW_FLAG_SLI | CCW_FLAG_CC;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/s390/net/iucv.c linux.15p9/drivers/s390/net/iucv.c
--- linux.vanilla/drivers/s390/net/iucv.c	Tue Jan  4 21:18:53 2000
+++ linux.15p9/drivers/s390/net/iucv.c	Thu Feb 17 13:38:52 2000
@@ -3,7 +3,7 @@
  *    Network driver for VM using iucv
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Stefan Hegewald <hegewald@de.ibm.com>
  *               Hartmut Penner <hpenner@de.ibm.com> 
  */
@@ -596,8 +596,8 @@
 #ifdef DEBUG
         printk(  "iucv: transaction complete now.\n");
 #endif
+        iucv_next = *((unsigned short*)rcvptr);
         rcvptr = rcvptr + iucv_data_len;
-        iucv_next = iucv_data_len; 
         /* get next packet offset */  
         iucv_data_len= *((unsigned short*)rcvptr);
 	
@@ -791,7 +791,9 @@
 /*----------------*/
 int iucv_ioctl(struct device *dev, struct ifreq *rq, int cmd)
 {
+#ifdef DEBUG
     printk(  "iucv: device %s; iucv_ioctl\n",dev->name);
+#endif
     return 0;
 }
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/sbus/audio/dbri.c linux.15p9/drivers/sbus/audio/dbri.c
--- linux.vanilla/drivers/sbus/audio/dbri.c	Tue Jan  4 21:18:53 2000
+++ linux.15p9/drivers/sbus/audio/dbri.c	Fri Jan 14 15:56:16 2000
@@ -17,6 +17,7 @@
  *   - Data sheet of the T7903, a newer but very similar ISA bus equivalent
  *     available from the Lucent (formarly AT&T microelectronics) home
  *     page.
+ *   - http://www.freesoft.org/Linux/DBRI (PDF data sheet)
  * - MMCODEC: Crystal Semiconductor CS4215 16 bit Multimedia Audio Codec
  *   Interfaces: CHI, Audio In & Out, 2 bits parallel
  *   Documentation: from the Crystal Semiconductor home page.
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/sbus/char/pcikbd.c linux.15p9/drivers/sbus/char/pcikbd.c
--- linux.vanilla/drivers/sbus/char/pcikbd.c	Tue Jan  4 21:18:53 2000
+++ linux.15p9/drivers/sbus/char/pcikbd.c	Fri Jan 21 17:50:17 2000
@@ -1,8 +1,8 @@
-/* $Id: pcikbd.c,v 1.27.2.1 1999/10/01 05:09:36 davem Exp $
+/* $Id: pcikbd.c,v 1.27.2.2 2000/01/21 01:05:45 davem Exp $
  * pcikbd.c: Ultra/AX PC keyboard support.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
- * JavaStation(MrCoffee) support by Pete A. Zaitcev.
+ * JavaStation support by Pete A. Zaitcev.
  *
  * This code is mainly put together from various places in
  * drivers/char, please refer to these sources for credits
@@ -30,13 +30,16 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
-#ifdef __sparc_v9__
-#define	PCI_KB_NAME	"kb_ps2"
-#define PCI_MS_NAME	"kdmouse"
-#else
-#define PCI_KB_NAME	"keyboard"
-#define PCI_MS_NAME	"mouse"
-#endif
+/*
+ * Different platforms provide different permutations of names.
+ * AXi - kb_ps2, kdmouse.
+ * MrCoffee - keyboard, mouse.
+ * Espresso - keyboard, kdmouse.
+ */
+#define	PCI_KB_NAME1	"kb_ps2"
+#define PCI_KB_NAME2	"keyboard"
+#define PCI_MS_NAME1	"kdmouse"
+#define PCI_MS_NAME2	"mouse"
 
 #include "pcikbd.h"
 #include "sunserial.h"
@@ -502,7 +505,8 @@
 			for_each_ebusdev(edev, ebus) {
 				if(!strcmp(edev->prom_name, "8042")) {
 					for_each_edevchild(edev, child) {
-                                                if (!strcmp(child->prom_name, PCI_KB_NAME))
+                                                if (strcmp(child->prom_name, PCI_KB_NAME1) == 0 ||
+						    strcmp(child->prom_name, PCI_KB_NAME2) == 0)
 							goto found;
 					}
 				}
@@ -513,12 +517,14 @@
 
 found:
 		pcikbd_iobase = child->base_address[0];
+#ifdef __sparc_v9__
 		if (check_region(pcikbd_iobase, sizeof(unsigned long))) {
 			printk("8042: can't get region %lx, %d\n",
 			       pcikbd_iobase, (int)sizeof(unsigned long));
 			return;
 		}
 		request_region(pcikbd_iobase, sizeof(unsigned long), "8042 controller");
+#endif
 
 		pcikbd_irq = child->irqs[0];
 		if (request_irq(pcikbd_irq, &pcikbd_interrupt,
@@ -548,7 +554,7 @@
 	 * XXX: my 3.1.3 PROM does not give me the beeper node for the audio
 	 *      auxio register, though I know it is there... (ecd)
 	 *
-	 * Both JE1 & MrCoffe have no beeper. How about Krups? --zaitcev
+	 * JavaStations appear not to have beeper. --zaitcev
 	 */
 	if (!edev)
 		pcibeep_iobase = (pcikbd_iobase & ~(0xffffff)) | 0x722000;
@@ -575,7 +581,6 @@
 }
 
 
-
 /*
  * Here begins the Mouse Driver.
  */
@@ -979,7 +984,8 @@
 			for_each_ebusdev(edev, ebus) {
 				if(!strcmp(edev->prom_name, "8042")) {
 					for_each_edevchild(edev, child) {
-							if (!strcmp(child->prom_name, PCI_MS_NAME))
+							if (strcmp(child->prom_name, PCI_MS_NAME1) == 0 ||
+							    strcmp(child->prom_name, PCI_MS_NAME2) == 0)
 							goto found;
 					}
 				}
@@ -1054,7 +1060,7 @@
 
 __initfunc(int ps2kbd_probe(unsigned long *memory_start))
 {
-	int pnode, enode, node, dnode;
+	int pnode, enode, node, dnode, xnode;
 	int kbnode = 0, msnode = 0, bnode = 0;
 	int devices = 0;
 	char prop[128];
@@ -1134,18 +1140,20 @@
 			 * For each '8042' on this EBus...
 			 */
 			while (node) {
+				dnode = prom_getchild(node);
+
 				/*
 				 * Does it match?
 				 */
-				dnode = prom_getchild(node);
-				dnode = prom_searchsiblings(dnode, PCI_KB_NAME);
-				if (dnode == kbnode) {
+				if ((xnode = prom_searchsiblings(dnode, PCI_KB_NAME1)) == kbnode) {
+					++devices;
+				} else if ((xnode = prom_searchsiblings(dnode, PCI_KB_NAME2)) == kbnode) {
 					++devices;
 				}
 
-				dnode = prom_getchild(node);
-				dnode = prom_searchsiblings(dnode, PCI_MS_NAME);
-				if (dnode == msnode) {
+				if ((xnode = prom_searchsiblings(dnode, PCI_MS_NAME1)) == msnode) {
+					++devices;
+				} else if ((xnode = prom_searchsiblings(dnode, PCI_MS_NAME2)) == msnode) {
 					++devices;
 				}
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/sbus/char/zs.c linux.15p9/drivers/sbus/char/zs.c
--- linux.vanilla/drivers/sbus/char/zs.c	Tue Jan  4 21:18:54 2000
+++ linux.15p9/drivers/sbus/char/zs.c	Fri Jan 21 17:50:18 2000
@@ -1,4 +1,4 @@
-/* $Id: zs.c,v 1.41.2.4 1999/10/14 08:44:40 davem Exp $
+/* $Id: zs.c,v 1.41.2.5 2000/01/21 01:05:47 davem Exp $
  * zs.c: Zilog serial port driver for the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -1855,7 +1855,7 @@
 
 static void show_serial_version(void)
 {
-	char *revision = "$Revision: 1.41.2.4 $";
+	char *revision = "$Revision: 1.41.2.5 $";
 	char *version, *p;
 
 	version = strchr(revision, ' ');
@@ -2023,9 +2023,8 @@
 		/* Can use the prom for other machine types */
 		zsnode = prom_getchild(prom_root_node);
 		if (sparc_cpu_model == sun4d) {
-			int node;
 			int no = 0;
-			
+
 			tmpnode = zsnode;
 			zsnode = 0;
 			bbnode = 0;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/scsi/3w-xxxx.c linux.15p9/drivers/scsi/3w-xxxx.c
--- linux.vanilla/drivers/scsi/3w-xxxx.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/scsi/3w-xxxx.c	Mon Feb  7 13:44:11 2000
@@ -0,0 +1,2225 @@
+/* 
+   3w-xxxx.c -- 3ware Storage Controller device driver for Linux.
+
+   Written By: Adam Radford <linux@3ware.com>
+   Copyright (C) 1999-2000 3ware Inc.
+
+   Kernel compatablity By: 	Andre Hedrick <andre@suse.com>
+   Non-Copyright (C) 2000	Andre Hedrick <andre@suse.com>
+   
+   Further tiny build fixes and trivial hoovering    Alan Cox
+
+   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; version 2 of the License.
+
+   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.                              
+
+   NO WARRANTY                                                               
+   THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR        
+   CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT      
+   LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,      
+   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is    
+   solely responsible for determining the appropriateness of using and       
+   distributing the Program and assumes all risks associated with its        
+   exercise of rights under this Agreement, including but not limited to     
+   the risks and costs of program errors, damage to or loss of data,         
+   programs or equipment, and unavailability or interruption of operations.  
+
+   DISCLAIMER OF LIABILITY                                                   
+   NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY   
+   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL        
+   DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND   
+   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     
+   TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE    
+   USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED  
+   HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES             
+
+   You should have received a copy of the GNU General Public License         
+   along with this program; if not, write to the Free Software               
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+
+   Bugs/Comments/Suggestions should be mailed to:                            
+   linux@3ware.com
+
+   For more information, goto:
+   http://www.3ware.com
+*/
+
+#include <linux/module.h>
+
+MODULE_AUTHOR ("3ware Inc.");
+MODULE_DESCRIPTION ("3ware Storage Controller Linux Driver");
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/time.h>
+#include <linux/proc_fs.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/blk.h>
+#include <linux/hdreg.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/smp.h>
+
+#include <asm/spinlock.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#define __3W_C			/* let 3w-xxxx.h know it is use */
+
+#include "sd.h"
+#include "scsi.h"
+#include "hosts.h"
+
+#include "3w-xxxx.h"
+
+static int tw_copy_info(TW_Info *info, char *fmt, ...);
+static void tw_copy_mem_info(TW_Info *info, char *data, int len);
+static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+
+struct proc_dir_entry tw_scsi_proc_entry = {
+	PROC_SCSI_3W_XXXX,
+	7, "3w-xxxx",
+	S_IFDIR|S_IRUGO|S_IXUGO, 2
+};
+
+/* Globals */
+char *tw_driver_version="0.4.001";
+TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
+int tw_device_extension_count = 0;
+
+/* Functions */
+
+/* This function will complete an aen request from the isr */
+int tw_aen_complete(TW_Device_Extension *tw_dev, int request_id) 
+{
+	TW_Param *param;
+	unsigned short aen, aen_code;
+
+	if (tw_dev->alignment_virtual_address[request_id] == NULL) {
+		printk(KERN_WARNING "3w-xxxx: tw_aen_complete(): Bad alignment virtual address.\n");
+		return 1;
+	}
+	param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
+	aen = *(unsigned short *)(param->data);
+	aen_code = (aen & 0x0ff);
+	dprintk(KERN_NOTICE "3w-xxxx: tw_aen_complete(): Queue'd code 0x%x\n", aen_code);
+	/* Now queue the code */
+	tw_dev->aen_queue[tw_dev->aen_tail] = aen_code;
+	if (tw_dev->aen_tail == TW_Q_LENGTH - 1) {
+		tw_dev->aen_tail = TW_Q_START;
+	} else {
+		tw_dev->aen_tail = tw_dev->aen_tail + 1;
+	}
+	if (tw_dev->aen_head == tw_dev->aen_tail) {
+		if (tw_dev->aen_head == TW_Q_LENGTH - 1) {
+			tw_dev->aen_head = TW_Q_START;
+		} else {
+			tw_dev->aen_head = tw_dev->aen_head + 1;
+		}
+	}
+	tw_dev->state[request_id] = TW_S_COMPLETED;
+	tw_state_request_finish(tw_dev, request_id);
+
+	return 0;
+} /* End tw_aen_complete() */
+
+/* This function will drain the aen queue after a soft reset */
+int tw_aen_drain_queue(TW_Device_Extension *tw_dev)
+{
+	TW_Command *command_packet;
+	TW_Param *param;
+	int tries = 0;
+	int request_id = 0;
+	u32 command_que_value = 0, command_que_addr;
+	u32 status_reg_value = 0, status_reg_addr;
+	u32 param_value;
+	TW_Response_Queue response_queue;
+	u32 response_que_addr;
+	unsigned short aen;
+	unsigned short aen_code;
+	int finished = 0;
+	int first_reset = 0;
+	int queue = 0;
+	int imax, i;
+	int found = 0;
+
+	dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue()\n");
+
+	command_que_addr = tw_dev->registers.command_que_addr;
+	status_reg_addr = tw_dev->registers.status_reg_addr;
+	response_que_addr = tw_dev->registers.response_que_addr;
+
+	if (tw_poll_status(tw_dev, TW_STATUS_ATTENTION_INTERRUPT, 15)) {
+		printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): No attention interrupt for card %d\n", tw_dev->host->host_no);
+		return 1;
+	}
+
+	/* Initialize command packet */
+	if (tw_dev->command_packet_virtual_address[request_id] == NULL) {
+		printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad command packet virtual address.\n");
+		return 1;
+	}
+	command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
+	memset(command_packet, 0, sizeof(TW_Sector));
+	command_packet->byte0.opcode = TW_OP_GET_PARAM;
+	command_packet->byte0.sgl_offset = 2;
+	command_packet->size = 4;
+	command_packet->request_id = request_id;
+	command_packet->byte3.unit = 0;
+	command_packet->byte3.host_id = 0;
+	command_packet->status = 0;
+	command_packet->flags = 0;
+	command_packet->byte6.parameter_count = 1;
+	command_que_value = tw_dev->command_packet_physical_address[request_id];
+	if (command_que_value == 0) {
+		printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad command packet physical address.\n");
+		return 1;
+	}
+
+	/* Now setup the param */
+	if (tw_dev->alignment_virtual_address[request_id] == NULL) {
+		printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad alignment virtual address.\n");
+		return 1;
+	}
+	param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
+	memset(param, 0, sizeof(TW_Sector));
+	param->table_id = 0x401; /* AEN table */
+	param->parameter_id = 2; /* Unit code */
+	param->parameter_size_bytes = 2;
+	param_value = tw_dev->alignment_physical_address[request_id];
+	if (param_value == 0) {
+		printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad alignment physical address.\n");
+		return 1;
+	}
+	command_packet->byte8.param.sgl[0].address = param_value;
+	command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
+
+	imax = TW_POLL_MAX_RETRIES;
+
+	/* Now drain the controller's aen queue */
+	do {
+		/* Post command packet */
+		outl(command_que_value, command_que_addr);
+    
+		/* Now poll for completion */
+		for (i=0;i<imax;i++) {
+			mdelay(10);
+			status_reg_value = inl(status_reg_addr);
+			if (tw_check_bits(status_reg_value)) {
+				printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Unexpected bits.\n");
+				return 1;
+			}
+			if ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
+				response_queue.value = inl(response_que_addr);
+				request_id = (unsigned char)response_queue.u.response_id;
+    
+				if (request_id != 0) {
+					/* Unexpected request id */
+					printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Unexpected request id.\n");
+					return 1;
+				}
+	
+				if (command_packet->status != 0) {
+					if (command_packet->flags != TW_AEN_TABLE_UNDEFINED) {
+						/* Bad response */
+						printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad response, flags = 0x%x.\n", command_packet->flags);
+						return 1;
+					} else {
+						/* We know this is a 3w-1x00, and doesn't support aen's */
+						return 0;
+					}
+				}
+
+				/* Now check the aen */
+				aen = *(unsigned short *)(param->data);
+				aen_code = (aen & 0x0ff);
+				queue = 0;
+				switch (aen_code) {
+					case TW_AEN_QUEUE_EMPTY:
+						dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue(): Found TW_AEN_QUEUE_EMPTY.\n");
+						if (first_reset != 1) {
+							continue;
+						} else {
+							finished = 1;
+						}
+						break;
+					case TW_AEN_SOFT_RESET:
+						dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue(): Found TW_AEN_SOFT_RESET.\n");
+						if (first_reset == 0) {
+							first_reset = 1;
+						} else {
+							queue = 1;
+						}
+						break;
+					case TW_AEN_DEGRADED_MIRROR:
+						dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue(): Found TW_AEN_DEGRADED_MIRROR.\n");
+						queue = 1;
+						break;
+					case TW_AEN_CONTROLLER_ERROR:
+						dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue(): Found TW_AEN_CONTROLLER_ERROR.\n");
+						queue = 1;
+						break;
+					case TW_AEN_REBUILD_FAIL:
+						dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue(): Found TW_AEN_REBUILD_FAIL.\n");
+						queue = 1;
+						break;
+					case TW_AEN_REBUILD_DONE:
+						dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue(): Found TW_AEN_REBUILD_DONE.\n");
+						queue = 1;
+						break;
+					case TW_AEN_QUEUE_FULL:
+						dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue(): Found TW_AEN_QUEUE_FULL.\n");
+						queue = 1;
+						break;
+					default:
+						dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Unknown AEN code 0x%x.\n", aen_code);
+						queue = 1;
+				}
+
+				/* Now put the aen on the aen_queue */
+				if (queue == 1) {
+					tw_dev->aen_queue[tw_dev->aen_tail] = aen_code;
+					if (tw_dev->aen_tail == TW_Q_LENGTH - 1) {
+						tw_dev->aen_tail = TW_Q_START;
+					} else {
+						tw_dev->aen_tail = tw_dev->aen_tail + 1;
+					}
+					if (tw_dev->aen_head == tw_dev->aen_tail) {
+						if (tw_dev->aen_head == TW_Q_LENGTH - 1) {
+							tw_dev->aen_head = TW_Q_START;
+						} else {
+							tw_dev->aen_head = tw_dev->aen_head + 1;
+						}
+					}
+				}
+				found = 1;
+				break;
+			}
+		}
+		if (found == 0) {
+			printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Response never received.\n");
+			return 1;
+		}
+		tries++;
+	} while ((tries < TW_MAX_AEN_TRIES) && (finished == 0));
+
+	if (tries >=TW_MAX_AEN_TRIES) {
+		printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Aen queue error.\n");
+		return 1;
+	}
+
+	return 0;
+} /* End tw_aen_drain_queue() */
+
+/* This function will read the aen queue from the isr */
+int tw_aen_read_queue(TW_Device_Extension *tw_dev, int request_id) 
+{
+	TW_Command *command_packet;
+	TW_Param *param;
+	u32 command_que_value = 0, command_que_addr;
+	u32 status_reg_value = 0, status_reg_addr;
+	u32 param_value = 0;
+
+	dprintk(KERN_NOTICE "3w-xxxx: tw_aen_read_queue()\n");
+	command_que_addr = tw_dev->registers.command_que_addr;
+	status_reg_addr = tw_dev->registers.status_reg_addr;
+
+	status_reg_value = inl(status_reg_addr);
+	if (tw_check_bits(status_reg_value)) {
+		printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Unexpected bits.\n");
+		return 1;
+	}
+	if (tw_dev->command_packet_virtual_address[request_id] == NULL) {
+		printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Bad command packet virtual address.\n");
+		return 1;
+	}
+	command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
+	memset(command_packet, 0, sizeof(TW_Sector));
+	command_packet->byte0.opcode = TW_OP_GET_PARAM;
+	command_packet->byte0.sgl_offset = 2;
+	command_packet->size = 4;
+	command_packet->request_id = request_id;
+	command_packet->byte3.unit = 0;
+	command_packet->byte3.host_id = 0;
+	command_packet->status = 0;
+	command_packet->flags = 0;
+	command_packet->byte6.parameter_count = 1;
+	command_que_value = tw_dev->command_packet_physical_address[request_id];
+	if (command_que_value == 0) {
+		printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Bad command packet physical address.\n");
+		return 1;
+	}
+	/* Now setup the param */
+	if (tw_dev->alignment_virtual_address[request_id] == NULL) {
+		printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Bad alignment virtual address.\n");
+		return 1;
+	}
+	param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
+	memset(param, 0, sizeof(TW_Sector));
+	param->table_id = 0x401; /* AEN table */
+	param->parameter_id = 2; /* Unit code */
+	param->parameter_size_bytes = 2;
+	param_value = tw_dev->alignment_physical_address[request_id];
+	if (param_value == 0) {
+		printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Bad alignment physical address.\n");
+		return 1;
+	}
+	command_packet->byte8.param.sgl[0].address = param_value;
+	command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
+
+	/* Now post the command packet */
+	if ((status_reg_value & TW_STATUS_COMMAND_QUEUE_FULL) == 0) {
+		dprintk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Post succeeded.\n");
+		tw_dev->srb[request_id] = 0; /* Flag internal command */
+		tw_dev->state[request_id] = TW_S_POSTED;
+		outl(command_que_value, command_que_addr);
+	} else {
+		printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Post failed, will retry.\n");
+		return 1;
+	}
+
+	return 0;
+} /* End tw_aen_read_queue() */
+
+/* This function will allocate memory and check if it is 16 d-word aligned */
+int tw_allocate_memory(TW_Device_Extension *tw_dev, int request_id, int size, int which)
+{
+	u32 *virt_addr;
+
+	dprintk(KERN_NOTICE "3w-xxxx: tw_allocate_memory()\n");
+
+	if (which == 0) {
+		/* Allocate command packet memory */
+		virt_addr = kmalloc(size, GFP_ATOMIC);
+		if (virt_addr == NULL) {
+			printk(KERN_WARNING "3w-xxxx: tw_allocate_memory(): kmalloc() failed.\n");
+			return 1;
+		}
+		if ((u32)virt_addr % TW_ALIGNMENT) {
+			printk(KERN_WARNING "3w-xxxx: tw_allocate_memory(): Found unaligned address.\n");
+			return 1;
+		}
+		tw_dev->command_packet_virtual_address[request_id] = virt_addr;
+		tw_dev->command_packet_physical_address[request_id] = 
+		virt_to_bus(virt_addr);
+	} else {
+		/* Allocate generic buffer */
+		virt_addr = kmalloc(size, GFP_ATOMIC);
+		if (virt_addr == NULL) {
+			printk(KERN_WARNING "3w-xxxx: tw_allocate_memory(): kmalloc() failed.\n");
+			return 1;
+		}
+		if ((u32)virt_addr % TW_ALIGNMENT) {
+			printk(KERN_WARNING "3w-xxxx: tw_allocate_memory(): Found unaligned address.\n");
+			return 1;
+		}
+		tw_dev->alignment_virtual_address[request_id] = virt_addr;
+		tw_dev->alignment_physical_address[request_id] = virt_to_bus(virt_addr);
+	}
+	return 0;
+} /* End tw_allocate_memory() */
+
+/* This function will check the status register for unexpected bits */
+int tw_check_bits(u32 status_reg_value)
+{
+	if ((status_reg_value & TW_STATUS_EXPECTED_BITS) != TW_STATUS_EXPECTED_BITS) {  
+		printk(KERN_WARNING "3w-xxxx: tw_check_bits(): No expected bits (0x%x).\n", status_reg_value);
+		return 1;
+	}
+	if ((status_reg_value & TW_STATUS_UNEXPECTED_BITS) != 0) {
+		printk(KERN_WARNING "3w-xxxx: tw_check_bits(): Found unexpected bits (0x%x).\n", status_reg_value);
+		return 1;
+	}
+
+	return 0;
+} /* End tw_check_bits() */
+
+/* This function will report controller error status */
+int tw_check_errors(TW_Device_Extension *tw_dev) 
+{
+	u32 status_reg_addr, status_reg_value;
+  
+	status_reg_addr = tw_dev->registers.status_reg_addr;
+	status_reg_value = inl(status_reg_addr);
+
+	if (TW_STATUS_ERRORS(status_reg_value) || tw_check_bits(status_reg_value))
+		return 1;
+
+	return 0;
+} /* End tw_check_errors() */
+
+/* This function will clear the attention interrupt */
+void tw_clear_attention_interrupt(TW_Device_Extension *tw_dev)
+{
+	u32 control_reg_addr, control_reg_value;
+  
+	control_reg_addr = tw_dev->registers.control_reg_addr;
+	control_reg_value = TW_CONTROL_CLEAR_ATTENTION_INTERRUPT;
+	outl(control_reg_value, control_reg_addr);
+} /* End tw_clear_attention_interrupt() */
+
+/* This function will clear the host interrupt */
+void tw_clear_host_interrupt(TW_Device_Extension *tw_dev)
+{
+	u32 control_reg_addr, control_reg_value;
+
+	control_reg_addr = tw_dev->registers.control_reg_addr;
+	control_reg_value = TW_CONTROL_CLEAR_HOST_INTERRUPT;
+	outl(control_reg_value, control_reg_addr);
+} /* End tw_clear_host_interrupt() */
+
+/* This function is called by tw_scsi_proc_info */
+static int tw_copy_info(TW_Info *info, char *fmt, ...) 
+{
+	va_list args;
+	char buf[81];
+	int len;
+  
+	va_start(args, fmt);
+	len = vsprintf(buf, fmt, args);
+	va_end(args);
+	tw_copy_mem_info(info, buf, len);
+	return len;
+} /* End tw_copy_info() */
+
+/* This function is called by tw_scsi_proc_info */
+static void tw_copy_mem_info(TW_Info *info, char *data, int len)
+{
+	if (info->position + len > info->length)
+		len = info->length - info->position;
+
+	if (info->position + len < info->offset) {
+		info->position += len;
+		return;
+	}
+	if (info->position < info->offset) {
+		data += (info->offset - info->position);
+		len  -= (info->offset - info->position);
+	}
+	if (len > 0) {
+		memcpy(info->buffer + info->position, data, len);
+		info->position += len;
+	}
+} /* End tw_copy_mem_info() */
+
+/* This function will disable interrupts on the controller */  
+void tw_disable_interrupts(TW_Device_Extension *tw_dev) 
+{
+	u32 control_reg_value, control_reg_addr;
+
+	control_reg_addr = tw_dev->registers.control_reg_addr;
+	control_reg_value = TW_CONTROL_DISABLE_INTERRUPTS;
+	outl(control_reg_value, control_reg_addr);
+} /* End tw_disable_interrupts() */
+
+/* This function will empty the response que */
+int tw_empty_response_que(TW_Device_Extension *tw_dev) 
+{
+	u32 status_reg_addr, status_reg_value;
+	u32 response_que_addr, response_que_value;
+
+	status_reg_addr = tw_dev->registers.status_reg_addr;
+	response_que_addr = tw_dev->registers.response_que_addr;
+  
+	status_reg_value = inl(status_reg_addr);
+
+	if (tw_check_bits(status_reg_value)) {
+		printk(KERN_WARNING "3w-xxxx: tw_empty_response_queue(): Unexpected bits 1.\n");
+		return 1;
+	}
+  
+	while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
+		response_que_value = inl(response_que_addr);
+		status_reg_value = inl(status_reg_addr);
+		if (tw_check_bits(status_reg_value)) {
+			printk(KERN_WARNING "3w-xxxx: tw_empty_response_queue(): Unexpected bits 2.\n");
+			return 1;
+		}
+	}
+	return 0;
+} /* End tw_empty_response_que() */
+
+/* This function will enable interrupts on the controller */
+void tw_enable_interrupts(TW_Device_Extension *tw_dev)
+{
+	u32 control_reg_value, control_reg_addr;
+
+	control_reg_addr = tw_dev->registers.control_reg_addr;
+	control_reg_value = (TW_CONTROL_CLEAR_ATTENTION_INTERRUPT |
+			     TW_CONTROL_UNMASK_RESPONSE_INTERRUPT |
+			     TW_CONTROL_ENABLE_INTERRUPTS);
+	outl(control_reg_value, control_reg_addr);
+} /* End tw_enable_interrupts() */
+
+/* This function will find and initialize all cards */
+int tw_findcards(Scsi_Host_Template *tw_host) 
+{
+	int numcards = 0, tries = 0, error = 0;
+	struct Scsi_Host *host;
+	TW_Device_Extension *tw_dev;
+	TW_Device_Extension *tw_dev2;
+	struct pci_dev *tw_pci_dev = pci_devices;
+	u32 status_reg_value;
+
+	dprintk(KERN_NOTICE "3w-xxxx: tw_findcards()\n");
+	while ((tw_pci_dev = pci_find_device(TW_VENDOR_ID, TW_DEVICE_ID, tw_pci_dev))) {
+		/* Prepare temporary device extension */
+		tw_dev=(TW_Device_Extension *)kmalloc(sizeof(TW_Device_Extension), GFP_ATOMIC);
+		if (tw_dev == NULL) {
+			printk(KERN_WARNING "3w-xxxx: tw_findcards(): kmalloc() failed for card %d.\n", numcards);
+			continue;
+		}
+		memset(tw_dev, 0, sizeof(TW_Device_Extension));
+
+		error = tw_initialize_device_extension(tw_dev);
+		if (error) {
+			printk(KERN_WARNING "3w-xxxx: tw_findcards(): Couldn't initialize device extension for card %d.\n", numcards);
+			tw_free_device_extension(tw_dev);
+			kfree(tw_dev);
+			continue;
+		}
+
+		/* Calculate the cards register addresses */
+		tw_dev->registers.base_addr = tw_pci_dev->base_address[0];
+		tw_dev->registers.control_reg_addr = (tw_pci_dev->base_address[0] & ~15);
+		tw_dev->registers.status_reg_addr = ((tw_pci_dev->base_address[0] & ~15) + 0x4);
+		tw_dev->registers.command_que_addr = ((tw_pci_dev->base_address[0] & ~15) + 0x8);
+		tw_dev->registers.response_que_addr = ((tw_pci_dev->base_address[0] & ~15) + 0xC);
+		/* Save pci_dev struct to device extension */
+		tw_dev->tw_pci_dev = tw_pci_dev;
+
+		/* Poll status register for 60 secs for 'Controller Ready' flag */
+		if (tw_poll_status(tw_dev, TW_STATUS_MICROCONTROLLER_READY, 60)) {
+			printk(KERN_WARNING "3w-xxxx: tw_findcards(): Microcontroller not ready for card %d.\n", numcards);
+			tw_free_device_extension(tw_dev);
+			kfree(tw_dev);
+			continue;
+		}
+
+		/* Disable interrupts on the card */
+		tw_disable_interrupts(tw_dev);
+
+		while (tries < TW_MAX_RESET_TRIES) {
+			/* Do soft reset */
+			tw_soft_reset(tw_dev);
+
+			error = tw_aen_drain_queue(tw_dev);
+			if (error) {
+				printk(KERN_WARNING "3w-xxxx: tw_findcards(): No attention interrupt for card %d.\n", numcards);
+				tries++;
+				continue;
+			}
+
+			/* Check for controller errors */
+			if (tw_check_errors(tw_dev)) {
+				printk(KERN_WARNING "3w-xxxx: tw_findcards(): Controller errors found, soft resetting card %d.\n", numcards);
+				tries++;
+				continue;
+			}
+
+			/* Empty the response queue */
+			error = tw_empty_response_que(tw_dev);
+			if (error) {
+				printk(KERN_WARNING "3w-xxxx: tw_findcards(): Couldn't empty response queue for card %d.\n", numcards);
+				tries++;
+				continue;
+			}
+
+			/* Now the controller is in a good state */
+			break;
+		}
+
+		if (tries >= TW_MAX_RESET_TRIES) {
+			printk(KERN_WARNING "3w-xxxx: tw_findcards(): Controller error or no attention interrupt: giving up for card %d.\n", numcards);
+			tw_free_device_extension(tw_dev);
+			kfree(tw_dev);
+			continue;
+		}
+
+		/* Make sure that io region isn't already taken */
+		if (check_region((tw_dev->tw_pci_dev->base_address[0]), TW_IO_ADDRESS_RANGE)) {
+			printk(KERN_WARNING "3w-xxxx: tw_findcards(): Couldn't get io range 0x%lx-0x%lx for card %d.\n", 
+				(tw_dev->tw_pci_dev->base_address[0]), 
+				(tw_dev->tw_pci_dev->base_address[0]) + 
+				TW_IO_ADDRESS_RANGE, numcards);
+			tw_free_device_extension(tw_dev);
+			kfree(tw_dev);
+			continue;
+		}
+    
+		/* Reserve the io address space */
+		request_region((tw_dev->tw_pci_dev->base_address[0]), TW_IO_ADDRESS_RANGE, TW_DEVICE_NAME);
+		error = tw_initialize_units(tw_dev);
+		if (error) {
+			printk(KERN_WARNING "3w-xxxx: tw_findcards(): Couldn't initialize units for card %d.\n", numcards);
+			release_region((tw_dev->tw_pci_dev->base_address[0]), TW_IO_ADDRESS_RANGE);
+			tw_free_device_extension(tw_dev);
+			kfree(tw_dev);
+			continue;
+		}
+
+		error = tw_initconnection(tw_dev);
+		if (error) {
+			printk(KERN_WARNING "3w-xxxx: tw_findcards(): Couldn't initconnection for card %d.\n", numcards);
+			release_region((tw_dev->tw_pci_dev->base_address[0]), TW_IO_ADDRESS_RANGE);
+			tw_free_device_extension(tw_dev);
+			kfree(tw_dev);
+			continue;
+		}
+
+		/* Calculate max cmds per lun */
+		if (tw_dev->num_units > 0)
+			tw_host->cmd_per_lun = (TW_Q_LENGTH-2)/tw_dev->num_units;
+
+		/* Register the card with the kernel SCSI layer */
+		host = scsi_register(tw_host, sizeof(TW_Device_Extension));
+		
+		/* FIXME - check for NULL */
+
+		status_reg_value = inl(tw_dev->registers.status_reg_addr);
+
+		dprintk(KERN_NOTICE "scsi%d : Found a 3ware Storage Controller at 0x%x, IRQ: %d P-chip: %d.%d\n", host->host_no,
+				(u32)(tw_pci_dev->base_address[0]), tw_pci_dev->irq, 
+				(status_reg_value & TW_STATUS_MAJOR_VERSION_MASK) >> 28, 
+				(status_reg_value & TW_STATUS_MINOR_VERSION_MASK) >> 24);
+
+		if (host->hostdata) {
+			tw_dev2 = (TW_Device_Extension *)host->hostdata;
+			memcpy(tw_dev2, tw_dev, sizeof(TW_Device_Extension));
+			tw_device_extension_list[tw_device_extension_count] = tw_dev2;
+			numcards++;
+			tw_device_extension_count = numcards;
+			tw_dev2->host = host;
+		} else { 
+			printk(KERN_WARNING "3w-xxxx: tw_findcards(): Bad scsi host data for card %d.\n", numcards-1);
+			scsi_unregister(host);
+			release_region((tw_dev->tw_pci_dev->base_address[0]), TW_IO_ADDRESS_RANGE);
+			tw_free_device_extension(tw_dev);
+			kfree(tw_dev);
+			continue;
+		}
+    
+		/* Re-enable interrupts on the card */
+		tw_enable_interrupts(tw_dev2);
+
+		/* Now setup the interrupt handler */
+		error = tw_setup_irq(tw_dev2);
+		if (error) {
+			printk(KERN_WARNING "3w-xxxx: tw_findcards(): Error requesting irq for card %d.\n", numcards-1);
+			scsi_unregister(host);
+			release_region((tw_dev->tw_pci_dev->base_address[0]), TW_IO_ADDRESS_RANGE);
+
+			tw_free_device_extension(tw_dev);
+			kfree(tw_dev);
+			numcards--;
+			continue;
+		}
+
+		/* Free the temporary device extension */
+		if (tw_dev)
+			kfree(tw_dev);
+	}
+
+	if (numcards == 0) 
+		printk(KERN_WARNING "3w-xxxx: tw_findcards(): No cards found.\n");
+
+	return numcards;
+} /* End tw_findcards() */
+
+/* This function will free up device extension resources */
+void tw_free_device_extension(TW_Device_Extension *tw_dev)
+{
+	int i, imax;
+	imax = TW_Q_LENGTH;
+
+	dprintk(KERN_NOTICE "3w-xxxx: tw_free_device_extension()\n");
+	/* Free command packet and generic buffer memory */
+	for (i=0;i<imax;i++) {
+		if (tw_dev->command_packet_virtual_address[i]) 
+			kfree(tw_dev->command_packet_virtual_address[i]);
+
+		if (tw_dev->alignment_virtual_address[i])
+			kfree(tw_dev->alignment_virtual_address[i]);
+	}
+} /* End tw_free_device_extension() */
+
+/* This function will send an initconnection command to controller */
+int tw_initconnection(TW_Device_Extension *tw_dev) 
+{
+	u32 command_que_addr, command_que_value;
+	u32 status_reg_addr, status_reg_value;
+	u32 response_que_addr;
+	TW_Command  *command_packet;
+	TW_Response_Queue response_queue;
+	int request_id = 0;
+	int i = 0;
+	int imax = 0;
+
+	dprintk(KERN_NOTICE "3w-xxxx: tw_initconnection()\n");
+	command_que_addr = tw_dev->registers.command_que_addr;
+	status_reg_addr = tw_dev->registers.status_reg_addr;
+	response_que_addr = tw_dev->registers.response_que_addr;
+
+	/* Initialize InitConnection command packet */
+	if (tw_dev->command_packet_virtual_address[request_id] == NULL) {
+		printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad command packet virtual address.\n");
+		return 1;
+	}
+
+	command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
+	memset(command_packet, 0, sizeof(TW_Sector));
+	command_packet->byte0.opcode = TW_OP_INIT_CONNECTION;
+	command_packet->byte0.sgl_offset = 0x0;
+	command_packet->size = TW_INIT_COMMAND_PACKET_SIZE;
+	command_packet->request_id = request_id;
+	command_packet->byte3.unit = 0x0;
+	command_packet->byte3.host_id = 0x0;
+	command_packet->status = 0x0;
+	command_packet->flags = 0x0;
+	command_packet->byte6.message_credits = TW_INIT_MESSAGE_CREDITS; 
+	command_packet->byte8.init_connection.response_queue_pointer = 0x0;
+	command_que_value = tw_dev->command_packet_physical_address[request_id];
+
+	if (command_que_value == 0) {
+		printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad command packet physical address.\n");
+		return 1;
+	}
+  
+	/* Send command packet to the board */
+	outl(command_que_value, command_que_addr);
+    
+	/* Poll for completion */
+	imax = TW_POLL_MAX_RETRIES;
+	for (i=0;i<imax;i++) {
+		mdelay(10);
+		status_reg_value = inl(status_reg_addr);
+		if (tw_check_bits(status_reg_value)) {
+			printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Unexpected bits.\n");
+			return 1;
+		}
+		if ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
+			response_queue.value = inl(response_que_addr);
+			request_id = (unsigned char)response_queue.u.response_id;
+			if (request_id != 0) {
+				/* unexpected request id */
+				printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Unexpected request id.\n");
+				return 1;
+			}
+			if (command_packet->status != 0) {
+				/* bad response */
+				printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad response, flags = 0x%x.\n", command_packet->flags);
+				return 1;
+			}
+			break;	/* Response was okay, so we exit */
+		}
+	}
+	return 0;
+} /* End tw_initconnection() */
+
+/* This function will initialize the fields of a device extension */
+int tw_initialize_device_extension(TW_Device_Extension *tw_dev)
+{
+	int i, imax;
+
+	dprintk(KERN_NOTICE "3w-xxxx: tw_initialize_device_extension()\n");
+	imax = TW_Q_LENGTH;
+
+	for (i=0; i<imax; i++) {
+		/* Initialize command packet buffers */
+		tw_allocate_memory(tw_dev, i, sizeof(TW_Sector), 0);
+		if (tw_dev->command_packet_virtual_address[i] == NULL) {
+			printk(KERN_WARNING "3w-xxxx: tw_initialize_device_extension(): Bad command packet virtual address.\n");
+			return 1;
+		}
+		memset(tw_dev->command_packet_virtual_address[i], 0, sizeof(TW_Sector));
+    
+		/* Initialize generic buffer */
+		tw_allocate_memory(tw_dev, i, sizeof(TW_Sector), 1);
+		if (tw_dev->alignment_virtual_address[i] == NULL) {
+			printk(KERN_WARNING "3w-xxxx: tw_initialize_device_extension(): Bad alignment virtual address.\n");
+			return 1;
+		}
+		memset(tw_dev->alignment_virtual_address[i], 0, sizeof(TW_Sector));
+
+		tw_dev->free_queue[i] = i;
+		tw_dev->state[i] = TW_S_INITIAL;
+		tw_dev->ioctl_size[i] = 0;
+		tw_dev->aen_queue[i] = 0;
+	}
+
+	for (i=0;i<TW_MAX_UNITS;i++)
+		tw_dev->is_unit_present[i] = 0;
+
+	tw_dev->num_units = 0;
+	tw_dev->num_aborts = 0;
+	tw_dev->num_resets = 0;
+	tw_dev->free_head = TW_Q_START;
+	tw_dev->free_tail = TW_Q_LENGTH - 1;
+	tw_dev->posted_request_count = 0;
+	tw_dev->max_posted_request_count = 0;
+	tw_dev->max_sgl_entries = 0;
+	tw_dev->sgl_entries = 0;
+	tw_dev->host = NULL;
+	tw_dev->pending_head = TW_Q_START;
+	tw_dev->pending_tail = TW_Q_START;
+	tw_dev->aen_head = 0;
+	tw_dev->aen_tail = 0;
+	tw_dev->sector_count = 0;
+	tw_dev->max_sector_count = 0;
+	spin_lock_init(&tw_dev->tw_lock);
+	return 0;
+} /* End tw_initialize_device_extension() */
+
+/* This function will get unit info from the controller */
+int tw_initialize_units(TW_Device_Extension *tw_dev) 
+{
+	int found = 0;
+	unsigned char request_id = 0;
+	TW_Command *command_packet;
+	TW_Param *param;
+	int i, imax, num_units = 0;
+	u32 status_reg_addr, status_reg_value;
+	u32 command_que_addr, command_que_value;
+	u32 response_que_addr;
+	TW_Response_Queue response_queue;
+	u32 param_value;
+	unsigned char *is_unit_present;
+
+	dprintk(KERN_NOTICE "3w-xxxx: tw_initialize_units()\n");
+
+	status_reg_addr = tw_dev->registers.status_reg_addr;
+	command_que_addr = tw_dev->registers.command_que_addr;
+	response_que_addr = tw_dev->registers.response_que_addr;
+  
+	/* Setup the command packet */
+	command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
+	if (command_packet == NULL) {
+		printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad command packet virtual address.\n");
+		return 1;
+	}
+	memset(command_packet, 0, sizeof(TW_Sector));
+	command_packet->byte0.opcode      = TW_OP_GET_PARAM;
+	command_packet->byte0.sgl_offset  = 2;
+	command_packet->size              = 4;
+	command_packet->request_id        = request_id;
+	command_packet->byte3.unit        = 0;
+	command_packet->byte3.host_id     = 0;
+	command_packet->status            = 0;
+	command_packet->flags             = 0;
+	command_packet->byte6.block_count = 1;
+
+	/* Now setup the param */
+	if (tw_dev->alignment_virtual_address[request_id] == NULL) {
+		printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad alignment virtual address.\n");
+		return 1;
+	}
+	param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
+	memset(param, 0, sizeof(TW_Sector));
+	param->table_id = 3;       /* unit summary table */
+	param->parameter_id = 3;   /* unitstatus parameter */
+	param->parameter_size_bytes = TW_MAX_UNITS;
+	param_value = tw_dev->alignment_physical_address[request_id];
+	if (param_value == 0) {
+		printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad alignment physical address.\n");
+		return 1;
+	}
+
+	command_packet->byte8.param.sgl[0].address = param_value;
+	command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
+
+	/* Post the command packet to the board */
+	command_que_value = tw_dev->command_packet_physical_address[request_id];
+	if (command_que_value == 0) {
+		printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad command packet physical address.\n");
+		return 1;
+	}
+	outl(command_que_value, command_que_addr);
+
+	/* Poll for completion */
+	imax = TW_POLL_MAX_RETRIES;
+	for(i=0; i<imax; i++) {
+		mdelay(10);
+		status_reg_value = inl(status_reg_addr);
+		if (tw_check_bits(status_reg_value)) {
+			printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected bits.\n");
+			return 1;
+		}
+		if ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
+			response_queue.value = inl(response_que_addr);
+			request_id = (unsigned char)response_queue.u.response_id;
+			if (request_id != 0) {
+				/* unexpected request id */
+				printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected request id.\n");
+				return 1;
+			}
+			if (command_packet->status != 0) {
+				/* bad response */
+				printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad response, flags = 0x%x.\n", command_packet->flags);
+				return 1;
+			}
+			found = 1;
+			break;
+		}
+	}
+	if (found == 0) {
+		/* response never received */
+		printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): No response.\n");
+		return 1;
+	}
+
+	param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
+	is_unit_present = (unsigned char *)&(param->data[0]);
+  
+	/* Show all units present */
+	imax = TW_MAX_UNITS;
+	for(i=0; i<imax; i++) {
+		if (is_unit_present[i] == 0) {
+			tw_dev->is_unit_present[i] = FALSE;
+		} else {
+			dprintk(KERN_NOTICE "3w-xxxx: tw_initialize_units(): Unit %d found.\n", i);
+			tw_dev->is_unit_present[i] = TRUE;
+			num_units++;
+		}
+	}
+	tw_dev->num_units = num_units;
+
+	if (num_units == 0) {
+		printk(KERN_NOTICE "3w-xxxx: tw_initialize_units(): No units found.\n");
+		return 1;
+	}
+  
+	return 0;
+} /* End tw_initialize_units() */
+
+/* This function is the interrupt service routine */
+static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs) 
+{
+	int request_id;
+	u32 status_reg_addr, status_reg_value;
+	u32 response_que_addr;
+	TW_Device_Extension *tw_dev = (TW_Device_Extension *)dev_instance;
+	TW_Response_Queue response_que;
+	int error = 0;
+	int do_response_interrupt=0;
+	int do_attention_interrupt=0;
+	int do_host_interrupt=0;
+	int do_command_interrupt=0;
+	int flags = 0;
+	int flags2 = 0;
+	TW_Command *command_packet;
+	spin_lock_irqsave(&io_request_lock, flags);
+
+	if (tw_dev->tw_pci_dev->irq == irq) {
+		spin_lock_irqsave(&tw_dev->tw_lock, flags2);
+		dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt()\n");
+
+		/* Read the registers */
+		status_reg_addr = tw_dev->registers.status_reg_addr;
+		response_que_addr = tw_dev->registers.response_que_addr;
+		status_reg_value = inl(status_reg_addr);
+
+		/* Check which interrupt */
+		if (status_reg_value & TW_STATUS_HOST_INTERRUPT)
+			do_host_interrupt=1;
+		if (status_reg_value & TW_STATUS_ATTENTION_INTERRUPT)
+			do_attention_interrupt=1;
+		if (status_reg_value & TW_STATUS_COMMAND_INTERRUPT)
+			do_command_interrupt=1;
+		if (status_reg_value & TW_STATUS_RESPONSE_INTERRUPT)
+			do_response_interrupt=1;
+
+		/* Handle host interrupt */
+		if (do_host_interrupt) {
+			dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received host interrupt.\n");
+			tw_clear_host_interrupt(tw_dev);
+		}
+
+		/* Handle attention interrupt */
+		if (do_attention_interrupt) {
+			dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received attention interrupt.\n");
+			tw_state_request_start(tw_dev, &request_id);
+			error = tw_aen_read_queue(tw_dev, request_id);
+			if (error) {
+				printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Error reading aen queue.\n");
+				tw_dev->state[request_id] = TW_S_COMPLETED;
+				tw_state_request_finish(tw_dev, request_id);
+			} else {
+				dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Clearing attention interrupt.\n");
+				tw_clear_attention_interrupt(tw_dev);
+			}
+		}
+
+		/* Handle command interrupt */
+		if (do_command_interrupt) {
+			/* Drain as many pending commands as we can */
+			while (tw_dev->pending_request_count > 0) {
+				request_id = tw_dev->pending_queue[tw_dev->pending_head];
+				if (tw_dev->state[request_id] != TW_S_PENDING) {
+					printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Found request id that wasn't pending.\n");
+					break;
+				}
+				if (tw_post_command_packet(tw_dev, request_id)==0) {
+					if (tw_dev->pending_head == TW_Q_LENGTH-1) {
+						tw_dev->pending_head = TW_Q_START;
+					} else {
+						tw_dev->pending_head = tw_dev->pending_head + 1;
+					}
+					tw_dev->pending_request_count--;
+				} else {
+					break;
+				}
+			}
+			/* If there are no more pending requests, we mask command interrupt */
+			if (tw_dev->pending_request_count == 0) 
+				tw_mask_command_interrupt(tw_dev);
+		}
+
+		/* Handle response interrupt */
+		if (do_response_interrupt) {
+			/* Drain the response queue from the board */
+			while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
+				response_que.value = inl(response_que_addr);
+				request_id = response_que.u.response_id;
+				command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
+				if (command_packet->status != 0) {
+					printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Bad response, flags = 0x%x.\n", command_packet->flags);
+				}
+				if (tw_dev->state[request_id] != TW_S_POSTED) {
+					printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Received a request id (%d) (opcode = 0x%x) that wasn't posted.\n", request_id, command_packet->byte0.opcode);
+				}
+				error = 0;
+				dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Response queue request id: %d.\n", request_id);
+				/* Check for internal command */
+				if (tw_dev->srb[request_id] == 0) {
+					dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Found internally posted command.\n");
+					error = tw_aen_complete(tw_dev, request_id);
+					if (error) {
+						printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Error completing aen.\n");
+					}
+					status_reg_value = inl(status_reg_addr);
+					if (tw_check_bits(status_reg_value)) {
+						printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
+					}
+		} else {
+				switch (tw_dev->srb[request_id]->cmnd[0]) {
+					case READ_10:
+						dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_10\n");
+					case READ_6:
+						dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_6\n");
+						break;
+					case WRITE_10:
+						dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_10\n");
+					case WRITE_6:
+						dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_6\n");
+						break;
+					case INQUIRY:
+						dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught INQUIRY\n");
+						error = tw_scsiop_inquiry_complete(tw_dev, request_id);
+						break;
+					case READ_CAPACITY:
+						dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_CAPACITY\n");
+						error = tw_scsiop_read_capacity_complete(tw_dev, request_id);
+						break;
+					case TW_IOCTL:
+						dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught TW_IOCTL\n");
+						error = tw_ioctl_complete(tw_dev, request_id);
+						break;
+					default:
+						printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unknown scsi opcode: 0x%x.\n", tw_dev->srb[request_id]->cmnd[0]);
+						tw_dev->srb[request_id]->result = (DID_BAD_TARGET << 16);
+						tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
+					}
+					if (error) {
+						/* Tell scsi layer there was an error */
+						printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Scsi Error.\n");
+						tw_dev->srb[request_id]->result = (DID_ERROR << 16);
+					} else {
+						/* Tell scsi layer command was a success */
+						tw_dev->srb[request_id]->result = (DID_OK << 16);
+					}
+					tw_dev->state[request_id] = TW_S_COMPLETED;
+					tw_state_request_finish(tw_dev, request_id);
+					tw_dev->posted_request_count--;
+					tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
+					status_reg_value = inl(status_reg_addr);
+					if (tw_check_bits(status_reg_value)) {
+						printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
+					}
+				}
+			}
+		}
+		spin_unlock_irqrestore(&tw_dev->tw_lock, flags2);
+	}
+	spin_unlock_irqrestore(&io_request_lock, flags);
+}	/* End tw_interrupt() */
+
+/* This function handles ioctls from userspace to the driver */
+int tw_ioctl(TW_Device_Extension *tw_dev, int request_id)
+{
+	unsigned char opcode;
+	int bufflen;
+	TW_Param *param;
+	TW_Command *command_packet;
+	u32 param_value;
+	TW_Ioctl *ioctl = NULL;
+	int tw_aen_code;
+
+	ioctl = (TW_Ioctl *)tw_dev->srb[request_id]->request_buffer;
+	if (ioctl == NULL) {
+		printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Request buffer NULL.\n");
+		tw_dev->state[request_id] = TW_S_COMPLETED;
+		tw_state_request_finish(tw_dev, request_id);
+		tw_dev->srb[request_id]->result = (DID_OK << 16);
+		tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
+		return 0;
+	}
+	bufflen = tw_dev->srb[request_id]->request_bufflen;
+
+	/* Initialize command packet */
+	command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
+	if (command_packet == NULL) {
+		printk(KERN_WARNING "3w-xxxx: twioctl(): Bad command packet virtual address.\n");
+		tw_dev->state[request_id] = TW_S_COMPLETED;
+		tw_state_request_finish(tw_dev, request_id);
+		tw_dev->srb[request_id]->result = (DID_OK << 16);
+		tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
+		return 0;
+	}
+	memset(command_packet, 0, sizeof(TW_Sector));
+
+	/* Initialize param */
+	if (tw_dev->alignment_virtual_address[request_id] == NULL) {
+		printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Bad alignment virtual address.\n");
+		tw_dev->state[request_id] = TW_S_COMPLETED;
+		tw_state_request_finish(tw_dev, request_id);
+		tw_dev->srb[request_id]->result = (DID_OK << 16);
+		tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
+		return 0;
+	}
+	param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
+	memset(param, 0, sizeof(TW_Sector));
+
+	dprintk(KERN_NOTICE "opcode = %d table_id = %d parameter_id = %d parameter_size_bytes = %d\n", ioctl->opcode, ioctl->table_id, ioctl->parameter_id,, ioctl->parameter_size_bytes);
+	opcode = ioctl->opcode;
+
+	switch (opcode) {
+		case TW_OP_NOP:
+			dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_NOP.\n");
+			command_packet->byte0.opcode = TW_OP_NOP;
+			break;
+		case TW_OP_GET_PARAM:
+			dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_GET_PARAM.\n");
+			command_packet->byte0.opcode = TW_OP_GET_PARAM;
+			param->table_id = ioctl->table_id;
+			param->parameter_id = ioctl->parameter_id;
+			param->parameter_size_bytes = ioctl->parameter_size_bytes;
+			tw_dev->ioctl_size[request_id] = ioctl->parameter_size_bytes;
+			dprintk(KERN_NOTICE "table_id = %d parameter_id = %d parameter_size_bytes %d\n", param->table_id, param->parameter_id, param->parameter_size_bytes);
+			break;
+		case TW_OP_SET_PARAM:
+			dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_SET_PARAM: table_id = %d, parameter_id = %d, parameter_size_bytes = %d.\n",
+			ioctl->table_id, ioctl->parameter_id, ioctl->parameter_size_bytes);
+			command_packet->byte0.opcode = TW_OP_SET_PARAM;
+			param->table_id = ioctl->table_id;
+			param->parameter_id = ioctl->parameter_id;
+			param->parameter_size_bytes = ioctl->parameter_size_bytes;
+			memcpy(param->data, ioctl->data, ioctl->parameter_size_bytes);
+			break;
+		case TW_OP_AEN_LISTEN:
+			dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_AEN_LISTEN.\n");
+			if (tw_dev->aen_head == tw_dev->aen_tail) {
+				/* aen queue empty */
+				dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): Aen queue empty.\n");
+				tw_aen_code = TW_AEN_QUEUE_EMPTY;
+				memcpy(tw_dev->srb[request_id]->request_buffer, &tw_aen_code, ioctl->parameter_size_bytes);
+			} else {
+				/* Copy aen queue entry to request buffer */
+				dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): Returning aen 0x%x\n", tw_dev->aen_queue[tw_dev->aen_head]);
+				tw_aen_code = tw_dev->aen_queue[tw_dev->aen_head];
+				memcpy(tw_dev->srb[request_id]->request_buffer, &tw_aen_code, ioctl->parameter_size_bytes);
+				if (tw_dev->aen_head == TW_Q_LENGTH - 1) {
+					tw_dev->aen_head = TW_Q_START;
+				} else {
+					tw_dev->aen_head = tw_dev->aen_head + 1;
+				}
+			}
+			tw_dev->state[request_id] = TW_S_COMPLETED;
+			tw_state_request_finish(tw_dev, request_id);
+			tw_dev->srb[request_id]->result = (DID_OK << 16);
+			tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
+			return 0;
+		default:
+			printk(KERN_WARNING "3w-xxxx: Unknown ioctl 0x%x.\n", opcode);
+			tw_dev->state[request_id] = TW_S_COMPLETED;
+			tw_state_request_finish(tw_dev, request_id);
+			tw_dev->srb[request_id]->result = (DID_OK << 16);
+			tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
+			return 0;
+	}
+
+	param_value = tw_dev->alignment_physical_address[request_id];
+	if (param_value == 0) {
+		printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Bad alignment physical address.\n");
+		tw_dev->state[request_id] = TW_S_COMPLETED;
+		tw_state_request_finish(tw_dev, request_id);
+		tw_dev->srb[request_id]->result = (DID_OK << 16);
+		tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
+	}
+
+	command_packet->byte8.param.sgl[0].address = param_value;
+	command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
+
+	command_packet->byte0.sgl_offset = 2;
+	command_packet->size = 4;
+	command_packet->request_id = request_id;
+	command_packet->byte3.unit = 0;
+	command_packet->byte3.host_id = 0;
+	command_packet->status = 0;
+	command_packet->flags = 0;
+	command_packet->byte6.parameter_count = 1;
+
+	/* Now try to post the command to the board */
+	tw_post_command_packet(tw_dev, request_id);
+
+	return 0;
+} /* End tw_ioctl() */
+
+/* This function is called by the isr to complete ioctl requests */
+int tw_ioctl_complete(TW_Device_Extension *tw_dev, int request_id)
+{
+	unsigned char *param_data;
+	unsigned char *buff;
+	TW_Param *param;
+
+	dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl_complete()\n");
+	buff = tw_dev->srb[request_id]->request_buffer;
+	if (buff == NULL) {
+		printk(KERN_WARNING "3w-xxxx: tw_ioctl_complete(): Request buffer NULL.\n");
+		return 1;
+	}
+	dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl_complete(): Request_bufflen = %d\n", tw_dev->srb[request_id]->request_bufflen);
+	memset(buff, 0, tw_dev->srb[request_id]->request_bufflen);
+	param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
+	if (param == NULL) {
+		printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Bad alignment virtual address.\n");
+		return 1;
+	}
+	param_data = &(param->data[0]);
+
+	memcpy(buff, param_data, tw_dev->ioctl_size[request_id]);
+
+	return 0;
+} /* End tw_ioctl_complete() */
+
+/* This function will mask the command interrupt */
+void tw_mask_command_interrupt(TW_Device_Extension *tw_dev)
+{
+	u32 control_reg_addr, control_reg_value;
+	
+	control_reg_addr = tw_dev->registers.control_reg_addr;
+	control_reg_value = TW_CONTROL_MASK_COMMAND_INTERRUPT;
+	outl(control_reg_value, control_reg_addr);
+} /* End tw_mask_command_interrupt() */
+
+/* This function will poll the status register for a flag */
+int tw_poll_status(TW_Device_Extension *tw_dev, u32 flag, int seconds)
+{
+	u32 status_reg_addr, status_reg_value;
+	struct timeval before, timeout;
+
+	status_reg_addr = tw_dev->registers.status_reg_addr;
+	do_gettimeofday(&before);
+	status_reg_value = inl(status_reg_addr);
+
+	while ((status_reg_value & flag) != flag) {
+		status_reg_value = inl(status_reg_addr);
+		do_gettimeofday(&timeout);
+		if (before.tv_sec + seconds < timeout.tv_sec) { 
+			printk(KERN_WARNING "3w-xxxx: tw_poll_status(): Flag 0x%x not found.\n", flag);
+			return 1;
+		}
+		mdelay(1);
+	}
+	return 0;
+} /* End tw_poll_status() */
+
+/* This function will attempt to post a command packet to the board */
+int tw_post_command_packet(TW_Device_Extension *tw_dev, int request_id)
+{
+	u32 status_reg_addr, status_reg_value;
+	u32 command_que_addr, command_que_value;
+
+	dprintk(KERN_NOTICE "3w-xxxx: tw_post_command_packet()\n");
+	command_que_addr = tw_dev->registers.command_que_addr;
+	command_que_value = tw_dev->command_packet_physical_address[request_id];
+	status_reg_addr = tw_dev->registers.status_reg_addr;
+	status_reg_value = inl(status_reg_addr);
+
+	if (tw_check_bits(status_reg_value)) 
+		printk(KERN_WARNING "3w-xxxx: tw_post_command_packet(): Unexpected bits.\n");
+
+	if ((status_reg_value & TW_STATUS_COMMAND_QUEUE_FULL) == 0) {
+		/* We successfully posted the command packet */
+		outl(command_que_value, command_que_addr);
+		tw_dev->state[request_id] = TW_S_POSTED;
+		tw_dev->posted_request_count++;
+		if (tw_dev->posted_request_count > tw_dev->max_posted_request_count) {
+			tw_dev->max_posted_request_count = tw_dev->posted_request_count;
+		}
+	} else {
+		/* Couldn't post the command packet, so we do it in the isr */
+		if (tw_dev->state[request_id] != TW_S_PENDING) {
+			tw_dev->state[request_id] = TW_S_PENDING;
+			tw_dev->pending_request_count++;
+			if (tw_dev->pending_request_count > tw_dev->max_pending_request_count) {
+				tw_dev->max_pending_request_count = tw_dev->pending_request_count;
+			}
+			tw_dev->pending_queue[tw_dev->pending_tail] = request_id;
+			if (tw_dev->pending_tail == TW_Q_LENGTH-1) {
+				tw_dev->pending_tail = TW_Q_START;
+			} else {
+				tw_dev->pending_tail = tw_dev->pending_tail + 1;
+			}
+		} 
+		tw_unmask_command_interrupt(tw_dev);
+		return 1;
+	}
+	return 0;
+} /* End tw_post_command_packet() */
+
+/* This function will reset a device extension */
+int tw_reset_device_extension(TW_Device_Extension *tw_dev) 
+{
+	int imax = 0;
+	int i = 0;
+	Scsi_Cmnd *srb;
+
+	dprintk(KERN_NOTICE "3w-xxxx: tw_reset_device_extension()\n");
+	imax = TW_Q_LENGTH;
+
+	if (tw_reset_sequence(tw_dev)) {
+		printk(KERN_WARNING "3w-xxxx: tw_reset_device_extension(): Reset sequence failed for card %d.\n", tw_dev->host->host_no);
+		return 1;
+	}
+
+	/* Abort all requests that are in progress */
+	for (i=0;i<imax;i++) {
+		if ((tw_dev->state[i] != TW_S_FINISHED) && 
+		    (tw_dev->state[i] != TW_S_INITIAL) &&
+		    (tw_dev->state[i] != TW_S_COMPLETED)) {
+			srb = tw_dev->srb[i];
+			srb->result = (DID_RESET << 16);
+			tw_dev->srb[i]->scsi_done(tw_dev->srb[i]);
+		}
+	}
+
+	/* Reset queues and counts */
+	for (i=0;i<imax;i++) {
+		tw_dev->free_queue[i] = i;
+		tw_dev->state[i] = TW_S_INITIAL;
+	}
+	tw_dev->free_head = TW_Q_START;
+	tw_dev->free_tail = TW_Q_LENGTH - 1;
+	tw_dev->posted_request_count = 0;
+	tw_dev->pending_request_count = 0;
+	tw_dev->pending_head = TW_Q_START;
+	tw_dev->pending_tail = TW_Q_START;
+
+	return 0;
+} /* End tw_reset_device_extension() */
+
+/* This function will reset a controller */
+int tw_reset_sequence(TW_Device_Extension *tw_dev) 
+{
+	int error = 0;
+	int tries = 0;
+
+	/* Disable interrupts */
+	tw_disable_interrupts(tw_dev);
+
+	/* Reset the board */
+	while (tries < TW_MAX_RESET_TRIES) {
+		tw_soft_reset(tw_dev);
+
+		error = tw_aen_drain_queue(tw_dev);
+		if (error) {
+			printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): No attention interrupt for card %d.\n", tw_dev->host->host_no);
+			tries++;
+			continue;
+		}
+
+		/* Check for controller errors */
+		if (tw_check_errors(tw_dev)) {
+			printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): Controller errors found, soft resetting card %d.\n", tw_dev->host->host_no);
+			tries++;
+			continue;
+		}
+
+		/* Empty the response queue again */
+		error = tw_empty_response_que(tw_dev);
+		if (error) {
+			printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): Couldn't empty response queue for card %d.\n", tw_dev->host->host_no);
+			tries++;
+			continue;
+		}
+
+		/* Now the controller is in a good state */
+		break;
+	}
+
+	if (tries >= TW_MAX_RESET_TRIES) {
+		printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): Controller error or no attention interrupt: giving up for card %d.\n", tw_dev->host->host_no);
+		return 1;
+	}
+
+	error = tw_initconnection(tw_dev);
+	if (error) {
+		printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): Couldn't initconnection for card %d.\n", tw_dev->host->host_no);
+		return 1;
+	}
+
+	/* Re-enable interrupts */
+	tw_enable_interrupts(tw_dev);
+
+	return 0;
+} /* End tw_reset_sequence() */
+
+/* This funciton returns unit geometry in cylinders/heads/sectors */
+int tw_scsi_biosparam(Disk *disk, kdev_t dev, int geom[]) 
+{
+	int heads, sectors, cylinders;
+	TW_Device_Extension *tw_dev;
+	
+	dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_biosparam()\n");
+	tw_dev = (TW_Device_Extension *)disk->device->host->hostdata;
+
+	heads = 64;
+	sectors = 32;
+	cylinders = disk->capacity / (heads * sectors);
+
+	if (disk->capacity >= 0x200000) {
+		heads = 255;
+		sectors = 63;
+		cylinders = disk->capacity / (heads * sectors);
+	}
+
+	dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_biosparam(): heads = %d, sectors = %d, cylinders = %d\n", heads, sectors, cylinders);
+	geom[0] = heads;			 
+	geom[1] = sectors;
+	geom[2] = cylinders;
+
+	return 0;
+} /* End tw_scsi_biosparam() */
+
+/* This function will find and initialize any cards */
+int tw_scsi_detect(Scsi_Host_Template *tw_host)
+{
+	dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_detect()\n");
+
+	/* Check if the kernel has PCI interface compiled in */
+	if (!pci_present()) {
+		printk(KERN_WARNING "3w-xxxx: tw_scsi_detect(): No pci interface present.\n");
+		return 0;
+	}
+
+	return(tw_findcards(tw_host));
+} /* End tw_scsi_detect() */
+
+/* This is the new scsi eh abort function */
+int tw_scsi_eh_abort(Scsi_Cmnd *SCpnt) 
+{
+	TW_Device_Extension *tw_dev=NULL;
+	int i = 0;
+
+	dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_eh_abort()\n");
+
+	if (!SCpnt) {
+		printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Invalid Scsi_Cmnd.\n");
+		return (FAILED);
+	}
+
+	tw_dev = (TW_Device_Extension *)SCpnt->host->hostdata;
+	if (tw_dev == NULL) {
+		printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Invalid device extension.\n");
+		return (FAILED);
+	}
+
+	spin_lock(&tw_dev->tw_lock);
+	tw_dev->num_aborts++;
+
+	/* If the command hasn't been posted yet, we can do the abort */
+	for (i=0;i<TW_Q_LENGTH;i++) {
+		if (tw_dev->srb[i] == SCpnt) {
+			if (tw_dev->state[i] == TW_S_STARTED) {
+				printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Abort succeeded for started Scsi_Cmnd 0x%x\n", (u32)tw_dev->srb[i]);
+				tw_dev->state[i] = TW_S_COMPLETED;
+				tw_state_request_finish(tw_dev, i);
+				spin_unlock(&tw_dev->tw_lock);
+				return (SUCCESS);
+			}
+			if (tw_dev->state[i] == TW_S_PENDING) {
+				printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Abort succeeded for pending Scsi_Cmnd 0x%x\n", (u32)tw_dev->srb[i]);
+				if (tw_dev->pending_head == TW_Q_LENGTH-1) {
+					tw_dev->pending_head = TW_Q_START;
+				} else {
+					tw_dev->pending_head = tw_dev->pending_head + 1;
+				}
+				tw_dev->pending_request_count--;
+				tw_dev->state[i] = TW_S_COMPLETED;
+				tw_state_request_finish(tw_dev, i);
+				spin_unlock(&tw_dev->tw_lock);
+				return (SUCCESS);
+			}
+		}
+	}
+
+	/* If the command has already been posted, we have to reset the card */
+	printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Abort failed for unknown Scsi_Cmnd 0x%x, resetting card %d.\n", (u32)SCpnt, tw_dev->host->host_no);
+
+	if (tw_reset_device_extension(tw_dev)) {
+		printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Reset failed for card %d.\n", tw_dev->host->host_no);
+		spin_unlock(&tw_dev->tw_lock);
+		return (FAILED);
+	}
+	spin_unlock(&tw_dev->tw_lock);
+
+	return (SUCCESS);
+} /* End tw_scsi_eh_abort() */
+
+/* This is the new scsi eh reset function */
+int tw_scsi_eh_reset(Scsi_Cmnd *SCpnt) 
+{
+	TW_Device_Extension *tw_dev=NULL;
+	int flags = 0;
+
+	dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_eh_reset()\n");
+
+	if (!SCpnt) {
+		printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_reset(): Invalid Scsi_Cmnd.\n");
+		return (FAILED);
+	}
+
+	tw_dev = (TW_Device_Extension *)SCpnt->host->hostdata;
+	if (tw_dev == NULL) {
+		printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_reset(): Invalid device extension.\n");
+		return (FAILED);
+	}
+
+	spin_lock_irqsave(&tw_dev->tw_lock, flags);
+	tw_dev->num_resets++;
+
+	/* Now reset the card and some of the device extension data */
+	if (tw_reset_device_extension(tw_dev)) {
+		printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_reset(): Reset failed for card %d.\n", tw_dev->host->host_no);
+		spin_unlock_irqrestore(&tw_dev->tw_lock, flags);
+		return (FAILED);
+	}
+	printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_reset(): Reset succeeded for card %d.\n", tw_dev->host->host_no);
+	spin_unlock_irqrestore(&tw_dev->tw_lock, flags);
+
+	return (SUCCESS);
+} /* End tw_scsi_eh_reset() */
+
+/* This function handles input and output from /proc/scsi/3w-xxxx/x */
+int tw_scsi_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout) 
+{
+	TW_Device_Extension *tw_dev = NULL;
+	TW_Info info;
+	int i;
+	int j;
+
+	dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_proc_info()\n");
+
+	/* Find the correct device extension */
+	for (i=0;i<tw_device_extension_count;i++) 
+		if (tw_device_extension_list[i]->host->host_no == hostno) 
+			tw_dev = tw_device_extension_list[i];
+	if (tw_dev == NULL) {
+		printk(KERN_WARNING "3w-xxxx: tw_scsi_proc_info(): Couldn't locate device extension.\n");
+		return (-EINVAL);
+	}
+
+	info.buffer = buffer;
+	info.length = length;
+	info.offset = offset;
+	info.position = 0;
+	
+	if (inout) {
+		/* Write */
+		if (strncmp(buffer, "debug", 5) == 0) {
+			printk(KERN_INFO "3w-xxxx: Posted commands:\n");
+			for (j=0;j<TW_Q_LENGTH;j++) {
+				if (tw_dev->state[j] == TW_S_POSTED) {
+					TW_Command *command = (TW_Command *)tw_dev->command_packet_virtual_address[j];
+					printk(KERN_INFO "3w-xxxx: Request_id: %d\n", j);
+					printk(KERN_INFO "Opcode: 0x%x\n", command->byte0.opcode);
+					printk(KERN_INFO "Block_count: 0x%x\n", command->byte6.block_count);
+					printk(KERN_INFO "LBA: 0x%x\n", (u32)command->byte8.io.lba);
+					printk(KERN_INFO "Physical command packet addr: 0x%x\n", tw_dev->command_packet_physical_address[j]);
+					printk(KERN_INFO "Scsi_Cmnd: 0x%x\n", (u32)tw_dev->srb[j]);
+				}
+			}
+			printk(KERN_INFO "3w-xxxx: Free_head: %3d\n", tw_dev->free_head);
+			printk(KERN_INFO "3w-xxxx: Free_tail: %3d\n", tw_dev->free_tail);
+		} 
+		return length;
+	} else {
+		/* Read */
+		if (start) {
+			*start = buffer;
+		}
+		tw_copy_info(&info, "scsi%d: 3ware Storage Controller\n", hostno);
+		tw_copy_info(&info, "Driver version: %s\n", tw_driver_version);
+		tw_copy_info(&info, "Current commands posted:       %3d\n", tw_dev->posted_request_count);
+		tw_copy_info(&info, "Max commands posted:           %3d\n", tw_dev->max_posted_request_count);
+		tw_copy_info(&info, "Current pending commands:      %3d\n", tw_dev->pending_request_count);
+		tw_copy_info(&info, "Max pending commands:          %3d\n", tw_dev->max_pending_request_count);
+		tw_copy_info(&info, "Last sgl length:               %3d\n", tw_dev->sgl_entries);
+		tw_copy_info(&info, "Max sgl length:                %3d\n", tw_dev->max_sgl_entries);
+		tw_copy_info(&info, "Last sector count:             %3d\n", tw_dev->sector_count);
+		tw_copy_info(&info, "Max sector count:              %3d\n", tw_dev->max_sector_count);
+		tw_copy_info(&info, "Resets:                        %3d\n", tw_dev->num_resets);
+		tw_copy_info(&info, "Aborts:                        %3d\n", tw_dev->num_aborts);
+	}
+	if (info.position > info.offset) {
+		return (info.position - info.offset);
+	} else { 
+		return 0;
+	}
+} /* End tw_scsi_proc_info() */
+
+/* This is the main scsi queue function to handle scsi opcodes */
+int tw_scsi_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) 
+{
+	unsigned char *command = SCpnt->cmnd;
+	int request_id = 0;
+	int error = 0;
+	int flags = 0;
+	TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->host->hostdata;
+
+	spin_lock_irqsave(&tw_dev->tw_lock, flags);
+	dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue()\n");
+
+	/* Skip scsi command if it isn't for us */
+	if ((tw_dev->is_unit_present[SCpnt->target] == FALSE) || (SCpnt->lun != 0)) {
+		SCpnt->result = (DID_BAD_TARGET << 16);
+		done(SCpnt);
+		spin_unlock_irqrestore(&tw_dev->tw_lock, flags);
+		return 0;
+	}
+	if (done == NULL) {
+		printk(KERN_WARNING "3w-xxxx: tw_scsi_queue(): Invalid done function.\n");
+		SCpnt->result = (DID_ERROR << 16);
+		done(SCpnt);
+		spin_unlock_irqrestore(&tw_dev->tw_lock, flags);
+		return 0;
+	}
+	if (tw_dev == NULL) {
+		printk(KERN_WARNING "3w-xxxx: tw_scsi_queue(): Invalid device extension.\n");
+		SCpnt->result = (DID_ERROR << 16);
+		done(SCpnt);
+		spin_unlock_irqrestore(&tw_dev->tw_lock, flags);
+		return 0;
+	}
+	
+	/* Save done function into Scsi_Cmnd struct */
+	SCpnt->scsi_done = done;
+		 
+	/* Queue the command and get a request id */
+	tw_state_request_start(tw_dev, &request_id);
+
+	/* Save the scsi command for use by the ISR */
+	tw_dev->srb[request_id] = SCpnt;
+
+	switch (*command) {
+		case READ_10:
+			dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ_10.\n");
+		case READ_6:
+			dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ_6.\n");
+		case WRITE_10:
+			dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught WRITE_10.\n");
+		case WRITE_6:
+			dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught WRITE_6.\n");
+			error = tw_scsiop_read_write(tw_dev, request_id);
+			break;
+		case TEST_UNIT_READY:
+			dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught TEST_UNIT_READY.\n");
+			error = tw_scsiop_test_unit_ready(tw_dev, request_id);
+			break;
+		case INQUIRY:
+			dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught INQUIRY.\n");
+			error = tw_scsiop_inquiry(tw_dev, request_id);
+			break;
+		case READ_CAPACITY:
+			dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ_CAPACITY.\n");
+			error = tw_scsiop_read_capacity(tw_dev, request_id);
+			break;
+		case TW_IOCTL:
+			dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught TW_SCSI_IOCTL.\n");
+			error = tw_ioctl(tw_dev, request_id);
+			break;
+		default:
+			printk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): Unknown scsi opcode: 0x%x\n", *command);
+			tw_dev->state[request_id] = TW_S_COMPLETED;
+			tw_state_request_finish(tw_dev, request_id);
+			SCpnt->result = (DID_BAD_TARGET << 16);
+			done(SCpnt);
+	}
+	if (error) {
+		tw_dev->state[request_id] = TW_S_COMPLETED;
+		tw_state_request_finish(tw_dev, request_id);
+		SCpnt->result = (DID_ERROR << 16);
+		done(SCpnt);
+	}
+	spin_unlock_irqrestore(&tw_dev->tw_lock, flags);
+
+	return 0;
+} /* End tw_scsi_queue() */
+
+/* This function will release the resources on an rmmod call */
+int tw_scsi_release(struct Scsi_Host *tw_host) 
+{
+	TW_Device_Extension *tw_dev;
+	tw_dev = (TW_Device_Extension *)tw_host->hostdata;
+
+	dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_release()\n");
+
+	/* Free up the IO region */
+	release_region((tw_dev->tw_pci_dev->base_address[0]), TW_IO_ADDRESS_RANGE);
+
+	/* Free up the IRQ */
+	free_irq(tw_dev->tw_pci_dev->irq, tw_dev);
+
+	/* Free up device extension resources */
+	tw_free_device_extension(tw_dev);
+
+	/* Tell kernel scsi-layer we are gone */
+	scsi_unregister(tw_host);
+
+	return 0;
+} /* End tw_scsi_release() */
+
+/* This function handles scsi inquiry commands */
+int tw_scsiop_inquiry(TW_Device_Extension *tw_dev, int request_id)
+{
+	TW_Param *param;
+	TW_Command *command_packet;
+	u32 command_que_value, command_que_addr;
+	u32 param_value;
+
+	dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry()\n");
+
+	/* Initialize command packet */
+	command_que_addr = tw_dev->registers.command_que_addr;
+	command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
+	if (command_packet == NULL) {
+		printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad command packet virtual address.\n");
+		return 1;
+	}
+	memset(command_packet, 0, sizeof(TW_Sector));
+	command_packet->byte0.opcode = TW_OP_GET_PARAM;
+	command_packet->byte0.sgl_offset = 2;
+	command_packet->size = 4;
+	command_packet->request_id = request_id;
+	command_packet->byte3.unit = 0;
+	command_packet->byte3.host_id = 0;
+	command_packet->status = 0;
+	command_packet->flags = 0;
+	command_packet->byte6.parameter_count = 1;
+
+	/* Now setup the param */
+	if (tw_dev->alignment_virtual_address[request_id] == NULL) {
+		printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad alignment virtual address.\n");
+		return 1;
+	}
+	param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
+	memset(param, 0, sizeof(TW_Sector));
+	param->table_id = 3;	 /* unit summary table */
+	param->parameter_id = 3; /* unitsstatus parameter */
+	param->parameter_size_bytes = TW_MAX_UNITS;
+	param_value = tw_dev->alignment_physical_address[request_id];
+	if (param_value == 0) {
+		printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad alignment physical address.\n");
+		return 1;
+	}
+
+	command_packet->byte8.param.sgl[0].address = param_value;
+	command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
+	command_que_value = tw_dev->command_packet_physical_address[request_id];
+	if (command_que_value == 0) {
+		printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad command packet physical address.\n");
+		return 1;
+	}
+
+	/* Now try to post the command packet */
+	tw_post_command_packet(tw_dev, request_id);
+
+	return 0;
+} /* End tw_scsiop_inquiry() */
+
+/* This function is called by the isr to complete an inquiry command */
+int tw_scsiop_inquiry_complete(TW_Device_Extension *tw_dev, int request_id)
+{
+	unsigned char *is_unit_present;
+	unsigned char *request_buffer;
+	int i;
+	TW_Param *param;
+
+	dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry_complete()\n");
+
+	/* Fill request buffer */
+	if (tw_dev->srb[request_id]->request_buffer == NULL) {
+		printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry_complete(): Request buffer NULL.\n");
+		return 1;
+	}
+	request_buffer = tw_dev->srb[request_id]->request_buffer;
+	memset(request_buffer, 0, tw_dev->srb[request_id]->request_bufflen);
+	request_buffer[0] = TYPE_DISK;									 /* Peripheral device type */
+	request_buffer[1] = 0;													 /* Device type modifier */
+	request_buffer[2] = 0;													 /* No ansi/iso compliance */
+	request_buffer[4] = 31;													/* Additional length */
+	memcpy(&request_buffer[8], "3ware   ", 8);	 /* Vendor ID */
+	memcpy(&request_buffer[16], "3w-xxxx         ", 16); /* Product ID */
+	memcpy(&request_buffer[32], tw_driver_version, 3);
+
+	param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
+	if (param == NULL) {
+		printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry_complete(): Bad alignment virtual address.\n");
+		return 1;
+	}
+	is_unit_present = &(param->data[0]);
+
+	for (i=0 ; i<TW_MAX_UNITS; i++) {
+		if (is_unit_present[i] == 0) {
+			tw_dev->is_unit_present[i] = FALSE;
+		} else {
+			tw_dev->is_unit_present[i] = TRUE;
+			dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry_complete: Unit %d found.\n", i);
+		}
+	}
+
+	return 0;
+} /* End tw_scsiop_inquiry_complete() */
+
+/* This function handles scsi read_capacity commands */
+int tw_scsiop_read_capacity(TW_Device_Extension *tw_dev, int request_id) 
+{
+	TW_Param *param;
+	TW_Command *command_packet;
+	u32 command_que_addr, command_que_value;
+	u32 param_value;
+
+	dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity()\n");
+
+	/* Initialize command packet */
+	command_que_addr = tw_dev->registers.command_que_addr;
+	command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
+
+	if (command_packet == NULL) {
+		dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad command packet virtual address.\n");
+		return 1;
+	}
+	memset(command_packet, 0, sizeof(TW_Sector));
+	command_packet->byte0.opcode = TW_OP_GET_PARAM;
+	command_packet->byte0.sgl_offset = 2;
+	command_packet->size = 4;
+	command_packet->request_id = request_id;
+	command_packet->byte3.unit = tw_dev->srb[request_id]->target;
+	command_packet->byte3.host_id = 0;
+	command_packet->status = 0;
+	command_packet->flags = 0;
+	command_packet->byte6.block_count = 1;
+
+	/* Now setup the param */
+	if (tw_dev->alignment_virtual_address[request_id] == NULL) {
+		dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad alignment virtual address.\n");
+		return 1;
+	}
+	param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
+	memset(param, 0, sizeof(TW_Sector));
+	param->table_id = TW_UNIT_INFORMATION_TABLE_BASE + 
+	tw_dev->srb[request_id]->target;
+	param->parameter_id = 4;	/* unitcapacity parameter */
+	param->parameter_size_bytes = 4;
+	param_value = tw_dev->alignment_physical_address[request_id];
+	if (param_value == 0) {
+		dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad alignment physical address.\n");
+		return 1;
+	}
+  
+	command_packet->byte8.param.sgl[0].address = param_value;
+	command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
+	command_que_value = tw_dev->command_packet_physical_address[request_id];
+	if (command_que_value == 0) {
+		dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad command packet physical address.\n");
+		return 1;
+	}
+
+	/* Now try to post the command to the board */
+	tw_post_command_packet(tw_dev, request_id);
+  
+	return 0;
+} /* End tw_scsiop_read_capacity() */
+
+/* This function is called by the isr to complete a readcapacity command */
+int tw_scsiop_read_capacity_complete(TW_Device_Extension *tw_dev, int request_id)
+{
+	unsigned char *param_data;
+	u32 capacity;
+	char *buff;
+	TW_Param *param;
+
+	dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity_complete()\n");
+
+	buff = tw_dev->srb[request_id]->request_buffer;
+	if (buff == NULL) {
+		printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Request buffer NULL.\n");
+		return 1;
+	}
+	memset(buff, 0, tw_dev->srb[request_id]->request_bufflen);
+	param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
+	if (param == NULL) {
+		printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Bad alignment virtual address.\n");
+		return 1;
+	}
+	param_data = &(param->data[0]);
+
+	capacity = (param_data[3] << 24) | (param_data[2] << 16) | 
+		   (param_data[1] << 8) | param_data[0];
+
+	dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity_complete(): Capacity = 0x%x.\n", capacity);
+
+	/* Number of LBA's */
+	buff[0] = (capacity >> 24);
+	buff[1] = (capacity >> 16) & 0xff;
+	buff[2] = (capacity >> 8) & 0xff;
+	buff[3] = capacity & 0xff;
+
+	/* Block size in bytes (512) */
+	buff[4] = (TW_BLOCK_SIZE >> 24);
+	buff[5] = (TW_BLOCK_SIZE >> 16) & 0xff;
+	buff[6] = (TW_BLOCK_SIZE >> 8) & 0xff;
+	buff[7] = TW_BLOCK_SIZE & 0xff;
+
+	return 0;
+} /* End tw_scsiop_read_capacity_complete() */
+
+/* This function handles scsi read or write commands */
+int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id) 
+{
+	TW_Command *command_packet;
+	u32 command_que_addr, command_que_value = 0;
+	u32 lba = 0x0, num_sectors = 0x0;
+	int i;
+	Scsi_Cmnd *srb;
+	struct scatterlist *sglist;
+
+	dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write()\n");
+
+	if (tw_dev->srb[request_id]->request_buffer == NULL) {
+		printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_write(): Request buffer NULL.\n");
+		return 1;
+	}
+	sglist = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
+	srb = tw_dev->srb[request_id];
+
+	/* Initialize command packet */
+	command_que_addr = tw_dev->registers.command_que_addr;
+	command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
+	if (command_packet == NULL) {
+		dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): Bad command packet virtual address.\n");
+		return 1;
+	}
+
+	if (srb->cmnd[0] == READ_6 || srb->cmnd[0] == READ_10) {
+		command_packet->byte0.opcode = TW_OP_READ;
+	} else {
+		command_packet->byte0.opcode = TW_OP_WRITE;
+	}
+
+	command_packet->byte0.sgl_offset = 3;
+	command_packet->size = 5;
+	command_packet->request_id = request_id;
+	command_packet->byte3.unit = srb->target;
+	command_packet->byte3.host_id = 0;
+	command_packet->status = 0;
+	command_packet->flags = 0;
+
+	if (srb->cmnd[0] == READ_6 || srb->cmnd[0] == WRITE_6) {
+		lba = ((u32)srb->cmnd[1] << 16) | ((u32)srb->cmnd[2] << 8) | (u32)srb->cmnd[3];
+		num_sectors = (u32)srb->cmnd[4];
+	} else {
+		lba = ((u32)srb->cmnd[2] << 24) | ((u32)srb->cmnd[3] << 16) | 
+		       ((u32)srb->cmnd[4] << 8) | (u32)srb->cmnd[5];
+		num_sectors = (u32)srb->cmnd[8] | ((u32)srb->cmnd[7] << 8);
+	}
+  
+	/* Update sector statistic */
+	tw_dev->sector_count = num_sectors;
+	if (tw_dev->sector_count > tw_dev->max_sector_count)
+		tw_dev->max_sector_count = tw_dev->sector_count;
+  
+	dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): lba = 0x%x num_sectors = 0x%x\n", lba, num_sectors);
+	command_packet->byte8.io.lba = lba;
+	command_packet->byte6.block_count = num_sectors;
+
+	/* Do this if there are no sg list entries */
+	if (tw_dev->srb[request_id]->use_sg == 0) {    
+		dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): SG = 0\n");
+		command_packet->byte8.io.sgl[0].address = virt_to_bus(tw_dev->srb[request_id]->request_buffer);
+		command_packet->byte8.io.sgl[0].length = tw_dev->srb[request_id]->request_bufflen;
+	}
+
+	/* Do this if we have multiple sg list entries */
+	if (tw_dev->srb[request_id]->use_sg > 0) {
+		for (i=0;i<tw_dev->srb[request_id]->use_sg; i++) {
+			command_packet->byte8.io.sgl[i].address = virt_to_bus(sglist[i].address);
+			command_packet->byte8.io.sgl[i].length = sglist[i].length;
+			command_packet->size+=2;
+		}
+		if (tw_dev->srb[request_id]->use_sg > 1)
+			command_packet->size-=2;
+	}
+
+	/* Update SG statistics */
+	tw_dev->sgl_entries = tw_dev->srb[request_id]->use_sg;
+	if (tw_dev->sgl_entries > tw_dev->max_sgl_entries)
+		tw_dev->max_sgl_entries = tw_dev->sgl_entries;
+
+	command_que_value = tw_dev->command_packet_physical_address[request_id];
+	if (command_que_value == 0) {
+		dprintk(KERN_WARNING "3w-xxxx: tw_scsiop_read_write(): Bad command packet physical address.\n");
+		return 1;
+	}
+      
+	/* Now try to post the command to the board */
+	tw_post_command_packet(tw_dev, request_id);
+
+	return 0;
+} /* End tw_scsiop_read_write() */
+
+/* This function will handle test unit ready scsi command */
+int tw_scsiop_test_unit_ready(TW_Device_Extension *tw_dev, int request_id)
+{
+	dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_test_unit_ready()\n");
+
+	/* Tell the scsi layer were done */
+	tw_dev->state[request_id] = TW_S_COMPLETED;
+	tw_state_request_finish(tw_dev, request_id);
+	tw_dev->srb[request_id]->result = (DID_OK << 16);
+	tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
+
+	return 0;
+} /* End tw_scsiop_test_unit_ready() */
+
+/* This function will setup the interrupt handler */
+int tw_setup_irq(TW_Device_Extension *tw_dev)
+{
+	char *device = TW_DEVICE_NAME;
+	int error;
+
+	dprintk(KERN_NOTICE "3w-xxxx: tw_setup_irq()\n");
+	error = request_irq(tw_dev->tw_pci_dev->irq, tw_interrupt, SA_SHIRQ, device, tw_dev);
+
+	if (error < 0) {
+		printk(KERN_WARNING "3w-xxxx: tw_setup_irq(): Error requesting IRQ: %d for card %d.\n", tw_dev->tw_pci_dev->irq, tw_dev->host->host_no);
+		return 1;
+	}
+	return 0;
+} /* End tw_setup_irq() */
+
+/* This function will soft reset the controller */
+void tw_soft_reset(TW_Device_Extension *tw_dev) 
+{
+	u32 control_reg_addr, control_reg_value;
+
+	control_reg_addr = tw_dev->registers.control_reg_addr;
+	control_reg_value = (	TW_CONTROL_ISSUE_SOFT_RESET |
+				TW_CONTROL_CLEAR_HOST_INTERRUPT |
+				TW_CONTROL_CLEAR_ATTENTION_INTERRUPT |
+				TW_CONTROL_MASK_COMMAND_INTERRUPT |
+				TW_CONTROL_MASK_RESPONSE_INTERRUPT |
+				TW_CONTROL_CLEAR_ERROR_STATUS | 
+				TW_CONTROL_DISABLE_INTERRUPTS);
+	outl(control_reg_value, control_reg_addr);
+} /* End tw_soft_reset() */
+
+/* This function will free a request_id */
+int tw_state_request_finish(TW_Device_Extension *tw_dev, int request_id)
+{
+	dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_finish()\n");
+  
+	do {    
+		if (tw_dev->free_tail == TW_Q_LENGTH-1) {
+			tw_dev->free_tail = TW_Q_START;
+		} else {
+			tw_dev->free_tail = tw_dev->free_tail + 1;
+		}
+	} while ((tw_dev->state[tw_dev->free_queue[tw_dev->free_tail]] != TW_S_COMPLETED));
+
+	tw_dev->free_queue[tw_dev->free_tail] = request_id;
+
+	tw_dev->state[request_id] = TW_S_FINISHED;
+	dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_finish(): Freeing request_id %d\n", request_id);
+
+	return 0;
+} /* End tw_state_request_finish() */
+
+/* This function will assign an available request_id */
+int tw_state_request_start(TW_Device_Extension *tw_dev, int *request_id)
+{
+	int id = 0;
+
+	dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_start()\n");
+
+	/* Obtain next free request_id */
+	do {
+		if (tw_dev->free_head == TW_Q_LENGTH - 1) {
+			tw_dev->free_head = TW_Q_START;
+		} else {
+			tw_dev->free_head = tw_dev->free_head + 1;
+		}
+	} while ((tw_dev->state[tw_dev->free_queue[tw_dev->free_head]] == TW_S_STARTED) ||
+		 (tw_dev->state[tw_dev->free_queue[tw_dev->free_head]] == TW_S_POSTED) ||
+		 (tw_dev->state[tw_dev->free_queue[tw_dev->free_head]] == TW_S_PENDING) ||
+		 (tw_dev->state[tw_dev->free_queue[tw_dev->free_head]] == TW_S_COMPLETED));
+
+	id = tw_dev->free_queue[tw_dev->free_head];
+
+	if (tw_dev->free_head == TW_Q_LENGTH - 1) {
+		tw_dev->free_head = TW_Q_START;
+	} else {
+		tw_dev->free_head = tw_dev->free_head + 1;
+	}
+
+	dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_start(): id = %d.\n", id);
+	*request_id = id;
+	tw_dev->state[id] = TW_S_STARTED;
+
+	return 0;
+} /* End tw_state_request_start() */
+
+/* This function will unmask the command interrupt on the controller */
+void tw_unmask_command_interrupt(TW_Device_Extension *tw_dev)
+{
+	u32 control_reg_addr, control_reg_value;
+
+	control_reg_addr = tw_dev->registers.control_reg_addr;
+	control_reg_value = TW_CONTROL_UNMASK_COMMAND_INTERRUPT;
+	outl(control_reg_value, control_reg_addr);
+} /* End tw_unmask_command_interrupt() */
+
+/* Now get things going */
+
+#ifdef MODULE
+Scsi_Host_Template driver_template = TWXXXX;
+#include "scsi_module.c"
+#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/scsi/3w-xxxx.h linux.15p9/drivers/scsi/3w-xxxx.h
--- linux.vanilla/drivers/scsi/3w-xxxx.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/drivers/scsi/3w-xxxx.h	Wed Feb 16 20:19:46 2000
@@ -0,0 +1,369 @@
+/* 
+   3w-xxxx.h -- 3ware Storage Controller device driver for Linux.
+   
+   Written By: Adam Radford <linux@3ware.com>
+   Copyright (C) 1999 3ware Inc.
+
+   Kernel compatablity By:	Andre Hedrick <andre@suse.com>
+   Non-Copyright (C) 2000	Andre Hedrick <andre@suse.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; version 2 of the License.
+
+   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.                              
+
+   NO WARRANTY                                                               
+   THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR        
+   CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT      
+   LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,      
+   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is    
+   solely responsible for determining the appropriateness of using and       
+   distributing the Program and assumes all risks associated with its        
+   exercise of rights under this Agreement, including but not limited to     
+   the risks and costs of program errors, damage to or loss of data,         
+   programs or equipment, and unavailability or interruption of operations.  
+
+   DISCLAIMER OF LIABILITY                                                   
+   NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY   
+   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL        
+   DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND   
+   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     
+   TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE    
+   USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED  
+   HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES             
+
+   You should have received a copy of the GNU General Public License         
+   along with this program; if not, write to the Free Software               
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+
+   Bugs/Comments/Suggestions should be mailed to:                            
+   linux@3ware.com
+   
+   For more information, goto:
+   http://www.3ware.com
+*/
+
+#ifndef _3W_XXXX_H
+#define _3W_XXXX_H
+
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/kdev_t.h>
+
+/* Control register bit definitions */
+#define TW_CONTROL_CLEAR_HOST_INTERRUPT	       0x00080000
+#define TW_CONTROL_CLEAR_ATTENTION_INTERRUPT   0x00040000
+#define TW_CONTROL_MASK_COMMAND_INTERRUPT      0x00020000
+#define TW_CONTROL_MASK_RESPONSE_INTERRUPT     0x00010000
+#define TW_CONTROL_UNMASK_COMMAND_INTERRUPT    0x00008000
+#define TW_CONTROL_UNMASK_RESPONSE_INTERRUPT   0x00004000
+#define TW_CONTROL_CLEAR_ERROR_STATUS	       0x00000200
+#define TW_CONTROL_ISSUE_SOFT_RESET	       0x00000100
+#define TW_CONTROL_ENABLE_INTERRUPTS	       0x00000080
+#define TW_CONTROL_DISABLE_INTERRUPTS	       0x00000040
+#define TW_CONTROL_ISSUE_HOST_INTERRUPT	       0x00000020
+
+/* Status register bit definitions */
+#define TW_STATUS_MAJOR_VERSION_MASK	       0xF0000000
+#define TW_STATUS_MINOR_VERSION_MASK	       0x0F000000
+#define TW_STATUS_PCI_PARITY_ERROR	       0x00800000
+#define TW_STATUS_QUEUE_ERROR		       0x00400000
+#define TW_STATUS_MICROCONTROLLER_ERROR	       0x00200000
+#define TW_STATUS_PCI_ABORT		       0x00100000
+#define TW_STATUS_HOST_INTERRUPT	       0x00080000
+#define TW_STATUS_ATTENTION_INTERRUPT	       0x00040000
+#define TW_STATUS_COMMAND_INTERRUPT	       0x00020000
+#define TW_STATUS_RESPONSE_INTERRUPT	       0x00010000
+#define TW_STATUS_COMMAND_QUEUE_FULL	       0x00008000
+#define TW_STATUS_RESPONSE_QUEUE_EMPTY	       0x00004000
+#define TW_STATUS_MICROCONTROLLER_READY	       0x00002000
+#define TW_STATUS_COMMAND_QUEUE_EMPTY	       0x00001000
+#define TW_STATUS_ALL_INTERRUPTS	       0x000F0000
+#define TW_STATUS_CLEARABLE_BITS	       0x00D00000
+#define TW_STATUS_EXPECTED_BITS		       0x00002000
+#define TW_STATUS_UNEXPECTED_BITS	       0x00F80000
+
+/* RESPONSE QUEUE BIT DEFINITIONS */
+#define TW_RESPONSE_ID_MASK		       0x00000FF0
+
+/* PCI related defines */
+#define TW_IO_ADDRESS_RANGE		       0xD
+#define TW_DEVICE_NAME			       "3ware Storage Controller"
+#define TW_VENDOR_ID (0x13C1)	/* 3ware */
+#define TW_DEVICE_ID (0x1000)	/* Storage Controller */
+
+/* Command packet opcodes */
+#define TW_OP_NOP	      0x0
+#define TW_OP_INIT_CONNECTION 0x1
+#define TW_OP_READ	      0x2
+#define TW_OP_WRITE	      0x3
+#define TW_OP_VERIFY	      0x4
+#define TW_OP_GET_PARAM	      0x12
+#define TW_OP_SET_PARAM	      0x13
+#define TW_OP_SECTOR_INFO     0x1a
+#define TW_OP_AEN_LISTEN      0x1c
+
+/* Asynchronous Event Notification (AEN) Codes */
+#define TW_AEN_QUEUE_EMPTY       0x0000
+#define TW_AEN_SOFT_RESET        0x0001
+#define TW_AEN_DEGRADED_MIRROR   0x0002
+#define TW_AEN_CONTROLLER_ERROR  0x0003
+#define TW_AEN_REBUILD_FAIL      0x0004
+#define TW_AEN_REBUILD_DONE      0x0005
+#define TW_AEN_QUEUE_FULL        0x00ff
+#define TW_AEN_TABLE_UNDEFINED   0x15
+
+/* Misc defines */
+#define TW_ALIGNMENT			      0x200 /* 16 D-WORDS */
+#define TW_MAX_UNITS			      16
+#define TW_COMMAND_ALIGNMENT_MASK	      0x1ff
+#define TW_INIT_MESSAGE_CREDITS		      0x100
+#define TW_INIT_COMMAND_PACKET_SIZE	      0x3
+#define TW_POLL_MAX_RETRIES        	      10000
+#define TW_MAX_SGL_LENGTH		      62
+#define TW_Q_LENGTH			      256
+#define TW_Q_START			      0
+#define TW_MAX_SLOT			      32
+#define TW_MAX_PCI_BUSES		      255
+#define TW_MAX_RESET_TRIES		      3
+#define TW_UNIT_INFORMATION_TABLE_BASE	      0x300
+#define TW_MAX_CMDS_PER_LUN		      (TW_Q_LENGTH-2)/TW_MAX_UNITS
+#define TW_BLOCK_SIZE			      0x200 /* 512-byte blocks */
+#define TW_IOCTL                              0x80
+#define TW_MAX_AEN_TRIES                      100
+
+#define TW_IN_INTR                            1
+
+/* Macros */
+#define TW_STATUS_ERRORS(x) \
+	(((x & TW_STATUS_PCI_ABORT) || \
+	(x & TW_STATUS_PCI_PARITY_ERROR) || \
+	(x & TW_STATUS_QUEUE_ERROR) || \
+	(x & TW_STATUS_MICROCONTROLLER_ERROR)) && \
+	(x & TW_STATUS_MICROCONTROLLER_READY))
+
+#ifdef TW_DEBUG
+#define dprintk(msg...) printk(msg)
+#else
+#define dprintk(msg...) do { } while(0);
+#endif
+
+extern struct proc_dir_entry tw_scsi_proc_entry;
+
+/* Scatter Gather List Entry */
+typedef struct TAG_TW_SG_Entry {
+	unsigned long address;
+	unsigned long length;
+} TW_SG_Entry;
+
+typedef unsigned char TW_Sector[512];
+
+/* Command Packet */
+typedef struct TW_Command {
+	/* First DWORD */
+	struct {
+		unsigned char opcode:5;
+		unsigned char sgl_offset:3;
+	} byte0;
+	unsigned char size;
+	unsigned char request_id;
+	struct {
+		unsigned char unit:4;
+		unsigned char host_id:4;
+	} byte3;
+	/* Second DWORD */
+	unsigned char status;
+	unsigned char flags;
+	union {
+		unsigned short block_count;
+		unsigned short parameter_count;
+		unsigned short message_credits;
+	} byte6;
+	union {
+		struct {
+			unsigned long lba;
+			TW_SG_Entry sgl[TW_MAX_SGL_LENGTH];
+			unsigned long padding;	/* pad to 512 bytes */
+		} io;
+		struct {
+			TW_SG_Entry sgl[TW_MAX_SGL_LENGTH];
+			unsigned long padding[2];
+		} param;
+		struct {
+			unsigned long response_queue_pointer;
+			unsigned long padding[125];
+		} init_connection;
+		struct {
+			char version[504];
+		} ioctl_miniport_version;
+	} byte8;
+} TW_Command;
+
+typedef struct TAG_TW_Ioctl {
+	int buffer;
+	unsigned char opcode;
+	unsigned short table_id;
+	unsigned char parameter_id;
+	unsigned char parameter_size_bytes;
+	unsigned char data[1];
+} TW_Ioctl;
+
+/* GetParam descriptor */
+typedef struct {
+	unsigned short	table_id;
+	unsigned char	parameter_id;
+	unsigned char	parameter_size_bytes;
+	unsigned char	data[1];
+} TW_Param, *PTW_Param;
+
+/* Response queue */
+typedef union TAG_TW_Response_Queue {
+	struct {
+		u32 undefined_1: 4;
+		u32 response_id: 8;
+		u32 undefined_2: 20;
+	} u;
+	u32 value;
+} TW_Response_Queue;
+
+typedef struct TAG_TW_Registers {
+	u32 base_addr;
+	u32 control_reg_addr;
+	u32 status_reg_addr;
+	u32 command_que_addr;
+	u32 response_que_addr;
+} TW_Registers;
+
+typedef struct TAG_TW_Info {
+	char *buffer;
+	int length;
+	int offset;
+	int position;
+} TW_Info;
+
+typedef enum TAG_TW_Cmd_State {
+	TW_S_INITIAL,		/* Initial state */
+	TW_S_STARTED,		/* Id in use */
+	TW_S_POSTED,		/* Posted to the controller */
+	TW_S_PENDING,		/* Waiting to be posted in isr */
+	TW_S_COMPLETED,		/* Completed by isr */
+	TW_S_FINISHED,		/* I/O completely done */
+} TW_Cmd_State;
+
+typedef struct TAG_TW_Device_Extension {
+	TW_Registers		registers;
+	u32			*alignment_virtual_address[TW_Q_LENGTH];
+	u32			alignment_physical_address[TW_Q_LENGTH];
+	int			is_unit_present[TW_MAX_UNITS];
+	int			num_units;
+	u32			*command_packet_virtual_address[TW_Q_LENGTH];
+	u32			command_packet_physical_address[TW_Q_LENGTH];
+	struct pci_dev		*tw_pci_dev;
+	Scsi_Cmnd		*srb[TW_Q_LENGTH];
+	unsigned char		free_queue[TW_Q_LENGTH];
+	unsigned char		free_head;
+	unsigned char		free_tail;
+	unsigned char		pending_queue[TW_Q_LENGTH];
+	unsigned char		pending_head;
+	unsigned char		pending_tail;
+	TW_Cmd_State		state[TW_Q_LENGTH];
+	u32			posted_request_count;
+	u32			max_posted_request_count;
+	u32			request_count_marked_pending;
+	u32			pending_request_count;
+	u32			max_pending_request_count;
+	u32			max_sgl_entries;
+	u32			sgl_entries;
+	u32			num_aborts;
+	u32			num_resets;
+	u32			sector_count;
+	u32			max_sector_count;
+	struct Scsi_Host	*host;
+	spinlock_t		tw_lock;
+	unsigned char		ioctl_size[TW_Q_LENGTH];
+	unsigned short		aen_queue[TW_Q_LENGTH];
+	unsigned char		aen_head;
+	unsigned char		aen_tail;
+	u32			flags;
+} TW_Device_Extension;
+
+/* Function prototypes */
+int tw_aen_complete(TW_Device_Extension *tw_dev, int request_id);
+int tw_aen_drain_queue(TW_Device_Extension *tw_dev);
+int tw_aen_read_queue(TW_Device_Extension *tw_dev, int request_id);
+int tw_allocate_memory(TW_Device_Extension *tw_dev, int request_id, int size, int which);
+int tw_check_bits(u32 status_reg_value);
+int tw_check_errors(TW_Device_Extension *tw_dev);
+void tw_clear_attention_interrupt(TW_Device_Extension *tw_dev);
+void tw_clear_host_interrupt(TW_Device_Extension *tw_dev);
+void tw_disable_interrupts(TW_Device_Extension *tw_dev);
+int tw_empty_response_que(TW_Device_Extension *tw_dev);
+void tw_enable_interrupts(TW_Device_Extension *tw_dev);
+int tw_findcards(Scsi_Host_Template *tw_host);
+void tw_free_device_extension(TW_Device_Extension *tw_dev);
+int tw_initconnection(TW_Device_Extension *tw_dev);
+int tw_initialize_device_extension(TW_Device_Extension *tw_dev);
+int tw_initialize_units(TW_Device_Extension *tw_dev);
+int tw_ioctl(TW_Device_Extension *tw_dev, int request_id);
+int tw_ioctl_complete(TW_Device_Extension *tw_dev, int request_id);
+void tw_mask_command_interrupt(TW_Device_Extension *tw_dev);
+int tw_poll_status(TW_Device_Extension *tw_dev, u32 flag, int seconds);
+int tw_post_command_packet(TW_Device_Extension *tw_dev, int request_id);
+int tw_reset_device_extension(TW_Device_Extension *tw_dev);
+int tw_reset_sequence(TW_Device_Extension *tw_dev);
+int tw_scsi_biosparam(Disk *disk, kdev_t dev, int geom[]);
+int tw_scsi_detect(Scsi_Host_Template *tw_host);
+int tw_scsi_eh_abort(Scsi_Cmnd *SCpnt);
+int tw_scsi_eh_reset(Scsi_Cmnd *SCpnt);
+int tw_scsi_proc_info(char *buffer, char **start, off_t offset, int length, int inode, int inout);
+int tw_scsi_queue(Scsi_Cmnd *cmd, void (*done) (Scsi_Cmnd *));
+int tw_scsi_release(struct Scsi_Host *tw_host);
+int tw_scsiop_inquiry(TW_Device_Extension *tw_dev, int request_id);
+int tw_scsiop_inquiry_complete(TW_Device_Extension *tw_dev, int request_id);
+int tw_scsiop_read_capacity(TW_Device_Extension *tw_dev, int request_id);
+int tw_scsiop_read_capacity_complete(TW_Device_Extension *tw_dev, int request_id);
+int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id);
+int tw_scsiop_test_unit_ready(TW_Device_Extension *tw_dev, int request_id);
+int tw_setup_irq(TW_Device_Extension *tw_dev);
+void tw_soft_reset(TW_Device_Extension *tw_dev);
+int tw_state_request_finish(TW_Device_Extension *tw_dev,int request_id);
+int tw_state_request_start(TW_Device_Extension *tw_dev, int *request_id);
+void tw_unmask_command_interrupt(TW_Device_Extension *tw_dev);
+
+#if defined(HOSTS_C) || defined(MODULE)
+/* Scsi_Host_Template Initializer */
+#define TWXXXX {					\
+	next : NULL,					\
+	module : NULL,					\
+	proc_dir : &tw_scsi_proc_entry,			\
+	proc_info : tw_scsi_proc_info,			\
+	name : "3ware Storage Controller",		\
+	detect : tw_scsi_detect,			\
+	release : tw_scsi_release,			\
+	info : NULL,					\
+	ioctl : NULL,                  			\
+	command : NULL,					\
+	queuecommand : tw_scsi_queue,			\
+	eh_strategy_handler : NULL,			\
+	eh_abort_handler : tw_scsi_eh_abort,		\
+	eh_device_reset_handler : NULL,			\
+	abort : NULL,					\
+	reset : NULL,					\
+	slave_attach : NULL,				\
+	bios_param : tw_scsi_biosparam,			\
+	can_queue : TW_Q_LENGTH,			\
+	this_id: -1,					\
+	sg_tablesize : TW_MAX_SGL_LENGTH,		\
+	cmd_per_lun: TW_MAX_CMDS_PER_LUN,		\
+	present : 0,					\
+	unchecked_isa_dma : 0,				\
+	use_clustering : ENABLE_CLUSTERING,		\
+ 	use_new_eh_code : 1,				\
+	emulated : 1					\
+}
+#endif /* HOSTS_C */
+#endif /* _3W_XXXX_H */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/scsi/Config.in linux.15p9/drivers/scsi/Config.in
--- linux.vanilla/drivers/scsi/Config.in	Wed Oct 20 01:12:40 1999
+++ linux.15p9/drivers/scsi/Config.in	Mon Feb  7 13:01:53 2000
@@ -18,6 +18,9 @@
 mainmenu_option next_comment
 comment 'SCSI low-level drivers'
 
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+   dep_tristate '3Ware Hardware ATA-RAID support (EXPERIMENTAL)' 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
 dep_tristate 'Adaptec AHA152X/2825 support' CONFIG_SCSI_AHA152X $CONFIG_SCSI
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/scsi/Makefile linux.15p9/drivers/scsi/Makefile
--- linux.vanilla/drivers/scsi/Makefile	Wed Oct 20 01:12:40 1999
+++ linux.15p9/drivers/scsi/Makefile	Mon Feb  7 13:02:46 2000
@@ -639,6 +639,14 @@
 L_OBJS += NCR53C9x.o jazz_esp.o
 endif
 
+ifeq ($(CONFIG_BLK_DEV_3W_XXXX_RAID),y)
+L_OBJS += 3w-xxxx.o
+else
+  ifeq ($(CONFIG_BLK_DEV_3W_XXXX_RAID),m)
+  M_OBJS += 3w-xxxx.o
+  endif
+endif
+
 include $(TOPDIR)/Rules.make
 
 53c8xx_d.h: 53c7,8xx.scr script_asm.pl
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/scsi/aic7xxx.c linux.15p9/drivers/scsi/aic7xxx.c
--- linux.vanilla/drivers/scsi/aic7xxx.c	Tue Jan  4 21:18:56 2000
+++ linux.15p9/drivers/scsi/aic7xxx.c	Wed Jan 26 23:19:00 2000
@@ -270,7 +270,7 @@
     0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-#define AIC7XXX_C_VERSION  "5.1.21"
+#define AIC7XXX_C_VERSION  "5.1.23"
 
 #define NUMBER(arr)     (sizeof(arr) / sizeof(arr[0]))
 #define MIN(a,b)        (((a) < (b)) ? (a) : (b))
@@ -5141,7 +5141,7 @@
         else if (scb->flags & SCB_MSGOUT_PPR)
         {
           unsigned int max_sync, period;
-          unsigned char options = p->transinfo[tindex].goal_options;
+          unsigned char options = 0;
 
           if (p->features & AHC_ULTRA2)
           {
@@ -5152,9 +5152,10 @@
                   (p->dev_flags[tindex] & DEVICE_SCSI_3) &&
                   (p->transinfo[tindex].goal_width ==
                    MSG_EXT_WDTR_BUS_16_BIT) &&
-                  (options != 0) )
+                  (p->transinfo[tindex].goal_options != 0) )
               {
                 max_sync = AHC_SYNCRATE_ULTRA3;
+                options = p->transinfo[tindex].goal_options;
               }
               else
               {
@@ -5662,16 +5663,6 @@
           break;
         }
 
-        /*
-         * If we aren't on one of the new Ultra3 cards, then reject any PPR
-         * message since we can't support any option field other than 0
-         */
-        if( !(p->features & AHC_ULTRA3) )
-        {
-          reject = TRUE;
-          break;
-        }
-
         if (p->msg_len < (MSG_EXT_PPR_LEN + 2))
         {
           break;
@@ -7329,10 +7320,16 @@
   };
   struct seeprom_cmd seeprom_read = {3, {1, 1, 0}};
 
-#define CLOCK_PULSE(p) \
-  while ((aic_inb(p, SEECTL) & SEERDY) == 0)        \
-  {                                                \
-    ;  /* Do nothing */                                \
+#define CLOCK_PULSE(p)                                               \
+  {                                                                  \
+    int limit = 0;                                                   \
+    while (((aic_inb(p, SEECTL) & SEERDY) == 0) && (++limit < 1000)) \
+    {                                                                \
+      mb();                                                          \
+      pause_sequencer(p);  /* This is just to generate some PCI */   \
+                           /* so the PCI read is flushed */          \
+      udelay(10);  /* Do nothing */                                  \
+    }                                                                \
   }
 
   /*
@@ -8664,15 +8661,15 @@
       if (!have_seeprom)
       {
         p->sc_size = 128;
-        have_seeprom = read_seeprom(p, (p->flags & (AHC_CHNLB|AHC_CHNLC)),
+        have_seeprom = read_seeprom(p, 4*(p->flags & (AHC_CHNLB|AHC_CHNLC)),
                                     scarray, p->sc_size, p->sc_type);
         if (!have_seeprom)
         {
           if(p->sc_type == C46)
-            have_seeprom = read_seeprom(p, (p->flags & (AHC_CHNLB|AHC_CHNLC)),
+            have_seeprom = read_seeprom(p, 4*(p->flags & (AHC_CHNLB|AHC_CHNLC)),
                                         scarray, p->sc_size, C56_66);
           else
-            have_seeprom = read_seeprom(p, (p->flags & (AHC_CHNLB|AHC_CHNLC)),
+            have_seeprom = read_seeprom(p, 4*(p->flags & (AHC_CHNLB|AHC_CHNLC)),
                                         scarray, p->sc_size, C46);
         }
       }
@@ -10396,7 +10393,7 @@
          * instead of slowing down if those exist.  That's hard to do with simple
          * checksums though.
          */
-        if(aic7xxx_verbose & VERBOSE_NEGOTIATION) 
+        if(aic7xxx_verbose & VERBOSE_NEGOTIATION2) 
         {
           printk(INFO_LEAD "reducing SCSI transfer speed due to Domain "
                  "validation failure.\n", p->host_no, CTL_OF_CMD(cmd));
@@ -10427,7 +10424,7 @@
       }
       else
       {
-        if(aic7xxx_verbose & VERBOSE_NEGOTIATION) 
+        if(aic7xxx_verbose & VERBOSE_NEGOTIATION2) 
         {
           printk(INFO_LEAD "Performing Domain validation.\n",
                  p->host_no, CTL_OF_CMD(cmd));
@@ -10452,7 +10449,7 @@
     } 
     else
     {
-      if( (aic7xxx_verbose & VERBOSE_NEGOTIATION) &&
+      if( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) &&
           (p->needdv & (1<<tindex)) )
       {
         printk(INFO_LEAD "Successfully completed Domain validation.\n",
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/scsi/esp.c linux.15p9/drivers/scsi/esp.c
--- linux.vanilla/drivers/scsi/esp.c	Tue Jan  4 21:18:56 2000
+++ linux.15p9/drivers/scsi/esp.c	Fri Jan 14 15:56:16 2000
@@ -39,6 +39,8 @@
 #include <asm/idprom.h>
 #include <asm/spinlock.h>
 
+#include <linux/module.h>
+
 #define DEBUG_ESP
 /* #define DEBUG_ESP_HME */
 /* #define DEBUG_ESP_DATA */
@@ -4313,3 +4315,11 @@
 	spin_unlock_irqrestore(&io_request_lock, flags);
 }
 #endif
+
+#ifdef MODULE
+Scsi_Host_Template driver_template = SCSI_SPARC_ESP;
+
+#include "scsi_module.c"
+
+EXPORT_NO_SYMBOLS;
+#endif /* MODULE */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/scsi/hosts.c linux.15p9/drivers/scsi/hosts.c
--- linux.vanilla/drivers/scsi/hosts.c	Wed Oct 20 01:12:41 1999
+++ linux.15p9/drivers/scsi/hosts.c	Mon Feb  7 13:00:44 2000
@@ -339,6 +339,10 @@
 #include "../net/fc/iph5526_scsi.h"
 #endif
 
+#ifdef CONFIG_BLK_DEV_3W_XXXX_RAID
+#include "3w-xxxx.h"
+#endif
+
 /*
  * Moved ppa driver to the end of the probe list
  * since it is a removable host adapter.
@@ -610,6 +614,10 @@
 #ifdef CONFIG_IPHASE5526
 	IPH5526_SCSI_FC,
 #endif
+#ifdef CONFIG_BLK_DEV_3W_XXXX_RAID
+	TWXXXX,
+#endif
+
 /* "Removable host adapters" below this line (Parallel Port/USB/other) */
 #ifdef CONFIG_SCSI_PPA
     PPA,
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/scsi/megaraid.c linux.15p9/drivers/scsi/megaraid.c
--- linux.vanilla/drivers/scsi/megaraid.c	Tue Jan  4 21:18:57 2000
+++ linux.15p9/drivers/scsi/megaraid.c	Fri Jan 21 17:54:45 2000
@@ -2,14 +2,14 @@
  *
  *                    Linux MegaRAID device driver
  *
- * Copyright 1998 American Megatrends Inc.
+ * Copyright 1999 American Megatrends Inc.
  *
  *              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.
  *
- * Version : 1.05
+ * Version : 1.07
  * 
  * Description: Linux device driver for AMI MegaRAID controller
  *
@@ -120,6 +120,9 @@
  *      also enables the driver to handle large amount of I/O requests for
  *      long duration of time.
  *
+ * Version 1.07
+ *    Removed the usage of uaccess.h file for kernel versions less than
+ *    2.0.36, as this file is not present in those versions.
  *
  * BUGS:
  *     Some older 2.1 kernels (eg. 2.1.90) have a bug in pci.c that
@@ -135,7 +138,7 @@
 #define CRLFSTR "\n"
 #define IOCTL_CMD_NEW  0x81
 
-#define MEGARAID_VERSION "v1.05 (October 27, 1999)"
+#define MEGARAID_VERSION "v107 (December 22, 1999)"
 
 
 #include <linux/config.h>
@@ -178,7 +181,9 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
+#if LINUX_VERSION_CODE > 0x020024
 #include <asm/uaccess.h>
+#endif
 
 #include "sd.h"
 #include "scsi.h"
@@ -265,7 +270,6 @@
 
 
 
-
 #if LINUX_VERSION_CODE > 0x020100
 #  include <asm/spinlock.h>
 #  include <linux/smp.h>
@@ -304,6 +308,7 @@
        cli();
 #  define DRIVER_UNLOCK(p) \
        restore_flags(cpu_flags);
+#  define IO_LOCK_T unsigned long io_flags = 0;
 #  define IO_LOCK(p)   DRIVER_LOCK(p)
 #  define IO_UNLOCK(p) DRIVER_UNLOCK(p)
 #  define le32_to_cpu(x) (x)
@@ -329,6 +334,7 @@
 /*  Use "megaraid=skipXX" as LILO option to prohibit driver from scanning
     XX scsi id on each channel.  Used for Madrona motherboard, where SAF_TE
     processor id cannot be scanned */
+
 static char *megaraid;
 #if LINUX_VERSION_CODE > 0x20100
 #ifdef MODULE
@@ -350,7 +356,6 @@
 #if SERDEBUG
 volatile static spinlock_t serial_lock;
 #endif
-//volatile static spinlock_t mega_lock;
 
 struct proc_dir_entry proc_scsi_megaraid =
 {
@@ -593,7 +598,6 @@
   }
 
   SCpnt = pScb->SCpnt;
-  /*freeSCB(megaCfg, pScb);*/ /*delay this to the end of this func.*/
   pthru = &pScb->pthru;
   mbox = (mega_mailbox *) &pScb->mboxData;
 
@@ -708,13 +712,11 @@
 
   if ( islogical ) {
 	lun = (SCpnt->target * 8) + lun;
-#if 1
         if ( lun > FC_MAX_LOGICAL_DRIVES ){
             SCpnt->result = (DID_BAD_TARGET << 16);
             callDone (SCpnt);
             return NULL;
         }
-#endif
   }
   /*-----------------------------------------------------
    *
@@ -878,7 +880,6 @@
     return NULL;
   }
 
-
   mboxdata = (u8 *) & pScb->mboxData;
   mbox = (mega_ioctl_mbox *) & pScb->mboxData;
   mailbox = (mega_mailbox *) & pScb->mboxData;
@@ -913,6 +914,14 @@
   }
   /* else normal (nonpassthru) command */
 
+#if LINUX_VERSION_CODE > 0x020024
+/*
+ * usage of the function copy from user is used in case of data more than
+ * 4KB.  This is used only with adapters which supports more than 8 logical
+ * drives.  This feature is disabled on kernels earlier or same as 2.0.36
+ * as the uaccess.h file is not available with those kernels.
+ */
+
   if (SCpnt->cmnd[0] == IOCTL_CMD_NEW) { 
             /* use external data area for large xfers  */
      /* If cmnd[0] is set to IOCTL_CMD_NEW then *
@@ -938,6 +947,7 @@
       copy_from_user(kern_area,user_area,xfer_size);
       pScb->kern_area = kern_area;
   }
+#endif
 
   mbox->cmd = data[0];
   mbox->channel = data[1];
@@ -998,7 +1008,9 @@
  *--------------------------------------------------------------------*/
 static void megaraid_isr (int irq, void *devp, struct pt_regs *regs)
 {
+#if LINUX_VERSION_CODE >= 0x20100
   IO_LOCK_T
+#endif
   mega_host_config    *megaCfg;
   u_char byte, idx, sIdx, tmpBox[MAILBOX_SIZE];
   u32 dword=0;
@@ -1011,7 +1023,6 @@
   megaCfg = (mega_host_config *) devp;
   mbox = (mega_mailbox *)tmpBox;
 
-
   if (megaCfg->host->irq == irq) {
 
     if (megaCfg->flag & IN_ISR) {
@@ -1031,10 +1042,6 @@
       if (dword != 0x10001234) {
 	/* Spurious interrupt */
 	megaCfg->flag &= ~IN_ISR;
-//#if LINUX_VERSION_CODE >= 0x20100
-//        IO_UNLOCK;
-//#endif
-//	break;
 	return;
       }
     }
@@ -1043,10 +1050,6 @@
       if ((byte & VALID_INTR_BYTE) == 0) {
 	/* Spurious interrupt */
 	megaCfg->flag &= ~IN_ISR;
-//#if LINUX_VERSION_CODE >= 0x20100
-//	IO_UNLOCK;
-//#endif
-//	break;
 	return;
       }
       WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte);
@@ -1110,9 +1113,6 @@
  */
 	if (pScb->state == SCB_ABORTED) {
           SCpnt = pScb->SCpnt;
-#if DEBUG
-printk("megaraid_isr:fcnt=%d, pcnt=%d, qcnt=%d\n",megaCfg->qFcnt, megaCfg->qPcnt, megaCfg->qCcnt); 
-#endif
 	}
 	if (pScb->state == SCB_RESET) {
           SCpnt = pScb->SCpnt;
@@ -1211,9 +1211,6 @@
 #endif
 
   /* Wait until mailbox is free */
-#if 0
-  while (mega_busyWaitMbox (megaCfg))
-#endif
   if (mega_busyWaitMbox (megaCfg)) {
     printk("Blocked mailbox......!!\n");
     udelay(1000);
@@ -1266,7 +1263,6 @@
 
       if (pScb) {
 	mega_cmd_done (megaCfg, pScb, mbox->status);
-//	mega_rundoneq (megaCfg);
       }
 
       WRINDOOR (megaCfg, phys_mbox | 0x2);
@@ -1285,7 +1281,6 @@
 
       if (pScb) {
 	mega_cmd_done (megaCfg, pScb, mbox->status);
-//	mega_rundoneq (megaCfg);
       }
       else {
 	TRACE (("Error: NULL pScb!\n"));
@@ -1424,7 +1419,6 @@
   u32 paddr;
   u8 retval;
 
-
   /* Initialize adapter inquiry mailbox*/
   paddr = virt_to_bus (megaCfg->mega_buffer);
   mbox = (mega_mailbox *) mboxData;
@@ -1496,25 +1490,6 @@
     megaCfg->host->can_queue = MAX_COMMANDS-1;
   }
 
-#if 0 
-  int i;
-  printk (KERN_DEBUG "---- Logical drive info from enquiry3 struct----\n");
-  for (i = 0; i < megaCfg->numldrv; i++) {
-    printk ("%d: size: %d prop: %x state: %x\n", i,
-	    enquiry3Pnt->lDrvSize[i],
-	    enquiry3Pnt->lDrvProp[i],
-	    enquiry3Pnt->lDrvState[i]);
-  }
-
-  printk (KERN_DEBUG "---- Physical drive info ----\n");
-  for (i = 0; i < FC_MAX_PHYSICAL_DEVICES; i++) {
-    if (i && !(i % 8))
-      printk ("\n");
-    printk ("%d: %x   ", i, enquiry3Pnt->pDrvState[i]);
-  }
-  printk ("\n");
-#endif
-
 #ifdef HP			/* use HP firmware and bios version encoding */
   sprintf (megaCfg->fwVer, "%c%d%d.%d%d",
 	   megaCfg->productInfo.FwVer[2],
@@ -1573,10 +1548,6 @@
 
 #if LINUX_VERSION_CODE < 0x20100
   while (!pcibios_find_device (pciVendor, pciDev, pciIdx, &pciBus, &pciDevFun)) {
-
-#if 0
-  } /* keep auto-indenters happy */
-#endif
 #else
   
   struct pci_dev *pdev = pci_devices;
@@ -1590,7 +1561,7 @@
       pcibios_read_config_word (pciBus, pciDevFun,
 				PCI_CONF_AMISIG,
 				&magic);
-      if (magic != AMI_SIGNATURE) {
+      if ((magic != AMI_SIGNATURE) && (magic != AMI_SIGNATURE_471) ){
         pciIdx++;
 	continue;		/* not an AMI board */
       }
@@ -1824,9 +1795,6 @@
 
   /* If driver in abort or reset.. cancel this command */
   if (megaCfg->flag & IN_ABORT) {
-#if DEBUG
-printk("mq: got a request while in abort\n");
-#endif
     SCpnt->result = (DID_ABORT << 16);
     /* Add Scsi_Command to end of completed queue */
     if( megaCfg->qCompletedH == NULL ) {
@@ -1843,9 +1811,6 @@
     return 0;
   }
   else if (megaCfg->flag & IN_RESET) {
-#if DEBUG
-printk("mq: got a request while in reset\n");
-#endif
     SCpnt->result = (DID_RESET << 16);
     /* Add Scsi_Command to end of completed queue */
     if( megaCfg->qCompletedH == NULL ) {
@@ -1878,16 +1843,9 @@
     megaCfg->qPendingT->next = NULL;
     megaCfg->qPcnt++;
 
-
-    /* Issue any pending command to the card if not in ISR */
-//    if (!(megaCfg->flag & IN_ISR)) {
       mega_runpendq(megaCfg);
-//    }
-/* 
- * try running the pend queue, irrespective of the driver's context.
- * -cn 
- */
 
+#if LINUX_VERSION_CODE > 0x020024
     if ( SCpnt->cmnd[0]==IOCTL_CMD_NEW )
     {  /* user data from external user buffer */
           char *user_area;
@@ -1905,6 +1863,7 @@
 
           mega_freeSCB(megaCfg, pScb);
     }
+#endif
   }
 
   megaCfg->flag &= ~IN_QUEUE;
@@ -1959,9 +1918,6 @@
 
   megaCfg->flag |= IN_ABORT;
 
-#if DEBUG
-printk("ma:fcnt=%d, pcnt=%d, qcnt=%d\n",megaCfg->qFcnt, megaCfg->qPcnt, megaCfg->qCcnt); 
-#endif
   for(pScb=megaCfg->qPendingH; pScb; pScb=pScb->next) {
     if (pScb->SCpnt == SCpnt) {
       /* Found an aborting command */
@@ -2013,20 +1969,6 @@
     }
   }
 
-#if 0
-  TRACE (("ABORT!!! %.08lx %.02x <%d.%d.%d>\n",
-	  SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
-	  SCpnt->lun));
-  for(pScb=megaCfg->qPending; pScb; pScb=pScb->next) {
-    if (pScb->SCpnt == SCpnt) { 
-      ser_printk("** %d<%x>  %c\n", pScb->SCpnt->pid, pScb->idx+1,
-		 pScb->state == SCB_ACTIVE ? 'A' : 'I');
-#if DEBUG
-      showMbox(pScb);
-#endif
-    }
-  }
-#endif
   megaCfg->flag &= ~IN_ABORT;
 
 #if DEBUG
@@ -2044,12 +1986,11 @@
   megaCfg->qCompletedH = (Scsi_Cmnd *)SCpnt->host_scribble;
   megaCfg->qCcnt--;
 
-  SCpnt->host_scribble = (unsigned char *) NULL ; // XC : sep 14
+  SCpnt->host_scribble = (unsigned char *) NULL ;
   /* Callback */
   callDone (SCpnt);
 }
   mega_rundoneq(megaCfg);
-
 
   return rc;
 }
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/scsi/megaraid.h linux.15p9/drivers/scsi/megaraid.h
--- linux.vanilla/drivers/scsi/megaraid.h	Tue Jan  4 21:18:57 2000
+++ linux.15p9/drivers/scsi/megaraid.h	Wed Feb 16 20:19:46 2000
@@ -12,7 +12,6 @@
 #define BOARD_QUARTZ            0x08000000L
 #define BOARD_40LD              0x04000000L
 
-#ifndef HOSTS_C
 #define SCB_FREE     0x0
 #define SCB_ACTIVE   0x1
 #define SCB_WAITQ    0x2
@@ -20,7 +19,6 @@
 #define SCB_COMPLETE 0x4
 #define SCB_ABORTED  0x5
 #define SCB_RESET    0x6
-#endif
 
 #define MEGA_CMD_TIMEOUT        10
 
@@ -109,6 +107,7 @@
 #define PCI_CONF_IRQ_OFFSET        0x3c
 #define PCI_CONF_AMISIG            0xa0
 #define AMI_SIGNATURE              0x3344
+#define AMI_SIGNATURE_471          0xCCCC
 
 #if LINUX_VERSION_CODE < 0x20100
 #define MEGARAID \
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/scsi/pci2000.c linux.15p9/drivers/scsi/pci2000.c
--- linux.vanilla/drivers/scsi/pci2000.c	Sat Aug 14 02:25:41 1999
+++ linux.15p9/drivers/scsi/pci2000.c	Thu Feb 17 21:42:32 2000
@@ -128,6 +128,28 @@
 	return TRUE;
 	}
 /****************************************************************
+ *	Name:			WaitReadyLong	:LOCAL
+ *
+ *	Description:	Wait for controller ready.
+ *
+ *	Parameters:		padapter - Pointer adapter data structure.
+ *
+ *	Returns:		TRUE on not ready.
+ *
+ ****************************************************************/
+static int WaitReadyLong (PADAPTER2000 padapter)
+	{
+	ULONG	z;
+
+	for ( z = 0;  z < (5000 * 4);  z++ )
+		{
+		if ( !inb_p (padapter->cmd) )
+			return FALSE;
+		udelay (250);
+		};								
+	return TRUE;
+	}
+/****************************************************************
  *	Name:	OpDone	:LOCAL
  *
  *	Description:	Clean up operation and issue done to caller.
@@ -212,7 +234,7 @@
 	if ( WaitReady (padapter) )						// test for command register ready
 		return DID_TIME_OUT;
 	outb_p (cmd, padapter->cmd);					// issue command
-	if ( WaitReady (padapter) )						// wait for adapter ready
+	if ( WaitReadyLong (padapter) )					// wait for adapter ready
 		return DID_TIME_OUT;
 	return DID_OK;
 	}
@@ -810,4 +832,3 @@
 
 #include "scsi_module.c"
 #endif
-
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/scsi/pci2220i.c linux.15p9/drivers/scsi/pci2220i.c
--- linux.vanilla/drivers/scsi/pci2220i.c	Sat Aug 14 02:25:42 1999
+++ linux.15p9/drivers/scsi/pci2220i.c	Thu Feb 17 21:42:32 2000
@@ -24,8 +24,15 @@
  *	Revisions 1.11		Mar-26-1999
  *		- Fixed spinlock and PCI configuration.
  *
+ *	Revision 2.00		December-1-1999
+ *		- Added code for the PCI-2240I controller
+ *		- Added code for ATAPI devices.
+ *		- Double buffer for scatter/gather support
+ *
  ****************************************************************************/
 
+//#define DEBUG 1
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
@@ -46,6 +53,7 @@
 #include "scsi.h"
 #include "hosts.h"
 #include "pci2220i.h"
+#include "psi_dale.h"
 
 #if LINUX_VERSION_CODE >= LINUXVERSION(2,1,95)
 #include <asm/spinlock.h>
@@ -54,20 +62,14 @@
 #include <linux/bios32.h>
 #endif
 
-#define	PCI2220I_VERSION		"1.11"
-//#define	READ_CMD				IDE_COMMAND_READ
-//#define	WRITE_CMD				IDE_COMMAND_WRITE
-//#define	MAX_BUS_MASTER_BLOCKS	1		// This is the maximum we can bus master
+#define	PCI2220I_VERSION		"2.00"
 #define	READ_CMD				IDE_CMD_READ_MULTIPLE
 #define	WRITE_CMD				IDE_CMD_WRITE_MULTIPLE
 #define	MAX_BUS_MASTER_BLOCKS	SECTORSXFER		// This is the maximum we can bus master
 
-
 struct proc_dir_entry Proc_Scsi_Pci2220i =
 	{ PROC_SCSI_PCI2220I, 8, "pci2220i", S_IFDIR | S_IRUGO | S_IXUGO, 2 };
 
-//#define DEBUG 1
-
 #ifdef DEBUG
 #define DEB(x) x
 #define STOP_HERE()	{int st;for(st=0;st<100;st++){st=1;}}
@@ -81,10 +83,10 @@
 
 typedef struct
 	{
-	UCHAR		   	device;				// device code
 	UCHAR			byte6;				// device select register image
 	UCHAR			spigot;				// spigot number
-	UCHAR			sparebyte;			// placeholder
+	UCHAR			spigots[2];			// RAID spigots
+	UCHAR			deviceID[2];		// device ID codes
 	USHORT			sectors;			// number of sectors per track
 	USHORT			heads;				// number of heads
 	USHORT			cylinders;			// number of cylinders for this device
@@ -94,12 +96,17 @@
 	ULONG			lastsectorlba[2];	// last addressable sector on the drive
 	USHORT			raid;				// RAID active flag
 	USHORT			mirrorRecon;
-	UCHAR			hotRecon;
+	UCHAR			reconOn;
 	USHORT			reconCount;
+	USHORT			reconIsStarting;	// indicate hot reconstruct is starting
+	UCHAR			cmdDrqInt;			// flag for command interrupt
+	UCHAR			packet;				// command packet size in bytes
 	}	OUR_DEVICE, *POUR_DEVICE;	
 
 typedef struct
 	{
+	USHORT		 bigD;					// identity is a PCI-2240I if true, otherwise a PCI-2220I
+	USHORT		 atapi;					// this interface is for ATAPI devices only
 	USHORT		 regDmaDesc;			// address of the DMA discriptor register for direction of transfer
 	USHORT		 regDmaCmdStat;			// Byte #1 of DMA command status register
 	USHORT		 regDmaAddrPci;			// 32 bit register for PCI address of DMA
@@ -128,16 +135,21 @@
 	USHORT		 timingPIO;				// TRUE if PIO timing is active
 	ULONG		 timingAddress;			// address to use on adapter for current timing mode
 	ULONG		 irqOwned;				// owned IRQ or zero if shared
-	OUR_DEVICE	 device[DALE_MAXDRIVES];
-	DISK_MIRROR	*raidData[8];
+	UCHAR		 numberOfDrives;		// saved number of drives on this controller
+	UCHAR		 failRegister;			// current inverted data in fail register
+	OUR_DEVICE	 device[BIGD_MAXDRIVES];
+	DISK_MIRROR	*raidData[BIGD_MAXDRIVES];
 	ULONG		 startSector;
 	USHORT		 sectorCount;
+	ULONG		 readCount;
+	UCHAR		*currentSgBuffer;
+	ULONG		 currentSgCount;
+	USHORT		 nextSg;
 	UCHAR		 cmd;
 	Scsi_Cmnd	*SCpnt;
-	VOID		*buffer;
 	POUR_DEVICE	 pdev;					// current device opearating on
+	USHORT		 devInReconIndex;
 	USHORT		 expectingIRQ;
-	USHORT		 reconIsStarting;		// indicate hot reconstruct is starting
 	USHORT		 reconOn;				// Hot reconstruct is to be done.
 	USHORT		 reconPhase;			// Hot reconstruct operation is in progress.
 	ULONG		 reconSize;
@@ -147,6 +159,9 @@
 	struct timer_list	reconTimer;	
 	struct timer_list	timer;
 	UCHAR		*kBuffer;
+	UCHAR		 reqSense;
+	UCHAR		 atapiCdb[16];
+	UCHAR		 atapiSpecial;
 	}	ADAPTER2220I, *PADAPTER2220I;
 
 #define HOSTDATA(host) ((PADAPTER2220I)&host->hostdata)
@@ -161,12 +176,41 @@
 
 static struct	Scsi_Host 	   *PsiHost[MAXADAPTER] = {NULL,};  // One for each adapter
 static			int				NumAdapters = 0;
+static			int				Installed = 0;
 static			SETUP			DaleSetup;
-static			DISK_MIRROR		DiskMirror[2];
-static			ULONG			ModeArray[] = {DALE_DATA_MODE2, DALE_DATA_MODE3, DALE_DATA_MODE4, DALE_DATA_MODE4P};
+static			DISK_MIRROR		DiskMirror[BIGD_MAXDRIVES];
+static			ULONG			ModeArray[] = {DALE_DATA_MODE2, DALE_DATA_MODE3, DALE_DATA_MODE4, DALE_DATA_MODE5};
+static			ULONG			ModeArray2[] = {BIGD_DATA_MODE2, BIGD_DATA_MODE3, BIGD_DATA_MODE4, BIGD_DATA_MODE5};
 
 static void ReconTimerExpiry (unsigned long data);
 
+/*******************************************************************************************************
+ *	Name:			Alarm
+ *
+ *	Description:	Sound the for the given device
+ *
+ *	Parameters:		padapter - Pointer adapter data structure.
+ *					device	 - Device number.
+ *	
+ *	Returns:		Nothing.
+ *
+ ******************************************************************************************************/
+static void Alarm (PADAPTER2220I padapter, UCHAR device)
+	{
+	UCHAR	zc;
+
+	if ( padapter->bigD )
+		{
+		zc = device | (FAIL_ANY | FAIL_AUDIBLE);
+		if ( padapter->failRegister & FAIL_ANY ) 
+			zc |= FAIL_MULTIPLE;
+		
+		padapter->failRegister = zc;
+		outb_p (~zc, padapter->regFail);
+		}
+	else
+		outb_p (0x3C | (1 << device), padapter->regFail);			// sound alarm and set fail light		
+	}
 /****************************************************************
  *	Name:	MuteAlarm	:LOCAL
  *
@@ -181,8 +225,16 @@
 	{
 	UCHAR	old;
 
-	old = (inb_p (padapter->regStatSel) >> 3) | (inb_p (padapter->regStatSel) & 0x83);
-	outb_p (old | 0x40, padapter->regFail);
+	if ( padapter->bigD )
+		{
+		padapter->failRegister &= ~FAIL_AUDIBLE;
+		outb_p (~padapter->failRegister, padapter->regFail);
+		}
+	else
+		{
+		old = (inb_p (padapter->regStatSel) >> 3) | (inb_p (padapter->regStatSel) & 0x83);
+		outb_p (old | 0x40, padapter->regFail);
+		}
 	}
 /****************************************************************
  *	Name:	WaitReady	:LOCAL
@@ -223,17 +275,17 @@
 	ULONG	z;
 	UCHAR	status;
 
-	for ( z = 0;  z < (250 * 4);  z++ )				// wait up to 1/4 second
+	for ( z = 0;  z < (125 * 16);  z++ )				// wait up to 1/4 second
 		{
 		status = inb_p (padapter->regStatCmd);
 		if ( (status & (IDE_STATUS_DRDY | IDE_STATUS_BUSY)) == IDE_STATUS_DRDY )
 			{
-			DEB (printk ("\nPCI2220I:  Reset took %ld mSec to be ready", z / 4));
+			DEB (printk ("\nPCI2220I:  Reset took %ld mSec to be ready", z / 8));
 			return 0;
 			}
-		udelay (250);
+		udelay (125);
 		}
-	DEB (printk ("\nPCI2220I:  Reset took more than 1 Second to come ready, Disk Failure"));
+	DEB (printk ("\nPCI2220I:  Reset took more than 2 Seconds to come ready, Disk Failure"));
 	return status;
 	}
 /****************************************************************
@@ -261,6 +313,52 @@
 	return status;
 	}
 /****************************************************************
+ *	Name:	AtapiWaitReady	:LOCAL
+ *
+ *	Description:	Wait for device busy and DRQ to be cleared.
+ *
+ *	Parameters:		padapter - Pointer adapter data structure.
+ *					msec	 - Number of milliseconds to wait.
+ *
+ *	Returns:		TRUE if drive does not clear busy in time.
+ *
+ ****************************************************************/
+static int AtapiWaitReady (PADAPTER2220I padapter, int msec)
+	{
+	int z;
+
+	for ( z = 0;  z < (msec * 16);  z++ )
+		{
+		if ( !(inb_p (padapter->regStatCmd) & (IDE_STATUS_BUSY | IDE_STATUS_DRQ)) )
+			return FALSE;
+		udelay (125);
+		}
+	return TRUE;
+	}
+/****************************************************************
+ *	Name:	AtapiWaitDrq	:LOCAL
+ *
+ *	Description:	Wait for device ready for data transfer.
+ *
+ *	Parameters:		padapter - Pointer adapter data structure.
+ *					msec	 - Number of milliseconds to wait.
+ *
+ *	Returns:		TRUE if drive does not assert DRQ in time.
+ *
+ ****************************************************************/
+static int AtapiWaitDrq (PADAPTER2220I padapter, int msec)
+	{
+	ULONG	z;
+
+	for ( z = 0;  z < (msec * 16);  z++ )
+		{
+		if ( inb_p (padapter->regStatCmd) & IDE_STATUS_DRQ )
+			return 0;
+		udelay (128);
+		}
+	return TRUE;
+	}
+/****************************************************************
  *	Name:	HardReset	:LOCAL
  *
  *	Description:	Wait for device ready for data transfer.
@@ -274,24 +372,113 @@
  ****************************************************************/
 static int HardReset (PADAPTER2220I padapter, POUR_DEVICE pdev, UCHAR spigot)
 	{
-	SelectSpigot (padapter, spigot | 0x80);
+	DEB (printk ("\npci2220i:RESET  spigot = %X  devices = %d, %d", spigot, pdev->deviceID[0], pdev->deviceID[1]));
+	udelay (100000);										// just wait 100 mSec to let drives flush	
+	SelectSpigot (padapter, spigot | SEL_IRQ_OFF);
 	
 	outb_p (0x0E, padapter->regAltStat);					// reset the suvivor
 	udelay (100);											// wait a little	
 	outb_p (0x08, padapter->regAltStat);					// clear the reset
 	udelay (100);
-	outb_p (0xA0, padapter->regLba24);						//Specify drive
 
-	outb_p (pdev->byte6, padapter->regLba24);				// select the drive
+	outb_p (0xA0, padapter->regLba24);						// select the master drive
 	if ( WaitReadyReset (padapter) )
+		{
+		DEB (printk ("\npci2220i: master not ready after reset"));
 		return TRUE;
+		}
+	outb_p (0xB0, padapter->regLba24);						// try the slave drive
+	if ( (inb_p (padapter->regStatCmd) & (IDE_STATUS_DRDY | IDE_STATUS_BUSY)) == IDE_STATUS_DRDY ) 
+		{
+		DEB (printk ("\nPCI2220I: initializing slave drive on spigot %X", spigot));
+		outb_p (SECTORSXFER, padapter->regSectCount);
+		WriteCommand (padapter, IDE_CMD_SET_MULTIPLE);	
+		if ( WaitReady (padapter) )
+			{
+			DEB (printk ("\npci2220i: slave not ready after set multiple"));
+			return TRUE;
+			}
+		}
+	
+	outb_p (0xA0, padapter->regLba24);				// select the drive
 	outb_p (SECTORSXFER, padapter->regSectCount);
 	WriteCommand (padapter, IDE_CMD_SET_MULTIPLE);	
 	if ( WaitReady (padapter) )
+		{
+		DEB (printk ("\npci2220i: master not ready after set multiple"));
+		return TRUE;
+		}
+	return FALSE;
+	}
+/****************************************************************
+ *	Name:	AtapiReset	:LOCAL
+ *
+ *	Description:	Wait for device ready for data transfer.
+ *
+ *	Parameters:		padapter - Pointer adapter data structure.
+ *					pdev	 - Pointer to device.
+ *
+ *	Returns:		TRUE if drive does not come ready.
+ *
+ ****************************************************************/
+static int AtapiReset (PADAPTER2220I padapter, POUR_DEVICE pdev)
+	{
+	SelectSpigot (padapter, pdev->spigot);
+	AtapiDevice (padapter, pdev->byte6);
+	AtapiCountLo (padapter, 0);
+	AtapiCountHi (padapter, 0);
+	WriteCommand (padapter, IDE_COMMAND_ATAPI_RESET);
+	udelay (125);
+	if ( AtapiWaitReady (padapter, 1000) )
+		return TRUE;
+	if ( inb_p (padapter->regStatCmd) || (inb_p (padapter->regLba8) != 0x14) || (inb_p (padapter->regLba16) != 0xEB) )
 		return TRUE;
 	return FALSE;
 	}
 /****************************************************************
+ *	Name:	WalkScatGath	:LOCAL
+ *
+ *	Description:	Transfer data to/from scatter/gather buffers.
+ *
+ *	Parameters:		padapter - Pointer adapter data structure.
+ *					datain   - TRUE if data read.
+ *					length   - Number of bytes to transfer.
+ *
+ *	Returns:		Nothing.
+ *
+ ****************************************************************/
+static void WalkScatGath (PADAPTER2220I padapter, UCHAR datain, ULONG length)
+	{
+	ULONG	 count;
+	UCHAR	*buffer = padapter->kBuffer;
+
+	while ( length )
+		{
+		count = ( length > padapter->currentSgCount ) ? padapter->currentSgCount : length; 
+		
+		if ( datain )
+			memcpy (padapter->currentSgBuffer, buffer, count);
+		else
+			memcpy (buffer, padapter->currentSgBuffer, count);
+
+		padapter->currentSgCount -= count;
+		if ( !padapter->currentSgCount )
+			{
+			if ( padapter->nextSg < padapter->SCpnt->use_sg )
+				{
+				padapter->currentSgBuffer = ((struct scatterlist *)padapter->SCpnt->request_buffer)[padapter->nextSg].address;
+				padapter->currentSgCount = ((struct scatterlist *)padapter->SCpnt->request_buffer)[padapter->nextSg].length;
+				padapter->nextSg++;
+				}
+			}
+		else
+			padapter->currentSgBuffer += count;
+
+		length -= count;
+		buffer += count;
+		}
+	}
+/****************************************************************
  *	Name:	BusMaster	:LOCAL
  *
  *	Description:	Do a bus master I/O.
@@ -300,34 +487,84 @@
  *					datain	 - TRUE if data read.
  *					irq		 - TRUE if bus master interrupt expected.
  *
- *	Returns:		TRUE if drive does not assert DRQ in time.
+ *	Returns:		Nothing.
  *
  ****************************************************************/
 static void BusMaster (PADAPTER2220I padapter, UCHAR datain, UCHAR irq)
 	{
 	ULONG zl;
 	
-	outl (padapter->timingAddress, padapter->regDmaAddrLoc);
-	outl (virt_to_bus (padapter->buffer), padapter->regDmaAddrPci);
-	zl = (padapter->sectorCount > MAX_BUS_MASTER_BLOCKS) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount;
+	zl = ( padapter->sectorCount > MAX_BUS_MASTER_BLOCKS ) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount;
 	padapter->sectorCount -= zl;
 	zl *= (ULONG)BYTES_PER_SECTOR;
-	padapter->buffer += zl;
-	outl (zl, padapter->regDmaCount);
+
 	if ( datain )
 		{
-		outb_p (8, padapter->regDmaDesc);						// read operation
-		if ( irq && !padapter->sectorCount )
-			outb_p (5, padapter->regDmaMode);					// interrupt on
+		padapter->readCount = zl;
+		outb_p (8, padapter->regDmaDesc);							// read operation
+		if ( padapter->bigD )
+			{
+			if ( irq && !padapter->sectorCount )
+				outb_p (0x0C, padapter->regDmaMode);				// interrupt on
+			else
+				outb_p (0x08, padapter->regDmaMode);				// no interrupt
+			}
+		else 
+			{
+			if ( irq && !padapter->sectorCount )
+				outb_p (0x05, padapter->regDmaMode);				// interrupt on
+			else
+				outb_p (0x01, padapter->regDmaMode);				// no interrupt
+			}
+		}
+	else
+		{
+		outb_p (0x00, padapter->regDmaDesc);						// write operation
+		if ( padapter->bigD )
+			outb_p (0x08, padapter->regDmaMode);					// no interrupt						
 		else
-			outb_p (1, padapter->regDmaMode);					// no interrupt
+			outb_p (0x01, padapter->regDmaMode);					// no interrupt
+		WalkScatGath (padapter, FALSE, zl);	
+		}
+	
+	outl (padapter->timingAddress, padapter->regDmaAddrLoc);
+	outl (virt_to_bus (padapter->kBuffer), padapter->regDmaAddrPci);
+	outl (zl, padapter->regDmaCount);
+	outb_p (0x03, padapter->regDmaCmdStat);							// kick the DMA engine in gear
+	}
+/****************************************************************
+ *	Name:	AtapiBusMaster	:LOCAL
+ *
+ *	Description:	Do a bus master I/O.
+ *
+ *	Parameters:		padapter - Pointer adapter data structure.
+ *					datain	 - TRUE if data read.
+ *					length	 - Number of bytes to transfer.
+ *
+ *	Returns:		Nothing.
+ *
+ ****************************************************************/
+static void AtapiBusMaster (PADAPTER2220I padapter, UCHAR datain, ULONG length)
+	{
+	outl (padapter->timingAddress, padapter->regDmaAddrLoc);
+	outl (virt_to_bus (padapter->kBuffer), padapter->regDmaAddrPci);
+	outl (length, padapter->regDmaCount);
+	if ( datain )
+		{
+		if ( padapter->readCount )
+				WalkScatGath (padapter, TRUE, padapter->readCount);
+		outb_p (0x08, padapter->regDmaDesc);						// read operation
+		outb_p (0x08, padapter->regDmaMode);						// no interrupt
+		padapter->readCount = length;
 		}
 	else
 		{
-		outb_p (0, padapter->regDmaDesc);						// write operation
-		outb_p (1, padapter->regDmaMode);						// no interrupt
+		outb_p (0x00, padapter->regDmaDesc);						// write operation
+		outb_p (0x08, padapter->regDmaMode);						// no interrupt						
+		if ( !padapter->atapiSpecial )
+			WalkScatGath (padapter, FALSE, length);	
 		}
-	outb_p (0x03, padapter->regDmaCmdStat);						// kick the DMA engine in gear
+	outb_p (0x03, padapter->regDmaCmdStat);							// kick the DMA engine in gear
 	}
 /****************************************************************
  *	Name:	WriteData	:LOCAL
@@ -348,9 +585,9 @@
 		if ( padapter->timingPIO )
 			{
 			zl = (padapter->sectorCount > MAX_BUS_MASTER_BLOCKS) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount;
-			outsw (padapter->regData, padapter->buffer, zl * (BYTES_PER_SECTOR / 2));
+			WalkScatGath (padapter, FALSE, zl * BYTES_PER_SECTOR);
+			outsw (padapter->regData, padapter->kBuffer, zl * (BYTES_PER_SECTOR / 2));
 			padapter->sectorCount -= zl;
-			padapter->buffer += zl * BYTES_PER_SECTOR;
 			}
 		else
 			BusMaster (padapter, 0, 0);
@@ -364,31 +601,32 @@
  *
  *	Description:	Write data to device.
  *
- *	Parameters:		padapter - Pointer adapter data structure.
+ *	Parameters:		padapter - Pointer to adapter structure.
+ *					pdev	 - Pointer to device structure
  *
- *	Returns:		TRUE if drive does not assert DRQ in time.
+ *	Returns:		Index + 1 of drive not failed or zero for OK.
  *
  ****************************************************************/
-static int WriteDataBoth (PADAPTER2220I padapter)
+static int WriteDataBoth (PADAPTER2220I padapter, POUR_DEVICE pdev)
 	{
 	ULONG	zl;
 	UCHAR	status0, status1;
 
-	SelectSpigot (padapter, 1);
+	SelectSpigot (padapter, pdev->spigots[0]);
 	status0 = WaitDrq (padapter);
 	if ( !status0 )
 		{
-		SelectSpigot (padapter, 2);
+		SelectSpigot (padapter, pdev->spigots[1]);
 		status1 = WaitDrq (padapter);
 		if ( !status1 )
 			{
-			SelectSpigot (padapter, 3);
+			SelectSpigot (padapter, pdev->spigots[0] | pdev->spigots[1] | padapter->bigD);
 			if ( padapter->timingPIO )
 				{
 				zl = (padapter->sectorCount > MAX_BUS_MASTER_BLOCKS) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount;
-				outsw (padapter->regData, padapter->buffer, zl * (BYTES_PER_SECTOR / 2));
+				WalkScatGath (padapter, FALSE, zl * BYTES_PER_SECTOR);
+				outsw (padapter->regData, padapter->kBuffer, zl * (BYTES_PER_SECTOR / 2));
 				padapter->sectorCount -= zl;
-				padapter->buffer += zl * BYTES_PER_SECTOR;
 				}
 			else
 				BusMaster (padapter, 0, 0);
@@ -397,8 +635,8 @@
 		}
 	padapter->cmd = 0;												// null out the command byte
 	if ( status0 )
-		return 1;
-	return 2;
+		return 2;
+	return 1;
 	}
 /****************************************************************
  *	Name:	IdeCmd	:LOCAL
@@ -415,7 +653,7 @@
 	{
 	UCHAR	status;
 
-	SelectSpigot (padapter, pdev->spigot);							// select the spigot
+	SelectSpigot (padapter, pdev->spigot | padapter->bigD);							// select the spigot
 	outb_p (pdev->byte6 | ((UCHAR *)(&padapter->startSector))[3], padapter->regLba24);			// select the drive
 	status = WaitReady (padapter);
 	if ( !status )
@@ -438,26 +676,27 @@
  *	Description:	Process an IDE command to both drivers.
  *
  *	Parameters:		padapter - Pointer adapter data structure.
+ *					pdev	 - Pointer to device structure
  *
- *	Returns:		Zero if no error or spigot of error.
+ *	Returns:		Index + 1 of drive not failed or zero for OK.
  *
  ****************************************************************/
-static UCHAR IdeCmdBoth (PADAPTER2220I padapter)
+static UCHAR IdeCmdBoth (PADAPTER2220I padapter, POUR_DEVICE pdev)
 	{
 	UCHAR	status0;
 	UCHAR	status1;
 
-	SelectSpigot (padapter, 3);										// select the spigots
+	SelectSpigot (padapter, pdev->spigots[0] | pdev->spigots[1]);								// select the spigots
 	outb_p (padapter->pdev->byte6 | ((UCHAR *)(&padapter->startSector))[3], padapter->regLba24);// select the drive
-	SelectSpigot (padapter, 1);
+	SelectSpigot (padapter, pdev->spigots[0]);
 	status0 = WaitReady (padapter);
 	if ( !status0 )
 		{
-		SelectSpigot (padapter, 2);
+		SelectSpigot (padapter, pdev->spigots[1]);
 		status1 = WaitReady (padapter);
 		if ( !status1 )
 			{
-			SelectSpigot (padapter, 3);
+			SelectSpigot (padapter, pdev->spigots[0] | pdev->spigots[1] | padapter->bigD);
 			outb_p (padapter->sectorCount, padapter->regSectCount);
 			outb_p (((UCHAR *)(&padapter->startSector))[0], padapter->regLba0);
 			outb_p (((UCHAR *)(&padapter->startSector))[1], padapter->regLba8);
@@ -469,8 +708,8 @@
 		}
 	padapter->cmd = 0;									// null out the command byte
 	if ( status0 )
-		return 1;
-	return 2;
+		return 2;
+	return 1;
 	}
 /****************************************************************
  *	Name:	OpDone	:LOCAL
@@ -507,6 +746,7 @@
 		{
 		padapter->cmd = 0;
 		padapter->SCpnt = NULL;	
+		padapter->pdev = NULL;
 		SCpnt->result = result;
 		SCpnt->scsi_done (SCpnt);
 		if ( padapter->reconOn && !padapter->reconTimer.data )
@@ -533,8 +773,8 @@
 	{
 	PIDENTIFY_DATA	pid = (PIDENTIFY_DATA)padapter->kBuffer;
 
-	SelectSpigot (padapter, spigot | 0x80);						// select the spigot
-	outb_p (device << 4, padapter->regLba24);				// select the drive
+	SelectSpigot (padapter, spigot | SEL_IRQ_OFF);					// select the spigot
+	outb_p ((device << 4) | 0xA0, padapter->regLba24);				// select the drive
 	if ( WaitReady (padapter) )
 		return 0;
 	WriteCommand (padapter, IDE_COMMAND_IDENTIFY);	
@@ -544,6 +784,192 @@
 	return (pid->LBATotalSectors - 1);
 	}
 /****************************************************************
+ *	Name:	AtapiIdentify	:LOCAL
+ *
+ *	Description:	Do an intline inquiry on a drive.
+ *
+ *	Parameters:		padapter - Pointer to host data block.
+ *					pdev	 - Pointer to device table.
+ *
+ *	Returns:		TRUE on error.
+ *
+ ****************************************************************/
+static ULONG AtapiIdentify (PADAPTER2220I padapter, POUR_DEVICE pdev)
+	{
+	ATAPI_GENERAL_0		ag0;
+	USHORT				zs;
+	int					z;
+
+	AtapiDevice (padapter, pdev->byte6);	
+	WriteCommand (padapter, IDE_COMMAND_ATAPI_IDENTIFY);	
+	if ( AtapiWaitDrq (padapter, 3000) )
+		return TRUE;
+
+	*(USHORT *)&ag0 = inw_p (padapter->regData);
+	for ( z = 0;  z < 255;  z++ )
+		zs = inw_p (padapter->regData);
+
+	if ( ag0.ProtocolType == 2 )
+		{
+		if ( ag0.CmdDrqType == 1 )
+			pdev->cmdDrqInt = TRUE;
+		switch ( ag0.CmdPacketSize )
+			{
+			case 0:
+				pdev->packet = 6;
+				break;
+			case 1:
+				pdev->packet = 8;
+				break;
+			default:
+				pdev->packet = 6;
+				break;
+			}
+		return FALSE;
+		}
+	return TRUE;
+	}
+/****************************************************************
+ *	Name:	Atapi2Scsi
+ *
+ *	Description:	Convert ATAPI data to SCSI data.
+ *
+ *	Parameters:		padapter - Pointer adapter data structure.
+ *					SCpnt	 - Pointer to SCSI command structure.
+ *
+ *	Returns:		Nothing.
+ *
+ ****************************************************************/
+void Atapi2Scsi (PADAPTER2220I padapter, Scsi_Cmnd *SCpnt)
+	{
+	UCHAR	*buff = padapter->currentSgBuffer;
+ 
+	switch ( SCpnt->cmnd[0] )
+		{
+		case SCSIOP_MODE_SENSE:
+			buff[0] = padapter->kBuffer[1];
+			buff[1] = padapter->kBuffer[2];
+			buff[2] = padapter->kBuffer[3];
+			buff[3] = padapter->kBuffer[7];
+			memcpy (&buff[4], &padapter->kBuffer[8], padapter->atapiCdb[8] - 8);
+			break;
+		case SCSIOP_INQUIRY:
+			padapter->kBuffer[2] = 2;
+			memcpy (buff, padapter->kBuffer, padapter->currentSgCount);
+			break;		
+		default:
+			if ( padapter->readCount )
+				WalkScatGath (padapter, TRUE, padapter->readCount);
+			break;
+		}
+	}
+/****************************************************************
+ *	Name:	Scsi2Atapi
+ *
+ *	Description:	Convert SCSI packet command to Atapi packet command.
+ *
+ *	Parameters:		padapter - Pointer adapter data structure.
+ *					SCpnt	 - Pointer to SCSI command structure.
+ *
+ *	Returns:		Nothing.
+ *
+ ****************************************************************/
+static void Scsi2Atapi (PADAPTER2220I padapter, Scsi_Cmnd *SCpnt)
+	{
+	UCHAR	*cdb = SCpnt->cmnd;
+	UCHAR	*buff = padapter->currentSgBuffer;
+
+	switch (cdb[0]) 
+		{
+		case SCSIOP_READ6:
+            padapter->atapiCdb[0] = SCSIOP_READ;
+			padapter->atapiCdb[1] = cdb[1] & 0xE0;
+            padapter->atapiCdb[3] = cdb[1] & 0x1F;
+			padapter->atapiCdb[4] = cdb[2];
+			padapter->atapiCdb[5] = cdb[3];
+			padapter->atapiCdb[8] = cdb[4];
+			padapter->atapiCdb[9] = cdb[5];
+			break;
+		case SCSIOP_WRITE6:
+            padapter->atapiCdb[0] = SCSIOP_WRITE;
+			padapter->atapiCdb[1] = cdb[1] & 0xE0;
+            padapter->atapiCdb[3] = cdb[1] & 0x1F;
+			padapter->atapiCdb[4] = cdb[2];
+			padapter->atapiCdb[5] = cdb[3];
+			padapter->atapiCdb[8] = cdb[4];
+			padapter->atapiCdb[9] = cdb[5];
+			break;
+        case SCSIOP_MODE_SENSE: 
+            padapter->atapiCdb[0] = SCSIOP_MODE_SENSE10;
+			padapter->atapiCdb[2] = cdb[2];
+			padapter->atapiCdb[8] = cdb[4] + 4;
+            break;
+
+        case SCSIOP_MODE_SELECT: 
+			padapter->atapiSpecial = TRUE;
+			padapter->atapiCdb[0] = SCSIOP_MODE_SELECT10;
+			padapter->atapiCdb[1] = cdb[1] | 0x10;
+			memcpy (padapter->kBuffer, buff, 4);
+			padapter->kBuffer[4] = padapter->kBuffer[5] = 0;
+			padapter->kBuffer[6] = padapter->kBuffer[7] = 0;
+			memcpy (&padapter->kBuffer[8], &buff[4], cdb[4] - 4);
+			padapter->atapiCdb[8] = cdb[4] + 4;
+			break;
+	    }
+	}
+/****************************************************************
+ *	Name:	AtapiSendCdb
+ *
+ *	Description:	Send the CDB packet to the device.
+ *
+ *	Parameters:		padapter - Pointer adapter data structure.
+ *					pdev	 - Pointer to device.
+ *					cdb		 - Pointer to 16 byte SCSI cdb.
+ *
+ *	Returns:		Nothing.
+ *
+ ****************************************************************/
+static void AtapiSendCdb (PADAPTER2220I padapter, POUR_DEVICE pdev, CHAR *cdb)
+	{
+	DEB (printk ("\nPCI2242I: CDB: %X %X %X %X %X %X %X %X %X %X %X %X", cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9], cdb[10], cdb[11]));
+	outsw (padapter->regData, cdb, pdev->packet);
+	}
+/****************************************************************
+ *	Name:	AtapiRequestSense
+ *
+ *	Description:	Send the CDB packet to the device.
+ *
+ *	Parameters:		padapter - Pointer adapter data structure.
+ *					pdev	 - Pointer to device.
+ *					SCpnt	 - Pointer to SCSI command structure.
+ *					pass	 - If true then this is the second pass to send cdb.
+ *
+ *	Returns:		TRUE on error.
+ *
+ ****************************************************************/
+static int AtapiRequestSense (PADAPTER2220I padapter, POUR_DEVICE pdev, Scsi_Cmnd *SCpnt, UCHAR pass)
+	{
+	UCHAR	cdb[16] = {SCSIOP_REQUEST_SENSE,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0};		
+	
+	DEB (printk ("\nPCI2242I: AUTO REQUEST SENSE"));
+	cdb[4] = (UCHAR)(sizeof (SCpnt->sense_buffer));
+	if ( !pass )
+		{
+		padapter->reqSense = TRUE;
+	 	AtapiCountLo (padapter, cdb[4]);						
+		AtapiCountHi (padapter, 0);						
+		outb_p (0, padapter->regError);						
+		WriteCommand (padapter, IDE_COMMAND_ATAPI_PACKET);
+		if ( pdev->cmdDrqInt )
+			return FALSE;
+
+		if ( AtapiWaitDrq (padapter, 500) )
+			return TRUE;
+		}
+	AtapiSendCdb (padapter, pdev, cdb);	
+	return FALSE;
+	}
+/****************************************************************
  *	Name:	InlineReadSignature	:LOCAL
  *
  *	Description:	Do an inline read RAID sigature.
@@ -558,10 +984,9 @@
 static UCHAR InlineReadSignature (PADAPTER2220I padapter, POUR_DEVICE pdev, int index)
 	{
 	UCHAR	status;
-	UCHAR	spigot = 1 << index;
 	ULONG	zl = pdev->lastsectorlba[index];
 
-	SelectSpigot (padapter, spigot | 0x80);				// select the spigot without interrupts
+	SelectSpigot (padapter, pdev->spigots[index] | SEL_IRQ_OFF);	// select the spigot without interrupts
 	outb_p (pdev->byte6 | ((UCHAR *)&zl)[3], padapter->regLba24);		
 	status = WaitReady (padapter);
 	if ( !status )
@@ -600,6 +1025,10 @@
 	UCHAR			error;
 
 	padapter->expectingIRQ = 0;
+#ifdef DEBUG
+	printk (" @@@@@@  status: %X @@@@@@@ ", status);
+	STOP_HERE();	
+#endif
 	if ( status & IDE_STATUS_WRITE_FAULT )
 		{
 		return DID_PARITY << 16;
@@ -687,25 +1116,33 @@
  ******************************************************************************************************/
 static int InitFailover (PADAPTER2220I padapter, POUR_DEVICE pdev)
 	{
-	UCHAR			 spigot;
+	UCHAR	spigot;
 	
-	DEB (printk ("\npci2220i:  Initialize failover process - survivor = %d", padapter->survivor));
+	DEB (printk ("\npci2220i:  Initialize failover process - survivor = %d", pdev->deviceID[padapter->survivor]));
 	pdev->raid = FALSE;									//initializes system for non raid mode
-	pdev->hotRecon = 0;
-	padapter->reconOn = FALSE;
-	spigot = (padapter->survivor) ? 2 : 1;	
+	pdev->reconOn = FALSE;
+	spigot = pdev->spigots[padapter->survivor];	
 
 	if ( pdev->DiskMirror[padapter->survivor].status & UCBF_REBUILD )
-		return (TRUE); 	
+		{
+		DEB (printk ("\n         failed, is survivor"));
+		return (TRUE); 
+		}
 
 	if ( HardReset (padapter, pdev, spigot) )
+		{
+		DEB (printk ("\n         failed, reset"));
 		return TRUE;
+		}
 
-	outb_p (0x3C | spigot, padapter->regFail);			// sound alarm and set fail light		
+	Alarm (padapter, pdev->deviceID[padapter->survivor ^ 1]);
 	pdev->DiskMirror[padapter->survivor].status = UCBF_MIRRORED | UCBF_SURVIVOR;	//clear present status
 	
 	if ( WriteSignature (padapter, pdev, spigot, padapter->survivor) )
+		{
+		DEB (printk ("\n         failed, write signature"));
 		return TRUE;
+		}
 	padapter->failinprog = TRUE;
 	return FALSE;
 	}
@@ -758,7 +1195,7 @@
 			{
 			case RECON_PHASE_MARKING:
 			case RECON_PHASE_LAST:
-				padapter->survivor = (pdev->spigot ^ 3) >> 1;
+				padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 1 : 0;
 				DEB (printk ("\npci2220i: FAILURE 1"));
 				if ( InitFailover (padapter, pdev) )
 					OpDone (padapter, DID_ERROR << 16);
@@ -769,7 +1206,7 @@
 				goto timerExpiryDone;
 
 			case RECON_PHASE_COPY:
-				padapter->survivor = (pdev->spigot) >> 1;
+				padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
 				DEB (printk ("\npci2220i: FAILURE 2"));
 				DEB (printk ("\n       spig/stat = %X", inb_p (padapter->regStatSel));
 				if ( InitFailover (padapter, pdev) )
@@ -777,14 +1214,14 @@
 				goto timerExpiryDone;
 
 			case RECON_PHASE_UPDATE:
-				padapter->survivor = (pdev->spigot) >> 1;
+				padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
 				DEB (printk ("\npci2220i: FAILURE 3")));
 				if ( InitFailover (padapter, pdev) )
 					OpDone (padapter, DID_ERROR << 16);
 				goto timerExpiryDone;
 
 			case RECON_PHASE_END:
-				padapter->survivor = (pdev->spigot) >> 1;
+				padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
 				DEB (printk ("\npci2220i: FAILURE 4"));
 				if ( InitFailover (padapter, pdev) )
 					OpDone (padapter, DID_ERROR << 16);
@@ -803,17 +1240,21 @@
 			if ( padapter->cmd == WRITE_CMD )
 				{
 				DEB (printk ("in RAID write operation"));
-				if ( inb_p (padapter->regStatSel) & 1 )
+				temp = ( pdev->spigot & (SEL_1 | SEL_2) ) ? SEL_1 : SEL_3;
+				if ( inb_p (padapter->regStatSel) & temp )
 					{
-					SelectSpigot (padapter, 0x81 ); // Masking the interrupt during spigot select
+					DEB (printk ("\npci2220i: Determined A OK"));
+					SelectSpigot (padapter, temp | SEL_IRQ_OFF); // Masking the interrupt during spigot select
 					temp = inb_p (padapter->regStatCmd);
 					}
 				else
 					temp = IDE_STATUS_BUSY;
 
-				if ( inb (padapter->regStatSel) & 2 )
+				temp1 = ( pdev->spigot & (SEL_1 | SEL_2) ) ? SEL_2 : SEL_4;
+				if ( inb (padapter->regStatSel) & temp1 )
 					{
-					SelectSpigot (padapter, 0x82 ); // Masking the interrupt during spigot select
+					DEB (printk ("\npci2220i: Determined B OK"));
+					SelectSpigot (padapter, temp1 | SEL_IRQ_OFF); // Masking the interrupt during spigot select
 					temp1 = inb_p (padapter->regStatCmd);
 					}
 				else
@@ -821,6 +1262,7 @@
 			
 				if ( (temp & IDE_STATUS_BUSY) || (temp1 & IDE_STATUS_BUSY) )
 					{
+					DEB (printk ("\npci2220i: Status A: %X   B: %X", temp & 0xFF, temp1 & 0xFF));
 	 				if ( (temp & IDE_STATUS_BUSY) && (temp1 & IDE_STATUS_BUSY) ) 
 						{
 						status = temp;
@@ -828,11 +1270,10 @@
 						}		
 					else	
 						{
-						if (temp & IDE_STATUS_BUSY)
+						if ( temp & IDE_STATUS_BUSY )
 							padapter->survivor = 1;
 						else
 							padapter->survivor = 0;
-						DEB (printk ("\npci2220i: FAILURE 5"));
 						if ( InitFailover (padapter, pdev) )
 							{
 							status = inb_p (padapter->regStatCmd);
@@ -845,7 +1286,7 @@
 			else
 				{
 				DEB (printk ("in RAID read operation"));
-				padapter->survivor = (pdev->spigot ^ 3) >> 1;
+				padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
 				DEB (printk ("\npci2220i: FAILURE 6"));
 				if ( InitFailover (padapter, pdev) )
 					{
@@ -898,7 +1339,6 @@
 	pdev->DiskMirror[index ^ 1].status = UCBF_MIRRORED | UCBF_REBUILD;
 	pdev->DiskMirror[index ^ 1].reconstructPoint = 0;						// start the reconstruct
 	pdev->reconCount = 1990;												// mark target drive early
-	pdev->hotRecon = 1 >> index;
 	return pdev->DiskMirror[index].reconstructPoint;
 	}
 /****************************************************************
@@ -920,6 +1360,7 @@
 	USHORT			minmode;
 	ULONG			zl;
 	UCHAR			zc;
+	USHORT			z;
 #if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
     int				flags;
 #else /* version >= v2.1.95 */
@@ -942,23 +1383,43 @@
 	if ( padapter->SCpnt )
 		goto reconTimerExpiry;
 
-	pdev = padapter->device;
-	pid = (PIDENTIFY_DATA)padapter->kBuffer;
 	padapter->reconTimer.data = 0;
+	for ( z = padapter->devInReconIndex + 1;  z < BIGD_MAXDRIVES;  z++ )
+		{
+		if ( padapter->device[z].reconOn )
+			break;
+		}
+	if ( z < BIGD_MAXDRIVES )
+		pdev = &padapter->device[z];
+	else
+		{
+		for ( z = 0;  z < BIGD_MAXDRIVES;  z++ )
+			{
+			if ( padapter->device[z].reconOn )
+				break;
+			}
+		if ( z < BIGD_MAXDRIVES )
+			pdev = &padapter->device[z];
+		else
+			{
+			padapter->reconOn = FALSE;
+			goto reconTimerExpiry;
+			}
+		}
+
+	padapter->devInReconIndex = z;
+	pid = (PIDENTIFY_DATA)padapter->kBuffer;
 	padapter->pdev = pdev;
-	if ( padapter->reconIsStarting )
+	if ( pdev->reconIsStarting )
 		{
-		padapter->reconIsStarting = FALSE;
-		padapter->reconOn = FALSE;
-		pdev->hotRecon = FALSE;
+		pdev->reconIsStarting = FALSE;
+		pdev->reconOn = FALSE;
 
-		if ( (pdev->DiskMirror[0].signature == SIGNATURE) && (pdev->DiskMirror[1].signature == SIGNATURE) &&
+		while ( (pdev->DiskMirror[0].signature == SIGNATURE) && (pdev->DiskMirror[1].signature == SIGNATURE) &&
 			 (pdev->DiskMirror[0].pairIdentifier == (pdev->DiskMirror[1].pairIdentifier ^ 1)) )
 			{
 			if ( (pdev->DiskMirror[0].status & UCBF_MATCHED) && (pdev->DiskMirror[1].status & UCBF_MATCHED) )
-				{
-				goto reconTimerExpiry;
-				}
+				break;;
 
 			if ( pdev->DiskMirror[0].status & UCBF_SURVIVOR )				// is first drive survivor?
 				testsize = SetReconstruct (pdev, 0);
@@ -969,33 +1430,38 @@
 			if ( (pdev->DiskMirror[0].status & UCBF_REBUILD) || (pdev->DiskMirror[1].status & UCBF_REBUILD) )
 				{
 				if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
-					{
-					pdev->hotRecon = 1;
 					pdev->mirrorRecon = 0;
-					}
 				else
-					{
-					pdev->hotRecon = 2;
 					pdev->mirrorRecon = 1;
-					}
+				pdev->reconOn = TRUE;
 				}
+			break;
 			}
 
-		if ( !pdev->hotRecon )
+		if ( !pdev->reconOn )
 			goto reconTimerExpiry;
 
-		zc = ((inb_p (padapter->regStatSel) >> 3) | inb_p (padapter->regStatSel)) & 0x83;		// mute the alarm
-		outb_p (zc | pdev->hotRecon | 0x40, padapter->regFail);
+		if ( padapter->bigD )
+			{
+			padapter->failRegister = 0;
+			outb_p (~padapter->failRegister, padapter->regFail);
+			}
+		else
+			{
+			zc = ((inb_p (padapter->regStatSel) >> 3) | inb_p (padapter->regStatSel)) & 0x83;		// mute the alarm
+			outb_p (0xFF, padapter->regFail);
+			}
 
 		while ( 1 )
 			{
-			if ( HardReset (padapter, pdev, pdev->hotRecon) )
+			DEB (printk ("\npci2220i: hard reset issue"));
+			if ( HardReset (padapter, pdev, pdev->spigots[pdev->mirrorRecon]) )
 				{
 				DEB (printk ("\npci2220i: sub 1"));
 				break;
 				}
 
-			pdev->lastsectorlba[pdev->mirrorRecon] = InlineIdentify (padapter, pdev->hotRecon, 0);
+			pdev->lastsectorlba[pdev->mirrorRecon] = InlineIdentify (padapter, pdev->spigots[pdev->mirrorRecon], pdev->deviceID[pdev->mirrorRecon] & 1);
 
 			if ( pdev->lastsectorlba[pdev->mirrorRecon] < testsize )
 				{
@@ -1051,12 +1517,11 @@
 			break;
 			}
 
-		if ( !padapter->reconOn )
+		if ( !pdev->reconOn )
 			{		
-			pdev->hotRecon = FALSE;
 			padapter->survivor = pdev->mirrorRecon ^ 1;
 			padapter->reconPhase = RECON_PHASE_FAILOVER;
-				DEB (printk ("\npci2220i: FAILURE 7"));
+			DEB (printk ("\npci2220i: FAILURE 7"));
 			InitFailover (padapter, pdev);
 			goto reconTimerExpiry;
 			}
@@ -1075,11 +1540,11 @@
 	if ( pdev->reconCount++ > 2000 )
 		{
 		pdev->reconCount = 0;
-		if ( WriteSignature (padapter, pdev, pdev->hotRecon, pdev->mirrorRecon) )
+		if ( WriteSignature (padapter, pdev, pdev->spigots[pdev->mirrorRecon], pdev->mirrorRecon) )
 			{
 			padapter->survivor = pdev->mirrorRecon ^ 1;
 			padapter->reconPhase = RECON_PHASE_FAILOVER;
-				DEB (printk ("\npci2220i: FAILURE 8"));
+			DEB (printk ("\npci2220i: FAILURE 8"));
 			InitFailover (padapter, pdev);
 			goto reconTimerExpiry;
 			}
@@ -1094,30 +1559,30 @@
 
 	if ( padapter->reconSize )
 		{
-		SelectSpigot (padapter, 3);										// select the spigots
-		outb_p (pdev->byte6 | ((UCHAR *)(&zl))[3], padapter->regLba24);// select the drive
+		SelectSpigot (padapter, pdev->spigots[0] | pdev->spigots[1]);	// select the spigots
+		outb_p (pdev->byte6 | ((UCHAR *)(&zl))[3], padapter->regLba24);	// select the drive
 		SelectSpigot (padapter, pdev->spigot);
 		if ( WaitReady (padapter) )
 			goto reconTimerExpiry;
 
-		SelectSpigot (padapter, pdev->hotRecon);
+		SelectSpigot (padapter, pdev->spigots[pdev->mirrorRecon]);
 		if ( WaitReady (padapter) )
 			{
 			padapter->survivor = pdev->mirrorRecon ^ 1;
 			padapter->reconPhase = RECON_PHASE_FAILOVER;
-				DEB (printk ("\npci2220i: FAILURE 9"));
+			DEB (printk ("\npci2220i: FAILURE 9"));
 			InitFailover (padapter, pdev);
 			goto reconTimerExpiry;
 			}
 	
-		SelectSpigot (padapter, 3);
+		SelectSpigot (padapter, pdev->spigots[0] | pdev->spigots[1]);
 		outb_p (padapter->reconSize & 0xFF, padapter->regSectCount);
 		outb_p (((UCHAR *)(&zl))[0], padapter->regLba0);
 		outb_p (((UCHAR *)(&zl))[1], padapter->regLba8);
 		outb_p (((UCHAR *)(&zl))[2], padapter->regLba16);
 		padapter->expectingIRQ = TRUE;
 		padapter->reconPhase = RECON_PHASE_READY;
-		SelectSpigot (padapter, pdev->hotRecon);
+		SelectSpigot (padapter, pdev->spigots[pdev->mirrorRecon]);
 		WriteCommand (padapter, WRITE_CMD);
 		StartTimer (padapter);
 		SelectSpigot (padapter, pdev->spigot);
@@ -1167,6 +1632,9 @@
 	Scsi_Cmnd		   *SCpnt;
 	UCHAR				status;
 	UCHAR				status1;
+	ATAPI_STATUS		statusa;
+	ATAPI_REASON		reasona;
+	ATAPI_ERROR			errora;
 	int					z;
 	ULONG				zl;
 #if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
@@ -1210,15 +1678,77 @@
 	padapter = HOSTDATA(shost);
 	pdev = padapter->pdev;
 	SCpnt = padapter->SCpnt;
+	outb_p (0x08, padapter->regDmaCmdStat);									// cancel interrupt from DMA engine
 
-	if ( !padapter->expectingIRQ || !(SCpnt || padapter->reconPhase) )
+	if ( padapter->atapi && SCpnt )
+		{
+		*(char *)&statusa = inb_p (padapter->regStatCmd);						// read the device status
+		*(char *)&reasona = inb_p (padapter->regSectCount);						// read the device interrupt reason
+	
+		if ( !statusa.bsy )
+			{
+			if ( statusa.drq )													// test for transfer phase
+				{
+				if ( !reasona.cod )												// test for data phase
+					{
+					z = (ULONG)inb_p (padapter->regLba8) | (ULONG)(inb_p (padapter->regLba16) << 8);
+					if ( padapter->reqSense )
+						insw (padapter->regData, SCpnt->sense_buffer, z / 2);
+					else
+						AtapiBusMaster (padapter, reasona.io, z);
+					goto irq_return;
+					}
+				if ( reasona.cod && !reasona.io )								// test for command packet phase
+					{
+					if ( padapter->reqSense )
+						AtapiRequestSense (padapter, pdev, SCpnt, TRUE);
+					else
+						AtapiSendCdb (padapter, pdev, padapter->atapiCdb);
+					goto irq_return;
+					}
+				}
+			else
+				{
+				if ( reasona.io && statusa.drdy )								// test for status phase
+					{
+					Atapi2Scsi (padapter, SCpnt);
+					if ( statusa.check )
+						{
+						*(UCHAR *)&errora = inb_p (padapter->regError);			// read the device error
+						if ( errora.senseKey )
+							{
+							if ( padapter->reqSense || AtapiRequestSense (padapter, pdev, SCpnt, FALSE) )
+								OpDone (padapter, DID_ERROR << 16);
+							}
+						else
+							{
+							if ( errora.ili || errora.abort )
+								OpDone (padapter, DID_ERROR << 16);
+							else
+								OpDone (padapter, DID_OK << 16);	
+							}
+						}
+					else
+						if ( padapter->reqSense )
+							{
+							DEB (printk ("PCI2242I: Sense codes - %X %X %X ", ((UCHAR *)SCpnt->sense_buffer)[0], ((UCHAR *)SCpnt->sense_buffer)[12], ((UCHAR *)SCpnt->sense_buffer)[13]));
+							OpDone (padapter, (DRIVER_SENSE << 24) | (DID_OK << 16) | 2);
+							}
+						else
+							OpDone (padapter, DID_OK << 16);	
+					}
+				}
+			}		
+		goto irq_return;
+		}
+	
+	if ( !padapter->expectingIRQ || !(SCpnt || padapter->reconPhase) )
 		{
 		DEB(printk ("\npci2220i Unsolicited interrupt\n"));
 		STOP_HERE ();
 		goto irq_return;
 		}
 	padapter->expectingIRQ = 0;
-	outb_p (0x08, padapter->regDmaCmdStat);									// cancel interrupt from DMA engine
 
 	if ( padapter->failinprog )
 		{
@@ -1233,7 +1763,7 @@
 		else
 			{
 			DEB (printk ("\npci2220i: restarting failed opertation."));
-			pdev->spigot = (padapter->survivor) ? 2 : 1;
+			pdev->spigot = (padapter->survivor) ? pdev->spigots[1] : pdev->spigots[0];
 			del_timer (&padapter->timer);
 			if ( padapter->reconPhase )
 				OpDone (padapter, DID_OK << 16);
@@ -1255,15 +1785,15 @@
 					{
 					if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
 						{
-						padapter->survivor = (pdev->spigot ^ 3) >> 1;
+						padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 1 : 0;
 						DEB (printk ("\npci2220i: FAILURE 10"));
 						if ( InitFailover (padapter, pdev) )
 							OpDone (padapter, DecodeError (padapter, status));
 						goto irq_return;
 						}
-					if ( WriteSignature (padapter, pdev, pdev->hotRecon, pdev->mirrorRecon) )
+					if ( WriteSignature (padapter, pdev, pdev->spigots[pdev->mirrorRecon], pdev->mirrorRecon) )
 						{
-						padapter->survivor = (pdev->spigot) >> 1;
+						padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
 						DEB (printk ("\npci2220i: FAILURE 11"));
 						if ( InitFailover (padapter, pdev) )
 							OpDone (padapter, DecodeError (padapter, status));
@@ -1283,17 +1813,17 @@
 					OpDone (padapter, DecodeError (padapter, status));
 					goto irq_return;
 					}
-				SelectSpigot (padapter, pdev->hotRecon);
+				SelectSpigot (padapter, pdev->spigots[pdev->mirrorRecon]);
 				if ( WaitDrq (padapter) )
 					{
 					del_timer (&padapter->timer);
-					padapter->survivor = (pdev->spigot) >> 1;
-				DEB (printk ("\npci2220i: FAILURE 12"));
+					padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
+					DEB (printk ("\npci2220i: FAILURE 12"));
 					if ( InitFailover (padapter, pdev) )
 						OpDone (padapter, DecodeError (padapter, status));
 					goto irq_return;
 					}
-				SelectSpigot (padapter, pdev->spigot | 0x40);
+				SelectSpigot (padapter, pdev->spigot | SEL_COPY | padapter->bigD);
 				padapter->reconPhase = RECON_PHASE_COPY;
 				padapter->expectingIRQ = TRUE;
 				if ( padapter->timingPIO )
@@ -1302,11 +1832,22 @@
 					}
 				else
 					{
-					outl (padapter->timingAddress, padapter->regDmaAddrLoc);
+					if ( (padapter->timingMode > 3) )
+						{
+						if ( padapter->bigD )
+							outl (BIGD_DATA_MODE3, padapter->regDmaAddrLoc);
+						else
+							outl (DALE_DATA_MODE3, padapter->regDmaAddrLoc);
+						}
+					else
+						outl (padapter->timingAddress, padapter->regDmaAddrLoc);
 					outl (virt_to_bus (padapter->kBuffer), padapter->regDmaAddrPci);
 					outl (padapter->reconSize * BYTES_PER_SECTOR, padapter->regDmaCount);
 					outb_p (8, padapter->regDmaDesc);						// read operation
-					outb_p (1, padapter->regDmaMode);						// no interrupt
+					if ( padapter->bigD )
+						outb_p (8, padapter->regDmaMode);					// no interrupt
+					else
+						outb_p (1, padapter->regDmaMode);					// no interrupt
 					outb_p (0x03, padapter->regDmaCmdStat);					// kick the DMA engine in gear
 					}
 				goto irq_return;
@@ -1315,13 +1856,14 @@
 				pdev->DiskMirror[pdev->mirrorRecon].reconstructPoint += padapter->reconSize;
 
 			case RECON_PHASE_UPDATE:
-				SelectSpigot (padapter, pdev->hotRecon | 0x80);
+				SelectSpigot (padapter, pdev->spigots[pdev->mirrorRecon] | SEL_IRQ_OFF);
 				status = inb_p (padapter->regStatCmd);						// read the device status
 				del_timer (&padapter->timer);
 				if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
 					{
-					padapter->survivor = (pdev->spigot) >> 1;
+					padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
 					DEB (printk ("\npci2220i: FAILURE 13"));
+					DEB (printk ("\n  status register = %X   error = %X", status, inb_p (padapter->regError)));
 					if ( InitFailover (padapter, pdev) )
 						OpDone (padapter, DecodeError (padapter, status));
 					goto irq_return;
@@ -1334,14 +1876,29 @@
 				del_timer (&padapter->timer);
 				if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
 					{
-					padapter->survivor = (pdev->spigot) >> 1;
-				DEB (printk ("\npci2220i: FAILURE 14"));
+					padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
+					DEB (printk ("\npci2220i: FAILURE 14"));
 					if ( InitFailover (padapter, pdev) )
 						OpDone (padapter, DecodeError (padapter, status));
 					goto irq_return;
 					}
-				padapter->reconOn = FALSE;
-				pdev->hotRecon = 0;
+				pdev->reconOn = 0;
+				if ( padapter->bigD )
+					{
+					for ( z = 0;  z < padapter->numberOfDrives;  z++ )
+						{
+						if ( padapter->device[z].DiskMirror[0].status & UCBF_SURVIVOR )
+							{
+							Alarm (padapter, padapter->device[z].deviceID[0] ^ 2);
+							MuteAlarm (padapter);
+							}
+						if ( padapter->device[z].DiskMirror[1].status & UCBF_SURVIVOR )
+							{
+							Alarm (padapter, padapter->device[z].deviceID[1] ^ 2);
+							MuteAlarm (padapter);
+							}
+						}
+					}
 				OpDone (padapter, DID_OK << 16);
 				goto irq_return;
 
@@ -1360,9 +1917,9 @@
 					{
 					if ( pdev->raid )
 						{
-						padapter->survivor = (pdev->spigot ^ 3) >> 1;
+						padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 1 : 0;
 						del_timer (&padapter->timer);
-				DEB (printk ("\npci2220i: FAILURE 15"));
+						DEB (printk ("\npci2220i: FAILURE 15"));
 						if ( !InitFailover (padapter, pdev) )
 							goto irq_return;
 						}
@@ -1370,10 +1927,9 @@
 					}
 				if ( padapter->timingPIO )
 					{
-					zl = (padapter->sectorCount > MAX_BUS_MASTER_BLOCKS) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount;
-					insw (padapter->regData, padapter->buffer, zl * (BYTES_PER_SECTOR / 2));
-					padapter->sectorCount -= zl;
-					padapter->buffer += zl * BYTES_PER_SECTOR;
+					insw (padapter->regData, padapter->kBuffer, padapter->readCount / 2);
+					padapter->sectorCount -= padapter->readCount / BYTES_PER_SECTOR;
+					WalkScatGath (padapter, TRUE, padapter->readCount);
 					if ( !padapter->sectorCount )
 						{
 						status = 0;
@@ -1381,32 +1937,40 @@
 						}
 					}
 				else
+					{
+					if ( padapter->readCount )
+						WalkScatGath (padapter, TRUE, padapter->readCount);
 					BusMaster (padapter, 1, 1);
+					}
 				padapter->expectingIRQ = TRUE;
 				goto irq_return;
 				}
+			if ( padapter->readCount && !padapter->timingPIO )
+				WalkScatGath (padapter, TRUE, padapter->readCount);
 			status = 0;
 			break;
 
 		case WRITE_CMD:
-			SelectSpigot (padapter, pdev->spigot | 0x80);				
-			status = inb_p (padapter->regStatCmd);								// read the device status
 			if ( pdev->raid )
 				{
-				SelectSpigot (padapter, (pdev->spigot ^ 3) | 0x80);				
-				status1 = inb_p (padapter->regStatCmd);							// read the device status
+				SelectSpigot (padapter, pdev->spigots[0] | SEL_IRQ_OFF);				
+				status = inb_p (padapter->regStatCmd);								// read the device status
+				SelectSpigot (padapter, pdev->spigots[1] | SEL_IRQ_OFF);				
+				status1 = inb_p (padapter->regStatCmd);								// read the device status
 				}
 			else
+				SelectSpigot (padapter, pdev->spigot | SEL_IRQ_OFF);				
+				status = inb_p (padapter->regStatCmd);								// read the device status
 				status1 = 0;
 		
 			if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
 				{	
 				if ( pdev->raid && !(status1 & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT)) )
 					{
-					padapter->survivor = (pdev->spigot ^ 3) >> 1;
+					padapter->survivor = 1;
 					del_timer (&padapter->timer);
-				SelectSpigot (padapter, pdev->spigot | 0x80);
-				DEB (printk ("\npci2220i: FAILURE 16  status = %X  error = %X", status, inb_p (padapter->regError)));
+					SelectSpigot (padapter, pdev->spigot | SEL_IRQ_OFF);
+					DEB (printk ("\npci2220i: FAILURE 16  status = %X  error = %X", status, inb_p (padapter->regError)));
 					if ( !InitFailover (padapter, pdev) )
 						goto irq_return;
 					}
@@ -1416,9 +1980,9 @@
 				{
 				if ( status1 & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
 					{	
-					padapter->survivor = pdev->spigot >> 1;
+					padapter->survivor = 0;
 					del_timer (&padapter->timer);
-				DEB (printk ("\npci2220i: FAILURE 17  status = %X  error = %X", status1, inb_p (padapter->regError)));
+					DEB (printk ("\npci2220i: FAILURE 17  status = %X  error = %X", status1, inb_p (padapter->regError)));
 					if ( !InitFailover (padapter, pdev) )
 						goto irq_return;
 					status = status1;
@@ -1426,15 +1990,15 @@
 					}
 				if ( padapter->sectorCount )
 					{
-					status = WriteDataBoth (padapter);
+					status = WriteDataBoth (padapter, pdev);
 					if ( status )
 						{
-						padapter->survivor = (status ^ 3) >> 1;
+						padapter->survivor = status >> 1;
 						del_timer (&padapter->timer);
-				DEB (printk ("\npci2220i: FAILURE 18"));
+						DEB (printk ("\npci2220i: FAILURE 18"));
 						if ( !InitFailover (padapter, pdev) )
 							goto irq_return;
-						SelectSpigot (padapter, status | 0x80);				
+						SelectSpigot (padapter, pdev->spigots[status] | SEL_IRQ_OFF);				
 						status = inb_p (padapter->regStatCmd);								// read the device status
 						break;
 						}
@@ -1446,7 +2010,7 @@
 				}
 			if ( padapter->sectorCount )	
 				{	
-				SelectSpigot (padapter, pdev->spigot);
+				SelectSpigot (padapter, pdev->spigot | padapter->bigD);
 				status = WriteData (padapter);
 				if ( status )
 					break;
@@ -1549,14 +2113,88 @@
 	PDEVICE_RAID1	pdr;
 
 	SCpnt->scsi_done = done;
-	padapter->buffer = SCpnt->request_buffer;
 	padapter->SCpnt = SCpnt;  									// Save this command data
+	padapter->readCount = 0;
+
+	if ( SCpnt->use_sg )
+		{
+		padapter->currentSgBuffer = ((struct scatterlist *)SCpnt->request_buffer)[0].address;
+		padapter->currentSgCount = ((struct scatterlist *)SCpnt->request_buffer)[0].length;
+		}
+	else
+		{
+		padapter->currentSgBuffer = SCpnt->request_buffer;
+		padapter->currentSgCount = SCpnt->request_bufflen;
+		}
+	padapter->nextSg = 1;
+
 	if ( !done )
 		{
 		printk("pci2220i_queuecommand: %02X: done can't be NULL\n", *cdb);
 		return 0;
 		}
 	
+	if ( padapter->atapi )
+		{
+		UCHAR			zlo, zhi;
+
+		DEB (printk ("\nPCI2242I: ID %d, LUN %d opcode %X ", SCpnt->target, SCpnt->lun, *cdb));
+		padapter->pdev = pdev;
+		if ( !pdev->byte6 || SCpnt->lun )
+			{
+			OpDone (padapter, DID_BAD_TARGET << 16);
+			return 0;
+			}
+	
+		padapter->atapiSpecial = FALSE;
+		padapter->reqSense = FALSE;
+		memset (padapter->atapiCdb, 0, 16);
+		SelectSpigot (padapter, pdev->spigot);									// select the spigot
+		AtapiDevice (padapter, pdev->byte6);									// select the drive
+		if ( AtapiWaitReady (padapter, 100) )
+			{
+			OpDone (padapter, DID_NO_CONNECT << 16);
+			return 0;
+			}
+
+		switch ( cdb[0] ) 
+			{
+			case SCSIOP_MODE_SENSE:
+			case SCSIOP_MODE_SELECT:
+				Scsi2Atapi (padapter, SCpnt);
+				z = SCpnt->request_bufflen + 4;
+				break;
+			case SCSIOP_READ6:
+			case SCSIOP_WRITE6:
+				Scsi2Atapi (padapter, SCpnt);
+				z = SCpnt->request_bufflen;
+				break;
+			default:
+				memcpy (padapter->atapiCdb, cdb, SCpnt->cmd_len);
+				z = SCpnt->request_bufflen;
+				break;
+			}
+		if ( z > ATAPI_TRANSFER )
+			z = ATAPI_TRANSFER;
+	    zlo = (UCHAR)(z & 0xFF);
+	    zhi = (UCHAR)(z >> 8);
+
+	 	AtapiCountLo (padapter, zlo);						
+	   	AtapiCountHi (padapter, zhi);						
+	   	outb_p (0, padapter->regError);						
+		WriteCommand (padapter, IDE_COMMAND_ATAPI_PACKET);
+		if ( pdev->cmdDrqInt )
+			return 0;
+
+		if ( AtapiWaitDrq (padapter, 500) )
+			{
+			OpDone (padapter, DID_ERROR << 16);
+			return 0;
+			}
+		AtapiSendCdb (padapter, pdev, padapter->atapiCdb);	
+		return 0;
+		}
+	
 	if ( padapter->reconPhase )
 		return 0;
 	if ( padapter->reconTimer.data )
@@ -1565,12 +2203,11 @@
 		padapter->reconTimer.data = 0;
 		}
 		
-	if ( !pdev->device || SCpnt->lun )
+	if ( (SCpnt->target >= padapter->numberOfDrives) || SCpnt->lun )
 		{
 		OpDone (padapter, DID_BAD_TARGET << 16);
 		return 0;
 		}
-
 	
 	switch ( *cdb )
 		{
@@ -1581,7 +2218,15 @@
 				switch ( cdb[3] ) 
 					{
 					case MY_SCSI_REBUILD:
-						padapter->reconOn = padapter->reconIsStarting = TRUE;
+						for ( z = 0;  z < padapter->numberOfDrives;  z++ )
+							{
+							pdev = &padapter->device[z];
+							if ( ((pdev->DiskMirror[0].status & UCBF_SURVIVOR) && (pdev->DiskMirror[1].status & UCBF_MIRRORED)) ||
+								 ((pdev->DiskMirror[1].status & UCBF_SURVIVOR) && (pdev->DiskMirror[0].status & UCBF_MIRRORED)) )
+								{
+								padapter->reconOn = pdev->reconOn = pdev->reconIsStarting = TRUE;
+								}
+							}
 						OpDone (padapter, DID_OK << 16);
 						break;
 					case MY_SCSI_ALARMMUTE:
@@ -1598,7 +2243,10 @@
 						if ( padapter->raidData[z] )
 							{
 							memcpy (&pdr->DiskRaid1, padapter->raidData[z], sizeof (DISK_MIRROR));
-							pdr->TotalSectors = padapter->device[0].blocks;
+							if ( padapter->raidData[z]->reconstructPoint > padapter->raidData[z ^ 2]->reconstructPoint )
+								pdr->TotalSectors = padapter->raidData[z]->reconstructPoint;
+							else
+								pdr->TotalSectors = padapter->raidData[z ^ 2]->reconstructPoint;
 							}
 						else
 							memset (pdr, 0, sizeof (DEVICE_RAID1));
@@ -1661,6 +2309,7 @@
 
 	while ( padapter->demoFail )
 		{
+		pdev = padapter->pdev = &padapter->device[0];
 		padapter->demoFail = FALSE;
 		if ( !pdev->raid || 
 			 (pdev->DiskMirror[0].status & UCBF_SURVIVOR) || 
@@ -1673,7 +2322,7 @@
 		else
 			padapter->survivor = 0;
 				DEB (printk ("\npci2220i: FAILURE 19"));
-		if ( InitFailover (padapter, pdev ) )
+		if ( InitFailover (padapter, pdev) )
 			break;
 		return 0;
 		}
@@ -1681,14 +2330,14 @@
 	StartTimer (padapter);
 	if ( pdev->raid && (padapter->cmd == WRITE_CMD) )
 		{
-		rc = IdeCmdBoth (padapter);
+		rc = IdeCmdBoth (padapter, pdev);
 		if ( !rc )
-			rc = WriteDataBoth (padapter);
+			rc = WriteDataBoth (padapter, pdev);
 		if ( rc )
 			{
 			del_timer (&padapter->timer);
 			padapter->expectingIRQ = 0;
-			padapter->survivor = (rc ^ 3) >> 1;
+			padapter->survivor = rc >> 1;
 				DEB (printk ("\npci2220i: FAILURE 20"));
 			if ( InitFailover (padapter, pdev) )
 				{
@@ -1719,7 +2368,6 @@
 		}
 	return 0;
 	}
-
 static void internal_done(Scsi_Cmnd *SCpnt)
 	{
 	SCpnt->SCp.Status++;
@@ -1755,25 +2403,192 @@
  *	Returns:		Nothing.
  *
  ****************************************************************/
-VOID ReadFlash (PADAPTER2220I padapter, VOID *pdata, ULONG base, ULONG length)
+static VOID ReadFlash (PADAPTER2220I padapter, VOID *pdata, ULONG base, ULONG length)
 	{
 	ULONG	 oldremap;
 	UCHAR	 olddesc;
 	ULONG	 z;
 	UCHAR	*pd = (UCHAR *)pdata;
 
-	oldremap = inl (padapter->regRemap);									// save values to restore later
+	oldremap = inl (padapter->regRemap);							// save values to restore later
 	olddesc  = inb_p (padapter->regDesc);
 
-	outl (base | 1, padapter->regRemap);									// remap to Flash space as specified
-	outb_p (0x40, padapter->regDesc);										// describe remap region as 8 bit
-	for ( z = 0;  z < length;  z++)											// get "length" data count
-		*pd++ = inb_p (padapter->regBase + z);								// read in the data
+	outl (base | 1, padapter->regRemap);							// remap to Flash space as specified
+	outb_p (0x40, padapter->regDesc);								// describe remap region as 8 bit
+	for ( z = 0;  z < length;  z++)									// get "length" data count
+		*pd++ = inb_p (padapter->regBase + z);						// read in the data
 
-	outl (oldremap, padapter->regRemap);									// restore remap register values
+	outl (oldremap, padapter->regRemap);							// restore remap register values
 	outb_p (olddesc, padapter->regDesc);
 	}
 /****************************************************************
+ *	Name:			GetRegs
+ *
+ *	Description:	Initialize the regester information.
+ *
+ *	Parameters:		pshost		  - Pointer to SCSI host data structure.
+ *					bigd		  - PCI-2240I identifier
+ *					pcidev		  - Pointer to device data structure.
+ *					pci_bus		  - PCI bus number.
+ *					pci_device_fn - PCI device and function number.
+ *
+ *	Returns:		TRUE if failure to install.
+ *
+ ****************************************************************/
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+static USHORT GetRegs (struct Scsi_Host *pshost, BOOL bigd, struct pci_dev *pcidev)
+#else
+static USHORT GetRegs (struct Scsi_Host *pshost, BOOL bigd, UCHAR pci_bus, UCHAR pci_device_fn)
+#endif
+	{
+	PADAPTER2220I	padapter;
+	int				setirq;
+	int				z;
+	USHORT			zr, zl;
+
+	padapter = HOSTDATA(pshost);
+	memset (padapter, 0, sizeof (ADAPTER2220I));
+	memset (&DaleSetup, 0, sizeof (DaleSetup));
+	memset (DiskMirror, 0, sizeof (DiskMirror));
+
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+	zr = pcidev->base_address[1] & 0xFFFE;
+	zl = pcidev->base_address[2] & 0xFFFE;
+#else
+	pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &zr);
+	zr &= 0xFFFE;
+	pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_2, &zl);
+	zl &= 0xFFFE;
+#endif
+	padapter->basePort = zr;
+	padapter->regRemap		= zr + RTR_LOCAL_REMAP;					// 32 bit local space remap
+	padapter->regDesc		= zr + RTR_REGIONS;	  					// 32 bit local region descriptor
+	padapter->regRange		= zr + RTR_LOCAL_RANGE;					// 32 bit local range
+	padapter->regIrqControl	= zr + RTR_INT_CONTROL_STATUS;			// 16 bit interupt control and status
+	padapter->regScratchPad	= zr + RTR_MAILBOX;	  					// 16 byte scratchpad I/O base address
+
+	padapter->regBase		= zl;
+	padapter->regData		= zl + REG_DATA;						// data register I/O address
+	padapter->regError		= zl + REG_ERROR;						// error register I/O address
+	padapter->regSectCount	= zl + REG_SECTOR_COUNT;				// sector count register I/O address
+	padapter->regLba0		= zl + REG_LBA_0;						// least significant byte of LBA
+	padapter->regLba8		= zl + REG_LBA_8;						// next least significant byte of LBA
+	padapter->regLba16		= zl + REG_LBA_16;						// next most significan byte of LBA
+	padapter->regLba24		= zl + REG_LBA_24;						// head and most 4 significant bits of LBA
+	padapter->regStatCmd	= zl + REG_STAT_CMD;					// status on read and command on write register
+	padapter->regStatSel	= zl + REG_STAT_SEL;					// board status on read and spigot select on write register
+	padapter->regFail		= zl + REG_FAIL;
+	padapter->regAltStat	= zl + REG_ALT_STAT;
+
+	if ( bigd )
+		{
+		padapter->regDmaDesc	= zr + RTR_DMA0_DESC_PTR;			// address of the DMA discriptor register for direction of transfer
+		padapter->regDmaCmdStat	= zr + RTR_DMA_COMMAND_STATUS;		// Byte #0 of DMA command status register
+		padapter->regDmaAddrPci	= zr + RTR_DMA0_PCI_ADDR;			// 32 bit register for PCI address of DMA
+		padapter->regDmaAddrLoc	= zr + RTR_DMA0_LOCAL_ADDR;			// 32 bit register for local bus address of DMA
+		padapter->regDmaCount	= zr + RTR_DMA0_COUNT;				// 32 bit register for DMA transfer count
+		padapter->regDmaMode	= zr + RTR_DMA0_MODE + 1;			// 32 bit register for DMA mode control
+		padapter->bigD			= SEL_NEW_SPEED_1;					// set spigot speed control bit
+		}
+	else
+		{
+		padapter->regDmaDesc	= zl + RTL_DMA1_DESC_PTR;			// address of the DMA discriptor register for direction of transfer
+		padapter->regDmaCmdStat	= zl + RTL_DMA_COMMAND_STATUS + 1;	// Byte #1 of DMA command status register
+		padapter->regDmaAddrPci	= zl + RTL_DMA1_PCI_ADDR;			// 32 bit register for PCI address of DMA
+		padapter->regDmaAddrLoc	= zl + RTL_DMA1_LOCAL_ADDR;			// 32 bit register for local bus address of DMA
+		padapter->regDmaCount	= zl + RTL_DMA1_COUNT;				// 32 bit register for DMA transfer count
+		padapter->regDmaMode	= zl + RTL_DMA1_MODE + 1;			// 32 bit register for DMA mode control
+		}
+
+	padapter->numberOfDrives = inb_p (padapter->regScratchPad + BIGD_NUM_DRIVES);
+	if ( !bigd && !padapter->numberOfDrives )						// if no devices on this board
+		return TRUE;
+
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+	pshost->irq = pcidev->irq;
+#else
+	pcibios_read_config_byte (pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pshost->irq);
+#endif
+	setirq = 1;
+	for ( z = 0;  z < Installed;  z++ )								// scan for shared interrupts
+		{
+		if ( PsiHost[z]->irq == pshost->irq )						// if shared then, don't posses
+			setirq = 0;
+		}
+	if ( setirq )													// if not shared, posses
+		{
+		if ( request_irq (pshost->irq, Irq_Handler, SA_SHIRQ, "pci2220i", padapter) < 0 )
+			{
+			if ( request_irq (pshost->irq, Irq_Handler, SA_INTERRUPT | SA_SHIRQ, "pci2220i", padapter) < 0 )
+				{
+				printk ("Unable to allocate IRQ for PCI-2220I controller.\n");
+				return TRUE;
+				}
+			}
+		padapter->irqOwned = pshost->irq;							// set IRQ as owned
+		}
+	if ( padapter->numberOfDrives )
+		padapter->kBuffer = kmalloc (SECTORSXFER * BYTES_PER_SECTOR, GFP_DMA | GFP_ATOMIC);
+	else
+		padapter->kBuffer = kmalloc (ATAPI_TRANSFER, GFP_DMA | GFP_ATOMIC);
+	if ( !padapter->kBuffer )
+		{
+		printk ("Unable to allocate DMA buffer for PCI-2220I controller.\n");
+#if LINUX_VERSION_CODE < LINUXVERSION(1,3,70)
+		free_irq (pshost->irq);
+#else /* version >= v1.3.70 */
+		free_irq (pshost->irq, padapter);
+#endif /* version >= v1.3.70 */
+		return TRUE;
+		}
+
+	PsiHost[Installed]	= pshost;									// save SCSI_HOST pointer
+
+	pshost->io_port		= padapter->basePort;
+	pshost->n_io_port	= 0xFF;
+	pshost->unique_id	= padapter->regBase;
+
+	outb_p (0x01, padapter->regRange);								// fix our range register because other drivers want to tromp on it
+
+	padapter->timingMode = inb_p (padapter->regScratchPad + DALE_TIMING_MODE);
+	if ( padapter->timingMode >= 2 )
+		{
+		if ( bigd )
+			padapter->timingAddress	= ModeArray2[padapter->timingMode - 2];
+		else
+			padapter->timingAddress	= ModeArray[padapter->timingMode - 2];
+		}
+	else
+		padapter->timingPIO = TRUE;
+
+	ReadFlash (padapter, &DaleSetup, DALE_FLASH_SETUP, sizeof (SETUP));
+	ReadFlash (padapter, &DiskMirror, DALE_FLASH_RAID, sizeof (DiskMirror));
+
+	return FALSE;
+	}
+/****************************************************************
+ *	Name:			SetupFinish
+ *
+ *	Description:	Complete the driver initialization process for a card
+ *
+ *	Parameters:		padapter  - Pointer to SCSI host data structure.
+ *					str		  - Pointer to board type string.
+ *
+ *	Returns:		Nothing.
+ *
+ ****************************************************************/
+VOID SetupFinish (PADAPTER2220I padapter, char *str, int irq)
+	{
+	init_timer (&padapter->timer);
+	padapter->timer.function = TimerExpiry;
+	padapter->timer.data = (unsigned long)padapter;
+	init_timer (&padapter->reconTimer);
+	padapter->reconTimer.function = ReconTimerExpiry;
+	padapter->reconTimer.data = (unsigned long)padapter;
+	printk("\nPCI-%sI EIDE CONTROLLER: at I/O = %X/%X  IRQ = %d\n", str, padapter->basePort, padapter->regBase, irq);
+	printk("Version %s, Compiled %s %s\n\n", PCI2220I_VERSION, __DATE__, __TIME__);
+	}	
+/****************************************************************
  *	Name:	Pci2220i_Detect
  *
  *	Description:	Detect and initialize our boards.
@@ -1785,20 +2600,18 @@
  ****************************************************************/
 int Pci2220i_Detect (Scsi_Host_Template *tpnt)
 	{
-	int					found = 0;
-	int					installed = 0;
 	struct Scsi_Host   *pshost;
 	PADAPTER2220I	    padapter;
+	POUR_DEVICE			pdev;
 	int					unit;
 	int					z;
-	USHORT				zs;
-	USHORT				raidon = FALSE;
-	int					setirq;
-	UCHAR				spigot1 = FALSE;
-	UCHAR				spigot2 = FALSE;
+	USHORT				raidon;
+	UCHAR				spigot1, spigot2;
+	UCHAR				device;
 #if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
-	struct pci_dev	   *pdev = NULL;
+	struct pci_dev	   *pcidev = NULL;
 #else
+	int					found;
 	UCHAR				pci_bus, pci_device_fn;
 #endif
 
@@ -1813,206 +2626,258 @@
 		}
 
 #if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
-	while ( (pdev = pci_find_device (VENDOR_PSI, DEVICE_DALE_1, pdev)) != NULL )
+	while ( (pcidev = pci_find_device (VENDOR_PSI, DEVICE_DALE_1, pcidev)) != NULL )
 #else
-	while ( !pcibios_find_device (VENDOR_PSI, DEVICE_DALE_1, found, &pci_bus, &pci_device_fn) )
+	found = 0;
+	while ( !pcibios_find_device (VENDOR_PSI, DEVICE_DALE_1, found++, &pci_bus, &pci_device_fn) )
 #endif
 		{
 		pshost = scsi_register (tpnt, sizeof(ADAPTER2220I));
 		padapter = HOSTDATA(pshost);
-		memset (padapter, 0, sizeof (ADAPTER2220I));
-
-#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
-		zs = pdev->base_address[1] & 0xFFFE;
-#else
-		pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &zs);
-		zs &= 0xFFFE;
-#endif
-		padapter->basePort = zs;
-		padapter->regRemap		= zs + RTR_LOCAL_REMAP;				// 32 bit local space remap
-		padapter->regDesc		= zs + RTR_REGIONS;	  				// 32 bit local region descriptor
-		padapter->regRange		= zs + RTR_LOCAL_RANGE;				// 32 bit local range
-		padapter->regIrqControl	= zs + RTR_INT_CONTROL_STATUS;		// 16 bit interupt control and status
-		padapter->regScratchPad	= zs + RTR_MAILBOX;	  				// 16 byte scratchpad I/O base address
 
 #if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
-		zs = pdev->base_address[2] & 0xFFFE;
+		if ( GetRegs (pshost, FALSE, pcidev) )
 #else
-		pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_2, &zs);
-		zs &= 0xFFFE;
+		if ( GetRegs (pshost, FALSE, pci_bus, pci_device_fn) )
 #endif
-		padapter->regBase		= zs;
-		padapter->regData		= zs + REG_DATA;					// data register I/O address
-		padapter->regError		= zs + REG_ERROR;					// error register I/O address
-		padapter->regSectCount	= zs + REG_SECTOR_COUNT;			// sector count register I/O address
-		padapter->regLba0		= zs + REG_LBA_0;					// least significant byte of LBA
-		padapter->regLba8		= zs + REG_LBA_8;					// next least significant byte of LBA
-		padapter->regLba16		= zs + REG_LBA_16;					// next most significan byte of LBA
-		padapter->regLba24		= zs + REG_LBA_24;					// head and most 4 significant bits of LBA
-		padapter->regStatCmd	= zs + REG_STAT_CMD;				// status on read and command on write register
-		padapter->regStatSel	= zs + REG_STAT_SEL;				// board status on read and spigot select on write register
-		padapter->regFail		= zs + REG_FAIL;
-		padapter->regAltStat	= zs + REG_ALT_STAT;
-
-		padapter->regDmaDesc	= zs + RTL_DMA1_DESC_PTR;			// address of the DMA discriptor register for direction of transfer
-		padapter->regDmaCmdStat	= zs + RTL_DMA_COMMAND_STATUS + 1;	// Byte #1 of DMA command status register
-		padapter->regDmaAddrPci	= zs + RTL_DMA1_PCI_ADDR;			// 32 bit register for PCI address of DMA
-		padapter->regDmaAddrLoc	= zs + RTL_DMA1_LOCAL_ADDR;			// 32 bit register for local bus address of DMA
-		padapter->regDmaCount	= zs + RTL_DMA1_COUNT;				// 32 bit register for DMA transfer count
-		padapter->regDmaMode	= zs + RTL_DMA1_MODE + 1;			// 32 bit register for DMA mode control
-
-		if ( !inb_p (padapter->regScratchPad + DALE_NUM_DRIVES) )	// if no devices on this board
 			goto unregister;
 
-#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
-		pshost->irq = pdev->irq;
-#else
-		pcibios_read_config_byte (pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pshost->irq);
-#endif
-		setirq = 1;
-		for ( z = 0;  z < installed;  z++ )							// scan for shared interrupts
-			{
-			if ( PsiHost[z]->irq == pshost->irq )					// if shared then, don't posses
-				setirq = 0;
-			}
-		if ( setirq )												// if not shared, posses
-			{
-			if ( request_irq (pshost->irq, Irq_Handler, SA_SHIRQ, "pci2220i", padapter) < 0 )
-				{
-				if ( request_irq (pshost->irq, Irq_Handler, SA_INTERRUPT | SA_SHIRQ, "pci2220i", padapter) < 0 )
-					{
-					printk ("Unable to allocate IRQ for PCI-2220I controller.\n");
-					goto unregister;
-					}
-				}
-			padapter->irqOwned = pshost->irq;						// set IRQ as owned
-			}
-		padapter->kBuffer = kmalloc (SECTORSXFER * BYTES_PER_SECTOR, GFP_DMA | GFP_ATOMIC);
-		if ( !padapter->kBuffer )
-			{
-			printk ("Unable to allocate DMA buffer for PCI-2220I controller.\n");
-#if LINUX_VERSION_CODE < LINUXVERSION(1,3,70)
-			free_irq (pshost->irq);
-#else /* version >= v1.3.70 */
-			free_irq (pshost->irq, padapter);
-#endif /* version >= v1.3.70 */
-			goto unregister;
-			}
-		PsiHost[installed]	= pshost;								// save SCSI_HOST pointer
-
-		pshost->io_port		= padapter->basePort;
-		pshost->n_io_port	= 0xFF;
-		pshost->unique_id	= padapter->regBase;
-		pshost->max_id		= 4;
-
-		outb_p (0x01, padapter->regRange);							// fix our range register because other drivers want to tromp on it
-
-		padapter->timingMode = inb_p (padapter->regScratchPad + DALE_TIMING_MODE);
-		if ( padapter->timingMode >= 2 )
-			padapter->timingAddress	= ModeArray[padapter->timingMode - 2];
-		else
-			padapter->timingPIO = TRUE;
-			
-		ReadFlash (padapter, &DaleSetup, DALE_FLASH_SETUP, sizeof (SETUP));
-		for ( z = 0;  z < inb_p (padapter->regScratchPad + DALE_NUM_DRIVES);  ++z )
+		pshost->max_id = padapter->numberOfDrives;
+		for ( z = 0;  z < padapter->numberOfDrives;  z++ )
 			{
 			unit = inb_p (padapter->regScratchPad + DALE_CHANNEL_DEVICE_0 + z) & 0x0F;
-			padapter->device[z].device	 = inb_p (padapter->regScratchPad + DALE_SCRATH_DEVICE_0 + unit);
-			padapter->device[z].byte6	 = (UCHAR)(((unit & 1) << 4) | 0xE0);
-			padapter->device[z].spigot	 = (UCHAR)(1 << (unit >> 1));
-			padapter->device[z].sectors	 = DaleSetup.setupDevice[unit].sectors;
-			padapter->device[z].heads	 = DaleSetup.setupDevice[unit].heads;
-			padapter->device[z].cylinders = DaleSetup.setupDevice[unit].cylinders;
-			padapter->device[z].blocks	 = DaleSetup.setupDevice[unit].blocks;
+			pdev = &padapter->device[z];
+			pdev->byte6		= (UCHAR)(((unit & 1) << 4) | 0xE0);
+			pdev->spigot	= (UCHAR)(1 << (unit >> 1));
+			pdev->sectors	= DaleSetup.setupDevice[unit].sectors;
+			pdev->heads		= DaleSetup.setupDevice[unit].heads;
+			pdev->cylinders = DaleSetup.setupDevice[unit].cylinders;
+			pdev->blocks	= DaleSetup.setupDevice[unit].blocks;
 
 			if ( !z )
 				{
-				ReadFlash (padapter, &DiskMirror, DALE_FLASH_RAID, sizeof (DiskMirror));
 				DiskMirror[0].status = inb_p (padapter->regScratchPad + DALE_RAID_0_STATUS);		
 				DiskMirror[1].status = inb_p (padapter->regScratchPad + DALE_RAID_1_STATUS);		
 				if ( (DiskMirror[0].signature == SIGNATURE) && (DiskMirror[1].signature == SIGNATURE) &&
 				     (DiskMirror[0].pairIdentifier == (DiskMirror[1].pairIdentifier ^ 1)) )
 					{			 
 					raidon = TRUE;
+					if ( unit > (unit ^ 2) )
+						unit = unit ^ 2;
 					}	
+				else
+					raidon = FALSE;
 
-				memcpy (padapter->device[z].DiskMirror, DiskMirror, sizeof (DiskMirror));
-				padapter->raidData[0] = &padapter->device[z].DiskMirror[0];
-				padapter->raidData[2] = &padapter->device[z].DiskMirror[1];
+				memcpy (pdev->DiskMirror, DiskMirror, sizeof (DiskMirror));
+				padapter->raidData[0] = &pdev->DiskMirror[0];
+				padapter->raidData[2] = &pdev->DiskMirror[1];
 				
-				if ( raidon )
-					{
-					padapter->device[z].lastsectorlba[0] = InlineIdentify (padapter, 1, 0);
-					padapter->device[z].lastsectorlba[1] = InlineIdentify (padapter, 2, 0);
+				spigot1 = spigot2 = FALSE;
+				pdev->spigots[0] = 1;
+				pdev->spigots[1] = 2;
+				pdev->lastsectorlba[0] = InlineIdentify (padapter, 1, 0);
+				pdev->lastsectorlba[1] = InlineIdentify (padapter, 2, 0);
 						
-					if ( !(DiskMirror[1].status & UCBF_SURVIVOR) && padapter->device[z].lastsectorlba[0] )
-						spigot1 = TRUE;
-					if ( !(DiskMirror[0].status & UCBF_SURVIVOR) && padapter->device[z].lastsectorlba[1] )
-						spigot2 = TRUE;
-					if ( DiskMirror[0].status & UCBF_SURVIVOR & DiskMirror[1].status & UCBF_SURVIVOR )
-						spigot1 = TRUE;
-
-					if ( spigot1 && (DiskMirror[0].status & UCBF_REBUILD) )
-						InlineReadSignature (padapter, &padapter->device[z], 0);
-					if ( spigot2 && (DiskMirror[1].status & UCBF_REBUILD) )
-						InlineReadSignature (padapter, &padapter->device[z], 1);
-
-					if ( spigot1 && spigot2 )
+				if ( !(pdev->DiskMirror[1].status & UCBF_SURVIVOR) && pdev->lastsectorlba[0] )
+					spigot1 = TRUE;
+				if ( !(pdev->DiskMirror[0].status & UCBF_SURVIVOR) && pdev->lastsectorlba[1] )
+					spigot2 = TRUE;
+				if ( pdev->DiskMirror[0].status & DiskMirror[1].status & UCBF_SURVIVOR )
+					spigot1 = TRUE;
+
+				if ( spigot1 && (pdev->DiskMirror[0].status & UCBF_REBUILD) )
+					InlineReadSignature (padapter, pdev, 0);
+				if ( spigot2 && (pdev->DiskMirror[1].status & UCBF_REBUILD) )
+					InlineReadSignature (padapter, pdev, 1);
+
+				if ( spigot1 && spigot2 && raidon )
+					{
+					pdev->raid = 1;
+					if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
+						pdev->spigot = 2;
+					else
+						pdev->spigot = 1;
+					if ( (pdev->DiskMirror[0].status & UCBF_REBUILD) || (pdev->DiskMirror[1].status & UCBF_REBUILD) )
+						padapter->reconOn = pdev->reconOn = pdev->reconIsStarting = TRUE;
+					}
+				else
+					{
+					if ( spigot1 )
 						{
-						padapter->device[z].raid = 1;
-						if ( DiskMirror[0].status & UCBF_REBUILD )
-							padapter->device[z].spigot = 2;
-						else
-							padapter->device[z].spigot = 1;
-						if ( (DiskMirror[0].status & UCBF_REBUILD) || (DiskMirror[1].status & UCBF_REBUILD) )
-							{
-							padapter->reconOn = padapter->reconIsStarting = TRUE;
-							}
+						if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
+							goto unregister;
+						pdev->DiskMirror[0].status = UCBF_MIRRORED | UCBF_SURVIVOR;
+						pdev->spigot = 1;
 						}
 					else
 						{
-						if ( spigot1 )
-							{
-							if ( DiskMirror[0].status & UCBF_REBUILD )
-								goto unregister;
-							DiskMirror[0].status = UCBF_MIRRORED | UCBF_SURVIVOR;
-							padapter->device[z].spigot = 1;
-							}
-						else
+						if ( pdev->DiskMirror[1].status & UCBF_REBUILD )
+							goto unregister;
+						pdev->DiskMirror[1].status = UCBF_MIRRORED | UCBF_SURVIVOR;
+						pdev->spigot = 2;
+						}
+					if ( DaleSetup.rebootRebuild && raidon )
+						padapter->reconOn = pdev->reconOn = pdev->reconIsStarting = TRUE;
+					}
+			
+				if ( raidon )
+					break;
+				}
+			}
+
+		SetupFinish (padapter, "2220", pshost->irq);
+	
+		if ( ++Installed < MAXADAPTER )
+			continue;
+		break;;
+unregister:;
+		scsi_unregister (pshost);
+		}
+
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+	while ( (pcidev = pci_find_device (VENDOR_PSI, DEVICE_BIGD_1, pcidev)) != NULL )
+#else
+	found = 0;
+	while ( !pcibios_find_device (VENDOR_PSI, DEVICE_BIGD_1, found++, &pci_bus, &pci_device_fn) )
+#endif
+		{
+		pshost = scsi_register (tpnt, sizeof(ADAPTER2220I));
+		padapter = HOSTDATA(pshost);
+
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+		if ( GetRegs (pshost, TRUE, pcidev) )
+#else
+		if ( GetRegs (pshost, TRUE, pci_bus, pci_device_fn) )
+#endif
+			goto unregister1;
+
+		for ( z = 0;  z < BIGD_MAXDRIVES;  z++ )
+			DiskMirror[z].status = inb_p (padapter->regScratchPad + BIGD_RAID_0_STATUS + z);		
+
+		pshost->max_id = padapter->numberOfDrives;
+		padapter->failRegister = inb_p (padapter->regScratchPad + BIGD_ALARM_IMAGE);
+		for ( z = 0;  z < padapter->numberOfDrives;  z++ )
+			{
+			unit = inb_p (padapter->regScratchPad + BIGD_DEVICE_0 + z);
+			pdev = &padapter->device[z];
+			pdev->byte6		= (UCHAR)(((unit & 1) << 4) | 0xE0);
+			pdev->spigot	= (UCHAR)(1 << (unit >> 1));
+			pdev->sectors	= DaleSetup.setupDevice[unit].sectors;
+			pdev->heads		= DaleSetup.setupDevice[unit].heads;
+			pdev->cylinders = DaleSetup.setupDevice[unit].cylinders;
+			pdev->blocks	= DaleSetup.setupDevice[unit].blocks;
+			
+			if ( (DiskMirror[unit].signature == SIGNATURE) && (DiskMirror[unit ^ 2].signature == SIGNATURE) &&
+			     (DiskMirror[unit].pairIdentifier == (DiskMirror[unit ^ 2].pairIdentifier ^ 1)) )
+				{			 
+				raidon = TRUE;
+				if ( unit > (unit ^ 2) )
+					unit = unit ^ 2;
+				}	
+			else
+				raidon = FALSE;
+				
+			spigot1 = spigot2 = FALSE;
+			memcpy (&pdev->DiskMirror[0], &DiskMirror[unit], sizeof (DISK_MIRROR));
+			memcpy (&pdev->DiskMirror[1], &DiskMirror[unit ^ 2], sizeof (DISK_MIRROR));
+			padapter->raidData[unit]	 = &pdev->DiskMirror[0];
+			padapter->raidData[unit ^ 2] = &pdev->DiskMirror[1];
+			pdev->spigots[0] = 1 << (unit >> 1);
+			pdev->spigots[1] = 1 << ((unit ^ 2) >> 1);
+			pdev->deviceID[0] = unit;
+			pdev->deviceID[1] = unit ^ 2;
+			pdev->lastsectorlba[0] = InlineIdentify (padapter, pdev->spigots[0], unit & 1);
+			pdev->lastsectorlba[1] = InlineIdentify (padapter, pdev->spigots[1], unit & 1);
+
+			if ( !(pdev->DiskMirror[1].status & UCBF_SURVIVOR) && pdev->lastsectorlba[0] )
+				spigot1 = TRUE;
+			if ( !(pdev->DiskMirror[0].status & UCBF_SURVIVOR) && pdev->lastsectorlba[1] )
+				spigot2 = TRUE;
+			if ( pdev->DiskMirror[0].status & pdev->DiskMirror[1].status & UCBF_SURVIVOR )
+				spigot1 = TRUE;
+
+			if ( spigot1 && (pdev->DiskMirror[0].status & UCBF_REBUILD) )
+				InlineReadSignature (padapter, pdev, 0);
+			if ( spigot2 && (pdev->DiskMirror[1].status & UCBF_REBUILD) )
+				InlineReadSignature (padapter, pdev, 1);
+
+			if ( spigot1 && spigot2 && raidon )
+				{
+				pdev->raid = 1;
+				if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
+					pdev->spigot = pdev->spigots[1];
+				else
+					pdev->spigot = pdev->spigots[0];
+				if ( (pdev->DiskMirror[0].status & UCBF_REBUILD) || (pdev->DiskMirror[1].status & UCBF_REBUILD) )
+					padapter->reconOn = pdev->reconOn = pdev->reconIsStarting = TRUE;
+				}
+			else
+				{
+				if ( spigot1 )
+					{
+					if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
+						goto unregister1;
+					pdev->DiskMirror[0].status = UCBF_MIRRORED | UCBF_SURVIVOR;
+					pdev->spigot = pdev->spigots[0];
+					}
+				else
+					{
+					if ( pdev->DiskMirror[1].status & UCBF_REBUILD )
+						goto unregister;
+					pdev->DiskMirror[1].status = UCBF_MIRRORED | UCBF_SURVIVOR;
+					pdev->spigot = pdev->spigots[1];
+					}
+				if ( DaleSetup.rebootRebuild && raidon )
+					padapter->reconOn = pdev->reconOn = pdev->reconIsStarting = TRUE;
+				}
+			}
+		
+		if ( !padapter->numberOfDrives )									// If no ATA devices then scan ATAPI
+			{
+			unit = 0;
+			for ( spigot1 = 0;  spigot1 < 4;  spigot1++ )
+				{
+				for ( device = 0;  device < 2;  device++ )
+					{
+					DEB (printk ("\nPCI2242I: scanning for ID %d ", (spigot1 * 2) + device));
+					pdev = &(padapter->device[(spigot1 * 2) + device]);
+					pdev->byte6 = 0x0A | (device << 4);
+					pdev->spigot = 1 << spigot1;
+					if ( !AtapiReset (padapter, pdev) )
+						{
+						DEB (printk (" Device found "));
+						if ( !AtapiIdentify (padapter, pdev) )
 							{
-							if ( DiskMirror[1].status & UCBF_REBUILD )
-								goto unregister;
-							DiskMirror[1].status = UCBF_MIRRORED | UCBF_SURVIVOR;
-							padapter->device[z].spigot = 2;
+							DEB (printk (" Device verified"));
+							unit++;
+							continue;
 							}
-						if ( DaleSetup.rebootRebuil )
-							padapter->reconOn = padapter->reconIsStarting = TRUE;
 						}
-				
-					break;
+					pdev->spigot = pdev->byte6 = 0;
 					}
 				}
+
+			if ( unit )
+				{
+				padapter->atapi = TRUE;
+				padapter->timingAddress = DALE_DATA_MODE3;
+				outw_p (0x0900, padapter->regIrqControl);					// Turn our interrupts on
+				outw_p (0x0C41, padapter->regDmaMode - 1);					// setup for 16 bits, ready enabled, done IRQ enabled, no incriment
+				outb_p (0xFF, padapter->regFail);							// all fail lights and alarm off
+				pshost->max_id = 8;
+				}
 			}
-			
-		init_timer (&padapter->timer);
-		padapter->timer.function = TimerExpiry;
-		padapter->timer.data = (unsigned long)padapter;
-		init_timer (&padapter->reconTimer);
-		padapter->reconTimer.function = ReconTimerExpiry;
-		padapter->reconTimer.data = (unsigned long)padapter;
-		printk("\nPCI-2220I EIDE CONTROLLER: at I/O = %X/%X  IRQ = %d\n", padapter->basePort, padapter->regBase, pshost->irq);
-		printk("Version %s, Compiled %s %s\n\n", PCI2220I_VERSION, __DATE__, __TIME__);
-		found++;
-		if ( ++installed < MAXADAPTER )
+		SetupFinish (padapter, "2240", pshost->irq);
+		
+		if ( ++Installed < MAXADAPTER )
 			continue;
 		break;;
-unregister:;
+unregister1:;
 		scsi_unregister (pshost);
-		found++;
 		}
-	
-	NumAdapters = installed;
-	return installed;
+
+	NumAdapters = Installed;
+	return Installed;
 	}
 /****************************************************************
  *	Name:	Pci2220i_Abort
@@ -2026,6 +2891,19 @@
  ****************************************************************/
 int Pci2220i_Abort (Scsi_Cmnd *SCpnt)
 	{
+	PADAPTER2220I	padapter = HOSTDATA(SCpnt->host);			// Pointer to adapter control structure
+	POUR_DEVICE		pdev	 = &padapter->device[SCpnt->target];// Pointer to device information
+
+	if ( !padapter->SCpnt )
+		return SCSI_ABORT_NOT_RUNNING;
+	
+	if ( padapter->atapi )
+		{
+		if ( AtapiReset (padapter, pdev) )
+			return SCSI_ABORT_ERROR;
+		OpDone (padapter, DID_ABORT << 16);
+		return SCSI_ABORT_SUCCESS;
+		}
 	return SCSI_ABORT_SNOOZE;
 	}
 /****************************************************************
@@ -2045,6 +2923,15 @@
  ****************************************************************/
 int Pci2220i_Reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags)
 	{
+	PADAPTER2220I	padapter = HOSTDATA(SCpnt->host);			// Pointer to adapter control structure
+	POUR_DEVICE		pdev	 = &padapter->device[SCpnt->target];// Pointer to device information
+
+	if ( padapter->atapi )
+		{
+		if ( AtapiReset (padapter, pdev) )
+			return SCSI_RESET_ERROR;
+		return SCSI_RESET_SUCCESS;
+		}
 	return SCSI_RESET_PUNT;
 	}
 /****************************************************************
@@ -2060,6 +2947,7 @@
 int Pci2220i_Release (struct Scsi_Host *pshost)
 	{
     PADAPTER2220I	padapter = HOSTDATA (pshost);
+	USHORT			z;
 
 	if ( padapter->reconOn )
 		{
@@ -2074,8 +2962,22 @@
 		}
 
 	// save RAID status on the board
-	outb_p (DiskMirror[0].status, padapter->regScratchPad + DALE_RAID_0_STATUS);		
-	outb_p (DiskMirror[1].status, padapter->regScratchPad + DALE_RAID_1_STATUS);		
+	if ( padapter->bigD )
+		{
+		outb_p (padapter->failRegister, padapter->regScratchPad + BIGD_ALARM_IMAGE);
+		for ( z = 0;  z < BIGD_MAXDRIVES;  z++ )
+			{
+			if ( padapter->raidData )
+				outb_p (padapter->raidData[z]->status, padapter->regScratchPad + BIGD_RAID_0_STATUS + z);	
+			else
+				outb_p (0, padapter->regScratchPad + BIGD_RAID_0_STATUS);	
+			}
+		}
+	else
+		{
+		outb_p (padapter->device[0].DiskMirror[0].status, padapter->regScratchPad + DALE_RAID_0_STATUS);		
+		outb_p (padapter->device[0].DiskMirror[1].status, padapter->regScratchPad + DALE_RAID_1_STATUS);		
+		}
 
 	if ( padapter->irqOwned )
 #if LINUX_VERSION_CODE < LINUXVERSION(1,3,70)
@@ -2108,11 +3010,14 @@
 	{
 	POUR_DEVICE	pdev;
 
-	pdev = &(HOSTDATA(disk->device->host)->device[disk->device->id]);
+	if ( !(HOSTDATA(disk->device->host))->atapi )
+		{
+		pdev = &(HOSTDATA(disk->device->host)->device[disk->device->id]);
 
-	geom[0] = pdev->heads;
-	geom[1] = pdev->sectors;
-	geom[2] = pdev->cylinders;
+		geom[0] = pdev->heads;
+		geom[1] = pdev->sectors;
+		geom[2] = pdev->cylinders;
+		}
 	return 0;
 	}
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/scsi/pci2220i.h linux.15p9/drivers/scsi/pci2220i.h
--- linux.vanilla/drivers/scsi/pci2220i.h	Sat Aug 14 02:25:42 1999
+++ linux.15p9/drivers/scsi/pci2220i.h	Thu Feb 17 21:42:32 2000
@@ -21,265 +21,11 @@
 #ifndef _PCI2220I_H
 #define _PCI2220I_H
 
-#ifndef	PSI_EIDE_SCSIOP
-#define	PSI_EIDE_SCSIOP	1
-
 #ifndef LINUX_VERSION_CODE
 #include <linux/version.h>
 #endif 
 #define	LINUXVERSION(v,p,s)    (((v)<<16) + ((p)<<8) + (s))
 
-/************************************************/
-/*		Some defines that we like 				*/
-/************************************************/
-#define	CHAR		char
-#define	UCHAR		unsigned char
-#define	SHORT		short
-#define	USHORT		unsigned short
-#define	BOOL		unsigned short
-#define	LONG		long
-#define	ULONG		unsigned long
-#define	VOID		void
-
-#include "psi_dale.h"
-
-/************************************************/
-/*		Timeout konstants		 				*/
-/************************************************/
-#define	TIMEOUT_READY				100			// 100 mSec
-#define	TIMEOUT_DRQ					300			// 300 mSec
-#define	TIMEOUT_DATA				(3 * HZ)	// 3 seconds
-
-/************************************************/
-/*		Misc. macros			 				*/
-/************************************************/
-#define ANY2SCSI(up, p)					\
-((UCHAR *)up)[0] = (((ULONG)(p)) >> 8);	\
-((UCHAR *)up)[1] = ((ULONG)(p));
-
-#define SCSI2LONG(up)					\
-( (((long)*(((UCHAR *)up))) << 16)		\
-+ (((long)(((UCHAR *)up)[1])) << 8)		\
-+ ((long)(((UCHAR *)up)[2])) )
-
-#define XANY2SCSI(up, p)				\
-((UCHAR *)up)[0] = ((long)(p)) >> 24;	\
-((UCHAR *)up)[1] = ((long)(p)) >> 16;	\
-((UCHAR *)up)[2] = ((long)(p)) >> 8;	\
-((UCHAR *)up)[3] = ((long)(p));
-
-#define XSCSI2LONG(up)					\
-( (((long)(((UCHAR *)up)[0])) << 24)	\
-+ (((long)(((UCHAR *)up)[1])) << 16)	\
-+ (((long)(((UCHAR *)up)[2])) <<  8)	\
-+ ((long)(((UCHAR *)up)[3])) )
-
-#define	SelectSpigot(padapter,spigot)	outb_p (spigot, padapter->regStatSel)
-#define WriteCommand(padapter,cmd)		outb_p (cmd, padapter->regStatCmd)
-
-/************************************************/
-/*		SCSI CDB operation codes 				*/
-/************************************************/
-#define SCSIOP_TEST_UNIT_READY		0x00
-#define SCSIOP_REZERO_UNIT			0x01
-#define SCSIOP_REWIND				0x01
-#define SCSIOP_REQUEST_BLOCK_ADDR	0x02
-#define SCSIOP_REQUEST_SENSE		0x03
-#define SCSIOP_FORMAT_UNIT			0x04
-#define SCSIOP_READ_BLOCK_LIMITS	0x05
-#define SCSIOP_REASSIGN_BLOCKS		0x07
-#define SCSIOP_READ6				0x08
-#define SCSIOP_RECEIVE				0x08
-#define SCSIOP_WRITE6				0x0A
-#define SCSIOP_PRINT				0x0A
-#define SCSIOP_SEND					0x0A
-#define SCSIOP_SEEK6				0x0B
-#define SCSIOP_TRACK_SELECT			0x0B
-#define SCSIOP_SLEW_PRINT			0x0B
-#define SCSIOP_SEEK_BLOCK			0x0C
-#define SCSIOP_PARTITION			0x0D
-#define SCSIOP_READ_REVERSE			0x0F
-#define SCSIOP_WRITE_FILEMARKS		0x10
-#define SCSIOP_FLUSH_BUFFER			0x10
-#define SCSIOP_SPACE				0x11
-#define SCSIOP_INQUIRY				0x12
-#define SCSIOP_VERIFY6				0x13
-#define SCSIOP_RECOVER_BUF_DATA		0x14
-#define SCSIOP_MODE_SELECT			0x15
-#define SCSIOP_RESERVE_UNIT			0x16
-#define SCSIOP_RELEASE_UNIT			0x17
-#define SCSIOP_COPY					0x18
-#define SCSIOP_ERASE				0x19
-#define SCSIOP_MODE_SENSE			0x1A
-#define SCSIOP_START_STOP_UNIT		0x1B
-#define SCSIOP_STOP_PRINT			0x1B
-#define SCSIOP_LOAD_UNLOAD			0x1B
-#define SCSIOP_RECEIVE_DIAGNOSTIC	0x1C
-#define SCSIOP_SEND_DIAGNOSTIC		0x1D
-#define SCSIOP_MEDIUM_REMOVAL		0x1E
-#define SCSIOP_READ_CAPACITY		0x25
-#define SCSIOP_READ					0x28
-#define SCSIOP_WRITE				0x2A
-#define SCSIOP_SEEK					0x2B
-#define SCSIOP_LOCATE				0x2B
-#define SCSIOP_WRITE_VERIFY			0x2E
-#define SCSIOP_VERIFY				0x2F
-#define SCSIOP_SEARCH_DATA_HIGH		0x30
-#define SCSIOP_SEARCH_DATA_EQUAL	0x31
-#define SCSIOP_SEARCH_DATA_LOW		0x32
-#define SCSIOP_SET_LIMITS			0x33
-#define SCSIOP_READ_POSITION		0x34
-#define SCSIOP_SYNCHRONIZE_CACHE	0x35
-#define SCSIOP_COMPARE				0x39
-#define SCSIOP_COPY_COMPARE			0x3A
-#define SCSIOP_WRITE_DATA_BUFF		0x3B
-#define SCSIOP_READ_DATA_BUFF		0x3C
-#define SCSIOP_CHANGE_DEFINITION	0x40
-#define SCSIOP_READ_SUB_CHANNEL		0x42
-#define SCSIOP_READ_TOC				0x43
-#define SCSIOP_READ_HEADER			0x44
-#define SCSIOP_PLAY_AUDIO			0x45
-#define SCSIOP_PLAY_AUDIO_MSF		0x47
-#define SCSIOP_PLAY_TRACK_INDEX		0x48
-#define SCSIOP_PLAY_TRACK_RELATIVE	0x49
-#define SCSIOP_PAUSE_RESUME			0x4B
-#define SCSIOP_LOG_SELECT			0x4C
-#define SCSIOP_LOG_SENSE			0x4D
-#define SCSIOP_MODE_SELECT10		0x55
-#define SCSIOP_MODE_SENSE10			0x5A
-#define SCSIOP_LOAD_UNLOAD_SLOT		0xA6
-#define SCSIOP_MECHANISM_STATUS		0xBD
-#define SCSIOP_READ_CD				0xBE
-
-// IDE command definitions
-#define IDE_COMMAND_ATAPI_RESET		0x08
-#define IDE_COMMAND_READ			0x20
-#define IDE_COMMAND_WRITE			0x30
-#define IDE_COMMAND_RECALIBRATE		0x10
-#define IDE_COMMAND_SEEK			0x70
-#define IDE_COMMAND_SET_PARAMETERS	0x91
-#define IDE_COMMAND_VERIFY			0x40
-#define IDE_COMMAND_ATAPI_PACKET	0xA0
-#define IDE_COMMAND_ATAPI_IDENTIFY	0xA1
-#define	IDE_CMD_READ_MULTIPLE		0xC4
-#define	IDE_CMD_WRITE_MULTIPLE		0xC5
-#define	IDE_CMD_SET_MULTIPLE		0xC6
-#define IDE_COMMAND_IDENTIFY		0xEC
-
-// IDE status definitions
-#define IDE_STATUS_ERROR			0x01
-#define IDE_STATUS_INDEX			0x02
-#define IDE_STATUS_CORRECTED_ERROR	0x04
-#define IDE_STATUS_DRQ				0x08
-#define IDE_STATUS_DSC				0x10
-#define	IDE_STATUS_WRITE_FAULT		0x20
-#define IDE_STATUS_DRDY				0x40
-#define IDE_STATUS_BUSY				0x80
-
-// IDE error definitions
-#define	IDE_ERROR_AMNF				0x01
-#define	IDE_ERROR_TKONF				0x02
-#define	IDE_ERROR_ABRT				0x04
-#define	IDE_ERROR_MCR				0x08
-#define	IDE_ERROR_IDFN				0x10
-#define	IDE_ERROR_MC				0x20
-#define	IDE_ERROR_UNC				0x40
-#define	IDE_ERROR_BBK				0x80
-
-// SCSI read capacity structure
-typedef	struct _READ_CAPACITY_DATA
-	{
-	ULONG blks;				/* total blocks (converted to little endian) */
-	ULONG blksiz;			/* size of each (converted to little endian) */
-	}	READ_CAPACITY_DATA, *PREAD_CAPACITY_DATA;
-
-// SCSI inquiry data
-typedef struct _INQUIRYDATA
-	{
-	UCHAR DeviceType			:5;
-	UCHAR DeviceTypeQualifier	:3;
-	UCHAR DeviceTypeModifier	:7;
-	UCHAR RemovableMedia		:1;
-    UCHAR Versions;
-    UCHAR ResponseDataFormat;
-    UCHAR AdditionalLength;
-    UCHAR Reserved[2];
-	UCHAR SoftReset				:1;
-	UCHAR CommandQueue			:1;
-	UCHAR Reserved2				:1;
-	UCHAR LinkedCommands		:1;
-	UCHAR Synchronous			:1;
-	UCHAR Wide16Bit				:1;
-	UCHAR Wide32Bit				:1;
-	UCHAR RelativeAddressing	:1;
-    UCHAR VendorId[8];
-    UCHAR ProductId[16];
-    UCHAR ProductRevisionLevel[4];
-    UCHAR VendorSpecific[20];
-    UCHAR Reserved3[40];
-	}	INQUIRYDATA, *PINQUIRYDATA;
-
-// IDE IDENTIFY data
-#pragma pack (1)
-#pragma align 1
-typedef struct _IDENTIFY_DATA
-	{
-    USHORT	GeneralConfiguration;		//  0
-    USHORT	NumberOfCylinders;			//  1
-    USHORT	Reserved1;					//  2
-    USHORT	NumberOfHeads;				//  3
-    USHORT	UnformattedBytesPerTrack;	//  4
-    USHORT	UnformattedBytesPerSector;	//  5
-    USHORT	SectorsPerTrack;			//  6
-	USHORT	NumBytesISG;				//  7 Byte Len - inter-sector gap
-	USHORT	NumBytesSync;				//  8          - sync field
-	USHORT	NumWordsVUS;				//  9 Len - Vendor Unique Info
-    USHORT	SerialNumber[10];			// 10
-    USHORT	BufferType;					// 20
-    USHORT	BufferSectorSize;			// 21
-    USHORT	NumberOfEccBytes;			// 22
-    USHORT	FirmwareRevision[4];		// 23
-    USHORT	ModelNumber[20];			// 27
-	USHORT	NumSectorsPerInt	:8;		// 47 Multiple Mode - Sec/Blk
-	USHORT	Reserved2			:8;		// 47
-	USHORT	DoubleWordMode;				// 48 flag for double word mode capable
-	USHORT	VendorUnique1		:8;		// 49
-	USHORT	SupportDMA			:1;		// 49 DMA supported
-	USHORT	SupportLBA			:1;		// 49 LBA supported
-	USHORT	SupportIORDYDisable	:1;		// 49 IORDY can be disabled
-	USHORT	SupportIORDY		:1;		// 49 IORDY supported
-	USHORT	ReservedPsuedoDMA	:1;		// 49 reserved for pseudo DMA mode support
-	USHORT	Reserved3			:3;		// 49
-	USHORT	Reserved4;					// 50
-	USHORT	Reserved5			:8;		// 51 Transfer Cycle Timing - PIO
-	USHORT	PIOCycleTime		:8;		// 51 Transfer Cycle Timing - PIO
-	USHORT	Reserved6			:8;		// 52                       - DMA
-	USHORT	DMACycleTime		:8;		// 52                       - DMA
-	USHORT	Valid_54_58			:1;		// 53 words 54 - 58 are vaild
-	USHORT	Valid_64_70			:1;		// 53 words 64 - 70 are valid
-	USHORT	Reserved7			:14;	// 53
-	USHORT	LogNumCyl;					// 54 Current Translation - Num Cyl
-	USHORT	LogNumHeads;				// 55                       Num Heads
-	USHORT	LogSectorsPerTrack;			// 56                       Sec/Trk
-	ULONG	LogTotalSectors;			// 57                       Total Sec
-	USHORT	CurrentNumSecPerInt	:8;		// 59 current setting for number of sectors per interrupt
-	USHORT	ValidNumSecPerInt	:1;		// 59 Current setting is valid for number of sectors per interrupt
-	USHORT	Reserved8			:7;		// 59
-	ULONG	LBATotalSectors;			// 60 LBA Mode - Sectors
-	USHORT	DMASWordFlags;				// 62
-	USHORT	DMAMWordFlags;				// 63
-	USHORT	AdvancedPIOSupport  :8;		// 64 Flow control PIO transfer modes supported
-	USHORT	Reserved9			:8;		// 64
-	USHORT	MinMultiDMACycle;			// 65 minimum multiword DMA transfer cycle time per word
-	USHORT	RecomendDMACycle;			// 66 Manufacturer's recommende multiword DMA transfer cycle time
-	USHORT	MinPIOCycleWithoutFlow;		// 67 Minimum PIO transfer cycle time without flow control
-	USHORT	MinPIOCylceWithFlow;		// 68 Minimum PIO transfer cycle time with IORDY flow control
-	USHORT	ReservedSpace[256-69];		// 69
-	}	IDENTIFY_DATA, *PIDENTIFY_DATA;
-#pragma pack ()
-#pragma align 0
-#endif	// PSI_EIDE_SCSIOP
-
 // function prototypes
 int Pci2220i_Detect			(Scsi_Host_Template *tpnt);
 int Pci2220i_Command		(Scsi_Cmnd *SCpnt);
@@ -301,7 +47,7 @@
 		module:						NULL,									\
 		proc_dir:					&Proc_Scsi_Pci2220i,					\
 		proc_info:					NULL,	/* let's not bloat the kernel */\
-		name:						"PCI-2220I EIDE Disk Controller",		\
+		name:						"PCI-2220I/PCI-2240I",					\
 		detect:						Pci2220i_Detect,						\
 		release:					Pci2220i_Release,						\
 		info:						NULL,	/* let's not bloat the kernel */\
@@ -318,7 +64,7 @@
 		bios_param:					Pci2220i_BiosParam,						\
 		can_queue:					1,										\
 		this_id:					-1,										\
-		sg_tablesize:				SG_NONE,								\
+		sg_tablesize:				SG_ALL,								\
 		cmd_per_lun:				1,										\
 		present:					0,										\
 		unchecked_isa_dma:			0,										\
@@ -329,7 +75,7 @@
 #define PCI2220I { NULL, NULL,						\
 			&Proc_Scsi_Pci2220i,/* proc_dir_entry */\
 			NULL,		                			\
-			"PCI-2220I EIDE Disk Controller",		\
+			"PCI-2220I/PCI-2240I",					\
 			Pci2220i_Detect,						\
 			Pci2220i_Release,						\
 			NULL,	 								\
@@ -341,7 +87,7 @@
 			Pci2220i_BiosParam,                 	\
 			1, 										\
 			-1, 									\
-			SG_NONE,		 						\
+			SG_ALL,		 						\
 			1, 										\
 			0, 										\
 			0, 										\
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/scsi/psi_dale.h linux.15p9/drivers/scsi/psi_dale.h
--- linux.vanilla/drivers/scsi/psi_dale.h	Sat Aug 14 02:25:42 1999
+++ linux.15p9/drivers/scsi/psi_dale.h	Thu Feb 17 21:42:32 2000
@@ -20,16 +20,32 @@
  ****************************************************************************/
 
 /************************************************/
+/*		Some defines that we like 				*/
+/************************************************/
+#define	CHAR		char
+#define	UCHAR		unsigned char
+#define	SHORT		short
+#define	USHORT		unsigned short
+#define	BOOL		unsigned short
+#define	LONG		long
+#define	ULONG		unsigned long
+#define	VOID		void
+
+/************************************************/
 /*		Dale PCI setup							*/
 /************************************************/
 #define	VENDOR_PSI			0x1256
 #define	DEVICE_DALE_1		0x4401		/* 'D1' */
+#define	DEVICE_BIGD_1		0x4201		/* 'B1' */
+#define	DEVICE_BIGD_2		0x4202		/* 'B2' */
 
 /************************************************/
 /*		Misc konstants							*/
 /************************************************/
 #define	DALE_MAXDRIVES			4
+#define	BIGD_MAXDRIVES			8
 #define	SECTORSXFER				8
+#define	ATAPI_TRANSFER			8192
 #define	BYTES_PER_SECTOR		512
 #define	DEFAULT_TIMING_MODE		5
 
@@ -49,90 +65,136 @@
 /************************************************/
 /*		DALE Register address offsets			*/
 /************************************************/
-#define	REG_DATA						0x80
-#define	REG_ERROR						0x84
-#define	REG_SECTOR_COUNT				0x88
-#define	REG_LBA_0						0x8C
-#define	REG_LBA_8						0x90
-#define	REG_LBA_16						0x94
-#define	REG_LBA_24						0x98
-#define	REG_STAT_CMD					0x9C
-#define	REG_STAT_SEL					0xA0
-#define	REG_FAIL						0xB0
-#define	REG_ALT_STAT					0xB8
-#define	REG_DRIVE_ADRS					0xBC
-
-#define	DALE_DATA_SLOW					0x00040000L
-#define	DALE_DATA_MODE2					0x00040000L
-#define	DALE_DATA_MODE3					0x00050000L
-#define	DALE_DATA_MODE4					0x00060000L
-#define	DALE_DATA_MODE4P				0x00070000L
-
-#define RTR_LOCAL_RANGE					0x000
-#define RTR_LOCAL_REMAP					0x004
-#define RTR_EXP_RANGE					0x010
-#define RTR_EXP_REMAP					0x014
-#define RTR_REGIONS						0x018
-#define RTR_DM_MASK						0x01C
-#define RTR_DM_LOCAL_BASE				0x020
-#define RTR_DM_IO_BASE					0x024
-#define RTR_DM_PCI_REMAP				0x028
-#define RTR_DM_IO_CONFIG				0x02C
-#define RTR_MAILBOX						0x040
-#define RTR_LOCAL_DOORBELL				0x060
-#define RTR_PCI_DOORBELL				0x064
-#define RTR_INT_CONTROL_STATUS 			0x068
-#define RTR_EEPROM_CONTROL_STATUS		0x06C
-
-#define RTL_DMA0_MODE					0x00
-#define RTL_DMA0_PCI_ADDR				0x04
-#define RTL_DMA0_LOCAL_ADDR				0x08
-#define RTL_DMA0_COUNT					0x0C
-#define RTL_DMA0_DESC_PTR				0x10
-#define RTL_DMA1_MODE					0x14
-#define RTL_DMA1_PCI_ADDR				0x18
-#define RTL_DMA1_LOCAL_ADDR				0x1C
-#define RTL_DMA1_COUNT					0x20
-#define RTL_DMA1_DESC_PTR				0x24
-#define RTL_DMA_COMMAND_STATUS			0x28
-#define RTL_DMA_ARB0					0x2C
-#define RTL_DMA_ARB1					0x30
+#define	REG_DATA					0x80
+#define	REG_ERROR					0x84
+#define	REG_SECTOR_COUNT			0x88
+#define	REG_LBA_0					0x8C
+#define	REG_LBA_8					0x90
+#define	REG_LBA_16					0x94
+#define	REG_LBA_24					0x98
+#define	REG_STAT_CMD				0x9C
+#define	REG_STAT_SEL				0xA0
+#define	REG_FAIL					0xB0
+#define	REG_ALT_STAT				0xB8
+#define	REG_DRIVE_ADRS				0xBC
+
+#define	DALE_DATA_SLOW				0x00040000L
+#define	DALE_DATA_MODE2				0x00040000L
+#define	DALE_DATA_MODE3				0x00050000L
+#define	DALE_DATA_MODE4				0x00060000L
+#define	DALE_DATA_MODE5				0x00070000L
+
+#define	BIGD_DATA_SLOW				0x00000000L
+#define	BIGD_DATA_MODE0				0x00000000L
+#define	BIGD_DATA_MODE2				0x00000000L
+#define	BIGD_DATA_MODE3				0x00000008L
+#define	BIGD_DATA_MODE4				0x00000010L
+#define	BIGD_DATA_MODE5				0x00000020L
+
+#define RTR_LOCAL_RANGE				0x000
+#define RTR_LOCAL_REMAP				0x004
+#define RTR_EXP_RANGE				0x010
+#define RTR_EXP_REMAP				0x014
+#define RTR_REGIONS					0x018
+#define RTR_DM_MASK					0x01C
+#define RTR_DM_LOCAL_BASE			0x020
+#define RTR_DM_IO_BASE				0x024
+#define RTR_DM_PCI_REMAP			0x028
+#define RTR_DM_IO_CONFIG			0x02C
+#define RTR_MAILBOX					0x040
+#define RTR_LOCAL_DOORBELL			0x060
+#define RTR_PCI_DOORBELL			0x064
+#define RTR_INT_CONTROL_STATUS 		0x068
+#define RTR_EEPROM_CONTROL_STATUS	0x06C
+
+#define RTR_DMA0_MODE				0x0080
+#define RTR_DMA0_PCI_ADDR			0x0084
+#define RTR_DMA0_LOCAL_ADDR			0x0088
+#define RTR_DMA0_COUNT				0x008C
+#define RTR_DMA0_DESC_PTR			0x0090
+#define RTR_DMA1_MODE				0x0094
+#define RTR_DMA1_PCI_ADDR			0x0098
+#define RTR_DMA1_LOCAL_ADDR			0x009C
+#define RTR_DMA1_COUNT				0x00A0
+#define RTR_DMA1_DESC_PTR			0x00A4
+#define RTR_DMA_COMMAND_STATUS		0x00A8
+#define RTR_DMA_ARB0				0x00AC
+#define RTR_DMA_ARB1				0x00B0
+
+#define RTL_DMA0_MODE				0x00
+#define RTL_DMA0_PCI_ADDR			0x04
+#define RTL_DMA0_LOCAL_ADDR			0x08
+#define RTL_DMA0_COUNT				0x0C
+#define RTL_DMA0_DESC_PTR			0x10
+#define RTL_DMA1_MODE				0x14
+#define RTL_DMA1_PCI_ADDR			0x18
+#define RTL_DMA1_LOCAL_ADDR			0x1C
+#define RTL_DMA1_COUNT				0x20
+#define RTL_DMA1_DESC_PTR			0x24
+#define RTL_DMA_COMMAND_STATUS		0x28
+#define RTL_DMA_ARB0				0x2C
+#define RTL_DMA_ARB1				0x30
 
 /************************************************/
 /*		Dale Scratchpad locations				*/
 /************************************************/
-#define	DALE_CHANNEL_DEVICE_0			0		// device channel locations
-#define	DALE_CHANNEL_DEVICE_1			1
-#define	DALE_CHANNEL_DEVICE_2			2
-#define	DALE_CHANNEL_DEVICE_3			3
-
-#define	DALE_SCRATH_DEVICE_0			4		// device type codes
-#define	DALE_SCRATH_DEVICE_1			5
-#define DALE_SCRATH_DEVICE_2			6
-#define	DALE_SCRATH_DEVICE_3			7
-
-#define	DALE_RAID_0_STATUS				8
-#define DALE_RAID_1_STATUS				9
-
-#define	DALE_TIMING_MODE				12		// bus master timing mode (2, 3, 4, 5)
-#define	DALE_NUM_DRIVES					13		// number of addressable drives on this board
-#define	DALE_RAID_ON					14 		// RAID status On
-#define	DALE_LAST_ERROR					15		// Last error code from BIOS
+#define	DALE_CHANNEL_DEVICE_0		0		// device channel locations
+#define	DALE_CHANNEL_DEVICE_1		1
+#define	DALE_CHANNEL_DEVICE_2		2
+#define	DALE_CHANNEL_DEVICE_3		3
+
+#define	DALE_SCRATCH_DEVICE_0		4		// device type codes
+#define	DALE_SCRATCH_DEVICE_1		5
+#define DALE_SCRATCH_DEVICE_2		6
+#define	DALE_SCRATCH_DEVICE_3		7
+
+#define	DALE_RAID_0_STATUS			8
+#define DALE_RAID_1_STATUS			9
+
+#define	DALE_TIMING_MODE			12		// bus master timing mode (2, 3, 4, 5)
+#define	DALE_NUM_DRIVES				13		// number of addressable drives on this board
+#define	DALE_RAID_ON				14 		// RAID status On
+#define	DALE_LAST_ERROR				15		// Last error code from BIOS
+
+/************************************************/
+/*		BigD Scratchpad locations				*/
+/************************************************/
+#define	BIGD_DEVICE_0			0		// device channel locations
+#define	BIGD_DEVICE_1			1
+#define	BIGD_DEVICE_2			2
+#define	BIGD_DEVICE_3			3
+
+#define	BIGD_DEVICE_4			4		// device type codes
+#define	BIGD_DEVICE_5			5
+#define BIGD_DEVICE_6			6
+#define	BIGD_DEVICE_7			7
+
+#define	BIGD_ALARM_IMAGE		11		// ~image of alarm fail register		
+#define	BIGD_TIMING_MODE		12		// bus master timing mode (2, 3, 4, 5)
+#define	BIGD_NUM_DRIVES			13		// number of addressable drives on this board
+#define	BIGD_RAID_ON			14 		// RAID status is on for the whole board
+#define	BIGD_LAST_ERROR			15		// Last error code from BIOS
+
+#define	BIGD_RAID_0_STATUS		16
+#define BIGD_RAID_1_STATUS		17
+#define	BIGD_RAID_2_STATUS		18
+#define	BIGD_RAID_3_STATUS		19
+#define	BIGD_RAID_4_STATUS		20
+#define BIGD_RAID_5_STATUS		21
+#define	BIGD_RAID_6_STATUS		22
+#define	BIGD_RAID_7_STATUS		23
 
 /************************************************/
 /*		Dale cable select bits					*/
 /************************************************/
-#define	SEL_NONE						0x00
-#define	SEL_1							0x01
-#define	SEL_2							0x02
-
-/************************************************/
-/*		Programmable Interrupt Controller		*/
-/************************************************/
-#define	PIC1							0x20		// first 8259 base port address
-#define	PIC2							0xA0		// second 8259 base port address
-#define	INT_OCW1						1			// Operation Control Word 1: IRQ mask
-#define	EOI								0x20		// non-specific end-of-interrupt
+#define	SEL_NONE					0x00
+#define	SEL_1						0x01
+#define	SEL_2						0x02
+#define	SEL_3						0x04
+#define	SEL_4						0x08
+#define	SEL_NEW_SPEED_1				0x20
+#define	SEL_COPY					0x40
+#define	SEL_IRQ_OFF					0x80
 
 /************************************************/
 /*		Device/Geometry controls				*/
@@ -149,6 +211,18 @@
 #define	DEVICE_DASD_LBA				0x4				// LBA compatible device
 
 /************************************************/
+/*		BigD fail register bits					*/
+/************************************************/
+#define	FAIL_NONE				0x00
+#define	FAIL_0					0x01
+#define	FAIL_1					0x02
+#define	FAIL_2					0x04
+#define	FAIL_MULTIPLE			0x08
+#define	FAIL_GOOD				0x20
+#define	FAIL_AUDIBLE			0x40
+#define	FAIL_ANY				0x80
+
+/************************************************/
 /*		Setup Structure Definitions				*/
 /************************************************/
 typedef struct		// device setup parameters
@@ -168,11 +242,11 @@
 	BOOL			promptBIOS;
 	BOOL			fastFormat;
 	BOOL			shareInterrupt;
-	BOOL			rebootRebuil;
+	BOOL			rebootRebuild;
 	USHORT			timingMode;
 	USHORT			spare5;
 	USHORT			spare6;
-	SETUP_DEVICE	setupDevice[4];
+	SETUP_DEVICE	setupDevice[BIGD_MAXDRIVES];
 	}	SETUP, *PSETUP;
 
 /************************************************/
@@ -210,3 +284,281 @@
 #define	MY_SCSI_REBUILD		0x40			// byte 1 subcommand to reconstruct a mirrored pair
 #define MY_SCSI_DEMOFAIL	0x54			// byte 1 subcommand for RAID failure demonstration
 #define	MY_SCSI_ALARMMUTE	0x60			// byte 1 subcommand to mute any alarm currently on
+
+/************************************************/
+/*		Timeout konstants		 				*/
+/************************************************/
+#define	TIMEOUT_READY				100			// 100 mSec
+#define	TIMEOUT_DRQ					300			// 300 mSec
+#define	TIMEOUT_DATA				(3 * HZ)	// 3 seconds
+
+/************************************************/
+/*		Misc. macros			 				*/
+/************************************************/
+#define ANY2SCSI(up, p)					\
+((UCHAR *)up)[0] = (((ULONG)(p)) >> 8);	\
+((UCHAR *)up)[1] = ((ULONG)(p));
+
+#define SCSI2LONG(up)					\
+( (((long)*(((UCHAR *)up))) << 16)		\
++ (((long)(((UCHAR *)up)[1])) << 8)		\
++ ((long)(((UCHAR *)up)[2])) )
+
+#define XANY2SCSI(up, p)				\
+((UCHAR *)up)[0] = ((long)(p)) >> 24;	\
+((UCHAR *)up)[1] = ((long)(p)) >> 16;	\
+((UCHAR *)up)[2] = ((long)(p)) >> 8;	\
+((UCHAR *)up)[3] = ((long)(p));
+
+#define XSCSI2LONG(up)					\
+( (((long)(((UCHAR *)up)[0])) << 24)	\
++ (((long)(((UCHAR *)up)[1])) << 16)	\
++ (((long)(((UCHAR *)up)[2])) <<  8)	\
++ ((long)(((UCHAR *)up)[3])) )
+
+#define	SelectSpigot(padapter,spigot)	outb_p (spigot, padapter->regStatSel)
+#define WriteCommand(padapter,cmd)		outb_p (cmd, padapter->regStatCmd)
+#define	AtapiDevice(padapter,b)			outb_p (b, padapter->regLba24);
+#define	AtapiCountLo(padapter,b)		outb_p (b, padapter->regLba8)
+#define	AtapiCountHi(padapter,b)		outb_p (b, padapter->regLba16)
+
+/************************************************/
+/*		SCSI CDB operation codes 				*/
+/************************************************/
+#define SCSIOP_TEST_UNIT_READY		0x00
+#define SCSIOP_REZERO_UNIT			0x01
+#define SCSIOP_REWIND				0x01
+#define SCSIOP_REQUEST_BLOCK_ADDR	0x02
+#define SCSIOP_REQUEST_SENSE		0x03
+#define SCSIOP_FORMAT_UNIT			0x04
+#define SCSIOP_READ_BLOCK_LIMITS	0x05
+#define SCSIOP_REASSIGN_BLOCKS		0x07
+#define SCSIOP_READ6				0x08
+#define SCSIOP_RECEIVE				0x08
+#define SCSIOP_WRITE6				0x0A
+#define SCSIOP_PRINT				0x0A
+#define SCSIOP_SEND					0x0A
+#define SCSIOP_SEEK6				0x0B
+#define SCSIOP_TRACK_SELECT			0x0B
+#define SCSIOP_SLEW_PRINT			0x0B
+#define SCSIOP_SEEK_BLOCK			0x0C
+#define SCSIOP_PARTITION			0x0D
+#define SCSIOP_READ_REVERSE			0x0F
+#define SCSIOP_WRITE_FILEMARKS		0x10
+#define SCSIOP_FLUSH_BUFFER			0x10
+#define SCSIOP_SPACE				0x11
+#define SCSIOP_INQUIRY				0x12
+#define SCSIOP_VERIFY6				0x13
+#define SCSIOP_RECOVER_BUF_DATA		0x14
+#define SCSIOP_MODE_SELECT			0x15
+#define SCSIOP_RESERVE_UNIT			0x16
+#define SCSIOP_RELEASE_UNIT			0x17
+#define SCSIOP_COPY					0x18
+#define SCSIOP_ERASE				0x19
+#define SCSIOP_MODE_SENSE			0x1A
+#define SCSIOP_START_STOP_UNIT		0x1B
+#define SCSIOP_STOP_PRINT			0x1B
+#define SCSIOP_LOAD_UNLOAD			0x1B
+#define SCSIOP_RECEIVE_DIAGNOSTIC	0x1C
+#define SCSIOP_SEND_DIAGNOSTIC		0x1D
+#define SCSIOP_MEDIUM_REMOVAL		0x1E
+#define SCSIOP_READ_CAPACITY		0x25
+#define SCSIOP_READ					0x28
+#define SCSIOP_WRITE				0x2A
+#define SCSIOP_SEEK					0x2B
+#define SCSIOP_LOCATE				0x2B
+#define SCSIOP_WRITE_VERIFY			0x2E
+#define SCSIOP_VERIFY				0x2F
+#define SCSIOP_SEARCH_DATA_HIGH		0x30
+#define SCSIOP_SEARCH_DATA_EQUAL	0x31
+#define SCSIOP_SEARCH_DATA_LOW		0x32
+#define SCSIOP_SET_LIMITS			0x33
+#define SCSIOP_READ_POSITION		0x34
+#define SCSIOP_SYNCHRONIZE_CACHE	0x35
+#define SCSIOP_COMPARE				0x39
+#define SCSIOP_COPY_COMPARE			0x3A
+#define SCSIOP_WRITE_DATA_BUFF		0x3B
+#define SCSIOP_READ_DATA_BUFF		0x3C
+#define SCSIOP_CHANGE_DEFINITION	0x40
+#define SCSIOP_READ_SUB_CHANNEL		0x42
+#define SCSIOP_READ_TOC				0x43
+#define SCSIOP_READ_HEADER			0x44
+#define SCSIOP_PLAY_AUDIO			0x45
+#define SCSIOP_PLAY_AUDIO_MSF		0x47
+#define SCSIOP_PLAY_TRACK_INDEX		0x48
+#define SCSIOP_PLAY_TRACK_RELATIVE	0x49
+#define SCSIOP_PAUSE_RESUME			0x4B
+#define SCSIOP_LOG_SELECT			0x4C
+#define SCSIOP_LOG_SENSE			0x4D
+#define SCSIOP_MODE_SELECT10		0x55
+#define SCSIOP_MODE_SENSE10			0x5A
+#define SCSIOP_LOAD_UNLOAD_SLOT		0xA6
+#define SCSIOP_MECHANISM_STATUS		0xBD
+#define SCSIOP_READ_CD				0xBE
+
+// IDE command definitions
+#define IDE_COMMAND_ATAPI_RESET		0x08
+#define IDE_COMMAND_READ			0x20
+#define IDE_COMMAND_WRITE			0x30
+#define IDE_COMMAND_RECALIBRATE		0x10
+#define IDE_COMMAND_SEEK			0x70
+#define IDE_COMMAND_SET_PARAMETERS	0x91
+#define IDE_COMMAND_VERIFY			0x40
+#define IDE_COMMAND_ATAPI_PACKET	0xA0
+#define IDE_COMMAND_ATAPI_IDENTIFY	0xA1
+#define	IDE_CMD_READ_MULTIPLE		0xC4
+#define	IDE_CMD_WRITE_MULTIPLE		0xC5
+#define	IDE_CMD_SET_MULTIPLE		0xC6
+#define IDE_COMMAND_IDENTIFY		0xEC
+
+// IDE status definitions
+#define IDE_STATUS_ERROR			0x01
+#define IDE_STATUS_INDEX			0x02
+#define IDE_STATUS_CORRECTED_ERROR	0x04
+#define IDE_STATUS_DRQ				0x08
+#define IDE_STATUS_DSC				0x10
+#define	IDE_STATUS_WRITE_FAULT		0x20
+#define IDE_STATUS_DRDY				0x40
+#define IDE_STATUS_BUSY				0x80
+
+typedef struct _ATAPI_STATUS
+	{
+	CHAR	check		:1;
+	CHAR	reserved1	:1;
+	CHAR	corr		:1;
+	CHAR	drq			:1;
+	CHAR	dsc			:1;
+	CHAR	reserved2	:1;
+	CHAR	drdy		:1;
+	CHAR	bsy			:1;
+	}	ATAPI_STATUS;
+
+typedef struct _ATAPI_REASON
+	{
+	CHAR	cod			:1;
+	CHAR	io			:1;
+	CHAR	reserved1	:6;
+	}	ATAPI_REASON;
+
+typedef struct _ATAPI_ERROR
+	{
+	CHAR	ili			:1;
+	CHAR	eom			:1;
+	CHAR	abort		:1;
+	CHAR	mcr			:1;
+	CHAR	senseKey	:4;
+	}	ATAPI_ERROR;
+
+// IDE error definitions
+#define	IDE_ERROR_AMNF				0x01
+#define	IDE_ERROR_TKONF				0x02
+#define	IDE_ERROR_ABRT				0x04
+#define	IDE_ERROR_MCR				0x08
+#define	IDE_ERROR_IDFN				0x10
+#define	IDE_ERROR_MC				0x20
+#define	IDE_ERROR_UNC				0x40
+#define	IDE_ERROR_BBK				0x80
+
+// SCSI read capacity structure
+typedef	struct _READ_CAPACITY_DATA
+	{
+	ULONG blks;				/* total blocks (converted to little endian) */
+	ULONG blksiz;			/* size of each (converted to little endian) */
+	}	READ_CAPACITY_DATA, *PREAD_CAPACITY_DATA;
+
+// SCSI inquiry data
+typedef struct _INQUIRYDATA
+	{
+	UCHAR DeviceType			:5;
+	UCHAR DeviceTypeQualifier	:3;
+	UCHAR DeviceTypeModifier	:7;
+	UCHAR RemovableMedia		:1;
+    UCHAR Versions;
+    UCHAR ResponseDataFormat;
+    UCHAR AdditionalLength;
+    UCHAR Reserved[2];
+	UCHAR SoftReset				:1;
+	UCHAR CommandQueue			:1;
+	UCHAR Reserved2				:1;
+	UCHAR LinkedCommands		:1;
+	UCHAR Synchronous			:1;
+	UCHAR Wide16Bit				:1;
+	UCHAR Wide32Bit				:1;
+	UCHAR RelativeAddressing	:1;
+    UCHAR VendorId[8];
+    UCHAR ProductId[16];
+    UCHAR ProductRevisionLevel[4];
+    UCHAR VendorSpecific[20];
+    UCHAR Reserved3[40];
+	}	INQUIRYDATA, *PINQUIRYDATA;
+
+// IDE IDENTIFY data
+#pragma pack (1)
+typedef struct _IDENTIFY_DATA
+	{
+    USHORT	GeneralConfiguration;		//  0
+    USHORT	NumberOfCylinders;			//  1
+    USHORT	Reserved1;					//  2
+    USHORT	NumberOfHeads;				//  3
+    USHORT	UnformattedBytesPerTrack;	//  4
+    USHORT	UnformattedBytesPerSector;	//  5
+    USHORT	SectorsPerTrack;			//  6
+	USHORT	NumBytesISG;				//  7 Byte Len - inter-sector gap
+	USHORT	NumBytesSync;				//  8          - sync field
+	USHORT	NumWordsVUS;				//  9 Len - Vendor Unique Info
+    USHORT	SerialNumber[10];			// 10
+    USHORT	BufferType;					// 20
+    USHORT	BufferSectorSize;			// 21
+    USHORT	NumberOfEccBytes;			// 22
+    USHORT	FirmwareRevision[4];		// 23
+    USHORT	ModelNumber[20];			// 27
+	USHORT	NumSectorsPerInt	:8;		// 47 Multiple Mode - Sec/Blk
+	USHORT	Reserved2			:8;		// 47
+	USHORT	DoubleWordMode;				// 48 flag for double word mode capable
+	USHORT	VendorUnique1		:8;		// 49
+	USHORT	SupportDMA			:1;		// 49 DMA supported
+	USHORT	SupportLBA			:1;		// 49 LBA supported
+	USHORT	SupportIORDYDisable	:1;		// 49 IORDY can be disabled
+	USHORT	SupportIORDY		:1;		// 49 IORDY supported
+	USHORT	ReservedPsuedoDMA	:1;		// 49 reserved for pseudo DMA mode support
+	USHORT	Reserved3			:3;		// 49
+	USHORT	Reserved4;					// 50
+	USHORT	Reserved5			:8;		// 51 Transfer Cycle Timing - PIO
+	USHORT	PIOCycleTime		:8;		// 51 Transfer Cycle Timing - PIO
+	USHORT	Reserved6			:8;		// 52                       - DMA
+	USHORT	DMACycleTime		:8;		// 52                       - DMA
+	USHORT	Valid_54_58			:1;		// 53 words 54 - 58 are vaild
+	USHORT	Valid_64_70			:1;		// 53 words 64 - 70 are valid
+	USHORT	Reserved7			:14;	// 53
+	USHORT	LogNumCyl;					// 54 Current Translation - Num Cyl
+	USHORT	LogNumHeads;				// 55                       Num Heads
+	USHORT	LogSectorsPerTrack;			// 56                       Sec/Trk
+	ULONG	LogTotalSectors;			// 57                       Total Sec
+	USHORT	CurrentNumSecPerInt	:8;		// 59 current setting for number of sectors per interrupt
+	USHORT	ValidNumSecPerInt	:1;		// 59 Current setting is valid for number of sectors per interrupt
+	USHORT	Reserved8			:7;		// 59
+	ULONG	LBATotalSectors;			// 60 LBA Mode - Sectors
+	USHORT	DMASWordFlags;				// 62
+	USHORT	DMAMWordFlags;				// 63
+	USHORT	AdvancedPIOSupport  :8;		// 64 Flow control PIO transfer modes supported
+	USHORT	Reserved9			:8;		// 64
+	USHORT	MinMultiDMACycle;			// 65 minimum multiword DMA transfer cycle time per word
+	USHORT	RecomendDMACycle;			// 66 Manufacturer's recommende multiword DMA transfer cycle time
+	USHORT	MinPIOCycleWithoutFlow;		// 67 Minimum PIO transfer cycle time without flow control
+	USHORT	MinPIOCylceWithFlow;		// 68 Minimum PIO transfer cycle time with IORDY flow control
+	USHORT	ReservedSpace[256-69];		// 69
+	}	IDENTIFY_DATA, *PIDENTIFY_DATA;
+
+// ATAPI configuration bits
+typedef struct _ATAPI_GENERAL_0
+	{
+	USHORT	CmdPacketSize		:2;		// Command packet size
+	USHORT	Reserved1			:3;
+	USHORT	CmdDrqType			:2;
+	USHORT	Removable			:1;
+	USHORT	DeviceType			:5;
+	USHORT	Reserved2			:1;
+	USHORT	ProtocolType		:2;
+	}	ATAPI_GENERAL_0;
+
+#pragma pack ()
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/scsi/qlogicfc.c linux.15p9/drivers/scsi/qlogicfc.c
--- linux.vanilla/drivers/scsi/qlogicfc.c	Tue Jan  4 21:18:58 2000
+++ linux.15p9/drivers/scsi/qlogicfc.c	Thu Feb 17 22:00:48 2000
@@ -64,7 +64,7 @@
 /* Configuration section **************************************************** */
 
 /* Set the following macro to 1 to reload the ISP2x00's firmware.  This is
-   version 1.15.37 of the isp2100's firmware and version 2.00.16 of the 
+   version 1.17.30 of the isp2100's firmware and version 2.00.40 of the 
    isp2200's firmware. 
 */
 
@@ -77,7 +77,7 @@
 /* Set the following to 1 to include fabric support, fabric support is 
  * currently not as well tested as the other aspects of the driver */
 
-#define ISP2x00_FABRIC          0
+#define ISP2x00_FABRIC          1
 
 /*  Macros used for debugging */
 /*
@@ -91,7 +91,7 @@
 /* #define TRACE_ISP             1 */
 
 
-#define DEFAULT_LOOP_COUNT	10000000
+#define DEFAULT_LOOP_COUNT	1000000000
 
 /* End Configuration section ************************************************ */
 
@@ -632,6 +632,17 @@
 #define QLOGICFC_MAX_LUN	128
 #define QLOGICFC_MAX_LOOP_ID 	0x7d
 
+/* the following connection options only apply to the 2200.  i have only
+ * had success with LOOP_ONLY and P2P_ONLY.
+ */
+
+#define LOOP_ONLY              0
+#define P2P_ONLY               1
+#define LOOP_PREFERED          2
+#define P2P_PREFERED           3
+
+#define CONNECTION_PREFERENCE  LOOP_ONLY
+
 /* adapter_state values */
 #define AS_FIRMWARE_DEAD      -1
 #define AS_LOOP_DOWN           0
@@ -649,11 +660,11 @@
 	/* this is here so the queues are nicely aligned */
 	long send_marker;	/* do we need to send a marker? */
 
-	char res[RES_QUEUE_LEN + 1][QUEUE_ENTRY_LEN];
-	char req[QLOGICFC_REQ_QUEUE_LEN + 1][QUEUE_ENTRY_LEN];
+	char * res;
+	char * req;
 	struct init_cb control_block;
 	int adapter_state;
-	unsigned long int tag_ages[126];
+	unsigned long int tag_ages[QLOGICFC_MAX_ID + 1];
 	Scsi_Cmnd *handle_ptrs[QLOGICFC_REQ_QUEUE_LEN + 1];
 	unsigned long handle_serials[QLOGICFC_REQ_QUEUE_LEN + 1];
 	struct id_name_map port_db[QLOGICFC_MAX_ID + 1];
@@ -662,6 +673,7 @@
 	u_int port_id;
 	u_char queued;
 	u_char host_id;
+        struct timer_list explore_timer;
 };
 
 
@@ -676,7 +688,7 @@
 static int isp2x00_init(struct Scsi_Host *);
 static int isp2x00_reset_hardware(struct Scsi_Host *);
 static int isp2x00_mbox_command(struct Scsi_Host *, u_short[]);
-static int isp2x00_return_status(struct Status_Entry *);
+static int isp2x00_return_status(Scsi_Cmnd *, struct Status_Entry *);
 static void isp2x00_intr_handler(int, void *, struct pt_regs *);
 static void do_isp2x00_intr_handler(int, void *, struct pt_regs *);
 static int isp2x00_make_portdb(struct Scsi_Host *);
@@ -751,13 +763,26 @@
 
 			memset(hostdata, 0, sizeof(struct isp2x00_hostdata));
 			hostdata->pci_dev = pdev;
+			hostdata->res = (char *) kmalloc((RES_QUEUE_LEN + 1)*QUEUE_ENTRY_LEN, GFP_KERNEL);
+			if (!hostdata->res){
+			        printk("qlogicfc%d : could not allocate memory for response queue.\n", hostdata->host_id);
+			        scsi_unregister(host);
+				continue;
+			}
+			hostdata->req = (char *) kmalloc((QLOGICFC_REQ_QUEUE_LEN + 1)*QUEUE_ENTRY_LEN, GFP_KERNEL);
+			if (!hostdata->req){
+			        printk("qlogicfc%d : could not allocate memory for request queue.\n", hostdata->host_id);
+			        kfree(hostdata->res);
+			        scsi_unregister(host);
+				continue;
+			}
 
 			hostdata->queued = 0;
 			/* set up the control block */
 			hostdata->control_block.version = 0x1;
-			hostdata->control_block.firm_opts = 0x0108;
+			hostdata->control_block.firm_opts = 0x800e;
 			hostdata->control_block.max_frame_len = 2048;
-			hostdata->control_block.max_iocb = 256;
+			hostdata->control_block.max_iocb = QLOGICFC_REQ_QUEUE_LEN;
 			hostdata->control_block.exec_throttle = QLOGICFC_CMD_PER_LUN;
 			hostdata->control_block.retry_delay = 5;
 			hostdata->control_block.retry_cnt = 1;
@@ -768,16 +793,20 @@
 			hostdata->control_block.hard_addr = 0x0003;
 			hostdata->control_block.req_queue_len = QLOGICFC_REQ_QUEUE_LEN + 1;
 			hostdata->control_block.res_queue_len = RES_QUEUE_LEN + 1;
-			hostdata->control_block.res_queue_addr_lo = virt_to_bus_low32(&hostdata->res);
-			hostdata->control_block.res_queue_addr_high = virt_to_bus_high32(&hostdata->res);
-			hostdata->control_block.req_queue_addr_lo = virt_to_bus_low32(&hostdata->req);
-			hostdata->control_block.req_queue_addr_high = virt_to_bus_high32(&hostdata->req);
+			hostdata->control_block.res_queue_addr_lo = virt_to_bus_low32(hostdata->res);
+			hostdata->control_block.res_queue_addr_high = virt_to_bus_high32(hostdata->res);
+			hostdata->control_block.req_queue_addr_lo = virt_to_bus_low32(hostdata->req);
+			hostdata->control_block.req_queue_addr_high = virt_to_bus_high32(hostdata->req);
 
 
+			hostdata->control_block.add_firm_opts |= CONNECTION_PREFERENCE<<4;
 			hostdata->adapter_state = AS_LOOP_DOWN;
+			hostdata->explore_timer.data = 1;
 			hostdata->host_id = hosts;
-		
+
 			if (isp2x00_init(host) || isp2x00_reset_hardware(host)) {
+			        kfree(hostdata->res);
+				kfree(hostdata->req);
 			        scsi_unregister(host);
 				continue;
 			}
@@ -786,6 +815,8 @@
 			if (request_irq(host->irq, do_isp2x00_intr_handler, SA_INTERRUPT | SA_SHIRQ, "qlogicfc", host)) {
 			        printk("qlogicfc%d : interrupt %d already in use\n",
 				       hostdata->host_id, host->irq);
+			        kfree(hostdata->res);
+				kfree(hostdata->req);
 				scsi_unregister(host);
 				continue;
 			}
@@ -794,6 +825,8 @@
 				       "in use\n",
 				       hostdata->host_id, host->io_port, host->io_port + 0xff);
 				free_irq(host->irq, host);
+			        kfree(hostdata->res);
+				kfree(hostdata->req);
 				scsi_unregister(host);
 				continue;
 			}
@@ -810,6 +843,7 @@
 			        printk("qlogicfc%d : link is not up\n", hostdata->host_id);
 			}
 			hosts++;
+			hostdata->explore_timer.data = 0;
 		}
 	}
 
@@ -1085,6 +1119,9 @@
 
 	release_region(host->io_port, 0xff);
 
+	kfree(hostdata->res);
+	kfree(hostdata->req);
+
 	LEAVE("isp2x00_release");
 
 	return 0;
@@ -1140,7 +1177,12 @@
 		hostdata->adapter_state = AS_LOOP_GOOD;
 		printk("qlogicfc%d : Port Database\n", hostdata->host_id);
 		for (i = 0; hostdata->port_db[i].wwn != 0; i++) {
-			printk("wwn: %08x%08x  scsi_id: %x  loop_id: %x\n", (u_int) (hostdata->port_db[i].wwn >> 32), (u_int) hostdata->port_db[i].wwn, i, hostdata->port_db[i].loop_id);
+			printk("wwn: %08x%08x  scsi_id: %x  loop_id: ", (u_int) (hostdata->port_db[i].wwn >> 32), (u_int) hostdata->port_db[i].wwn, i);
+			if (hostdata->port_db[i].loop_id != hostdata->port_db[0].loop_id || i == 0)
+			        printk("%x", hostdata->port_db[i].loop_id);
+			else
+			        printk("Not Available");
+			printk("\n");
 		}
 	}
 	if (hostdata->adapter_state == AS_FIRMWARE_DEAD) {
@@ -1155,7 +1197,7 @@
 	DEBUG(printk("qlogicfc%d : request queue depth %d\n", hostdata->host_id,
 		     REQ_QUEUE_DEPTH(in_ptr, out_ptr)));
 
-	cmd = (struct Command_Entry *) &hostdata->req[in_ptr][0];
+	cmd = (struct Command_Entry *) &hostdata->req[in_ptr*QUEUE_ENTRY_LEN];
 	in_ptr = (in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN;
 	if (in_ptr == out_ptr) {
 		DEBUG(printk("qlogicfc%d : request queue overflow\n", hostdata->host_id));
@@ -1182,7 +1224,7 @@
 			DEBUG(printk("qlogicfc%d : request queue overflow\n", hostdata->host_id));
 			return 1;
 		}
-		cmd = (struct Command_Entry *) &hostdata->req[in_ptr][0];
+		cmd = (struct Command_Entry *) &hostdata->req[in_ptr*QUEUE_ENTRY_LEN];
 		in_ptr = (in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN;
 	}
 	TRACE("queue command", in_ptr, Cmnd);
@@ -1204,6 +1246,7 @@
 				printk("slot %d has %p\n", i, hostdata->handle_ptrs[i]);
 			}
 		}
+		return 1;
 	}
 
 	cmd->hdr.entry_type = ENTRY_COMMAND;
@@ -1241,7 +1284,7 @@
 		while (sg_count > 0) {
 			++cmd->hdr.entry_cnt;
 			cont = (struct Continuation_Entry *)
-			    &hostdata->req[in_ptr][0];
+			    &hostdata->req[in_ptr*QUEUE_ENTRY_LEN];
 			memset(cont, 0, sizeof(struct Continuation_Entry));
 			in_ptr = (in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN;
 			if (in_ptr == out_ptr) {
@@ -1341,8 +1384,57 @@
 }
 
 
-#define ASYNC_EVENT_INTERRUPT	0x01
+/* we have received an event, such as a lip or an RSCN, which may mean that
+ * our port database is incorrect so the port database must be recreated.
+ */
+static void redo_port_db(unsigned long arg)
+{
+
+        struct Scsi_Host * host = (struct Scsi_Host *) arg;
+	struct isp2x00_hostdata * hostdata;
+	unsigned long flags;
+	int i;
+
+	hostdata = (struct isp2x00_hostdata *) host->hostdata;
+	hostdata->explore_timer.data = 0;
+	del_timer(&hostdata->explore_timer);
+
+	spin_lock_irqsave(&io_request_lock, flags);
 
+	if (hostdata->adapter_state & AS_REDO_FABRIC_PORTDB || hostdata->adapter_state & AS_REDO_LOOP_PORTDB) {
+		isp2x00_make_portdb(host);
+		printk("qlogicfc%d : Port Database\n", hostdata->host_id);
+		for (i = 0; hostdata->port_db[i].wwn != 0; i++) {
+			printk("wwn: %08x%08x  scsi_id: %x  loop_id: ", (u_int) (hostdata->port_db[i].wwn >> 32), (u_int) hostdata->port_db[i].wwn, i);
+			if (hostdata->port_db[i].loop_id != hostdata->port_db[0].loop_id || i == 0)
+			        printk("%x", hostdata->port_db[i].loop_id);
+			else
+			        printk("Not Available");
+			printk("\n");
+		}
+		
+	        for (i = 0; i < QLOGICFC_REQ_QUEUE_LEN; i++){ 
+		        if (hostdata->handle_ptrs[i] && (hostdata->port_db[hostdata->handle_ptrs[i]->target].loop_id > QLOGICFC_MAX_LOOP_ID || hostdata->adapter_state & AS_REDO_LOOP_PORTDB)){
+                                if (hostdata->port_db[hostdata->handle_ptrs[i]->target].loop_id != hostdata->port_db[0].loop_id){
+					 hostdata->handle_ptrs[i]->result = DID_SOFT_ERROR << 16;
+					 if (hostdata->handle_ptrs[i]->scsi_done){
+					   (*hostdata->handle_ptrs[i]->scsi_done) (hostdata->handle_ptrs[i]);
+					 }
+					 else printk("qlogicfc%d : done is null?\n", hostdata->host_id);
+					 hostdata->handle_ptrs[i] = NULL;
+					 hostdata->handle_serials[i] = 0;
+				}
+			}
+		}
+		
+		hostdata->adapter_state = AS_LOOP_GOOD;
+	}
+
+	spin_unlock_irqrestore(&io_request_lock, flags);
+
+}
+
+#define ASYNC_EVENT_INTERRUPT	0x01
 
 void do_isp2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
@@ -1385,23 +1477,24 @@
 		switch (status) {
 		case LOOP_UP:
 		case POINT_TO_POINT_UP:
-		        printk("qlogicfc%d : link is up\n", hostdata->host_id);
+		        printk("qlogicfc%d : Link is Up\n", hostdata->host_id);
 			hostdata->adapter_state = AS_REDO_FABRIC_PORTDB | AS_REDO_LOOP_PORTDB;
 			break;
 		case LOOP_DOWN:
-		        printk("qlogicfc%d : link is down\n", hostdata->host_id);
+		        printk("qlogicfc%d : Link is Down\n", hostdata->host_id);
 			hostdata->adapter_state = AS_LOOP_DOWN;
 			break;
 		case CONNECTION_MODE:
 		        printk("received CONNECTION_MODE irq %x\n", inw(host->io_port + MBOX1));
 			break;
 		case CHANGE_NOTIFICATION:
+		        printk("qlogicfc%d : RSCN Received\n", hostdata->host_id);
 			if (hostdata->adapter_state == AS_LOOP_GOOD)
 				hostdata->adapter_state = AS_REDO_FABRIC_PORTDB;
 			break;		        
 		case LIP_OCCURED:
-		case PORT_DB_CHANGED:
 		case LIP_RECEIVED:
+		        printk("qlogicfc%d : Loop Reinitialized\n", hostdata->host_id);
 			if (hostdata->adapter_state == AS_LOOP_GOOD)
 				hostdata->adapter_state = AS_REDO_LOOP_PORTDB;
 			break;
@@ -1436,22 +1529,27 @@
 		default:
 			printk("qlogicfc%d : got an unknown status? %x\n", hostdata->host_id, status);
 		}
+		if ((hostdata->adapter_state & AS_REDO_LOOP_PORTDB || hostdata->adapter_state & AS_REDO_FABRIC_PORTDB) && hostdata->explore_timer.data == 0){
+                        hostdata->explore_timer.function = redo_port_db;
+			hostdata->explore_timer.data = (unsigned long)host;
+			hostdata->explore_timer.expires = jiffies + (HZ/4);
+			init_timer(&hostdata->explore_timer);
+			add_timer(&hostdata->explore_timer);
+		}
 		outw(0x0, host->io_port + PCI_SEMAPHORE);
 	} else {
 		DEBUG_INTR(printk("qlogicfc%d : response queue update\n", hostdata->host_id));
 		DEBUG_INTR(printk("qlogicfc%d : response queue depth %d\n", hostdata->host_id, RES_QUEUE_DEPTH(in_ptr, out_ptr)));
 
 		while (out_ptr != in_ptr) {
-			sts = (struct Status_Entry *) &hostdata->res[out_ptr][0];
+			sts = (struct Status_Entry *) &hostdata->res[out_ptr*QUEUE_ENTRY_LEN];
 			out_ptr = (out_ptr + 1) & RES_QUEUE_LEN;
                  
 			TRACE("done", out_ptr, Cmnd);
 			DEBUG_INTR(isp2x00_print_status_entry(sts));
 			if (sts->hdr.entry_type == ENTRY_STATUS && (Cmnd = hostdata->handle_ptrs[sts->handle])) {
-				Cmnd->result = isp2x00_return_status(sts);
-				hostdata->handle_ptrs[sts->handle] = NULL;
+				Cmnd->result = isp2x00_return_status(Cmnd, sts);
 				hostdata->queued--;
-
 				/* 
 				 * if any of the following are true we do not
 				 * call scsi_done.  if the status is CS_ABORTED
@@ -1461,6 +1559,7 @@
 				if (hostdata->handle_serials[sts->handle] != Cmnd->serial_number 
 				    || sts->completion_status == CS_ABORTED){
 					hostdata->handle_serials[sts->handle] = 0;
+					hostdata->handle_ptrs[sts->handle] = NULL;
 					outw(out_ptr, host->io_port + MBOX5);
 					continue;
 				}
@@ -1481,6 +1580,8 @@
 				continue;
 			}
 
+			hostdata->handle_ptrs[sts->handle] = NULL;
+
 			if (sts->completion_status == CS_RESET_OCCURRED
 			    || (sts->status_flags & STF_BUS_RESET))
 				hostdata->send_marker = 1;
@@ -1522,7 +1623,7 @@
 }
 
 
-static int isp2x00_return_status(struct Status_Entry *sts)
+static int isp2x00_return_status(Scsi_Cmnd *Cmnd, struct Status_Entry *sts)
 {
 	int host_status = DID_ERROR;
 #if DEBUG_ISP2x00_INTR
@@ -1566,7 +1667,10 @@
 		host_status = DID_ERROR;
 		break;
 	case CS_DATA_UNDERRUN:
-		host_status = DID_OK;
+	        if (Cmnd->underflow <= (Cmnd->request_bufflen - sts->residual))
+		        host_status = DID_OK;
+		else
+		        host_status = DID_ERROR;
 		break;
 	case CS_PORT_UNAVAILABLE:
 	case CS_PORT_LOGGED_OUT:
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/scsi/qlogicfc_asm.c linux.15p9/drivers/scsi/qlogicfc_asm.c
--- linux.vanilla/drivers/scsi/qlogicfc_asm.c	Wed Oct 20 01:12:42 1999
+++ linux.15p9/drivers/scsi/qlogicfc_asm.c	Sat Jan 22 00:09:05 2000
@@ -1,7464 +1,7804 @@
-
+/************************************************************************
+ *									*
+ * 	 --- ISP2100 Fabric Initiator/Target Firmware ---               *
+ *                   with expanded LUN addressing.                      *
+ *									*
+ ************************************************************************
+ * Copyright (C) 1999 Qlogic, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted provided
+ * that the following conditions are met:
+ * 1. Redistribution of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistribution in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *									*
+ ************************************************************************
+ */
 /*
- *	Firmware Version 1.15.37 (15:37 May 03, 1999)
+ *     W     W     A     RRRR    N   N   IIIII   N   N    GGG
+ *     W     W    A A    R   R   N   N     I     N   N   G   G
+ *     W     W   A   A   R  R    NN  N     I     NN  N   G  
+ *     W  W  W   AAAAA   RRR     N N N     I     N N N   G  GG
+ *     W  W  W   A   A   R R     N  NN     I     N  NN   G   G
+ *     W W W W   A   A   R  R    N   N     I     N   N   G   G
+ *      W   W    A   A   R   R   N   N   IIIII   N   N    GGGG
+ *
+ *         This version of firmware is a release candidate,
+ *     design verification testing (DVT) has not been completed.
+ */
+/*
+ *	Firmware Version 1.17.30 (14:05 Sep 30, 1999)
  */
 
 unsigned short risc_code_addr01 = 0x1000 ;
-unsigned short risc_code_length2100 = 0x66e6;
-unsigned short risc_code_length2200 = 0x81bd;
+unsigned short risc_code_length2100 = 0x77a0;
+unsigned short risc_code_length2200 = 0x7a68;
 
-unsigned short risc_code2100[] = { 
-	0x0078, 0x1029, 0x0000, 0x66e6, 0x0000, 0x2043, 0x4f50, 0x5952,
-	0x4947, 0x4854, 0x2031, 0x3939, 0x3620, 0x514c, 0x4f47, 0x4943,
+unsigned short risc_code2100[] = {
+	0x0078, 0x1029, 0x0000, 0x77a0, 0x0000, 0x2043, 0x4f50, 0x5952,
+	0x4947, 0x4854, 0x2031, 0x3939, 0x3920, 0x514c, 0x4f47, 0x4943,
 	0x2043, 0x4f52, 0x504f, 0x5241, 0x5449, 0x4f4e, 0x2049, 0x5350,
 	0x3231, 0x3030, 0x2046, 0x6972, 0x6d77, 0x6172, 0x6520, 0x2056,
-	0x6572, 0x7369, 0x6f6e, 0x2030, 0x312e, 0x3135, 0x2020, 0x2020,
-	0x2400, 0x20c1, 0x0021, 0x20a1, 0x76e6, 0x2009, 0x0000, 0x20a9,
-	0x071a, 0x41a4, 0x3400, 0x20c9, 0x7bff, 0x2091, 0x2000, 0x2059,
-	0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x209a, 0x2051, 0x7700,
-	0x2a70, 0x705b, 0x9600, 0x705f, 0xffff, 0x7057, 0x95f9, 0x7063,
-	0x0300, 0x1078, 0x127a, 0x20a1, 0x7e00, 0x715c, 0x810d, 0x810d,
-	0x810d, 0x810d, 0xa18c, 0x000f, 0x2001, 0x0007, 0xa112, 0xa00e,
-	0x21a8, 0x41a4, 0x3400, 0x8211, 0x00c0, 0x1058, 0x715c, 0x3400,
-	0xa102, 0x0040, 0x1068, 0x0048, 0x1068, 0x20a8, 0xa00e, 0x41a4,
-	0x1078, 0x1241, 0x1078, 0x1366, 0x1078, 0x14eb, 0x1078, 0x19c0,
-	0x1078, 0x362b, 0x1078, 0x5cac, 0x1078, 0x12f1, 0x1078, 0x2429,
-	0x1078, 0x3d6e, 0x1078, 0x3b46, 0x1078, 0x45af, 0x1078, 0x1e55,
-	0x1078, 0x47ef, 0x1078, 0x428f, 0x1078, 0x1d74, 0x1078, 0x1e34,
-	0x2091, 0x3009, 0x7823, 0x0000, 0x0090, 0x109d, 0x7820, 0xa086,
-	0x0002, 0x00c0, 0x109d, 0x7823, 0x4000, 0x0068, 0x1095, 0x781b,
-	0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70, 0x7003, 0x0000,
-	0x2001, 0x017f, 0x2003, 0x0000, 0x2a70, 0x7000, 0xa08e, 0x0003,
-	0x00c0, 0x10bd, 0x1078, 0x2d9c, 0x1078, 0x2451, 0x1078, 0x3dbe,
-	0x1078, 0x3c31, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0048,
-	0x10c1, 0x1078, 0x45c7, 0x0078, 0x10a4, 0x1079, 0x10c5, 0x0078,
-	0x10aa, 0x1078, 0x597e, 0x0078, 0x10b9, 0x10cf, 0x10d0, 0x1143,
-	0x10cd, 0x11be, 0x123e, 0x123f, 0x1240, 0x1078, 0x12cd, 0x007c,
-	0x127e, 0x0f7e, 0x2091, 0x8000, 0x1078, 0x2ec1, 0x2079, 0x0100,
-	0x7844, 0xa005, 0x00c0, 0x1134, 0x2011, 0x3558, 0x1078, 0x4689,
-	0x780f, 0x00ff, 0x7840, 0xa084, 0xfffb, 0x7842, 0x2011, 0x8010,
-	0x73b8, 0x1078, 0x2d59, 0x1078, 0x57c9, 0x2011, 0x0004, 0x1078,
-	0x6a6d, 0x1078, 0x3ae0, 0x70c7, 0x0000, 0x70c3, 0x0000, 0x1078,
-	0x1137, 0x72bc, 0x2079, 0x7751, 0x7804, 0xd0ac, 0x0040, 0x1101,
-	0xc295, 0x72be, 0xa296, 0x0004, 0x0040, 0x1122, 0x2011, 0x0001,
-	0x1078, 0x6a6d, 0x708b, 0x0000, 0x708f, 0xffff, 0x7003, 0x0002,
-	0x0f7f, 0x1078, 0x214a, 0x2011, 0x0005, 0x1078, 0x58d8, 0x1078,
-	0x4d96, 0x0c7e, 0x2061, 0x0100, 0x60e3, 0x0008, 0x0c7f, 0x127f,
-	0x0078, 0x1136, 0x708b, 0x0000, 0x708f, 0xffff, 0x7003, 0x0002,
-	0x2011, 0x0005, 0x1078, 0x58d8, 0x1078, 0x4d96, 0x0c7e, 0x2061,
-	0x0100, 0x60e3, 0x0008, 0x0c7f, 0x0f7f, 0x127f, 0x007c, 0x0c7e,
-	0x20a9, 0x0082, 0x2009, 0x007e, 0x1078, 0x3834, 0x8108, 0x00f0,
-	0x113c, 0x0c7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x708c, 0xa086,
-	0xffff, 0x0040, 0x1151, 0x1078, 0x214a, 0x1078, 0x4d96, 0x0078,
-	0x11bc, 0x70bc, 0xd09c, 0x0040, 0x1179, 0xd084, 0x0040, 0x1179,
-	0x0f7e, 0x2079, 0x0100, 0x790c, 0xc1b5, 0x790e, 0x0f7f, 0xd08c,
-	0x0040, 0x1179, 0x70c0, 0xa086, 0xffff, 0x0040, 0x1175, 0x1078,
-	0x223f, 0x1078, 0x4d96, 0x2011, 0x0001, 0x2019, 0x0000, 0x1078,
-	0x2277, 0x1078, 0x4d96, 0x0078, 0x11bc, 0x70c4, 0xa005, 0x00c0,
-	0x11bc, 0x7088, 0xa005, 0x00c0, 0x11bc, 0x2001, 0x7752, 0x2004,
-	0xd0ac, 0x0040, 0x119f, 0x157e, 0x0c7e, 0x20a9, 0x007f, 0x2009,
-	0x0000, 0x017e, 0x1078, 0x384c, 0x00c0, 0x1192, 0x6000, 0xd0ec,
-	0x00c0, 0x119a, 0x017f, 0x8108, 0x00f0, 0x1189, 0x0c7f, 0x157f,
-	0x0078, 0x119f, 0x017f, 0x0c7f, 0x157f, 0x0078, 0x11bc, 0x7003,
-	0x0003, 0x708f, 0xffff, 0x2001, 0x0000, 0x1078, 0x2025, 0x1078,
-	0x2dd7, 0x2001, 0x7937, 0x2004, 0xa086, 0x0005, 0x00c0, 0x11b4,
-	0x2011, 0x0000, 0x1078, 0x58d8, 0x2011, 0x0000, 0x1078, 0x58e2,
-	0x1078, 0x4d96, 0x1078, 0x4e56, 0x127f, 0x007c, 0x017e, 0x0f7e,
-	0x127e, 0x2091, 0x8000, 0x2079, 0x0100, 0x7940, 0xa18c, 0x0010,
-	0x7942, 0x7924, 0xd1b4, 0x0040, 0x11cf, 0x7827, 0x0040, 0xd19c,
-	0x0040, 0x11d4, 0x7827, 0x0008, 0x007e, 0x037e, 0x157e, 0x7900,
-	0xa18a, 0x0003, 0x0050, 0x11fa, 0x7954, 0xd1ac, 0x00c0, 0x11fa,
-	0x2009, 0x00f8, 0x1078, 0x35fa, 0x7843, 0x0090, 0x7843, 0x0010,
-	0x20a9, 0x09c4, 0x7820, 0xd09c, 0x00c0, 0x11f2, 0x7824, 0xd0ac,
-	0x00c0, 0x122e, 0x00f0, 0x11ea, 0x2001, 0x0001, 0x1078, 0x2025,
-	0x0078, 0x1237, 0x7853, 0x0000, 0x782f, 0x0020, 0x20a9, 0x0008,
-	0x00e0, 0x1200, 0x2091, 0x6000, 0x00f0, 0x1200, 0x7853, 0x0400,
-	0x782f, 0x0000, 0x2009, 0x00f8, 0x1078, 0x35fa, 0x20a9, 0x000e,
-	0x0005, 0x00f0, 0x1210, 0x7853, 0x1400, 0x7843, 0x0090, 0x7843,
-	0x0010, 0x2019, 0x61a8, 0x7854, 0x0005, 0x0005, 0xd08c, 0x0040,
-	0x1225, 0x7824, 0xd0ac, 0x00c0, 0x122e, 0x8319, 0x00c0, 0x121b,
-	0x2001, 0x0001, 0x1078, 0x2025, 0x0078, 0x1235, 0x7828, 0xc09d,
-	0x782a, 0x7827, 0x0008, 0x7827, 0x0040, 0x7853, 0x0400, 0x157f,
-	0x037f, 0x007f, 0x127f, 0x0f7f, 0x017f, 0x007c, 0x007c, 0x007c,
-	0x007c, 0x2a70, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0048,
-	0x124d, 0x704f, 0xffff, 0x0078, 0x124f, 0x704f, 0x0000, 0x7053,
-	0xffff, 0x7067, 0x0000, 0x706b, 0x0000, 0x2061, 0x7920, 0x6003,
-	0x0909, 0x6007, 0x0000, 0x600b, 0x8800, 0x600f, 0x0200, 0x6013,
-	0x00ff, 0x6017, 0x0003, 0x601b, 0x0000, 0x601f, 0x07d0, 0x2061,
-	0x7928, 0x6003, 0x8000, 0x6007, 0x0000, 0x600b, 0x0000, 0x600f,
-	0x0200, 0x6013, 0x00ff, 0x6017, 0x0000, 0x601b, 0x0001, 0x601f,
-	0x0000, 0x007c, 0x1078, 0x12a0, 0x2011, 0x0000, 0x81ff, 0x0040,
-	0x129f, 0xa186, 0x0001, 0x00c0, 0x128f, 0x705f, 0x8fff, 0x7057,
-	0x8601, 0x7063, 0x0100, 0x705b, 0x8600, 0x0078, 0x129d, 0xa186,
-	0x0002, 0x00c0, 0x1297, 0x2011, 0x0000, 0x0078, 0x129d, 0xa186,
-	0x0005, 0x00c0, 0x129d, 0x2011, 0x0001, 0x1078, 0x12c7, 0x007c,
-	0x2009, 0x0000, 0x2011, 0x0000, 0x1078, 0x12c7, 0x2019, 0xaaaa,
-	0x2061, 0xffff, 0x2362, 0x2c24, 0x2061, 0x7fff, 0x2c04, 0xa406,
-	0x0040, 0x12b5, 0xc18d, 0x0078, 0x12c2, 0xc185, 0x2011, 0x0001,
-	0x1078, 0x12c7, 0x2061, 0xffff, 0x2362, 0x2c04, 0xa306, 0x00c0,
-	0x12c2, 0xc195, 0x2011, 0x0001, 0x1078, 0x12c7, 0x007c, 0x3800,
-	0xa084, 0xfffc, 0xa205, 0x20c0, 0x007c, 0x2091, 0x8000, 0x0068,
-	0x12cf, 0x007e, 0x017e, 0x2079, 0x0000, 0x7818, 0xa084, 0x0000,
-	0x00c0, 0x12d5, 0x017f, 0x792e, 0x007f, 0x782a, 0x007f, 0x7826,
-	0x3900, 0x783a, 0x7823, 0x8002, 0x781b, 0x0001, 0x2091, 0x5000,
-	0x2091, 0x4080, 0x2079, 0x7700, 0x7803, 0x0005, 0x0078, 0x12ee,
-	0x007c, 0x2071, 0x7700, 0x7158, 0x712e, 0x2021, 0x0001, 0xa190,
-	0x002d, 0xa298, 0x002d, 0x0048, 0x1307, 0x705c, 0xa302, 0x00c8,
-	0x1307, 0x220a, 0x2208, 0x2310, 0x8420, 0x0078, 0x12f9, 0x200b,
-	0x0000, 0x749e, 0x74a2, 0x007c, 0x0e7e, 0x127e, 0x2091, 0x8000,
-	0x2071, 0x7700, 0x70a0, 0xa0ea, 0x0010, 0x00c8, 0x131a, 0xa06e,
-	0x0078, 0x1324, 0x8001, 0x70a2, 0x702c, 0x2068, 0x2d04, 0x702e,
-	0x206b, 0x0000, 0x6807, 0x0000, 0x127f, 0x0e7f, 0x007c, 0x0e7e,
-	0x2071, 0x7700, 0x127e, 0x2091, 0x8000, 0x70a0, 0x8001, 0x00c8,
-	0x1334, 0xa06e, 0x0078, 0x133d, 0x70a2, 0x702c, 0x2068, 0x2d04,
-	0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x127f, 0x0e7f, 0x007c,
-	0x0e7e, 0x127e, 0x2091, 0x8000, 0x2071, 0x7700, 0x702c, 0x206a,
-	0x2d00, 0x702e, 0x70a0, 0x8000, 0x70a2, 0x127f, 0x0e7f, 0x007c,
-	0x8dff, 0x0040, 0x135c, 0x6804, 0x6807, 0x0000, 0x007e, 0x1078,
-	0x1340, 0x0d7f, 0x0078, 0x1350, 0x007c, 0x0e7e, 0x2071, 0x7700,
-	0x70a0, 0xa08a, 0x0010, 0xa00d, 0x0e7f, 0x007c, 0x0e7e, 0x2071,
-	0x7959, 0x7007, 0x0000, 0x701b, 0x0000, 0x701f, 0x0000, 0x2071,
-	0x0000, 0x7010, 0xa085, 0x8004, 0x7012, 0x0e7f, 0x007c, 0x0e7e,
-	0x2270, 0x700b, 0x0000, 0x2071, 0x7959, 0x7018, 0xa088, 0x7962,
-	0x220a, 0x8000, 0xa084, 0x0007, 0x701a, 0x7004, 0xa005, 0x00c0,
-	0x138f, 0x0f7e, 0x2079, 0x0010, 0x1078, 0x13a0, 0x0f7f, 0x0e7f,
-	0x007c, 0x0e7e, 0x2071, 0x7959, 0x7004, 0xa005, 0x00c0, 0x139e,
-	0x0f7e, 0x2079, 0x0010, 0x1078, 0x13a0, 0x0f7f, 0x0e7f, 0x007c,
-	0x7000, 0x0079, 0x13a3, 0x13a7, 0x1411, 0x142e, 0x142e, 0x7018,
-	0x711c, 0xa106, 0x00c0, 0x13af, 0x7007, 0x0000, 0x007c, 0x0d7e,
-	0xa180, 0x7962, 0x2004, 0x700a, 0x2068, 0x8108, 0xa18c, 0x0007,
-	0x711e, 0x7803, 0x0026, 0x6824, 0x7832, 0x6828, 0x7836, 0x682c,
-	0x783a, 0x6830, 0x783e, 0x6810, 0x700e, 0x680c, 0x7016, 0x6804,
-	0x0d7f, 0xd084, 0x0040, 0x13d1, 0x7007, 0x0001, 0x1078, 0x13d6,
-	0x007c, 0x7007, 0x0002, 0x1078, 0x13ec, 0x007c, 0x017e, 0x027e,
-	0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x00c8, 0x13e1, 0x2110,
-	0xa006, 0x700e, 0x7212, 0x8203, 0x7822, 0x7803, 0x0020, 0x7803,
-	0x0041, 0x027f, 0x017f, 0x007c, 0x017e, 0x027e, 0x137e, 0x147e,
-	0x157e, 0x7014, 0x2098, 0x20a1, 0x0014, 0x7803, 0x0026, 0x710c,
-	0x2011, 0x0040, 0xa182, 0x0040, 0x00c8, 0x1400, 0x2110, 0xa006,
-	0x700e, 0x22a8, 0x53a6, 0x8203, 0x7822, 0x7803, 0x0020, 0x7803,
-	0x0001, 0x3300, 0x7016, 0x157f, 0x147f, 0x137f, 0x027f, 0x017f,
-	0x007c, 0x137e, 0x147e, 0x157e, 0x2099, 0x77e5, 0x20a1, 0x0018,
-	0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x127e, 0x2091, 0x8000,
-	0x7803, 0x0041, 0x7007, 0x0003, 0x7000, 0xc084, 0x7002, 0x700b,
-	0x77e0, 0x127f, 0x157f, 0x147f, 0x137f, 0x007c, 0x137e, 0x147e,
-	0x157e, 0x2001, 0x7814, 0x209c, 0x20a1, 0x0014, 0x7803, 0x0026,
-	0x2001, 0x7815, 0x20ac, 0x53a6, 0x2099, 0x7816, 0x20a1, 0x0018,
-	0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x127e, 0x2091, 0x8000,
-	0x7803, 0x0001, 0x7007, 0x0004, 0x7000, 0xc08c, 0x7002, 0x700b,
-	0x7811, 0x127f, 0x157f, 0x147f, 0x137f, 0x007c, 0x017e, 0x0e7e,
-	0x2071, 0x7959, 0x0f7e, 0x2079, 0x0010, 0x7904, 0x7803, 0x0002,
-	0xd1fc, 0x0040, 0x1471, 0xa18c, 0x0700, 0x0040, 0x146e, 0x7008,
-	0xa080, 0x0002, 0x2003, 0x0200, 0x0078, 0x1471, 0x7004, 0x1079,
-	0x1475, 0x0f7f, 0x0e7f, 0x017f, 0x007c, 0x13a0, 0x147d, 0x149f,
-	0x14b9, 0x14e2, 0x147b, 0x0078, 0x147b, 0x137e, 0x147e, 0x157e,
-	0x7014, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x7010, 0x20a8,
-	0x53a5, 0x3400, 0x7016, 0x157f, 0x147f, 0x137f, 0x700c, 0xa005,
-	0x0040, 0x14a6, 0x1078, 0x13d6, 0x007c, 0x7008, 0xa080, 0x0002,
-	0x2003, 0x0100, 0x7007, 0x0000, 0x1078, 0x13a0, 0x007c, 0x700c,
-	0xa005, 0x0040, 0x14a6, 0x1078, 0x13ec, 0x007c, 0x0d7e, 0x7008,
-	0x2068, 0x7830, 0x6826, 0x7834, 0x682a, 0x7838, 0x682e, 0x783c,
-	0x6832, 0x680b, 0x0100, 0x0d7f, 0x7007, 0x0000, 0x1078, 0x13a0,
-	0x007c, 0x137e, 0x147e, 0x157e, 0x2001, 0x77e3, 0x2004, 0xa080,
+	0x6572, 0x7369, 0x6f6e, 0x2030, 0x312e, 0x3137, 0x2020, 0x2020,
+	0x2400, 0x2091, 0x2000, 0x20c1, 0x0021, 0x2039, 0xffff, 0x2019,
+	0xaaaa, 0x2760, 0x2069, 0x7fff, 0x20c1, 0x0020, 0x2c2c, 0x2d34,
+	0x2762, 0x236a, 0x2c24, 0x2d04, 0x266a, 0x2562, 0xa406, 0x00c0,
+	0x104e, 0x20c1, 0x0021, 0x2c2c, 0x2362, 0x2c04, 0x2562, 0xa306,
+	0x0040, 0x104e, 0x20c1, 0x0020, 0x2039, 0x8fff, 0x20a1, 0x8f00,
+	0x2708, 0x810d, 0x810d, 0x810d, 0x810d, 0xa18c, 0x000f, 0x2001,
+	0x0008, 0xa112, 0xa00e, 0x21a8, 0x41a4, 0x3400, 0x8211, 0x00c0,
+	0x105b, 0x2708, 0x3400, 0xa102, 0x0040, 0x106b, 0x0048, 0x106b,
+	0x20a8, 0xa00e, 0x41a4, 0x20a1, 0x87a0, 0x2009, 0x0000, 0x20a9,
+	0x0760, 0x41a4, 0x3400, 0x20c9, 0x8cff, 0x2059, 0x0000, 0x2b78,
+	0x7823, 0x0004, 0x2089, 0x226f, 0x2051, 0x8800, 0x2a70, 0x775e,
+	0xa786, 0x8fff, 0x0040, 0x108e, 0x705b, 0xa700, 0x7057, 0xa6f5,
+	0x7063, 0x0200, 0x7067, 0x0200, 0x0078, 0x1096, 0x7057, 0x9b01,
+	0x7063, 0x0100, 0x7067, 0x0100, 0x705b, 0x9b00, 0x1078, 0x128f,
+	0x1078, 0x136a, 0x1078, 0x1513, 0x1078, 0x1b00, 0x1078, 0x3d25,
+	0x1078, 0x68a0, 0x1078, 0x12f5, 0x1078, 0x26b2, 0x1078, 0x4778,
+	0x1078, 0x42aa, 0x1078, 0x5004, 0x1078, 0x1fc3, 0x1078, 0x5260,
+	0x1078, 0x4cb7, 0x1078, 0x1ee5, 0x1078, 0x1fa0, 0x2091, 0x3009,
+	0x7823, 0x0000, 0x0090, 0x10cb, 0x7820, 0xa086, 0x0002, 0x00c0,
+	0x10cb, 0x7823, 0x4000, 0x0068, 0x10c3, 0x781b, 0x0001, 0x2091,
+	0x5000, 0x2091, 0x4080, 0x2a70, 0x7003, 0x0000, 0x2001, 0x017f,
+	0x2003, 0x0000, 0x2a70, 0x7000, 0xa08e, 0x0003, 0x00c0, 0x10eb,
+	0x1078, 0x31bd, 0x1078, 0x26da, 0x1078, 0x47c8, 0x1078, 0x4469,
+	0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0048, 0x10ef, 0x1078,
+	0x5020, 0x0078, 0x10d2, 0x1079, 0x10f3, 0x0078, 0x10d8, 0x1078,
+	0x6565, 0x0078, 0x10e7, 0x10fd, 0x10fe, 0x1189, 0x10fb, 0x1208,
+	0x128c, 0x128d, 0x128e, 0x1078, 0x12d2, 0x007c, 0x127e, 0x0f7e,
+	0x2091, 0x8000, 0x1078, 0x3541, 0x2079, 0x0100, 0x7844, 0xa005,
+	0x00c0, 0x117a, 0x2011, 0x3c35, 0x1078, 0x50f2, 0x780f, 0x00ff,
+	0x7840, 0xa084, 0xfffb, 0x7842, 0x2011, 0x8010, 0x73bc, 0x1078,
+	0x317a, 0x7238, 0xc284, 0x723a, 0x2001, 0x880c, 0x2014, 0xc2ac,
+	0x2202, 0x1078, 0x6376, 0x2011, 0x0004, 0x1078, 0x7802, 0x1078,
+	0x4236, 0x1078, 0x3d0d, 0x0040, 0x1135, 0x7083, 0x0001, 0x70b7,
+	0x0000, 0x1078, 0x36ef, 0x0078, 0x117a, 0x70cb, 0x0000, 0x70c7,
+	0x0000, 0x706b, 0x0000, 0x706f, 0x0000, 0x1078, 0x117d, 0x72c0,
+	0x2079, 0x8851, 0x7804, 0xd0ac, 0x0040, 0x1147, 0xc295, 0x72c2,
+	0xa296, 0x0004, 0x0040, 0x1168, 0x2011, 0x0001, 0x1078, 0x7802,
+	0x708f, 0x0000, 0x7093, 0xffff, 0x7003, 0x0002, 0x0f7f, 0x1078,
+	0x231f, 0x2011, 0x0005, 0x1078, 0x64ae, 0x1078, 0x5888, 0x0c7e,
+	0x2061, 0x0100, 0x60e3, 0x0008, 0x0c7f, 0x127f, 0x0078, 0x117c,
+	0x708f, 0x0000, 0x7093, 0xffff, 0x7003, 0x0002, 0x2011, 0x0005,
+	0x1078, 0x64ae, 0x1078, 0x5888, 0x0c7e, 0x2061, 0x0100, 0x60e3,
+	0x0008, 0x0c7f, 0x0f7f, 0x127f, 0x007c, 0x0c7e, 0x20a9, 0x0082,
+	0x2009, 0x007e, 0x1078, 0x3f76, 0x8108, 0x00f0, 0x1182, 0x0c7f,
+	0x007c, 0x127e, 0x2091, 0x8000, 0x7090, 0xa086, 0xffff, 0x0040,
+	0x1197, 0x1078, 0x231f, 0x1078, 0x5888, 0x0078, 0x1206, 0x70c0,
+	0xd09c, 0x0040, 0x11c3, 0xd084, 0x0040, 0x11c3, 0x0f7e, 0x2079,
+	0x0100, 0x790c, 0xc1b5, 0x790e, 0x0f7f, 0xd08c, 0x0040, 0x11c3,
+	0x70c4, 0xa086, 0xffff, 0x0040, 0x11bf, 0x1078, 0x2449, 0x1078,
+	0x5888, 0x70c0, 0xd094, 0x00c0, 0x1206, 0x2011, 0x0001, 0x2019,
+	0x0000, 0x1078, 0x2481, 0x1078, 0x5888, 0x0078, 0x1206, 0x70c8,
+	0xa005, 0x00c0, 0x1206, 0x708c, 0xa005, 0x00c0, 0x1206, 0x2001,
+	0x8852, 0x2004, 0xd0ac, 0x0040, 0x11e9, 0x157e, 0x0c7e, 0x20a9,
+	0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x3f8e, 0x00c0, 0x11dc,
+	0x6000, 0xd0ec, 0x00c0, 0x11e4, 0x017f, 0x8108, 0x00f0, 0x11d3,
+	0x0c7f, 0x157f, 0x0078, 0x11e9, 0x017f, 0x0c7f, 0x157f, 0x0078,
+	0x1206, 0x7003, 0x0003, 0x7093, 0xffff, 0x2001, 0x0000, 0x1078,
+	0x21f3, 0x1078, 0x31f8, 0x2001, 0x8aa3, 0x2004, 0xa086, 0x0005,
+	0x00c0, 0x11fe, 0x2011, 0x0000, 0x1078, 0x64ae, 0x2011, 0x0000,
+	0x1078, 0x64b8, 0x1078, 0x5888, 0x1078, 0x5948, 0x127f, 0x007c,
+	0x017e, 0x0f7e, 0x127e, 0x2091, 0x8000, 0x2079, 0x0100, 0x2009,
+	0x00f7, 0x1078, 0x3cdc, 0x7940, 0xa18c, 0x0010, 0x7942, 0x7924,
+	0xd1b4, 0x0040, 0x121d, 0x7827, 0x0040, 0xd19c, 0x0040, 0x1222,
+	0x7827, 0x0008, 0x007e, 0x037e, 0x157e, 0x7900, 0xa18a, 0x0003,
+	0x0050, 0x1248, 0x7954, 0xd1ac, 0x00c0, 0x1248, 0x2009, 0x00f8,
+	0x1078, 0x3cdc, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, 0x09c4,
+	0x7820, 0xd09c, 0x00c0, 0x1240, 0x7824, 0xd0ac, 0x00c0, 0x127c,
+	0x00f0, 0x1238, 0x2001, 0x0001, 0x1078, 0x21f3, 0x0078, 0x1285,
+	0x7853, 0x0000, 0x782f, 0x0020, 0x20a9, 0x0050, 0x00e0, 0x124e,
+	0x2091, 0x6000, 0x00f0, 0x124e, 0x7853, 0x0400, 0x782f, 0x0000,
+	0x2009, 0x00f8, 0x1078, 0x3cdc, 0x20a9, 0x000e, 0x0005, 0x00f0,
+	0x125e, 0x7853, 0x1400, 0x7843, 0x0090, 0x7843, 0x0010, 0x2019,
+	0x61a8, 0x7854, 0x0005, 0x0005, 0xd08c, 0x0040, 0x1273, 0x7824,
+	0xd0ac, 0x00c0, 0x127c, 0x8319, 0x00c0, 0x1269, 0x2001, 0x0001,
+	0x1078, 0x21f3, 0x0078, 0x1283, 0x7828, 0xc09d, 0x782a, 0x7827,
+	0x0008, 0x7827, 0x0040, 0x7853, 0x0400, 0x157f, 0x037f, 0x007f,
+	0x127f, 0x0f7f, 0x017f, 0x007c, 0x007c, 0x007c, 0x007c, 0x2a70,
+	0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0048, 0x129b, 0x704f,
+	0xffff, 0x0078, 0x129d, 0x704f, 0x0000, 0x7053, 0xffff, 0x706b,
+	0x0000, 0x706f, 0x0000, 0x2061, 0x8a8c, 0x6003, 0x0909, 0x6007,
+	0x0000, 0x600b, 0x8800, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017,
+	0x0003, 0x601b, 0x0000, 0x601f, 0x07d0, 0x2061, 0x8a94, 0x6003,
+	0x8000, 0x6007, 0x0000, 0x600b, 0x0000, 0x600f, 0x0200, 0x6013,
+	0x00ff, 0x6017, 0x0000, 0x601b, 0x0001, 0x601f, 0x0000, 0x2061,
+	0x8a9c, 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b, 0x4943, 0x600f,
+	0x2020, 0x007c, 0x2091, 0x8000, 0x0068, 0x12d4, 0x007e, 0x017e,
+	0x2079, 0x0000, 0x7818, 0xd084, 0x00c0, 0x12da, 0x017f, 0x792e,
+	0x007f, 0x782a, 0x007f, 0x7826, 0x3900, 0x783a, 0x7823, 0x8002,
+	0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2079, 0x8800,
+	0x7803, 0x0005, 0x0078, 0x12f2, 0x007c, 0x2071, 0x8800, 0x7158,
+	0x712e, 0x2021, 0x0001, 0xa190, 0x002d, 0xa298, 0x002d, 0x0048,
+	0x130b, 0x705c, 0xa302, 0x00c8, 0x130b, 0x220a, 0x2208, 0x2310,
+	0x8420, 0x0078, 0x12fd, 0x200b, 0x0000, 0x74a2, 0x74a6, 0x007c,
+	0x0e7e, 0x127e, 0x2091, 0x8000, 0x2071, 0x8800, 0x70a4, 0xa0ea,
+	0x0010, 0x00c8, 0x131e, 0xa06e, 0x0078, 0x1328, 0x8001, 0x70a6,
+	0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000,
+	0x127f, 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0x8800, 0x127e, 0x2091,
+	0x8000, 0x70a4, 0x8001, 0x00c8, 0x1338, 0xa06e, 0x0078, 0x1341,
+	0x70a6, 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807,
+	0x0000, 0x127f, 0x0e7f, 0x007c, 0x0e7e, 0x127e, 0x2091, 0x8000,
+	0x2071, 0x8800, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70a4, 0x8000,
+	0x70a6, 0x127f, 0x0e7f, 0x007c, 0x8dff, 0x0040, 0x1360, 0x6804,
+	0x6807, 0x0000, 0x007e, 0x1078, 0x1344, 0x0d7f, 0x0078, 0x1354,
+	0x007c, 0x0e7e, 0x2071, 0x8800, 0x70a4, 0xa08a, 0x0010, 0xa00d,
+	0x0e7f, 0x007c, 0x0e7e, 0x2071, 0x8ac7, 0x7007, 0x0000, 0x701b,
+	0x0000, 0x701f, 0x0000, 0x2071, 0x0000, 0x7010, 0xa085, 0x8004,
+	0x7012, 0x0e7f, 0x007c, 0x0e7e, 0x2270, 0x700b, 0x0000, 0x2071,
+	0x8ac7, 0x7018, 0xa088, 0x8ad0, 0x220a, 0x8000, 0xa084, 0x0007,
+	0x701a, 0x7004, 0xa005, 0x00c0, 0x1393, 0x0f7e, 0x2079, 0x0010,
+	0x1078, 0x13a4, 0x0f7f, 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0x8ac7,
+	0x7004, 0xa005, 0x00c0, 0x13a2, 0x0f7e, 0x2079, 0x0010, 0x1078,
+	0x13a4, 0x0f7f, 0x0e7f, 0x007c, 0x7000, 0x0079, 0x13a7, 0x13ab,
+	0x1415, 0x1432, 0x1432, 0x7018, 0x711c, 0xa106, 0x00c0, 0x13b3,
+	0x7007, 0x0000, 0x007c, 0x0d7e, 0xa180, 0x8ad0, 0x2004, 0x700a,
+	0x2068, 0x8108, 0xa18c, 0x0007, 0x711e, 0x7803, 0x0026, 0x6824,
+	0x7832, 0x6828, 0x7836, 0x682c, 0x783a, 0x6830, 0x783e, 0x6810,
+	0x700e, 0x680c, 0x7016, 0x6804, 0x0d7f, 0xd084, 0x0040, 0x13d5,
+	0x7007, 0x0001, 0x1078, 0x13da, 0x007c, 0x7007, 0x0002, 0x1078,
+	0x13f0, 0x007c, 0x017e, 0x027e, 0x710c, 0x2011, 0x0040, 0xa182,
+	0x0040, 0x00c8, 0x13e5, 0x2110, 0xa006, 0x700e, 0x7212, 0x8203,
+	0x7822, 0x7803, 0x0020, 0x7803, 0x0041, 0x027f, 0x017f, 0x007c,
+	0x017e, 0x027e, 0x137e, 0x147e, 0x157e, 0x7014, 0x2098, 0x20a1,
+	0x0014, 0x7803, 0x0026, 0x710c, 0x2011, 0x0040, 0xa182, 0x0040,
+	0x00c8, 0x1404, 0x2110, 0xa006, 0x700e, 0x22a8, 0x53a6, 0x8203,
+	0x7822, 0x7803, 0x0020, 0x3300, 0x7016, 0x7803, 0x0001, 0x157f,
+	0x147f, 0x137f, 0x027f, 0x017f, 0x007c, 0x137e, 0x147e, 0x157e,
+	0x2099, 0x88f9, 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803,
+	0x0020, 0x127e, 0x2091, 0x8000, 0x7803, 0x0041, 0x7007, 0x0003,
+	0x7000, 0xc084, 0x7002, 0x700b, 0x88f4, 0x127f, 0x157f, 0x147f,
+	0x137f, 0x007c, 0x137e, 0x147e, 0x157e, 0x2001, 0x8928, 0x209c,
+	0x20a1, 0x0014, 0x7803, 0x0026, 0x2001, 0x8929, 0x20ac, 0x53a6,
+	0x2099, 0x892a, 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803,
+	0x0020, 0x127e, 0x2091, 0x8000, 0x7803, 0x0001, 0x7007, 0x0004,
+	0x7000, 0xc08c, 0x7002, 0x700b, 0x8925, 0x127f, 0x157f, 0x147f,
+	0x137f, 0x007c, 0x017e, 0x0e7e, 0x2071, 0x8ac7, 0x0f7e, 0x2079,
+	0x0010, 0x7904, 0x7803, 0x0002, 0xd1fc, 0x0040, 0x146c, 0xa18c,
+	0x0700, 0x7004, 0x1079, 0x1470, 0x0f7f, 0x0e7f, 0x017f, 0x007c,
+	0x13a4, 0x1478, 0x14a5, 0x14cd, 0x1500, 0x1476, 0x0078, 0x1476,
+	0xa18c, 0x0700, 0x00c0, 0x149e, 0x137e, 0x147e, 0x157e, 0x7014,
+	0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x7010, 0x20a8, 0x53a5,
+	0x3400, 0x7016, 0x157f, 0x147f, 0x137f, 0x700c, 0xa005, 0x0040,
+	0x14ba, 0x1078, 0x13da, 0x007c, 0x7008, 0xa080, 0x0002, 0x2003,
+	0x0100, 0x7007, 0x0000, 0x1078, 0x13a4, 0x007c, 0x7008, 0xa080,
+	0x0002, 0x2003, 0x0200, 0x0078, 0x1499, 0xa18c, 0x0700, 0x00c0,
+	0x14b0, 0x700c, 0xa005, 0x0040, 0x14ba, 0x1078, 0x13f0, 0x007c,
+	0x7008, 0xa080, 0x0002, 0x2003, 0x0200, 0x7007, 0x0000, 0x1078,
+	0x13a4, 0x007c, 0x0d7e, 0x7008, 0x2068, 0x7830, 0x6826, 0x7834,
+	0x682a, 0x7838, 0x682e, 0x783c, 0x6832, 0x680b, 0x0100, 0x0d7f,
+	0x7007, 0x0000, 0x1078, 0x13a4, 0x007c, 0xa18c, 0x0700, 0x00c0,
+	0x14fa, 0x137e, 0x147e, 0x157e, 0x2001, 0x88f7, 0x2004, 0xa080,
 	0x000d, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x20a9, 0x0020,
-	0x53a5, 0x2001, 0x77e5, 0x2004, 0xd0bc, 0x0040, 0x14d8, 0x2001,
-	0x77ee, 0x2004, 0xa080, 0x000d, 0x20a0, 0x20a9, 0x0020, 0x53a5,
-	0x157f, 0x147f, 0x137f, 0x7007, 0x0000, 0x1078, 0x3e67, 0x1078,
-	0x13a0, 0x007c, 0x2001, 0x7813, 0x2003, 0x0100, 0x7007, 0x0000,
-	0x1078, 0x13a0, 0x007c, 0x127e, 0x2091, 0x2100, 0x2079, 0x0030,
-	0x2071, 0x796a, 0x7003, 0x0000, 0x700f, 0x7970, 0x7013, 0x7970,
-	0x780f, 0x0070, 0x127f, 0x007c, 0x6934, 0xa184, 0x0007, 0x0079,
-	0x1501, 0x1509, 0x154f, 0x1509, 0x1509, 0x1509, 0x1534, 0x1518,
-	0x150d, 0xa085, 0x0001, 0x0078, 0x1569, 0x684c, 0xd0bc, 0x0040,
-	0x1509, 0x6860, 0x682e, 0x685c, 0x682a, 0x6858, 0x0078, 0x1557,
-	0xa18c, 0x00ff, 0xa186, 0x001e, 0x00c0, 0x1509, 0x684c, 0xd0bc,
-	0x0040, 0x1509, 0x6860, 0x682e, 0x685c, 0x682a, 0x6804, 0x681a,
-	0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x1c7e, 0x2004,
-	0x6832, 0x6858, 0x0078, 0x155f, 0xa18c, 0x00ff, 0xa186, 0x0015,
-	0x00c0, 0x1509, 0x684c, 0xd0ac, 0x0040, 0x1509, 0x6804, 0x681a,
-	0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x1c7e, 0x2004,
-	0x6832, 0xa006, 0x682e, 0x682a, 0x6858, 0x0078, 0x155f, 0x684c,
-	0xd0ac, 0x0040, 0x1509, 0xa006, 0x682e, 0x682a, 0x6858, 0xa18c,
-	0x000f, 0xa188, 0x1c7e, 0x210c, 0x6932, 0x2d08, 0x691a, 0x6826,
-	0x684c, 0xc0dd, 0x684e, 0xa006, 0x680a, 0x697c, 0x6912, 0x6980,
-	0x6916, 0x007c, 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001, 0x020a,
-	0x2004, 0x82ff, 0x0040, 0x1584, 0xa280, 0x0004, 0x0d7e, 0x206c,
-	0x684c, 0xd0dc, 0x00c0, 0x1580, 0x1078, 0x14fc, 0x10c0, 0x12cd,
-	0x6808, 0x8000, 0x680a, 0x0d7f, 0x127e, 0x047e, 0x037e, 0x027e,
-	0x2091, 0x2100, 0x027f, 0x037f, 0x047f, 0x7000, 0xa005, 0x00c0,
-	0x1598, 0x7206, 0x2001, 0x15ac, 0x007e, 0x2260, 0x0078, 0x16c4,
-	0x710c, 0x220a, 0x8108, 0x230a, 0x8108, 0x240a, 0x8108, 0xa182,
-	0x798b, 0x0048, 0x15a5, 0x2009, 0x7970, 0x710e, 0x7000, 0xa005,
-	0x00c0, 0x15ac, 0x1078, 0x16ad, 0x127f, 0x007c, 0x127e, 0x027e,
-	0x037e, 0x0c7e, 0x007e, 0x2091, 0x2100, 0x007f, 0x047f, 0x037f,
-	0x027f, 0x0d7e, 0x0c7e, 0x2460, 0x6110, 0x2168, 0x6a62, 0x6b5e,
-	0xa005, 0x0040, 0x1600, 0x6808, 0xa005, 0x0040, 0x1666, 0x7000,
-	0xa005, 0x00c0, 0x15cd, 0x0078, 0x15fa, 0x700c, 0x7110, 0xa106,
-	0x00c0, 0x166a, 0x7004, 0xa406, 0x00c0, 0x15fa, 0x2001, 0x0005,
-	0x2004, 0xd08c, 0x0040, 0x15e3, 0x047e, 0x1078, 0x1785, 0x047f,
-	0x2460, 0x0078, 0x15c3, 0x2001, 0x0207, 0x2004, 0xd09c, 0x00c0,
-	0x15d6, 0x7804, 0xa084, 0x6000, 0x0040, 0x15f4, 0xa086, 0x6000,
-	0x0040, 0x15f4, 0x0078, 0x15d6, 0x7803, 0x0004, 0x7003, 0x0000,
-	0x7004, 0x2060, 0x2009, 0x0048, 0x1078, 0x5d41, 0x0078, 0x166a,
-	0x6808, 0xa005, 0x0040, 0x1666, 0x7000, 0xa005, 0x00c0, 0x160a,
-	0x0078, 0x1666, 0x700c, 0x7110, 0xa106, 0x00c0, 0x1613, 0x7004,
-	0xa406, 0x00c0, 0x1666, 0x2001, 0x0005, 0x2004, 0xd08c, 0x0040,
-	0x1620, 0x047e, 0x1078, 0x1785, 0x047f, 0x2460, 0x0078, 0x1600,
-	0x2001, 0x0207, 0x2004, 0xd09c, 0x00c0, 0x1613, 0x2001, 0x0005,
-	0x2004, 0xd08c, 0x00c0, 0x1619, 0x7804, 0xa084, 0x6000, 0x0040,
-	0x1637, 0xa086, 0x6000, 0x0040, 0x1637, 0x0078, 0x1613, 0x7007,
-	0x0000, 0xa016, 0x2218, 0x7000, 0xa08e, 0x0001, 0x0040, 0x1658,
-	0xa08e, 0x0002, 0x00c0, 0x1666, 0x0c7e, 0x0e7e, 0x6818, 0x2060,
-	0x1078, 0x1c53, 0x2804, 0xac70, 0x6034, 0xd09c, 0x00c0, 0x1654,
-	0x7308, 0x720c, 0x0078, 0x1656, 0x7310, 0x7214, 0x0e7f, 0x0c7f,
-	0x7820, 0xa318, 0x7824, 0xa211, 0x6810, 0xa300, 0x6812, 0x6814,
-	0xa201, 0x6816, 0x7803, 0x0004, 0x7003, 0x0000, 0x2009, 0x0048,
-	0x1078, 0x5d41, 0x0c7f, 0x0d7f, 0x127f, 0x007c, 0x0f7e, 0x0e7e,
-	0x2071, 0x796a, 0x7000, 0xa086, 0x0000, 0x0040, 0x16aa, 0x7004,
-	0xac06, 0x00c0, 0x169b, 0x2079, 0x0030, 0x7804, 0xd0fc, 0x00c0,
-	0x1697, 0x2001, 0x0207, 0x2004, 0xd09c, 0x00c0, 0x167d, 0x7803,
-	0x0004, 0x7804, 0xd0ac, 0x00c0, 0x1689, 0x7803, 0x0002, 0x7803,
-	0x0009, 0x7003, 0x0003, 0x7007, 0x0000, 0x0078, 0x169b, 0x1078,
-	0x1785, 0x0078, 0x1672, 0x157e, 0x20a9, 0x0009, 0x2009, 0x7970,
-	0x2104, 0xac06, 0x00c0, 0x16a5, 0x200a, 0xa188, 0x0003, 0x00f0,
-	0x16a0, 0x157f, 0x0e7f, 0x0f7f, 0x007c, 0x700c, 0x7110, 0xa106,
-	0x00c0, 0x16b5, 0x7003, 0x0000, 0x007c, 0x2104, 0x7006, 0x2060,
-	0x8108, 0x211c, 0x8108, 0x2124, 0x8108, 0xa182, 0x798b, 0x0048,
-	0x16c3, 0x2009, 0x7970, 0x7112, 0x8cff, 0x00c0, 0x16cb, 0x1078,
-	0x1950, 0x0078, 0x16f2, 0x6010, 0x2068, 0x2d58, 0x6828, 0xa406,
-	0x00c0, 0x16d6, 0x682c, 0xa306, 0x0040, 0x16da, 0x1078, 0x1c9e,
-	0x00c0, 0x16c7, 0x684c, 0xd0f4, 0x00c0, 0x16c7, 0x6824, 0x2050,
-	0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, 0x000f, 0x2009,
-	0x0011, 0x1078, 0x16f3, 0x0040, 0x16f1, 0x2009, 0x0001, 0x1078,
-	0x16f3, 0x2d58, 0x007c, 0x8aff, 0x0040, 0x1780, 0xa03e, 0x2730,
-	0x6850, 0xd0fc, 0x00c0, 0x1712, 0x0d7e, 0x2804, 0xac68, 0x2900,
-	0x0079, 0x1702, 0x1762, 0x1722, 0x1722, 0x1762, 0x1762, 0x175a,
-	0x1762, 0x1722, 0x1762, 0x1728, 0x1728, 0x1762, 0x1762, 0x1762,
-	0x1751, 0x1728, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20,
-	0x0d7e, 0xd99c, 0x0040, 0x1765, 0x2804, 0xac68, 0x6f08, 0x6e0c,
-	0x0078, 0x1765, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x0078, 0x1765,
-	0x7b0c, 0xd3bc, 0x0040, 0x1749, 0x7004, 0x0e7e, 0x2070, 0x701c,
-	0x0e7f, 0xa086, 0x0008, 0x00c0, 0x1749, 0x7b08, 0xa39c, 0x0fff,
-	0x2d20, 0x0d7f, 0x0d7e, 0x6a14, 0x82ff, 0x00c0, 0x1744, 0x6810,
-	0xa302, 0x0048, 0x1744, 0x6b10, 0x2011, 0x0000, 0x2468, 0x0078,
-	0x174b, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0078,
-	0x1765, 0x0d7f, 0x0d7e, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e,
-	0x00c0, 0x1762, 0x0d7f, 0x1078, 0x1c3a, 0x00c0, 0x16f3, 0xa00e,
-	0x0078, 0x1780, 0x0d7f, 0x1078, 0x12cd, 0x7b22, 0x7a26, 0x7d32,
-	0x7c36, 0x7f3a, 0x7e3e, 0x7902, 0x7000, 0x8000, 0x7002, 0x0d7f,
-	0x6828, 0xa300, 0x682a, 0x682c, 0xa201, 0x682e, 0x2300, 0x6b10,
-	0xa302, 0x6812, 0x2200, 0x6a14, 0xa203, 0x6816, 0x1078, 0x1c3a,
-	0x007c, 0x1078, 0x12cd, 0x1078, 0x12cd, 0x127e, 0x2091, 0x2100,
-	0x007e, 0x017e, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002,
-	0xa184, 0x0700, 0x00c0, 0x1783, 0xa184, 0x0003, 0xa086, 0x0003,
-	0x0040, 0x1783, 0x7000, 0x0079, 0x179d, 0x17a5, 0x17a7, 0x187f,
-	0x18e7, 0x18fe, 0x17a5, 0x17a5, 0x17a5, 0x1078, 0x12cd, 0x8001,
-	0x7002, 0xa184, 0x0880, 0x00c0, 0x17bc, 0x8aff, 0x0040, 0x181f,
-	0x2009, 0x0001, 0x1078, 0x16f3, 0x0040, 0x1910, 0x2009, 0x0001,
-	0x1078, 0x16f3, 0x0078, 0x1910, 0x7803, 0x0004, 0x7003, 0x0000,
-	0xd1bc, 0x00c0, 0x1807, 0x027e, 0x037e, 0x6b28, 0x6a2c, 0x7820,
-	0x686e, 0xa31a, 0x7824, 0x6872, 0xa213, 0x6b2a, 0x6a2e, 0x7820,
-	0x6910, 0xa100, 0x6812, 0x7824, 0x6914, 0xa101, 0x6816, 0x037f,
-	0x027f, 0x7830, 0x681e, 0x7834, 0x6822, 0x1078, 0x1c53, 0x2a00,
-	0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, 0x0000, 0x6850,
-	0xc0fd, 0x6852, 0x6808, 0x8001, 0x680a, 0x00c0, 0x17f9, 0x684c,
-	0xd0e4, 0x0040, 0x17f9, 0x7004, 0x2060, 0x2009, 0x0048, 0x1078,
-	0x5d41, 0x7808, 0xd0ec, 0x00c0, 0x1803, 0x7803, 0x0009, 0x7003,
-	0x0004, 0x0078, 0x1910, 0x1078, 0x16ad, 0x0078, 0x1910, 0x057e,
-	0x7d0c, 0xd5bc, 0x00c0, 0x180e, 0x1078, 0x7692, 0x057f, 0x1078,
-	0x1914, 0x682b, 0xffff, 0x682f, 0xffff, 0x697c, 0x6912, 0x6980,
-	0x6916, 0x7803, 0x0009, 0x7003, 0x0003, 0x0078, 0x1910, 0x684c,
-	0xc0f5, 0x684e, 0x7814, 0xa005, 0x00c0, 0x1837, 0x7003, 0x0000,
-	0x6808, 0x8001, 0x680a, 0x00c0, 0x1833, 0x7004, 0x2060, 0x2009,
-	0x0048, 0x1078, 0x5d41, 0x1078, 0x16ad, 0x0078, 0x1910, 0x7814,
-	0x6910, 0xa102, 0x6812, 0x6914, 0xa183, 0x0000, 0x6816, 0x7814,
-	0x7908, 0xa18c, 0x0fff, 0xa188, 0x0007, 0x8114, 0x8214, 0x8214,
-	0xa10a, 0x8104, 0x8004, 0x8004, 0xa20a, 0x810b, 0x810b, 0x810b,
-	0x1078, 0x197b, 0x7803, 0x0004, 0x780f, 0xffff, 0x7803, 0x0001,
-	0x7804, 0xd0fc, 0x0040, 0x1858, 0x7803, 0x0002, 0x7803, 0x0004,
-	0x780f, 0x0070, 0x7004, 0x7007, 0x0000, 0x2060, 0x2009, 0x0048,
-	0x1078, 0x5d41, 0x1078, 0x199e, 0x0040, 0x1833, 0x7908, 0xd1ec,
-	0x00c0, 0x1876, 0x2009, 0x0009, 0x0078, 0x1878, 0x2009, 0x0019,
-	0x7902, 0x7803, 0x0009, 0x7003, 0x0003, 0x0078, 0x1910, 0x8001,
-	0x7002, 0xd194, 0x0040, 0x1891, 0x7804, 0xd0fc, 0x00c0, 0x178d,
-	0x8aff, 0x0040, 0x1910, 0x2009, 0x0001, 0x1078, 0x16f3, 0x0078,
-	0x1910, 0xa184, 0x0880, 0x00c0, 0x189e, 0x8aff, 0x0040, 0x1910,
-	0x2009, 0x0001, 0x1078, 0x16f3, 0x0078, 0x1910, 0x7803, 0x0004,
-	0x7003, 0x0000, 0xd1bc, 0x00c0, 0x18d2, 0x027e, 0x037e, 0x6b28,
-	0x6a2c, 0x1078, 0x1c53, 0x0d7e, 0x0f7e, 0x2d78, 0x2804, 0xac68,
-	0x6034, 0xd09c, 0x00c0, 0x18c2, 0x6808, 0x2008, 0xa31a, 0x680c,
-	0xa213, 0x7810, 0xa100, 0x7812, 0x690c, 0x7814, 0xa101, 0x7816,
-	0x0078, 0x18ce, 0x6810, 0x2008, 0xa31a, 0x6814, 0xa213, 0x7810,
-	0xa100, 0x7812, 0x6914, 0x7814, 0xa101, 0x7816, 0x0f7f, 0x0d7f,
-	0x0078, 0x17c7, 0x057e, 0x7d0c, 0x1078, 0x7692, 0x057f, 0x1078,
-	0x1914, 0x682b, 0xffff, 0x682f, 0xffff, 0x697c, 0x6912, 0x6980,
-	0x6916, 0x7803, 0x0009, 0x7003, 0x0003, 0x0078, 0x1910, 0x7803,
-	0x0004, 0x7003, 0x0000, 0x7004, 0xa00d, 0x0040, 0x18fa, 0x6808,
-	0x8001, 0x680a, 0x00c0, 0x18fa, 0x7004, 0x2060, 0x2009, 0x0048,
-	0x1078, 0x5d41, 0x1078, 0x16ad, 0x0078, 0x1910, 0x7803, 0x0004,
-	0x7003, 0x0000, 0x7004, 0x2060, 0x6010, 0xa005, 0x0040, 0x18fa,
-	0x2068, 0x6808, 0x8000, 0x680a, 0x6c28, 0x6b2c, 0x1078, 0x16c4,
-	0x017f, 0x007f, 0x127f, 0x007c, 0x1078, 0x1925, 0x20e1, 0x9028,
-	0x700f, 0x7970, 0x7013, 0x7970, 0x2001, 0x015d, 0x200c, 0x810a,
-	0x2102, 0x2001, 0x0138, 0x2202, 0x007c, 0x2001, 0x0138, 0x2014,
+	0x53a5, 0x2001, 0x88f9, 0x2004, 0xd0bc, 0x0040, 0x14f0, 0x2001,
+	0x8902, 0x2004, 0xa080, 0x000d, 0x20a0, 0x20a9, 0x0020, 0x53a5,
+	0x157f, 0x147f, 0x137f, 0x7007, 0x0000, 0x1078, 0x4871, 0x1078,
+	0x13a4, 0x007c, 0x2011, 0x8003, 0x1078, 0x317a, 0x0078, 0x14fe,
+	0xa18c, 0x0700, 0x00c0, 0x150d, 0x2001, 0x8927, 0x2003, 0x0100,
+	0x7007, 0x0000, 0x1078, 0x13a4, 0x007c, 0x2011, 0x8004, 0x1078,
+	0x317a, 0x0078, 0x1511, 0x127e, 0x2091, 0x2100, 0x2079, 0x0030,
+	0x2071, 0x8ad8, 0x7803, 0x0004, 0x7003, 0x0000, 0x700f, 0x8ade,
+	0x7013, 0x8ade, 0x780f, 0x0076, 0x127f, 0x007c, 0x6934, 0xa184,
+	0x0007, 0x0079, 0x152b, 0x1533, 0x1579, 0x1533, 0x1533, 0x1533,
+	0x155e, 0x1542, 0x1537, 0xa085, 0x0001, 0x0078, 0x1593, 0x684c,
+	0xd0bc, 0x0040, 0x1533, 0x6860, 0x682e, 0x685c, 0x682a, 0x6858,
+	0x0078, 0x1581, 0xa18c, 0x00ff, 0xa186, 0x001e, 0x00c0, 0x1533,
+	0x684c, 0xd0bc, 0x0040, 0x1533, 0x6860, 0x682e, 0x685c, 0x682a,
+	0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080,
+	0x1def, 0x2004, 0x6832, 0x6858, 0x0078, 0x1589, 0xa18c, 0x00ff,
+	0xa186, 0x0015, 0x00c0, 0x1533, 0x684c, 0xd0ac, 0x0040, 0x1533,
+	0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080,
+	0x1def, 0x2004, 0x6832, 0xa006, 0x682e, 0x682a, 0x6858, 0x0078,
+	0x1589, 0x684c, 0xd0ac, 0x0040, 0x1533, 0xa006, 0x682e, 0x682a,
+	0x6858, 0xa18c, 0x000f, 0xa188, 0x1def, 0x210c, 0x6932, 0x2d08,
+	0x691a, 0x6826, 0x684c, 0xc0dd, 0x684e, 0xa006, 0x680a, 0x697c,
+	0x6912, 0x6980, 0x6916, 0x007c, 0x20e1, 0x0007, 0x20e1, 0x2000,
+	0x2001, 0x020a, 0x2004, 0x82ff, 0x0040, 0x15ae, 0xa280, 0x0004,
+	0x0d7e, 0x206c, 0x684c, 0xd0dc, 0x00c0, 0x15aa, 0x1078, 0x1526,
+	0x10c0, 0x12d2, 0x6808, 0x8000, 0x680a, 0x0d7f, 0x127e, 0x047e,
+	0x037e, 0x027e, 0x2091, 0x2100, 0x027f, 0x037f, 0x047f, 0x7000,
+	0xa005, 0x00c0, 0x15c2, 0x7206, 0x2001, 0x15e3, 0x007e, 0x2260,
+	0x0078, 0x1724, 0x710c, 0x220a, 0x8108, 0x230a, 0x8108, 0x240a,
+	0x8108, 0xa182, 0x8af9, 0x0048, 0x15cf, 0x2009, 0x8ade, 0x710e,
+	0x7010, 0xa102, 0xa082, 0x0009, 0x0040, 0x15da, 0xa080, 0x001b,
+	0x00c0, 0x15dd, 0x2009, 0x0138, 0x200a, 0x7000, 0xa005, 0x00c0,
+	0x15e3, 0x1078, 0x1705, 0x127f, 0x007c, 0x127e, 0x027e, 0x037e,
+	0x0c7e, 0x007e, 0x2091, 0x2100, 0x007f, 0x047f, 0x037f, 0x027f,
+	0x0d7e, 0x0c7e, 0x2460, 0x6110, 0x2168, 0x6a62, 0x6b5e, 0xa005,
+	0x0040, 0x163c, 0x6808, 0xa005, 0x0040, 0x16a2, 0x7000, 0xa005,
+	0x00c0, 0x1604, 0x0078, 0x1631, 0x700c, 0x7110, 0xa106, 0x00c0,
+	0x16ab, 0x7004, 0xa406, 0x00c0, 0x1631, 0x2001, 0x0005, 0x2004,
+	0xd08c, 0x0040, 0x161a, 0x047e, 0x1078, 0x1816, 0x047f, 0x2460,
+	0x0078, 0x15fa, 0x2001, 0x0207, 0x2004, 0xd09c, 0x00c0, 0x160d,
+	0x7804, 0xa084, 0x6000, 0x0040, 0x162b, 0xa086, 0x6000, 0x0040,
+	0x162b, 0x0078, 0x160d, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004,
+	0x2060, 0x6100, 0xa18e, 0x0004, 0x00c0, 0x16ab, 0x2009, 0x0048,
+	0x1078, 0x6939, 0x0078, 0x16ab, 0x6808, 0xa005, 0x0040, 0x16a2,
+	0x7000, 0xa005, 0x00c0, 0x1646, 0x0078, 0x16a2, 0x700c, 0x7110,
+	0xa106, 0x00c0, 0x164f, 0x7004, 0xa406, 0x00c0, 0x16a2, 0x2001,
+	0x0005, 0x2004, 0xd08c, 0x0040, 0x165c, 0x047e, 0x1078, 0x1816,
+	0x047f, 0x2460, 0x0078, 0x163c, 0x2001, 0x0207, 0x2004, 0xd09c,
+	0x00c0, 0x164f, 0x2001, 0x0005, 0x2004, 0xd08c, 0x00c0, 0x1655,
+	0x7804, 0xa084, 0x6000, 0x0040, 0x1673, 0xa086, 0x6000, 0x0040,
+	0x1673, 0x0078, 0x164f, 0x7007, 0x0000, 0xa016, 0x2218, 0x7000,
+	0xa08e, 0x0001, 0x0040, 0x1694, 0xa08e, 0x0002, 0x00c0, 0x16a2,
+	0x0c7e, 0x0e7e, 0x6818, 0x2060, 0x1078, 0x1dc4, 0x2804, 0xac70,
+	0x6034, 0xd09c, 0x00c0, 0x1690, 0x7308, 0x720c, 0x0078, 0x1692,
+	0x7310, 0x7214, 0x0e7f, 0x0c7f, 0x7820, 0xa318, 0x7824, 0xa211,
+	0x6810, 0xa300, 0x6812, 0x6814, 0xa201, 0x6816, 0x7803, 0x0004,
+	0x7003, 0x0000, 0x6100, 0xa18e, 0x0004, 0x00c0, 0x16ab, 0x2009,
+	0x0048, 0x1078, 0x6939, 0x0c7f, 0x0d7f, 0x127f, 0x007c, 0x0f7e,
+	0x0e7e, 0x027e, 0x037e, 0x047e, 0x1078, 0x19e5, 0x027e, 0x2071,
+	0x8ad8, 0x7000, 0xa086, 0x0000, 0x0040, 0x16f6, 0x7004, 0xac06,
+	0x00c0, 0x16e7, 0x2079, 0x0030, 0x7000, 0xa086, 0x0003, 0x0040,
+	0x16e7, 0x7804, 0xd0fc, 0x00c0, 0x16e3, 0x2001, 0x0207, 0x2004,
+	0xd09c, 0x00c0, 0x16c9, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x00c0,
+	0x16d5, 0x7803, 0x0002, 0x7803, 0x0009, 0x7003, 0x0003, 0x7007,
+	0x0000, 0x0078, 0x16e7, 0x1078, 0x1816, 0x0078, 0x16b9, 0x157e,
+	0x20a9, 0x0009, 0x2009, 0x8ade, 0x2104, 0xac06, 0x00c0, 0x16f1,
+	0x200a, 0xa188, 0x0003, 0x00f0, 0x16ec, 0x157f, 0x027f, 0x2001,
+	0x015d, 0x201c, 0x831a, 0x2302, 0x2001, 0x0138, 0x2202, 0x047f,
+	0x037f, 0x027f, 0x0e7f, 0x0f7f, 0x007c, 0x700c, 0x7110, 0xa106,
+	0x00c0, 0x170d, 0x7003, 0x0000, 0x007c, 0x2104, 0x7006, 0x2060,
+	0x8108, 0x211c, 0x8108, 0x2124, 0x8108, 0xa182, 0x8af9, 0x0048,
+	0x171b, 0x2009, 0x8ade, 0x7112, 0x700c, 0xa106, 0x00c0, 0x1724,
+	0x2001, 0x0138, 0x2003, 0x0008, 0x8cff, 0x00c0, 0x172b, 0x1078,
+	0x1a10, 0x0078, 0x1757, 0x6010, 0x2068, 0x2d58, 0x6828, 0xa406,
+	0x00c0, 0x1736, 0x682c, 0xa306, 0x0040, 0x173f, 0x601c, 0xa086,
+	0x0008, 0x0040, 0x173f, 0x1078, 0x1e0f, 0x00c0, 0x1727, 0x684c,
+	0xd0f4, 0x00c0, 0x1727, 0x6824, 0x2050, 0x6818, 0x2060, 0x6830,
+	0x2040, 0x6034, 0xa0cc, 0x000f, 0x2009, 0x0011, 0x1078, 0x1758,
+	0x0040, 0x1756, 0x2009, 0x0001, 0x1078, 0x1758, 0x2d58, 0x007c,
+	0x8aff, 0x0040, 0x17ef, 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x00c0,
+	0x177a, 0xd0f4, 0x00c0, 0x178a, 0x0d7e, 0x2804, 0xac68, 0x2900,
+	0x0079, 0x176a, 0x17d1, 0x1791, 0x1791, 0x17d1, 0x17d1, 0x17c9,
+	0x17d1, 0x1791, 0x17d1, 0x1797, 0x1797, 0x17d1, 0x17d1, 0x17d1,
+	0x17c0, 0x1797, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20,
+	0x0d7e, 0xd99c, 0x0040, 0x17d4, 0x2804, 0xac68, 0x6f08, 0x6e0c,
+	0x0078, 0x17d4, 0xc0f4, 0x6852, 0x6b6c, 0x6a70, 0x0d7e, 0x0078,
+	0x17db, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x0078, 0x17d4, 0x7b0c,
+	0xd3bc, 0x0040, 0x17b8, 0x7004, 0x0e7e, 0x2070, 0x701c, 0x0e7f,
+	0xa086, 0x0008, 0x00c0, 0x17b8, 0x7b08, 0xa39c, 0x0fff, 0x2d20,
+	0x0d7f, 0x0d7e, 0x6a14, 0x82ff, 0x00c0, 0x17b3, 0x6810, 0xa302,
+	0x0048, 0x17b3, 0x6b10, 0x2011, 0x0000, 0x2468, 0x0078, 0x17ba,
+	0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0078, 0x17d4,
+	0x0d7f, 0x0d7e, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x00c0,
+	0x17d1, 0x0d7f, 0x1078, 0x1dab, 0x00c0, 0x1758, 0xa00e, 0x0078,
+	0x17ef, 0x0d7f, 0x1078, 0x12d2, 0x7b22, 0x7a26, 0x7d32, 0x7c36,
+	0x7f3a, 0x7e3e, 0x7902, 0x7000, 0x8000, 0x7002, 0x0d7f, 0x6828,
+	0xa300, 0x682a, 0x682c, 0xa201, 0x682e, 0x2300, 0x6b10, 0xa302,
+	0x6812, 0x2200, 0x6a14, 0xa203, 0x6816, 0x1078, 0x1dab, 0x007c,
+	0x1078, 0x12d2, 0x7803, 0x0004, 0x7004, 0x2060, 0x0d7e, 0x6010,
+	0x2068, 0x7003, 0x0000, 0x1078, 0x19b4, 0x1078, 0x77ed, 0x0040,
+	0x180f, 0x6808, 0x8001, 0x680a, 0x697c, 0x6912, 0x6980, 0x6916,
+	0x682b, 0xffff, 0x682f, 0xffff, 0x6850, 0xc0bd, 0x6852, 0x0d7f,
+	0x1078, 0x759a, 0x0078, 0x19b0, 0x1078, 0x12d2, 0x127e, 0x2091,
+	0x2100, 0x007e, 0x017e, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803,
+	0x0002, 0xa184, 0x0700, 0x00c0, 0x17f2, 0xa184, 0x0003, 0xa086,
+	0x0003, 0x0040, 0x1814, 0x7000, 0x0079, 0x182e, 0x1836, 0x1838,
+	0x1914, 0x1987, 0x199e, 0x1836, 0x1836, 0x1836, 0x1078, 0x12d2,
+	0x8001, 0x7002, 0xa184, 0x0880, 0x00c0, 0x184d, 0x8aff, 0x0040,
+	0x18b6, 0x2009, 0x0001, 0x1078, 0x1758, 0x0040, 0x19b0, 0x2009,
+	0x0001, 0x1078, 0x1758, 0x0078, 0x19b0, 0x7803, 0x0004, 0x7003,
+	0x0000, 0xd1bc, 0x00c0, 0x189f, 0x027e, 0x037e, 0x7808, 0xd0ec,
+	0x00c0, 0x1860, 0x7803, 0x0009, 0x7003, 0x0004, 0x0078, 0x1862,
+	0x1078, 0x1a80, 0x6b28, 0x6a2c, 0x2400, 0x686e, 0xa31a, 0x2500,
+	0x6872, 0xa213, 0x6b2a, 0x6a2e, 0x2400, 0x6910, 0xa100, 0x6812,
+	0x2500, 0x6914, 0xa101, 0x6816, 0x037f, 0x027f, 0x2600, 0x681e,
+	0x2700, 0x6822, 0x1078, 0x1dc4, 0x2a00, 0x6826, 0x2c00, 0x681a,
+	0x2800, 0x6832, 0x6850, 0xc0fd, 0x6852, 0x6808, 0x8001, 0x680a,
+	0x00c0, 0x1894, 0x684c, 0xd0e4, 0x0040, 0x1894, 0x7004, 0x2060,
+	0x2009, 0x0048, 0x1078, 0x6939, 0x7000, 0xa086, 0x0004, 0x0040,
+	0x19b0, 0x7003, 0x0000, 0x1078, 0x1705, 0x0078, 0x19b0, 0x057e,
+	0x7d0c, 0xd5bc, 0x00c0, 0x18a6, 0x1078, 0x874c, 0x057f, 0x1078,
+	0x19b4, 0x682b, 0xffff, 0x682f, 0xffff, 0x6808, 0x8001, 0x680a,
+	0x697c, 0x6912, 0x6980, 0x6916, 0x0078, 0x19b0, 0x684c, 0xc0f5,
+	0x684e, 0x7814, 0xa005, 0x00c0, 0x18ce, 0x7003, 0x0000, 0x6808,
+	0x8001, 0x680a, 0x00c0, 0x18ca, 0x7004, 0x2060, 0x2009, 0x0048,
+	0x1078, 0x6939, 0x1078, 0x1705, 0x0078, 0x19b0, 0x7814, 0x6910,
+	0xa102, 0x6812, 0x6914, 0xa183, 0x0000, 0x6816, 0x7814, 0x7908,
+	0xa18c, 0x0fff, 0xa188, 0x0007, 0x8114, 0x8214, 0x8214, 0xa10a,
+	0x8104, 0x8004, 0x8004, 0xa20a, 0x810b, 0x810b, 0x810b, 0x1078,
+	0x1a3b, 0x7803, 0x0004, 0x780f, 0xffff, 0x7803, 0x0001, 0x7804,
+	0xd0fc, 0x0040, 0x18ef, 0x7803, 0x0002, 0x7803, 0x0004, 0x780f,
+	0x0076, 0x7004, 0x7007, 0x0000, 0x2060, 0x2009, 0x0048, 0x1078,
+	0x6939, 0x1078, 0x1a5e, 0x0040, 0x18ca, 0x7908, 0xd1ec, 0x00c0,
+	0x190d, 0x2009, 0x0009, 0x0078, 0x190f, 0x2009, 0x0019, 0x7902,
+	0x7003, 0x0003, 0x0078, 0x19b0, 0x8001, 0x7002, 0xd194, 0x0040,
+	0x1926, 0x7804, 0xd0fc, 0x00c0, 0x181e, 0x8aff, 0x0040, 0x19b0,
+	0x2009, 0x0001, 0x1078, 0x1758, 0x0078, 0x19b0, 0xa184, 0x0880,
+	0x00c0, 0x1933, 0x8aff, 0x0040, 0x19b0, 0x2009, 0x0001, 0x1078,
+	0x1758, 0x0078, 0x19b0, 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc,
+	0x00c0, 0x1973, 0x027e, 0x037e, 0x7808, 0xd0ec, 0x00c0, 0x1946,
+	0x7803, 0x0009, 0x7003, 0x0004, 0x0078, 0x1948, 0x1078, 0x1a80,
+	0x6b28, 0x6a2c, 0x1078, 0x1dc4, 0x0d7e, 0x0f7e, 0x2d78, 0x2804,
+	0xac68, 0x6034, 0xd09c, 0x00c0, 0x1963, 0x6808, 0x2008, 0xa31a,
+	0x680c, 0xa213, 0x7810, 0xa100, 0x7812, 0x690c, 0x7814, 0xa101,
+	0x7816, 0x0078, 0x196f, 0x6810, 0x2008, 0xa31a, 0x6814, 0xa213,
+	0x7810, 0xa100, 0x7812, 0x6914, 0x7814, 0xa101, 0x7816, 0x0f7f,
+	0x0d7f, 0x0078, 0x1864, 0x057e, 0x7d0c, 0x1078, 0x874c, 0x057f,
+	0x1078, 0x19b4, 0x682b, 0xffff, 0x682f, 0xffff, 0x6808, 0x8001,
+	0x680a, 0x697c, 0x6912, 0x6980, 0x6916, 0x0078, 0x19b0, 0x7803,
+	0x0004, 0x7003, 0x0000, 0x7004, 0xa00d, 0x0040, 0x199a, 0x6808,
+	0x8001, 0x680a, 0x00c0, 0x199a, 0x7004, 0x2060, 0x2009, 0x0048,
+	0x1078, 0x6939, 0x1078, 0x1705, 0x0078, 0x19b0, 0x7803, 0x0004,
+	0x7003, 0x0000, 0x7004, 0x2060, 0x6010, 0xa005, 0x0040, 0x199a,
+	0x2068, 0x6808, 0x8000, 0x680a, 0x6c28, 0x6b2c, 0x1078, 0x1724,
+	0x017f, 0x007f, 0x127f, 0x007c, 0x0c7e, 0x1078, 0x19e5, 0x20e1,
+	0x9028, 0x700c, 0x7110, 0xa106, 0x0040, 0x19db, 0x2104, 0xa005,
+	0x0040, 0x19c8, 0x2060, 0x6010, 0x2060, 0x6008, 0x8001, 0x600a,
+	0xa188, 0x0003, 0xa182, 0x8af9, 0x0048, 0x19d0, 0x2009, 0x8ade,
+	0x7112, 0x700c, 0xa106, 0x00c0, 0x19b9, 0x2001, 0x0138, 0x2003,
+	0x0008, 0x0078, 0x19b9, 0x2001, 0x015d, 0x200c, 0x810a, 0x2102,
+	0x2001, 0x0138, 0x2202, 0x0c7f, 0x007c, 0x2001, 0x0138, 0x2014,
 	0x2003, 0x0000, 0x2021, 0xb015, 0x2001, 0x0141, 0x201c, 0xd3dc,
-	0x00c0, 0x1942, 0x2001, 0x0109, 0x201c, 0xa39c, 0x0048, 0x00c0,
-	0x1942, 0x2001, 0x0111, 0x201c, 0x83ff, 0x00c0, 0x1942, 0x8421,
-	0x00c0, 0x192c, 0x007c, 0x2011, 0x0201, 0x2009, 0x003c, 0x2204,
-	0xa005, 0x00c0, 0x194f, 0x8109, 0x00c0, 0x1947, 0x007c, 0x007c,
-	0x1078, 0x1943, 0x0040, 0x1978, 0x7908, 0xd1ec, 0x00c0, 0x1968,
-	0x1078, 0x199e, 0x0040, 0x1968, 0x7803, 0x0009, 0x7904, 0xd1fc,
-	0x0040, 0x195e, 0x7803, 0x0006, 0x1078, 0x1943, 0x0040, 0x1978,
-	0x780c, 0xd0a4, 0x00c0, 0x1978, 0x7007, 0x0000, 0x1078, 0x199e,
-	0x0040, 0x197a, 0x7803, 0x0019, 0x7003, 0x0003, 0x0078, 0x197a,
-	0x1078, 0x1914, 0x007c, 0x3c00, 0x007e, 0x0e7e, 0x2071, 0x0200,
-	0x7808, 0xa084, 0xf000, 0xa10d, 0x1078, 0x1925, 0x20e1, 0x7000,
+	0x00c0, 0x1a02, 0x2001, 0x0109, 0x201c, 0xa39c, 0x0048, 0x00c0,
+	0x1a02, 0x2001, 0x0111, 0x201c, 0x83ff, 0x00c0, 0x1a02, 0x8421,
+	0x00c0, 0x19ec, 0x007c, 0x2011, 0x0201, 0x2009, 0x003c, 0x2204,
+	0xa005, 0x00c0, 0x1a0f, 0x8109, 0x00c0, 0x1a07, 0x007c, 0x007c,
+	0x1078, 0x1a03, 0x0040, 0x1a38, 0x7908, 0xd1ec, 0x00c0, 0x1a28,
+	0x1078, 0x1a5e, 0x0040, 0x1a28, 0x7803, 0x0009, 0x7904, 0xd1fc,
+	0x0040, 0x1a1e, 0x7803, 0x0006, 0x1078, 0x1a03, 0x0040, 0x1a38,
+	0x780c, 0xd0a4, 0x00c0, 0x1a38, 0x7007, 0x0000, 0x1078, 0x1a5e,
+	0x0040, 0x1a3a, 0x7803, 0x0019, 0x7003, 0x0003, 0x0078, 0x1a3a,
+	0x1078, 0x19b4, 0x007c, 0x3c00, 0x007e, 0x0e7e, 0x2071, 0x0200,
+	0x7808, 0xa084, 0xf000, 0xa10d, 0x1078, 0x19e5, 0x20e1, 0x7000,
 	0x7324, 0x7420, 0x7028, 0x7028, 0x7426, 0x7037, 0x0001, 0x810f,
 	0x712e, 0x702f, 0x0100, 0x7037, 0x0008, 0x7326, 0x7422, 0x2001,
 	0x0138, 0x2202, 0x0e7f, 0x007f, 0x20e0, 0x007c, 0x3c00, 0x007e,
-	0x7908, 0xa18c, 0x0fff, 0xa182, 0x0009, 0x0048, 0x19ab, 0xa085,
-	0x0001, 0x0078, 0x19bd, 0x2001, 0x020a, 0x81ff, 0x0040, 0x19b6,
+	0x7908, 0xa18c, 0x0fff, 0xa182, 0x0009, 0x0048, 0x1a6b, 0xa085,
+	0x0001, 0x0078, 0x1a7d, 0x2001, 0x020a, 0x81ff, 0x0040, 0x1a76,
 	0x20e1, 0x6000, 0x200c, 0x200c, 0x200c, 0x200c, 0x20e1, 0x7000,
 	0x200c, 0x200c, 0x7003, 0x0000, 0xa006, 0x007f, 0x20e0, 0x007c,
-	0x0e7e, 0x2071, 0x798b, 0x7003, 0x0000, 0x0e7f, 0x007c, 0x0d7e,
-	0xa280, 0x0004, 0x206c, 0x694c, 0xd1dc, 0x00c0, 0x1a42, 0x6934,
-	0xa184, 0x0007, 0x0079, 0x19d4, 0x19dc, 0x1a2d, 0x19dc, 0x19dc,
-	0x19dc, 0x1a12, 0x19ef, 0x19de, 0x1078, 0x12cd, 0x684c, 0xd0b4,
-	0x0040, 0x1b46, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812,
-	0x687c, 0x680a, 0x6880, 0x680e, 0x6958, 0x0078, 0x1a35, 0x6834,
-	0xa084, 0x00ff, 0xa086, 0x001e, 0x00c0, 0x19dc, 0x684c, 0xd0b4,
-	0x0040, 0x1b46, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812,
+	0x7c20, 0x7d24, 0x7e30, 0x7f34, 0x700c, 0x7110, 0xa106, 0x0040,
+	0x1aff, 0x7004, 0x017e, 0x210c, 0xa106, 0x017f, 0x0040, 0x1aff,
+	0x0d7e, 0x0c7e, 0x216c, 0x2d00, 0xa005, 0x0040, 0x1afd, 0x6810,
+	0x2068, 0x6850, 0xd0fc, 0x0040, 0x1ac9, 0x8108, 0x2104, 0x6b2c,
+	0xa306, 0x00c0, 0x1afd, 0x8108, 0x2104, 0x6a28, 0xa206, 0x00c0,
+	0x1afd, 0x6850, 0xc0fc, 0xc0f5, 0x6852, 0x686c, 0x7822, 0x6870,
+	0x7826, 0x681c, 0x7832, 0x6820, 0x7836, 0x6818, 0x2060, 0x6034,
+	0xd09c, 0x0040, 0x1ac4, 0x6830, 0x2004, 0xac68, 0x6808, 0x783a,
+	0x680c, 0x783e, 0x0078, 0x1afb, 0xa006, 0x783a, 0x783e, 0x0078,
+	0x1afb, 0x8108, 0x2104, 0xa005, 0x00c0, 0x1afd, 0x8108, 0x2104,
+	0xa005, 0x00c0, 0x1afd, 0x6850, 0xc0f5, 0x6852, 0x6830, 0x2004,
+	0x6918, 0xa160, 0x6834, 0xd09c, 0x00c0, 0x1aed, 0x6008, 0x7822,
+	0x686e, 0x600c, 0x7826, 0x6872, 0x6000, 0x7832, 0x6004, 0x7836,
+	0xa006, 0x783a, 0x783e, 0x0078, 0x1afb, 0x6010, 0x7822, 0x686e,
+	0x6014, 0x7826, 0x6872, 0x6000, 0x7832, 0x6004, 0x7836, 0x6008,
+	0x783a, 0x600c, 0x783e, 0x7803, 0x0011, 0x0c7f, 0x0d7f, 0x007c,
+	0x0e7e, 0x2071, 0x8af9, 0x7003, 0x0000, 0x0e7f, 0x007c, 0x0d7e,
+	0xa280, 0x0004, 0x206c, 0x694c, 0xd1dc, 0x00c0, 0x1b82, 0x6934,
+	0xa184, 0x0007, 0x0079, 0x1b14, 0x1b1c, 0x1b6d, 0x1b1c, 0x1b1c,
+	0x1b1c, 0x1b52, 0x1b2f, 0x1b1e, 0x1078, 0x12d2, 0x684c, 0xd0b4,
+	0x0040, 0x1c90, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812,
+	0x687c, 0x680a, 0x6880, 0x680e, 0x6958, 0x0078, 0x1b75, 0x6834,
+	0xa084, 0x00ff, 0xa086, 0x001e, 0x00c0, 0x1b1c, 0x684c, 0xd0b4,
+	0x0040, 0x1c90, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812,
 	0x687c, 0x680a, 0x6880, 0x680e, 0x6804, 0x681a, 0xa080, 0x000d,
-	0x2004, 0xa084, 0x000f, 0xa080, 0x1c7e, 0x2004, 0x6832, 0x6958,
-	0x0078, 0x1a3e, 0xa18c, 0x00ff, 0xa186, 0x0015, 0x00c0, 0x1a42,
-	0x684c, 0xd0b4, 0x0040, 0x1b46, 0x6804, 0x681a, 0xa080, 0x000d,
-	0x2004, 0xa084, 0x000f, 0xa080, 0x1c7e, 0x2004, 0x6832, 0x6958,
-	0xa006, 0x682e, 0x682a, 0x0078, 0x1a3e, 0x684c, 0xd0b4, 0x0040,
-	0x1781, 0x6958, 0xa006, 0x682e, 0x682a, 0x2d00, 0x681a, 0x6834,
-	0xa084, 0x000f, 0xa080, 0x1c7e, 0x2004, 0x6832, 0x6926, 0x684c,
+	0x2004, 0xa084, 0x000f, 0xa080, 0x1def, 0x2004, 0x6832, 0x6958,
+	0x0078, 0x1b7e, 0xa18c, 0x00ff, 0xa186, 0x0015, 0x00c0, 0x1b82,
+	0x684c, 0xd0b4, 0x0040, 0x1c90, 0x6804, 0x681a, 0xa080, 0x000d,
+	0x2004, 0xa084, 0x000f, 0xa080, 0x1def, 0x2004, 0x6832, 0x6958,
+	0xa006, 0x682e, 0x682a, 0x0078, 0x1b7e, 0x684c, 0xd0b4, 0x0040,
+	0x17f0, 0x6958, 0xa006, 0x682e, 0x682a, 0x2d00, 0x681a, 0x6834,
+	0xa084, 0x000f, 0xa080, 0x1def, 0x2004, 0x6832, 0x6926, 0x684c,
 	0xc0dd, 0x684e, 0x0d7f, 0x007c, 0x0f7e, 0x2079, 0x0020, 0x7804,
-	0xd0fc, 0x10c0, 0x1b4a, 0x0e7e, 0x0d7e, 0x2071, 0x798b, 0x7000,
-	0xa005, 0x00c0, 0x1ac0, 0x0c7e, 0x7206, 0xa280, 0x0004, 0x205c,
+	0xd0fc, 0x10c0, 0x1cb7, 0x0e7e, 0x0d7e, 0x2071, 0x8af9, 0x7000,
+	0xa005, 0x00c0, 0x1c07, 0x0c7e, 0x7206, 0xa280, 0x0004, 0x205c,
 	0x7004, 0x2068, 0x7803, 0x0004, 0x6818, 0x0d7e, 0x2068, 0x686c,
 	0x7812, 0x6890, 0x0f7e, 0x20e1, 0x9040, 0x2079, 0x0200, 0x781a,
 	0x2079, 0x0100, 0x8004, 0x78d6, 0x0f7f, 0x0d7f, 0x2b68, 0x6824,
 	0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, 0x000f,
-	0x6908, 0xa184, 0x0007, 0x0040, 0x1a82, 0x017e, 0x2009, 0x0008,
-	0xa102, 0x017f, 0xa108, 0x791a, 0x7116, 0x701e, 0x680c, 0xa081,
-	0x0000, 0x781e, 0x701a, 0xa006, 0x700e, 0x7012, 0x7004, 0x692c,
-	0x6814, 0xa106, 0x00c0, 0x1a99, 0x6928, 0x6810, 0xa106, 0x0040,
-	0x1aa6, 0x037e, 0x047e, 0x6b14, 0x6c10, 0x1078, 0x1c9e, 0x047f,
-	0x037f, 0x0040, 0x1aa6, 0x0c7f, 0x0078, 0x1ac0, 0x8aff, 0x00c0,
-	0x1aae, 0x0c7f, 0xa085, 0x0001, 0x0078, 0x1ac0, 0x127e, 0x2091,
-	0x8000, 0x2079, 0x0020, 0x2009, 0x0001, 0x1078, 0x1ac4, 0x0040,
-	0x1abd, 0x2009, 0x0001, 0x1078, 0x1ac4, 0x127f, 0x0c7f, 0xa006,
-	0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x077e, 0x067e, 0x057e, 0x047e,
-	0x037e, 0x027e, 0x8aff, 0x0040, 0x1b3f, 0x700c, 0x7214, 0xa202,
-	0x7010, 0x7218, 0xa203, 0x0048, 0x1b3e, 0xa03e, 0x2730, 0x6850,
-	0xd0fc, 0x00c0, 0x1af1, 0x0d7e, 0x2804, 0xac68, 0x2900, 0x0079,
-	0x1ae1, 0x1b20, 0x1b01, 0x1b01, 0x1b20, 0x1b20, 0x1b18, 0x1b20,
-	0x1b01, 0x1b20, 0x1b07, 0x1b07, 0x1b20, 0x1b20, 0x1b20, 0x1b0f,
-	0x1b07, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0xd99c,
-	0x0040, 0x1b24, 0x0d7e, 0x2804, 0xac68, 0x6f08, 0x6e0c, 0x0078,
-	0x1b23, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x0078, 0x1b23, 0x6b10,
-	0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0078, 0x1b23, 0x0d7f,
-	0x0d7e, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x00c0, 0x1b20,
-	0x0d7f, 0x1078, 0x1c3a, 0x00c0, 0x1aca, 0xa00e, 0x0078, 0x1b3f,
-	0x0d7f, 0x1078, 0x12cd, 0x0d7f, 0x7b22, 0x7a26, 0x7d32, 0x7c36,
-	0x7f3a, 0x7e3e, 0x7902, 0x7000, 0x8000, 0x7002, 0x6828, 0xa300,
-	0x682a, 0x682c, 0xa201, 0x682e, 0x700c, 0xa300, 0x700e, 0x7010,
-	0xa201, 0x7012, 0x1078, 0x1c3a, 0x0078, 0x1b3f, 0xa006, 0x027f,
-	0x037f, 0x047f, 0x057f, 0x067f, 0x077f, 0x007c, 0x1078, 0x12cd,
-	0x1078, 0x12cd, 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, 0x0f7e,
-	0x0e7e, 0x0d7e, 0x0c7e, 0x2079, 0x0020, 0x2071, 0x798b, 0x2b68,
-	0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, 0x00c0,
-	0x1b48, 0x7000, 0x0079, 0x1b64, 0x1c0b, 0x1b68, 0x1bd8, 0x1c09,
-	0x8001, 0x7002, 0xd19c, 0x00c0, 0x1b7c, 0x8aff, 0x0040, 0x1b9b,
-	0x2009, 0x0001, 0x1078, 0x1ac4, 0x0040, 0x1c0b, 0x2009, 0x0001,
-	0x1078, 0x1ac4, 0x0078, 0x1c0b, 0x7803, 0x0004, 0xd194, 0x0040,
-	0x1b8c, 0x6850, 0xc0fc, 0x6852, 0x8aff, 0x00c0, 0x1b91, 0x684c,
-	0xc0f5, 0x684e, 0x0078, 0x1b91, 0x1078, 0x1c53, 0x6850, 0xc0fd,
-	0x6852, 0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003,
-	0x0000, 0x0078, 0x1c0b, 0x711c, 0x81ff, 0x0040, 0x1bb1, 0x7918,
-	0x7922, 0x7827, 0x0000, 0x7803, 0x0001, 0x7000, 0x8000, 0x7002,
-	0x700c, 0xa100, 0x700e, 0x7010, 0xa081, 0x0000, 0x7012, 0x0078,
-	0x1c0b, 0x0f7e, 0x027e, 0x781c, 0x007e, 0x7818, 0x007e, 0x2079,
-	0x0100, 0x7a14, 0xa284, 0x0004, 0xa085, 0x0012, 0x7816, 0x7820,
-	0xd0bc, 0x00c0, 0x1bbf, 0x79c8, 0x007f, 0xa102, 0x78ca, 0x79c4,
-	0x007f, 0xa102, 0x78c6, 0xa284, 0x0004, 0xa085, 0x0012, 0x7816,
-	0x027f, 0x0f7f, 0x7803, 0x0008, 0x7003, 0x0000, 0x0078, 0x1c0b,
-	0x8001, 0x7002, 0xd194, 0x0040, 0x1bed, 0x7804, 0xd0fc, 0x00c0,
-	0x1b5a, 0xd19c, 0x00c0, 0x1c07, 0x8aff, 0x0040, 0x1c0b, 0x2009,
-	0x0001, 0x1078, 0x1ac4, 0x0078, 0x1c0b, 0x027e, 0x037e, 0x6b28,
-	0x6a2c, 0x1078, 0x1c53, 0x0d7e, 0x2804, 0xac68, 0x6034, 0xd09c,
-	0x00c0, 0x1c00, 0x6808, 0xa31a, 0x680c, 0xa213, 0x0078, 0x1c04,
-	0x6810, 0xa31a, 0x6814, 0xa213, 0x0d7f, 0x0078, 0x1b8c, 0x0078,
-	0x1b8c, 0x1078, 0x12cd, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x017f,
-	0x007f, 0x127f, 0x007c, 0x0f7e, 0x0e7e, 0x2071, 0x798b, 0x7000,
-	0xa086, 0x0000, 0x0040, 0x1c37, 0x2079, 0x0020, 0x20e1, 0x9040,
-	0x7804, 0xd0fc, 0x0040, 0x1c1e, 0x1078, 0x1b4a, 0x7000, 0xa086,
-	0x0000, 0x00c0, 0x1c1e, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x00c0,
-	0x1c2d, 0x20e1, 0x9040, 0x7803, 0x0002, 0x7003, 0x0000, 0x0e7f,
-	0x0f7f, 0x007c, 0x8840, 0x2804, 0xa005, 0x00c0, 0x1c4e, 0x6004,
-	0xa005, 0x0040, 0x1c50, 0x681a, 0x2060, 0x6034, 0xa084, 0x000f,
-	0xa080, 0x1c7e, 0x2044, 0x88ff, 0x1040, 0x12cd, 0x8a51, 0x007c,
-	0x2051, 0x0000, 0x007c, 0x8a50, 0x8841, 0x2804, 0xa005, 0x00c0,
-	0x1c6d, 0x2c00, 0xad06, 0x0040, 0x1c62, 0x6000, 0xa005, 0x00c0,
-	0x1c62, 0x2d00, 0x2060, 0x681a, 0x6034, 0xa084, 0x000f, 0xa080,
-	0x1c8e, 0x2044, 0x88ff, 0x1040, 0x12cd, 0x007c, 0x0000, 0x0011,
-	0x0015, 0x0019, 0x001d, 0x0021, 0x0025, 0x0029, 0x0000, 0x000f,
-	0x0015, 0x001b, 0x0021, 0x0027, 0x0000, 0x0000, 0x0000, 0x1c73,
-	0x1c6f, 0x0000, 0x0000, 0x1c7d, 0x0000, 0x1c73, 0x0000, 0x1c7a,
-	0x1c77, 0x0000, 0x0000, 0x0000, 0x1c7d, 0x1c7a, 0x0000, 0x1c75,
-	0x1c75, 0x0000, 0x0000, 0x1c7d, 0x0000, 0x1c75, 0x0000, 0x1c7b,
-	0x1c7b, 0x0000, 0x0000, 0x0000, 0x1c7d, 0x1c7b, 0x0a7e, 0x097e,
-	0x087e, 0x6858, 0xa055, 0x0040, 0x1d3f, 0x2d60, 0x6034, 0xa0cc,
-	0x000f, 0xa9c0, 0x1c7e, 0xa986, 0x0007, 0x0040, 0x1cb7, 0xa986,
-	0x000e, 0x0040, 0x1cb7, 0xa986, 0x000f, 0x00c0, 0x1cbb, 0x605c,
-	0xa422, 0x6060, 0xa31a, 0x2804, 0xa045, 0x00c0, 0x1cc9, 0x0050,
-	0x1cc3, 0x0078, 0x1d3f, 0x6004, 0xa065, 0x0040, 0x1d3f, 0x0078,
-	0x1ca6, 0x2804, 0xa005, 0x0040, 0x1ce7, 0xac68, 0xd99c, 0x00c0,
-	0x1cd7, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0078, 0x1cdb, 0x6810,
-	0xa422, 0x6814, 0xa31b, 0x0048, 0x1d06, 0x2300, 0xa405, 0x0040,
-	0x1ced, 0x8a51, 0x0040, 0x1d3f, 0x8840, 0x0078, 0x1cc9, 0x6004,
-	0xa065, 0x0040, 0x1d3f, 0x0078, 0x1ca6, 0x8a51, 0x0040, 0x1d3f,
-	0x8840, 0x2804, 0xa005, 0x00c0, 0x1d00, 0x6004, 0xa065, 0x0040,
-	0x1d3f, 0x6034, 0xa0cc, 0x000f, 0xa9c0, 0x1c7e, 0x2804, 0x2040,
-	0x2b68, 0x6850, 0xc0fc, 0x6852, 0x0078, 0x1d33, 0x8422, 0x8420,
-	0x831a, 0xa399, 0x0000, 0x0d7e, 0x2b68, 0x6c6e, 0x6b72, 0x0d7f,
-	0xd99c, 0x00c0, 0x1d21, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300,
-	0xa11b, 0x1048, 0x12cd, 0x6800, 0xa420, 0x6804, 0xa319, 0x0078,
-	0x1d2d, 0x6910, 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b, 0x1048,
-	0x12cd, 0x6800, 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e, 0x6b22,
-	0x6850, 0xc0fd, 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832, 0x2a00,
-	0x6826, 0x007f, 0x007f, 0x007f, 0xa006, 0x0078, 0x1d44, 0x087f,
-	0x097f, 0x0a7f, 0xa085, 0x0001, 0x007c, 0x2001, 0x0005, 0x2004,
-	0xa084, 0x0007, 0x0079, 0x1d4c, 0x1d54, 0x1d55, 0x1d58, 0x1d5b,
-	0x1d60, 0x1d63, 0x1d68, 0x1d6d, 0x007c, 0x1078, 0x1b4a, 0x007c,
-	0x1078, 0x1785, 0x007c, 0x1078, 0x1785, 0x1078, 0x1b4a, 0x007c,
-	0x1078, 0x1456, 0x007c, 0x1078, 0x1b4a, 0x1078, 0x1456, 0x007c,
-	0x1078, 0x1785, 0x1078, 0x1456, 0x007c, 0x1078, 0x1785, 0x1078,
-	0x1b4a, 0x1078, 0x1456, 0x007c, 0x127e, 0x2091, 0x2300, 0x2079,
-	0x0200, 0x2071, 0x7c80, 0x2069, 0x7700, 0x2009, 0x0004, 0x7912,
-	0x7817, 0x0004, 0x1078, 0x2052, 0x781b, 0x0002, 0x20e1, 0x8700,
-	0x127f, 0x007c, 0x127e, 0x2091, 0x2300, 0x781c, 0xa084, 0x0007,
-	0x0079, 0x1d92, 0x1db6, 0x1d9a, 0x1d9e, 0x1da2, 0x1da8, 0x1dac,
-	0x1db0, 0x1db4, 0x1078, 0x4298, 0x0078, 0x1db6, 0x1078, 0x42c7,
-	0x0078, 0x1db6, 0x1078, 0x4298, 0x1078, 0x42c7, 0x0078, 0x1db6,
-	0x1078, 0x1db8, 0x0078, 0x1db6, 0x1078, 0x1db8, 0x0078, 0x1db6,
-	0x1078, 0x1db8, 0x0078, 0x1db6, 0x1078, 0x1db8, 0x127f, 0x007c,
-	0x007e, 0x017e, 0x027e, 0x7930, 0xa184, 0x0003, 0x0040, 0x1dc2,
-	0x1078, 0x12cd, 0xa184, 0x0030, 0x0040, 0x1dd3, 0x6a00, 0xa286,
-	0x0003, 0x00c0, 0x1dcd, 0x1078, 0x12cd, 0x1078, 0x3591, 0x20e1,
-	0x9010, 0x0078, 0x1ddf, 0xa184, 0x00c0, 0x0040, 0x1dd9, 0x1078,
-	0x12cd, 0xa184, 0x0300, 0x0040, 0x1ddf, 0x20e1, 0x9020, 0x7932,
-	0x027f, 0x017f, 0x007f, 0x007c, 0x017e, 0x0e7e, 0x0f7e, 0x2071,
-	0x7700, 0x7128, 0x2001, 0x7923, 0x2102, 0x2001, 0x792b, 0x2102,
-	0xa182, 0x0211, 0x00c8, 0x1df8, 0x2009, 0x0008, 0x0078, 0x1e22,
-	0xa182, 0x0259, 0x00c8, 0x1e00, 0x2009, 0x0007, 0x0078, 0x1e22,
-	0xa182, 0x02c1, 0x00c8, 0x1e08, 0x2009, 0x0006, 0x0078, 0x1e22,
-	0xa182, 0x0349, 0x00c8, 0x1e10, 0x2009, 0x0005, 0x0078, 0x1e22,
-	0xa182, 0x0421, 0x00c8, 0x1e18, 0x2009, 0x0004, 0x0078, 0x1e22,
-	0xa182, 0x0581, 0x00c8, 0x1e20, 0x2009, 0x0003, 0x0078, 0x1e22,
-	0x2009, 0x0002, 0x2079, 0x0200, 0x7912, 0xa182, 0x0005, 0x00c8,
-	0x1e2c, 0x7916, 0x0078, 0x1e2e, 0x7817, 0x0004, 0x1078, 0x2052,
-	0x0f7f, 0x0e7f, 0x017f, 0x007c, 0x127e, 0x2091, 0x2200, 0x2061,
-	0x0100, 0x2071, 0x7700, 0x6024, 0x6026, 0x6033, 0x00ef, 0x60e7,
-	0x0000, 0x60eb, 0x00ef, 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043,
-	0x0000, 0x602f, 0x0080, 0x602f, 0x0000, 0x6007, 0x0caf, 0x600f,
-	0x00ff, 0x602b, 0x002f, 0x127f, 0x007c, 0x2001, 0x772d, 0x2003,
-	0x0000, 0x2001, 0x772c, 0x2003, 0x0001, 0x007c, 0x127e, 0x2091,
-	0x2200, 0x007e, 0x017e, 0x027e, 0x6124, 0xa184, 0x002c, 0x00c0,
-	0x1e6d, 0xa184, 0x0007, 0x0079, 0x1e73, 0xa195, 0x0004, 0xa284,
-	0x0007, 0x0079, 0x1e73, 0x1e9f, 0x1e7b, 0x1e7f, 0x1e83, 0x1e89,
-	0x1e8d, 0x1e93, 0x1e99, 0x1078, 0x4802, 0x0078, 0x1e9f, 0x1078,
-	0x48f1, 0x0078, 0x1e9f, 0x1078, 0x48f1, 0x1078, 0x4802, 0x0078,
-	0x1e9f, 0x1078, 0x1ea4, 0x0078, 0x1e9f, 0x1078, 0x4802, 0x1078,
-	0x1ea4, 0x0078, 0x1e9f, 0x1078, 0x48f1, 0x1078, 0x1ea4, 0x0078,
-	0x1e9f, 0x1078, 0x48f1, 0x1078, 0x4802, 0x1078, 0x1ea4, 0x027f,
-	0x017f, 0x007f, 0x127f, 0x007c, 0xd1ac, 0x0040, 0x1f58, 0x017e,
-	0x047e, 0x0c7e, 0x644c, 0x74ba, 0xa48c, 0xff00, 0xa196, 0xff00,
-	0x0040, 0x1ed3, 0x6030, 0xa084, 0x00ff, 0x810f, 0xa116, 0x0040,
-	0x1ed3, 0x7130, 0xd18c, 0x00c0, 0x1ed3, 0x2011, 0x7752, 0x2214,
-	0xd2ec, 0x0040, 0x1ec7, 0xc18d, 0x7132, 0x0078, 0x1ed3, 0x6240,
-	0xa294, 0x0010, 0x0040, 0x1f15, 0x6248, 0xa294, 0xff00, 0xa296,
-	0xff00, 0x00c0, 0x1f15, 0x037e, 0x73b8, 0x2011, 0x8013, 0x1078,
-	0x2d59, 0x037f, 0x7130, 0xc185, 0x7132, 0x2011, 0x7752, 0x220c,
-	0xd1a4, 0x0040, 0x1efd, 0x017e, 0x2009, 0x0001, 0x2011, 0x0100,
-	0x1078, 0x47d0, 0x2019, 0x000e, 0x1078, 0x75d9, 0xa484, 0x00ff,
-	0xa080, 0x2329, 0x200c, 0xa18c, 0xff00, 0x810f, 0x8127, 0xa006,
-	0x2009, 0x000e, 0x1078, 0x7641, 0x017f, 0xd1ac, 0x00c0, 0x1f06,
-	0x2019, 0x0004, 0x1078, 0x2293, 0x0078, 0x1f15, 0x157e, 0x20a9,
-	0x007f, 0x2009, 0x0000, 0x1078, 0x384c, 0x00c0, 0x1f11, 0x1078,
-	0x3637, 0x8108, 0x00f0, 0x1f0b, 0x157f, 0x0c7f, 0x047f, 0x6043,
-	0x0000, 0x2009, 0x00f7, 0x1078, 0x35fa, 0x0f7e, 0x2079, 0x7949,
-	0x783c, 0xa086, 0x0000, 0x0040, 0x1f2d, 0x6027, 0x0004, 0x783f,
-	0x0000, 0x2079, 0x0140, 0x7803, 0x0000, 0x0f7f, 0x2011, 0x0003,
-	0x1078, 0x58d8, 0x2011, 0x0002, 0x1078, 0x58e2, 0x1078, 0x57ee,
-	0x1078, 0x4706, 0x037e, 0x2019, 0x0000, 0x1078, 0x5880, 0x037f,
-	0x60e3, 0x0000, 0x017f, 0x2001, 0x7700, 0x2014, 0xa296, 0x0004,
-	0x00c0, 0x1f50, 0xd19c, 0x00c0, 0x1f50, 0x6228, 0xc29d, 0x622a,
-	0x2003, 0x0001, 0x2001, 0x7720, 0x2003, 0x0000, 0x6027, 0x0020,
-	0xd194, 0x0040, 0x1ff9, 0x0f7e, 0x2079, 0x7949, 0x783c, 0xa086,
-	0x0001, 0x00c0, 0x1f7c, 0x017e, 0x6027, 0x0004, 0x783f, 0x0000,
-	0x2079, 0x0140, 0x7803, 0x1000, 0x7803, 0x0000, 0x2079, 0x7936,
-	0x7807, 0x0000, 0x7833, 0x0000, 0x1078, 0x4d96, 0x1078, 0x4e56,
-	0x017f, 0x0f7f, 0x0078, 0x1ff9, 0x0f7f, 0x017e, 0x6220, 0xd2b4,
-	0x0040, 0x1fb1, 0x1078, 0x4706, 0x1078, 0x569c, 0x6027, 0x0004,
-	0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0040, 0x1f94,
-	0x6803, 0x1000, 0x6803, 0x0000, 0x0d7f, 0x0c7e, 0x2061, 0x7936,
-	0x6028, 0xa09a, 0x0002, 0x00c8, 0x1fa4, 0x8000, 0x602a, 0x0c7f,
-	0x1078, 0x568e, 0x0078, 0x1ff8, 0x2019, 0x793f, 0x2304, 0xa065,
-	0x0040, 0x1fae, 0x2009, 0x0027, 0x1078, 0x5d41, 0x0c7f, 0x0078,
-	0x1ff8, 0xd2bc, 0x0040, 0x1ff8, 0x1078, 0x4714, 0x6017, 0x0010,
-	0x6027, 0x0004, 0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000,
-	0x0040, 0x1fc6, 0x6803, 0x1000, 0x6803, 0x0000, 0x0d7f, 0x0c7e,
-	0x2061, 0x7936, 0x6044, 0xa09a, 0x0002, 0x00c8, 0x1fe7, 0x8000,
-	0x6046, 0x603c, 0x0c7f, 0xa005, 0x0040, 0x1ff8, 0x1078, 0x470b,
-	0xa080, 0x0007, 0x2004, 0xa086, 0x0006, 0x00c0, 0x1fe3, 0x6017,
-	0x0012, 0x0078, 0x1ff8, 0x6017, 0x0016, 0x0078, 0x1ff8, 0x037e,
-	0x2019, 0x0001, 0x1078, 0x5880, 0x037f, 0x2019, 0x7945, 0x2304,
-	0xa065, 0x0040, 0x1ff7, 0x2009, 0x004f, 0x1078, 0x5d41, 0x0c7f,
-	0x017f, 0xd19c, 0x0040, 0x2021, 0x017e, 0x6028, 0xc09c, 0x602a,
-	0x2011, 0x0003, 0x1078, 0x58d8, 0x2011, 0x0002, 0x1078, 0x58e2,
-	0x1078, 0x57ee, 0x1078, 0x4706, 0x037e, 0x2019, 0x0000, 0x1078,
-	0x5880, 0x037f, 0x60e3, 0x0000, 0x1078, 0x76b0, 0x1078, 0x76ce,
-	0x2001, 0x7700, 0x2003, 0x0004, 0x6027, 0x0008, 0x1078, 0x11be,
-	0x017f, 0xa18c, 0xffd0, 0x6126, 0x007c, 0x007e, 0x017e, 0x027e,
-	0x0e7e, 0x0f7e, 0x127e, 0x2091, 0x8000, 0x2071, 0x7700, 0x71b0,
-	0x70b2, 0xa116, 0x0040, 0x204b, 0x81ff, 0x0040, 0x203d, 0x2011,
-	0x8011, 0x1078, 0x2d59, 0x0078, 0x204b, 0x2011, 0x8012, 0x1078,
-	0x2d59, 0x037e, 0x0c7e, 0x2061, 0x0100, 0x2019, 0x0028, 0x1078,
-	0x2293, 0x0c7f, 0x037f, 0x127f, 0x0f7f, 0x0e7f, 0x027f, 0x017f,
-	0x007f, 0x007c, 0x0c7e, 0x0f7e, 0x007e, 0x027e, 0x2061, 0x0100,
-	0xa190, 0x206d, 0x2204, 0x60f2, 0xa192, 0x0005, 0x00c8, 0x2064,
-	0xa190, 0x2076, 0x0078, 0x2066, 0x2011, 0x207a, 0x2204, 0x60ee,
-	0x027f, 0x007f, 0x0f7f, 0x0c7f, 0x007c, 0x0840, 0x0840, 0x0840,
-	0x0580, 0x0420, 0x0348, 0x02c0, 0x0258, 0x0210, 0x01a8, 0x01a8,
-	0x01a8, 0x01a8, 0x0140, 0x00f8, 0x00d0, 0x00b0, 0x00a0, 0x2028,
-	0x2130, 0xa094, 0xff00, 0x00c0, 0x2088, 0x81ff, 0x0040, 0x208c,
-	0x1078, 0x444b, 0x0078, 0x2093, 0xa080, 0x2329, 0x200c, 0xa18c,
-	0xff00, 0x810f, 0xa006, 0x007c, 0xa080, 0x2329, 0x200c, 0xa18c,
-	0x00ff, 0x007c, 0x20ba, 0x20be, 0x20c2, 0x20c8, 0x20ce, 0x20d4,
-	0x20da, 0x20e2, 0x20ea, 0x20f0, 0x20f6, 0x20fe, 0x2106, 0x210e,
-	0x2116, 0x2120, 0x212a, 0x212a, 0x212a, 0x212a, 0x212a, 0x212a,
-	0x212a, 0x212a, 0x212a, 0x212a, 0x212a, 0x212a, 0x212a, 0x212a,
-	0x212a, 0x212a, 0x107e, 0x007e, 0x0078, 0x2143, 0x107e, 0x007e,
-	0x0078, 0x2143, 0x107e, 0x007e, 0x1078, 0x1e5e, 0x0078, 0x2143,
-	0x107e, 0x007e, 0x1078, 0x1e5e, 0x0078, 0x2143, 0x107e, 0x007e,
-	0x1078, 0x1d45, 0x0078, 0x2143, 0x107e, 0x007e, 0x1078, 0x1d45,
-	0x0078, 0x2143, 0x107e, 0x007e, 0x1078, 0x1e5e, 0x1078, 0x1d45,
-	0x0078, 0x2143, 0x107e, 0x007e, 0x1078, 0x1e5e, 0x1078, 0x1d45,
-	0x0078, 0x2143, 0x107e, 0x007e, 0x1078, 0x1d8a, 0x0078, 0x2143,
-	0x107e, 0x007e, 0x1078, 0x1d8a, 0x0078, 0x2143, 0x107e, 0x007e,
-	0x1078, 0x1e5e, 0x1078, 0x1d8a, 0x0078, 0x2143, 0x107e, 0x007e,
-	0x1078, 0x1e5e, 0x1078, 0x1d8a, 0x0078, 0x2143, 0x107e, 0x007e,
-	0x1078, 0x1d45, 0x1078, 0x1d8a, 0x0078, 0x2143, 0x107e, 0x007e,
-	0x1078, 0x1d45, 0x1078, 0x1d8a, 0x0078, 0x2143, 0x107e, 0x007e,
-	0x1078, 0x1e5e, 0x1078, 0x1d45, 0x1078, 0x1d8a, 0x0078, 0x2143,
-	0x107e, 0x007e, 0x1078, 0x1e5e, 0x1078, 0x1d45, 0x1078, 0x1d8a,
-	0x0078, 0x2143, 0x0005, 0x0078, 0x212a, 0xb084, 0x003c, 0x8004,
-	0x8004, 0x0079, 0x2133, 0x2143, 0x20c0, 0x20c4, 0x20ca, 0x20d0,
-	0x20d6, 0x20dc, 0x20e4, 0x20ec, 0x20f2, 0x20f8, 0x2100, 0x2108,
-	0x2110, 0x2118, 0x2122, 0x0008, 0x212d, 0x007f, 0x107f, 0x2091,
-	0x8001, 0x007c, 0x0c7e, 0x027e, 0x2041, 0x007e, 0x70bc, 0xd09c,
-	0x0040, 0x2154, 0x2041, 0x007f, 0x2001, 0x010c, 0x203c, 0x727c,
-	0x82ff, 0x0040, 0x219f, 0x037e, 0x738c, 0xa38e, 0xffff, 0x00c0,
-	0x2163, 0x2019, 0x0001, 0x8314, 0xa2e0, 0x7dc0, 0x2c04, 0xa38c,
-	0x0001, 0x0040, 0x2170, 0xa084, 0xff00, 0x8007, 0x0078, 0x2172,
-	0xa084, 0x00ff, 0xa70e, 0x0040, 0x2194, 0xa08e, 0x00ff, 0x0040,
-	0x219a, 0x2009, 0x0000, 0x1078, 0x207f, 0x1078, 0x3811, 0x00c0,
-	0x2197, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x218e,
-	0x1078, 0x21f1, 0x0040, 0x2197, 0x0078, 0x2194, 0x1078, 0x22f5,
-	0x1078, 0x2218, 0x0040, 0x2197, 0x8318, 0x0078, 0x2163, 0x738e,
-	0x0078, 0x219c, 0x708f, 0xffff, 0x037f, 0x0078, 0x21ee, 0xa780,
-	0x2329, 0x203c, 0xa7bc, 0xff00, 0x873f, 0x708c, 0xa096, 0xffff,
-	0x0040, 0x21b1, 0xa812, 0x00c8, 0x21c1, 0x708f, 0xffff, 0x0078,
-	0x21eb, 0x2009, 0x0000, 0x70bc, 0xd09c, 0x0040, 0x21bc, 0xd094,
-	0x0040, 0x21bc, 0x2009, 0x007e, 0x2100, 0xa802, 0x20a8, 0x0078,
-	0x21c5, 0x2008, 0x2810, 0xa202, 0x20a8, 0x2700, 0x157e, 0x017e,
-	0xa106, 0x0040, 0x21e2, 0x1078, 0x3811, 0x00c0, 0x21eb, 0x6004,
-	0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x21dc, 0x1078, 0x21f1,
-	0x0040, 0x21eb, 0x0078, 0x21e2, 0x1078, 0x22f5, 0x1078, 0x2218,
-	0x0040, 0x21eb, 0x017f, 0x8108, 0x157f, 0x00f0, 0x21c5, 0x708f,
-	0xffff, 0x0078, 0x21ee, 0x017f, 0x157f, 0x718e, 0x027f, 0x0c7f,
-	0x007c, 0x017e, 0x077e, 0x0d7e, 0x0c7e, 0x2c68, 0x1078, 0x5cb4,
-	0x0040, 0x2213, 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001, 0x0000,
-	0x1078, 0x37e0, 0x2001, 0x0000, 0x1078, 0x37f4, 0x127e, 0x2091,
-	0x8000, 0x7088, 0x8000, 0x708a, 0x127f, 0x2009, 0x0004, 0x1078,
-	0x5d41, 0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f, 0x007c,
-	0x017e, 0x077e, 0x0d7e, 0x0c7e, 0x2c68, 0x1078, 0x5cb4, 0x0040,
-	0x223a, 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078,
-	0x37e0, 0x2001, 0x0002, 0x1078, 0x37f4, 0x127e, 0x2091, 0x8000,
-	0x7088, 0x8000, 0x708a, 0x127f, 0x2009, 0x0002, 0x1078, 0x5d41,
-	0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f, 0x007c, 0x0c7e,
-	0x027e, 0x2009, 0x0080, 0x1078, 0x3811, 0x00c0, 0x224d, 0x1078,
-	0x2250, 0x0040, 0x224d, 0x70c3, 0xffff, 0x027f, 0x0c7f, 0x007c,
-	0x017e, 0x077e, 0x0d7e, 0x0c7e, 0x2c68, 0x1078, 0x5cb4, 0x0040,
-	0x2272, 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078,
-	0x37e0, 0x2001, 0x0002, 0x1078, 0x37f4, 0x127e, 0x2091, 0x8000,
-	0x70c4, 0x8000, 0x70c6, 0x127f, 0x2009, 0x0002, 0x1078, 0x5d41,
-	0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f, 0x007c, 0x0c7e,
-	0x0d7e, 0x2009, 0x007f, 0x1078, 0x3811, 0x00c0, 0x2290, 0x2c68,
-	0x1078, 0x5cb4, 0x0040, 0x2290, 0x2d00, 0x601a, 0x6312, 0x601f,
-	0x0001, 0x620a, 0x2009, 0x0022, 0x1078, 0x5d41, 0xa085, 0x0001,
-	0x0d7f, 0x0c7f, 0x007c, 0x0e7e, 0x0c7e, 0x067e, 0x037e, 0x027e,
-	0x1078, 0x4a85, 0x1078, 0x4a35, 0x1078, 0x6219, 0x20a9, 0x007f,
-	0x2009, 0x0000, 0x017e, 0x1078, 0x384c, 0x00c0, 0x22ab, 0x1078,
-	0x3a36, 0x1078, 0x3637, 0x017f, 0x8108, 0x00f0, 0x22a2, 0x027f,
-	0x037f, 0x067f, 0x0c7f, 0x0e7f, 0x007c, 0x0e7e, 0x0c7e, 0x037e,
-	0x027e, 0x017e, 0x6218, 0x2270, 0x72a0, 0x027e, 0x2019, 0x0029,
-	0x1078, 0x4a7e, 0x1078, 0x49c1, 0x2c08, 0x1078, 0x747b, 0x017f,
-	0x2e60, 0x1078, 0x3a36, 0x6210, 0x6314, 0x1078, 0x3637, 0x6212,
-	0x6316, 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f, 0x007c, 0x0e7e,
-	0x007e, 0x6018, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x00c0, 0x22eb,
-	0x2071, 0x7700, 0x7088, 0xa005, 0x0040, 0x22e8, 0x8001, 0x708a,
-	0x007f, 0x0e7f, 0x007c, 0x2071, 0x7700, 0x70c4, 0xa005, 0x0040,
-	0x22e8, 0x8001, 0x70c6, 0x0078, 0x22e8, 0x6000, 0xc08c, 0x6002,
-	0x007c, 0x0e7e, 0x0c7e, 0x037e, 0x027e, 0x017e, 0x157e, 0x81ff,
-	0x00c0, 0x2306, 0x20a9, 0x0001, 0x0078, 0x230a, 0x20a9, 0x007f,
-	0x2011, 0x0000, 0x027e, 0xa2e0, 0x7820, 0x2c64, 0x8cff, 0x0040,
-	0x231c, 0x2019, 0x0029, 0x1078, 0x4a7e, 0x1078, 0x49c1, 0x2c08,
-	0x1078, 0x747b, 0x1078, 0x3a36, 0x027f, 0x8210, 0x00f0, 0x230a,
-	0x027e, 0x027f, 0x157f, 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f,
-	0x007c, 0x7eef, 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc,
-	0x80da, 0x7ad9, 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1,
-	0x79ce, 0x78cd, 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6,
-	0x77c5, 0x76c3, 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4,
-	0x72b3, 0x80b2, 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa,
-	0x6ea9, 0x80a7, 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d,
-	0x809b, 0x8098, 0x6797, 0x6690, 0x658f, 0x6488, 0x6384, 0x6282,
-	0x8081, 0x8080, 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074,
-	0x8073, 0x8072, 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a,
-	0x5b69, 0x8067, 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, 0x5559,
-	0x8056, 0x8055, 0x5454, 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d,
-	0x804c, 0x804b, 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043,
-	0x803c, 0x803a, 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932,
-	0x4831, 0x802e, 0x472d, 0x462c, 0x452b, 0x442a, 0x4329, 0x4227,
-	0x8026, 0x8025, 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18,
-	0x8017, 0x8010, 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000,
-	0x8000, 0x3800, 0x3700, 0x3600, 0x8000, 0x3500, 0x8000, 0x8000,
-	0x8000, 0x3400, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
-	0x3300, 0x3200, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
-	0x3100, 0x3000, 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00,
-	0x2c00, 0x8000, 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900,
-	0x2800, 0x8000, 0x2700, 0x2600, 0x2500, 0x2400, 0x2300, 0x2200,
-	0x8000, 0x8000, 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00,
-	0x8000, 0x8000, 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x1800, 0x8000, 0x1700, 0x1600,
-	0x1500, 0x8000, 0x1400, 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00,
-	0x8000, 0x8000, 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900,
-	0x8000, 0x8000, 0x0800, 0x0700, 0x8000, 0x0600, 0x8000, 0x8000,
-	0x8000, 0x0500, 0x0400, 0x0300, 0x8000, 0x0200, 0x8000, 0x8000,
-	0x8000, 0x0100, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
-	0x0000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
+	0x6908, 0x2001, 0x04fd, 0x2004, 0xa086, 0x0007, 0x0040, 0x1bc9,
+	0xa184, 0x0007, 0x0040, 0x1bc9, 0x017e, 0x2009, 0x0008, 0xa102,
+	0x017f, 0xa108, 0x791a, 0x7116, 0x701e, 0x680c, 0xa081, 0x0000,
+	0x781e, 0x701a, 0xa006, 0x700e, 0x7012, 0x7004, 0x692c, 0x6814,
+	0xa106, 0x00c0, 0x1be0, 0x6928, 0x6810, 0xa106, 0x0040, 0x1bed,
+	0x037e, 0x047e, 0x6b14, 0x6c10, 0x1078, 0x1e0f, 0x047f, 0x037f,
+	0x0040, 0x1bed, 0x0c7f, 0x0078, 0x1c07, 0x8aff, 0x00c0, 0x1bf5,
+	0x0c7f, 0xa085, 0x0001, 0x0078, 0x1c07, 0x127e, 0x2091, 0x8000,
+	0x2079, 0x0020, 0x2009, 0x0001, 0x1078, 0x1c0b, 0x0040, 0x1c04,
+	0x2009, 0x0001, 0x1078, 0x1c0b, 0x127f, 0x0c7f, 0xa006, 0x0d7f,
+	0x0e7f, 0x0f7f, 0x007c, 0x077e, 0x067e, 0x057e, 0x047e, 0x037e,
+	0x027e, 0x8aff, 0x0040, 0x1c89, 0x700c, 0x7214, 0xa23a, 0x7010,
+	0x7218, 0xa203, 0x0048, 0x1c88, 0xa705, 0x0040, 0x1c88, 0xa03e,
+	0x2730, 0x6850, 0xd0fc, 0x00c0, 0x1c3b, 0x0d7e, 0x2804, 0xac68,
+	0x2900, 0x0079, 0x1c2b, 0x1c6a, 0x1c4b, 0x1c4b, 0x1c6a, 0x1c6a,
+	0x1c62, 0x1c6a, 0x1c4b, 0x1c6a, 0x1c51, 0x1c51, 0x1c6a, 0x1c6a,
+	0x1c6a, 0x1c59, 0x1c51, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c,
+	0x6c20, 0xd99c, 0x0040, 0x1c6e, 0x0d7e, 0x2804, 0xac68, 0x6f08,
+	0x6e0c, 0x0078, 0x1c6d, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x0078,
+	0x1c6d, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0078,
+	0x1c6d, 0x0d7f, 0x0d7e, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e,
+	0x00c0, 0x1c6a, 0x0d7f, 0x1078, 0x1dab, 0x00c0, 0x1c11, 0xa00e,
+	0x0078, 0x1c89, 0x0d7f, 0x1078, 0x12d2, 0x0d7f, 0x7b22, 0x7a26,
+	0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902, 0x7000, 0x8000, 0x7002,
+	0x6828, 0xa300, 0x682a, 0x682c, 0xa201, 0x682e, 0x700c, 0xa300,
+	0x700e, 0x7010, 0xa201, 0x7012, 0x1078, 0x1dab, 0x0078, 0x1c89,
+	0xa006, 0x027f, 0x037f, 0x047f, 0x057f, 0x067f, 0x077f, 0x007c,
+	0x1078, 0x12d2, 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040,
+	0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x0d7e, 0x6010,
+	0x2068, 0x1078, 0x77ed, 0x0040, 0x1ca8, 0x6850, 0xc0bd, 0x6852,
+	0x0d7f, 0x1078, 0x759a, 0x20e1, 0x9040, 0x1078, 0x6753, 0x2011,
+	0x0000, 0x1078, 0x64b8, 0x1078, 0x5948, 0x0078, 0x1d7c, 0x127e,
+	0x2091, 0x2200, 0x007e, 0x017e, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e,
+	0x2079, 0x0020, 0x2071, 0x8af9, 0x2b68, 0x6818, 0x2060, 0x7904,
+	0x7803, 0x0002, 0xa184, 0x0700, 0x00c0, 0x1c92, 0x7000, 0x0079,
+	0x1cd1, 0x1d7c, 0x1cd5, 0x1d49, 0x1d7a, 0x8001, 0x7002, 0xd19c,
+	0x00c0, 0x1ce9, 0x8aff, 0x0040, 0x1d08, 0x2009, 0x0001, 0x1078,
+	0x1c0b, 0x0040, 0x1d7c, 0x2009, 0x0001, 0x1078, 0x1c0b, 0x0078,
+	0x1d7c, 0x7803, 0x0004, 0xd194, 0x0040, 0x1cf9, 0x6850, 0xc0fc,
+	0x6852, 0x8aff, 0x00c0, 0x1cfe, 0x684c, 0xc0f5, 0x684e, 0x0078,
+	0x1cfe, 0x1078, 0x1dc4, 0x6850, 0xc0fd, 0x6852, 0x2a00, 0x6826,
+	0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, 0x0000, 0x0078, 0x1d7c,
+	0x711c, 0x81ff, 0x0040, 0x1d1e, 0x7918, 0x7922, 0x7827, 0x0000,
+	0x7803, 0x0001, 0x7000, 0x8000, 0x7002, 0x700c, 0xa100, 0x700e,
+	0x7010, 0xa081, 0x0000, 0x7012, 0x0078, 0x1d7c, 0x0f7e, 0x027e,
+	0x781c, 0x007e, 0x7818, 0x007e, 0x2079, 0x0100, 0x7a14, 0xa284,
+	0x0004, 0xa085, 0x0012, 0x7816, 0x7820, 0xd0bc, 0x00c0, 0x1d2c,
+	0x79c8, 0x007f, 0xa102, 0x017f, 0x007e, 0x017e, 0x79c4, 0x007f,
+	0xa102, 0x78c6, 0x007f, 0x78ca, 0xa284, 0x0004, 0xa085, 0x0012,
+	0x7816, 0x027f, 0x0f7f, 0x7803, 0x0008, 0x7003, 0x0000, 0x0078,
+	0x1d7c, 0x8001, 0x7002, 0xd194, 0x0040, 0x1d5e, 0x7804, 0xd0fc,
+	0x00c0, 0x1cc7, 0xd19c, 0x00c0, 0x1d78, 0x8aff, 0x0040, 0x1d7c,
+	0x2009, 0x0001, 0x1078, 0x1c0b, 0x0078, 0x1d7c, 0x027e, 0x037e,
+	0x6b28, 0x6a2c, 0x1078, 0x1dc4, 0x0d7e, 0x2804, 0xac68, 0x6034,
+	0xd09c, 0x00c0, 0x1d71, 0x6808, 0xa31a, 0x680c, 0xa213, 0x0078,
+	0x1d75, 0x6810, 0xa31a, 0x6814, 0xa213, 0x0d7f, 0x0078, 0x1cf9,
+	0x0078, 0x1cf9, 0x1078, 0x12d2, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f,
+	0x017f, 0x007f, 0x127f, 0x007c, 0x0f7e, 0x0e7e, 0x2071, 0x8af9,
+	0x7000, 0xa086, 0x0000, 0x0040, 0x1da8, 0x2079, 0x0020, 0x20e1,
+	0x9040, 0x7804, 0xd0fc, 0x0040, 0x1d8f, 0x1078, 0x1cb7, 0x7000,
+	0xa086, 0x0000, 0x00c0, 0x1d8f, 0x7803, 0x0004, 0x7804, 0xd0ac,
+	0x00c0, 0x1d9e, 0x20e1, 0x9040, 0x7803, 0x0002, 0x7003, 0x0000,
+	0x0e7f, 0x0f7f, 0x007c, 0x8840, 0x2804, 0xa005, 0x00c0, 0x1dbf,
+	0x6004, 0xa005, 0x0040, 0x1dc1, 0x681a, 0x2060, 0x6034, 0xa084,
+	0x000f, 0xa080, 0x1def, 0x2044, 0x88ff, 0x1040, 0x12d2, 0x8a51,
+	0x007c, 0x2051, 0x0000, 0x007c, 0x8a50, 0x8841, 0x2804, 0xa005,
+	0x00c0, 0x1dde, 0x2c00, 0xad06, 0x0040, 0x1dd3, 0x6000, 0xa005,
+	0x00c0, 0x1dd3, 0x2d00, 0x2060, 0x681a, 0x6034, 0xa084, 0x000f,
+	0xa080, 0x1dff, 0x2044, 0x88ff, 0x1040, 0x12d2, 0x007c, 0x0000,
+	0x0011, 0x0015, 0x0019, 0x001d, 0x0021, 0x0025, 0x0029, 0x0000,
+	0x000f, 0x0015, 0x001b, 0x0021, 0x0027, 0x0000, 0x0000, 0x0000,
+	0x1de4, 0x1de0, 0x0000, 0x0000, 0x1dee, 0x0000, 0x1de4, 0x0000,
+	0x1deb, 0x1de8, 0x0000, 0x0000, 0x0000, 0x1dee, 0x1deb, 0x0000,
+	0x1de6, 0x1de6, 0x0000, 0x0000, 0x1dee, 0x0000, 0x1de6, 0x0000,
+	0x1dec, 0x1dec, 0x0000, 0x0000, 0x0000, 0x1dee, 0x1dec, 0x0a7e,
+	0x097e, 0x087e, 0x6858, 0xa055, 0x0040, 0x1eb0, 0x2d60, 0x6034,
+	0xa0cc, 0x000f, 0xa9c0, 0x1def, 0xa986, 0x0007, 0x0040, 0x1e28,
+	0xa986, 0x000e, 0x0040, 0x1e28, 0xa986, 0x000f, 0x00c0, 0x1e2c,
+	0x605c, 0xa422, 0x6060, 0xa31a, 0x2804, 0xa045, 0x00c0, 0x1e3a,
+	0x0050, 0x1e34, 0x0078, 0x1eb0, 0x6004, 0xa065, 0x0040, 0x1eb0,
+	0x0078, 0x1e17, 0x2804, 0xa005, 0x0040, 0x1e58, 0xac68, 0xd99c,
+	0x00c0, 0x1e48, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0078, 0x1e4c,
+	0x6810, 0xa422, 0x6814, 0xa31b, 0x0048, 0x1e77, 0x2300, 0xa405,
+	0x0040, 0x1e5e, 0x8a51, 0x0040, 0x1eb0, 0x8840, 0x0078, 0x1e3a,
+	0x6004, 0xa065, 0x0040, 0x1eb0, 0x0078, 0x1e17, 0x8a51, 0x0040,
+	0x1eb0, 0x8840, 0x2804, 0xa005, 0x00c0, 0x1e71, 0x6004, 0xa065,
+	0x0040, 0x1eb0, 0x6034, 0xa0cc, 0x000f, 0xa9c0, 0x1def, 0x2804,
+	0x2040, 0x2b68, 0x6850, 0xc0fc, 0x6852, 0x0078, 0x1ea4, 0x8422,
+	0x8420, 0x831a, 0xa399, 0x0000, 0x0d7e, 0x2b68, 0x6c6e, 0x6b72,
+	0x0d7f, 0xd99c, 0x00c0, 0x1e92, 0x6908, 0x2400, 0xa122, 0x690c,
+	0x2300, 0xa11b, 0x1048, 0x12d2, 0x6800, 0xa420, 0x6804, 0xa319,
+	0x0078, 0x1e9e, 0x6910, 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b,
+	0x1048, 0x12d2, 0x6800, 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e,
+	0x6b22, 0x6850, 0xc0fd, 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832,
+	0x2a00, 0x6826, 0x007f, 0x007f, 0x007f, 0xa006, 0x0078, 0x1eb5,
+	0x087f, 0x097f, 0x0a7f, 0xa085, 0x0001, 0x007c, 0x2001, 0x0005,
+	0x2004, 0xa084, 0x0007, 0x0079, 0x1ebd, 0x1ec5, 0x1ec6, 0x1ec9,
+	0x1ecc, 0x1ed1, 0x1ed4, 0x1ed9, 0x1ede, 0x007c, 0x1078, 0x1cb7,
+	0x007c, 0x1078, 0x1816, 0x007c, 0x1078, 0x1816, 0x1078, 0x1cb7,
+	0x007c, 0x1078, 0x145a, 0x007c, 0x1078, 0x1cb7, 0x1078, 0x145a,
+	0x007c, 0x1078, 0x1816, 0x1078, 0x145a, 0x007c, 0x1078, 0x1816,
+	0x1078, 0x1cb7, 0x1078, 0x145a, 0x007c, 0x127e, 0x2091, 0x2300,
+	0x2079, 0x0200, 0x2071, 0x8d80, 0x2069, 0x8800, 0x2009, 0x0004,
+	0x7912, 0x7817, 0x0004, 0x1078, 0x2220, 0x781b, 0x0002, 0x20e1,
+	0x8700, 0x127f, 0x007c, 0x127e, 0x2091, 0x2300, 0x781c, 0xa084,
+	0x0007, 0x0079, 0x1f03, 0x1f27, 0x1f0b, 0x1f0f, 0x1f13, 0x1f19,
+	0x1f1d, 0x1f21, 0x1f25, 0x1078, 0x4cc0, 0x0078, 0x1f27, 0x1078,
+	0x4cef, 0x0078, 0x1f27, 0x1078, 0x4cc0, 0x1078, 0x4cef, 0x0078,
+	0x1f27, 0x1078, 0x1f29, 0x0078, 0x1f27, 0x1078, 0x1f29, 0x0078,
+	0x1f27, 0x1078, 0x1f29, 0x0078, 0x1f27, 0x1078, 0x1f29, 0x127f,
+	0x007c, 0x007e, 0x017e, 0x027e, 0x7930, 0xa184, 0x0003, 0x0040,
+	0x1f35, 0x20e1, 0x9040, 0x0078, 0x1f52, 0xa184, 0x0030, 0x0040,
+	0x1f46, 0x6a00, 0xa286, 0x0003, 0x00c0, 0x1f40, 0x0078, 0x1f42,
+	0x1078, 0x3c73, 0x20e1, 0x9010, 0x0078, 0x1f52, 0xa184, 0x00c0,
+	0x0040, 0x1f4c, 0x1078, 0x12d2, 0xa184, 0x0300, 0x0040, 0x1f52,
+	0x20e1, 0x9020, 0x7932, 0x027f, 0x017f, 0x007f, 0x007c, 0x017e,
+	0x0e7e, 0x0f7e, 0x2071, 0x8800, 0x7128, 0x2001, 0x8a8f, 0x2102,
+	0x2001, 0x8a97, 0x2102, 0xa182, 0x0211, 0x00c8, 0x1f6b, 0x2009,
+	0x0008, 0x0078, 0x1f95, 0xa182, 0x0259, 0x00c8, 0x1f73, 0x2009,
+	0x0007, 0x0078, 0x1f95, 0xa182, 0x02c1, 0x00c8, 0x1f7b, 0x2009,
+	0x0006, 0x0078, 0x1f95, 0xa182, 0x0349, 0x00c8, 0x1f83, 0x2009,
+	0x0005, 0x0078, 0x1f95, 0xa182, 0x0421, 0x00c8, 0x1f8b, 0x2009,
+	0x0004, 0x0078, 0x1f95, 0xa182, 0x0581, 0x00c8, 0x1f93, 0x2009,
+	0x0003, 0x0078, 0x1f95, 0x2009, 0x0002, 0x2079, 0x0200, 0x7912,
+	0x7817, 0x0004, 0x1078, 0x2220, 0x0f7f, 0x0e7f, 0x017f, 0x007c,
+	0x127e, 0x2091, 0x2200, 0x2061, 0x0100, 0x2071, 0x8800, 0x6024,
+	0x6026, 0x6053, 0x0030, 0x6033, 0x00ef, 0x60e7, 0x0000, 0x60eb,
+	0x00ef, 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f,
+	0x0080, 0x602f, 0x0000, 0x6007, 0x0eaf, 0x600f, 0x00ff, 0x602b,
+	0x002f, 0x127f, 0x007c, 0x2001, 0x882e, 0x2003, 0x0000, 0x2001,
+	0x882d, 0x2003, 0x0001, 0x007c, 0x127e, 0x2091, 0x2200, 0x007e,
+	0x017e, 0x027e, 0x6124, 0xa184, 0x002c, 0x00c0, 0x1fdb, 0xa184,
+	0x0007, 0x0079, 0x1fe1, 0xa195, 0x0004, 0xa284, 0x0007, 0x0079,
+	0x1fe1, 0x200d, 0x1fe9, 0x1fed, 0x1ff1, 0x1ff7, 0x1ffb, 0x2001,
+	0x2007, 0x1078, 0x5273, 0x0078, 0x200d, 0x1078, 0x5362, 0x0078,
+	0x200d, 0x1078, 0x5362, 0x1078, 0x5273, 0x0078, 0x200d, 0x1078,
+	0x2012, 0x0078, 0x200d, 0x1078, 0x5273, 0x1078, 0x2012, 0x0078,
+	0x200d, 0x1078, 0x5362, 0x1078, 0x2012, 0x0078, 0x200d, 0x1078,
+	0x5362, 0x1078, 0x5273, 0x1078, 0x2012, 0x027f, 0x017f, 0x007f,
+	0x127f, 0x007c, 0xd1ac, 0x0040, 0x20ec, 0x017e, 0x047e, 0x0c7e,
+	0x644c, 0xa486, 0xf0f0, 0x00c0, 0x2024, 0x2061, 0x0100, 0x644a,
+	0x6043, 0x0090, 0x6043, 0x0010, 0x74be, 0xa48c, 0xff00, 0x7034,
+	0xd084, 0x0040, 0x203c, 0xa186, 0xf800, 0x00c0, 0x203c, 0x7038,
+	0xd084, 0x00c0, 0x203c, 0xc085, 0x703a, 0x037e, 0x2418, 0x2011,
+	0x8016, 0x1078, 0x317a, 0x037f, 0xa196, 0xff00, 0x0040, 0x2061,
+	0x6030, 0xa084, 0x00ff, 0x810f, 0xa116, 0x0040, 0x2061, 0x7130,
+	0xd18c, 0x00c0, 0x2061, 0x2011, 0x8852, 0x2214, 0xd2ec, 0x0040,
+	0x2055, 0xc18d, 0x7132, 0x0078, 0x2061, 0x6240, 0xa294, 0x0010,
+	0x0040, 0x20af, 0x6248, 0xa294, 0xff00, 0xa296, 0xff00, 0x00c0,
+	0x20af, 0x7034, 0xd08c, 0x00c0, 0x206d, 0x2001, 0x880c, 0x200c,
+	0xd1ac, 0x00c0, 0x20af, 0xc1ad, 0x2102, 0x037e, 0x73bc, 0x2011,
+	0x8013, 0x1078, 0x317a, 0x037f, 0x7130, 0xc185, 0x7132, 0x2011,
+	0x8852, 0x220c, 0xd1a4, 0x0040, 0x2097, 0x017e, 0x2009, 0x0001,
+	0x2011, 0x0100, 0x1078, 0x5243, 0x2019, 0x000e, 0x1078, 0x8683,
+	0xa484, 0x00ff, 0xa080, 0x25b2, 0x200c, 0xa18c, 0xff00, 0x810f,
+	0x8127, 0xa006, 0x2009, 0x000e, 0x1078, 0x86f5, 0x017f, 0xd1ac,
+	0x00c0, 0x20a0, 0x2019, 0x0004, 0x1078, 0x249d, 0x0078, 0x20af,
+	0x157e, 0x20a9, 0x007f, 0x2009, 0x0000, 0x1078, 0x3f8e, 0x00c0,
+	0x20ab, 0x1078, 0x3d31, 0x8108, 0x00f0, 0x20a5, 0x157f, 0x0c7f,
+	0x047f, 0x0f7e, 0x2079, 0x8ab5, 0x783c, 0xa086, 0x0000, 0x0040,
+	0x20c1, 0x6027, 0x0004, 0x783f, 0x0000, 0x2079, 0x0140, 0x7803,
+	0x0000, 0x0f7f, 0x2011, 0x0003, 0x1078, 0x64ae, 0x2011, 0x0002,
+	0x1078, 0x64b8, 0x1078, 0x639b, 0x1078, 0x516f, 0x037e, 0x2019,
+	0x0000, 0x1078, 0x642d, 0x037f, 0x60e3, 0x0000, 0x017f, 0x2001,
+	0x8800, 0x2014, 0xa296, 0x0004, 0x00c0, 0x20e4, 0xd19c, 0x00c0,
+	0x20e4, 0x6228, 0xc29d, 0x622a, 0x2003, 0x0001, 0x2001, 0x8821,
+	0x2003, 0x0000, 0x6027, 0x0020, 0xd194, 0x0040, 0x21c7, 0x0f7e,
+	0x2079, 0x8ab5, 0x783c, 0xa086, 0x0001, 0x00c0, 0x2110, 0x017e,
+	0x6027, 0x0004, 0x783f, 0x0000, 0x2079, 0x0140, 0x7803, 0x1000,
+	0x7803, 0x0000, 0x2079, 0x8aa2, 0x7807, 0x0000, 0x7833, 0x0000,
+	0x1078, 0x5888, 0x1078, 0x5948, 0x017f, 0x0f7f, 0x0078, 0x21c7,
+	0x0f7f, 0x017e, 0x6220, 0xd2b4, 0x0040, 0x217d, 0x1078, 0x516f,
+	0x1078, 0x6232, 0x6027, 0x0004, 0x0f7e, 0x2019, 0x8aab, 0x2304,
+	0xa07d, 0x0040, 0x2153, 0x7804, 0xa086, 0x0032, 0x00c0, 0x2153,
+	0x0d7e, 0x0c7e, 0x0e7e, 0x2069, 0x0140, 0x618c, 0x6288, 0x7818,
+	0x608e, 0x7808, 0x608a, 0x6043, 0x0002, 0x2001, 0x0003, 0x8001,
+	0x00c0, 0x2137, 0x6043, 0x0000, 0x6803, 0x1000, 0x6803, 0x0000,
+	0x618e, 0x628a, 0x1078, 0x578f, 0x1078, 0x5888, 0x7810, 0x2070,
+	0x7037, 0x0103, 0x2f60, 0x1078, 0x690e, 0x0e7f, 0x0c7f, 0x0d7f,
+	0x0f7f, 0x017f, 0x007c, 0x0f7f, 0x0d7e, 0x2069, 0x0140, 0x6804,
+	0xa084, 0x4000, 0x0040, 0x2160, 0x6803, 0x1000, 0x6803, 0x0000,
+	0x0d7f, 0x0c7e, 0x2061, 0x8aa2, 0x6028, 0xa09a, 0x0002, 0x00c8,
+	0x2170, 0x8000, 0x602a, 0x0c7f, 0x1078, 0x6224, 0x0078, 0x21c6,
+	0x2019, 0x8aab, 0x2304, 0xa065, 0x0040, 0x217a, 0x2009, 0x0027,
+	0x1078, 0x6939, 0x0c7f, 0x0078, 0x21c6, 0xd2bc, 0x0040, 0x21c6,
+	0x1078, 0x517c, 0x6017, 0x0010, 0x6027, 0x0004, 0x0d7e, 0x2069,
+	0x0140, 0x6804, 0xa084, 0x4000, 0x0040, 0x2192, 0x6803, 0x1000,
+	0x6803, 0x0000, 0x0d7f, 0x0c7e, 0x2061, 0x8aa2, 0x6044, 0xa09a,
+	0x0002, 0x00c8, 0x21b5, 0x8000, 0x6046, 0x603c, 0x0c7f, 0xa005,
+	0x0040, 0x21c6, 0x2009, 0x07d0, 0x1078, 0x5174, 0xa080, 0x0007,
+	0x2004, 0xa086, 0x0006, 0x00c0, 0x21b1, 0x6017, 0x0012, 0x0078,
+	0x21c6, 0x6017, 0x0016, 0x0078, 0x21c6, 0x037e, 0x2019, 0x0001,
+	0x1078, 0x642d, 0x037f, 0x2019, 0x8ab1, 0x2304, 0xa065, 0x0040,
+	0x21c5, 0x2009, 0x004f, 0x1078, 0x6939, 0x0c7f, 0x017f, 0xd19c,
+	0x0040, 0x21ef, 0x017e, 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003,
+	0x1078, 0x64ae, 0x2011, 0x0002, 0x1078, 0x64b8, 0x1078, 0x639b,
+	0x1078, 0x516f, 0x037e, 0x2019, 0x0000, 0x1078, 0x642d, 0x037f,
+	0x60e3, 0x0000, 0x1078, 0x876a, 0x1078, 0x8788, 0x2001, 0x8800,
+	0x2003, 0x0004, 0x6027, 0x0008, 0x1078, 0x1208, 0x017f, 0xa18c,
+	0xffd0, 0x6126, 0x007c, 0x007e, 0x017e, 0x027e, 0x0e7e, 0x0f7e,
+	0x127e, 0x2091, 0x8000, 0x2071, 0x8800, 0x71b4, 0x70b6, 0xa116,
+	0x0040, 0x2219, 0x81ff, 0x0040, 0x220b, 0x2011, 0x8011, 0x1078,
+	0x317a, 0x0078, 0x2219, 0x2011, 0x8012, 0x1078, 0x317a, 0x037e,
+	0x0c7e, 0x2061, 0x0100, 0x2019, 0x0028, 0x1078, 0x249d, 0x0c7f,
+	0x037f, 0x127f, 0x0f7f, 0x0e7f, 0x027f, 0x017f, 0x007f, 0x007c,
+	0x0c7e, 0x0f7e, 0x007e, 0x027e, 0x2061, 0x0100, 0xa190, 0x2233,
+	0x2204, 0x60f2, 0x2011, 0x2240, 0x2204, 0x60ee, 0x027f, 0x007f,
+	0x0f7f, 0x0c7f, 0x007c, 0x0840, 0x0840, 0x0840, 0x0580, 0x0420,
+	0x0348, 0x02c0, 0x0258, 0x0210, 0x01a8, 0x01a8, 0x01a8, 0x01a8,
+	0x0140, 0x00f8, 0x00d0, 0x00b0, 0x00a0, 0x2028, 0xa18c, 0x00ff,
+	0x2130, 0xa094, 0xff00, 0x00c0, 0x2250, 0x81ff, 0x0040, 0x2254,
+	0x1078, 0x4e98, 0x0078, 0x225b, 0xa080, 0x25b2, 0x200c, 0xa18c,
+	0xff00, 0x810f, 0xa006, 0x007c, 0xa080, 0x25b2, 0x200c, 0xa18c,
+	0x00ff, 0x007c, 0x0c7e, 0x2061, 0x8800, 0x6030, 0x0040, 0x226b,
+	0xc09d, 0x0078, 0x226c, 0xc09c, 0x6032, 0x0c7f, 0x007c, 0x228f,
+	0x2293, 0x2297, 0x229d, 0x22a3, 0x22a9, 0x22af, 0x22b7, 0x22bf,
+	0x22c5, 0x22cb, 0x22d3, 0x22db, 0x22e3, 0x22eb, 0x22f5, 0x22ff,
+	0x22ff, 0x22ff, 0x22ff, 0x22ff, 0x22ff, 0x22ff, 0x22ff, 0x22ff,
+	0x22ff, 0x22ff, 0x22ff, 0x22ff, 0x22ff, 0x22ff, 0x22ff, 0x107e,
+	0x007e, 0x0078, 0x2318, 0x107e, 0x007e, 0x0078, 0x2318, 0x107e,
+	0x007e, 0x1078, 0x1fcc, 0x0078, 0x2318, 0x107e, 0x007e, 0x1078,
+	0x1fcc, 0x0078, 0x2318, 0x107e, 0x007e, 0x1078, 0x1eb6, 0x0078,
+	0x2318, 0x107e, 0x007e, 0x1078, 0x1eb6, 0x0078, 0x2318, 0x107e,
+	0x007e, 0x1078, 0x1fcc, 0x1078, 0x1eb6, 0x0078, 0x2318, 0x107e,
+	0x007e, 0x1078, 0x1fcc, 0x1078, 0x1eb6, 0x0078, 0x2318, 0x107e,
+	0x007e, 0x1078, 0x1efb, 0x0078, 0x2318, 0x107e, 0x007e, 0x1078,
+	0x1efb, 0x0078, 0x2318, 0x107e, 0x007e, 0x1078, 0x1fcc, 0x1078,
+	0x1efb, 0x0078, 0x2318, 0x107e, 0x007e, 0x1078, 0x1fcc, 0x1078,
+	0x1efb, 0x0078, 0x2318, 0x107e, 0x007e, 0x1078, 0x1eb6, 0x1078,
+	0x1efb, 0x0078, 0x2318, 0x107e, 0x007e, 0x1078, 0x1eb6, 0x1078,
+	0x1efb, 0x0078, 0x2318, 0x107e, 0x007e, 0x1078, 0x1fcc, 0x1078,
+	0x1eb6, 0x1078, 0x1efb, 0x0078, 0x2318, 0x107e, 0x007e, 0x1078,
+	0x1fcc, 0x1078, 0x1eb6, 0x1078, 0x1efb, 0x0078, 0x2318, 0x0005,
+	0x0078, 0x22ff, 0xb084, 0x003c, 0x8004, 0x8004, 0x0079, 0x2308,
+	0x2318, 0x2295, 0x2299, 0x229f, 0x22a5, 0x22ab, 0x22b1, 0x22b9,
+	0x22c1, 0x22c7, 0x22cd, 0x22d5, 0x22dd, 0x22e5, 0x22ed, 0x22f7,
+	0x0008, 0x2302, 0x007f, 0x107f, 0x2091, 0x8001, 0x007c, 0x0c7e,
+	0x027e, 0x2041, 0x007e, 0x70c0, 0xd09c, 0x0040, 0x2329, 0x2041,
+	0x007f, 0xd094, 0x2001, 0x010c, 0x203c, 0x00c0, 0x2388, 0x7280,
+	0xd284, 0x0040, 0x2388, 0xd28c, 0x00c0, 0x2388, 0x037e, 0x7390,
+	0xa38e, 0xffff, 0x00c0, 0x233e, 0x2019, 0x0001, 0x8314, 0xa2e0,
+	0x8ec0, 0x2c04, 0xa38c, 0x0001, 0x0040, 0x234b, 0xa084, 0xff00,
+	0x8007, 0x0078, 0x234d, 0xa084, 0x00ff, 0xa70e, 0x0040, 0x237d,
+	0xa08e, 0x00ff, 0x00c0, 0x2362, 0x2011, 0x8852, 0x2214, 0xd2ec,
+	0x00c0, 0x2383, 0x7280, 0xc28d, 0x7282, 0x7093, 0xffff, 0x037f,
+	0x0078, 0x2388, 0x2009, 0x0000, 0x1078, 0x2245, 0x1078, 0x3f53,
+	0x00c0, 0x2380, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0,
+	0x2377, 0x1078, 0x23ef, 0x0040, 0x2380, 0x0078, 0x237d, 0x1078,
+	0x2503, 0x1078, 0x241c, 0x0040, 0x2380, 0x8318, 0x0078, 0x233e,
+	0x7392, 0x0078, 0x2385, 0x7093, 0xffff, 0x037f, 0x0078, 0x23ec,
+	0xa780, 0x25b2, 0x203c, 0xa7bc, 0xff00, 0x873f, 0x7090, 0xa096,
+	0xffff, 0x0040, 0x239a, 0xa812, 0x00c8, 0x23aa, 0x7093, 0xffff,
+	0x0078, 0x23e9, 0x2009, 0x0000, 0x70c0, 0xd09c, 0x0040, 0x23a5,
+	0xd094, 0x0040, 0x23a5, 0x2009, 0x007e, 0x2100, 0xa802, 0x20a8,
+	0x0078, 0x23ae, 0x2008, 0x2810, 0xa202, 0x20a8, 0x2700, 0x157e,
+	0x017e, 0xa106, 0x0040, 0x23e0, 0x1078, 0x3f53, 0x00c0, 0x23e9,
+	0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x23c5, 0x1078,
+	0x257d, 0x0040, 0x23e0, 0x0078, 0x23d4, 0x7280, 0xd28c, 0x0040,
+	0x23da, 0x6004, 0xa084, 0x00ff, 0xa082, 0x0006, 0x0048, 0x23e0,
+	0x1078, 0x3f76, 0x0078, 0x23e0, 0x1078, 0x23ef, 0x0040, 0x23e9,
+	0x0078, 0x23e0, 0x1078, 0x2503, 0x1078, 0x241c, 0x0040, 0x23e9,
+	0x017f, 0x8108, 0x157f, 0x00f0, 0x23ae, 0x7093, 0xffff, 0x0078,
+	0x23ec, 0x017f, 0x157f, 0x7192, 0x027f, 0x0c7f, 0x007c, 0x017e,
+	0x077e, 0x0d7e, 0x0c7e, 0x2c68, 0x2001, 0x8856, 0x2004, 0xa084,
+	0x00ff, 0x6842, 0x1078, 0x68a8, 0x0040, 0x2417, 0x2d00, 0x601a,
+	0x601f, 0x0001, 0x2001, 0x0000, 0x1078, 0x3ef1, 0x2001, 0x0000,
+	0x1078, 0x3f05, 0x127e, 0x2091, 0x8000, 0x708c, 0x8000, 0x708e,
+	0x127f, 0x2009, 0x0004, 0x1078, 0x6939, 0xa085, 0x0001, 0x0c7f,
+	0x0d7f, 0x077f, 0x017f, 0x007c, 0x017e, 0x077e, 0x0d7e, 0x0c7e,
+	0x2c68, 0x2001, 0x8856, 0x2004, 0xa084, 0x00ff, 0x6842, 0x1078,
+	0x68a8, 0x0040, 0x2444, 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001,
+	0x0000, 0x1078, 0x3ef1, 0x2001, 0x0002, 0x1078, 0x3f05, 0x127e,
+	0x2091, 0x8000, 0x708c, 0x8000, 0x708e, 0x127f, 0x2009, 0x0002,
+	0x1078, 0x6939, 0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f,
+	0x007c, 0x0c7e, 0x027e, 0x2009, 0x0080, 0x1078, 0x3f53, 0x00c0,
+	0x2457, 0x1078, 0x245a, 0x0040, 0x2457, 0x70c7, 0xffff, 0x027f,
+	0x0c7f, 0x007c, 0x017e, 0x077e, 0x0d7e, 0x0c7e, 0x2c68, 0x1078,
+	0x68a8, 0x0040, 0x247c, 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001,
+	0x0000, 0x1078, 0x3ef1, 0x2001, 0x0002, 0x1078, 0x3f05, 0x127e,
+	0x2091, 0x8000, 0x70c8, 0x8000, 0x70ca, 0x127f, 0x2009, 0x0002,
+	0x1078, 0x6939, 0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f,
+	0x007c, 0x0c7e, 0x0d7e, 0x2009, 0x007f, 0x1078, 0x3f53, 0x00c0,
+	0x249a, 0x2c68, 0x1078, 0x68a8, 0x0040, 0x249a, 0x2d00, 0x601a,
+	0x6312, 0x601f, 0x0001, 0x620a, 0x2009, 0x0022, 0x1078, 0x6939,
+	0xa085, 0x0001, 0x0d7f, 0x0c7f, 0x007c, 0x0e7e, 0x0c7e, 0x067e,
+	0x037e, 0x027e, 0x1078, 0x54fd, 0x1078, 0x549f, 0x1078, 0x6ea5,
+	0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x3f8e, 0x00c0,
+	0x24b5, 0x1078, 0x418b, 0x1078, 0x3d31, 0x017f, 0x8108, 0x00f0,
+	0x24ac, 0x027f, 0x037f, 0x067f, 0x0c7f, 0x0e7f, 0x007c, 0x0e7e,
+	0x0c7e, 0x037e, 0x027e, 0x017e, 0x6218, 0x2270, 0x72a0, 0x027e,
+	0x2019, 0x0029, 0x1078, 0x54f0, 0x087e, 0x2041, 0x0000, 0x1078,
+	0x5419, 0x2c08, 0x1078, 0x84d2, 0x087f, 0x017f, 0x2e60, 0x1078,
+	0x418b, 0x6210, 0x6314, 0x1078, 0x3d31, 0x6212, 0x6316, 0x017f,
+	0x027f, 0x037f, 0x0c7f, 0x0e7f, 0x007c, 0x0e7e, 0x007e, 0x6018,
+	0xa080, 0x0028, 0x2004, 0xd0bc, 0x00c0, 0x24f9, 0x2071, 0x8800,
+	0x708c, 0xa005, 0x0040, 0x24f6, 0x8001, 0x708e, 0x007f, 0x0e7f,
+	0x007c, 0x2071, 0x8800, 0x70c8, 0xa005, 0x0040, 0x24f6, 0x8001,
+	0x70ca, 0x0078, 0x24f6, 0x6000, 0xc08c, 0x6002, 0x007c, 0x0f7e,
+	0x0e7e, 0x0c7e, 0x037e, 0x027e, 0x017e, 0x157e, 0x2178, 0x81ff,
+	0x00c0, 0x2516, 0x20a9, 0x0001, 0x0078, 0x2531, 0x2001, 0x8852,
+	0x2004, 0xd0c4, 0x0040, 0x252d, 0xd0a4, 0x0040, 0x252d, 0x047e,
+	0x6018, 0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427, 0xa006,
+	0x2009, 0x002d, 0x1078, 0x86f5, 0x047f, 0x20a9, 0x00ff, 0x2011,
+	0x0000, 0x027e, 0xa288, 0x8934, 0x210c, 0x81ff, 0x0040, 0x255a,
+	0x8fff, 0x1040, 0x2566, 0x2019, 0x0029, 0x1078, 0x54f0, 0x087e,
+	0x2041, 0x0000, 0x1078, 0x5419, 0x0c7e, 0x027e, 0x2160, 0x6204,
+	0xa294, 0x00ff, 0x2001, 0x0004, 0x8007, 0xa215, 0x6206, 0x027f,
+	0x0c7f, 0x017e, 0x2c08, 0x1078, 0x84d2, 0x017f, 0x087f, 0x2160,
+	0x1078, 0x418b, 0x027f, 0x8210, 0x00f0, 0x2531, 0x157f, 0x017f,
+	0x027f, 0x037f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0x047e, 0x027e,
+	0x017e, 0x2001, 0x8852, 0x2004, 0xd0c4, 0x0040, 0x2579, 0xd0a4,
+	0x0040, 0x2579, 0xa006, 0x2220, 0x8427, 0x2009, 0x0029, 0x1078,
+	0x86f5, 0x017f, 0x027f, 0x047f, 0x007c, 0x017e, 0x027e, 0x037e,
+	0x0c7e, 0x7280, 0x82ff, 0x0040, 0x25ab, 0xa290, 0x8852, 0x2214,
+	0xd2ac, 0x00c0, 0x25ab, 0x2100, 0x1078, 0x225c, 0x81ff, 0x0040,
+	0x25ad, 0x2019, 0x0001, 0x8314, 0xa2e0, 0x8ec0, 0x2c04, 0xd384,
+	0x0040, 0x259f, 0xa084, 0xff00, 0x8007, 0x0078, 0x25a1, 0xa084,
+	0x00ff, 0xa116, 0x0040, 0x25ad, 0xa096, 0x00ff, 0x0040, 0x25ab,
+	0x8318, 0x0078, 0x2593, 0xa085, 0x0001, 0x0c7f, 0x037f, 0x027f,
+	0x017f, 0x007c, 0x7eef, 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0,
+	0x80dc, 0x80da, 0x7ad9, 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2,
+	0x80d1, 0x79ce, 0x78cd, 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7,
+	0x80c6, 0x77c5, 0x76c3, 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5,
+	0x73b4, 0x72b3, 0x80b2, 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab,
+	0x6faa, 0x6ea9, 0x80a7, 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e,
+	0x689d, 0x809b, 0x8098, 0x6797, 0x6690, 0x658f, 0x6488, 0x6384,
+	0x6282, 0x8081, 0x8080, 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075,
+	0x8074, 0x8073, 0x8072, 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b,
+	0x5c6a, 0x5b69, 0x8067, 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a,
+	0x5559, 0x8056, 0x8055, 0x5454, 0x5353, 0x5252, 0x5151, 0x504e,
+	0x4f4d, 0x804c, 0x804b, 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045,
+	0x8043, 0x803c, 0x803a, 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33,
+	0x4932, 0x4831, 0x802e, 0x472d, 0x462c, 0x452b, 0x442a, 0x4329,
+	0x4227, 0x8026, 0x8025, 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b,
+	0x3c18, 0x8017, 0x8010, 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001,
+	0x8000, 0x8000, 0x3800, 0x3700, 0x3600, 0x8000, 0x3500, 0x8000,
+	0x8000, 0x8000, 0x3400, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
+	0x8000, 0x3300, 0x3200, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
+	0x8000, 0x3100, 0x3000, 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00,
+	0x2d00, 0x2c00, 0x8000, 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00,
+	0x2900, 0x2800, 0x8000, 0x2700, 0x2600, 0x2500, 0x2400, 0x2300,
+	0x2200, 0x8000, 0x8000, 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00,
+	0x1c00, 0x8000, 0x8000, 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000,
+	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x1800, 0x8000, 0x1700,
+	0x1600, 0x1500, 0x8000, 0x1400, 0x1300, 0x1200, 0x1100, 0x1000,
+	0x0f00, 0x8000, 0x8000, 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00,
+	0x0900, 0x8000, 0x8000, 0x0800, 0x0700, 0x8000, 0x0600, 0x8000,
+	0x8000, 0x8000, 0x0500, 0x0400, 0x0300, 0x8000, 0x0200, 0x8000,
+	0x8000, 0x8000, 0x0100, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
+	0x8000, 0x0000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
 	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
-	0x8000, 0x2071, 0x776d, 0x7003, 0x0002, 0xa006, 0x7012, 0x7016,
-	0x703a, 0x703e, 0x7033, 0x777d, 0x7037, 0x777d, 0x7007, 0x0001,
-	0x2061, 0x77bd, 0x6003, 0x0002, 0x007c, 0x0090, 0x2450, 0x0068,
-	0x2450, 0x2071, 0x776d, 0x2b78, 0x7818, 0xd084, 0x00c0, 0x2450,
-	0x2a60, 0x7820, 0xa08e, 0x0069, 0x00c0, 0x2537, 0x0079, 0x24d4,
-	0x007c, 0x2071, 0x776d, 0x7004, 0x0079, 0x2456, 0x245a, 0x245b,
-	0x2465, 0x2477, 0x007c, 0x0090, 0x2464, 0x0068, 0x2464, 0x2b78,
-	0x7818, 0xd084, 0x0040, 0x2483, 0x007c, 0x2b78, 0x2061, 0x77bd,
-	0x6008, 0xa08e, 0x0100, 0x0040, 0x2472, 0xa086, 0x0200, 0x0040,
-	0x252f, 0x007c, 0x7014, 0x2068, 0x2a60, 0x7018, 0x007a, 0x7010,
-	0x2068, 0x6834, 0xa086, 0x0103, 0x0040, 0x247f, 0x007c, 0x2a60,
-	0x2b78, 0x7018, 0x007a, 0x2a60, 0x7820, 0xa08a, 0x0040, 0x00c8,
-	0x248c, 0x61b0, 0x0079, 0x2494, 0x2100, 0xa08a, 0x0036, 0x00c8,
-	0x252b, 0x61b0, 0x0079, 0x24d4, 0x250d, 0x253f, 0x2547, 0x254b,
-	0x2553, 0x2559, 0x255d, 0x2566, 0x256a, 0x2572, 0x2576, 0x252b,
-	0x252b, 0x252b, 0x257a, 0x252b, 0x258a, 0x25a1, 0x25b8, 0x2634,
-	0x2639, 0x2666, 0x26c0, 0x26d1, 0x26ef, 0x2722, 0x272c, 0x2739,
-	0x274c, 0x2766, 0x276f, 0x27ac, 0x27b2, 0x252b, 0x27c2, 0x252b,
-	0x252b, 0x252b, 0x252b, 0x252b, 0x27c6, 0x27cc, 0x252b, 0x252b,
-	0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x27d4, 0x252b,
-	0x252b, 0x252b, 0x252b, 0x252b, 0x27e1, 0x27e7, 0x252b, 0x252b,
-	0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b,
-	0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b,
-	0x252b, 0x252b, 0x252b, 0x252b, 0x2572, 0x2576, 0x252b, 0x252b,
-	0x27f9, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b,
-	0x252b, 0x252b, 0x252b, 0x252b, 0x2846, 0x2913, 0x2927, 0x292e,
-	0x2991, 0x29e2, 0x29ed, 0x2a2c, 0x2a3b, 0x2a4a, 0x2a4d, 0x27fd,
-	0x2a76, 0x2abd, 0x2aca, 0x2bc5, 0x2cb3, 0x2cda, 0x2de4, 0x2df2,
-	0x2dff, 0x2e39, 0x713c, 0x0078, 0x250d, 0x2021, 0x4000, 0x1078,
-	0x2d33, 0x127e, 0x2091, 0x8000, 0x0068, 0x251a, 0x7818, 0xd084,
-	0x0040, 0x251d, 0x127f, 0x0078, 0x2511, 0x781b, 0x0001, 0x7c22,
-	0x7926, 0x7a2a, 0x7b2e, 0x2091, 0x4080, 0x7007, 0x0001, 0x2091,
-	0x5000, 0x127f, 0x007c, 0x2021, 0x4001, 0x0078, 0x250f, 0x2021,
-	0x4002, 0x0078, 0x250f, 0x2021, 0x4003, 0x0078, 0x250f, 0x2021,
-	0x4005, 0x0078, 0x250f, 0x2021, 0x4006, 0x0078, 0x250f, 0xa02e,
-	0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0078, 0x2d42, 0x7823,
-	0x0004, 0x7824, 0x007a, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824,
-	0x7930, 0x0078, 0x2d46, 0x7924, 0x7828, 0x2114, 0x200a, 0x0078,
-	0x250d, 0x7924, 0x2114, 0x0078, 0x250d, 0x2099, 0x0009, 0x20a1,
-	0x0009, 0x20a9, 0x0007, 0x53a3, 0x0078, 0x250d, 0x7824, 0x2060,
-	0x0078, 0x257c, 0x2009, 0x0001, 0x2011, 0x000f, 0x2019, 0x0025,
-	0x0078, 0x250d, 0x7d38, 0x7c3c, 0x0078, 0x2541, 0x7d38, 0x7c3c,
-	0x0078, 0x254d, 0x2061, 0x1000, 0x610c, 0xa006, 0x2c14, 0xa200,
-	0x8c60, 0x8109, 0x00c0, 0x257e, 0x2010, 0xa005, 0x0040, 0x250d,
-	0x0078, 0x2533, 0x2061, 0x7751, 0x7824, 0x7930, 0xa11a, 0x00c8,
-	0x253b, 0x8019, 0x0040, 0x253b, 0x604a, 0x6142, 0x782c, 0x6052,
-	0x7828, 0x6056, 0xa006, 0x605a, 0x605e, 0x1078, 0x3d89, 0x0078,
-	0x250d, 0x2061, 0x7751, 0x7824, 0x7930, 0xa11a, 0x00c8, 0x253b,
-	0x8019, 0x0040, 0x253b, 0x604e, 0x6146, 0x782c, 0x6062, 0x7828,
-	0x6066, 0xa006, 0x606a, 0x606e, 0x1078, 0x3b5f, 0x0078, 0x250d,
-	0xa02e, 0x2520, 0x81ff, 0x00c0, 0x2537, 0x7924, 0x7b28, 0x7a2c,
-	0x20a9, 0x0005, 0x20a1, 0x7774, 0x41a1, 0x1078, 0x2cf8, 0x0040,
-	0x2537, 0x2009, 0x0020, 0x1078, 0x2d42, 0x701b, 0x25d0, 0x007c,
-	0x6834, 0x2008, 0xa084, 0x00ff, 0xa096, 0x0011, 0x0040, 0x25dc,
-	0xa096, 0x0019, 0x00c0, 0x2537, 0x810f, 0xa18c, 0x00ff, 0x0040,
-	0x2537, 0x710e, 0x700c, 0x8001, 0x0040, 0x260d, 0x700e, 0x1078,
-	0x2cf8, 0x0040, 0x2537, 0x2009, 0x0020, 0x2061, 0x77bd, 0x6224,
-	0x6328, 0x642c, 0x6530, 0xa290, 0x0040, 0xa399, 0x0000, 0xa4a1,
-	0x0000, 0xa5a9, 0x0000, 0x1078, 0x2d42, 0x701b, 0x2600, 0x007c,
-	0x6834, 0xa084, 0x00ff, 0xa096, 0x0002, 0x0040, 0x260b, 0xa096,
-	0x000a, 0x00c0, 0x2537, 0x0078, 0x25e2, 0x7010, 0x2068, 0x6838,
-	0xc0fd, 0x683a, 0x1078, 0x3744, 0x00c0, 0x261b, 0x7007, 0x0003,
-	0x701b, 0x261d, 0x007c, 0x1078, 0x3c22, 0x127e, 0x2091, 0x8000,
-	0x20a9, 0x0005, 0x2099, 0x7774, 0x530a, 0x2100, 0xa210, 0xa399,
-	0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0xad80, 0x000d, 0x2009,
-	0x0020, 0x127f, 0x0078, 0x2d46, 0x6198, 0x7824, 0x609a, 0x0078,
-	0x250d, 0x2091, 0x8000, 0x7823, 0x4000, 0x7827, 0x4953, 0x782b,
-	0x5020, 0x782f, 0x2020, 0x2009, 0x017f, 0x2104, 0x7832, 0x3f00,
-	0x7836, 0x2061, 0x0100, 0x6200, 0x2061, 0x0200, 0x603c, 0x8007,
-	0xa205, 0x783a, 0x2009, 0x04fd, 0x2104, 0x783e, 0x781b, 0x0001,
-	0x2091, 0x5000, 0x2091, 0x4080, 0x2071, 0x0010, 0x20c1, 0x00f0,
-	0xa08a, 0x0003, 0x00c8, 0x0427, 0x0078, 0x0423, 0x81ff, 0x00c0,
-	0x2537, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x1078, 0x384c, 0x00c0,
-	0x253b, 0x7e38, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0048, 0x267a,
-	0x0078, 0x253b, 0x7c28, 0x7d2c, 0x1078, 0x39fd, 0xd28c, 0x00c0,
-	0x2685, 0x1078, 0x3991, 0x0078, 0x2687, 0x1078, 0x39cb, 0x00c0,
-	0x26b1, 0x2061, 0x7e00, 0x127e, 0x2091, 0x8000, 0x6000, 0xa086,
-	0x0000, 0x0040, 0x269f, 0x6010, 0xa06d, 0x0040, 0x269f, 0x683c,
-	0xa406, 0x00c0, 0x269f, 0x6840, 0xa506, 0x0040, 0x26aa, 0x127f,
-	0xace0, 0x0008, 0x2001, 0x7715, 0x2004, 0xac02, 0x00c8, 0x2537,
-	0x0078, 0x268b, 0x1078, 0x6852, 0x127f, 0x0040, 0x2537, 0x0078,
-	0x250d, 0xa00e, 0x2001, 0x0005, 0x1078, 0x3c22, 0x127e, 0x2091,
-	0x8000, 0x1078, 0x6c5c, 0x1078, 0x3b92, 0x127f, 0x0078, 0x250d,
-	0x81ff, 0x00c0, 0x2537, 0x1078, 0x2d10, 0x0040, 0x253b, 0x1078,
-	0x38d5, 0x0040, 0x2537, 0x1078, 0x3a0a, 0x0040, 0x2537, 0x0078,
-	0x250d, 0x81ff, 0x00c0, 0x2537, 0x1078, 0x2d22, 0x0040, 0x253b,
-	0x1078, 0x3a71, 0x0040, 0x2537, 0x2019, 0x0005, 0x1078, 0x3a2b,
-	0x0040, 0x2537, 0x7828, 0xa08a, 0x1000, 0x00c8, 0x253b, 0x8003,
-	0x800b, 0x810b, 0xa108, 0x1078, 0x4696, 0x0078, 0x250d, 0x127e,
-	0x2091, 0x8000, 0x81ff, 0x00c0, 0x271c, 0x2029, 0x00ff, 0x644c,
-	0x2400, 0xa506, 0x0040, 0x2716, 0x2508, 0x1078, 0x384c, 0x00c0,
-	0x2716, 0x1078, 0x3a71, 0x0040, 0x271c, 0x2019, 0x0004, 0x1078,
-	0x3a2b, 0x0040, 0x271c, 0x7824, 0xa08a, 0x1000, 0x00c8, 0x271f,
-	0x8003, 0x800b, 0x810b, 0xa108, 0x1078, 0x4696, 0x8529, 0x00c8,
-	0x26f8, 0x127f, 0x0078, 0x250d, 0x127f, 0x0078, 0x2537, 0x127f,
-	0x0078, 0x253b, 0x1078, 0x2d10, 0x0040, 0x253b, 0x1078, 0x3942,
-	0x1078, 0x39fd, 0x0078, 0x250d, 0x81ff, 0x00c0, 0x2537, 0x1078,
-	0x2d10, 0x0040, 0x253b, 0x1078, 0x3931, 0x1078, 0x39fd, 0x0078,
-	0x250d, 0x81ff, 0x00c0, 0x2537, 0x1078, 0x2d10, 0x0040, 0x253b,
-	0x1078, 0x39ce, 0x0040, 0x2537, 0x1078, 0x378d, 0x1078, 0x398a,
-	0x1078, 0x39fd, 0x0078, 0x250d, 0x1078, 0x2d10, 0x0040, 0x253b,
-	0x1078, 0x38d5, 0x0040, 0x2537, 0x62a0, 0x2019, 0x0005, 0x0c7e,
-	0x1078, 0x3a36, 0x0c7f, 0x1078, 0x4a7e, 0x1078, 0x49c1, 0x2c08,
-	0x1078, 0x747b, 0x1078, 0x39fd, 0x0078, 0x250d, 0x1078, 0x2d10,
-	0x0040, 0x253b, 0x1078, 0x39fd, 0x2208, 0x0078, 0x250d, 0x157e,
-	0x0d7e, 0x0e7e, 0x2069, 0x77ff, 0x6810, 0x6914, 0xa10a, 0x00c8,
-	0x277b, 0x2009, 0x0000, 0x6816, 0x2011, 0x0000, 0x2019, 0x0000,
-	0x20a9, 0x007e, 0x2069, 0x7820, 0x2d04, 0xa075, 0x0040, 0x2790,
-	0x704c, 0x1078, 0x279a, 0xa210, 0x7080, 0x1078, 0x279a, 0xa318,
-	0x8d68, 0x00f0, 0x2784, 0x2300, 0xa218, 0x0e7f, 0x0d7f, 0x157f,
-	0x0078, 0x250d, 0x0f7e, 0x017e, 0xa07d, 0x0040, 0x27a9, 0x2001,
-	0x0000, 0x8000, 0x2f0c, 0x81ff, 0x0040, 0x27a9, 0x2178, 0x0078,
-	0x27a1, 0x017f, 0x0f7f, 0x007c, 0x2069, 0x77ff, 0x6910, 0x629c,
-	0x0078, 0x250d, 0x81ff, 0x00c0, 0x2537, 0x614c, 0xa190, 0x2329,
-	0x2214, 0xa294, 0x00ff, 0x6068, 0xa084, 0xff00, 0xa215, 0x6364,
-	0x0078, 0x250d, 0x613c, 0x6240, 0x0078, 0x250d, 0x1078, 0x2d22,
-	0x0040, 0x253b, 0x0078, 0x250d, 0x1078, 0x2d22, 0x0040, 0x253b,
-	0x6244, 0x6338, 0x0078, 0x250d, 0x613c, 0x6240, 0x7824, 0x603e,
-	0x7b28, 0x6342, 0x2069, 0x7751, 0x831f, 0xa305, 0x6816, 0x0078,
-	0x250d, 0x1078, 0x2d22, 0x0040, 0x253b, 0x0078, 0x250d, 0x1078,
-	0x2d22, 0x0040, 0x253b, 0x7828, 0xa00d, 0x0040, 0x253b, 0x782c,
-	0xa005, 0x0040, 0x253b, 0x6244, 0x6146, 0x6338, 0x603a, 0x0078,
-	0x250d, 0x7d38, 0x7c3c, 0x0078, 0x25ba, 0x7824, 0xa09c, 0x00ff,
-	0xa39a, 0x0003, 0x00c8, 0x2537, 0x624c, 0xa084, 0xff00, 0x8007,
-	0xa206, 0x00c0, 0x2815, 0x2001, 0x7740, 0x2009, 0x000c, 0x7a2c,
-	0x7b28, 0x7c3c, 0x7d38, 0x0078, 0x2d46, 0x81ff, 0x00c0, 0x2537,
-	0x1078, 0x2d22, 0x0040, 0x253b, 0x6004, 0xa084, 0x00ff, 0xa086,
-	0x0006, 0x00c0, 0x2537, 0x0c7e, 0x1078, 0x2cf8, 0x0c7f, 0x0040,
-	0x2537, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x1078, 0x6b56,
-	0x0040, 0x2537, 0x7007, 0x0003, 0x701b, 0x2837, 0x007c, 0x6830,
-	0xa086, 0x0100, 0x0040, 0x2537, 0xad80, 0x000e, 0x2009, 0x000c,
-	0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, 0x2d46, 0x1078, 0x2cf8,
-	0x0040, 0x2537, 0x2009, 0x001c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
-	0x1078, 0x2d42, 0x701b, 0x2855, 0x007c, 0xade8, 0x000d, 0x6800,
-	0xa005, 0x0040, 0x253b, 0x6804, 0xd0ac, 0x0040, 0x2862, 0xd0a4,
-	0x0040, 0x253b, 0xd094, 0x0040, 0x286d, 0x0c7e, 0x2061, 0x0100,
-	0x6104, 0xa18c, 0xffdf, 0x6106, 0x0c7f, 0xd08c, 0x0040, 0x2878,
-	0x0c7e, 0x2061, 0x0100, 0x6104, 0xa18d, 0x0010, 0x6106, 0x0c7f,
-	0x2009, 0x0100, 0x210c, 0xa18a, 0x0002, 0x0048, 0x288d, 0xd084,
-	0x0040, 0x288d, 0x6a28, 0xa28a, 0x007f, 0x00c8, 0x253b, 0xa288,
-	0x2329, 0x210c, 0xa18c, 0x00ff, 0x6152, 0xd0dc, 0x0040, 0x2896,
-	0x6828, 0xa08a, 0x007f, 0x00c8, 0x253b, 0x604e, 0x6808, 0xa08a,
-	0x0100, 0x0048, 0x253b, 0xa08a, 0x0841, 0x00c8, 0x253b, 0xa084,
-	0x0007, 0x00c0, 0x253b, 0x680c, 0xa005, 0x0040, 0x253b, 0x6810,
-	0xa005, 0x0040, 0x253b, 0x6848, 0x6940, 0xa10a, 0x00c8, 0x253b,
-	0x8001, 0x0040, 0x253b, 0x684c, 0x6944, 0xa10a, 0x00c8, 0x253b,
-	0x8001, 0x0040, 0x253b, 0x20a9, 0x001c, 0x2d98, 0x2069, 0x7751,
-	0x2da0, 0x53a3, 0x6814, 0xa08c, 0x00ff, 0x613e, 0x8007, 0xa084,
-	0x00ff, 0x6042, 0x1078, 0x3d89, 0x1078, 0x3b5f, 0x6000, 0xa086,
-	0x0000, 0x00c0, 0x2911, 0x6808, 0x602a, 0x1078, 0x1de4, 0x6818,
-	0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f, 0x6016,
-	0x611a, 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0040, 0x28f1, 0x6830,
-	0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, 0x0078,
-	0x28f3, 0xa084, 0xf0ff, 0x6006, 0x610a, 0x620e, 0x6312, 0x1078,
-	0x4722, 0x0c7e, 0x2061, 0x0100, 0x602f, 0x0040, 0x602f, 0x0000,
-	0x0c7f, 0x60b4, 0xa005, 0x0040, 0x290d, 0x6003, 0x0001, 0x2091,
-	0x301d, 0x1078, 0x3591, 0x0078, 0x2911, 0x6003, 0x0004, 0x2091,
-	0x301d, 0x0078, 0x250d, 0x6000, 0xa086, 0x0000, 0x0040, 0x2537,
-	0x2069, 0x7751, 0x7830, 0x6842, 0x7834, 0x6846, 0x2d00, 0x2009,
-	0x001c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, 0x2d46, 0x81ff,
-	0x00c0, 0x2537, 0x1078, 0x3591, 0x0078, 0x250d, 0x81ff, 0x00c0,
-	0x2537, 0x617c, 0x81ff, 0x0040, 0x2948, 0x703f, 0x0000, 0x2001,
-	0x7dc0, 0x2009, 0x0040, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x127e,
-	0x2091, 0x8000, 0x1078, 0x2d46, 0x701b, 0x250a, 0x127f, 0x007c,
-	0x703f, 0x0001, 0x0d7e, 0x2069, 0x7dc0, 0x20a9, 0x0040, 0x20a1,
-	0x7dc0, 0x2019, 0xffff, 0x43a4, 0x654c, 0xa588, 0x2329, 0x210c,
-	0xa18c, 0x00ff, 0x216a, 0xa00e, 0x2011, 0x0002, 0x2100, 0xa506,
-	0x0040, 0x297a, 0x1078, 0x384c, 0x00c0, 0x297a, 0x6014, 0x821c,
-	0x0048, 0x2972, 0xa398, 0x7dc0, 0xa085, 0xff00, 0x8007, 0x201a,
-	0x0078, 0x2979, 0xa398, 0x7dc0, 0x2324, 0xa4a4, 0xff00, 0xa405,
-	0x201a, 0x8210, 0x8108, 0xa182, 0x0080, 0x00c8, 0x2981, 0x0078,
-	0x295e, 0x8201, 0x8007, 0x2d0c, 0xa105, 0x206a, 0x0d7f, 0x20a9,
-	0x0040, 0x20a1, 0x7dc0, 0x2099, 0x7dc0, 0x1078, 0x35da, 0x0078,
-	0x2937, 0x1078, 0x2d22, 0x0040, 0x253b, 0x0c7e, 0x1078, 0x2cf8,
-	0x0c7f, 0x0040, 0x2537, 0x2001, 0x7752, 0x2004, 0xd0b4, 0x0040,
-	0x29be, 0x6000, 0xd08c, 0x00c0, 0x29be, 0x6004, 0xa084, 0x00ff,
-	0xa086, 0x0006, 0x00c0, 0x29be, 0x6837, 0x0000, 0x6838, 0xc0fd,
-	0x683a, 0x1078, 0x6b8e, 0x0040, 0x2537, 0x7007, 0x0003, 0x701b,
-	0x29ba, 0x007c, 0x1078, 0x2d22, 0x0040, 0x253b, 0x20a9, 0x002b,
-	0x2c98, 0xade8, 0x0002, 0x2da0, 0x53a3, 0x20a9, 0x0004, 0xac80,
-	0x0006, 0x2098, 0xad80, 0x0006, 0x20a0, 0x1078, 0x35da, 0x20a9,
-	0x0004, 0xac80, 0x000a, 0x2098, 0xad80, 0x000a, 0x20a0, 0x1078,
-	0x35da, 0x2d00, 0x2009, 0x002b, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
-	0x0078, 0x2d46, 0x81ff, 0x00c0, 0x2537, 0x1078, 0x2d10, 0x0040,
-	0x253b, 0x1078, 0x3a15, 0x0078, 0x250d, 0x81ff, 0x00c0, 0x2537,
-	0x7828, 0xa08a, 0x1000, 0x00c8, 0x253b, 0x1078, 0x2d22, 0x0040,
-	0x253b, 0x1078, 0x3a71, 0x0040, 0x2537, 0x2019, 0x0004, 0x1078,
-	0x3a2b, 0x7924, 0x810f, 0x7a28, 0x1078, 0x2a08, 0x0078, 0x250d,
-	0xa186, 0x00ff, 0x0040, 0x2a10, 0x1078, 0x2a20, 0x0078, 0x2a1f,
-	0x2029, 0x007e, 0x2061, 0x7700, 0x644c, 0x2400, 0xa506, 0x0040,
-	0x2a1c, 0x2508, 0x1078, 0x2a20, 0x8529, 0x00c8, 0x2a15, 0x007c,
-	0x1078, 0x384c, 0x00c0, 0x2a2b, 0x2200, 0x8003, 0x800b, 0x810b,
-	0xa108, 0x1078, 0x4696, 0x007c, 0x81ff, 0x00c0, 0x2537, 0x1078,
-	0x2d10, 0x0040, 0x253b, 0x1078, 0x38d5, 0x0040, 0x2537, 0x1078,
-	0x3a20, 0x0078, 0x250d, 0x81ff, 0x00c0, 0x2537, 0x1078, 0x2d10,
-	0x0040, 0x253b, 0x1078, 0x38d5, 0x0040, 0x2537, 0x1078, 0x3a0a,
-	0x0078, 0x250d, 0x6100, 0x0078, 0x250d, 0x1078, 0x2d22, 0x0040,
-	0x253b, 0x6004, 0xa086, 0x0707, 0x0040, 0x253b, 0x2001, 0x7700,
-	0x2004, 0xa086, 0x0003, 0x00c0, 0x2537, 0x0d7e, 0xace8, 0x000a,
-	0x7924, 0xd184, 0x0040, 0x2a66, 0xace8, 0x0006, 0x680c, 0x8007,
-	0x783e, 0x6808, 0x8007, 0x783a, 0x6b04, 0x831f, 0x6a00, 0x8217,
-	0x0d7f, 0x6100, 0xa18c, 0x0200, 0x0078, 0x250d, 0x7824, 0xa084,
-	0x00ff, 0xa086, 0x00ff, 0x0040, 0x2a80, 0x81ff, 0x00c0, 0x2537,
-	0x7828, 0xa08a, 0x1000, 0x00c8, 0x253b, 0x7924, 0xa18c, 0xff00,
-	0x810f, 0xa186, 0x00ff, 0x0040, 0x2a94, 0xa182, 0x007f, 0x00c8,
-	0x253b, 0x2100, 0x1078, 0x2094, 0x027e, 0x0c7e, 0x127e, 0x2091,
-	0x8000, 0x2061, 0x7949, 0x601b, 0x0000, 0x601f, 0x0000, 0x2061,
+	0x8000, 0x8000, 0x2071, 0x8881, 0x7003, 0x0002, 0xa006, 0x7012,
+	0x7016, 0x703a, 0x703e, 0x7033, 0x8891, 0x7037, 0x8891, 0x7007,
+	0x0001, 0x2061, 0x88d1, 0x6003, 0x0002, 0x007c, 0x0090, 0x26d9,
+	0x0068, 0x26d9, 0x2071, 0x8881, 0x2b78, 0x7818, 0xd084, 0x00c0,
+	0x26d9, 0x2a60, 0x7820, 0xa08e, 0x0069, 0x00c0, 0x27c9, 0x0079,
+	0x275d, 0x007c, 0x2071, 0x8881, 0x7004, 0x0079, 0x26df, 0x26e3,
+	0x26e4, 0x26ee, 0x2700, 0x007c, 0x0090, 0x26ed, 0x0068, 0x26ed,
+	0x2b78, 0x7818, 0xd084, 0x0040, 0x270c, 0x007c, 0x2b78, 0x2061,
+	0x88d1, 0x6008, 0xa08e, 0x0100, 0x0040, 0x26fb, 0xa086, 0x0200,
+	0x0040, 0x27c1, 0x007c, 0x7014, 0x2068, 0x2a60, 0x7018, 0x007a,
+	0x7010, 0x2068, 0x6834, 0xa086, 0x0103, 0x0040, 0x2708, 0x007c,
+	0x2a60, 0x2b78, 0x7018, 0x007a, 0x2a60, 0x7820, 0xa08a, 0x0040,
+	0x00c8, 0x2715, 0x61b4, 0x0079, 0x271d, 0x2100, 0xa08a, 0x003f,
+	0x00c8, 0x27bd, 0x61b4, 0x0079, 0x275d, 0x279f, 0x27d1, 0x27d9,
+	0x27dd, 0x27e5, 0x27eb, 0x27ef, 0x27f8, 0x27fc, 0x2804, 0x2808,
+	0x27bd, 0x27bd, 0x27bd, 0x280c, 0x27bd, 0x281c, 0x2833, 0x284a,
+	0x28c6, 0x28cb, 0x28f8, 0x2952, 0x2963, 0x2981, 0x29c2, 0x29cc,
+	0x29d9, 0x29ec, 0x2a0a, 0x2a13, 0x2a50, 0x2a56, 0x27bd, 0x2a66,
+	0x27bd, 0x27bd, 0x27bd, 0x27bd, 0x27bd, 0x2a6a, 0x2a74, 0x27bd,
+	0x27bd, 0x27bd, 0x27bd, 0x27bd, 0x27bd, 0x27bd, 0x27bd, 0x2a7c,
+	0x27bd, 0x27bd, 0x27bd, 0x27bd, 0x27bd, 0x2a89, 0x2a91, 0x27bd,
+	0x27bd, 0x27bd, 0x27bd, 0x27bd, 0x27bd, 0x2aa3, 0x2af4, 0x2b45,
+	0x2b56, 0x27bd, 0x27bd, 0x27bd, 0x34bd, 0x27bd, 0x27bd, 0x27bd,
+	0x27bd, 0x27bd, 0x27bd, 0x27bd, 0x27bd, 0x2804, 0x2808, 0x27bd,
+	0x27bd, 0x2b6d, 0x27bd, 0x27bd, 0x27bd, 0x27bd, 0x27bd, 0x27bd,
+	0x27bd, 0x27bd, 0x27bd, 0x27bd, 0x27bd, 0x2bba, 0x2ce1, 0x2cf5,
+	0x2d01, 0x2d64, 0x2dbd, 0x2dc8, 0x2e07, 0x2e16, 0x2e25, 0x2e28,
+	0x2b71, 0x2e51, 0x2e9d, 0x2eaa, 0x2fb9, 0x30d1, 0x30f8, 0x3205,
+	0x3214, 0x3221, 0x325b, 0x32f8, 0x27bd, 0x27bd, 0x27bd, 0x27bd,
+	0x3360, 0x337c, 0x33f6, 0x34ae, 0x713c, 0x0078, 0x279f, 0x2021,
+	0x4000, 0x1078, 0x3154, 0x127e, 0x2091, 0x8000, 0x0068, 0x27ac,
+	0x7818, 0xd084, 0x0040, 0x27af, 0x127f, 0x0078, 0x27a3, 0x7c22,
+	0x7926, 0x7a2a, 0x7b2e, 0x781b, 0x0001, 0x2091, 0x4080, 0x7007,
+	0x0001, 0x2091, 0x5000, 0x127f, 0x007c, 0x2021, 0x4001, 0x0078,
+	0x27a1, 0x2021, 0x4002, 0x0078, 0x27a1, 0x2021, 0x4003, 0x0078,
+	0x27a1, 0x2021, 0x4005, 0x0078, 0x27a1, 0x2021, 0x4006, 0x0078,
+	0x27a1, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0078,
+	0x3163, 0x7823, 0x0004, 0x7824, 0x007a, 0xa02e, 0x2520, 0x7b28,
+	0x7a2c, 0x7824, 0x7930, 0x0078, 0x3167, 0x7924, 0x7828, 0x2114,
+	0x200a, 0x0078, 0x279f, 0x7924, 0x2114, 0x0078, 0x279f, 0x2099,
+	0x0009, 0x20a1, 0x0009, 0x20a9, 0x0007, 0x53a3, 0x0078, 0x279f,
+	0x7824, 0x2060, 0x0078, 0x280e, 0x2009, 0x0001, 0x2011, 0x0011,
+	0x2019, 0x001e, 0x0078, 0x279f, 0x7d38, 0x7c3c, 0x0078, 0x27d3,
+	0x7d38, 0x7c3c, 0x0078, 0x27df, 0x2061, 0x1000, 0x610c, 0xa006,
+	0x2c14, 0xa200, 0x8c60, 0x8109, 0x00c0, 0x2810, 0x2010, 0xa005,
+	0x0040, 0x279f, 0x0078, 0x27c5, 0x2069, 0x8851, 0x7824, 0x7930,
+	0xa11a, 0x00c8, 0x27cd, 0x8019, 0x0040, 0x27cd, 0x684a, 0x6942,
+	0x782c, 0x6852, 0x7828, 0x6856, 0xa006, 0x685a, 0x685e, 0x1078,
+	0x4793, 0x0078, 0x279f, 0x2069, 0x8851, 0x7824, 0x7934, 0xa11a,
+	0x00c8, 0x27cd, 0x8019, 0x0040, 0x27cd, 0x684e, 0x6946, 0x782c,
+	0x6862, 0x7828, 0x6866, 0xa006, 0x686a, 0x686e, 0x1078, 0x4343,
+	0x0078, 0x279f, 0xa02e, 0x2520, 0x81ff, 0x00c0, 0x27c9, 0x7924,
+	0x7b28, 0x7a2c, 0x20a9, 0x0005, 0x20a1, 0x8888, 0x41a1, 0x1078,
+	0x3119, 0x0040, 0x27c9, 0x2009, 0x0020, 0x1078, 0x3163, 0x701b,
+	0x2862, 0x007c, 0x6834, 0x2008, 0xa084, 0x00ff, 0xa096, 0x0011,
+	0x0040, 0x286e, 0xa096, 0x0019, 0x00c0, 0x27c9, 0x810f, 0xa18c,
+	0x00ff, 0x0040, 0x27c9, 0x710e, 0x700c, 0x8001, 0x0040, 0x289f,
+	0x700e, 0x1078, 0x3119, 0x0040, 0x27c9, 0x2009, 0x0020, 0x2061,
+	0x88d1, 0x6224, 0x6328, 0x642c, 0x6530, 0xa290, 0x0040, 0xa399,
+	0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x1078, 0x3163, 0x701b,
+	0x2892, 0x007c, 0x6834, 0xa084, 0x00ff, 0xa096, 0x0002, 0x0040,
+	0x289d, 0xa096, 0x000a, 0x00c0, 0x27c9, 0x0078, 0x2874, 0x7010,
+	0x2068, 0x6838, 0xc0fd, 0x683a, 0x1078, 0x3e3e, 0x00c0, 0x28ad,
+	0x7007, 0x0003, 0x701b, 0x28af, 0x007c, 0x1078, 0x4454, 0x127e,
+	0x2091, 0x8000, 0x20a9, 0x0005, 0x2099, 0x8888, 0x530a, 0x2100,
+	0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0xad80,
+	0x000d, 0x2009, 0x0020, 0x127f, 0x0078, 0x3167, 0x619c, 0x7824,
+	0x609e, 0x0078, 0x279f, 0x2091, 0x8000, 0x7823, 0x4000, 0x7827,
+	0x4953, 0x782b, 0x5020, 0x782f, 0x2020, 0x2009, 0x017f, 0x2104,
+	0x7832, 0x3f00, 0x7836, 0x2061, 0x0100, 0x6200, 0x2061, 0x0200,
+	0x603c, 0x8007, 0xa205, 0x783a, 0x2009, 0x04fd, 0x2104, 0x783e,
+	0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2071, 0x0010,
+	0x20c1, 0x00f0, 0xa08a, 0x0003, 0x00c8, 0x0427, 0x0078, 0x0423,
+	0x81ff, 0x00c0, 0x27c9, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x1078,
+	0x3f8e, 0x00c0, 0x27cd, 0x7e38, 0xa684, 0x3fff, 0xa082, 0x4000,
+	0x0048, 0x290c, 0x0078, 0x27cd, 0x7c28, 0x7d2c, 0x1078, 0x4146,
+	0xd28c, 0x00c0, 0x2917, 0x1078, 0x40da, 0x0078, 0x2919, 0x1078,
+	0x4114, 0x00c0, 0x2943, 0x2061, 0x8f00, 0x127e, 0x2091, 0x8000,
+	0x6000, 0xa086, 0x0000, 0x0040, 0x2931, 0x6010, 0xa06d, 0x0040,
+	0x2931, 0x683c, 0xa406, 0x00c0, 0x2931, 0x6840, 0xa506, 0x0040,
+	0x293c, 0x127f, 0xace0, 0x000c, 0x2001, 0x8815, 0x2004, 0xac02,
+	0x00c8, 0x27c9, 0x0078, 0x291d, 0x1078, 0x759a, 0x127f, 0x0040,
+	0x27c9, 0x0078, 0x279f, 0xa00e, 0x2001, 0x0005, 0x1078, 0x4454,
+	0x127e, 0x2091, 0x8000, 0x1078, 0x7a4e, 0x1078, 0x4376, 0x127f,
+	0x0078, 0x279f, 0x81ff, 0x00c0, 0x27c9, 0x1078, 0x3131, 0x0040,
+	0x27cd, 0x1078, 0x4017, 0x0040, 0x27c9, 0x1078, 0x4154, 0x0040,
+	0x27c9, 0x0078, 0x279f, 0x81ff, 0x00c0, 0x27c9, 0x1078, 0x3143,
+	0x0040, 0x27cd, 0x1078, 0x41c7, 0x0040, 0x27c9, 0x2019, 0x0005,
+	0x1078, 0x4175, 0x0040, 0x27c9, 0x7828, 0xa08a, 0x1000, 0x00c8,
+	0x27cd, 0x8003, 0x800b, 0x810b, 0xa108, 0x1078, 0x50ff, 0x0078,
+	0x279f, 0x127e, 0x2091, 0x8000, 0x81ff, 0x0040, 0x298b, 0x2009,
+	0x0001, 0x0078, 0x29bc, 0x2029, 0x00ff, 0x644c, 0x2400, 0xa506,
+	0x0040, 0x29b6, 0x2508, 0x1078, 0x3f8e, 0x00c0, 0x29b6, 0x1078,
+	0x41c7, 0x00c0, 0x29a1, 0x2009, 0x0002, 0x62a4, 0x2518, 0x0078,
+	0x29bc, 0x2019, 0x0004, 0x1078, 0x4175, 0x00c0, 0x29ab, 0x2009,
+	0x0006, 0x0078, 0x29bc, 0x7824, 0xa08a, 0x1000, 0x00c8, 0x29bf,
+	0x8003, 0x800b, 0x810b, 0xa108, 0x1078, 0x50ff, 0x8529, 0x00c8,
+	0x298e, 0x127f, 0x0078, 0x279f, 0x127f, 0x0078, 0x27c9, 0x127f,
+	0x0078, 0x27cd, 0x1078, 0x3131, 0x0040, 0x27cd, 0x1078, 0x408b,
+	0x1078, 0x4146, 0x0078, 0x279f, 0x81ff, 0x00c0, 0x27c9, 0x1078,
+	0x3131, 0x0040, 0x27cd, 0x1078, 0x407a, 0x1078, 0x4146, 0x0078,
+	0x279f, 0x81ff, 0x00c0, 0x27c9, 0x1078, 0x3131, 0x0040, 0x27cd,
+	0x1078, 0x4117, 0x0040, 0x27c9, 0x1078, 0x3e87, 0x1078, 0x40d3,
+	0x1078, 0x4146, 0x0078, 0x279f, 0x1078, 0x3131, 0x0040, 0x27cd,
+	0x1078, 0x4017, 0x0040, 0x27c9, 0x62a0, 0x2019, 0x0005, 0x0c7e,
+	0x1078, 0x418b, 0x0c7f, 0x1078, 0x54f0, 0x087e, 0x2041, 0x0000,
+	0x1078, 0x5419, 0x2c08, 0x1078, 0x84d2, 0x087f, 0x1078, 0x4146,
+	0x0078, 0x279f, 0x1078, 0x3131, 0x0040, 0x27cd, 0x1078, 0x4146,
+	0x2208, 0x0078, 0x279f, 0x157e, 0x0d7e, 0x0e7e, 0x2069, 0x8913,
+	0x6810, 0x6914, 0xa10a, 0x00c8, 0x2a1f, 0x2009, 0x0000, 0x6816,
+	0x2011, 0x0000, 0x2019, 0x0000, 0x20a9, 0x00ff, 0x2069, 0x8934,
+	0x2d04, 0xa075, 0x0040, 0x2a34, 0x704c, 0x1078, 0x2a3e, 0xa210,
+	0x7080, 0x1078, 0x2a3e, 0xa318, 0x8d68, 0x00f0, 0x2a28, 0x2300,
+	0xa218, 0x0e7f, 0x0d7f, 0x157f, 0x0078, 0x279f, 0x0f7e, 0x017e,
+	0xa07d, 0x0040, 0x2a4d, 0x2001, 0x0000, 0x8000, 0x2f0c, 0x81ff,
+	0x0040, 0x2a4d, 0x2178, 0x0078, 0x2a45, 0x017f, 0x0f7f, 0x007c,
+	0x2069, 0x8913, 0x6910, 0x62a0, 0x0078, 0x279f, 0x81ff, 0x00c0,
+	0x27c9, 0x614c, 0xa190, 0x25b2, 0x2214, 0xa294, 0x00ff, 0x606c,
+	0xa084, 0xff00, 0xa215, 0x6368, 0x0078, 0x279f, 0x613c, 0x6240,
+	0x0078, 0x279f, 0x127e, 0x2091, 0x8000, 0x6134, 0xa006, 0x2010,
+	0x2018, 0x127f, 0x0078, 0x279f, 0x1078, 0x3143, 0x0040, 0x27cd,
+	0x6244, 0x6338, 0x0078, 0x279f, 0x613c, 0x6240, 0x7824, 0x603e,
+	0x7b28, 0x6342, 0x2069, 0x8851, 0x831f, 0xa305, 0x6816, 0x0078,
+	0x279f, 0x127e, 0x2091, 0x8000, 0x7824, 0x6036, 0x127f, 0x0078,
+	0x279f, 0x1078, 0x3143, 0x0040, 0x27cd, 0x7828, 0xa00d, 0x0040,
+	0x27cd, 0x782c, 0xa005, 0x0040, 0x27cd, 0x6244, 0x6146, 0x6338,
+	0x603a, 0x0078, 0x279f, 0x2001, 0x8800, 0x2004, 0xa086, 0x0003,
+	0x00c0, 0x27c9, 0x0c7e, 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c,
+	0x00ff, 0xa196, 0x00ff, 0x00c0, 0x2aba, 0x6030, 0xa085, 0xff00,
+	0x0078, 0x2ac9, 0xa182, 0x007f, 0x00c8, 0x2aed, 0xa188, 0x25b2,
+	0x210c, 0xa18c, 0x00ff, 0x6030, 0xa116, 0x0040, 0x2aed, 0x810f,
+	0xa105, 0x127e, 0x2091, 0x8000, 0x007e, 0x1078, 0x68a8, 0x007f,
+	0x0040, 0x2aea, 0x601a, 0x600b, 0xbc09, 0x601f, 0x0001, 0x1078,
+	0x3119, 0x0040, 0x2af0, 0x6837, 0x0000, 0x7007, 0x0003, 0x701b,
+	0x279f, 0x2d00, 0x6012, 0x2009, 0x0032, 0x1078, 0x6939, 0x127f,
+	0x0c7f, 0x007c, 0x0c7f, 0x0078, 0x27c9, 0x0c7f, 0x0078, 0x27cd,
+	0x1078, 0x690e, 0x0078, 0x2aea, 0x2001, 0x8800, 0x2004, 0xa086,
+	0x0003, 0x00c0, 0x27c9, 0x0c7e, 0x2061, 0x0100, 0x7924, 0x810f,
+	0xa18c, 0x00ff, 0xa196, 0x00ff, 0x00c0, 0x2b0b, 0x6030, 0xa085,
+	0xff00, 0x0078, 0x2b1a, 0xa182, 0x007f, 0x00c8, 0x2b3e, 0xa188,
+	0x25b2, 0x210c, 0xa18c, 0x00ff, 0x6030, 0xa116, 0x0040, 0x2b3e,
+	0x810f, 0xa105, 0x127e, 0x2091, 0x8000, 0x007e, 0x1078, 0x68a8,
+	0x007f, 0x0040, 0x2b3b, 0x601a, 0x600b, 0xbc05, 0x601f, 0x0001,
+	0x1078, 0x3119, 0x0040, 0x2b41, 0x6837, 0x0000, 0x7007, 0x0003,
+	0x701b, 0x279f, 0x2d00, 0x6012, 0x2009, 0x0032, 0x1078, 0x6939,
+	0x127f, 0x0c7f, 0x007c, 0x0c7f, 0x0078, 0x27c9, 0x0c7f, 0x0078,
+	0x27cd, 0x1078, 0x690e, 0x0078, 0x2b3b, 0x2061, 0x8b24, 0x127e,
+	0x2091, 0x8000, 0x6000, 0xd084, 0x0040, 0x2b53, 0x6104, 0x6208,
+	0x127f, 0x0078, 0x279f, 0x127f, 0x0078, 0x27cd, 0x81ff, 0x00c0,
+	0x27c9, 0x127e, 0x2091, 0x8000, 0x6244, 0x6060, 0xa202, 0x0048,
+	0x2b6a, 0xa085, 0x0001, 0x1078, 0x2262, 0x1078, 0x36ef, 0x127f,
+	0x0078, 0x279f, 0x127f, 0x0078, 0x27cd, 0x7d38, 0x7c3c, 0x0078,
+	0x284c, 0x7824, 0xa09c, 0x00ff, 0xa39a, 0x0003, 0x00c8, 0x27c9,
+	0x624c, 0xa084, 0xff00, 0x8007, 0xa206, 0x00c0, 0x2b89, 0x2001,
+	0x8840, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078,
+	0x3167, 0x81ff, 0x00c0, 0x27c9, 0x1078, 0x3143, 0x0040, 0x27cd,
+	0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x27c9, 0x0c7e,
+	0x1078, 0x3119, 0x0c7f, 0x0040, 0x27c9, 0x6837, 0x0000, 0x6838,
+	0xc0fd, 0x683a, 0x1078, 0x792c, 0x0040, 0x27c9, 0x7007, 0x0003,
+	0x701b, 0x2bab, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x27c9,
+	0xad80, 0x000e, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
+	0x0078, 0x3167, 0x1078, 0x3119, 0x0040, 0x27c9, 0x1078, 0x3d16,
+	0x2009, 0x001c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3163,
+	0x701b, 0x2bcb, 0x007c, 0xade8, 0x000d, 0x6800, 0xa005, 0x0040,
+	0x27cd, 0x6804, 0xd0ac, 0x0040, 0x2bd8, 0xd0a4, 0x0040, 0x27cd,
+	0xd094, 0x0040, 0x2be3, 0x0c7e, 0x2061, 0x0100, 0x6104, 0xa18c,
+	0xffdf, 0x6106, 0x0c7f, 0xd08c, 0x0040, 0x2bee, 0x0c7e, 0x2061,
+	0x0100, 0x6104, 0xa18d, 0x0010, 0x6106, 0x0c7f, 0x2009, 0x0100,
+	0x210c, 0xa18a, 0x0002, 0x0048, 0x2c03, 0xd084, 0x0040, 0x2c03,
+	0x6a28, 0xa28a, 0x007f, 0x00c8, 0x27cd, 0xa288, 0x25b2, 0x210c,
+	0xa18c, 0x00ff, 0x6152, 0xd0dc, 0x0040, 0x2c0c, 0x6828, 0xa08a,
+	0x007f, 0x00c8, 0x27cd, 0x604e, 0x6808, 0xa08a, 0x0100, 0x0048,
+	0x27cd, 0xa08a, 0x0841, 0x00c8, 0x27cd, 0xa084, 0x0007, 0x00c0,
+	0x27cd, 0x680c, 0xa005, 0x0040, 0x27cd, 0x6810, 0xa005, 0x0040,
+	0x27cd, 0x6848, 0x6940, 0xa10a, 0x00c8, 0x27cd, 0x8001, 0x0040,
+	0x27cd, 0x684c, 0x6944, 0xa10a, 0x00c8, 0x27cd, 0x8001, 0x0040,
+	0x27cd, 0x6804, 0xd0fc, 0x0040, 0x2c54, 0x1078, 0x3119, 0x0040,
+	0x27c9, 0x2009, 0x0014, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0xa290,
+	0x0038, 0xa399, 0x0000, 0x1078, 0x3163, 0x701b, 0x2c48, 0x007c,
+	0xade8, 0x000d, 0x20a9, 0x0014, 0x2d98, 0x2069, 0x886d, 0x2da0,
+	0x53a3, 0x7010, 0xa0e8, 0x000d, 0x20a9, 0x001c, 0x2d98, 0x2069,
+	0x8851, 0x2da0, 0x53a3, 0x6814, 0xa08c, 0x00ff, 0x613e, 0x8007,
+	0xa084, 0x00ff, 0x6042, 0x1078, 0x4793, 0x1078, 0x42d3, 0x1078,
+	0x4343, 0x6000, 0xa086, 0x0000, 0x00c0, 0x2cdf, 0x6808, 0x602a,
+	0x1078, 0x1f57, 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f,
+	0x8217, 0x831f, 0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, 0xd4f4,
+	0x0040, 0x2c8c, 0x6830, 0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f,
+	0x8217, 0x831f, 0x0078, 0x2c8e, 0xa084, 0xf0ff, 0x6006, 0x610a,
+	0x620e, 0x6312, 0x1078, 0x518a, 0x6904, 0xd1fc, 0x0040, 0x2cc1,
+	0x0c7e, 0x2009, 0x0000, 0x20a9, 0x0001, 0x6b70, 0xd384, 0x0040,
+	0x2cbe, 0x0078, 0x2ca8, 0x839d, 0x00c8, 0x2cbe, 0x3508, 0x8109,
+	0x1078, 0x4cb2, 0x6878, 0x6016, 0x6874, 0x2008, 0xa084, 0xff00,
+	0x8007, 0x600a, 0xa184, 0x00ff, 0x6006, 0x8108, 0x00c0, 0x2cbc,
+	0x6003, 0x0003, 0x0078, 0x2cbe, 0x6003, 0x0001, 0x00f0, 0x2ca3,
+	0x0c7f, 0x0c7e, 0x2061, 0x0100, 0x602f, 0x0040, 0x602f, 0x0000,
+	0x0c7f, 0x1078, 0x3352, 0x0040, 0x2ccf, 0x1078, 0x2262, 0x60b8,
+	0xa005, 0x0040, 0x2cdb, 0x6003, 0x0001, 0x2091, 0x301d, 0x1078,
+	0x3c73, 0x0078, 0x2cdf, 0x6003, 0x0004, 0x2091, 0x301d, 0x0078,
+	0x279f, 0x6000, 0xa086, 0x0000, 0x0040, 0x27c9, 0x2069, 0x8851,
+	0x7830, 0x6842, 0x7834, 0x6846, 0x2d00, 0x2009, 0x001c, 0x7a2c,
+	0x7b28, 0x7c3c, 0x7d38, 0x0078, 0x3167, 0x81ff, 0x00c0, 0x27c9,
+	0xa006, 0x1078, 0x2262, 0x1078, 0x3d16, 0x1078, 0x3c73, 0x0078,
+	0x279f, 0x81ff, 0x00c0, 0x27c9, 0x6180, 0x81ff, 0x0040, 0x2d1b,
+	0x703f, 0x0000, 0x2001, 0x8ec0, 0x2009, 0x0040, 0x7a2c, 0x7b28,
+	0x7c3c, 0x7d38, 0x127e, 0x2091, 0x8000, 0x1078, 0x3167, 0x701b,
+	0x279c, 0x127f, 0x007c, 0x703f, 0x0001, 0x0d7e, 0x2069, 0x8ec0,
+	0x20a9, 0x0040, 0x20a1, 0x8ec0, 0x2019, 0xffff, 0x43a4, 0x654c,
+	0xa588, 0x25b2, 0x210c, 0xa18c, 0x00ff, 0x216a, 0xa00e, 0x2011,
+	0x0002, 0x2100, 0xa506, 0x0040, 0x2d4d, 0x1078, 0x3f8e, 0x00c0,
+	0x2d4d, 0x6014, 0x821c, 0x0048, 0x2d45, 0xa398, 0x8ec0, 0xa085,
+	0xff00, 0x8007, 0x201a, 0x0078, 0x2d4c, 0xa398, 0x8ec0, 0x2324,
+	0xa4a4, 0xff00, 0xa405, 0x201a, 0x8210, 0x8108, 0xa182, 0x0080,
+	0x00c8, 0x2d54, 0x0078, 0x2d31, 0x8201, 0x8007, 0x2d0c, 0xa105,
+	0x206a, 0x0d7f, 0x20a9, 0x0040, 0x20a1, 0x8ec0, 0x2099, 0x8ec0,
+	0x1078, 0x3cbc, 0x0078, 0x2d0a, 0x1078, 0x3143, 0x0040, 0x27cd,
+	0x0c7e, 0x1078, 0x3119, 0x0c7f, 0x00c0, 0x2d72, 0x2009, 0x0002,
+	0x0078, 0x27c9, 0x2001, 0x8852, 0x2004, 0xd0b4, 0x0040, 0x2d99,
+	0x6000, 0xd08c, 0x00c0, 0x2d99, 0x6004, 0xa084, 0x00ff, 0xa086,
+	0x0006, 0x00c0, 0x2d99, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a,
+	0x1078, 0x7980, 0x00c0, 0x2d90, 0x2009, 0x0003, 0x0078, 0x27c9,
+	0x7007, 0x0003, 0x701b, 0x2d95, 0x007c, 0x1078, 0x3143, 0x0040,
+	0x27cd, 0x20a9, 0x002b, 0x2c98, 0xade8, 0x0002, 0x2da0, 0x53a3,
+	0x20a9, 0x0004, 0xac80, 0x0006, 0x2098, 0xad80, 0x0006, 0x20a0,
+	0x1078, 0x3cbc, 0x20a9, 0x0004, 0xac80, 0x000a, 0x2098, 0xad80,
+	0x000a, 0x20a0, 0x1078, 0x3cbc, 0x2d00, 0x2009, 0x002b, 0x7a2c,
+	0x7b28, 0x7c3c, 0x7d38, 0x0078, 0x3167, 0x81ff, 0x00c0, 0x27c9,
+	0x1078, 0x3131, 0x0040, 0x27cd, 0x1078, 0x415f, 0x0078, 0x279f,
+	0x81ff, 0x00c0, 0x27c9, 0x7828, 0xa08a, 0x1000, 0x00c8, 0x27cd,
+	0x1078, 0x3143, 0x0040, 0x27cd, 0x1078, 0x41c7, 0x0040, 0x27c9,
+	0x2019, 0x0004, 0x1078, 0x4175, 0x7924, 0x810f, 0x7a28, 0x1078,
+	0x2de3, 0x0078, 0x279f, 0xa186, 0x00ff, 0x0040, 0x2deb, 0x1078,
+	0x2dfb, 0x0078, 0x2dfa, 0x2029, 0x007e, 0x2061, 0x8800, 0x644c,
+	0x2400, 0xa506, 0x0040, 0x2df7, 0x2508, 0x1078, 0x2dfb, 0x8529,
+	0x00c8, 0x2df0, 0x007c, 0x1078, 0x3f8e, 0x00c0, 0x2e06, 0x2200,
+	0x8003, 0x800b, 0x810b, 0xa108, 0x1078, 0x50ff, 0x007c, 0x81ff,
+	0x00c0, 0x27c9, 0x1078, 0x3131, 0x0040, 0x27cd, 0x1078, 0x4017,
+	0x0040, 0x27c9, 0x1078, 0x416a, 0x0078, 0x279f, 0x81ff, 0x00c0,
+	0x27c9, 0x1078, 0x3131, 0x0040, 0x27cd, 0x1078, 0x4017, 0x0040,
+	0x27c9, 0x1078, 0x4154, 0x0078, 0x279f, 0x6100, 0x0078, 0x279f,
+	0x1078, 0x3143, 0x0040, 0x27cd, 0x6004, 0xa086, 0x0707, 0x0040,
+	0x27cd, 0x2001, 0x8800, 0x2004, 0xa086, 0x0003, 0x00c0, 0x27c9,
+	0x0d7e, 0xace8, 0x000a, 0x7924, 0xd184, 0x0040, 0x2e41, 0xace8,
+	0x0006, 0x680c, 0x8007, 0x783e, 0x6808, 0x8007, 0x783a, 0x6b04,
+	0x831f, 0x6a00, 0x8217, 0x0d7f, 0x6100, 0xa18c, 0x0200, 0x0078,
+	0x279f, 0x7824, 0xa084, 0x00ff, 0xa086, 0x00ff, 0x0040, 0x2e5b,
+	0x81ff, 0x00c0, 0x27c9, 0xa006, 0x1078, 0x2262, 0x1078, 0x3d16,
+	0x7828, 0xa08a, 0x1000, 0x00c8, 0x27cd, 0x7924, 0xa18c, 0xff00,
+	0x810f, 0xa186, 0x00ff, 0x0040, 0x2e74, 0xa182, 0x007f, 0x00c8,
+	0x27cd, 0x2100, 0x1078, 0x225c, 0x027e, 0x0c7e, 0x127e, 0x2091,
+	0x8000, 0x2061, 0x8ab5, 0x601b, 0x0000, 0x601f, 0x0000, 0x2061,
 	0x0100, 0x6030, 0xa084, 0x00ff, 0x810f, 0xa105, 0x604a, 0x6043,
-	0x0090, 0x6043, 0x0010, 0x2009, 0x001e, 0x2011, 0x35b6, 0x1078,
-	0x4719, 0x7924, 0xa18c, 0xff00, 0x810f, 0x7a28, 0x1078, 0x2a08,
-	0x127f, 0x0c7f, 0x027f, 0x0078, 0x250d, 0x7924, 0xa18c, 0xff00,
-	0x810f, 0x0c7e, 0x1078, 0x3811, 0x2c08, 0x0c7f, 0x00c0, 0x253b,
-	0x0078, 0x250d, 0x81ff, 0x00c0, 0x2537, 0x60bc, 0xd09c, 0x0040,
-	0x2537, 0x1078, 0x2cf8, 0x0040, 0x2537, 0x6823, 0x0000, 0x7924,
-	0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x2d42, 0x701b, 0x2ae1,
-	0x007c, 0x2009, 0x0080, 0x1078, 0x384c, 0x00c0, 0x2aee, 0x6004,
-	0xa084, 0x00ff, 0xa086, 0x0006, 0x0040, 0x2af2, 0x2021, 0x400a,
-	0x0078, 0x250f, 0x0d7e, 0xade8, 0x000d, 0x6900, 0x6a08, 0x6b0c,
-	0x6c10, 0x6d14, 0x6e18, 0x6820, 0xa0be, 0x0100, 0x0040, 0x2b65,
-	0xa0be, 0x0112, 0x0040, 0x2b65, 0xa0be, 0x0113, 0x0040, 0x2b65,
-	0xa0be, 0x0114, 0x0040, 0x2b65, 0xa0be, 0x0117, 0x0040, 0x2b65,
-	0xa0be, 0x011a, 0x0040, 0x2b65, 0xa0be, 0x0121, 0x0040, 0x2b5b,
-	0xa0be, 0x0131, 0x0040, 0x2b5b, 0xa0be, 0x0171, 0x0040, 0x2b65,
-	0xa0be, 0x0173, 0x0040, 0x2b65, 0xa0be, 0x01a1, 0x00c0, 0x2b2d,
-	0x6830, 0x8007, 0x6832, 0x0078, 0x2b6b, 0xa0be, 0x0212, 0x0040,
-	0x2b61, 0xa0be, 0x0213, 0x0040, 0x2b61, 0xa0be, 0x0214, 0x0040,
-	0x2b53, 0xa0be, 0x0217, 0x0040, 0x2b4d, 0xa0be, 0x021a, 0x00c0,
-	0x2b46, 0x6838, 0x8007, 0x683a, 0x0078, 0x2b65, 0xa0be, 0x0300,
-	0x0040, 0x2b65, 0x0d7f, 0x0078, 0x253b, 0xad80, 0x0010, 0x20a9,
-	0x0007, 0x1078, 0x2ba1, 0xad80, 0x000e, 0x20a9, 0x0001, 0x1078,
-	0x2ba1, 0x0078, 0x2b65, 0xad80, 0x000c, 0x1078, 0x2baf, 0x0078,
-	0x2b6b, 0xad80, 0x000e, 0x1078, 0x2baf, 0xad80, 0x000c, 0x20a9,
-	0x0001, 0x1078, 0x2ba1, 0x0c7e, 0x1078, 0x2cf8, 0x0040, 0x2b96,
-	0x6838, 0xc0fd, 0x683a, 0x6837, 0x0119, 0x684f, 0x0020, 0x685b,
-	0x0001, 0x810b, 0x697e, 0x6883, 0x0000, 0x6a86, 0x6b8a, 0x6c8e,
-	0x6d92, 0x6996, 0x689b, 0x0000, 0x0c7f, 0x0d7f, 0x6837, 0x0000,
-	0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000, 0x1078, 0x6b72, 0x0040,
-	0x2537, 0x7007, 0x0003, 0x701b, 0x2b9a, 0x007c, 0x0c7f, 0x0d7f,
-	0x0078, 0x2537, 0x6820, 0xa086, 0x8001, 0x0040, 0x2537, 0x0078,
-	0x250d, 0x017e, 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x290a,
-	0x8108, 0x280a, 0x8108, 0x00f0, 0x2ba3, 0x017f, 0x007c, 0x017e,
-	0x0a7e, 0x0b7e, 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x2054,
-	0x8000, 0x205c, 0x2b0a, 0x8108, 0x2a0a, 0x8108, 0x290a, 0x8108,
-	0x280a, 0x0b7f, 0x0a7f, 0x017f, 0x007c, 0x81ff, 0x00c0, 0x2537,
+	0x0090, 0x6043, 0x0010, 0x2009, 0x001e, 0x2011, 0x3c98, 0x1078,
+	0x5181, 0x7924, 0xa18c, 0xff00, 0x810f, 0x7a28, 0x1078, 0x2de3,
+	0x127f, 0x0c7f, 0x027f, 0x0078, 0x279f, 0x7924, 0xa18c, 0xff00,
+	0x810f, 0x0c7e, 0x1078, 0x3f53, 0x2c08, 0x0c7f, 0x00c0, 0x27cd,
+	0x0078, 0x279f, 0x81ff, 0x0040, 0x2eb1, 0x2009, 0x0001, 0x0078,
+	0x27c9, 0x60c0, 0xd09c, 0x00c0, 0x2eb9, 0x2009, 0x0005, 0x0078,
+	0x27c9, 0x1078, 0x3119, 0x00c0, 0x2ec1, 0x2009, 0x0002, 0x0078,
+	0x27c9, 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3163,
+	0x701b, 0x2ecb, 0x007c, 0x2009, 0x0080, 0x1078, 0x3f8e, 0x00c0,
+	0x2ed8, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0040, 0x2edc,
+	0x2021, 0x400a, 0x0078, 0x27a1, 0x0d7e, 0xade8, 0x000d, 0x6900,
+	0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x6e18, 0x6820, 0xa0be, 0x0100,
+	0x0040, 0x2f4f, 0xa0be, 0x0112, 0x0040, 0x2f4f, 0xa0be, 0x0113,
+	0x0040, 0x2f4f, 0xa0be, 0x0114, 0x0040, 0x2f4f, 0xa0be, 0x0117,
+	0x0040, 0x2f4f, 0xa0be, 0x011a, 0x0040, 0x2f4f, 0xa0be, 0x0121,
+	0x0040, 0x2f45, 0xa0be, 0x0131, 0x0040, 0x2f45, 0xa0be, 0x0171,
+	0x0040, 0x2f4f, 0xa0be, 0x0173, 0x0040, 0x2f4f, 0xa0be, 0x01a1,
+	0x00c0, 0x2f17, 0x6830, 0x8007, 0x6832, 0x0078, 0x2f55, 0xa0be,
+	0x0212, 0x0040, 0x2f4b, 0xa0be, 0x0213, 0x0040, 0x2f4b, 0xa0be,
+	0x0214, 0x0040, 0x2f3d, 0xa0be, 0x0217, 0x0040, 0x2f37, 0xa0be,
+	0x021a, 0x00c0, 0x2f30, 0x6838, 0x8007, 0x683a, 0x0078, 0x2f4f,
+	0xa0be, 0x0300, 0x0040, 0x2f4f, 0x0d7f, 0x0078, 0x27cd, 0xad80,
+	0x0010, 0x20a9, 0x0007, 0x1078, 0x2f95, 0xad80, 0x000e, 0x20a9,
+	0x0001, 0x1078, 0x2f95, 0x0078, 0x2f4f, 0xad80, 0x000c, 0x1078,
+	0x2fa3, 0x0078, 0x2f55, 0xad80, 0x000e, 0x1078, 0x2fa3, 0xad80,
+	0x000c, 0x20a9, 0x0001, 0x1078, 0x2f95, 0x0c7e, 0x1078, 0x3119,
+	0x0040, 0x2f86, 0x6838, 0xc0fd, 0x683a, 0x6837, 0x0119, 0x6853,
+	0x0000, 0x684f, 0x0020, 0x685b, 0x0001, 0x810b, 0x697e, 0x6883,
+	0x0000, 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, 0x6996, 0x689b, 0x0000,
+	0x0c7f, 0x0d7f, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823,
+	0x0000, 0x1078, 0x7948, 0x00c0, 0x2f81, 0x2009, 0x0003, 0x0078,
+	0x27c9, 0x7007, 0x0003, 0x701b, 0x2f8c, 0x007c, 0x0c7f, 0x0d7f,
+	0x2009, 0x0002, 0x0078, 0x27c9, 0x6820, 0xa086, 0x8001, 0x00c0,
+	0x279f, 0x2009, 0x0004, 0x0078, 0x27c9, 0x017e, 0x2008, 0x2044,
+	0x8000, 0x204c, 0x8000, 0x290a, 0x8108, 0x280a, 0x8108, 0x00f0,
+	0x2f97, 0x017f, 0x007c, 0x017e, 0x0a7e, 0x0b7e, 0x2008, 0x2044,
+	0x8000, 0x204c, 0x8000, 0x2054, 0x8000, 0x205c, 0x2b0a, 0x8108,
+	0x2a0a, 0x8108, 0x290a, 0x8108, 0x280a, 0x0b7f, 0x0a7f, 0x017f,
+	0x007c, 0x81ff, 0x0040, 0x2fc0, 0x2009, 0x0001, 0x0078, 0x27c9,
 	0x7924, 0x2140, 0xa18c, 0xff00, 0x810f, 0xa182, 0x0080, 0x0048,
-	0x253b, 0xa182, 0x00ff, 0x00c8, 0x253b, 0x7a2c, 0x7b28, 0x6064,
-	0xa306, 0x00c0, 0x2be3, 0x6068, 0xa24e, 0x0040, 0x253b, 0xa9cc,
-	0xff00, 0x0040, 0x253b, 0x0c7e, 0x1078, 0x2c57, 0x2c68, 0x0c7f,
-	0x0040, 0x2c0a, 0xa0c6, 0x4000, 0x00c0, 0x2bf0, 0x0078, 0x2c07,
-	0xa0c6, 0x4007, 0x00c0, 0x2bf7, 0x2408, 0x0078, 0x2c07, 0xa0c6,
-	0x4008, 0x00c0, 0x2bff, 0x2708, 0x2610, 0x0078, 0x2c07, 0xa0c6,
-	0x4009, 0x00c0, 0x2c05, 0x0078, 0x2c07, 0x2001, 0x4006, 0x2020,
-	0x0078, 0x250f, 0x017e, 0x0b7e, 0x0c7e, 0x0e7e, 0x2c70, 0x1078,
-	0x5cb4, 0x0040, 0x2c45, 0x2d00, 0x601a, 0x2e58, 0x0e7f, 0x0e7e,
-	0x0c7e, 0x1078, 0x2cf8, 0x0c7f, 0x2b70, 0x0040, 0x2537, 0x6837,
-	0x0000, 0x2d00, 0x6012, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a,
-	0x127e, 0x2091, 0x8000, 0x1078, 0x22b5, 0x127f, 0x601f, 0x0001,
-	0x2001, 0x0000, 0x1078, 0x37e0, 0x2001, 0x0002, 0x1078, 0x37f4,
-	0x127e, 0x2091, 0x8000, 0x7088, 0x8000, 0x708a, 0x127f, 0x2009,
-	0x0002, 0x1078, 0x5d41, 0xa085, 0x0001, 0x0e7f, 0x0c7f, 0x0b7f,
-	0x017f, 0x0040, 0x2537, 0x7007, 0x0003, 0x701b, 0x2c50, 0x007c,
-	0x6830, 0xa086, 0x0100, 0x00c0, 0x250d, 0x0078, 0x2537, 0x0e7e,
-	0x0d7e, 0x2029, 0x0000, 0x2021, 0x0080, 0x20a9, 0x007f, 0x2071,
-	0x78a0, 0x2e04, 0xa005, 0x00c0, 0x2c6b, 0x2100, 0xa406, 0x0040,
-	0x2ca8, 0x0078, 0x2c9c, 0x2068, 0x6f10, 0x2700, 0xa306, 0x00c0,
-	0x2c8d, 0x6e14, 0x2600, 0xa206, 0x00c0, 0x2c8d, 0x2400, 0xa106,
-	0x00c0, 0x2c89, 0x2d60, 0xd884, 0x0040, 0x2cae, 0x6004, 0xa084,
-	0x00ff, 0xa086, 0x0006, 0x00c0, 0x2cae, 0x2001, 0x4000, 0x0078,
-	0x2caf, 0x2001, 0x4007, 0x0078, 0x2caf, 0x2400, 0xa106, 0x00c0,
-	0x2c9c, 0x6e14, 0x87ff, 0x00c0, 0x2c98, 0x86ff, 0x0040, 0x2ca8,
-	0x2001, 0x4008, 0x0078, 0x2caf, 0x8420, 0x8e70, 0x00f0, 0x2c61,
-	0x2001, 0x4009, 0x0078, 0x2caf, 0x2001, 0x0001, 0x0078, 0x2caf,
-	0x1078, 0x3811, 0x00c0, 0x2ca4, 0x6312, 0x6216, 0xa006, 0xa005,
-	0x0d7f, 0x0e7f, 0x007c, 0x81ff, 0x00c0, 0x2537, 0x1078, 0x2cf8,
-	0x0040, 0x2537, 0x6837, 0x0000, 0x7824, 0xa005, 0x0040, 0x253b,
-	0xa096, 0x00ff, 0x0040, 0x2cc8, 0xa092, 0x0004, 0x00c8, 0x253b,
-	0x2010, 0x2d18, 0x1078, 0x2277, 0x0040, 0x2537, 0x7007, 0x0003,
-	0x701b, 0x2cd3, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x2537,
-	0x0078, 0x250d, 0x81ff, 0x00c0, 0x2537, 0x7924, 0xa18c, 0xff00,
-	0x810f, 0xa182, 0x0080, 0x0048, 0x253b, 0xa182, 0x00ff, 0x00c8,
-	0x253b, 0x127e, 0x2091, 0x8000, 0x1078, 0x6a99, 0x00c0, 0x2cf5,
-	0x1078, 0x3834, 0x127f, 0x0078, 0x250d, 0x127f, 0x0078, 0x2537,
-	0x1078, 0x1327, 0x0040, 0x2d0f, 0xa006, 0x6802, 0x7010, 0xa005,
-	0x00c0, 0x2d07, 0x2d00, 0x7012, 0x7016, 0x0078, 0x2d0d, 0x7014,
-	0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, 0xad80, 0x000d, 0x007c,
-	0x7924, 0x810f, 0xa18c, 0x00ff, 0x1078, 0x384c, 0x00c0, 0x2d1f,
-	0x7e28, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0048, 0x2d20, 0xa066,
-	0x8cff, 0x007c, 0x7e24, 0x860f, 0xa18c, 0x00ff, 0x1078, 0x384c,
-	0x00c0, 0x2d30, 0xa6b4, 0x00ff, 0xa682, 0x4000, 0x0048, 0x2d31,
-	0xa066, 0x8cff, 0x007c, 0x017e, 0x7110, 0x81ff, 0x0040, 0x2d3e,
-	0x2168, 0x6904, 0x1078, 0x1340, 0x0078, 0x2d35, 0x7112, 0x7116,
-	0x017f, 0x007c, 0x2031, 0x0001, 0x0078, 0x2d48, 0x2031, 0x0000,
-	0x2061, 0x77bd, 0x6606, 0x6112, 0x600e, 0x6226, 0x632a, 0x642e,
-	0x6532, 0x2c10, 0x1078, 0x1377, 0x7007, 0x0002, 0x701b, 0x250d,
-	0x007c, 0x0f7e, 0x127e, 0x2091, 0x8000, 0x2079, 0x0000, 0x2001,
-	0x777b, 0x2004, 0xa005, 0x00c0, 0x2d74, 0x0068, 0x2d74, 0x7818,
-	0xd084, 0x00c0, 0x2d74, 0x781b, 0x0001, 0x7a22, 0x7b26, 0x7c2a,
-	0x2091, 0x4080, 0x0078, 0x2d99, 0x017e, 0x0c7e, 0x0e7e, 0x2071,
-	0x776d, 0x7138, 0xa182, 0x0008, 0x0048, 0x2d82, 0x7030, 0x2060,
-	0x0078, 0x2d93, 0x7030, 0xa0e0, 0x0008, 0xac82, 0x77bd, 0x0048,
-	0x2d8b, 0x2061, 0x777d, 0x2c00, 0x7032, 0x81ff, 0x00c0, 0x2d91,
-	0x7036, 0x8108, 0x713a, 0x2262, 0x6306, 0x640a, 0x0e7f, 0x0c7f,
-	0x017f, 0x127f, 0x0f7f, 0x007c, 0x0e7e, 0x2071, 0x776d, 0x7038,
-	0xa005, 0x0040, 0x2dd5, 0x127e, 0x2091, 0x8000, 0x0068, 0x2dd4,
-	0x0f7e, 0x2079, 0x0000, 0x7818, 0xd084, 0x00c0, 0x2dd3, 0x0c7e,
-	0x781b, 0x0001, 0x7034, 0x2060, 0x2c04, 0x7822, 0x6004, 0x7826,
-	0x6008, 0x782a, 0x2091, 0x4080, 0x7038, 0x8001, 0x703a, 0xa005,
-	0x00c0, 0x2dc9, 0x7033, 0x777d, 0x7037, 0x777d, 0x0c7f, 0x0078,
-	0x2dd3, 0xac80, 0x0008, 0xa0fa, 0x77bd, 0x0048, 0x2dd1, 0x2001,
-	0x777d, 0x7036, 0x0c7f, 0x0f7f, 0x127f, 0x0e7f, 0x007c, 0x027e,
-	0x2001, 0x7752, 0x2004, 0xd0c4, 0x0040, 0x2de2, 0x2011, 0x8014,
-	0x1078, 0x2d59, 0x027f, 0x007c, 0x81ff, 0x00c0, 0x2537, 0x127e,
-	0x2091, 0x8000, 0x6030, 0xc08d, 0x6032, 0x1078, 0x3591, 0x127f,
-	0x0078, 0x250d, 0x7824, 0x2008, 0xa18c, 0xfffd, 0x00c0, 0x2dfd,
-	0x61c8, 0xa10d, 0x61ca, 0x0078, 0x250d, 0x0078, 0x253b, 0x81ff,
-	0x00c0, 0x2537, 0x6000, 0xa086, 0x0003, 0x00c0, 0x2537, 0x2001,
-	0x7752, 0x2004, 0xd0a4, 0x00c0, 0x2537, 0x1078, 0x2d22, 0x0040,
-	0x253b, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x2e1c,
-	0x7828, 0xa005, 0x0040, 0x250d, 0x0c7e, 0x1078, 0x2cf8, 0x0c7f,
-	0x0040, 0x2537, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd,
-	0x683a, 0x1078, 0x6bfb, 0x0040, 0x2537, 0x7007, 0x0003, 0x701b,
-	0x2e32, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x2537, 0x0078,
-	0x250d, 0x2001, 0x7700, 0x2004, 0xa086, 0x0003, 0x00c0, 0x2537,
-	0x7f24, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x2cf8, 0x0040,
-	0x2537, 0x2009, 0x0000, 0x2031, 0x0000, 0x7023, 0x0000, 0x702f,
-	0x0000, 0xad80, 0x0005, 0x7026, 0x20a0, 0x1078, 0x384c, 0x00c0,
-	0x2e7f, 0x6004, 0xa0c6, 0x0707, 0x0040, 0x2e7f, 0xa084, 0x00ff,
-	0xa0c6, 0x0006, 0x00c0, 0x2e7f, 0x87ff, 0x0040, 0x2e72, 0xac80,
-	0x0006, 0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3, 0x1078, 0x2baf,
-	0x0078, 0x2e7b, 0xac80, 0x000a, 0x2098, 0x3400, 0x20a9, 0x0004,
-	0x53a3, 0x1078, 0x2baf, 0x21a2, 0x94a0, 0xa6b0, 0x0005, 0x8108,
-	0xa186, 0x007e, 0x0040, 0x2e8a, 0xa686, 0x0028, 0x0040, 0x2e93,
-	0x0078, 0x2e55, 0x86ff, 0x00c0, 0x2e91, 0x7120, 0x810b, 0x0078,
-	0x250d, 0x702f, 0x0001, 0x711e, 0x7020, 0xa600, 0x7022, 0x772a,
-	0x2061, 0x77bd, 0x6007, 0x0000, 0x6612, 0x7024, 0x600e, 0x6226,
-	0x632a, 0x642e, 0x6532, 0x2c10, 0x1078, 0x1377, 0x7007, 0x0002,
-	0x701b, 0x2eab, 0x007c, 0x702c, 0xa005, 0x00c0, 0x2ebd, 0x711c,
-	0x7024, 0x20a0, 0x7728, 0x2031, 0x0000, 0x2061, 0x77bd, 0x6224,
-	0x6328, 0x642c, 0x6530, 0x0078, 0x2e55, 0x7120, 0x810b, 0x0078,
-	0x250d, 0x127e, 0x0c7e, 0x0e7e, 0x2061, 0x0100, 0x2071, 0x7700,
-	0x6044, 0xd0a4, 0x00c0, 0x2eea, 0xd084, 0x0040, 0x2ed3, 0x1078,
-	0x3015, 0x0078, 0x2ee6, 0xd08c, 0x0040, 0x2eda, 0x1078, 0x2f2c,
-	0x0078, 0x2ee6, 0xd094, 0x0040, 0x2ee1, 0x1078, 0x2f0f, 0x0078,
-	0x2ee6, 0xd09c, 0x0040, 0x2ee6, 0x1078, 0x2ef4, 0x0e7f, 0x0c7f,
-	0x127f, 0x007c, 0x017e, 0x6128, 0xd19c, 0x00c0, 0x2ef1, 0xc19d,
-	0x612a, 0x017f, 0x0078, 0x2ee6, 0x6043, 0x0040, 0x6043, 0x0000,
-	0x706f, 0x0000, 0x7087, 0x0001, 0x70a7, 0x0000, 0x70bf, 0x0000,
-	0x2009, 0x7dc0, 0x200b, 0x0000, 0x707f, 0x0000, 0x7073, 0x000f,
-	0x2009, 0x000f, 0x2011, 0x3551, 0x1078, 0x4719, 0x007c, 0x7070,
-	0xa005, 0x00c0, 0x2f2b, 0x2011, 0x3551, 0x1078, 0x4689, 0x6043,
-	0x0020, 0x6043, 0x0000, 0x6044, 0xd08c, 0x00c0, 0x2f27, 0x7083,
-	0x0000, 0x6043, 0x0090, 0x6043, 0x0010, 0x0078, 0x2f2b, 0x7077,
-	0x0000, 0x0078, 0x2f2b, 0x007c, 0x7074, 0xa08a, 0x0003, 0x00c8,
-	0x2f35, 0x1079, 0x2f38, 0x0078, 0x2f37, 0x1078, 0x12cd, 0x007c,
-	0x2f3b, 0x2f8a, 0x3014, 0x0f7e, 0x7077, 0x0001, 0x20e1, 0xa000,
-	0x20e1, 0x8700, 0x1078, 0x1de4, 0x20e1, 0x9080, 0x20e1, 0x4000,
-	0x2079, 0x7c00, 0x207b, 0x2200, 0x7807, 0x00ef, 0x780b, 0x0000,
-	0x780f, 0x00ef, 0x7813, 0x0138, 0x7817, 0x0000, 0x781b, 0x0000,
-	0x781f, 0x0000, 0x7823, 0xffff, 0x7827, 0xffff, 0x782b, 0x0000,
-	0x782f, 0x0000, 0x2079, 0x7c0c, 0x207b, 0x1101, 0x7807, 0x0000,
-	0x2099, 0x7705, 0x20a1, 0x7c0e, 0x20a9, 0x0004, 0x53a3, 0x2079,
-	0x7c12, 0x207b, 0x0000, 0x7807, 0x0000, 0x2099, 0x7c00, 0x20a1,
-	0x020b, 0x20a9, 0x0014, 0x53a6, 0x60c3, 0x000c, 0x600f, 0x0000,
-	0x1078, 0x3578, 0x0f7f, 0x707b, 0x0000, 0x6043, 0x0008, 0x6043,
-	0x0000, 0x007c, 0x0d7e, 0x7078, 0x707b, 0x0000, 0xa025, 0x0040,
-	0x2ffe, 0x6020, 0xd0b4, 0x00c0, 0x2ffc, 0x7184, 0x81ff, 0x0040,
-	0x2fe5, 0xa486, 0x000c, 0x00c0, 0x2ff0, 0xa480, 0x0018, 0x8004,
-	0x20a8, 0x2011, 0x7c80, 0x2019, 0x7c00, 0x220c, 0x2304, 0xa106,
-	0x00c0, 0x2fbc, 0x8210, 0x8318, 0x00f0, 0x2fa5, 0x6043, 0x0004,
-	0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006, 0x7077, 0x0002,
-	0x7083, 0x0002, 0x0078, 0x2ffc, 0x2069, 0x7c80, 0x6930, 0xa18e,
-	0x1101, 0x00c0, 0x2ff0, 0x6834, 0xa005, 0x00c0, 0x2ff0, 0x6900,
-	0xa18c, 0x00ff, 0x00c0, 0x2fd0, 0x6804, 0xa005, 0x0040, 0x2fe5,
-	0x2011, 0x7c8e, 0x2019, 0x7705, 0x20a9, 0x0004, 0x220c, 0x2304,
-	0xa102, 0x0048, 0x2fe3, 0x00c0, 0x2ff0, 0x8210, 0x8318, 0x00f0,
-	0x2fd6, 0x0078, 0x2ff0, 0x7087, 0x0000, 0x20e1, 0x9080, 0x20e1,
-	0x4000, 0x2099, 0x7c80, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6,
-	0x6043, 0x0008, 0x6043, 0x0000, 0x6020, 0xd0b4, 0x00c0, 0x2ffc,
-	0x60c3, 0x000c, 0x1078, 0x3578, 0x0d7f, 0x007c, 0x6020, 0xd0b4,
-	0x00c0, 0x2ffc, 0x60c3, 0x000c, 0x2011, 0x7940, 0x2013, 0x0000,
-	0x707b, 0x0000, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575,
-	0x1078, 0x5693, 0x0078, 0x2ffc, 0x007c, 0x7080, 0xa08a, 0x001d,
-	0x00c8, 0x301e, 0x1079, 0x3021, 0x0078, 0x3020, 0x1078, 0x12cd,
-	0x007c, 0x3045, 0x3054, 0x3085, 0x309a, 0x30ca, 0x30f2, 0x3122,
-	0x314c, 0x317c, 0x31a2, 0x31eb, 0x320d, 0x3231, 0x3247, 0x326f,
-	0x3282, 0x328b, 0x32a4, 0x32d2, 0x32fa, 0x3328, 0x3352, 0x339a,
-	0x33cb, 0x33ed, 0x342b, 0x3451, 0x346a, 0x3477, 0x7003, 0x0007,
-	0x6004, 0xa084, 0xfff9, 0x6006, 0x007c, 0x608b, 0xbc94, 0x608f,
-	0xf0f0, 0x6043, 0x0002, 0x7083, 0x0001, 0x2009, 0x07d0, 0x2011,
-	0x3558, 0x1078, 0x467c, 0x007c, 0x0f7e, 0x7078, 0xa086, 0x0014,
-	0x00c0, 0x3083, 0x6043, 0x0000, 0x6020, 0xd0b4, 0x00c0, 0x3083,
-	0x2079, 0x7c80, 0x7a30, 0xa296, 0x1102, 0x00c0, 0x3081, 0x7834,
-	0xa005, 0x00c0, 0x3081, 0x7a38, 0xd2fc, 0x0040, 0x3077, 0x70a4,
-	0xa005, 0x00c0, 0x3077, 0x1078, 0x3611, 0x70a7, 0x0001, 0x2011,
-	0x3558, 0x1078, 0x4689, 0x7083, 0x0010, 0x1078, 0x328b, 0x0078,
-	0x3083, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x0003, 0x6043,
-	0x0004, 0x1078, 0x35e2, 0x20a3, 0x1102, 0x20a3, 0x0000, 0x20a9,
-	0x000a, 0x20a3, 0x0000, 0x00f0, 0x3091, 0x60c3, 0x0014, 0x1078,
-	0x3578, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x30c8, 0x2011,
-	0x3558, 0x1078, 0x4689, 0xa086, 0x0014, 0x00c0, 0x30c4, 0x2079,
-	0x7c80, 0x7a30, 0xa296, 0x1102, 0x00c0, 0x30c4, 0x7834, 0xa005,
-	0x00c0, 0x30c4, 0x7a38, 0xd2fc, 0x0040, 0x30be, 0x70a4, 0xa005,
-	0x00c0, 0x30be, 0x1078, 0x3611, 0x70a7, 0x0001, 0x7083, 0x0004,
-	0x1078, 0x30ca, 0x0078, 0x30c8, 0x7083, 0x0002, 0x707b, 0x0000,
-	0x0f7f, 0x007c, 0x7083, 0x0005, 0x1078, 0x35e2, 0x20a3, 0x1103,
-	0x20a3, 0x0000, 0x3430, 0x2011, 0x7c8e, 0x706c, 0xa005, 0x00c0,
-	0x30e4, 0x714c, 0xa186, 0xffff, 0x0040, 0x30e4, 0x1078, 0x351c,
-	0x0040, 0x30e4, 0x1078, 0x3611, 0x20a9, 0x0008, 0x2298, 0x26a0,
-	0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078,
-	0x3578, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x3120, 0x2011,
-	0x3558, 0x1078, 0x4689, 0xa086, 0x0014, 0x00c0, 0x311c, 0x2079,
-	0x7c80, 0x7a30, 0xa296, 0x1103, 0x00c0, 0x311c, 0x7834, 0xa005,
-	0x00c0, 0x311c, 0x7a38, 0xd2fc, 0x0040, 0x3116, 0x70a4, 0xa005,
-	0x00c0, 0x3116, 0x1078, 0x3611, 0x70a7, 0x0001, 0x7083, 0x0006,
-	0x1078, 0x3122, 0x0078, 0x3120, 0x7083, 0x0002, 0x707b, 0x0000,
-	0x0f7f, 0x007c, 0x7083, 0x0007, 0x1078, 0x35e2, 0x20a3, 0x1104,
-	0x20a3, 0x0000, 0x3430, 0x2011, 0x7c8e, 0x706c, 0xa005, 0x00c0,
-	0x313e, 0x7150, 0xa186, 0xffff, 0x0040, 0x313e, 0xa180, 0x2329,
-	0x200c, 0xa18c, 0xff00, 0x810f, 0x1078, 0x351c, 0x20a9, 0x0008,
-	0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
-	0x0014, 0x1078, 0x3578, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040,
-	0x317a, 0x2011, 0x3558, 0x1078, 0x4689, 0xa086, 0x0014, 0x00c0,
-	0x3176, 0x2079, 0x7c80, 0x7a30, 0xa296, 0x1104, 0x00c0, 0x3176,
-	0x7834, 0xa005, 0x00c0, 0x3176, 0x7a38, 0xd2fc, 0x0040, 0x3170,
-	0x70a4, 0xa005, 0x00c0, 0x3170, 0x1078, 0x3611, 0x70a7, 0x0001,
-	0x7083, 0x0008, 0x1078, 0x317c, 0x0078, 0x317a, 0x7083, 0x0002,
-	0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x0009, 0x1078, 0x35e2,
-	0x20a3, 0x1105, 0x20a3, 0x0100, 0x3430, 0x706c, 0xa005, 0x00c0,
-	0x318f, 0x1078, 0x3486, 0x0040, 0x319f, 0x0078, 0x3199, 0x20a9,
-	0x0008, 0x2099, 0x7c8e, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x60c3, 0x0014, 0x1078, 0x3578, 0x0078, 0x31a1, 0x1078,
-	0x303e, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x31e9, 0x2011,
-	0x3558, 0x1078, 0x4689, 0xa086, 0x0014, 0x00c0, 0x31e5, 0x2079,
-	0x7c80, 0x7a30, 0xa296, 0x1105, 0x00c0, 0x31e5, 0x7834, 0x2011,
-	0x0100, 0xa21e, 0x00c0, 0x31ce, 0x7a38, 0xd2fc, 0x0040, 0x31c8,
-	0x70a4, 0xa005, 0x00c0, 0x31c8, 0x1078, 0x3611, 0x70a7, 0x0001,
-	0x7083, 0x000a, 0x1078, 0x31eb, 0x0078, 0x31e9, 0xa005, 0x00c0,
-	0x31e5, 0x7a38, 0xd2fc, 0x0040, 0x31dd, 0x70a4, 0xa005, 0x00c0,
-	0x31dd, 0x1078, 0x3611, 0x70a7, 0x0001, 0x707f, 0x0000, 0x7083,
-	0x000e, 0x1078, 0x326f, 0x0078, 0x31e9, 0x7083, 0x0002, 0x707b,
-	0x0000, 0x0f7f, 0x007c, 0x7083, 0x000b, 0x2011, 0x7c0e, 0x22a0,
-	0x20a9, 0x0040, 0x2019, 0xffff, 0x43a4, 0x20a9, 0x0002, 0x2009,
-	0x0000, 0x41a4, 0x1078, 0x35e2, 0x20a3, 0x1106, 0x20a3, 0x0000,
-	0x6030, 0xa085, 0x0100, 0x2012, 0x2298, 0x20a9, 0x0042, 0x53a6,
-	0x60c3, 0x0084, 0x1078, 0x3578, 0x007c, 0x0f7e, 0x7078, 0xa005,
-	0x0040, 0x322f, 0x2011, 0x3558, 0x1078, 0x4689, 0xa086, 0x0084,
-	0x00c0, 0x322b, 0x2079, 0x7c80, 0x7a30, 0xa296, 0x1106, 0x00c0,
-	0x322b, 0x7834, 0xa005, 0x00c0, 0x322b, 0x7083, 0x000c, 0x1078,
-	0x3231, 0x0078, 0x322f, 0x7083, 0x0002, 0x707b, 0x0000, 0x0f7f,
-	0x007c, 0x7083, 0x000d, 0x1078, 0x35e2, 0x20a3, 0x1107, 0x20a3,
-	0x0000, 0x2099, 0x7c8e, 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x60c3, 0x0084, 0x1078, 0x3578, 0x007c, 0x0f7e,
-	0x7078, 0xa005, 0x0040, 0x326d, 0x2011, 0x3558, 0x1078, 0x4689,
-	0xa086, 0x0084, 0x00c0, 0x3269, 0x2079, 0x7c80, 0x7a30, 0xa296,
-	0x1107, 0x00c0, 0x3269, 0x7834, 0xa005, 0x00c0, 0x3269, 0x707f,
-	0x0001, 0x1078, 0x35d4, 0x7083, 0x000e, 0x1078, 0x326f, 0x0078,
-	0x326d, 0x7083, 0x0002, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083,
-	0x000f, 0x707b, 0x0000, 0x608b, 0xbc85, 0x608f, 0xb5b5, 0x6043,
-	0x0005, 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011, 0x3558, 0x1078,
-	0x467c, 0x007c, 0x7078, 0xa005, 0x0040, 0x328a, 0x2011, 0x3558,
-	0x1078, 0x4689, 0x007c, 0x7083, 0x0011, 0x20e1, 0x9080, 0x20e1,
-	0x4000, 0x2099, 0x7c80, 0x20a1, 0x020b, 0x7478, 0xa480, 0x0018,
-	0xa080, 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3,
-	0x0014, 0x1078, 0x3578, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040,
-	0x32d0, 0x2011, 0x3558, 0x1078, 0x4689, 0xa086, 0x0014, 0x00c0,
-	0x32ce, 0x2079, 0x7c80, 0x7a30, 0xa296, 0x1103, 0x00c0, 0x32ce,
-	0x7834, 0xa005, 0x00c0, 0x32ce, 0x7a38, 0xd2fc, 0x0040, 0x32c8,
-	0x70a4, 0xa005, 0x00c0, 0x32c8, 0x1078, 0x3611, 0x70a7, 0x0001,
-	0x7083, 0x0012, 0x1078, 0x32d2, 0x0078, 0x32d0, 0x707b, 0x0000,
-	0x0f7f, 0x007c, 0x7083, 0x0013, 0x1078, 0x35ee, 0x20a3, 0x1103,
-	0x20a3, 0x0000, 0x3430, 0x2011, 0x7c8e, 0x706c, 0xa005, 0x00c0,
-	0x32ec, 0x714c, 0xa186, 0xffff, 0x0040, 0x32ec, 0x1078, 0x351c,
-	0x0040, 0x32ec, 0x1078, 0x3611, 0x20a9, 0x0008, 0x2298, 0x26a0,
-	0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078,
-	0x3578, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x3326, 0x2011,
-	0x3558, 0x1078, 0x4689, 0xa086, 0x0014, 0x00c0, 0x3324, 0x2079,
-	0x7c80, 0x7a30, 0xa296, 0x1104, 0x00c0, 0x3324, 0x7834, 0xa005,
-	0x00c0, 0x3324, 0x7a38, 0xd2fc, 0x0040, 0x331e, 0x70a4, 0xa005,
-	0x00c0, 0x331e, 0x1078, 0x3611, 0x70a7, 0x0001, 0x7083, 0x0014,
-	0x1078, 0x3328, 0x0078, 0x3326, 0x707b, 0x0000, 0x0f7f, 0x007c,
-	0x7083, 0x0015, 0x1078, 0x35ee, 0x20a3, 0x1104, 0x20a3, 0x0000,
-	0x3430, 0x2011, 0x7c8e, 0x706c, 0xa006, 0x00c0, 0x3344, 0x7150,
-	0xa186, 0xffff, 0x0040, 0x3344, 0xa180, 0x2329, 0x200c, 0xa18c,
-	0xff00, 0x810f, 0x1078, 0x351c, 0x20a9, 0x0008, 0x2298, 0x26a0,
+	0x27cd, 0xa182, 0x00ff, 0x00c8, 0x27cd, 0x7a2c, 0x7b28, 0x6068,
+	0xa306, 0x00c0, 0x2fdb, 0x606c, 0xa24e, 0x0040, 0x27cd, 0xa9cc,
+	0xff00, 0x0040, 0x27cd, 0x0c7e, 0x1078, 0x3071, 0x2c68, 0x0c7f,
+	0x0040, 0x3002, 0xa0c6, 0x4000, 0x00c0, 0x2fe8, 0x0078, 0x2fff,
+	0xa0c6, 0x4007, 0x00c0, 0x2fef, 0x2408, 0x0078, 0x2fff, 0xa0c6,
+	0x4008, 0x00c0, 0x2ff7, 0x2708, 0x2610, 0x0078, 0x2fff, 0xa0c6,
+	0x4009, 0x00c0, 0x2ffd, 0x0078, 0x2fff, 0x2001, 0x4006, 0x2020,
+	0x0078, 0x27a1, 0x2d00, 0x7022, 0x017e, 0x0b7e, 0x0c7e, 0x0e7e,
+	0x2c70, 0x1078, 0x68a8, 0x0040, 0x304f, 0x2d00, 0x601a, 0x2001,
+	0x8856, 0x2004, 0xa084, 0x00ff, 0x6842, 0x2e58, 0x0e7f, 0x0e7e,
+	0x0c7e, 0x1078, 0x3119, 0x0c7f, 0x2b70, 0x00c0, 0x3029, 0x1078,
+	0x690e, 0x0e7f, 0x0c7f, 0x0b7f, 0x017f, 0x2009, 0x0002, 0x0078,
+	0x27c9, 0x6837, 0x0000, 0x2d00, 0x6012, 0x6833, 0x0000, 0x6838,
+	0xc0fd, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x24bf, 0x127f,
+	0x601f, 0x0001, 0x2001, 0x0000, 0x1078, 0x3ef1, 0x2001, 0x0002,
+	0x1078, 0x3f05, 0x127e, 0x2091, 0x8000, 0x708c, 0x8000, 0x708e,
+	0x127f, 0x2009, 0x0002, 0x1078, 0x6939, 0xa085, 0x0001, 0x0e7f,
+	0x0c7f, 0x0b7f, 0x017f, 0x00c0, 0x3059, 0x2009, 0x0003, 0x0078,
+	0x27c9, 0x7007, 0x0003, 0x701b, 0x305e, 0x007c, 0x6830, 0xa086,
+	0x0100, 0x2009, 0x0004, 0x0040, 0x27c9, 0x7020, 0x2060, 0x2009,
+	0x0000, 0x1078, 0x4233, 0x00c0, 0x306f, 0x2009, 0x0001, 0x0078,
+	0x279f, 0x0e7e, 0x0d7e, 0x2029, 0x0000, 0x2021, 0x0080, 0x20a9,
+	0x007f, 0x2071, 0x89b4, 0x2e04, 0xa005, 0x00c0, 0x3086, 0x2100,
+	0xa406, 0x00c0, 0x30b7, 0x2428, 0x0078, 0x30b7, 0x2068, 0x6f10,
+	0x2700, 0xa306, 0x00c0, 0x30a8, 0x6e14, 0x2600, 0xa206, 0x00c0,
+	0x30a8, 0x2400, 0xa106, 0x00c0, 0x30a4, 0x2d60, 0xd884, 0x0040,
+	0x30cc, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x30cc,
+	0x2001, 0x4000, 0x0078, 0x30cd, 0x2001, 0x4007, 0x0078, 0x30cd,
+	0x2400, 0xa106, 0x00c0, 0x30b7, 0x6e14, 0x87ff, 0x00c0, 0x30b3,
+	0x86ff, 0x0040, 0x3083, 0x2001, 0x4008, 0x0078, 0x30cd, 0x8420,
+	0x8e70, 0x00f0, 0x307b, 0x85ff, 0x00c0, 0x30c6, 0x2001, 0x4009,
+	0x0078, 0x30cd, 0x2001, 0x0001, 0x0078, 0x30cd, 0x1078, 0x3f53,
+	0x00c0, 0x30c2, 0x6312, 0x6216, 0xa006, 0xa005, 0x0d7f, 0x0e7f,
+	0x007c, 0x81ff, 0x00c0, 0x27c9, 0x1078, 0x3119, 0x0040, 0x27c9,
+	0x6837, 0x0000, 0x7824, 0xa005, 0x0040, 0x27cd, 0xa096, 0x00ff,
+	0x0040, 0x30e6, 0xa092, 0x0004, 0x00c8, 0x27cd, 0x2010, 0x2d18,
+	0x1078, 0x2481, 0x0040, 0x27c9, 0x7007, 0x0003, 0x701b, 0x30f1,
+	0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x27c9, 0x0078, 0x279f,
+	0x7924, 0xa18c, 0xff00, 0x810f, 0xa182, 0x0080, 0x0048, 0x27cd,
+	0xa182, 0x00ff, 0x00c8, 0x27cd, 0x127e, 0x2091, 0x8000, 0x1078,
+	0x782e, 0x00c0, 0x3116, 0xa190, 0x8934, 0x2204, 0xa065, 0x0040,
+	0x3116, 0x1078, 0x3d31, 0x127f, 0x0078, 0x279f, 0x127f, 0x0078,
+	0x27c9, 0x1078, 0x132b, 0x0040, 0x3130, 0xa006, 0x6802, 0x7010,
+	0xa005, 0x00c0, 0x3128, 0x2d00, 0x7012, 0x7016, 0x0078, 0x312e,
+	0x7014, 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, 0xad80, 0x000d,
+	0x007c, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x1078, 0x3f8e, 0x00c0,
+	0x3140, 0x7e28, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0048, 0x3141,
+	0xa066, 0x8cff, 0x007c, 0x7e24, 0x860f, 0xa18c, 0x00ff, 0x1078,
+	0x3f8e, 0x00c0, 0x3151, 0xa6b4, 0x00ff, 0xa682, 0x4000, 0x0048,
+	0x3152, 0xa066, 0x8cff, 0x007c, 0x017e, 0x7110, 0x81ff, 0x0040,
+	0x315f, 0x2168, 0x6904, 0x1078, 0x1344, 0x0078, 0x3156, 0x7112,
+	0x7116, 0x017f, 0x007c, 0x2031, 0x0001, 0x0078, 0x3169, 0x2031,
+	0x0000, 0x2061, 0x88d1, 0x6606, 0x6112, 0x600e, 0x6226, 0x632a,
+	0x642e, 0x6532, 0x2c10, 0x1078, 0x137b, 0x7007, 0x0002, 0x701b,
+	0x279f, 0x007c, 0x0f7e, 0x127e, 0x2091, 0x8000, 0x2079, 0x0000,
+	0x2001, 0x888f, 0x2004, 0xa005, 0x00c0, 0x3195, 0x0068, 0x3195,
+	0x7818, 0xd084, 0x00c0, 0x3195, 0x7a22, 0x7b26, 0x7c2a, 0x781b,
+	0x0001, 0x2091, 0x4080, 0x0078, 0x31ba, 0x017e, 0x0c7e, 0x0e7e,
+	0x2071, 0x8881, 0x7138, 0xa182, 0x0008, 0x0048, 0x31a3, 0x7030,
+	0x2060, 0x0078, 0x31b4, 0x7030, 0xa0e0, 0x0008, 0xac82, 0x88d1,
+	0x0048, 0x31ac, 0x2061, 0x8891, 0x2c00, 0x7032, 0x81ff, 0x00c0,
+	0x31b2, 0x7036, 0x8108, 0x713a, 0x2262, 0x6306, 0x640a, 0x0e7f,
+	0x0c7f, 0x017f, 0x127f, 0x0f7f, 0x007c, 0x0e7e, 0x2071, 0x8881,
+	0x7038, 0xa005, 0x0040, 0x31f6, 0x127e, 0x2091, 0x8000, 0x0068,
+	0x31f5, 0x0f7e, 0x2079, 0x0000, 0x7818, 0xd084, 0x00c0, 0x31f4,
+	0x0c7e, 0x7034, 0x2060, 0x2c04, 0x7822, 0x6004, 0x7826, 0x6008,
+	0x782a, 0x781b, 0x0001, 0x2091, 0x4080, 0x7038, 0x8001, 0x703a,
+	0xa005, 0x00c0, 0x31ea, 0x7033, 0x8891, 0x7037, 0x8891, 0x0c7f,
+	0x0078, 0x31f4, 0xac80, 0x0008, 0xa0fa, 0x88d1, 0x0048, 0x31f2,
+	0x2001, 0x8891, 0x7036, 0x0c7f, 0x0f7f, 0x127f, 0x0e7f, 0x007c,
+	0x027e, 0x2001, 0x8852, 0x2004, 0xd0c4, 0x0040, 0x3203, 0x2011,
+	0x8014, 0x1078, 0x317a, 0x027f, 0x007c, 0x81ff, 0x00c0, 0x27c9,
+	0x127e, 0x2091, 0x8000, 0x6030, 0xc08d, 0xc0ac, 0x6032, 0x1078,
+	0x3c73, 0x127f, 0x0078, 0x279f, 0x7824, 0x2008, 0xa18c, 0xfffd,
+	0x00c0, 0x321f, 0x61cc, 0xa10d, 0x61ce, 0x0078, 0x279f, 0x0078,
+	0x27cd, 0x81ff, 0x00c0, 0x27c9, 0x6000, 0xa086, 0x0003, 0x00c0,
+	0x27c9, 0x2001, 0x8852, 0x2004, 0xd0a4, 0x00c0, 0x27c9, 0x1078,
+	0x3143, 0x0040, 0x27cd, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006,
+	0x00c0, 0x323e, 0x7828, 0xa005, 0x0040, 0x279f, 0x0c7e, 0x1078,
+	0x3119, 0x0c7f, 0x0040, 0x27c9, 0x6837, 0x0000, 0x6833, 0x0000,
+	0x6838, 0xc0fd, 0x683a, 0x1078, 0x79ed, 0x0040, 0x27c9, 0x7007,
+	0x0003, 0x701b, 0x3254, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040,
+	0x27c9, 0x0078, 0x279f, 0x2001, 0x8800, 0x2004, 0xa086, 0x0003,
+	0x00c0, 0x27c9, 0x7f24, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078,
+	0x3119, 0x0040, 0x27c9, 0x2009, 0x0000, 0x2031, 0x0000, 0x7023,
+	0x0000, 0x702f, 0x0000, 0xad80, 0x0005, 0x7026, 0x20a0, 0x1078,
+	0x3f8e, 0x00c0, 0x32ad, 0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006,
+	0x0040, 0x3288, 0xa0c4, 0xff00, 0xa8c6, 0x0600, 0x00c0, 0x32ad,
+	0x2001, 0x8852, 0x2004, 0xd0ac, 0x00c0, 0x3292, 0x1078, 0x4233,
+	0x0040, 0x32ad, 0xd784, 0x0040, 0x32a0, 0xac80, 0x0006, 0x2098,
+	0x3400, 0x20a9, 0x0004, 0x53a3, 0x1078, 0x2fa3, 0x0078, 0x32a9,
+	0xac80, 0x000a, 0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3, 0x1078,
+	0x2fa3, 0x21a2, 0x94a0, 0xa6b0, 0x0005, 0x8108, 0xd78c, 0x0040,
+	0x32b7, 0xa186, 0x0100, 0x0040, 0x32c1, 0x0078, 0x32bb, 0xa186,
+	0x007e, 0x0040, 0x32c1, 0xa686, 0x0028, 0x0040, 0x32ca, 0x0078,
+	0x3277, 0x86ff, 0x00c0, 0x32c8, 0x7120, 0x810b, 0x0078, 0x279f,
+	0x702f, 0x0001, 0x711e, 0x7020, 0xa600, 0x7022, 0x772a, 0x2061,
+	0x88d1, 0x6007, 0x0000, 0x6612, 0x7024, 0x600e, 0x6226, 0x632a,
+	0x642e, 0x6532, 0x2c10, 0x1078, 0x137b, 0x7007, 0x0002, 0x701b,
+	0x32e2, 0x007c, 0x702c, 0xa005, 0x00c0, 0x32f4, 0x711c, 0x7024,
+	0x20a0, 0x7728, 0x2031, 0x0000, 0x2061, 0x88d1, 0x6224, 0x6328,
+	0x642c, 0x6530, 0x0078, 0x3277, 0x7120, 0x810b, 0x0078, 0x279f,
+	0x2029, 0x007e, 0x7924, 0x7a28, 0x7b2c, 0x7c38, 0xa184, 0xff00,
+	0x8007, 0xa0e2, 0x0020, 0x0048, 0x27cd, 0xa502, 0x0048, 0x27cd,
+	0xa184, 0x00ff, 0xa0e2, 0x0020, 0x0048, 0x27cd, 0xa502, 0x0048,
+	0x27cd, 0xa284, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0048, 0x27cd,
+	0xa502, 0x0048, 0x27cd, 0xa284, 0x00ff, 0xa0e2, 0x0020, 0x0048,
+	0x27cd, 0xa502, 0x0048, 0x27cd, 0xa384, 0xff00, 0x8007, 0xa0e2,
+	0x0020, 0x0048, 0x27cd, 0xa502, 0x0048, 0x27cd, 0xa384, 0x00ff,
+	0xa0e2, 0x0020, 0x0048, 0x27cd, 0xa502, 0x0048, 0x27cd, 0xa484,
+	0xff00, 0x8007, 0xa0e2, 0x0020, 0x0048, 0x27cd, 0xa502, 0x0048,
+	0x27cd, 0xa484, 0x00ff, 0xa0e2, 0x0020, 0x0048, 0x27cd, 0xa502,
+	0x0048, 0x27cd, 0x2061, 0x8a9c, 0x6102, 0x6206, 0x630a, 0x640e,
+	0x0078, 0x279f, 0x007e, 0x2001, 0x8852, 0x2004, 0xd0cc, 0x007f,
+	0x007c, 0x007e, 0x2001, 0x8871, 0x2004, 0xd0bc, 0x007f, 0x007c,
+	0x6160, 0x7a24, 0x6300, 0x82ff, 0x00c0, 0x3369, 0x7926, 0x0078,
+	0x279f, 0x83ff, 0x00c0, 0x27cd, 0x2001, 0xfff0, 0xa200, 0x00c8,
+	0x27cd, 0x2019, 0xffff, 0x6064, 0xa302, 0xa200, 0x0048, 0x27cd,
+	0x7926, 0x6262, 0x0078, 0x279f, 0x2001, 0x8800, 0x2004, 0xa086,
+	0x0003, 0x00c0, 0x27c9, 0x7c28, 0x7d24, 0x7e38, 0x7f2c, 0x1078,
+	0x3119, 0x0040, 0x27c9, 0x2009, 0x0000, 0x2019, 0x0000, 0x7023,
+	0x0000, 0x702f, 0x0000, 0xad80, 0x0003, 0x7026, 0x20a0, 0xa1e0,
+	0x8934, 0x2c64, 0x8cff, 0x0040, 0x33b6, 0x6004, 0xa084, 0x00ff,
+	0xa086, 0x0006, 0x0040, 0x33ab, 0x6004, 0xa084, 0xff00, 0xa086,
+	0x0600, 0x00c0, 0x33b6, 0x6014, 0x20a2, 0x94a0, 0x6010, 0x8007,
+	0xa105, 0x8007, 0x20a2, 0x94a0, 0xa398, 0x0002, 0x8108, 0xa182,
+	0x00ff, 0x0040, 0x33c1, 0xa386, 0x002a, 0x0040, 0x33ca, 0x0078,
+	0x3397, 0x83ff, 0x00c0, 0x33c8, 0x7120, 0x810c, 0x0078, 0x279f,
+	0x702f, 0x0001, 0x711e, 0x7020, 0xa300, 0x7022, 0x2061, 0x88d1,
+	0x6007, 0x0000, 0x6312, 0x7024, 0x600e, 0x6426, 0x652a, 0x662e,
+	0x6732, 0x2c10, 0x1078, 0x137b, 0x7007, 0x0002, 0x701b, 0x33e1,
+	0x007c, 0x702c, 0xa005, 0x00c0, 0x33f2, 0x711c, 0x7024, 0x20a0,
+	0x2019, 0x0000, 0x2061, 0x88d1, 0x6424, 0x6528, 0x662c, 0x6730,
+	0x0078, 0x3397, 0x7120, 0x810c, 0x0078, 0x279f, 0x81ff, 0x00c0,
+	0x27c9, 0x60c0, 0xd09c, 0x0040, 0x27c9, 0x1078, 0x3119, 0x0040,
+	0x27c9, 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3163,
+	0x701b, 0x340b, 0x007c, 0x0d7e, 0xade8, 0x000d, 0x6828, 0xa0be,
+	0x7000, 0x0040, 0x341e, 0xa0be, 0x7100, 0x0040, 0x341e, 0xa0be,
+	0x7200, 0x0040, 0x341e, 0x0d7f, 0x0078, 0x27cd, 0x6820, 0x6924,
+	0x1078, 0x2245, 0x00c0, 0x3447, 0x1078, 0x3f53, 0x00c0, 0x3447,
+	0x7122, 0x6612, 0x6516, 0x6e18, 0x0c7e, 0x1078, 0x3119, 0x0040,
+	0x3447, 0x1078, 0x3119, 0x0040, 0x3447, 0x0c7f, 0x0d7f, 0x6837,
+	0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000, 0x1078, 0x7964,
+	0x0040, 0x27c9, 0x7007, 0x0003, 0x701b, 0x344a, 0x007c, 0x0d7f,
+	0x0078, 0x27c9, 0x7120, 0x1078, 0x3f76, 0x6820, 0xa086, 0x8001,
+	0x0040, 0x27c9, 0x2d00, 0x701e, 0x6804, 0xa080, 0x0002, 0x007e,
+	0x20a9, 0x002a, 0x2098, 0x20a0, 0x1078, 0x3cbc, 0x007f, 0xade8,
+	0x000d, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x2061, 0x88d1, 0x6007,
+	0x0000, 0x6e00, 0x6f28, 0xa7c6, 0x7000, 0x00c0, 0x3471, 0x0078,
+	0x3475, 0xa7c6, 0x7100, 0x00c0, 0x347d, 0xa6c2, 0x0004, 0x0048,
+	0x27cd, 0x2009, 0x0004, 0x0078, 0x3167, 0xa7c6, 0x7200, 0x00c0,
+	0x27cd, 0xa6c2, 0x0054, 0x0048, 0x27cd, 0x600e, 0x6013, 0x002a,
+	0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x1078, 0x137b, 0x7007,
+	0x0002, 0x701b, 0x3494, 0x007c, 0x701c, 0x2068, 0x6804, 0xa080,
+	0x0001, 0x2004, 0xa080, 0x0002, 0x007e, 0x20a9, 0x002a, 0x2098,
+	0x20a0, 0x1078, 0x3cbc, 0x007f, 0x2009, 0x002a, 0x2061, 0x88d1,
+	0x6224, 0x6328, 0x642c, 0x6530, 0x0078, 0x3167, 0x81ff, 0x00c0,
+	0x27c9, 0x1078, 0x3131, 0x0040, 0x27cd, 0x1078, 0x4017, 0x0040,
+	0x27c9, 0x1078, 0x4180, 0x0078, 0x279f, 0x7824, 0xd084, 0x0040,
+	0x2d64, 0x1078, 0x3143, 0x0040, 0x27cd, 0x0c7e, 0x1078, 0x3119,
+	0x0c7f, 0x00c0, 0x34cf, 0x2009, 0x0002, 0x0078, 0x27c9, 0x6004,
+	0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x34f8, 0x2001, 0x8852,
+	0x2004, 0xd0b4, 0x0040, 0x2d99, 0x6000, 0xd08c, 0x00c0, 0x2d99,
+	0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x1078, 0x7980, 0x00c0,
+	0x34ed, 0x2009, 0x0003, 0x0078, 0x27c9, 0x7007, 0x0003, 0x701b,
+	0x34f2, 0x007c, 0x1078, 0x3143, 0x0040, 0x27cd, 0x0078, 0x2d99,
+	0x2009, 0x882d, 0x210c, 0x81ff, 0x0040, 0x3502, 0x2009, 0x0001,
+	0x0078, 0x27c9, 0x2001, 0x8800, 0x2004, 0xa086, 0x0003, 0x0040,
+	0x350d, 0x2009, 0x0007, 0x0078, 0x27c9, 0x2001, 0x8852, 0x2004,
+	0xd0ac, 0x0040, 0x3517, 0x2009, 0x0008, 0x0078, 0x27c9, 0x609c,
+	0xd0a4, 0x00c0, 0x351e, 0xd0ac, 0x00c0, 0x2d99, 0x6837, 0x0000,
+	0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x1078, 0x79ed, 0x00c0,
+	0x352d, 0x2009, 0x0003, 0x0078, 0x27c9, 0x7007, 0x0003, 0x701b,
+	0x3532, 0x007c, 0x6830, 0xa086, 0x0100, 0x00c0, 0x353b, 0x2009,
+	0x0004, 0x0078, 0x27c9, 0x1078, 0x3143, 0x0040, 0x27cd, 0x0078,
+	0x34d6, 0x127e, 0x0c7e, 0x0e7e, 0x2061, 0x0100, 0x2071, 0x8800,
+	0x6044, 0xd0a4, 0x00c0, 0x356a, 0xd084, 0x0040, 0x3553, 0x1078,
+	0x36c6, 0x0078, 0x3566, 0xd08c, 0x0040, 0x355a, 0x1078, 0x35dd,
+	0x0078, 0x3566, 0xd094, 0x0040, 0x3561, 0x1078, 0x35b1, 0x0078,
+	0x3566, 0xd09c, 0x0040, 0x3566, 0x1078, 0x3574, 0x0e7f, 0x0c7f,
+	0x127f, 0x007c, 0x017e, 0x6128, 0xd19c, 0x00c0, 0x3571, 0xc19d,
+	0x612a, 0x017f, 0x0078, 0x3566, 0x624c, 0xa286, 0xf0f0, 0x00c0,
+	0x3585, 0x6048, 0xa086, 0xf0f0, 0x0040, 0x3585, 0x624a, 0x6043,
+	0x0090, 0x6043, 0x0010, 0x0078, 0x35b0, 0xa294, 0xff00, 0xa296,
+	0xf700, 0x0040, 0x3596, 0x6240, 0xa294, 0x0010, 0x0040, 0x3596,
+	0x2009, 0x00f7, 0x1078, 0x3cdc, 0x0078, 0x35b0, 0x6043, 0x0040,
+	0x6043, 0x0000, 0x7073, 0x0000, 0x708b, 0x0001, 0x70ab, 0x0000,
+	0x70c3, 0x0000, 0x2009, 0x8ec0, 0x200b, 0x0000, 0x7083, 0x0000,
+	0x7077, 0x000f, 0x2009, 0x000f, 0x2011, 0x3c2e, 0x1078, 0x5181,
+	0x007c, 0x157e, 0x7074, 0xa005, 0x00c0, 0x35db, 0x2011, 0x3c2e,
+	0x1078, 0x50f2, 0x6040, 0xa094, 0x0010, 0xa285, 0x0020, 0x6042,
+	0x20a9, 0x00c8, 0x6044, 0xd08c, 0x00c0, 0x35d4, 0x00f0, 0x35c2,
+	0x6242, 0x7087, 0x0000, 0x6040, 0xa094, 0x0010, 0xa285, 0x0080,
+	0x6042, 0x6242, 0x0078, 0x35db, 0x6242, 0x7087, 0x0000, 0x707b,
+	0x0000, 0x0078, 0x35db, 0x157f, 0x007c, 0x7078, 0xa08a, 0x0003,
+	0x00c8, 0x35e6, 0x1079, 0x35e9, 0x0078, 0x35e8, 0x1078, 0x12d2,
+	0x007c, 0x35ec, 0x363b, 0x36c5, 0x0f7e, 0x707b, 0x0001, 0x20e1,
+	0xa000, 0x20e1, 0x8700, 0x1078, 0x1f57, 0x20e1, 0x9080, 0x20e1,
+	0x4000, 0x2079, 0x8d00, 0x207b, 0x2200, 0x7807, 0x00ef, 0x780b,
+	0x0000, 0x780f, 0x00ef, 0x7813, 0x0138, 0x7817, 0x0000, 0x781b,
+	0x0000, 0x781f, 0x0000, 0x7823, 0xffff, 0x7827, 0xffff, 0x782b,
+	0x0000, 0x782f, 0x0000, 0x2079, 0x8d0c, 0x207b, 0x1101, 0x7807,
+	0x0000, 0x2099, 0x8805, 0x20a1, 0x8d0e, 0x20a9, 0x0004, 0x53a3,
+	0x2079, 0x8d12, 0x207b, 0x0000, 0x7807, 0x0000, 0x2099, 0x8d00,
+	0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x60c3, 0x000c, 0x600f,
+	0x0000, 0x1078, 0x3c5a, 0x0f7f, 0x707f, 0x0000, 0x6043, 0x0008,
+	0x6043, 0x0000, 0x007c, 0x0d7e, 0x707c, 0x707f, 0x0000, 0xa025,
+	0x0040, 0x36af, 0x6020, 0xd0b4, 0x00c0, 0x36ad, 0x7188, 0x81ff,
+	0x0040, 0x3696, 0xa486, 0x000c, 0x00c0, 0x36a1, 0xa480, 0x0018,
+	0x8004, 0x20a8, 0x2011, 0x8d80, 0x2019, 0x8d00, 0x220c, 0x2304,
+	0xa106, 0x00c0, 0x366d, 0x8210, 0x8318, 0x00f0, 0x3656, 0x6043,
+	0x0004, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006, 0x707b,
+	0x0002, 0x7087, 0x0002, 0x0078, 0x36ad, 0x2069, 0x8d80, 0x6930,
+	0xa18e, 0x1101, 0x00c0, 0x36a1, 0x6834, 0xa005, 0x00c0, 0x36a1,
+	0x6900, 0xa18c, 0x00ff, 0x00c0, 0x3681, 0x6804, 0xa005, 0x0040,
+	0x3696, 0x2011, 0x8d8e, 0x2019, 0x8805, 0x20a9, 0x0004, 0x220c,
+	0x2304, 0xa102, 0x0048, 0x3694, 0x00c0, 0x36a1, 0x8210, 0x8318,
+	0x00f0, 0x3687, 0x0078, 0x36a1, 0x708b, 0x0000, 0x20e1, 0x9080,
+	0x20e1, 0x4000, 0x2099, 0x8d80, 0x20a1, 0x020b, 0x20a9, 0x0014,
+	0x53a6, 0x6043, 0x0008, 0x6043, 0x0000, 0x6020, 0xd0b4, 0x00c0,
+	0x36ad, 0x60c3, 0x000c, 0x1078, 0x3c5a, 0x0d7f, 0x007c, 0x6020,
+	0xd0b4, 0x00c0, 0x36ad, 0x60c3, 0x000c, 0x2011, 0x8aac, 0x2013,
+	0x0000, 0x707f, 0x0000, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7,
+	0x9575, 0x1078, 0x6229, 0x0078, 0x36ad, 0x007c, 0x7084, 0xa08a,
+	0x001d, 0x00c8, 0x36cf, 0x1079, 0x36d2, 0x0078, 0x36d1, 0x1078,
+	0x12d2, 0x007c, 0x36fc, 0x370b, 0x373c, 0x3751, 0x3781, 0x37ad,
+	0x37dd, 0x3813, 0x3843, 0x386b, 0x38b4, 0x38de, 0x3902, 0x3918,
+	0x3940, 0x3953, 0x395c, 0x3988, 0x39b6, 0x39e2, 0x3a10, 0x3a46,
+	0x3a8f, 0x3abe, 0x3ae0, 0x3b22, 0x3b48, 0x3b61, 0x3b62, 0x0c7e,
+	0x2061, 0x8800, 0x6003, 0x0007, 0x2061, 0x0100, 0x6004, 0xa084,
+	0xfff9, 0x6006, 0x0c7f, 0x007c, 0x608b, 0xbc94, 0x608f, 0xf0f0,
+	0x6043, 0x0002, 0x7087, 0x0001, 0x2009, 0x07d0, 0x2011, 0x3c35,
+	0x1078, 0x50e5, 0x007c, 0x0f7e, 0x707c, 0xa086, 0x0014, 0x00c0,
+	0x373a, 0x6043, 0x0000, 0x6020, 0xd0b4, 0x00c0, 0x373a, 0x2079,
+	0x8d80, 0x7a30, 0xa296, 0x1102, 0x00c0, 0x3738, 0x7834, 0xa005,
+	0x00c0, 0x3738, 0x7a38, 0xd2fc, 0x0040, 0x372e, 0x70a8, 0xa005,
+	0x00c0, 0x372e, 0x1078, 0x3cf3, 0x70ab, 0x0001, 0x2011, 0x3c35,
+	0x1078, 0x50f2, 0x7087, 0x0010, 0x1078, 0x395c, 0x0078, 0x373a,
+	0x707f, 0x0000, 0x0f7f, 0x007c, 0x7087, 0x0003, 0x6043, 0x0004,
+	0x1078, 0x3cc4, 0x20a3, 0x1102, 0x20a3, 0x0000, 0x20a9, 0x000a,
+	0x20a3, 0x0000, 0x00f0, 0x3748, 0x60c3, 0x0014, 0x1078, 0x3c5a,
+	0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040, 0x377f, 0x2011, 0x3c35,
+	0x1078, 0x50f2, 0xa086, 0x0014, 0x00c0, 0x377b, 0x2079, 0x8d80,
+	0x7a30, 0xa296, 0x1102, 0x00c0, 0x377b, 0x7834, 0xa005, 0x00c0,
+	0x377b, 0x7a38, 0xd2fc, 0x0040, 0x3775, 0x70a8, 0xa005, 0x00c0,
+	0x3775, 0x1078, 0x3cf3, 0x70ab, 0x0001, 0x7087, 0x0004, 0x1078,
+	0x3781, 0x0078, 0x377f, 0x7087, 0x0002, 0x707f, 0x0000, 0x0f7f,
+	0x007c, 0x7087, 0x0005, 0x1078, 0x3cc4, 0x20a3, 0x1103, 0x20a3,
+	0x0000, 0x3430, 0x2011, 0x8d8e, 0x1078, 0x3d0d, 0x00c0, 0x379f,
+	0x7070, 0xa005, 0x00c0, 0x379f, 0x714c, 0xa186, 0xffff, 0x0040,
+	0x379f, 0x1078, 0x3bf9, 0x0040, 0x379f, 0x1078, 0x3cf3, 0x20a9,
+	0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000,
+	0x60c3, 0x0014, 0x1078, 0x3c5a, 0x007c, 0x0f7e, 0x707c, 0xa005,
+	0x0040, 0x37db, 0x2011, 0x3c35, 0x1078, 0x50f2, 0xa086, 0x0014,
+	0x00c0, 0x37d7, 0x2079, 0x8d80, 0x7a30, 0xa296, 0x1103, 0x00c0,
+	0x37d7, 0x7834, 0xa005, 0x00c0, 0x37d7, 0x7a38, 0xd2fc, 0x0040,
+	0x37d1, 0x70a8, 0xa005, 0x00c0, 0x37d1, 0x1078, 0x3cf3, 0x70ab,
+	0x0001, 0x7087, 0x0006, 0x1078, 0x37dd, 0x0078, 0x37db, 0x7087,
+	0x0002, 0x707f, 0x0000, 0x0f7f, 0x007c, 0x7087, 0x0007, 0x1078,
+	0x3cc4, 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, 0x8d8e,
+	0x1078, 0x3d0d, 0x00c0, 0x3805, 0x7070, 0xa005, 0x00c0, 0x3805,
+	0x7150, 0xa186, 0xffff, 0x0040, 0x3805, 0xa180, 0x25b2, 0x200c,
+	0xa18c, 0xff00, 0x810f, 0x1078, 0x3bf9, 0x0040, 0x3805, 0x1078,
+	0x3359, 0x0040, 0x3805, 0x1078, 0x2262, 0x20a9, 0x0008, 0x2298,
+	0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014,
+	0x1078, 0x3c5a, 0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040, 0x3841,
+	0x2011, 0x3c35, 0x1078, 0x50f2, 0xa086, 0x0014, 0x00c0, 0x383d,
+	0x2079, 0x8d80, 0x7a30, 0xa296, 0x1104, 0x00c0, 0x383d, 0x7834,
+	0xa005, 0x00c0, 0x383d, 0x7a38, 0xd2fc, 0x0040, 0x3837, 0x70a8,
+	0xa005, 0x00c0, 0x3837, 0x1078, 0x3cf3, 0x70ab, 0x0001, 0x7087,
+	0x0008, 0x1078, 0x3843, 0x0078, 0x3841, 0x7087, 0x0002, 0x707f,
+	0x0000, 0x0f7f, 0x007c, 0x7087, 0x0009, 0x1078, 0x3cc4, 0x20a3,
+	0x1105, 0x20a3, 0x0100, 0x3430, 0x1078, 0x3d0d, 0x00c0, 0x385c,
+	0x7070, 0xa005, 0x00c0, 0x385c, 0x1078, 0x3b63, 0x00c0, 0x3866,
+	0xa085, 0x0001, 0x1078, 0x2262, 0x20a9, 0x0008, 0x2099, 0x8d8e,
+	0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014,
+	0x1078, 0x3c5a, 0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040, 0x38b2,
+	0x2011, 0x3c35, 0x1078, 0x50f2, 0xa086, 0x0014, 0x00c0, 0x38ae,
+	0x2079, 0x8d80, 0x7a30, 0xa296, 0x1105, 0x00c0, 0x38ae, 0x7834,
+	0x2011, 0x0100, 0xa21e, 0x00c0, 0x3897, 0x7a38, 0xd2fc, 0x0040,
+	0x3891, 0x70a8, 0xa005, 0x00c0, 0x3891, 0x1078, 0x3cf3, 0x70ab,
+	0x0001, 0x7087, 0x000a, 0x1078, 0x38b4, 0x0078, 0x38b2, 0xa005,
+	0x00c0, 0x38ae, 0x7a38, 0xd2fc, 0x0040, 0x38a6, 0x70a8, 0xa005,
+	0x00c0, 0x38a6, 0x1078, 0x3cf3, 0x70ab, 0x0001, 0x7083, 0x0000,
+	0x7087, 0x000e, 0x1078, 0x3940, 0x0078, 0x38b2, 0x7087, 0x0002,
+	0x707f, 0x0000, 0x0f7f, 0x007c, 0x7087, 0x000b, 0x2011, 0x8d0e,
+	0x22a0, 0x20a9, 0x0040, 0x2019, 0xffff, 0x43a4, 0x20a9, 0x0002,
+	0x2009, 0x0000, 0x41a4, 0x1078, 0x3cc4, 0x20a3, 0x1106, 0x20a3,
+	0x0000, 0x1078, 0x3d0d, 0x0040, 0x38d1, 0x2013, 0x0000, 0x0078,
+	0x38d5, 0x6030, 0xa085, 0x0100, 0x2012, 0x2298, 0x20a9, 0x0042,
+	0x53a6, 0x60c3, 0x0084, 0x1078, 0x3c5a, 0x007c, 0x0f7e, 0x707c,
+	0xa005, 0x0040, 0x3900, 0x2011, 0x3c35, 0x1078, 0x50f2, 0xa086,
+	0x0084, 0x00c0, 0x38fc, 0x2079, 0x8d80, 0x7a30, 0xa296, 0x1106,
+	0x00c0, 0x38fc, 0x7834, 0xa005, 0x00c0, 0x38fc, 0x7087, 0x000c,
+	0x1078, 0x3902, 0x0078, 0x3900, 0x7087, 0x0002, 0x707f, 0x0000,
+	0x0f7f, 0x007c, 0x7087, 0x000d, 0x1078, 0x3cc4, 0x20a3, 0x1107,
+	0x20a3, 0x0000, 0x2099, 0x8d8e, 0x20a9, 0x0040, 0x53a6, 0x20a3,
+	0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, 0x1078, 0x3c5a, 0x007c,
+	0x0f7e, 0x707c, 0xa005, 0x0040, 0x393e, 0x2011, 0x3c35, 0x1078,
+	0x50f2, 0xa086, 0x0084, 0x00c0, 0x393a, 0x2079, 0x8d80, 0x7a30,
+	0xa296, 0x1107, 0x00c0, 0x393a, 0x7834, 0xa005, 0x00c0, 0x393a,
+	0x7083, 0x0001, 0x1078, 0x3cb6, 0x7087, 0x000e, 0x1078, 0x3940,
+	0x0078, 0x393e, 0x7087, 0x0002, 0x707f, 0x0000, 0x0f7f, 0x007c,
+	0x7087, 0x000f, 0x707f, 0x0000, 0x608b, 0xbc85, 0x608f, 0xb5b5,
+	0x6043, 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011, 0x3c35,
+	0x1078, 0x50e5, 0x007c, 0x707c, 0xa005, 0x0040, 0x395b, 0x2011,
+	0x3c35, 0x1078, 0x50f2, 0x007c, 0x7087, 0x0011, 0x7168, 0x81ff,
+	0x0040, 0x3971, 0x2009, 0x0000, 0x706c, 0xa084, 0x00ff, 0x1078,
+	0x2245, 0xa186, 0x0080, 0x0040, 0x3971, 0x2011, 0x8d8e, 0x1078,
+	0x3bf9, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0x8d80, 0x20a1,
+	0x020b, 0x747c, 0xa480, 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8,
+	0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0014, 0x1078, 0x3c5a, 0x007c,
+	0x0f7e, 0x707c, 0xa005, 0x0040, 0x39b4, 0x2011, 0x3c35, 0x1078,
+	0x50f2, 0xa086, 0x0014, 0x00c0, 0x39b2, 0x2079, 0x8d80, 0x7a30,
+	0xa296, 0x1103, 0x00c0, 0x39b2, 0x7834, 0xa005, 0x00c0, 0x39b2,
+	0x7a38, 0xd2fc, 0x0040, 0x39ac, 0x70a8, 0xa005, 0x00c0, 0x39ac,
+	0x1078, 0x3cf3, 0x70ab, 0x0001, 0x7087, 0x0012, 0x1078, 0x39b6,
+	0x0078, 0x39b4, 0x707f, 0x0000, 0x0f7f, 0x007c, 0x7087, 0x0013,
+	0x1078, 0x3cd0, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011,
+	0x8d8e, 0x1078, 0x3d0d, 0x00c0, 0x39d4, 0x7070, 0xa005, 0x00c0,
+	0x39d4, 0x714c, 0xa186, 0xffff, 0x0040, 0x39d4, 0x1078, 0x3bf9,
+	0x0040, 0x39d4, 0x1078, 0x3cf3, 0x20a9, 0x0008, 0x2298, 0x26a0,
 	0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078,
-	0x3578, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x3398, 0x2011,
-	0x3558, 0x1078, 0x4689, 0xa086, 0x0014, 0x00c0, 0x3396, 0x2079,
-	0x7c80, 0x7a30, 0xa296, 0x1105, 0x00c0, 0x3396, 0x7834, 0x2011,
-	0x0100, 0xa21e, 0x00c0, 0x337f, 0x7a38, 0xd2f4, 0x0040, 0x3372,
-	0x70bf, 0x0008, 0xd2fc, 0x0040, 0x337d, 0x70a4, 0xa005, 0x00c0,
-	0x337d, 0x1078, 0x3611, 0x70a7, 0x0001, 0x0078, 0x3390, 0xa005,
-	0x00c0, 0x3396, 0x7a38, 0xd2fc, 0x0040, 0x338e, 0x70a4, 0xa005,
-	0x00c0, 0x338e, 0x1078, 0x3611, 0x70a7, 0x0001, 0x707f, 0x0000,
-	0x7083, 0x0016, 0x1078, 0x339a, 0x0078, 0x3398, 0x707b, 0x0000,
-	0x0f7f, 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0x7c80,
-	0x20a1, 0x020b, 0x20a9, 0x000e, 0x53a6, 0x3430, 0x2011, 0x7c8e,
-	0x7083, 0x0017, 0x0078, 0x33ae, 0x7083, 0x001b, 0x706c, 0xa005,
-	0x00c0, 0x33b8, 0x1078, 0x3486, 0x0040, 0x33c8, 0x0078, 0x33c2,
-	0x20a9, 0x0008, 0x2099, 0x7c8e, 0x26a0, 0x53a6, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x3578, 0x0078, 0x33ca,
-	0x1078, 0x303e, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x33eb,
-	0x2011, 0x3558, 0x1078, 0x4689, 0xa086, 0x0084, 0x00c0, 0x33e9,
-	0x2079, 0x7c80, 0x7a30, 0xa296, 0x1106, 0x00c0, 0x33e9, 0x7834,
-	0xa005, 0x00c0, 0x33e9, 0x7083, 0x0018, 0x1078, 0x33ed, 0x0078,
-	0x33eb, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x0019, 0x1078,
-	0x35ee, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x3430, 0x2099, 0x7c8e,
-	0x2039, 0x7c0e, 0x27a0, 0x20a9, 0x0040, 0x53a3, 0x2728, 0x2514,
-	0x8207, 0xa084, 0x00ff, 0x8000, 0x2018, 0xa294, 0x00ff, 0x8007,
-	0xa205, 0x202a, 0x6030, 0x2310, 0x8214, 0xa2a0, 0x7c0e, 0x2414,
-	0xa38c, 0x0001, 0x0040, 0x3418, 0xa294, 0xff00, 0x0078, 0x341b,
-	0xa294, 0x00ff, 0x8007, 0xa215, 0x2222, 0x2798, 0x26a0, 0x20a9,
-	0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084,
-	0x1078, 0x3578, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x344f,
-	0x2011, 0x3558, 0x1078, 0x4689, 0xa086, 0x0084, 0x00c0, 0x344d,
-	0x2079, 0x7c80, 0x7a30, 0xa296, 0x1107, 0x00c0, 0x344d, 0x7834,
-	0xa005, 0x00c0, 0x344d, 0x707f, 0x0001, 0x1078, 0x35d4, 0x7083,
-	0x001a, 0x1078, 0x3451, 0x0078, 0x344f, 0x707b, 0x0000, 0x0f7f,
-	0x007c, 0x7083, 0x001b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099,
-	0x7c80, 0x20a1, 0x020b, 0x7478, 0xa480, 0x0018, 0xa080, 0x0007,
-	0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0084, 0x1078,
-	0x3578, 0x007c, 0x7078, 0xa005, 0x0040, 0x3476, 0x2011, 0x3558,
-	0x1078, 0x4689, 0x7083, 0x001c, 0x1078, 0x3477, 0x007c, 0x707b,
-	0x0000, 0x608b, 0xbc85, 0x608f, 0xb5b5, 0x6043, 0x0001, 0x2009,
-	0x07d0, 0x2011, 0x3558, 0x1078, 0x467c, 0x007c, 0x087e, 0x097e,
-	0x2029, 0x7752, 0x252c, 0x20a9, 0x0008, 0x2041, 0x7c0e, 0x28a0,
-	0x2099, 0x7c8e, 0x53a3, 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4,
-	0x0040, 0x349c, 0x2011, 0x0000, 0x2800, 0xa200, 0x200c, 0xa1a6,
-	0xffff, 0x00c0, 0x34ae, 0xd5d4, 0x0040, 0x34a9, 0x8210, 0x0078,
-	0x34aa, 0x8211, 0x00f0, 0x349c, 0x0078, 0x3513, 0x82ff, 0x00c0,
-	0x34c0, 0xd5d4, 0x0040, 0x34ba, 0xa1a6, 0x3fff, 0x0040, 0x34a6,
-	0x0078, 0x34be, 0xa1a6, 0x3fff, 0x0040, 0x3513, 0xa18d, 0xc000,
-	0x20a9, 0x0010, 0x2019, 0x0001, 0xd5d4, 0x0040, 0x34c9, 0x2019,
-	0x0010, 0x2120, 0xd5d4, 0x0040, 0x34d0, 0x8423, 0x0078, 0x34d1,
-	0x8424, 0x00c8, 0x34de, 0xd5d4, 0x0040, 0x34d9, 0x8319, 0x0078,
-	0x34da, 0x8318, 0x00f0, 0x34ca, 0x0078, 0x3513, 0x23a8, 0x2021,
-	0x0001, 0x8426, 0x8425, 0x00f0, 0x34e2, 0x2328, 0x8529, 0xa2be,
-	0x0007, 0x0040, 0x34f6, 0x007e, 0x2039, 0x0007, 0x2200, 0xa73a,
-	0x007f, 0x27a8, 0xa5a8, 0x0010, 0x00f0, 0x34f2, 0x754e, 0xa5c8,
-	0x2329, 0x292c, 0xa5ac, 0x00ff, 0x6532, 0x60e7, 0x0000, 0x65ea,
-	0x2018, 0x2304, 0xa405, 0x201a, 0x706f, 0x0001, 0x26a0, 0x2898,
-	0x20a9, 0x0008, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0xa085,
-	0x0001, 0x0078, 0x3519, 0xa006, 0x0078, 0x3519, 0xa006, 0x1078,
-	0x12cd, 0x097f, 0x087f, 0x007c, 0x2118, 0x2021, 0x0000, 0x2001,
-	0x0007, 0xa39a, 0x0010, 0x0048, 0x3529, 0x8420, 0x8001, 0x0078,
-	0x3521, 0x2118, 0x84ff, 0x0040, 0x3532, 0xa39a, 0x0010, 0x8421,
-	0x00c0, 0x352d, 0x2021, 0x0001, 0x83ff, 0x0040, 0x353b, 0x8423,
-	0x8319, 0x00c0, 0x3537, 0xa238, 0x2704, 0xa42c, 0x00c0, 0x3550,
-	0xa405, 0x203a, 0x714e, 0xa1a0, 0x2329, 0x242c, 0xa5ac, 0x00ff,
-	0x6532, 0x60e7, 0x0000, 0x65ea, 0x706f, 0x0001, 0xa084, 0x0000,
-	0x007c, 0x0e7e, 0x2071, 0x7700, 0x7073, 0x0000, 0x0e7f, 0x007c,
-	0x0e7e, 0x0f7e, 0x2079, 0x0100, 0x2071, 0x0140, 0x1078, 0x569c,
-	0x7004, 0xa084, 0x4000, 0x0040, 0x3569, 0x7003, 0x1000, 0x7003,
-	0x0000, 0x127e, 0x2091, 0x8000, 0x2071, 0x7720, 0x2073, 0x0000,
-	0x7843, 0x0090, 0x7843, 0x0010, 0x127f, 0x0f7f, 0x0e7f, 0x007c,
-	0x127e, 0x2091, 0x8000, 0x2011, 0x7940, 0x2013, 0x0000, 0x707b,
-	0x0000, 0x127f, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575,
-	0x1078, 0x5693, 0x2009, 0x07d0, 0x2011, 0x3558, 0x1078, 0x4719,
-	0x007c, 0x017e, 0x027e, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x2009,
-	0x00f7, 0x1078, 0x35fa, 0x2061, 0x7949, 0x601b, 0x0000, 0x601f,
-	0x0000, 0x2061, 0x7700, 0x6003, 0x0001, 0x2061, 0x0100, 0x6043,
-	0x0090, 0x6043, 0x0010, 0x2009, 0x001e, 0x2011, 0x35b6, 0x1078,
-	0x467c, 0x127f, 0x0c7f, 0x027f, 0x017f, 0x007c, 0x0e7e, 0x007e,
-	0x127e, 0x2091, 0x8000, 0x2071, 0x0100, 0x1078, 0x569c, 0x2071,
-	0x0140, 0x7004, 0xa084, 0x4000, 0x0040, 0x35ca, 0x7003, 0x1000,
-	0x7003, 0x0000, 0x2001, 0x0001, 0x1078, 0x2025, 0x1078, 0x3591,
-	0x127f, 0x007f, 0x0e7f, 0x007c, 0x20a9, 0x0040, 0x20a1, 0x7dc0,
-	0x2099, 0x7c8e, 0x3304, 0x8007, 0x20a2, 0x9398, 0x94a0, 0x00f0,
-	0x35da, 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0x7c00,
-	0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, 0x007c, 0x20e1, 0x9080,
-	0x20e1, 0x4000, 0x2099, 0x7c80, 0x20a1, 0x020b, 0x20a9, 0x000c,
-	0x53a6, 0x007c, 0x0c7e, 0x007e, 0x2061, 0x0100, 0x810f, 0x2001,
-	0x772c, 0x2004, 0xa005, 0x00c0, 0x360b, 0x6030, 0xa084, 0x00ff,
-	0xa105, 0x0078, 0x360d, 0xa185, 0x00f7, 0x604a, 0x007f, 0x0c7f,
-	0x007c, 0x017e, 0x047e, 0x2001, 0x7752, 0x2004, 0xd0a4, 0x0040,
-	0x3624, 0xa006, 0x2020, 0x2009, 0x002a, 0x1078, 0x7641, 0x2001,
-	0x770c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x1078, 0x2293,
-	0x047f, 0x017f, 0x007c, 0x157e, 0x20a9, 0x00ff, 0x2009, 0x7820,
-	0xa006, 0x200a, 0x8108, 0x00f0, 0x3631, 0x157f, 0x007c, 0x0d7e,
-	0x037e, 0x157e, 0x137e, 0x147e, 0x2069, 0x7751, 0xa006, 0x6002,
-	0x6007, 0x0707, 0x600a, 0x600e, 0x6012, 0xa198, 0x2329, 0x231c,
-	0xa39c, 0x00ff, 0x6316, 0x20a9, 0x0004, 0xac98, 0x0006, 0x23a0,
-	0x40a4, 0x20a9, 0x0004, 0xac98, 0x000a, 0x23a0, 0x40a4, 0x603e,
-	0x6042, 0x604e, 0x6052, 0x6056, 0x605a, 0x605e, 0x6062, 0x6066,
-	0x606a, 0x606e, 0x6072, 0x6076, 0x607a, 0x607e, 0x6082, 0x6086,
-	0x608a, 0x608e, 0x6092, 0x6096, 0x609a, 0x609e, 0x61a2, 0x0d7e,
-	0x60a4, 0xa06d, 0x0040, 0x3676, 0x1078, 0x1340, 0x60a7, 0x0000,
-	0x60a8, 0xa06d, 0x0040, 0x367e, 0x1078, 0x1340, 0x60ab, 0x0000,
-	0x0d7f, 0xa006, 0x604a, 0x6810, 0x603a, 0x680c, 0x6046, 0x6814,
-	0xa084, 0x00ff, 0x6042, 0x147f, 0x137f, 0x157f, 0x037f, 0x0d7f,
-	0x007c, 0x127e, 0x2091, 0x8000, 0x6944, 0x6e48, 0xa684, 0x3fff,
-	0xa082, 0x4000, 0x00c8, 0x3737, 0xa18c, 0xff00, 0x810f, 0xa182,
-	0x00ff, 0x00c8, 0x373d, 0x2001, 0x770c, 0x2004, 0xa084, 0x0003,
-	0x00c0, 0x3720, 0xa188, 0x7820, 0x2104, 0xa065, 0x0040, 0x370e,
-	0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x00c0, 0x3714, 0x60a4,
-	0xa00d, 0x0040, 0x36bf, 0x1078, 0x3a5c, 0x0040, 0x3708, 0x60a8,
-	0xa00d, 0x0040, 0x36d9, 0x1078, 0x3aac, 0x00c0, 0x36d9, 0x694c,
-	0xd1fc, 0x00c0, 0x36cf, 0x1078, 0x37d1, 0x0078, 0x3703, 0x1078,
-	0x37a2, 0x694c, 0xd1ec, 0x00c0, 0x3703, 0x1078, 0x3931, 0x0078,
-	0x3703, 0x694c, 0xa184, 0xa000, 0x0040, 0x36f3, 0xd1ec, 0x0040,
-	0x36ec, 0xd1fc, 0x0040, 0x36e8, 0x1078, 0x3942, 0x0078, 0x36ef,
-	0x1078, 0x3942, 0x0078, 0x36f3, 0xd1fc, 0x0040, 0x36f3, 0x1078,
-	0x37a2, 0x0078, 0x3703, 0x6050, 0xa00d, 0x0040, 0x36fe, 0x2d00,
-	0x200a, 0x6803, 0x0000, 0x6052, 0x0078, 0x3703, 0x2d00, 0x6052,
-	0x604e, 0x6803, 0x0000, 0x1078, 0x4960, 0xa006, 0x127f, 0x007c,
-	0x2001, 0x0005, 0x2009, 0x0000, 0x0078, 0x3741, 0x2001, 0x0028,
-	0x2009, 0x0000, 0x0078, 0x3741, 0xa082, 0x0006, 0x00c8, 0x3720,
-	0x60a0, 0xd0bc, 0x0040, 0x36b7, 0x2001, 0x0028, 0x0078, 0x3733,
-	0x2009, 0x770c, 0x210c, 0xd18c, 0x0040, 0x372a, 0x2001, 0x0004,
-	0x0078, 0x3733, 0xd184, 0x0040, 0x3731, 0x2001, 0x0004, 0x0078,
-	0x3733, 0x2001, 0x0029, 0x2009, 0x0000, 0x0078, 0x3741, 0x2001,
-	0x0029, 0x2009, 0x0000, 0x0078, 0x3741, 0x2001, 0x0029, 0x2009,
-	0x0000, 0xa005, 0x127f, 0x007c, 0x6944, 0x6e48, 0xa684, 0x3fff,
-	0xa082, 0x4000, 0x00c8, 0x3787, 0xa18c, 0xff00, 0x810f, 0xa182,
-	0x00ff, 0x00c8, 0x3777, 0xa188, 0x7820, 0x2104, 0xa065, 0x0040,
-	0x3777, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x00c0, 0x377d,
-	0x684c, 0xd0ec, 0x0040, 0x376a, 0x1078, 0x3942, 0x1078, 0x37a2,
-	0x0078, 0x3772, 0x1078, 0x37a2, 0x684c, 0xd0fc, 0x0040, 0x3772,
-	0x1078, 0x3931, 0x1078, 0x398a, 0xa006, 0x0078, 0x378b, 0x2001,
-	0x0028, 0x2009, 0x0000, 0x0078, 0x378b, 0xa082, 0x0006, 0x0048,
-	0x3760, 0x2001, 0x0029, 0x2009, 0x0000, 0x0078, 0x378b, 0x2001,
-	0x0029, 0x2009, 0x0000, 0xa005, 0x007c, 0x127e, 0x2091, 0x8000,
-	0x6050, 0xa00d, 0x0040, 0x379b, 0x2d00, 0x200a, 0x6803, 0x0000,
-	0x6052, 0x127f, 0x007c, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000,
-	0x0078, 0x3799, 0x127e, 0x2091, 0x8000, 0x604c, 0xa005, 0x0040,
-	0x37ae, 0x6802, 0x2d00, 0x604e, 0x127f, 0x007c, 0x2d00, 0x6052,
-	0x604e, 0x6803, 0x0000, 0x0078, 0x37ac, 0x127e, 0x2091, 0x8000,
-	0x604c, 0xa06d, 0x0040, 0x37c3, 0x6800, 0xa005, 0x00c0, 0x37c1,
-	0x6052, 0x604e, 0xad05, 0x127f, 0x007c, 0x604c, 0xa06d, 0x0040,
-	0x37d0, 0x6800, 0xa005, 0x00c0, 0x37ce, 0x6052, 0x604e, 0xad05,
-	0x007c, 0x6803, 0x0000, 0x6084, 0xa00d, 0x0040, 0x37db, 0x2d00,
-	0x200a, 0x6086, 0x007c, 0x2d00, 0x6086, 0x6082, 0x0078, 0x37da,
-	0x127e, 0x0c7e, 0x027e, 0x2091, 0x8000, 0x6218, 0x2260, 0x6200,
-	0xa005, 0x0040, 0x37ee, 0xc285, 0x0078, 0x37ef, 0xc284, 0x6202,
-	0x027f, 0x0c7f, 0x127f, 0x007c, 0x127e, 0x0c7e, 0x2091, 0x8000,
-	0x6218, 0x2260, 0x6204, 0xa294, 0xff00, 0xa215, 0x6206, 0x0c7f,
-	0x127f, 0x007c, 0x127e, 0x0c7e, 0x2091, 0x8000, 0x6218, 0x2260,
-	0x6204, 0xa294, 0x00ff, 0x8007, 0xa215, 0x6206, 0x0c7f, 0x127f,
-	0x007c, 0x027e, 0xa182, 0x00ff, 0x0048, 0x381a, 0xa085, 0x0001,
-	0x0078, 0x3832, 0xa190, 0x7820, 0x2204, 0xa065, 0x00c0, 0x3831,
-	0x017e, 0x0d7e, 0x1078, 0x130c, 0x2d60, 0x0d7f, 0x017f, 0x0040,
-	0x3816, 0x2c00, 0x2012, 0x60a7, 0x0000, 0x60ab, 0x0000, 0x1078,
-	0x3637, 0xa006, 0x027f, 0x007c, 0x027e, 0xa182, 0x00ff, 0x0048,
-	0x383d, 0xa085, 0x0001, 0x0078, 0x384a, 0x0d7e, 0xa190, 0x7820,
-	0x2204, 0xa06d, 0x0040, 0x3848, 0x2013, 0x0000, 0x1078, 0x1340,
-	0x0d7f, 0xa006, 0x027f, 0x007c, 0x017e, 0xa182, 0x00ff, 0x0048,
-	0x3855, 0xa085, 0x0001, 0x0078, 0x385c, 0xa188, 0x7820, 0x2104,
-	0xa065, 0x0040, 0x3851, 0xa006, 0x017f, 0x007c, 0x0d7e, 0x157e,
-	0x137e, 0x147e, 0x600b, 0x0000, 0x600f, 0x0000, 0x6000, 0xc08c,
-	0x6002, 0x2069, 0x7c8e, 0x6808, 0x605e, 0x6810, 0x6062, 0x6138,
-	0xa10a, 0x0048, 0x3874, 0x603a, 0x6814, 0x6066, 0x2099, 0x7c96,
-	0xac88, 0x000a, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2099, 0x7c9a,
-	0xac88, 0x0006, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2069, 0x7cae,
-	0x6808, 0x606a, 0x690c, 0x616e, 0x6810, 0x6072, 0x6818, 0x6076,
-	0xa182, 0x0211, 0x00c8, 0x3898, 0x2009, 0x0008, 0x0078, 0x38c2,
-	0xa182, 0x0259, 0x00c8, 0x38a0, 0x2009, 0x0007, 0x0078, 0x38c2,
-	0xa182, 0x02c1, 0x00c8, 0x38a8, 0x2009, 0x0006, 0x0078, 0x38c2,
-	0xa182, 0x0349, 0x00c8, 0x38b0, 0x2009, 0x0005, 0x0078, 0x38c2,
-	0xa182, 0x0421, 0x00c8, 0x38b8, 0x2009, 0x0004, 0x0078, 0x38c2,
-	0xa182, 0x0581, 0x00c8, 0x38c0, 0x2009, 0x0003, 0x0078, 0x38c2,
-	0x2009, 0x0002, 0x6192, 0x147f, 0x137f, 0x157f, 0x0d7f, 0x007c,
-	0x0e7e, 0x2071, 0x7c8d, 0x2e04, 0x6896, 0x2071, 0x7c8e, 0x7004,
-	0x689a, 0x701c, 0x689e, 0x0e7f, 0x007c, 0x0d7e, 0x127e, 0x2091,
-	0x8000, 0x60a4, 0xa06d, 0x0040, 0x38f9, 0x6900, 0x81ff, 0x00c0,
-	0x390d, 0x6a04, 0xa282, 0x0010, 0x00c8, 0x3912, 0xad88, 0x0004,
-	0x20a9, 0x0010, 0x2104, 0xa086, 0xffff, 0x0040, 0x38f4, 0x8108,
-	0x00f0, 0x38ea, 0x1078, 0x12cd, 0x260a, 0x8210, 0x6a06, 0x0078,
-	0x390d, 0x1078, 0x130c, 0x0040, 0x3912, 0x2d00, 0x60a6, 0x6803,
+	0x3c5a, 0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040, 0x3a0e, 0x2011,
+	0x3c35, 0x1078, 0x50f2, 0xa086, 0x0014, 0x00c0, 0x3a0c, 0x2079,
+	0x8d80, 0x7a30, 0xa296, 0x1104, 0x00c0, 0x3a0c, 0x7834, 0xa005,
+	0x00c0, 0x3a0c, 0x7a38, 0xd2fc, 0x0040, 0x3a06, 0x70a8, 0xa005,
+	0x00c0, 0x3a06, 0x1078, 0x3cf3, 0x70ab, 0x0001, 0x7087, 0x0014,
+	0x1078, 0x3a10, 0x0078, 0x3a0e, 0x707f, 0x0000, 0x0f7f, 0x007c,
+	0x7087, 0x0015, 0x1078, 0x3cd0, 0x20a3, 0x1104, 0x20a3, 0x0000,
+	0x3430, 0x2011, 0x8d8e, 0x1078, 0x3d0d, 0x00c0, 0x3a38, 0x7070,
+	0xa005, 0x00c0, 0x3a38, 0x7150, 0xa186, 0xffff, 0x0040, 0x3a38,
+	0xa180, 0x25b2, 0x200c, 0xa18c, 0xff00, 0x810f, 0x1078, 0x3bf9,
+	0x0040, 0x3a38, 0x1078, 0x3359, 0x0040, 0x3a38, 0x1078, 0x2262,
+	0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3,
+	0x0000, 0x60c3, 0x0014, 0x1078, 0x3c5a, 0x007c, 0x0f7e, 0x707c,
+	0xa005, 0x0040, 0x3a8d, 0x2011, 0x3c35, 0x1078, 0x50f2, 0xa086,
+	0x0014, 0x00c0, 0x3a8b, 0x2079, 0x8d80, 0x7a30, 0xa296, 0x1105,
+	0x00c0, 0x3a8b, 0x7834, 0x2011, 0x0100, 0xa21e, 0x00c0, 0x3a6e,
+	0x7a38, 0xd2fc, 0x0040, 0x3a6c, 0x70a8, 0xa005, 0x00c0, 0x3a6c,
+	0x1078, 0x3cf3, 0x70ab, 0x0001, 0x0078, 0x3a7f, 0xa005, 0x00c0,
+	0x3a8b, 0x7a38, 0xd2fc, 0x0040, 0x3a7d, 0x70a8, 0xa005, 0x00c0,
+	0x3a7d, 0x1078, 0x3cf3, 0x70ab, 0x0001, 0x7083, 0x0000, 0x7a38,
+	0xd2f4, 0x0040, 0x3a85, 0x70c3, 0x0008, 0x7087, 0x0016, 0x1078,
+	0x3a8f, 0x0078, 0x3a8d, 0x707f, 0x0000, 0x0f7f, 0x007c, 0x20e1,
+	0x9080, 0x20e1, 0x4000, 0x2099, 0x8d80, 0x20a1, 0x020b, 0x20a9,
+	0x000e, 0x53a6, 0x3430, 0x2011, 0x8d8e, 0x7087, 0x0017, 0x1078,
+	0x3d0d, 0x00c0, 0x3aaf, 0x7070, 0xa005, 0x00c0, 0x3aaf, 0x1078,
+	0x3b63, 0x00c0, 0x3ab9, 0xa085, 0x0001, 0x1078, 0x2262, 0x20a9,
+	0x0008, 0x2099, 0x8d8e, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3,
+	0x0000, 0x60c3, 0x0014, 0x1078, 0x3c5a, 0x007c, 0x0f7e, 0x707c,
+	0xa005, 0x0040, 0x3ade, 0x2011, 0x3c35, 0x1078, 0x50f2, 0xa086,
+	0x0084, 0x00c0, 0x3adc, 0x2079, 0x8d80, 0x7a30, 0xa296, 0x1106,
+	0x00c0, 0x3adc, 0x7834, 0xa005, 0x00c0, 0x3adc, 0x7087, 0x0018,
+	0x1078, 0x3ae0, 0x0078, 0x3ade, 0x707f, 0x0000, 0x0f7f, 0x007c,
+	0x7087, 0x0019, 0x1078, 0x3cd0, 0x20a3, 0x1106, 0x20a3, 0x0000,
+	0x3430, 0x2099, 0x8d8e, 0x2039, 0x8d0e, 0x27a0, 0x20a9, 0x0040,
+	0x53a3, 0x1078, 0x3d0d, 0x00c0, 0x3b14, 0x2728, 0x2514, 0x8207,
+	0xa084, 0x00ff, 0x8000, 0x2018, 0xa294, 0x00ff, 0x8007, 0xa205,
+	0x202a, 0x6030, 0x2310, 0x8214, 0xa2a0, 0x8d0e, 0x2414, 0xa38c,
+	0x0001, 0x0040, 0x3b0f, 0xa294, 0xff00, 0x0078, 0x3b12, 0xa294,
+	0x00ff, 0x8007, 0xa215, 0x2222, 0x2798, 0x26a0, 0x20a9, 0x0040,
+	0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, 0x1078,
+	0x3c5a, 0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040, 0x3b46, 0x2011,
+	0x3c35, 0x1078, 0x50f2, 0xa086, 0x0084, 0x00c0, 0x3b44, 0x2079,
+	0x8d80, 0x7a30, 0xa296, 0x1107, 0x00c0, 0x3b44, 0x7834, 0xa005,
+	0x00c0, 0x3b44, 0x7083, 0x0001, 0x1078, 0x3cb6, 0x7087, 0x001a,
+	0x1078, 0x3b48, 0x0078, 0x3b46, 0x707f, 0x0000, 0x0f7f, 0x007c,
+	0x7087, 0x001b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0x8d80,
+	0x20a1, 0x020b, 0x747c, 0xa480, 0x0018, 0xa080, 0x0007, 0xa084,
+	0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0084, 0x1078, 0x3c5a,
+	0x007c, 0x007c, 0x007c, 0x087e, 0x097e, 0x2029, 0x8852, 0x252c,
+	0x20a9, 0x0008, 0x2041, 0x8d0e, 0x28a0, 0x2099, 0x8d8e, 0x53a3,
+	0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0040, 0x3b79, 0x2011,
+	0x0000, 0x2800, 0xa200, 0x200c, 0xa1a6, 0xffff, 0x00c0, 0x3b8b,
+	0xd5d4, 0x0040, 0x3b86, 0x8210, 0x0078, 0x3b87, 0x8211, 0x00f0,
+	0x3b79, 0x0078, 0x3bf0, 0x82ff, 0x00c0, 0x3b9d, 0xd5d4, 0x0040,
+	0x3b97, 0xa1a6, 0x3fff, 0x0040, 0x3b83, 0x0078, 0x3b9b, 0xa1a6,
+	0x3fff, 0x0040, 0x3bf0, 0xa18d, 0xc000, 0x20a9, 0x0010, 0x2019,
+	0x0001, 0xd5d4, 0x0040, 0x3ba6, 0x2019, 0x0010, 0x2120, 0xd5d4,
+	0x0040, 0x3bad, 0x8423, 0x0078, 0x3bae, 0x8424, 0x00c8, 0x3bbb,
+	0xd5d4, 0x0040, 0x3bb6, 0x8319, 0x0078, 0x3bb7, 0x8318, 0x00f0,
+	0x3ba7, 0x0078, 0x3bf0, 0x23a8, 0x2021, 0x0001, 0x8426, 0x8425,
+	0x00f0, 0x3bbf, 0x2328, 0x8529, 0xa2be, 0x0007, 0x0040, 0x3bd3,
+	0x007e, 0x2039, 0x0007, 0x2200, 0xa73a, 0x007f, 0x27a8, 0xa5a8,
+	0x0010, 0x00f0, 0x3bcf, 0x754e, 0xa5c8, 0x25b2, 0x292c, 0xa5ac,
+	0x00ff, 0x6532, 0x60e7, 0x0000, 0x65ea, 0x2018, 0x2304, 0xa405,
+	0x201a, 0x7073, 0x0001, 0x26a0, 0x2898, 0x20a9, 0x0008, 0x53a6,
+	0x20a3, 0x0000, 0x20a3, 0x0000, 0xa085, 0x0001, 0x0078, 0x3bf6,
+	0xa006, 0x0078, 0x3bf6, 0xa006, 0x1078, 0x12d2, 0x097f, 0x087f,
+	0x007c, 0x2118, 0x2021, 0x0000, 0x2001, 0x0007, 0xa39a, 0x0010,
+	0x0048, 0x3c06, 0x8420, 0x8001, 0x0078, 0x3bfe, 0x2118, 0x84ff,
+	0x0040, 0x3c0f, 0xa39a, 0x0010, 0x8421, 0x00c0, 0x3c0a, 0x2021,
+	0x0001, 0x83ff, 0x0040, 0x3c18, 0x8423, 0x8319, 0x00c0, 0x3c14,
+	0xa238, 0x2704, 0xa42c, 0x00c0, 0x3c2d, 0xa405, 0x203a, 0x714e,
+	0xa1a0, 0x25b2, 0x242c, 0xa5ac, 0x00ff, 0x6532, 0x60e7, 0x0000,
+	0x65ea, 0x7073, 0x0001, 0xa084, 0x0000, 0x007c, 0x0e7e, 0x2071,
+	0x8800, 0x7077, 0x0000, 0x0e7f, 0x007c, 0x0e7e, 0x0f7e, 0x2079,
+	0x0100, 0x2071, 0x0140, 0x1078, 0x6232, 0x7004, 0xa084, 0x4000,
+	0x0040, 0x3c46, 0x7003, 0x1000, 0x7003, 0x0000, 0x127e, 0x2091,
+	0x8000, 0x2071, 0x8821, 0x2073, 0x0000, 0x7840, 0x027e, 0xa094,
+	0x0010, 0xa285, 0x0080, 0x7842, 0x7a42, 0x027f, 0x127f, 0x0f7f,
+	0x0e7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x2011, 0x8aac, 0x2013,
+	0x0000, 0x707f, 0x0000, 0x127f, 0x20e1, 0x9080, 0x60a3, 0x0056,
+	0x60a7, 0x9575, 0x1078, 0x6229, 0x2009, 0x07d0, 0x2011, 0x3c35,
+	0x1078, 0x5181, 0x007c, 0x017e, 0x027e, 0x0c7e, 0x127e, 0x2091,
+	0x8000, 0x2009, 0x00f7, 0x1078, 0x3cdc, 0x2061, 0x8ab5, 0x601b,
+	0x0000, 0x601f, 0x0000, 0x2061, 0x8800, 0x6003, 0x0001, 0x2061,
+	0x0100, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x001e, 0x2011,
+	0x3c98, 0x1078, 0x50e5, 0x127f, 0x0c7f, 0x027f, 0x017f, 0x007c,
+	0x0e7e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0x0100, 0x1078,
+	0x6232, 0x2071, 0x0140, 0x7004, 0xa084, 0x4000, 0x0040, 0x3cac,
+	0x7003, 0x1000, 0x7003, 0x0000, 0x2001, 0x0001, 0x1078, 0x21f3,
+	0x1078, 0x3c73, 0x127f, 0x007f, 0x0e7f, 0x007c, 0x20a9, 0x0040,
+	0x20a1, 0x8ec0, 0x2099, 0x8d8e, 0x3304, 0x8007, 0x20a2, 0x9398,
+	0x94a0, 0x00f0, 0x3cbc, 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000,
+	0x2099, 0x8d00, 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, 0x007c,
+	0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0x8d80, 0x20a1, 0x020b,
+	0x20a9, 0x000c, 0x53a6, 0x007c, 0x0c7e, 0x007e, 0x2061, 0x0100,
+	0x810f, 0x2001, 0x882d, 0x2004, 0xa005, 0x00c0, 0x3ced, 0x6030,
+	0xa084, 0x00ff, 0xa105, 0x0078, 0x3cef, 0xa185, 0x00f7, 0x604a,
+	0x007f, 0x0c7f, 0x007c, 0x017e, 0x047e, 0x2001, 0x8852, 0x2004,
+	0xd0a4, 0x0040, 0x3d06, 0xa006, 0x2020, 0x2009, 0x002a, 0x1078,
+	0x86f5, 0x2001, 0x880c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a,
+	0x1078, 0x249d, 0x047f, 0x017f, 0x007c, 0x007e, 0x2001, 0x880c,
+	0x2004, 0xd09c, 0x0040, 0x3d14, 0x007f, 0x007c, 0x007e, 0x017e,
+	0x127e, 0x2091, 0x8000, 0x2001, 0x0101, 0x200c, 0xa18d, 0x0006,
+	0x2102, 0x127f, 0x017f, 0x007f, 0x007c, 0x157e, 0x20a9, 0x00ff,
+	0x2009, 0x8934, 0xa006, 0x200a, 0x8108, 0x00f0, 0x3d2b, 0x157f,
+	0x007c, 0x0d7e, 0x037e, 0x157e, 0x137e, 0x147e, 0x2069, 0x8851,
+	0xa006, 0x6002, 0x6007, 0x0707, 0x600a, 0x600e, 0x6012, 0xa198,
+	0x25b2, 0x231c, 0xa39c, 0x00ff, 0x6316, 0x20a9, 0x0004, 0xac98,
+	0x0006, 0x23a0, 0x40a4, 0x20a9, 0x0004, 0xac98, 0x000a, 0x23a0,
+	0x40a4, 0x603e, 0x6042, 0x604e, 0x6052, 0x6056, 0x605a, 0x605e,
+	0x6062, 0x6066, 0x606a, 0x606e, 0x6072, 0x6076, 0x607a, 0x607e,
+	0x6082, 0x6086, 0x608a, 0x608e, 0x6092, 0x6096, 0x609a, 0x609e,
+	0x61a2, 0x0d7e, 0x60a4, 0xa06d, 0x0040, 0x3d70, 0x1078, 0x1344,
+	0x60a7, 0x0000, 0x60a8, 0xa06d, 0x0040, 0x3d78, 0x1078, 0x1344,
+	0x60ab, 0x0000, 0x0d7f, 0xa006, 0x604a, 0x6810, 0x603a, 0x680c,
+	0x6046, 0x6814, 0xa084, 0x00ff, 0x6042, 0x147f, 0x137f, 0x157f,
+	0x037f, 0x0d7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x6944, 0x6e48,
+	0xa684, 0x3fff, 0xa082, 0x4000, 0x00c8, 0x3e31, 0xa18c, 0xff00,
+	0x810f, 0xa182, 0x00ff, 0x00c8, 0x3e37, 0x2001, 0x880c, 0x2004,
+	0xa084, 0x0003, 0x00c0, 0x3e1a, 0xa188, 0x8934, 0x2104, 0xa065,
+	0x0040, 0x3e08, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x00c0,
+	0x3e0e, 0x60a4, 0xa00d, 0x0040, 0x3db9, 0x1078, 0x41b1, 0x0040,
+	0x3e02, 0x60a8, 0xa00d, 0x0040, 0x3dd3, 0x1078, 0x4202, 0x00c0,
+	0x3dd3, 0x694c, 0xd1fc, 0x00c0, 0x3dc9, 0x1078, 0x3ee2, 0x0078,
+	0x3dfd, 0x1078, 0x3e9c, 0x694c, 0xd1ec, 0x00c0, 0x3dfd, 0x1078,
+	0x407a, 0x0078, 0x3dfd, 0x694c, 0xa184, 0xa000, 0x0040, 0x3ded,
+	0xd1ec, 0x0040, 0x3de6, 0xd1fc, 0x0040, 0x3de2, 0x1078, 0x408b,
+	0x0078, 0x3de9, 0x1078, 0x408b, 0x0078, 0x3ded, 0xd1fc, 0x0040,
+	0x3ded, 0x1078, 0x3e9c, 0x0078, 0x3dfd, 0x6050, 0xa00d, 0x0040,
+	0x3df8, 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, 0x0078, 0x3dfd,
+	0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x1078, 0x53b8, 0xa006,
+	0x127f, 0x007c, 0x2001, 0x0005, 0x2009, 0x0000, 0x0078, 0x3e3b,
+	0x2001, 0x0028, 0x2009, 0x0000, 0x0078, 0x3e3b, 0xa082, 0x0006,
+	0x00c8, 0x3e1a, 0x60a0, 0xd0bc, 0x0040, 0x3db1, 0x2001, 0x0028,
+	0x0078, 0x3e2d, 0x2009, 0x880c, 0x210c, 0xd18c, 0x0040, 0x3e24,
+	0x2001, 0x0004, 0x0078, 0x3e2d, 0xd184, 0x0040, 0x3e2b, 0x2001,
+	0x0004, 0x0078, 0x3e2d, 0x2001, 0x0029, 0x2009, 0x0000, 0x0078,
+	0x3e3b, 0x2001, 0x0029, 0x2009, 0x0000, 0x0078, 0x3e3b, 0x2001,
+	0x0029, 0x2009, 0x0000, 0xa005, 0x127f, 0x007c, 0x6944, 0x6e48,
+	0xa684, 0x3fff, 0xa082, 0x4000, 0x00c8, 0x3e81, 0xa18c, 0xff00,
+	0x810f, 0xa182, 0x00ff, 0x00c8, 0x3e71, 0xa188, 0x8934, 0x2104,
+	0xa065, 0x0040, 0x3e71, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006,
+	0x00c0, 0x3e77, 0x684c, 0xd0ec, 0x0040, 0x3e64, 0x1078, 0x408b,
+	0x1078, 0x3e9c, 0x0078, 0x3e6c, 0x1078, 0x3e9c, 0x684c, 0xd0fc,
+	0x0040, 0x3e6c, 0x1078, 0x407a, 0x1078, 0x40d3, 0xa006, 0x0078,
+	0x3e85, 0x2001, 0x0028, 0x2009, 0x0000, 0x0078, 0x3e85, 0xa082,
+	0x0006, 0x0048, 0x3e5a, 0x2001, 0x0029, 0x2009, 0x0000, 0x0078,
+	0x3e85, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x007c, 0x127e,
+	0x2091, 0x8000, 0x6050, 0xa00d, 0x0040, 0x3e95, 0x2d00, 0x200a,
+	0x6803, 0x0000, 0x6052, 0x127f, 0x007c, 0x2d00, 0x6052, 0x604e,
+	0x6803, 0x0000, 0x0078, 0x3e93, 0x127e, 0x2091, 0x8000, 0x604c,
+	0xa005, 0x0040, 0x3eb2, 0x0e7e, 0x2071, 0x8aa2, 0x7004, 0xa086,
+	0x0002, 0x0040, 0x3eb9, 0x0e7f, 0x604c, 0x6802, 0x2d00, 0x604e,
+	0x127f, 0x007c, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x0078,
+	0x3eb0, 0x701c, 0xac06, 0x00c0, 0x3eab, 0x604c, 0x2070, 0x7000,
+	0x6802, 0x2d00, 0x7002, 0x0e7f, 0x127f, 0x007c, 0x127e, 0x2091,
+	0x8000, 0x604c, 0xa06d, 0x0040, 0x3ed4, 0x6800, 0xa005, 0x00c0,
+	0x3ed2, 0x6052, 0x604e, 0xad05, 0x127f, 0x007c, 0x604c, 0xa06d,
+	0x0040, 0x3ee1, 0x6800, 0xa005, 0x00c0, 0x3edf, 0x6052, 0x604e,
+	0xad05, 0x007c, 0x6803, 0x0000, 0x6084, 0xa00d, 0x0040, 0x3eec,
+	0x2d00, 0x200a, 0x6086, 0x007c, 0x2d00, 0x6086, 0x6082, 0x0078,
+	0x3eeb, 0x127e, 0x0c7e, 0x027e, 0x2091, 0x8000, 0x6218, 0x2260,
+	0x6200, 0xa005, 0x0040, 0x3eff, 0xc285, 0x0078, 0x3f00, 0xc284,
+	0x6202, 0x027f, 0x0c7f, 0x127f, 0x007c, 0x127e, 0x0c7e, 0x2091,
+	0x8000, 0x6218, 0x2260, 0x6204, 0x007e, 0xa086, 0x0006, 0x00c0,
+	0x3f24, 0x609c, 0xd0ac, 0x0040, 0x3f24, 0x2001, 0x8852, 0x2004,
+	0xd0a4, 0x0040, 0x3f24, 0xa284, 0xff00, 0x8007, 0xa086, 0x0007,
+	0x00c0, 0x3f24, 0x6007, 0x0600, 0x007f, 0xa294, 0xff00, 0xa215,
+	0x6206, 0x0c7f, 0x127f, 0x007c, 0x127e, 0x0c7e, 0x2091, 0x8000,
+	0x6218, 0x2260, 0x6204, 0x007e, 0xa086, 0x0006, 0x00c0, 0x3f4a,
+	0x609c, 0xd0a4, 0x0040, 0x3f4a, 0x2001, 0x8852, 0x2004, 0xd0ac,
+	0x00c0, 0x3f4a, 0xa284, 0x00ff, 0xa086, 0x0007, 0x00c0, 0x3f4a,
+	0x6007, 0x0006, 0x007f, 0xa294, 0x00ff, 0x8007, 0xa215, 0x6206,
+	0x0c7f, 0x127f, 0x007c, 0x027e, 0xa182, 0x00ff, 0x0048, 0x3f5c,
+	0xa085, 0x0001, 0x0078, 0x3f74, 0xa190, 0x8934, 0x2204, 0xa065,
+	0x00c0, 0x3f73, 0x017e, 0x0d7e, 0x1078, 0x1310, 0x2d60, 0x0d7f,
+	0x017f, 0x0040, 0x3f58, 0x2c00, 0x2012, 0x60a7, 0x0000, 0x60ab,
+	0x0000, 0x1078, 0x3d31, 0xa006, 0x027f, 0x007c, 0x027e, 0xa182,
+	0x00ff, 0x0048, 0x3f7f, 0xa085, 0x0001, 0x0078, 0x3f8c, 0x0d7e,
+	0xa190, 0x8934, 0x2204, 0xa06d, 0x0040, 0x3f8a, 0x2013, 0x0000,
+	0x1078, 0x1344, 0x0d7f, 0xa006, 0x027f, 0x007c, 0x017e, 0xa182,
+	0x00ff, 0x0048, 0x3f97, 0xa085, 0x0001, 0x0078, 0x3f9e, 0xa188,
+	0x8934, 0x2104, 0xa065, 0x0040, 0x3f93, 0xa006, 0x017f, 0x007c,
+	0x0d7e, 0x157e, 0x137e, 0x147e, 0x600b, 0x0000, 0x600f, 0x0000,
+	0x6000, 0xc08c, 0x6002, 0x2069, 0x8d8e, 0x6808, 0x605e, 0x6810,
+	0x6062, 0x6138, 0xa10a, 0x0048, 0x3fb6, 0x603a, 0x6814, 0x6066,
+	0x2099, 0x8d96, 0xac88, 0x000a, 0x21a0, 0x20a9, 0x0004, 0x53a3,
+	0x2099, 0x8d9a, 0xac88, 0x0006, 0x21a0, 0x20a9, 0x0004, 0x53a3,
+	0x2069, 0x8dae, 0x6808, 0x606a, 0x690c, 0x616e, 0x6810, 0x6072,
+	0x6818, 0x6076, 0xa182, 0x0211, 0x00c8, 0x3fda, 0x2009, 0x0008,
+	0x0078, 0x4004, 0xa182, 0x0259, 0x00c8, 0x3fe2, 0x2009, 0x0007,
+	0x0078, 0x4004, 0xa182, 0x02c1, 0x00c8, 0x3fea, 0x2009, 0x0006,
+	0x0078, 0x4004, 0xa182, 0x0349, 0x00c8, 0x3ff2, 0x2009, 0x0005,
+	0x0078, 0x4004, 0xa182, 0x0421, 0x00c8, 0x3ffa, 0x2009, 0x0004,
+	0x0078, 0x4004, 0xa182, 0x0581, 0x00c8, 0x4002, 0x2009, 0x0003,
+	0x0078, 0x4004, 0x2009, 0x0002, 0x6192, 0x147f, 0x137f, 0x157f,
+	0x0d7f, 0x007c, 0x0e7e, 0x2071, 0x8d8d, 0x2e04, 0x6896, 0x2071,
+	0x8d8e, 0x7004, 0x689a, 0x701c, 0x689e, 0x0e7f, 0x007c, 0x0d7e,
+	0x127e, 0x2091, 0x8000, 0x60a4, 0xa06d, 0x0040, 0x403b, 0x6900,
+	0x81ff, 0x00c0, 0x404f, 0x6a04, 0xa282, 0x0010, 0x00c8, 0x4054,
+	0xad88, 0x0004, 0x20a9, 0x0010, 0x2104, 0xa086, 0xffff, 0x0040,
+	0x4036, 0x8108, 0x00f0, 0x402c, 0x1078, 0x12d2, 0x260a, 0x8210,
+	0x6a06, 0x0078, 0x404f, 0x1078, 0x132b, 0x0040, 0x4054, 0x2d00,
+	0x60a6, 0x6803, 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b,
+	0xffff, 0x8108, 0x00f0, 0x4047, 0x6807, 0x0001, 0x6e12, 0xa085,
+	0x0001, 0x127f, 0x0d7f, 0x007c, 0xa006, 0x0078, 0x4051, 0x127e,
+	0x2091, 0x8000, 0x0d7e, 0x60a4, 0xa00d, 0x0040, 0x4077, 0x2168,
+	0x6800, 0xa005, 0x00c0, 0x4073, 0x1078, 0x41b1, 0x00c0, 0x4077,
+	0x200b, 0xffff, 0x6804, 0xa08a, 0x0002, 0x0048, 0x4073, 0x8001,
+	0x6806, 0x0078, 0x4077, 0x1078, 0x1344, 0x60a7, 0x0000, 0x0d7f,
+	0x127f, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, 0x4217, 0x0078,
+	0x4083, 0x1078, 0x3e87, 0x1078, 0x4117, 0x00c0, 0x4081, 0x1078,
+	0x40d3, 0x127f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x60a8,
+	0xa06d, 0x0040, 0x40af, 0x6950, 0x81ff, 0x00c0, 0x40c3, 0x6a54,
+	0xa282, 0x0010, 0x00c8, 0x40d0, 0xad88, 0x0018, 0x20a9, 0x0010,
+	0x2104, 0xa086, 0xffff, 0x0040, 0x40aa, 0x8108, 0x00f0, 0x40a0,
+	0x1078, 0x12d2, 0x260a, 0x8210, 0x6a56, 0x0078, 0x40c3, 0x1078,
+	0x132b, 0x0040, 0x40d0, 0x2d00, 0x60aa, 0x6853, 0x0000, 0xad88,
+	0x0018, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, 0x00f0, 0x40bb,
+	0x6857, 0x0001, 0x6e62, 0x0078, 0x40c7, 0x1078, 0x3ee2, 0x1078,
+	0x40dd, 0x00c0, 0x40c5, 0xa085, 0x0001, 0x127f, 0x0d7f, 0x007c,
+	0xa006, 0x0078, 0x40cd, 0x127e, 0x2091, 0x8000, 0x1078, 0x53b8,
+	0x127f, 0x007c, 0xa01e, 0x0078, 0x40df, 0x2019, 0x0001, 0xa00e,
+	0x127e, 0x2091, 0x8000, 0x604c, 0x2068, 0x6000, 0xd0dc, 0x00c0,
+	0x40fd, 0x8dff, 0x0040, 0x4112, 0x83ff, 0x0040, 0x40f5, 0x6848,
+	0xa606, 0x0040, 0x4102, 0x0078, 0x40fd, 0x683c, 0xa406, 0x00c0,
+	0x40fd, 0x6840, 0xa506, 0x0040, 0x4102, 0x2d08, 0x6800, 0x2068,
+	0x0078, 0x40e9, 0x6a00, 0x604c, 0xad06, 0x00c0, 0x410a, 0x624e,
+	0x0078, 0x410d, 0xa180, 0x0000, 0x2202, 0x82ff, 0x00c0, 0x4112,
+	0x6152, 0x8dff, 0x127f, 0x007c, 0xa01e, 0x0078, 0x4119, 0x2019,
+	0x0001, 0xa00e, 0x6080, 0x2068, 0x8dff, 0x0040, 0x4145, 0x83ff,
+	0x0040, 0x4128, 0x6848, 0xa606, 0x0040, 0x4135, 0x0078, 0x4130,
+	0x683c, 0xa406, 0x00c0, 0x4130, 0x6840, 0xa506, 0x0040, 0x4135,
+	0x2d08, 0x6800, 0x2068, 0x0078, 0x411c, 0x6a00, 0x6080, 0xad06,
+	0x00c0, 0x413d, 0x6282, 0x0078, 0x4140, 0xa180, 0x0000, 0x2202,
+	0x82ff, 0x00c0, 0x4145, 0x6186, 0x8dff, 0x007c, 0xa016, 0x1078,
+	0x41aa, 0x00c0, 0x414d, 0x2011, 0x0001, 0x1078, 0x41fb, 0x00c0,
+	0x4153, 0xa295, 0x0002, 0x007c, 0x1078, 0x4233, 0x0040, 0x415c,
+	0x1078, 0x78b9, 0x0078, 0x415e, 0xa085, 0x0001, 0x007c, 0x1078,
+	0x4233, 0x0040, 0x4167, 0x1078, 0x784f, 0x0078, 0x4169, 0xa085,
+	0x0001, 0x007c, 0x1078, 0x4233, 0x0040, 0x4172, 0x1078, 0x7899,
+	0x0078, 0x4174, 0xa085, 0x0001, 0x007c, 0x1078, 0x4233, 0x0040,
+	0x417d, 0x1078, 0x786b, 0x0078, 0x417f, 0xa085, 0x0001, 0x007c,
+	0x1078, 0x4233, 0x0040, 0x4188, 0x1078, 0x78d9, 0x0078, 0x418a,
+	0xa085, 0x0001, 0x007c, 0x127e, 0x007e, 0x0d7e, 0x2091, 0x8000,
+	0x6080, 0xa06d, 0x0040, 0x41a2, 0x6800, 0x007e, 0x6837, 0x0103,
+	0x6b4a, 0x6847, 0x0000, 0x1078, 0x7a46, 0x1078, 0x4376, 0x007f,
+	0x0078, 0x4191, 0x6083, 0x0000, 0x6087, 0x0000, 0x0d7f, 0x007f,
+	0x127f, 0x007c, 0x60a4, 0xa00d, 0x00c0, 0x41b1, 0xa085, 0x0001,
+	0x007c, 0x0e7e, 0x2170, 0x7000, 0xa005, 0x00c0, 0x41c4, 0x20a9,
+	0x0010, 0xae88, 0x0004, 0x2104, 0xa606, 0x0040, 0x41c4, 0x8108,
+	0x00f0, 0x41bb, 0xa085, 0x0001, 0xa006, 0x0e7f, 0x007c, 0x0d7e,
+	0x127e, 0x2091, 0x8000, 0x60a4, 0xa06d, 0x00c0, 0x41d5, 0x1078,
+	0x132b, 0x0040, 0x41e7, 0x2d00, 0x60a6, 0x6803, 0x0001, 0x6807,
 	0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108,
-	0x00f0, 0x3905, 0x6807, 0x0001, 0x6e12, 0xa085, 0x0001, 0x127f,
-	0x0d7f, 0x007c, 0xa006, 0x0078, 0x390f, 0x127e, 0x2091, 0x8000,
-	0x1078, 0x3a55, 0x00c0, 0x392f, 0x200b, 0xffff, 0x0d7e, 0x60a4,
-	0x2068, 0x6804, 0xa08a, 0x0002, 0x0048, 0x392a, 0x8001, 0x6806,
-	0x0078, 0x392e, 0x1078, 0x1340, 0x60a7, 0x0000, 0x0d7f, 0x127f,
-	0x007c, 0x127e, 0x2091, 0x8000, 0x1078, 0x3ac1, 0x0078, 0x393a,
-	0x1078, 0x378d, 0x1078, 0x39ce, 0x00c0, 0x3938, 0x1078, 0x398a,
-	0x127f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x60a8, 0xa06d,
-	0x0040, 0x3966, 0x6950, 0x81ff, 0x00c0, 0x397a, 0x6a54, 0xa282,
-	0x0010, 0x00c8, 0x3987, 0xad88, 0x0018, 0x20a9, 0x0010, 0x2104,
-	0xa086, 0xffff, 0x0040, 0x3961, 0x8108, 0x00f0, 0x3957, 0x1078,
-	0x12cd, 0x260a, 0x8210, 0x6a56, 0x0078, 0x397a, 0x1078, 0x130c,
-	0x0040, 0x3987, 0x2d00, 0x60aa, 0x6853, 0x0000, 0xad88, 0x0018,
-	0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, 0x00f0, 0x3972, 0x6857,
-	0x0001, 0x6e62, 0x0078, 0x397e, 0x1078, 0x37d1, 0x1078, 0x3994,
-	0x00c0, 0x397c, 0xa085, 0x0001, 0x127f, 0x0d7f, 0x007c, 0xa006,
-	0x0078, 0x3984, 0x127e, 0x2091, 0x8000, 0x1078, 0x4960, 0x127f,
-	0x007c, 0xa01e, 0x0078, 0x3996, 0x2019, 0x0001, 0xa00e, 0x127e,
-	0x2091, 0x8000, 0x604c, 0x2068, 0x6000, 0xd0dc, 0x00c0, 0x39b4,
-	0x8dff, 0x0040, 0x39c9, 0x83ff, 0x0040, 0x39ac, 0x6848, 0xa606,
-	0x0040, 0x39b9, 0x0078, 0x39b4, 0x683c, 0xa406, 0x00c0, 0x39b4,
-	0x6840, 0xa506, 0x0040, 0x39b9, 0x2d08, 0x6800, 0x2068, 0x0078,
-	0x39a0, 0x6a00, 0x604c, 0xad06, 0x00c0, 0x39c1, 0x624e, 0x0078,
-	0x39c4, 0xa180, 0x0000, 0x2202, 0x82ff, 0x00c0, 0x39c9, 0x6152,
-	0x8dff, 0x127f, 0x007c, 0xa01e, 0x0078, 0x39d0, 0x2019, 0x0001,
-	0xa00e, 0x6080, 0x2068, 0x8dff, 0x0040, 0x39fc, 0x83ff, 0x0040,
-	0x39df, 0x6848, 0xa606, 0x0040, 0x39ec, 0x0078, 0x39e7, 0x683c,
-	0xa406, 0x00c0, 0x39e7, 0x6840, 0xa506, 0x0040, 0x39ec, 0x2d08,
-	0x6800, 0x2068, 0x0078, 0x39d3, 0x6a00, 0x6080, 0xad06, 0x00c0,
-	0x39f4, 0x6282, 0x0078, 0x39f7, 0xa180, 0x0000, 0x2202, 0x82ff,
-	0x00c0, 0x39fc, 0x6186, 0x8dff, 0x007c, 0x1078, 0x3a55, 0x00c0,
-	0x3a03, 0x2011, 0x0001, 0x1078, 0x3aa5, 0x00c0, 0x3a09, 0xa295,
-	0x0002, 0x007c, 0x1078, 0x3add, 0x0040, 0x3a12, 0x1078, 0x6b2b,
-	0x0078, 0x3a14, 0xa085, 0x0001, 0x007c, 0x1078, 0x3add, 0x0040,
-	0x3a1d, 0x1078, 0x6aba, 0x0078, 0x3a1f, 0xa085, 0x0001, 0x007c,
-	0x1078, 0x3add, 0x0040, 0x3a28, 0x1078, 0x6b00, 0x0078, 0x3a2a,
-	0xa085, 0x0001, 0x007c, 0x1078, 0x3add, 0x0040, 0x3a33, 0x1078,
-	0x6ad6, 0x0078, 0x3a35, 0xa085, 0x0001, 0x007c, 0x127e, 0x007e,
-	0x0d7e, 0x2091, 0x8000, 0x6080, 0xa06d, 0x0040, 0x3a4d, 0x6800,
-	0x007e, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x6c54,
-	0x1078, 0x3b92, 0x007f, 0x0078, 0x3a3c, 0x6083, 0x0000, 0x6087,
-	0x0000, 0x0d7f, 0x007f, 0x127f, 0x007c, 0x60a4, 0xa00d, 0x00c0,
-	0x3a5c, 0xa085, 0x0001, 0x007c, 0x0e7e, 0x2170, 0x7000, 0xa005,
-	0x00c0, 0x3a6f, 0x20a9, 0x0010, 0xae88, 0x0004, 0x2104, 0xa606,
-	0x0040, 0x3a6f, 0x8108, 0x00f0, 0x3a66, 0xa085, 0x0001, 0x0e7f,
-	0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x60a4, 0xa06d, 0x00c0,
-	0x3a7f, 0x1078, 0x130c, 0x0040, 0x3a91, 0x2d00, 0x60a6, 0x6803,
-	0x0001, 0x6807, 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b,
-	0xffff, 0x8108, 0x00f0, 0x3a87, 0xa085, 0x0001, 0x127f, 0x0d7f,
-	0x007c, 0xa006, 0x0078, 0x3a8e, 0x0d7e, 0x127e, 0x2091, 0x8000,
-	0x60a4, 0xa06d, 0x0040, 0x3aa2, 0x60a7, 0x0000, 0x1078, 0x1340,
-	0xa085, 0x0001, 0x127f, 0x0d7f, 0x007c, 0x60a8, 0xa00d, 0x00c0,
-	0x3aac, 0xa085, 0x0001, 0x007c, 0x0e7e, 0x2170, 0x7050, 0xa005,
-	0x00c0, 0x3abf, 0x20a9, 0x0010, 0xae88, 0x0018, 0x2104, 0xa606,
-	0x0040, 0x3abf, 0x8108, 0x00f0, 0x3ab6, 0xa085, 0x0001, 0x0e7f,
-	0x007c, 0x127e, 0x2091, 0x8000, 0x1078, 0x3aa5, 0x00c0, 0x3adb,
-	0x200b, 0xffff, 0x0d7e, 0x60a8, 0x2068, 0x6854, 0xa08a, 0x0002,
-	0x0048, 0x3ad6, 0x8001, 0x6856, 0x0078, 0x3ada, 0x1078, 0x1340,
-	0x60ab, 0x0000, 0x0d7f, 0x127f, 0x007c, 0x609c, 0xd0a4, 0x007c,
-	0x0f7e, 0x2079, 0x7751, 0x7804, 0xd0a4, 0x0040, 0x3b09, 0x157e,
-	0x0c7e, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x384c,
-	0x00c0, 0x3afd, 0x6004, 0xa084, 0xff00, 0x8007, 0xa086, 0x0006,
-	0x00c0, 0x3afd, 0x6000, 0xc0ed, 0x6002, 0x017f, 0x8108, 0x00f0,
-	0x3aed, 0x0c7f, 0x157f, 0x2009, 0x07d0, 0x2011, 0x3b0b, 0x1078,
-	0x4719, 0x0f7f, 0x007c, 0x2011, 0x3b0b, 0x1078, 0x4689, 0x157e,
-	0x0c7e, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x384c,
-	0x00c0, 0x3b37, 0x6000, 0xd0ec, 0x0040, 0x3b37, 0x047e, 0x62a0,
-	0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, 0x0029, 0x1078, 0x7641,
-	0x6000, 0xc0e5, 0xc0ec, 0x6002, 0x2019, 0x0029, 0x1078, 0x4a7e,
-	0x1078, 0x49c1, 0x2009, 0x0000, 0x1078, 0x747b, 0x047f, 0x017f,
-	0x8108, 0x00f0, 0x3b15, 0x0c7f, 0x157f, 0x007c, 0x0c7e, 0x6018,
-	0x2060, 0x6000, 0xc0ec, 0x6002, 0x0c7f, 0x007c, 0x2071, 0x77ff,
-	0x7003, 0x0001, 0x7007, 0x0000, 0x7013, 0x0000, 0x7017, 0x0000,
-	0x701b, 0x0000, 0x701f, 0x0000, 0x704b, 0x0001, 0x704f, 0x0000,
-	0x705b, 0x0020, 0x705f, 0x0040, 0x707f, 0x0000, 0x007c, 0x0e7e,
-	0x2071, 0x77ff, 0x684c, 0xa005, 0x00c0, 0x3b6d, 0x7028, 0xc085,
-	0x702a, 0xa085, 0x0001, 0x0078, 0x3b90, 0x6a60, 0x7236, 0x6b64,
-	0x733a, 0x6868, 0x703e, 0x7076, 0x686c, 0x7042, 0x707a, 0x684c,
-	0x702e, 0x6844, 0x7032, 0x2009, 0x000d, 0x200a, 0x8007, 0x8006,
-	0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319,
-	0x726e, 0x7372, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0xa006,
-	0x0e7f, 0x007c, 0x0e7e, 0x6838, 0xd0fc, 0x00c0, 0x3be3, 0x6804,
-	0xa00d, 0x0040, 0x3bb1, 0x0d7e, 0x0e7e, 0x2071, 0x7700, 0x027e,
-	0xa016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff,
-	0x00c0, 0x3ba2, 0x702e, 0x70a0, 0xa200, 0x70a2, 0x027f, 0x0e7f,
-	0x0d7f, 0x2071, 0x77ff, 0x701c, 0xa005, 0x00c0, 0x3bf4, 0x0068,
-	0x3bf2, 0x2071, 0x7751, 0x7004, 0xd09c, 0x0040, 0x3bf2, 0x6934,
-	0xa186, 0x0103, 0x00c0, 0x3c05, 0x6948, 0x6844, 0xa105, 0x00c0,
-	0x3be5, 0x2009, 0x8020, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0,
-	0x3bf2, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001,
-	0x2091, 0x4080, 0x2071, 0x7700, 0x702c, 0x206a, 0x2d00, 0x702e,
-	0x70a0, 0x8000, 0x70a2, 0x0e7f, 0x007c, 0x6844, 0xa086, 0x0100,
-	0x00c0, 0x3bf2, 0x6868, 0xa005, 0x00c0, 0x3bf2, 0x2009, 0x8020,
-	0x0078, 0x3bcb, 0x2071, 0x77ff, 0x2d08, 0x206b, 0x0000, 0x7010,
-	0x8000, 0x7012, 0x7018, 0xa06d, 0x711a, 0x0040, 0x3c02, 0x6902,
-	0x0078, 0x3c03, 0x711e, 0x0078, 0x3be3, 0xa18c, 0x00ff, 0xa186,
-	0x0017, 0x0040, 0x3c13, 0xa186, 0x001e, 0x0040, 0x3c13, 0xa18e,
-	0x001f, 0x00c0, 0x3bf2, 0x684c, 0xd0cc, 0x0040, 0x3bf2, 0x6850,
-	0xa084, 0x00ff, 0xa086, 0x0001, 0x00c0, 0x3bf2, 0x2009, 0x8021,
-	0x0078, 0x3bcb, 0x007e, 0x6837, 0x0103, 0x20a9, 0x001c, 0xad80,
-	0x0011, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x007f, 0x684a, 0x6952,
-	0x007c, 0x2071, 0x77ff, 0x7004, 0x0079, 0x3c36, 0x3c3e, 0x3c4d,
-	0x3cdd, 0x3cde, 0x3cee, 0x3cf4, 0x3c3f, 0x3ccb, 0x007c, 0x127e,
-	0x2091, 0x8000, 0x0068, 0x3c4c, 0x2009, 0x000d, 0x7030, 0x200a,
-	0x2091, 0x4080, 0x7007, 0x0001, 0x127f, 0x701c, 0xa06d, 0x0040,
-	0x3cca, 0x0e7e, 0x2071, 0x7751, 0x7004, 0xd09c, 0x0040, 0x3cac,
-	0x6934, 0xa186, 0x0103, 0x00c0, 0x3c82, 0x6948, 0x6844, 0xa105,
-	0x00c0, 0x3c9f, 0x2009, 0x8020, 0x127e, 0x2091, 0x8000, 0x0068,
-	0x3c7e, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x3c7e, 0x7122,
-	0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080,
-	0x127f, 0x0e7f, 0x1078, 0x3d27, 0x0078, 0x3cca, 0x127f, 0x0e7f,
-	0x0078, 0x3cca, 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0040, 0x3c90,
-	0xa186, 0x001e, 0x0040, 0x3c90, 0xa18e, 0x001f, 0x00c0, 0x3cac,
-	0x684c, 0xd0cc, 0x0040, 0x3cac, 0x6850, 0xa084, 0x00ff, 0xa086,
-	0x0001, 0x00c0, 0x3cac, 0x2009, 0x8021, 0x0078, 0x3c64, 0x6844,
-	0xa086, 0x0100, 0x00c0, 0x3cac, 0x6868, 0xa005, 0x00c0, 0x3cac,
-	0x2009, 0x8020, 0x0078, 0x3c64, 0x0e7f, 0x1078, 0x3d3b, 0x0040,
-	0x3cca, 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, 0x0003,
-	0x00c0, 0x3cc1, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0040, 0x3cc1,
-	0x710e, 0x7007, 0x0003, 0x1078, 0x3d5b, 0x7050, 0xa086, 0x0100,
-	0x0040, 0x3cde, 0x007c, 0x701c, 0xa06d, 0x0040, 0x3cdc, 0x1078,
-	0x3d3b, 0x0040, 0x3cdc, 0x7007, 0x0003, 0x1078, 0x3d5b, 0x7050,
-	0xa086, 0x0100, 0x0040, 0x3cde, 0x007c, 0x007c, 0x7050, 0xa09e,
-	0x0100, 0x00c0, 0x3ce7, 0x7007, 0x0004, 0x0078, 0x3cee, 0xa086,
-	0x0200, 0x00c0, 0x3ced, 0x7007, 0x0005, 0x007c, 0x1078, 0x3cf5,
-	0x7006, 0x1078, 0x3d27, 0x007c, 0x007c, 0x702c, 0x7130, 0x8108,
-	0xa102, 0x0048, 0x3d02, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072,
-	0x0078, 0x3d0c, 0x706c, 0xa080, 0x0040, 0x706e, 0x00c8, 0x3d0c,
-	0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x700c, 0x8001, 0x700e,
-	0x00c0, 0x3d20, 0x127e, 0x2091, 0x8000, 0x0068, 0x3d23, 0x2001,
-	0x000d, 0x2102, 0x2091, 0x4080, 0x2001, 0x0001, 0x127f, 0x007c,
-	0x2001, 0x0007, 0x007c, 0x2001, 0x0006, 0x127f, 0x007c, 0x701c,
-	0xa06d, 0x0040, 0x3d3a, 0x127e, 0x2091, 0x8000, 0x7010, 0x8001,
-	0x7012, 0x2d04, 0x701e, 0xa005, 0x00c0, 0x3d37, 0x701a, 0x127f,
-	0x1078, 0x1340, 0x007c, 0x2019, 0x000d, 0x2304, 0x230c, 0xa10e,
-	0x0040, 0x3d4a, 0x2304, 0x230c, 0xa10e, 0x0040, 0x3d4a, 0xa006,
-	0x0078, 0x3d5a, 0x732c, 0x8319, 0x7130, 0xa102, 0x00c0, 0x3d54,
-	0x2300, 0xa005, 0x0078, 0x3d5a, 0x0048, 0x3d59, 0xa302, 0x0078,
-	0x3d5a, 0x8002, 0x007c, 0x2d00, 0x7026, 0xa080, 0x000d, 0x7056,
-	0x7053, 0x0000, 0x127e, 0x2091, 0x8000, 0x2009, 0x7959, 0x2104,
-	0xc08d, 0x200a, 0x127f, 0x1078, 0x1391, 0x007c, 0x2071, 0x77cd,
-	0x7003, 0x0000, 0x7007, 0x0000, 0x700f, 0x0000, 0x702b, 0x0001,
-	0x704f, 0x0000, 0x7053, 0x0001, 0x705f, 0x0020, 0x7063, 0x0040,
-	0x7083, 0x0000, 0x708b, 0x0000, 0x708f, 0x0001, 0x70bf, 0x0000,
-	0x007c, 0x0e7e, 0x2071, 0x77cd, 0x6848, 0xa005, 0x00c0, 0x3d97,
-	0x7028, 0xc085, 0x702a, 0xa085, 0x0001, 0x0078, 0x3dbc, 0x6a50,
-	0x7236, 0x6b54, 0x733a, 0x6858, 0x703e, 0x707a, 0x685c, 0x7042,
-	0x707e, 0x6848, 0x702e, 0x6840, 0x7032, 0x2009, 0x000c, 0x200a,
-	0x8007, 0x8006, 0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210,
-	0x2100, 0xa319, 0x7272, 0x7376, 0x7028, 0xc084, 0x702a, 0x7007,
-	0x0001, 0x700f, 0x0000, 0xa006, 0x0e7f, 0x007c, 0x2b78, 0x2071,
-	0x77cd, 0x7004, 0x1079, 0x3e1c, 0x700c, 0x0079, 0x3dc7, 0x3dcc,
-	0x3dc1, 0x3dc1, 0x3dc1, 0x3dc1, 0x007c, 0x700c, 0x0079, 0x3dd0,
-	0x3dd5, 0x3e1a, 0x3e1a, 0x3e1b, 0x3e1b, 0x7830, 0x7930, 0xa106,
-	0x0040, 0x3ddf, 0x7830, 0x7930, 0xa106, 0x00c0, 0x3e05, 0x7030,
-	0xa10a, 0x0040, 0x3e05, 0x00c8, 0x3de7, 0x712c, 0xa10a, 0xa18a,
-	0x0002, 0x00c8, 0x3e06, 0x1078, 0x130c, 0x0040, 0x3e05, 0x2d00,
-	0x705a, 0x7063, 0x0040, 0x2001, 0x0003, 0x7057, 0x0000, 0x127e,
-	0x007e, 0x2091, 0x8000, 0x2009, 0x7959, 0x2104, 0xc085, 0x200a,
-	0x007f, 0x700e, 0x127f, 0x1078, 0x1391, 0x007c, 0x1078, 0x130c,
-	0x0040, 0x3e05, 0x2d00, 0x705a, 0x1078, 0x130c, 0x00c0, 0x3e12,
-	0x0078, 0x3df1, 0x2d00, 0x7086, 0x7063, 0x0080, 0x2001, 0x0004,
-	0x0078, 0x3df5, 0x007c, 0x007c, 0x3e2d, 0x3e2e, 0x3e65, 0x3e66,
-	0x3e1a, 0x3e9c, 0x3ea1, 0x3ed8, 0x3ed9, 0x3ef4, 0x3ef5, 0x3ef6,
-	0x3ef7, 0x3ef8, 0x3ef9, 0x3f62, 0x3f8c, 0x007c, 0x700c, 0x0079,
-	0x3e31, 0x3e36, 0x3e39, 0x3e49, 0x3e64, 0x3e64, 0x1078, 0x3dcd,
-	0x007c, 0x127e, 0x8001, 0x700e, 0x7058, 0x007e, 0x1078, 0x426e,
-	0x0040, 0x3e46, 0x2091, 0x8000, 0x1078, 0x3dcd, 0x0d7f, 0x0078,
-	0x3e52, 0x127e, 0x8001, 0x700e, 0x1078, 0x426e, 0x7058, 0x2068,
-	0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834, 0xa084,
-	0x00ff, 0xa08a, 0x0020, 0x00c8, 0x3e61, 0x1079, 0x3e7c, 0x127f,
-	0x007c, 0x127f, 0x1078, 0x3efa, 0x007c, 0x007c, 0x007c, 0x0e7e,
-	0x2071, 0x77cd, 0x700c, 0x0079, 0x3e6d, 0x3e72, 0x3e72, 0x3e72,
-	0x3e74, 0x3e78, 0x0e7f, 0x007c, 0x700f, 0x0001, 0x0078, 0x3e7a,
-	0x700f, 0x0002, 0x0e7f, 0x007c, 0x3efa, 0x3efa, 0x3f16, 0x3efa,
-	0x4001, 0x3efa, 0x3efa, 0x3efa, 0x3efa, 0x3efa, 0x3f16, 0x4040,
-	0x408a, 0x40e3, 0x40f7, 0x3efa, 0x3efa, 0x3f32, 0x3f16, 0x3efa,
-	0x3efa, 0x3f48, 0x4182, 0x41a0, 0x3efa, 0x3f32, 0x3efa, 0x3efa,
-	0x3efa, 0x3efa, 0x3f48, 0x41a0, 0x7020, 0x2068, 0x1078, 0x1340,
-	0x007c, 0x700c, 0x0079, 0x3ea4, 0x3ea9, 0x3eac, 0x3ebc, 0x3ed7,
-	0x3ed7, 0x1078, 0x3dcd, 0x007c, 0x127e, 0x8001, 0x700e, 0x7058,
-	0x007e, 0x1078, 0x426e, 0x0040, 0x3eb9, 0x2091, 0x8000, 0x1078,
-	0x3dcd, 0x0d7f, 0x0078, 0x3ec5, 0x127e, 0x8001, 0x700e, 0x1078,
-	0x426e, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807,
-	0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x001a, 0x00c8, 0x3ed4,
-	0x1079, 0x3eda, 0x127f, 0x007c, 0x127f, 0x1078, 0x3efa, 0x007c,
-	0x007c, 0x007c, 0x3efa, 0x3f16, 0x3feb, 0x3efa, 0x3f16, 0x3efa,
-	0x3f16, 0x3f16, 0x3efa, 0x3f16, 0x3feb, 0x3f16, 0x3f16, 0x3f16,
-	0x3f16, 0x3f16, 0x3efa, 0x3f16, 0x3feb, 0x3efa, 0x3efa, 0x3f16,
-	0x3efa, 0x3efa, 0x3efa, 0x3f16, 0x007c, 0x007c, 0x007c, 0x007c,
-	0x007c, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0d5,
-	0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x3b92, 0x127f, 0x007c,
-	0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0e5, 0x683a, 0x127e,
-	0x2091, 0x8000, 0x1078, 0x3b92, 0x127f, 0x007c, 0x7007, 0x0001,
-	0x6838, 0xa084, 0x00ff, 0xc0ed, 0x683a, 0x127e, 0x2091, 0x8000,
-	0x1078, 0x3b92, 0x127f, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084,
-	0x00ff, 0xc0dd, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x3b92,
-	0x127f, 0x007c, 0x6834, 0x8007, 0xa084, 0x00ff, 0x0040, 0x3f08,
-	0x8001, 0x00c0, 0x3f3f, 0x7007, 0x0001, 0x0078, 0x3fc8, 0x7007,
-	0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x3fc8, 0x007c,
-	0x2d00, 0x7016, 0x701a, 0x20a9, 0x0004, 0xa080, 0x0024, 0x2098,
-	0x20a1, 0x77f8, 0x53a3, 0x6858, 0x7012, 0xa082, 0x0401, 0x00c8,
-	0x3f24, 0x6884, 0xa08a, 0x0003, 0x00c8, 0x3f24, 0xa080, 0x3fb9,
-	0x2004, 0x70c6, 0x7010, 0xa015, 0x0040, 0x3fac, 0x1078, 0x130c,
-	0x00c0, 0x3f6d, 0x7007, 0x000f, 0x007c, 0x2d00, 0x7022, 0x70c4,
-	0x2060, 0x6000, 0x6836, 0x6004, 0xad00, 0x7096, 0x6008, 0xa20a,
-	0x00c8, 0x3f7c, 0xa00e, 0x2200, 0x7112, 0x620c, 0x8003, 0x800b,
-	0xa296, 0x0004, 0x0040, 0x3f85, 0xa108, 0x719a, 0x810b, 0x719e,
-	0xae90, 0x0022, 0x1078, 0x1377, 0x7090, 0xa08e, 0x0100, 0x0040,
-	0x3fa0, 0xa086, 0x0200, 0x0040, 0x3f98, 0x7007, 0x0010, 0x007c,
-	0x7020, 0x2068, 0x1078, 0x1340, 0x7014, 0x2068, 0x0078, 0x3f24,
-	0x7020, 0x2068, 0x7018, 0x6802, 0x6807, 0x0000, 0x2d08, 0x2068,
-	0x6906, 0x711a, 0x0078, 0x3f62, 0x7014, 0x2068, 0x7007, 0x0001,
-	0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x0040, 0x41bd, 0x0078,
-	0x3fc8, 0x3fbc, 0x3fc0, 0x3fc4, 0x0002, 0x0011, 0x0007, 0x0004,
-	0x000a, 0x000f, 0x0005, 0x0006, 0x0012, 0x000f, 0x0005, 0x0006,
-	0x2009, 0x772c, 0x210c, 0x81ff, 0x00c0, 0x3fe5, 0x6838, 0xa084,
-	0x00ff, 0x683a, 0x6853, 0x0000, 0x1078, 0x3691, 0x00c0, 0x3fd9,
-	0x007c, 0x1078, 0x3c22, 0x127e, 0x2091, 0x8000, 0x1078, 0x6c54,
-	0x1078, 0x3b92, 0x127f, 0x0078, 0x3fd8, 0x2001, 0x0028, 0x2009,
-	0x0000, 0x0078, 0x3fd9, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906,
-	0x711a, 0x7010, 0x8001, 0x7012, 0x0040, 0x3ffa, 0x7007, 0x0006,
-	0x0078, 0x4000, 0x7014, 0x2068, 0x7007, 0x0001, 0x7048, 0x107a,
-	0x007c, 0x7007, 0x0001, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x6848,
-	0xa084, 0x00ff, 0x20a9, 0x0001, 0xa096, 0x0001, 0x0040, 0x402a,
-	0x2009, 0x0000, 0x20a9, 0x007e, 0xa096, 0x0002, 0x0040, 0x402a,
-	0xa005, 0x00c0, 0x403d, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x1078,
-	0x384c, 0x00c0, 0x403d, 0x067e, 0x6e50, 0x1078, 0x3915, 0x067f,
-	0x0078, 0x403d, 0x047e, 0x2011, 0x770c, 0x2224, 0xc484, 0xc48c,
-	0x2412, 0x047f, 0x0c7e, 0x1078, 0x384c, 0x00c0, 0x4039, 0x1078,
-	0x3a94, 0x8108, 0x00f0, 0x4033, 0x0c7f, 0x1078, 0x1340, 0x007c,
-	0x127e, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0x7752, 0x2004,
-	0xd0a4, 0x0040, 0x4081, 0x2009, 0x0000, 0x1078, 0x428a, 0x6100,
-	0xd184, 0x0040, 0x4066, 0x6858, 0xa084, 0x00ff, 0x00c0, 0x4084,
-	0x6000, 0xd084, 0x0040, 0x4081, 0x6004, 0xa005, 0x00c0, 0x4087,
-	0x6003, 0x0000, 0x600b, 0x0000, 0x0078, 0x407e, 0x2011, 0x0001,
-	0x6860, 0xa005, 0x00c0, 0x406e, 0x2001, 0x001e, 0x8000, 0x6016,
-	0x6858, 0xa084, 0x00ff, 0x0040, 0x4081, 0x6006, 0x6858, 0x8007,
-	0xa084, 0x00ff, 0x0040, 0x4081, 0x600a, 0x6202, 0x127f, 0x0078,
-	0x425d, 0x127f, 0x0078, 0x4255, 0x127f, 0x0078, 0x424d, 0x127f,
-	0x0078, 0x4251, 0x127e, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001,
-	0x7752, 0x2004, 0xd0a4, 0x0040, 0x40e0, 0x2009, 0x0000, 0x1078,
-	0x428a, 0x6000, 0xa084, 0x0001, 0x0040, 0x40e0, 0x6204, 0x6308,
-	0x6c48, 0xa484, 0x0003, 0x0040, 0x40b8, 0x6958, 0xa18c, 0x00ff,
-	0x8001, 0x00c0, 0x40b1, 0x2100, 0xa210, 0x0048, 0x40dd, 0x0078,
-	0x40b8, 0x8001, 0x00c0, 0x40dd, 0x2100, 0xa212, 0x0048, 0x40dd,
-	0xa484, 0x000c, 0x0040, 0x40d2, 0x6958, 0x810f, 0xa18c, 0x00ff,
-	0xa082, 0x0004, 0x00c0, 0x40ca, 0x2100, 0xa318, 0x0048, 0x40dd,
-	0x0078, 0x40d2, 0xa082, 0x0004, 0x00c0, 0x40dd, 0x2100, 0xa31a,
-	0x0048, 0x40dd, 0x6860, 0xa005, 0x0040, 0x40d8, 0x8000, 0x6016,
-	0x6206, 0x630a, 0x127f, 0x0078, 0x425d, 0x127f, 0x0078, 0x4259,
-	0x127f, 0x0078, 0x4255, 0x127e, 0x2091, 0x8000, 0x7007, 0x0001,
-	0x2009, 0x0000, 0x1078, 0x428a, 0x6308, 0x8318, 0x0048, 0x40f4,
-	0x630a, 0x127f, 0x0078, 0x426b, 0x127f, 0x0078, 0x4259, 0x127e,
-	0x0c7e, 0x2091, 0x8000, 0x7007, 0x0001, 0x684c, 0xd0ac, 0x0040,
-	0x410d, 0x2009, 0x0000, 0x0c7e, 0x1078, 0x4727, 0x6000, 0x2001,
-	0xfcff, 0x6002, 0x0c7f, 0x0078, 0x4144, 0x6858, 0xa005, 0x0040,
-	0x4159, 0x685c, 0xa065, 0x0040, 0x4155, 0x2001, 0x772c, 0x2004,
-	0xa005, 0x0040, 0x411f, 0x1078, 0x6bb6, 0x0078, 0x4125, 0x6013,
-	0x0400, 0x2009, 0x0041, 0x1078, 0x5d41, 0x6958, 0xa18c, 0xe600,
-	0xa186, 0x2000, 0x0040, 0x413c, 0xa186, 0x0400, 0x0040, 0x413c,
-	0x2009, 0x0000, 0x0c7e, 0x1078, 0x4727, 0x6000, 0xa084, 0xfdff,
-	0x6002, 0x0c7f, 0x0078, 0x4144, 0x027e, 0x2009, 0x0000, 0x2011,
-	0xfdff, 0x1078, 0x47d0, 0x027f, 0x684c, 0xd0c4, 0x0040, 0x4151,
-	0x2009, 0x0000, 0x1078, 0x4727, 0x6008, 0x8000, 0x0048, 0x4151,
-	0x600a, 0x0c7f, 0x127f, 0x0078, 0x425d, 0x0c7f, 0x127f, 0x0078,
-	0x4255, 0x6954, 0xa186, 0x002a, 0x00c0, 0x4165, 0x2001, 0x770c,
-	0x200c, 0xc194, 0x2102, 0x0078, 0x4144, 0xa186, 0x0020, 0x0040,
-	0x417a, 0xa186, 0x0029, 0x00c0, 0x4155, 0x6944, 0xa18c, 0xff00,
-	0x810f, 0x1078, 0x384c, 0x00c0, 0x4144, 0x6000, 0xc0e4, 0x6002,
-	0x0078, 0x4144, 0x685c, 0xa065, 0x0040, 0x4155, 0x6017, 0x0014,
-	0x0078, 0x4144, 0x2009, 0x0000, 0x1078, 0x428a, 0x6000, 0xa084,
-	0x0001, 0x0040, 0x419c, 0x2091, 0x8000, 0x6204, 0x8210, 0x0048,
-	0x4196, 0x6206, 0x2091, 0x8001, 0x0078, 0x426b, 0x2091, 0x8001,
-	0x6853, 0x0016, 0x0078, 0x4264, 0x6853, 0x0007, 0x0078, 0x4264,
-	0x6834, 0x8007, 0xa084, 0x00ff, 0x00c0, 0x41aa, 0x1078, 0x3f08,
-	0x0078, 0x41bc, 0x2030, 0x8001, 0x00c0, 0x41b4, 0x7007, 0x0001,
-	0x1078, 0x41bd, 0x0078, 0x41bc, 0x7007, 0x0006, 0x7012, 0x2d00,
-	0x7016, 0x701a, 0x704b, 0x41bd, 0x007c, 0x0e7e, 0x2009, 0x772c,
-	0x210c, 0x81ff, 0x00c0, 0x423f, 0x2009, 0x770c, 0x210c, 0xd194,
-	0x00c0, 0x4249, 0x6848, 0x2070, 0xae82, 0x7e00, 0x0048, 0x422e,
-	0x2001, 0x7715, 0x2004, 0xae02, 0x00c8, 0x422e, 0x2009, 0x0000,
-	0x1078, 0x428a, 0x6100, 0xa184, 0x0001, 0x0040, 0x4214, 0xa184,
-	0x0100, 0x00c0, 0x4232, 0xa184, 0x0200, 0x00c0, 0x4236, 0x601c,
-	0xa005, 0x00c0, 0x423a, 0x711c, 0xa186, 0x0006, 0x00c0, 0x4219,
-	0x6853, 0x0000, 0x6803, 0x0000, 0x2d08, 0x127e, 0x2091, 0x8000,
-	0x7010, 0xa005, 0x00c0, 0x420b, 0x7112, 0x7018, 0xa065, 0x0040,
-	0x423e, 0x6000, 0xd0e4, 0x00c0, 0x4243, 0x2e60, 0x1078, 0x4730,
-	0x127f, 0x0e7f, 0x007c, 0x2068, 0x6800, 0xa005, 0x00c0, 0x420b,
-	0x6902, 0x127f, 0x0e7f, 0x007c, 0x0e7f, 0x6853, 0x0006, 0x0078,
-	0x4264, 0x6944, 0xa18c, 0xff00, 0x810f, 0x1078, 0x384c, 0x00c0,
-	0x4244, 0x6000, 0xd0e4, 0x00c0, 0x4244, 0x711c, 0xa186, 0x0007,
-	0x00c0, 0x422e, 0x6853, 0x0002, 0x0078, 0x4246, 0x6853, 0x0008,
-	0x0078, 0x4246, 0x6853, 0x000e, 0x0078, 0x4246, 0x6853, 0x0017,
-	0x0078, 0x4246, 0x6853, 0x0035, 0x0078, 0x4246, 0x127f, 0x6853,
-	0x0028, 0x0078, 0x4246, 0x127f, 0x6853, 0x0029, 0x0e7f, 0x0078,
-	0x4264, 0x6853, 0x002a, 0x0078, 0x4246, 0x2009, 0x003e, 0x0078,
-	0x425f, 0x2009, 0x0004, 0x0078, 0x425f, 0x2009, 0x0006, 0x0078,
-	0x425f, 0x2009, 0x0016, 0x0078, 0x425f, 0x2009, 0x0001, 0x6854,
-	0xa084, 0xff00, 0xa105, 0x6856, 0x2091, 0x8000, 0x1078, 0x3b92,
-	0x2091, 0x8001, 0x007c, 0x1078, 0x1340, 0x007c, 0x702c, 0x7130,
-	0x8108, 0xa102, 0x0048, 0x427b, 0xa00e, 0x7034, 0x7072, 0x7038,
-	0x7076, 0x0078, 0x4287, 0x7070, 0xa080, 0x0040, 0x7072, 0x00c8,
-	0x4287, 0x7074, 0xa081, 0x0000, 0x7076, 0xa085, 0x0001, 0x7932,
-	0x7132, 0x007c, 0x0d7e, 0x1078, 0x4727, 0x0d7f, 0x007c, 0x0d7e,
+	0x00f0, 0x41dd, 0xa085, 0x0001, 0x127f, 0x0d7f, 0x007c, 0xa006,
+	0x0078, 0x41e4, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x60a4, 0xa06d,
+	0x0040, 0x41f8, 0x60a7, 0x0000, 0x1078, 0x1344, 0xa085, 0x0001,
+	0x127f, 0x0d7f, 0x007c, 0x60a8, 0xa00d, 0x00c0, 0x4202, 0xa085,
+	0x0001, 0x007c, 0x0e7e, 0x2170, 0x7050, 0xa005, 0x00c0, 0x4215,
+	0x20a9, 0x0010, 0xae88, 0x0018, 0x2104, 0xa606, 0x0040, 0x4215,
+	0x8108, 0x00f0, 0x420c, 0xa085, 0x0001, 0x0e7f, 0x007c, 0x127e,
+	0x2091, 0x8000, 0x1078, 0x41fb, 0x00c0, 0x4231, 0x200b, 0xffff,
+	0x0d7e, 0x60a8, 0x2068, 0x6854, 0xa08a, 0x0002, 0x0048, 0x422c,
+	0x8001, 0x6856, 0x0078, 0x4230, 0x1078, 0x1344, 0x60ab, 0x0000,
+	0x0d7f, 0x127f, 0x007c, 0x609c, 0xd0a4, 0x007c, 0x0f7e, 0x2079,
+	0x8851, 0x7804, 0xd0a4, 0x0040, 0x4263, 0x157e, 0x0c7e, 0x20a9,
+	0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x3f8e, 0x00c0, 0x4257,
+	0x6004, 0xa084, 0xff00, 0x8007, 0xa096, 0x0004, 0x0040, 0x4254,
+	0xa086, 0x0006, 0x00c0, 0x4257, 0x6000, 0xc0ed, 0x6002, 0x017f,
+	0x8108, 0x00f0, 0x4243, 0x0c7f, 0x157f, 0x2009, 0x07d0, 0x2011,
+	0x4265, 0x1078, 0x5181, 0x0f7f, 0x007c, 0x2011, 0x4265, 0x1078,
+	0x50f2, 0x157e, 0x0c7e, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e,
+	0x1078, 0x3f8e, 0x00c0, 0x429b, 0x6000, 0xd0ec, 0x0040, 0x429b,
+	0x047e, 0x62a0, 0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, 0x0029,
+	0x1078, 0x86f5, 0x6000, 0xc0e5, 0xc0ec, 0x6002, 0x6004, 0xa084,
+	0x00ff, 0xa085, 0x0700, 0x6006, 0x2019, 0x0029, 0x1078, 0x54f0,
+	0x087e, 0x2041, 0x0000, 0x1078, 0x5419, 0x2009, 0x0000, 0x1078,
+	0x84d2, 0x087f, 0x047f, 0x017f, 0x8108, 0x00f0, 0x426f, 0x0c7f,
+	0x157f, 0x007c, 0x0c7e, 0x6018, 0x2060, 0x6000, 0xc0ec, 0x6002,
+	0x0c7f, 0x007c, 0x2071, 0x8913, 0x7003, 0x0001, 0x7007, 0x0000,
+	0x7013, 0x0000, 0x7017, 0x0000, 0x701b, 0x0000, 0x701f, 0x0000,
+	0x704b, 0x0001, 0x704f, 0x0000, 0x705b, 0x0020, 0x705f, 0x0040,
+	0x707f, 0x0000, 0x2071, 0x8a7c, 0x7003, 0x8913, 0x7007, 0x0000,
+	0x700b, 0x0000, 0x700f, 0x8a5c, 0x7013, 0x0020, 0x7017, 0x0040,
+	0x7037, 0x0000, 0x007c, 0x017e, 0x0e7e, 0x2071, 0x8a34, 0xa00e,
+	0x7186, 0x718a, 0x7097, 0x0001, 0x2001, 0x8852, 0x2004, 0xd0fc,
+	0x00c0, 0x42ed, 0x2001, 0x8852, 0x2004, 0xa00e, 0xd09c, 0x0040,
+	0x42ea, 0x8108, 0x7102, 0x0078, 0x4340, 0x2001, 0x8871, 0x200c,
+	0xa184, 0x000f, 0x2009, 0x8872, 0x210c, 0x0079, 0x42f7, 0x42e2,
+	0x4318, 0x4320, 0x432b, 0x4331, 0x42e2, 0x42e2, 0x42e2, 0x4307,
+	0x42e2, 0x42e2, 0x42e2, 0x42e2, 0x42e2, 0x42e2, 0x42e2, 0x7003,
+	0x0004, 0x137e, 0x147e, 0x157e, 0x2099, 0x8875, 0x20a1, 0x8a85,
+	0x20a9, 0x0004, 0x53a3, 0x157f, 0x147f, 0x137f, 0x0078, 0x4340,
+	0x708f, 0x0005, 0x7007, 0x0122, 0x2001, 0x0002, 0x0078, 0x4326,
+	0x708f, 0x0002, 0x7007, 0x0121, 0x2001, 0x0003, 0x7002, 0x7097,
+	0x0001, 0x0078, 0x433d, 0x7007, 0x0122, 0x2001, 0x0002, 0x0078,
+	0x4335, 0x7007, 0x0121, 0x2001, 0x0003, 0x7002, 0xa006, 0x7096,
+	0x708e, 0xa184, 0xff00, 0x8007, 0x709a, 0xa184, 0x00ff, 0x7092,
+	0x0e7f, 0x017f, 0x007c, 0x0e7e, 0x2071, 0x8913, 0x684c, 0xa005,
+	0x00c0, 0x4351, 0x7028, 0xc085, 0x702a, 0xa085, 0x0001, 0x0078,
+	0x4374, 0x6a60, 0x7236, 0x6b64, 0x733a, 0x6868, 0x703e, 0x7076,
+	0x686c, 0x7042, 0x707a, 0x684c, 0x702e, 0x6844, 0x7032, 0x2009,
+	0x000d, 0x200a, 0x8007, 0x8006, 0x8006, 0xa08c, 0x003f, 0xa084,
+	0xffc0, 0xa210, 0x2100, 0xa319, 0x726e, 0x7372, 0x7028, 0xc084,
+	0x702a, 0x7007, 0x0001, 0xa006, 0x0e7f, 0x007c, 0x0e7e, 0x027e,
+	0x6838, 0xd0fc, 0x00c0, 0x43cc, 0x6804, 0xa00d, 0x0040, 0x4392,
+	0x0d7e, 0x2071, 0x8800, 0xa016, 0x702c, 0x2168, 0x6904, 0x206a,
+	0x8210, 0x2d00, 0x81ff, 0x00c0, 0x4385, 0x702e, 0x70a4, 0xa200,
+	0x70a6, 0x0d7f, 0x2071, 0x8913, 0x701c, 0xa005, 0x00c0, 0x43de,
+	0x0068, 0x43dc, 0x2071, 0x8a34, 0x7200, 0x82ff, 0x0040, 0x43dc,
+	0x6934, 0xa186, 0x0103, 0x00c0, 0x43ef, 0x6948, 0x6844, 0xa105,
+	0x00c0, 0x43cf, 0x2009, 0x8020, 0x2200, 0x0079, 0x43af, 0x43dc,
+	0x43b4, 0x440c, 0x441a, 0x43dc, 0x2071, 0x0000, 0x7018, 0xd084,
+	0x00c0, 0x43dc, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a, 0x701b,
+	0x0001, 0x2091, 0x4080, 0x2071, 0x8800, 0x702c, 0x206a, 0x2d00,
+	0x702e, 0x70a4, 0x8000, 0x70a6, 0x027f, 0x0e7f, 0x007c, 0x6844,
+	0xa086, 0x0100, 0x00c0, 0x43dc, 0x6868, 0xa005, 0x00c0, 0x43dc,
+	0x2009, 0x8020, 0x0078, 0x43ac, 0x2071, 0x8913, 0x2d08, 0x206b,
+	0x0000, 0x7010, 0x8000, 0x7012, 0x7018, 0xa06d, 0x711a, 0x0040,
+	0x43ec, 0x6902, 0x0078, 0x43ed, 0x711e, 0x0078, 0x43cc, 0xa18c,
+	0x00ff, 0xa186, 0x0017, 0x0040, 0x43fd, 0xa186, 0x001e, 0x0040,
+	0x43fd, 0xa18e, 0x001f, 0x00c0, 0x43dc, 0x684c, 0xd0cc, 0x0040,
+	0x43dc, 0x6850, 0xa084, 0x00ff, 0xa086, 0x0001, 0x00c0, 0x43dc,
+	0x2009, 0x8021, 0x0078, 0x43ac, 0x7084, 0x8008, 0xa092, 0x001e,
+	0x00c8, 0x43dc, 0x7186, 0xae90, 0x0003, 0xa210, 0x683c, 0x2012,
+	0x0078, 0x442a, 0x7084, 0x8008, 0xa092, 0x000f, 0x00c8, 0x43dc,
+	0x7186, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012, 0x8210,
+	0x6840, 0x2012, 0x7088, 0xa10a, 0x0048, 0x43c3, 0x718c, 0x7084,
+	0xa10a, 0x0048, 0x43c3, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0,
+	0x43c3, 0x2071, 0x8a34, 0x7000, 0xa086, 0x0002, 0x00c0, 0x444a,
+	0x1078, 0x46a6, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080,
+	0x0078, 0x43c3, 0x1078, 0x46d1, 0x2071, 0x0000, 0x701b, 0x0001,
+	0x2091, 0x4080, 0x0078, 0x43c3, 0x007e, 0x684c, 0x007e, 0x6837,
+	0x0103, 0x20a9, 0x001c, 0xad80, 0x0011, 0x20a0, 0x2001, 0x0000,
+	0x40a4, 0x007f, 0xa084, 0x00ff, 0x684e, 0x007f, 0x684a, 0x6952,
+	0x007c, 0x2071, 0x8913, 0x7004, 0x0079, 0x446e, 0x4478, 0x4487,
+	0x4677, 0x4678, 0x469f, 0x46a5, 0x4479, 0x4665, 0x4608, 0x4688,
+	0x007c, 0x127e, 0x2091, 0x8000, 0x0068, 0x4486, 0x2009, 0x000d,
+	0x7030, 0x200a, 0x2091, 0x4080, 0x7007, 0x0001, 0x127f, 0x2069,
+	0x8ab5, 0x6844, 0xa005, 0x0050, 0x44af, 0x00c0, 0x44af, 0x127e,
+	0x2091, 0x8000, 0x2069, 0x0000, 0x6934, 0x2001, 0x891f, 0x2004,
+	0xa10a, 0x0040, 0x44aa, 0x0068, 0x44af, 0x2069, 0x0000, 0x6818,
+	0xd084, 0x00c0, 0x44ae, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001,
+	0x2091, 0x4080, 0x2069, 0x8ab5, 0x6847, 0xffff, 0x127f, 0x2069,
+	0x8800, 0x6844, 0x6960, 0xa102, 0x2069, 0x8a34, 0x688a, 0x6984,
+	0x701c, 0xa06d, 0x0040, 0x44c1, 0x81ff, 0x0040, 0x4509, 0x0078,
+	0x44d7, 0x81ff, 0x0040, 0x45db, 0x2071, 0x8a34, 0x7184, 0x7088,
+	0xa10a, 0x00c8, 0x44d7, 0x7190, 0x2071, 0x8ab5, 0x7040, 0xa005,
+	0x0040, 0x44d7, 0x00d0, 0x45db, 0x7142, 0x0078, 0x45db, 0x2071,
+	0x8a34, 0x718c, 0x127e, 0x2091, 0x8000, 0x7084, 0xa10a, 0x0048,
+	0x45dc, 0x0068, 0x458d, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0,
+	0x458d, 0x2001, 0xffff, 0x2071, 0x8ab5, 0x7042, 0x2071, 0x8a34,
+	0x7000, 0xa086, 0x0002, 0x00c0, 0x44ff, 0x1078, 0x46a6, 0x2071,
+	0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, 0x458d, 0x1078,
+	0x46d1, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0078,
+	0x458d, 0x2071, 0x8a34, 0x7000, 0xa005, 0x0040, 0x45ba, 0x6934,
+	0xa186, 0x0103, 0x00c0, 0x4590, 0x684c, 0xd0bc, 0x00c0, 0x45ba,
+	0x6948, 0x6844, 0xa105, 0x00c0, 0x45ad, 0x2071, 0x8a34, 0x7000,
+	0x0079, 0x4522, 0x45ba, 0x4570, 0x4548, 0x455a, 0x4527, 0x137e,
+	0x147e, 0x157e, 0x2099, 0x8875, 0x20a1, 0x8a85, 0x20a9, 0x0004,
+	0x53a3, 0x157f, 0x147f, 0x137f, 0x2071, 0x8a7c, 0xad80, 0x000f,
+	0x700e, 0x7013, 0x0002, 0x7007, 0x0002, 0x700b, 0x0000, 0x2e10,
+	0x1078, 0x137b, 0x2071, 0x8913, 0x7007, 0x0009, 0x0078, 0x45db,
+	0x7084, 0x8008, 0xa092, 0x001e, 0x00c8, 0x45db, 0xae90, 0x0003,
+	0xa210, 0x683c, 0x2012, 0x7186, 0x2071, 0x8913, 0x1078, 0x4731,
+	0x0078, 0x45db, 0x7084, 0x8008, 0xa092, 0x000f, 0x00c8, 0x45db,
+	0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012, 0x8210, 0x6840,
+	0x2012, 0x7186, 0x2071, 0x8913, 0x1078, 0x4731, 0x0078, 0x45db,
+	0x2009, 0x8020, 0x127e, 0x2091, 0x8000, 0x0068, 0x458d, 0x2071,
+	0x0000, 0x7018, 0xd084, 0x00c0, 0x458d, 0x7122, 0x683c, 0x7026,
+	0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, 0x127f, 0x2071,
+	0x8913, 0x1078, 0x4731, 0x0078, 0x45db, 0x127f, 0x0078, 0x45db,
+	0xa18c, 0x00ff, 0xa186, 0x0017, 0x0040, 0x459e, 0xa186, 0x001e,
+	0x0040, 0x459e, 0xa18e, 0x001f, 0x00c0, 0x45ba, 0x684c, 0xd0cc,
+	0x0040, 0x45ba, 0x6850, 0xa084, 0x00ff, 0xa086, 0x0001, 0x00c0,
+	0x45ba, 0x2009, 0x8021, 0x0078, 0x4572, 0x6844, 0xa086, 0x0100,
+	0x00c0, 0x45ba, 0x6868, 0xa005, 0x00c0, 0x45ba, 0x2009, 0x8020,
+	0x0078, 0x4572, 0x2071, 0x8913, 0x1078, 0x4745, 0x0040, 0x45db,
+	0x2071, 0x8913, 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086,
+	0x0003, 0x00c0, 0x45d2, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0040,
+	0x45d2, 0x710e, 0x7007, 0x0003, 0x1078, 0x4765, 0x7050, 0xa086,
+	0x0100, 0x0040, 0x4678, 0x007c, 0x2071, 0x8913, 0x1078, 0x4745,
+	0x0040, 0x4605, 0x2071, 0x8a34, 0x7084, 0x700a, 0x20a9, 0x0020,
+	0x2099, 0x8a35, 0x20a1, 0x8a5c, 0x53a3, 0x7087, 0x0000, 0x2071,
+	0x8913, 0x2069, 0x8a7c, 0x706c, 0x6826, 0x7070, 0x682a, 0x7074,
+	0x682e, 0x7078, 0x6832, 0x2d10, 0x1078, 0x137b, 0x7007, 0x0008,
+	0x2001, 0xffff, 0x2071, 0x8ab5, 0x7042, 0x127f, 0x0078, 0x45db,
+	0x2069, 0x8a7c, 0x6808, 0xa08e, 0x0000, 0x0040, 0x4664, 0xa08e,
+	0x0200, 0x0040, 0x4662, 0xa08e, 0x0100, 0x00c0, 0x4664, 0x127e,
+	0x2091, 0x8000, 0x0068, 0x465f, 0x2069, 0x0000, 0x6818, 0xd084,
+	0x00c0, 0x465f, 0x702c, 0x7130, 0x8108, 0xa102, 0x0048, 0x462f,
+	0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, 0x0078, 0x4639, 0x706c,
+	0xa080, 0x0040, 0x706e, 0x00c8, 0x4639, 0x7070, 0xa081, 0x0000,
+	0x7072, 0x7132, 0x6936, 0x2001, 0x8a59, 0x2004, 0xa005, 0x00c0,
+	0x4656, 0x6934, 0x2069, 0x8a34, 0x689c, 0x699e, 0x2069, 0x8ab5,
+	0xa102, 0x00c0, 0x464f, 0x6844, 0xa005, 0x00d0, 0x465d, 0x2001,
+	0x8a5a, 0x200c, 0x810d, 0x6946, 0x0078, 0x465d, 0x2009, 0x8040,
+	0x6922, 0x681b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, 0x127f,
+	0x0078, 0x4664, 0x7007, 0x0005, 0x007c, 0x701c, 0xa06d, 0x0040,
+	0x4676, 0x1078, 0x4745, 0x0040, 0x4676, 0x7007, 0x0003, 0x1078,
+	0x4765, 0x7050, 0xa086, 0x0100, 0x0040, 0x4678, 0x007c, 0x007c,
+	0x7050, 0xa09e, 0x0100, 0x00c0, 0x4681, 0x7007, 0x0004, 0x0078,
+	0x469f, 0xa086, 0x0200, 0x00c0, 0x4687, 0x7007, 0x0005, 0x007c,
+	0x2001, 0x8a7e, 0x2004, 0xa08e, 0x0100, 0x00c0, 0x4694, 0x7007,
+	0x0001, 0x1078, 0x4731, 0x007c, 0xa08e, 0x0000, 0x0040, 0x4693,
+	0xa08e, 0x0200, 0x00c0, 0x4693, 0x7007, 0x0005, 0x007c, 0x1078,
+	0x46f9, 0x7006, 0x1078, 0x4731, 0x007c, 0x007c, 0x0e7e, 0x157e,
+	0x2071, 0x8a34, 0x7184, 0x81ff, 0x0040, 0x46ce, 0xa006, 0x7086,
+	0xae80, 0x0003, 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000,
+	0x0070, 0x46cb, 0x2014, 0x722a, 0x8000, 0x0070, 0x46cb, 0x2014,
+	0x722e, 0x8000, 0x0070, 0x46cb, 0x2014, 0x723a, 0x8000, 0x0070,
+	0x46cb, 0x2014, 0x723e, 0xa180, 0x8030, 0x7022, 0x157f, 0x0e7f,
+	0x007c, 0x0e7e, 0x157e, 0x2071, 0x8a34, 0x7184, 0x81ff, 0x0040,
+	0x46f6, 0xa006, 0x7086, 0xae80, 0x0003, 0x2071, 0x0000, 0x21a8,
+	0x2014, 0x7226, 0x8000, 0x2014, 0x722a, 0x8000, 0x0070, 0x46ef,
+	0x2014, 0x723a, 0x8000, 0x2014, 0x723e, 0x0078, 0x46f3, 0x2001,
+	0x8020, 0x0078, 0x46f5, 0xa180, 0x8042, 0x7022, 0x157f, 0x0e7f,
+	0x007c, 0x702c, 0x7130, 0x8108, 0xa102, 0x0048, 0x4706, 0xa00e,
+	0x7034, 0x706e, 0x7038, 0x7072, 0x0078, 0x4710, 0x706c, 0xa080,
+	0x0040, 0x706e, 0x00c8, 0x4710, 0x7070, 0xa081, 0x0000, 0x7072,
+	0x7132, 0x700c, 0x8001, 0x700e, 0x00c0, 0x472a, 0x127e, 0x2091,
+	0x8000, 0x0068, 0x472d, 0x2001, 0x000d, 0x2102, 0x2091, 0x4080,
+	0x2001, 0x0001, 0x127f, 0x007c, 0x2001, 0x000d, 0x2102, 0x2001,
+	0x0001, 0x007c, 0x2001, 0x0007, 0x007c, 0x2001, 0x0006, 0x127f,
+	0x007c, 0x701c, 0xa06d, 0x0040, 0x4744, 0x127e, 0x2091, 0x8000,
+	0x7010, 0x8001, 0x7012, 0x2d04, 0x701e, 0xa005, 0x00c0, 0x4741,
+	0x701a, 0x127f, 0x1078, 0x1344, 0x007c, 0x2019, 0x000d, 0x2304,
+	0x230c, 0xa10e, 0x0040, 0x4754, 0x2304, 0x230c, 0xa10e, 0x0040,
+	0x4754, 0xa006, 0x0078, 0x4764, 0x732c, 0x8319, 0x7130, 0xa102,
+	0x00c0, 0x475e, 0x2300, 0xa005, 0x0078, 0x4764, 0x0048, 0x4763,
+	0xa302, 0x0078, 0x4764, 0x8002, 0x007c, 0x2d00, 0x7026, 0xa080,
+	0x000d, 0x7056, 0x7053, 0x0000, 0x127e, 0x2091, 0x8000, 0x2009,
+	0x8ac7, 0x2104, 0xc08d, 0x200a, 0x127f, 0x1078, 0x1395, 0x007c,
+	0x2071, 0x88e1, 0x7003, 0x0000, 0x7007, 0x0000, 0x700f, 0x0000,
+	0x702b, 0x0001, 0x704f, 0x0000, 0x7053, 0x0001, 0x705f, 0x0020,
+	0x7063, 0x0040, 0x7083, 0x0000, 0x708b, 0x0000, 0x708f, 0x0001,
+	0x70bf, 0x0000, 0x007c, 0x0e7e, 0x2071, 0x88e1, 0x6848, 0xa005,
+	0x00c0, 0x47a1, 0x7028, 0xc085, 0x702a, 0xa085, 0x0001, 0x0078,
+	0x47c6, 0x6a50, 0x7236, 0x6b54, 0x733a, 0x6858, 0x703e, 0x707a,
+	0x685c, 0x7042, 0x707e, 0x6848, 0x702e, 0x6840, 0x7032, 0x2009,
+	0x000c, 0x200a, 0x8007, 0x8006, 0x8006, 0xa08c, 0x003f, 0xa084,
+	0xffc0, 0xa210, 0x2100, 0xa319, 0x7272, 0x7376, 0x7028, 0xc084,
+	0x702a, 0x7007, 0x0001, 0x700f, 0x0000, 0xa006, 0x0e7f, 0x007c,
+	0x2b78, 0x2071, 0x88e1, 0x7004, 0x1079, 0x4826, 0x700c, 0x0079,
+	0x47d1, 0x47d6, 0x47cb, 0x47cb, 0x47cb, 0x47cb, 0x007c, 0x700c,
+	0x0079, 0x47da, 0x47df, 0x4824, 0x4824, 0x4825, 0x4825, 0x7830,
+	0x7930, 0xa106, 0x0040, 0x47e9, 0x7830, 0x7930, 0xa106, 0x00c0,
+	0x480f, 0x7030, 0xa10a, 0x0040, 0x480f, 0x00c8, 0x47f1, 0x712c,
+	0xa10a, 0xa18a, 0x0002, 0x00c8, 0x4810, 0x1078, 0x1310, 0x0040,
+	0x480f, 0x2d00, 0x705a, 0x7063, 0x0040, 0x2001, 0x0003, 0x7057,
+	0x0000, 0x127e, 0x007e, 0x2091, 0x8000, 0x2009, 0x8ac7, 0x2104,
+	0xc085, 0x200a, 0x007f, 0x700e, 0x127f, 0x1078, 0x1395, 0x007c,
+	0x1078, 0x1310, 0x0040, 0x480f, 0x2d00, 0x705a, 0x1078, 0x1310,
+	0x00c0, 0x481c, 0x0078, 0x47fb, 0x2d00, 0x7086, 0x7063, 0x0080,
+	0x2001, 0x0004, 0x0078, 0x47ff, 0x007c, 0x007c, 0x4837, 0x4838,
+	0x486f, 0x4870, 0x4824, 0x48a6, 0x48ab, 0x48e2, 0x48e3, 0x48fe,
+	0x48ff, 0x4900, 0x4901, 0x4902, 0x4903, 0x496c, 0x4996, 0x007c,
+	0x700c, 0x0079, 0x483b, 0x4840, 0x4843, 0x4853, 0x486e, 0x486e,
+	0x1078, 0x47d7, 0x007c, 0x127e, 0x8001, 0x700e, 0x7058, 0x007e,
+	0x1078, 0x4c96, 0x0040, 0x4850, 0x2091, 0x8000, 0x1078, 0x47d7,
+	0x0d7f, 0x0078, 0x485c, 0x127e, 0x8001, 0x700e, 0x1078, 0x4c96,
+	0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000,
+	0x6834, 0xa084, 0x00ff, 0xa08a, 0x0020, 0x00c8, 0x486b, 0x1079,
+	0x4886, 0x127f, 0x007c, 0x127f, 0x1078, 0x4904, 0x007c, 0x007c,
+	0x007c, 0x0e7e, 0x2071, 0x88e1, 0x700c, 0x0079, 0x4877, 0x487c,
+	0x487c, 0x487c, 0x487e, 0x4882, 0x0e7f, 0x007c, 0x700f, 0x0001,
+	0x0078, 0x4884, 0x700f, 0x0002, 0x0e7f, 0x007c, 0x4904, 0x4904,
+	0x4920, 0x4904, 0x4a0b, 0x4904, 0x4904, 0x4904, 0x4904, 0x4904,
+	0x4920, 0x4a55, 0x4aa2, 0x4afb, 0x4b11, 0x4904, 0x4904, 0x493c,
+	0x4920, 0x4904, 0x4904, 0x4952, 0x4bac, 0x4bca, 0x4904, 0x493c,
+	0x4904, 0x4904, 0x4904, 0x4904, 0x4952, 0x4bca, 0x7020, 0x2068,
+	0x1078, 0x1344, 0x007c, 0x700c, 0x0079, 0x48ae, 0x48b3, 0x48b6,
+	0x48c6, 0x48e1, 0x48e1, 0x1078, 0x47d7, 0x007c, 0x127e, 0x8001,
+	0x700e, 0x7058, 0x007e, 0x1078, 0x4c96, 0x0040, 0x48c3, 0x2091,
+	0x8000, 0x1078, 0x47d7, 0x0d7f, 0x0078, 0x48cf, 0x127e, 0x8001,
+	0x700e, 0x1078, 0x4c96, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803,
+	0x0000, 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x001a,
+	0x00c8, 0x48de, 0x1079, 0x48e4, 0x127f, 0x007c, 0x127f, 0x1078,
+	0x4904, 0x007c, 0x007c, 0x007c, 0x4904, 0x4920, 0x49f5, 0x4904,
+	0x4920, 0x4904, 0x4920, 0x4920, 0x4904, 0x4920, 0x49f5, 0x4920,
+	0x4920, 0x4920, 0x4920, 0x4920, 0x4904, 0x4920, 0x49f5, 0x4904,
+	0x4904, 0x4920, 0x4904, 0x4904, 0x4904, 0x4920, 0x007c, 0x007c,
+	0x007c, 0x007c, 0x007c, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084,
+	0x00ff, 0xc0d5, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x4376,
+	0x127f, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0e5,
+	0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x4376, 0x127f, 0x007c,
+	0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0ed, 0x683a, 0x127e,
+	0x2091, 0x8000, 0x1078, 0x4376, 0x127f, 0x007c, 0x7007, 0x0001,
+	0x6838, 0xa084, 0x00ff, 0xc0dd, 0x683a, 0x127e, 0x2091, 0x8000,
+	0x1078, 0x4376, 0x127f, 0x007c, 0x6834, 0x8007, 0xa084, 0x00ff,
+	0x0040, 0x4912, 0x8001, 0x00c0, 0x4949, 0x7007, 0x0001, 0x0078,
+	0x49d2, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b,
+	0x49d2, 0x007c, 0x2d00, 0x7016, 0x701a, 0x20a9, 0x0004, 0xa080,
+	0x0024, 0x2098, 0x20a1, 0x890c, 0x53a3, 0x6858, 0x7012, 0xa082,
+	0x0401, 0x00c8, 0x492e, 0x6884, 0xa08a, 0x0003, 0x00c8, 0x492e,
+	0xa080, 0x49c3, 0x2004, 0x70c6, 0x7010, 0xa015, 0x0040, 0x49b6,
+	0x1078, 0x1310, 0x00c0, 0x4977, 0x7007, 0x000f, 0x007c, 0x2d00,
+	0x7022, 0x70c4, 0x2060, 0x6000, 0x6836, 0x6004, 0xad00, 0x7096,
+	0x6008, 0xa20a, 0x00c8, 0x4986, 0xa00e, 0x2200, 0x7112, 0x620c,
+	0x8003, 0x800b, 0xa296, 0x0004, 0x0040, 0x498f, 0xa108, 0x719a,
+	0x810b, 0x719e, 0xae90, 0x0022, 0x1078, 0x137b, 0x7090, 0xa08e,
+	0x0100, 0x0040, 0x49aa, 0xa086, 0x0200, 0x0040, 0x49a2, 0x7007,
+	0x0010, 0x007c, 0x7020, 0x2068, 0x1078, 0x1344, 0x7014, 0x2068,
+	0x0078, 0x492e, 0x7020, 0x2068, 0x7018, 0x6802, 0x6807, 0x0000,
+	0x2d08, 0x2068, 0x6906, 0x711a, 0x0078, 0x496c, 0x7014, 0x2068,
+	0x7007, 0x0001, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x0040,
+	0x4be7, 0x0078, 0x49d2, 0x49c6, 0x49ca, 0x49ce, 0x0002, 0x0011,
+	0x0007, 0x0004, 0x000a, 0x000f, 0x0005, 0x0006, 0x0012, 0x000f,
+	0x0005, 0x0006, 0x2009, 0x882d, 0x210c, 0x81ff, 0x00c0, 0x49ef,
+	0x6838, 0xa084, 0x00ff, 0x683a, 0x6853, 0x0000, 0x1078, 0x3d8b,
+	0x00c0, 0x49e3, 0x007c, 0x1078, 0x4454, 0x127e, 0x2091, 0x8000,
+	0x1078, 0x7a46, 0x1078, 0x4376, 0x127f, 0x0078, 0x49e2, 0x2001,
+	0x0028, 0x2009, 0x0000, 0x0078, 0x49e3, 0x7018, 0x6802, 0x2d08,
+	0x2068, 0x6906, 0x711a, 0x7010, 0x8001, 0x7012, 0x0040, 0x4a04,
+	0x7007, 0x0006, 0x0078, 0x4a0a, 0x7014, 0x2068, 0x7007, 0x0001,
+	0x7048, 0x107a, 0x007c, 0x7007, 0x0001, 0x6944, 0x810f, 0xa18c,
+	0x00ff, 0x6848, 0xa084, 0x00ff, 0x20a9, 0x0001, 0xa096, 0x0001,
+	0x0040, 0x4a34, 0x2009, 0x0000, 0x20a9, 0x007e, 0xa096, 0x0002,
+	0x0040, 0x4a34, 0xa005, 0x00c0, 0x4a47, 0x6944, 0x810f, 0xa18c,
+	0x00ff, 0x1078, 0x3f8e, 0x00c0, 0x4a47, 0x067e, 0x6e50, 0x1078,
+	0x4057, 0x067f, 0x0078, 0x4a47, 0x047e, 0x2011, 0x880c, 0x2224,
+	0xc484, 0xc48c, 0x2412, 0x047f, 0x0c7e, 0x1078, 0x3f8e, 0x00c0,
+	0x4a43, 0x1078, 0x41ea, 0x8108, 0x00f0, 0x4a3d, 0x0c7f, 0x684c,
+	0xd084, 0x00c0, 0x4a4e, 0x1078, 0x1344, 0x007c, 0x127e, 0x2091,
+	0x8000, 0x1078, 0x4376, 0x127f, 0x007c, 0x127e, 0x2091, 0x8000,
+	0x7007, 0x0001, 0x2001, 0x8852, 0x2004, 0xd0a4, 0x0040, 0x4a99,
+	0x2061, 0x8b24, 0x6100, 0xd184, 0x0040, 0x4a79, 0x6858, 0xa084,
+	0x00ff, 0x00c0, 0x4a9c, 0x6000, 0xd084, 0x0040, 0x4a99, 0x6004,
+	0xa005, 0x00c0, 0x4a9f, 0x6003, 0x0000, 0x600b, 0x0000, 0x0078,
+	0x4a96, 0x2011, 0x0001, 0x6860, 0xa005, 0x00c0, 0x4a81, 0x2001,
+	0x001e, 0x8000, 0x6016, 0x6858, 0xa084, 0x00ff, 0x0040, 0x4a99,
+	0x6006, 0x6858, 0x8007, 0xa084, 0x00ff, 0x0040, 0x4a99, 0x600a,
+	0x6858, 0x8000, 0x00c0, 0x4a95, 0xc28d, 0x6202, 0x127f, 0x0078,
+	0x4c85, 0x127f, 0x0078, 0x4c7d, 0x127f, 0x0078, 0x4c75, 0x127f,
+	0x0078, 0x4c79, 0x127e, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001,
+	0x8852, 0x2004, 0xd0a4, 0x0040, 0x4af8, 0x2061, 0x8b24, 0x6000,
+	0xd084, 0x0040, 0x4af8, 0x6204, 0x6308, 0xd08c, 0x00c0, 0x4aea,
+	0x6c48, 0xa484, 0x0003, 0x0040, 0x4ad0, 0x6958, 0xa18c, 0x00ff,
+	0x8001, 0x00c0, 0x4ac9, 0x2100, 0xa210, 0x0048, 0x4af5, 0x0078,
+	0x4ad0, 0x8001, 0x00c0, 0x4af5, 0x2100, 0xa212, 0x0048, 0x4af5,
+	0xa484, 0x000c, 0x0040, 0x4aea, 0x6958, 0x810f, 0xa18c, 0x00ff,
+	0xa082, 0x0004, 0x00c0, 0x4ae2, 0x2100, 0xa318, 0x0048, 0x4af5,
+	0x0078, 0x4aea, 0xa082, 0x0004, 0x00c0, 0x4af5, 0x2100, 0xa31a,
+	0x0048, 0x4af5, 0x6860, 0xa005, 0x0040, 0x4af0, 0x8000, 0x6016,
+	0x6206, 0x630a, 0x127f, 0x0078, 0x4c85, 0x127f, 0x0078, 0x4c81,
+	0x127f, 0x0078, 0x4c7d, 0x127e, 0x2091, 0x8000, 0x7007, 0x0001,
+	0x2061, 0x8b24, 0x6300, 0xd38c, 0x00c0, 0x4b0b, 0x6308, 0x8318,
+	0x0048, 0x4b0e, 0x630a, 0x127f, 0x0078, 0x4c93, 0x127f, 0x0078,
+	0x4c81, 0x127e, 0x0c7e, 0x2091, 0x8000, 0x7007, 0x0001, 0x684c,
+	0xd0ac, 0x0040, 0x4b25, 0x0c7e, 0x2061, 0x8b24, 0x6000, 0xa084,
+	0xfcff, 0x6002, 0x0c7f, 0x0078, 0x4b68, 0x6858, 0xa005, 0x0040,
+	0x4b7f, 0x685c, 0xa065, 0x0040, 0x4b7b, 0x2001, 0x882d, 0x2004,
+	0xa005, 0x0040, 0x4b37, 0x1078, 0x79a8, 0x0078, 0x4b45, 0x6013,
+	0x0400, 0x6027, 0x0000, 0x694c, 0xd1a4, 0x0040, 0x4b41, 0x6950,
+	0x6126, 0x2009, 0x0041, 0x1078, 0x6939, 0x6958, 0xa18c, 0xff00,
+	0xa186, 0x2000, 0x0040, 0x4b60, 0xa186, 0x0400, 0x0040, 0x4b60,
+	0xa186, 0x1000, 0x0040, 0x4b56, 0x0078, 0x4b68, 0x0c7e, 0x2061,
+	0x8b24, 0x6000, 0xa084, 0xfdff, 0x6002, 0x0c7f, 0x0078, 0x4b68,
+	0x027e, 0x2009, 0x0000, 0x2011, 0xfdff, 0x1078, 0x5243, 0x027f,
+	0x684c, 0xd0c4, 0x0040, 0x4b77, 0x2061, 0x8b24, 0x6000, 0xd08c,
+	0x00c0, 0x4b77, 0x6008, 0x8000, 0x0048, 0x4b7b, 0x600a, 0x0c7f,
+	0x127f, 0x0078, 0x4c85, 0x0c7f, 0x127f, 0x0078, 0x4c7d, 0x6954,
+	0xa186, 0x002a, 0x00c0, 0x4b8b, 0x2001, 0x880c, 0x200c, 0xc194,
+	0x2102, 0x0078, 0x4b68, 0xa186, 0x0020, 0x0040, 0x4ba4, 0xa186,
+	0x0029, 0x0040, 0x4b97, 0xa186, 0x002d, 0x00c0, 0x4b7b, 0x6944,
+	0xa18c, 0xff00, 0x810f, 0x1078, 0x3f8e, 0x00c0, 0x4b68, 0x6000,
+	0xc0e4, 0x6002, 0x0078, 0x4b68, 0x685c, 0xa065, 0x0040, 0x4b7b,
+	0x6017, 0x0014, 0x0078, 0x4b68, 0x2061, 0x8b24, 0x6000, 0xd084,
+	0x0040, 0x4bc6, 0xd08c, 0x00c0, 0x4c93, 0x2091, 0x8000, 0x6204,
+	0x8210, 0x0048, 0x4bc0, 0x6206, 0x2091, 0x8001, 0x0078, 0x4c93,
+	0x2091, 0x8001, 0x6853, 0x0016, 0x0078, 0x4c8c, 0x6853, 0x0007,
+	0x0078, 0x4c8c, 0x6834, 0x8007, 0xa084, 0x00ff, 0x00c0, 0x4bd4,
+	0x1078, 0x4912, 0x0078, 0x4be6, 0x2030, 0x8001, 0x00c0, 0x4bde,
+	0x7007, 0x0001, 0x1078, 0x4be7, 0x0078, 0x4be6, 0x7007, 0x0006,
+	0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x4be7, 0x007c, 0x0e7e,
+	0x127e, 0x2091, 0x8000, 0x2009, 0x882d, 0x210c, 0x81ff, 0x00c0,
+	0x4c67, 0x2009, 0x880c, 0x210c, 0xd194, 0x00c0, 0x4c71, 0x6848,
+	0x2070, 0xae82, 0x8f00, 0x0048, 0x4c57, 0x2001, 0x8815, 0x2004,
+	0xae02, 0x00c8, 0x4c57, 0x2061, 0x8b24, 0x6100, 0xa184, 0x0001,
+	0x0040, 0x4c3c, 0xa184, 0x0100, 0x00c0, 0x4c5b, 0xa184, 0x0200,
+	0x00c0, 0x4c5f, 0x601c, 0xa005, 0x00c0, 0x4c63, 0x711c, 0xa186,
+	0x0006, 0x00c0, 0x4c42, 0x7018, 0xa005, 0x0040, 0x4c67, 0x2004,
+	0xd0e4, 0x00c0, 0x4c6b, 0x6853, 0x0000, 0x6803, 0x0000, 0x2d08,
+	0x7010, 0xa005, 0x00c0, 0x4c33, 0x7112, 0x2e60, 0x1078, 0x5198,
+	0x127f, 0x0e7f, 0x007c, 0x2068, 0x6800, 0xa005, 0x00c0, 0x4c33,
+	0x6902, 0x127f, 0x0e7f, 0x007c, 0x127f, 0x0e7f, 0x6853, 0x0006,
+	0x0078, 0x4c8c, 0x6944, 0xa18c, 0xff00, 0x810f, 0x1078, 0x3f8e,
+	0x00c0, 0x4c6b, 0x6000, 0xd0e4, 0x00c0, 0x4c6b, 0x711c, 0xa186,
+	0x0007, 0x00c0, 0x4c57, 0x6853, 0x0002, 0x0078, 0x4c6d, 0x6853,
+	0x0008, 0x0078, 0x4c6d, 0x6853, 0x000e, 0x0078, 0x4c6d, 0x6853,
+	0x0017, 0x0078, 0x4c6d, 0x6853, 0x0035, 0x0078, 0x4c6d, 0x6853,
+	0x0028, 0x0078, 0x4c6d, 0x6853, 0x0029, 0x127f, 0x0e7f, 0x0078,
+	0x4c8c, 0x6853, 0x002a, 0x0078, 0x4c6d, 0x2009, 0x003e, 0x0078,
+	0x4c87, 0x2009, 0x0004, 0x0078, 0x4c87, 0x2009, 0x0006, 0x0078,
+	0x4c87, 0x2009, 0x0016, 0x0078, 0x4c87, 0x2009, 0x0001, 0x6854,
+	0xa084, 0xff00, 0xa105, 0x6856, 0x2091, 0x8000, 0x1078, 0x4376,
+	0x2091, 0x8001, 0x007c, 0x1078, 0x1344, 0x007c, 0x702c, 0x7130,
+	0x8108, 0xa102, 0x0048, 0x4ca3, 0xa00e, 0x7034, 0x7072, 0x7038,
+	0x7076, 0x0078, 0x4caf, 0x7070, 0xa080, 0x0040, 0x7072, 0x00c8,
+	0x4caf, 0x7074, 0xa081, 0x0000, 0x7076, 0xa085, 0x0001, 0x7932,
+	0x7132, 0x007c, 0x0d7e, 0x1078, 0x518f, 0x0d7f, 0x007c, 0x0d7e,
 	0x2011, 0x0004, 0x2204, 0xa085, 0x8002, 0x2012, 0x0d7f, 0x007c,
 	0x20e1, 0x0002, 0x3d08, 0x20e1, 0x2000, 0x3d00, 0xa084, 0x7000,
-	0x0040, 0x42a6, 0xa086, 0x1000, 0x00c0, 0x42c2, 0x20e1, 0x0004,
-	0x3d60, 0xd1bc, 0x00c0, 0x42ad, 0x3e60, 0xac84, 0x0007, 0x00c0,
-	0x42c2, 0xac82, 0x7e00, 0x0048, 0x42c2, 0x6854, 0xac02, 0x00c8,
-	0x42c2, 0x2009, 0x0047, 0x1078, 0x5d41, 0x7a1c, 0xd284, 0x00c0,
-	0x4298, 0x007c, 0xa016, 0x1078, 0x156a, 0x0078, 0x42bd, 0x157e,
+	0x0040, 0x4cce, 0xa086, 0x1000, 0x00c0, 0x4cea, 0x20e1, 0x0004,
+	0x3d60, 0xd1bc, 0x00c0, 0x4cd5, 0x3e60, 0xac84, 0x0003, 0x00c0,
+	0x4cea, 0xac82, 0x8f00, 0x0048, 0x4cea, 0x6854, 0xac02, 0x00c8,
+	0x4cea, 0x2009, 0x0047, 0x1078, 0x6939, 0x7a1c, 0xd284, 0x00c0,
+	0x4cc0, 0x007c, 0xa016, 0x1078, 0x1594, 0x0078, 0x4ce5, 0x157e,
 	0x137e, 0x147e, 0x20e1, 0x3000, 0x3d20, 0x3e28, 0xa584, 0x0070,
-	0x00c0, 0x42f0, 0xa484, 0x7000, 0xa086, 0x1000, 0x00c0, 0x42f0,
-	0x1078, 0x42fd, 0x0040, 0x42f0, 0x20e1, 0x3000, 0x7828, 0x7828,
-	0x1078, 0x431b, 0x147f, 0x137f, 0x157f, 0x2009, 0x793e, 0x2104,
-	0xa005, 0x00c0, 0x42ec, 0x007c, 0x1078, 0x4d96, 0x0078, 0x42eb,
-	0x1078, 0x7674, 0x1078, 0x42fd, 0x20e1, 0x3000, 0x7828, 0x7828,
-	0x147f, 0x137f, 0x157f, 0x0078, 0x42eb, 0xa484, 0x01ff, 0x687a,
-	0xa005, 0x0040, 0x430f, 0xa080, 0x001f, 0xa084, 0x03f8, 0x80ac,
-	0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x007c, 0x20a9,
-	0x000c, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0xa085,
-	0x0001, 0x0078, 0x430e, 0x7000, 0xa084, 0xff00, 0xa08c, 0xf000,
-	0x8007, 0xa196, 0x0000, 0x00c0, 0x4328, 0x0078, 0x449c, 0x007c,
-	0xa196, 0x2000, 0x00c0, 0x4339, 0x6900, 0xa18e, 0x0001, 0x00c0,
-	0x4335, 0x1078, 0x2ec1, 0x0078, 0x4327, 0x1078, 0x4341, 0x0078,
-	0x4327, 0xa196, 0x8000, 0x00c0, 0x4327, 0x1078, 0x4522, 0x0078,
-	0x4327, 0x0c7e, 0x7110, 0xa18c, 0xff00, 0x810f, 0xa196, 0x0001,
-	0x0040, 0x434e, 0xa196, 0x0023, 0x00c0, 0x4443, 0xa08e, 0x0023,
-	0x00c0, 0x437f, 0x1078, 0x4599, 0x0040, 0x4443, 0x7124, 0x610a,
-	0x7030, 0xa08e, 0x0200, 0x00c0, 0x4367, 0x7034, 0xa005, 0x00c0,
-	0x4443, 0x2009, 0x0015, 0x1078, 0x5d41, 0x0078, 0x4443, 0xa08e,
-	0x0210, 0x00c0, 0x4371, 0x2009, 0x0015, 0x1078, 0x5d41, 0x0078,
-	0x4443, 0xa08e, 0x0100, 0x00c0, 0x4443, 0x7034, 0xa005, 0x00c0,
-	0x4443, 0x2009, 0x0016, 0x1078, 0x5d41, 0x0078, 0x4443, 0xa08e,
-	0x0022, 0x00c0, 0x4443, 0x7030, 0xa08e, 0x0300, 0x00c0, 0x4390,
-	0x7034, 0xa005, 0x00c0, 0x4443, 0x2009, 0x0017, 0x0078, 0x440f,
-	0xa08e, 0x0500, 0x00c0, 0x439c, 0x7034, 0xa005, 0x00c0, 0x4443,
-	0x2009, 0x0018, 0x0078, 0x440f, 0xa08e, 0x2010, 0x00c0, 0x43a4,
-	0x2009, 0x0019, 0x0078, 0x440f, 0xa08e, 0x2110, 0x00c0, 0x43ac,
-	0x2009, 0x001a, 0x0078, 0x440f, 0xa08e, 0x5200, 0x00c0, 0x43b8,
-	0x7034, 0xa005, 0x00c0, 0x4443, 0x2009, 0x001b, 0x0078, 0x440f,
-	0xa08e, 0x5000, 0x00c0, 0x43c4, 0x7034, 0xa005, 0x00c0, 0x4443,
-	0x2009, 0x001c, 0x0078, 0x440f, 0xa08e, 0x1200, 0x00c0, 0x43d0,
-	0x7034, 0xa005, 0x00c0, 0x4443, 0x2009, 0x0024, 0x0078, 0x440f,
-	0xa08c, 0xff00, 0xa18e, 0x2400, 0x00c0, 0x43da, 0x2009, 0x002d,
-	0x0078, 0x440f, 0xa08c, 0xff00, 0xa18e, 0x5300, 0x00c0, 0x43e4,
-	0x2009, 0x002a, 0x0078, 0x440f, 0xa08e, 0x0f00, 0x00c0, 0x43ec,
-	0x2009, 0x0020, 0x0078, 0x440f, 0xa08e, 0x5300, 0x00c0, 0x43f2,
-	0x0078, 0x440d, 0xa08e, 0x6104, 0x00c0, 0x440d, 0x2011, 0x7c8d,
-	0x8208, 0x2204, 0xa082, 0x0004, 0x20a8, 0x95ac, 0x95ac, 0x2011,
-	0x8015, 0x211c, 0x8108, 0x2124, 0x1078, 0x2d59, 0x8108, 0x00f0,
-	0x43ff, 0x2009, 0x0023, 0x0078, 0x440f, 0x2009, 0x001d, 0x017e,
-	0x2011, 0x7c83, 0x2204, 0x8211, 0x220c, 0x1078, 0x207f, 0x00c0,
-	0x4445, 0x1078, 0x3811, 0x00c0, 0x4445, 0x6612, 0x6516, 0x86ff,
-	0x0040, 0x4435, 0x017f, 0x017e, 0xa186, 0x0017, 0x00c0, 0x4435,
-	0x6864, 0xa606, 0x00c0, 0x4435, 0x6868, 0xa506, 0xa084, 0xff00,
-	0x00c0, 0x4435, 0x6000, 0xc0f5, 0x6002, 0x0c7e, 0x1078, 0x5cb4,
-	0x0040, 0x4448, 0x017f, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a,
-	0x017f, 0x1078, 0x5d41, 0x0c7f, 0x007c, 0x017f, 0x0078, 0x4443,
-	0x0c7f, 0x0078, 0x4445, 0x0e7e, 0x0d7e, 0x2028, 0x2130, 0xa696,
-	0x00ff, 0x00c0, 0x446b, 0xa596, 0xfffd, 0x00c0, 0x445b, 0x2009,
-	0x007f, 0x0078, 0x4498, 0xa596, 0xfffe, 0x00c0, 0x4463, 0x2009,
-	0x007e, 0x0078, 0x4498, 0xa596, 0xfffc, 0x00c0, 0x446b, 0x2009,
-	0x0080, 0x0078, 0x4498, 0x2011, 0x0000, 0x2021, 0x007e, 0x20a9,
-	0x0082, 0x2071, 0x789e, 0x2e1c, 0x83ff, 0x00c0, 0x447d, 0x82ff,
-	0x00c0, 0x448c, 0x2410, 0x0078, 0x448c, 0x2368, 0x6b10, 0x007e,
-	0x2100, 0xa31e, 0x007f, 0x00c0, 0x448c, 0x6b14, 0xa31e, 0x00c0,
-	0x448c, 0x2408, 0x0078, 0x4498, 0x8420, 0x8e70, 0x00f0, 0x4473,
-	0x82ff, 0x00c0, 0x4497, 0xa085, 0x0001, 0x0078, 0x4499, 0x2208,
-	0xa006, 0x0d7f, 0x0e7f, 0x007c, 0xa084, 0x0007, 0x0079, 0x44a1,
-	0x007c, 0x44a9, 0x44a9, 0x44a9, 0x44a9, 0x44a9, 0x44aa, 0x44c3,
-	0x450b, 0x007c, 0x7110, 0xd1bc, 0x0040, 0x44c2, 0x7120, 0x2160,
-	0xac8c, 0x0007, 0x00c0, 0x44c2, 0xac8a, 0x7e00, 0x0048, 0x44c2,
-	0x6854, 0xac02, 0x00c8, 0x44c2, 0x7124, 0x610a, 0x2009, 0x0046,
-	0x1078, 0x5d41, 0x007c, 0x0c7e, 0x7110, 0xd1bc, 0x00c0, 0x4509,
-	0x2011, 0x7c83, 0x2204, 0x8211, 0x220c, 0x1078, 0x207f, 0x00c0,
-	0x4509, 0x1078, 0x384c, 0x00c0, 0x4509, 0x6204, 0xa294, 0xff00,
-	0x8217, 0xa286, 0x0006, 0x00c0, 0x44ee, 0x0c7e, 0x1078, 0x5cb4,
-	0x017f, 0x0040, 0x4509, 0x611a, 0x601f, 0x0006, 0x7120, 0x610a,
-	0x2009, 0x0044, 0x1078, 0x5d41, 0x0078, 0x4509, 0x0c7e, 0x1078,
-	0x5cb4, 0x017f, 0x0040, 0x4509, 0x611a, 0x601f, 0x0004, 0x7120,
-	0x610a, 0xa286, 0x0004, 0x00c0, 0x4501, 0x6007, 0x0005, 0x0078,
-	0x4503, 0x6007, 0x0001, 0x6003, 0x0001, 0x1078, 0x498e, 0x1078,
-	0x4d96, 0x0c7f, 0x007c, 0x7110, 0xd1bc, 0x0040, 0x4521, 0x7020,
-	0x2060, 0xac84, 0x0007, 0x00c0, 0x4521, 0xac82, 0x7e00, 0x0048,
-	0x4521, 0x6854, 0xac02, 0x00c8, 0x4521, 0x2009, 0x0045, 0x1078,
-	0x5d41, 0x007c, 0x7110, 0xa18c, 0xff00, 0x810f, 0xa18e, 0x0000,
-	0x00c0, 0x4532, 0xa084, 0x000f, 0xa08a, 0x0006, 0x10c8, 0x12cd,
-	0x1079, 0x4533, 0x007c, 0x4539, 0x453a, 0x4539, 0x4539, 0x457b,
-	0x458a, 0x007c, 0x7110, 0xd1bc, 0x00c0, 0x457a, 0x700c, 0x7108,
-	0x1078, 0x207f, 0x00c0, 0x457a, 0x1078, 0x3811, 0x00c0, 0x457a,
-	0x6612, 0x6516, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006,
-	0x00c0, 0x4563, 0x0c7e, 0x1078, 0x5cb4, 0x017f, 0x0040, 0x457a,
-	0x611a, 0x601f, 0x0005, 0x7120, 0x610a, 0x2009, 0x0088, 0x1078,
-	0x5d41, 0x0078, 0x457a, 0x0c7e, 0x1078, 0x5cb4, 0x017f, 0x0040,
-	0x457a, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0xa286, 0x0004,
-	0x00c0, 0x4576, 0x2009, 0x0005, 0x0078, 0x4578, 0x2009, 0x0001,
-	0x1078, 0x5d41, 0x007c, 0x7110, 0xd1bc, 0x0040, 0x4589, 0x1078,
-	0x4599, 0x0040, 0x4589, 0x7124, 0x610a, 0x2009, 0x0089, 0x1078,
-	0x5d41, 0x007c, 0x7110, 0xd1bc, 0x0040, 0x4598, 0x1078, 0x4599,
-	0x0040, 0x4598, 0x7124, 0x610a, 0x2009, 0x008a, 0x1078, 0x5d41,
-	0x007c, 0x7020, 0x2060, 0xac84, 0x0007, 0x00c0, 0x45ac, 0xac82,
-	0x7e00, 0x0048, 0x45ac, 0x2001, 0x7715, 0x2004, 0xac02, 0x00c8,
-	0x45ac, 0xa085, 0x0001, 0x007c, 0xa006, 0x0078, 0x45ab, 0x2071,
-	0x7949, 0x7003, 0x0003, 0x700f, 0x0361, 0xa006, 0x701a, 0x7012,
-	0x7017, 0x7e00, 0x7007, 0x0000, 0x7026, 0x702b, 0x56a9, 0x7032,
-	0x7037, 0x56ea, 0x703b, 0x0002, 0x703f, 0x0000, 0x007c, 0x2071,
-	0x7949, 0x00e0, 0x4676, 0x2091, 0x6000, 0x700c, 0x8001, 0x700e,
-	0x00c0, 0x463f, 0x700f, 0x0361, 0x7007, 0x0001, 0x127e, 0x2091,
-	0x8000, 0x7138, 0x8109, 0x713a, 0x00c0, 0x463d, 0x703b, 0x0002,
-	0x2009, 0x0100, 0x2104, 0xa082, 0x0003, 0x00c8, 0x463d, 0x703c,
-	0xa086, 0x0001, 0x00c0, 0x461a, 0x0d7e, 0x2069, 0x0140, 0x6804,
-	0xa084, 0x4000, 0x0040, 0x45f8, 0x6803, 0x1000, 0x0078, 0x45ff,
-	0x6804, 0xa084, 0x1000, 0x0040, 0x45ff, 0x6803, 0x0100, 0x6803,
-	0x0000, 0x703f, 0x0000, 0x2069, 0x7936, 0x6804, 0xa082, 0x0006,
-	0x00c0, 0x460c, 0x6807, 0x0000, 0x6830, 0xa082, 0x0003, 0x00c0,
-	0x4613, 0x6833, 0x0000, 0x1078, 0x4d96, 0x1078, 0x4e56, 0x0d7f,
-	0x0078, 0x463d, 0x0d7e, 0x2069, 0x7700, 0x6944, 0x6860, 0xa102,
-	0x00c8, 0x463c, 0x2069, 0x7936, 0x6804, 0xa086, 0x0000, 0x00c0,
-	0x463c, 0x6830, 0xa086, 0x0000, 0x00c0, 0x463c, 0x703f, 0x0001,
-	0x6807, 0x0006, 0x6833, 0x0003, 0x2069, 0x0100, 0x6830, 0x689e,
-	0x2069, 0x0140, 0x6803, 0x0600, 0x0d7f, 0x0078, 0x4642, 0x127e,
-	0x2091, 0x8000, 0x7024, 0xa00d, 0x0040, 0x4653, 0x7020, 0x8001,
-	0x7022, 0x00c0, 0x4653, 0x7023, 0x0009, 0x8109, 0x7126, 0x00c0,
-	0x4653, 0x7028, 0x107a, 0x7030, 0xa00d, 0x0040, 0x4664, 0x702c,
-	0x8001, 0x702e, 0x00c0, 0x4664, 0x702f, 0x0009, 0x8109, 0x7132,
-	0x00c0, 0x4664, 0x7034, 0x107a, 0x7018, 0xa00d, 0x0040, 0x4675,
-	0x7008, 0x8001, 0x700a, 0x00c0, 0x4675, 0x700b, 0x0009, 0x8109,
-	0x711a, 0x00c0, 0x4675, 0x701c, 0x107a, 0x127f, 0x7004, 0x0079,
-	0x4679, 0x46a0, 0x46a1, 0x46bd, 0x0e7e, 0x2071, 0x7949, 0x7018,
-	0xa005, 0x00c0, 0x4687, 0x711a, 0x721e, 0x700b, 0x0009, 0x0e7f,
-	0x007c, 0x0e7e, 0x007e, 0x2071, 0x7949, 0x701c, 0xa206, 0x00c0,
-	0x4693, 0x701a, 0x701e, 0x007f, 0x0e7f, 0x007c, 0x0e7e, 0x2071,
-	0x7949, 0x6088, 0xa102, 0x0048, 0x469e, 0x618a, 0x0e7f, 0x007c,
-	0x007c, 0x7110, 0x1078, 0x384c, 0x00c0, 0x46b3, 0x6088, 0x8001,
-	0x0048, 0x46b3, 0x608a, 0x00c0, 0x46b3, 0x127e, 0x2091, 0x8000,
-	0x1078, 0x4d96, 0x127f, 0x8108, 0xa182, 0x00ff, 0x0048, 0x46bb,
-	0xa00e, 0x7007, 0x0002, 0x7112, 0x007c, 0x7014, 0x2060, 0x127e,
-	0x2091, 0x8000, 0x6014, 0xa005, 0x0040, 0x46ec, 0x8001, 0x6016,
-	0x00c0, 0x46ec, 0x611c, 0xa186, 0x0003, 0x0040, 0x46d3, 0xa186,
-	0x0006, 0x00c0, 0x46ea, 0x6010, 0x2068, 0x6854, 0xa08a, 0x199a,
-	0x0048, 0x46ea, 0xa082, 0x1999, 0x6856, 0xa08a, 0x199a, 0x0048,
-	0x46e3, 0x2001, 0x1999, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116,
-	0x0078, 0x46ec, 0x1078, 0x68e3, 0x127f, 0xac88, 0x0008, 0x7116,
-	0x2001, 0x7716, 0x2004, 0xa102, 0x0048, 0x46fa, 0x7017, 0x7e00,
-	0x7007, 0x0000, 0x007c, 0x0e7e, 0x2071, 0x7949, 0x7027, 0x07d0,
-	0x7023, 0x0009, 0x703b, 0x0002, 0x0e7f, 0x007c, 0x2001, 0x7952,
-	0x2003, 0x0000, 0x007c, 0x0e7e, 0x2071, 0x7949, 0x7033, 0x07d0,
-	0x702f, 0x0009, 0x0e7f, 0x007c, 0x2011, 0x7955, 0x2013, 0x0000,
-	0x007c, 0x0e7e, 0x2071, 0x7949, 0x711a, 0x721e, 0x700b, 0x0009,
-	0x0e7f, 0x007c, 0x0c7e, 0x2061, 0x79da, 0x0c7f, 0x007c, 0xa184,
-	0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x79da, 0x2060, 0x007c,
-	0x6854, 0xa08a, 0x199a, 0x0048, 0x4737, 0x2001, 0x1999, 0xa005,
-	0x00c0, 0x4747, 0x6944, 0x0c7e, 0x1078, 0x4727, 0x6014, 0x0c7f,
-	0xa005, 0x00c0, 0x474c, 0x2001, 0x001e, 0x0078, 0x474c, 0xa08e,
-	0xffff, 0x00c0, 0x474c, 0xa006, 0x8003, 0x800b, 0x810b, 0xa108,
-	0x6116, 0x684c, 0xa08c, 0x00c0, 0xa18e, 0x00c0, 0x0040, 0x4787,
-	0xd0b4, 0x00c0, 0x4763, 0xd0bc, 0x00c0, 0x4775, 0x2009, 0x0006,
-	0x1078, 0x47aa, 0x007c, 0xd0fc, 0x0040, 0x4770, 0xa084, 0x0003,
-	0xa08e, 0x0003, 0x0040, 0x47a3, 0xa08e, 0x0000, 0x00c0, 0x47a3,
-	0x2009, 0x0043, 0x1078, 0x5d41, 0x007c, 0xd0fc, 0x0040, 0x4782,
-	0xa084, 0x0003, 0xa08e, 0x0003, 0x0040, 0x47a3, 0xa08e, 0x0000,
-	0x00c0, 0x47a3, 0x2009, 0x0042, 0x1078, 0x5d41, 0x007c, 0xd0fc,
-	0x0040, 0x4799, 0xa084, 0x0003, 0xa08e, 0x0003, 0x0040, 0x47a3,
-	0xa08e, 0x0002, 0x0040, 0x479d, 0x2009, 0x0041, 0x1078, 0x5d41,
-	0x007c, 0x1078, 0x47a8, 0x0078, 0x4798, 0x2009, 0x0043, 0x1078,
-	0x5d41, 0x0078, 0x4798, 0x2009, 0x0004, 0x1078, 0x47aa, 0x007c,
-	0x2009, 0x0001, 0x6010, 0xa0ec, 0xf000, 0x0040, 0x47cf, 0x2068,
-	0x6952, 0x6800, 0x6012, 0xa186, 0x0001, 0x00c0, 0x47c9, 0x694c,
-	0xa18c, 0x8100, 0xa18e, 0x8100, 0x00c0, 0x47c9, 0x0c7e, 0x2009,
-	0x0000, 0x1078, 0x4727, 0x6204, 0x8210, 0x0048, 0x47c8, 0x6206,
-	0x0c7f, 0x1078, 0x3b92, 0x6010, 0xa06d, 0x10c0, 0x4730, 0x007c,
-	0x157e, 0x0c7e, 0x20a9, 0x0010, 0x2061, 0x79da, 0x6000, 0x81ff,
-	0x0040, 0x47dd, 0xa205, 0x0078, 0x47de, 0xa204, 0x6002, 0xace0,
-	0x0008, 0x00f0, 0x47d6, 0x0c7f, 0x157f, 0x007c, 0x6808, 0xa005,
-	0x0040, 0x47ee, 0x8001, 0x680a, 0xa085, 0x0001, 0x007c, 0x127e,
-	0x2091, 0x2200, 0x2079, 0x7936, 0x127f, 0x0d7e, 0x2069, 0x7936,
-	0x6803, 0x0005, 0x2069, 0x0004, 0x2d04, 0xa085, 0x8001, 0x206a,
-	0x0d7f, 0x007c, 0x0c7e, 0x6027, 0x0001, 0x7804, 0xa084, 0x0007,
-	0x0079, 0x480a, 0x4814, 0x4839, 0x4894, 0x481a, 0x4839, 0x4812,
-	0x4812, 0x4812, 0x1078, 0x12cd, 0x1078, 0x4706, 0x1078, 0x4d96,
-	0x0c7f, 0x007c, 0x62c0, 0x82ff, 0x00c0, 0x4820, 0x0c7f, 0x007c,
-	0x2011, 0x3558, 0x1078, 0x4689, 0x7828, 0xa092, 0x0002, 0x00c8,
-	0x482f, 0x8000, 0x782a, 0x1078, 0x3588, 0x0078, 0x481e, 0x1078,
-	0x3558, 0x7807, 0x0003, 0x7827, 0x0000, 0x782b, 0x0000, 0x0078,
-	0x481e, 0x1078, 0x4706, 0x3c00, 0x007e, 0x2011, 0x0209, 0x20e1,
-	0x4000, 0x2214, 0x007f, 0x20e0, 0x82ff, 0x0040, 0x4857, 0x62c0,
-	0x82ff, 0x00c0, 0x4857, 0x782b, 0x0000, 0x7824, 0xa065, 0x1040,
-	0x12cd, 0x2009, 0x0013, 0x1078, 0x5d41, 0x0c7f, 0x007c, 0x3900,
-	0xa082, 0x7a7a, 0x00c8, 0x485e, 0x1078, 0x5c44, 0x0c7e, 0x7824,
-	0xa065, 0x1040, 0x12cd, 0x7804, 0xa086, 0x0004, 0x0040, 0x48d9,
-	0x7828, 0xa092, 0x2710, 0x00c8, 0x4874, 0x8000, 0x782a, 0x0c7f,
-	0x1078, 0x568e, 0x0078, 0x4855, 0x6104, 0xa186, 0x0003, 0x00c0,
-	0x488b, 0x0e7e, 0x2071, 0x7700, 0x70c8, 0x0e7f, 0xd08c, 0x0040,
-	0x488b, 0x0c7e, 0x0e7e, 0x2061, 0x0100, 0x2071, 0x7700, 0x1078,
-	0x3591, 0x0e7f, 0x0c7f, 0x1078, 0x76c7, 0x2009, 0x0014, 0x1078,
-	0x5d41, 0x0c7f, 0x0078, 0x4855, 0x2001, 0x7952, 0x2003, 0x0000,
-	0x62c0, 0x82ff, 0x00c0, 0x48a8, 0x782b, 0x0000, 0x7824, 0xa065,
-	0x1040, 0x12cd, 0x2009, 0x0013, 0x1078, 0x5d8f, 0x0c7f, 0x007c,
-	0x0c7e, 0x0d7e, 0x3900, 0xa082, 0x7a7a, 0x00c8, 0x48b1, 0x1078,
-	0x5c44, 0x7824, 0xa005, 0x1040, 0x12cd, 0x781c, 0xa06d, 0x1040,
-	0x12cd, 0x6800, 0xc0dc, 0x6802, 0x7924, 0x2160, 0x1078, 0x5d1a,
-	0x693c, 0x81ff, 0x1040, 0x12cd, 0x8109, 0x693e, 0x6854, 0xa015,
-	0x0040, 0x48cd, 0x7a1e, 0x0078, 0x48cf, 0x7918, 0x791e, 0x7807,
-	0x0000, 0x7827, 0x0000, 0x0d7f, 0x0c7f, 0x1078, 0x4d96, 0x0078,
-	0x48a6, 0x6104, 0xa186, 0x0002, 0x0040, 0x48e4, 0xa186, 0x0004,
-	0x0040, 0x48e4, 0x0078, 0x4868, 0x7808, 0xac06, 0x0040, 0x4868,
-	0x1078, 0x4c9d, 0x1078, 0x498e, 0x0c7f, 0x1078, 0x4d96, 0x0078,
-	0x4855, 0x0c7e, 0x6027, 0x0002, 0x2011, 0x7955, 0x2013, 0x0000,
-	0x62c8, 0x82ff, 0x00c0, 0x490b, 0x62c4, 0x82ff, 0x00c0, 0x490b,
-	0x793c, 0xa1e5, 0x0000, 0x0040, 0x4909, 0x2009, 0x0049, 0x1078,
-	0x5d41, 0x0c7f, 0x007c, 0x3908, 0xa192, 0x7a7a, 0x00c8, 0x4912,
-	0x1078, 0x5c44, 0x6017, 0x0010, 0x793c, 0x81ff, 0x0040, 0x4909,
-	0x7944, 0xa192, 0x7530, 0x00c8, 0x4931, 0x8108, 0x7946, 0x1078,
-	0x470b, 0x793c, 0xa188, 0x0007, 0x210c, 0xa18e, 0x0006, 0x00c0,
-	0x492d, 0x6017, 0x0012, 0x0078, 0x4909, 0x6017, 0x0016, 0x0078,
-	0x4909, 0x037e, 0x2019, 0x0001, 0x1078, 0x5880, 0x037f, 0x1078,
-	0x76c7, 0x793c, 0x2160, 0x2009, 0x004a, 0x1078, 0x5d41, 0x0078,
-	0x4909, 0x007e, 0x017e, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x600f,
-	0x0000, 0x2c08, 0x2061, 0x7936, 0x6020, 0x8000, 0x6022, 0x6010,
-	0xa005, 0x0040, 0x495c, 0xa080, 0x0003, 0x2102, 0x6112, 0x127f,
-	0x0c7f, 0x017f, 0x007f, 0x007c, 0x6116, 0x6112, 0x0078, 0x4957,
-	0x0d7e, 0x2069, 0x7936, 0x6000, 0xd0d4, 0x0040, 0x4975, 0x6820,
-	0x8000, 0x6822, 0xa086, 0x0001, 0x00c0, 0x4970, 0x2c00, 0x681e,
-	0x6804, 0xa084, 0x0007, 0x0079, 0x4d9e, 0xc0d5, 0x6002, 0x6818,
-	0xa005, 0x0040, 0x4987, 0x6056, 0x605b, 0x0000, 0x007e, 0x2c00,
-	0x681a, 0x0d7f, 0x685a, 0x2069, 0x7936, 0x0078, 0x4967, 0x6056,
-	0x605a, 0x2c00, 0x681a, 0x681e, 0x0078, 0x4967, 0x007e, 0x017e,
+	0x00c0, 0x4d31, 0xa484, 0x7000, 0xa086, 0x1000, 0x00c0, 0x4d20,
+	0xa584, 0x0007, 0xd094, 0x00c0, 0x4d31, 0xd09c, 0x00c0, 0x4d31,
+	0x1078, 0x4d4a, 0x0040, 0x4d31, 0x20e1, 0x3000, 0x7828, 0x7828,
+	0x1078, 0x4d68, 0x147f, 0x137f, 0x157f, 0x2009, 0x8aaa, 0x2104,
+	0xa005, 0x00c0, 0x4d1c, 0x007c, 0x1078, 0x5888, 0x0078, 0x4d1b,
+	0xa484, 0x7000, 0x00c0, 0x4d31, 0x1078, 0x4d4a, 0x0040, 0x4d41,
+	0x7000, 0xa084, 0xff00, 0xa086, 0x8100, 0x0040, 0x4d0c, 0x0078,
+	0x4d41, 0x1078, 0x872e, 0xd5a4, 0x0040, 0x4d3f, 0x1078, 0x19e5,
+	0x20e1, 0x9010, 0x2001, 0x0138, 0x2202, 0x0078, 0x4d45, 0x1078,
+	0x4d4a, 0x20e1, 0x3000, 0x7828, 0x7828, 0x147f, 0x137f, 0x157f,
+	0x0078, 0x4d1b, 0xa484, 0x01ff, 0x687e, 0xa005, 0x0040, 0x4d5c,
+	0xa080, 0x001f, 0xa084, 0x03f8, 0x80ac, 0x20e1, 0x1000, 0x2ea0,
+	0x2099, 0x020a, 0x53a5, 0x007c, 0x20a9, 0x000c, 0x20e1, 0x1000,
+	0x2ea0, 0x2099, 0x020a, 0x53a5, 0xa085, 0x0001, 0x0078, 0x4d5b,
+	0x7000, 0xa084, 0xff00, 0xa08c, 0xf000, 0x8007, 0xa196, 0x0000,
+	0x00c0, 0x4d75, 0x0078, 0x4eef, 0x007c, 0xa196, 0x2000, 0x00c0,
+	0x4d86, 0x6900, 0xa18e, 0x0001, 0x00c0, 0x4d82, 0x1078, 0x3541,
+	0x0078, 0x4d74, 0x1078, 0x4d8e, 0x0078, 0x4d74, 0xa196, 0x8000,
+	0x00c0, 0x4d74, 0x1078, 0x4f7b, 0x0078, 0x4d74, 0x0c7e, 0x7110,
+	0xa18c, 0xff00, 0x810f, 0xa196, 0x0001, 0x0040, 0x4d9b, 0xa196,
+	0x0023, 0x00c0, 0x4e90, 0xa08e, 0x0023, 0x00c0, 0x4dcc, 0x1078,
+	0x4fee, 0x0040, 0x4e90, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200,
+	0x00c0, 0x4db4, 0x7034, 0xa005, 0x00c0, 0x4e90, 0x2009, 0x0015,
+	0x1078, 0x6939, 0x0078, 0x4e90, 0xa08e, 0x0210, 0x00c0, 0x4dbe,
+	0x2009, 0x0015, 0x1078, 0x6939, 0x0078, 0x4e90, 0xa08e, 0x0100,
+	0x00c0, 0x4e90, 0x7034, 0xa005, 0x00c0, 0x4e90, 0x2009, 0x0016,
+	0x1078, 0x6939, 0x0078, 0x4e90, 0xa08e, 0x0022, 0x00c0, 0x4e90,
+	0x7030, 0xa08e, 0x0300, 0x00c0, 0x4ddd, 0x7034, 0xa005, 0x00c0,
+	0x4e90, 0x2009, 0x0017, 0x0078, 0x4e5c, 0xa08e, 0x0500, 0x00c0,
+	0x4de9, 0x7034, 0xa005, 0x00c0, 0x4e90, 0x2009, 0x0018, 0x0078,
+	0x4e5c, 0xa08e, 0x2010, 0x00c0, 0x4df1, 0x2009, 0x0019, 0x0078,
+	0x4e5c, 0xa08e, 0x2110, 0x00c0, 0x4df9, 0x2009, 0x001a, 0x0078,
+	0x4e5c, 0xa08e, 0x5200, 0x00c0, 0x4e05, 0x7034, 0xa005, 0x00c0,
+	0x4e90, 0x2009, 0x001b, 0x0078, 0x4e5c, 0xa08e, 0x5000, 0x00c0,
+	0x4e11, 0x7034, 0xa005, 0x00c0, 0x4e90, 0x2009, 0x001c, 0x0078,
+	0x4e5c, 0xa08e, 0x1200, 0x00c0, 0x4e1d, 0x7034, 0xa005, 0x00c0,
+	0x4e90, 0x2009, 0x0024, 0x0078, 0x4e5c, 0xa08c, 0xff00, 0xa18e,
+	0x2400, 0x00c0, 0x4e27, 0x2009, 0x002d, 0x0078, 0x4e5c, 0xa08c,
+	0xff00, 0xa18e, 0x5300, 0x00c0, 0x4e31, 0x2009, 0x002a, 0x0078,
+	0x4e5c, 0xa08e, 0x0f00, 0x00c0, 0x4e39, 0x2009, 0x0020, 0x0078,
+	0x4e5c, 0xa08e, 0x5300, 0x00c0, 0x4e3f, 0x0078, 0x4e5a, 0xa08e,
+	0x6104, 0x00c0, 0x4e5a, 0x2011, 0x8d8d, 0x8208, 0x2204, 0xa082,
+	0x0004, 0x20a8, 0x95ac, 0x95ac, 0x2011, 0x8015, 0x211c, 0x8108,
+	0x2124, 0x1078, 0x317a, 0x8108, 0x00f0, 0x4e4c, 0x2009, 0x0023,
+	0x0078, 0x4e5c, 0x2009, 0x001d, 0x017e, 0x2011, 0x8d83, 0x2204,
+	0x8211, 0x220c, 0x1078, 0x2245, 0x00c0, 0x4e92, 0x1078, 0x3f53,
+	0x00c0, 0x4e92, 0x6612, 0x6516, 0x86ff, 0x0040, 0x4e82, 0x017f,
+	0x017e, 0xa186, 0x0017, 0x00c0, 0x4e82, 0x6868, 0xa606, 0x00c0,
+	0x4e82, 0x686c, 0xa506, 0xa084, 0xff00, 0x00c0, 0x4e82, 0x6000,
+	0xc0f5, 0x6002, 0x0c7e, 0x1078, 0x68a8, 0x0040, 0x4e95, 0x017f,
+	0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0x017f, 0x1078, 0x6939,
+	0x0c7f, 0x007c, 0x017f, 0x0078, 0x4e90, 0x0c7f, 0x0078, 0x4e92,
+	0x0e7e, 0x0d7e, 0x2028, 0x2130, 0xa696, 0x00ff, 0x00c0, 0x4eb8,
+	0xa596, 0xfffd, 0x00c0, 0x4ea8, 0x2009, 0x007f, 0x0078, 0x4eeb,
+	0xa596, 0xfffe, 0x00c0, 0x4eb0, 0x2009, 0x007e, 0x0078, 0x4eeb,
+	0xa596, 0xfffc, 0x00c0, 0x4eb8, 0x2009, 0x0080, 0x0078, 0x4eeb,
+	0x2011, 0x0000, 0x2021, 0x0081, 0x20a9, 0x007e, 0x2071, 0x89b5,
+	0x2e1c, 0x83ff, 0x00c0, 0x4eca, 0x82ff, 0x00c0, 0x4edf, 0x2410,
+	0x0078, 0x4edf, 0x2368, 0x6f10, 0x007e, 0x2100, 0xa706, 0x007f,
+	0x6b14, 0x00c0, 0x4ed9, 0xa346, 0x00c0, 0x4ed9, 0x2408, 0x0078,
+	0x4eeb, 0x87ff, 0x00c0, 0x4edf, 0x83ff, 0x0040, 0x4ec4, 0x8420,
+	0x8e70, 0x00f0, 0x4ec0, 0x82ff, 0x00c0, 0x4eea, 0xa085, 0x0001,
+	0x0078, 0x4eec, 0x2208, 0xa006, 0x0d7f, 0x0e7f, 0x007c, 0xa084,
+	0x0007, 0x0079, 0x4ef4, 0x007c, 0x4efc, 0x4efc, 0x4efc, 0x4efc,
+	0x4efc, 0x4efd, 0x4f16, 0x4f64, 0x007c, 0x7110, 0xd1bc, 0x0040,
+	0x4f15, 0x7120, 0x2160, 0xac8c, 0x0003, 0x00c0, 0x4f15, 0xac8a,
+	0x8f00, 0x0048, 0x4f15, 0x6854, 0xac02, 0x00c8, 0x4f15, 0x7124,
+	0x610a, 0x2009, 0x0046, 0x1078, 0x6939, 0x007c, 0x0c7e, 0x7110,
+	0xd1bc, 0x00c0, 0x4f62, 0x2011, 0x8d83, 0x2204, 0x8211, 0x220c,
+	0x1078, 0x2245, 0x00c0, 0x4f62, 0x1078, 0x3f8e, 0x00c0, 0x4f62,
+	0x6000, 0xd0ec, 0x00c0, 0x4f62, 0x6204, 0xa294, 0xff00, 0x8217,
+	0xa286, 0x0006, 0x00c0, 0x4f47, 0x0c7e, 0x1078, 0x68a8, 0x017f,
+	0x0040, 0x4f62, 0x611a, 0x601f, 0x0006, 0x7120, 0x610a, 0x7130,
+	0x6122, 0x2009, 0x0044, 0x1078, 0x6939, 0x0078, 0x4f62, 0x0c7e,
+	0x1078, 0x68a8, 0x017f, 0x0040, 0x4f62, 0x611a, 0x601f, 0x0004,
+	0x7120, 0x610a, 0xa286, 0x0004, 0x00c0, 0x4f5a, 0x6007, 0x0005,
+	0x0078, 0x4f5c, 0x6007, 0x0001, 0x6003, 0x0001, 0x1078, 0x53e6,
+	0x1078, 0x5888, 0x0c7f, 0x007c, 0x7110, 0xd1bc, 0x0040, 0x4f7a,
+	0x7020, 0x2060, 0xac84, 0x0003, 0x00c0, 0x4f7a, 0xac82, 0x8f00,
+	0x0048, 0x4f7a, 0x6854, 0xac02, 0x00c8, 0x4f7a, 0x2009, 0x0045,
+	0x1078, 0x6939, 0x007c, 0x7110, 0xa18c, 0xff00, 0x810f, 0xa18e,
+	0x0000, 0x00c0, 0x4f8b, 0xa084, 0x000f, 0xa08a, 0x0006, 0x10c8,
+	0x12d2, 0x1079, 0x4f8c, 0x007c, 0x4f92, 0x4f93, 0x4f92, 0x4f92,
+	0x4fd0, 0x4fdf, 0x007c, 0x7110, 0xd1bc, 0x00c0, 0x4fcf, 0x700c,
+	0x7108, 0x1078, 0x2245, 0x00c0, 0x4fcf, 0x1078, 0x3f53, 0x00c0,
+	0x4fcf, 0x6612, 0x6516, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286,
+	0x0004, 0x0040, 0x4faf, 0xa286, 0x0006, 0x00c0, 0x4fc0, 0x0c7e,
+	0x1078, 0x68a8, 0x017f, 0x0040, 0x4fcf, 0x611a, 0x601f, 0x0005,
+	0x7120, 0x610a, 0x2009, 0x0088, 0x1078, 0x6939, 0x0078, 0x4fcf,
+	0x0c7e, 0x1078, 0x68a8, 0x017f, 0x0040, 0x4fcf, 0x611a, 0x601f,
+	0x0004, 0x7120, 0x610a, 0x2009, 0x0001, 0x1078, 0x6939, 0x007c,
+	0x7110, 0xd1bc, 0x0040, 0x4fde, 0x1078, 0x4fee, 0x0040, 0x4fde,
+	0x7124, 0x610a, 0x2009, 0x0089, 0x1078, 0x6939, 0x007c, 0x7110,
+	0xd1bc, 0x0040, 0x4fed, 0x1078, 0x4fee, 0x0040, 0x4fed, 0x7124,
+	0x610a, 0x2009, 0x008a, 0x1078, 0x6939, 0x007c, 0x7020, 0x2060,
+	0xac84, 0x0003, 0x00c0, 0x5001, 0xac82, 0x8f00, 0x0048, 0x5001,
+	0x2001, 0x8815, 0x2004, 0xac02, 0x00c8, 0x5001, 0xa085, 0x0001,
+	0x007c, 0xa006, 0x0078, 0x5000, 0x2071, 0x8ab5, 0x7003, 0x0003,
+	0x700f, 0x0361, 0xa006, 0x701a, 0x7012, 0x7017, 0x8f00, 0x7007,
+	0x0000, 0x7026, 0x702b, 0x623f, 0x7032, 0x7037, 0x6280, 0x703b,
+	0x0002, 0x703f, 0x0000, 0x7043, 0xffff, 0x7047, 0xffff, 0x007c,
+	0x2071, 0x8ab5, 0x00e0, 0x50df, 0x2091, 0x6000, 0x700c, 0x8001,
+	0x700e, 0x00c0, 0x5098, 0x700f, 0x0361, 0x7007, 0x0001, 0x127e,
+	0x2091, 0x8000, 0x7138, 0x8109, 0x713a, 0x00c0, 0x5096, 0x703b,
+	0x0002, 0x2009, 0x0100, 0x2104, 0xa082, 0x0003, 0x00c8, 0x5096,
+	0x703c, 0xa086, 0x0001, 0x00c0, 0x5073, 0x0d7e, 0x2069, 0x0140,
+	0x6804, 0xa084, 0x4000, 0x0040, 0x5051, 0x6803, 0x1000, 0x0078,
+	0x5058, 0x6804, 0xa084, 0x1000, 0x0040, 0x5058, 0x6803, 0x0100,
+	0x6803, 0x0000, 0x703f, 0x0000, 0x2069, 0x8aa2, 0x6804, 0xa082,
+	0x0006, 0x00c0, 0x5065, 0x6807, 0x0000, 0x6830, 0xa082, 0x0003,
+	0x00c0, 0x506c, 0x6833, 0x0000, 0x1078, 0x5888, 0x1078, 0x5948,
+	0x0d7f, 0x0078, 0x5096, 0x0d7e, 0x2069, 0x8800, 0x6944, 0x6860,
+	0xa102, 0x00c8, 0x5095, 0x2069, 0x8aa2, 0x6804, 0xa086, 0x0000,
+	0x00c0, 0x5095, 0x6830, 0xa086, 0x0000, 0x00c0, 0x5095, 0x703f,
+	0x0001, 0x6807, 0x0006, 0x6833, 0x0003, 0x2069, 0x0100, 0x6830,
+	0x689e, 0x2069, 0x0140, 0x6803, 0x0600, 0x0d7f, 0x0078, 0x509b,
+	0x127e, 0x2091, 0x8000, 0x7024, 0xa00d, 0x0040, 0x50ac, 0x7020,
+	0x8001, 0x7022, 0x00c0, 0x50ac, 0x7023, 0x0009, 0x8109, 0x7126,
+	0x00c0, 0x50ac, 0x7028, 0x107a, 0x7030, 0xa00d, 0x0040, 0x50bd,
+	0x702c, 0x8001, 0x702e, 0x00c0, 0x50bd, 0x702f, 0x0009, 0x8109,
+	0x7132, 0x00c0, 0x50bd, 0x7034, 0x107a, 0x7040, 0xa005, 0x0040,
+	0x50c5, 0x0050, 0x50c5, 0x8001, 0x7042, 0x7044, 0xa005, 0x0040,
+	0x50cd, 0x0050, 0x50cd, 0x8001, 0x7046, 0x7018, 0xa00d, 0x0040,
+	0x50de, 0x7008, 0x8001, 0x700a, 0x00c0, 0x50de, 0x700b, 0x0009,
+	0x8109, 0x711a, 0x00c0, 0x50de, 0x701c, 0x107a, 0x127f, 0x7004,
+	0x0079, 0x50e2, 0x5109, 0x510a, 0x5126, 0x0e7e, 0x2071, 0x8ab5,
+	0x7018, 0xa005, 0x00c0, 0x50f0, 0x711a, 0x721e, 0x700b, 0x0009,
+	0x0e7f, 0x007c, 0x0e7e, 0x007e, 0x2071, 0x8ab5, 0x701c, 0xa206,
+	0x00c0, 0x50fc, 0x701a, 0x701e, 0x007f, 0x0e7f, 0x007c, 0x0e7e,
+	0x2071, 0x8ab5, 0x6088, 0xa102, 0x0048, 0x5107, 0x618a, 0x0e7f,
+	0x007c, 0x007c, 0x7110, 0x1078, 0x3f8e, 0x00c0, 0x511c, 0x6088,
+	0x8001, 0x0048, 0x511c, 0x608a, 0x00c0, 0x511c, 0x127e, 0x2091,
+	0x8000, 0x1078, 0x5888, 0x127f, 0x8108, 0xa182, 0x00ff, 0x0048,
+	0x5124, 0xa00e, 0x7007, 0x0002, 0x7112, 0x007c, 0x7014, 0x2060,
+	0x127e, 0x2091, 0x8000, 0x6014, 0xa005, 0x0040, 0x5155, 0x8001,
+	0x6016, 0x00c0, 0x5155, 0x611c, 0xa186, 0x0003, 0x0040, 0x513c,
+	0xa186, 0x0006, 0x00c0, 0x5153, 0x6010, 0x2068, 0x6854, 0xa08a,
+	0x199a, 0x0048, 0x5153, 0xa082, 0x1999, 0x6856, 0xa08a, 0x199a,
+	0x0048, 0x514c, 0x2001, 0x1999, 0x8003, 0x800b, 0x810b, 0xa108,
+	0x6116, 0x0078, 0x5155, 0x1078, 0x7632, 0x127f, 0xac88, 0x000c,
+	0x7116, 0x2001, 0x8816, 0x2004, 0xa102, 0x0048, 0x5163, 0x7017,
+	0x8f00, 0x7007, 0x0000, 0x007c, 0x0e7e, 0x2071, 0x8ab5, 0x7027,
+	0x07d0, 0x7023, 0x0009, 0x703b, 0x0002, 0x0e7f, 0x007c, 0x2001,
+	0x8abe, 0x2003, 0x0000, 0x007c, 0x0e7e, 0x2071, 0x8ab5, 0x7132,
+	0x702f, 0x0009, 0x0e7f, 0x007c, 0x2011, 0x8ac1, 0x2013, 0x0000,
+	0x007c, 0x0e7e, 0x2071, 0x8ab5, 0x711a, 0x721e, 0x700b, 0x0009,
+	0x0e7f, 0x007c, 0x0c7e, 0x2061, 0x8b24, 0x0c7f, 0x007c, 0xa184,
+	0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x8b24, 0x2060, 0x007c,
+	0x6854, 0xa08a, 0x199a, 0x0048, 0x519f, 0x2001, 0x1999, 0xa005,
+	0x00c0, 0x51ae, 0x0c7e, 0x2061, 0x8b24, 0x6014, 0x0c7f, 0xa005,
+	0x00c0, 0x51b3, 0x2001, 0x001e, 0x0078, 0x51b3, 0xa08e, 0xffff,
+	0x00c0, 0x51b3, 0xa006, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116,
+	0x684c, 0xa08c, 0x00c0, 0xa18e, 0x00c0, 0x0040, 0x51fc, 0xd0b4,
+	0x00c0, 0x51ca, 0xd0bc, 0x00c0, 0x51ec, 0x2009, 0x0006, 0x1078,
+	0x521b, 0x007c, 0xd0fc, 0x0040, 0x51d5, 0xa084, 0x0003, 0x0040,
+	0x51d5, 0xa086, 0x0003, 0x00c0, 0x5214, 0x2009, 0x8873, 0x2104,
+	0xd084, 0x0040, 0x51e7, 0x6118, 0xa188, 0x0027, 0x2104, 0xd08c,
+	0x00c0, 0x51e7, 0x2009, 0x0042, 0x1078, 0x6939, 0x007c, 0x2009,
+	0x0043, 0x1078, 0x6939, 0x007c, 0xd0fc, 0x0040, 0x51f7, 0xa084,
+	0x0003, 0x0040, 0x51f7, 0xa086, 0x0003, 0x00c0, 0x5214, 0x2009,
+	0x0042, 0x1078, 0x6939, 0x007c, 0xd0fc, 0x0040, 0x520a, 0xa084,
+	0x0003, 0xa08e, 0x0002, 0x0040, 0x520e, 0x2009, 0x0041, 0x1078,
+	0x6939, 0x007c, 0x1078, 0x5219, 0x0078, 0x5209, 0x2009, 0x0043,
+	0x1078, 0x6939, 0x0078, 0x5209, 0x2009, 0x0004, 0x1078, 0x521b,
+	0x007c, 0x2009, 0x0001, 0x6010, 0xa0ec, 0xf000, 0x0040, 0x5242,
+	0x2068, 0x6952, 0x6800, 0x6012, 0xa186, 0x0001, 0x00c0, 0x523c,
+	0x694c, 0xa18c, 0x8100, 0xa18e, 0x8100, 0x00c0, 0x523c, 0x0c7e,
+	0x2061, 0x8b24, 0x6200, 0xd28c, 0x00c0, 0x523b, 0x6204, 0x8210,
+	0x0048, 0x523b, 0x6206, 0x0c7f, 0x1078, 0x4376, 0x6010, 0xa06d,
+	0x10c0, 0x5198, 0x007c, 0x157e, 0x0c7e, 0x2061, 0x8b24, 0x6000,
+	0x81ff, 0x0040, 0x524e, 0xa205, 0x0078, 0x524f, 0xa204, 0x6002,
+	0x0c7f, 0x157f, 0x007c, 0x6800, 0xd08c, 0x00c0, 0x525f, 0x6808,
+	0xa005, 0x0040, 0x525f, 0x8001, 0x680a, 0xa085, 0x0001, 0x007c,
+	0x127e, 0x2091, 0x2200, 0x2079, 0x8aa2, 0x127f, 0x0d7e, 0x2069,
+	0x8aa2, 0x6803, 0x0005, 0x2069, 0x0004, 0x2d04, 0xa085, 0x8001,
+	0x206a, 0x0d7f, 0x007c, 0x0c7e, 0x6027, 0x0001, 0x7804, 0xa084,
+	0x0007, 0x0079, 0x527b, 0x5285, 0x52aa, 0x5305, 0x528b, 0x52aa,
+	0x5285, 0x5283, 0x5283, 0x1078, 0x12d2, 0x1078, 0x516f, 0x1078,
+	0x5888, 0x0c7f, 0x007c, 0x62c0, 0x82ff, 0x00c0, 0x5291, 0x0c7f,
+	0x007c, 0x2011, 0x3c35, 0x1078, 0x50f2, 0x7828, 0xa092, 0x0002,
+	0x00c8, 0x52a0, 0x8000, 0x782a, 0x1078, 0x3c6a, 0x0078, 0x528f,
+	0x1078, 0x3c35, 0x7807, 0x0003, 0x7827, 0x0000, 0x782b, 0x0000,
+	0x0078, 0x528f, 0x1078, 0x516f, 0x3c00, 0x007e, 0x2011, 0x0209,
+	0x20e1, 0x4000, 0x2214, 0x007f, 0x20e0, 0x82ff, 0x0040, 0x52c8,
+	0x62c0, 0x82ff, 0x00c0, 0x52c8, 0x782b, 0x0000, 0x7824, 0xa065,
+	0x1040, 0x12d2, 0x2009, 0x0013, 0x1078, 0x6939, 0x0c7f, 0x007c,
+	0x3900, 0xa082, 0x8bc4, 0x00c8, 0x52cf, 0x1078, 0x683b, 0x0c7e,
+	0x7824, 0xa065, 0x1040, 0x12d2, 0x7804, 0xa086, 0x0004, 0x0040,
+	0x534a, 0x7828, 0xa092, 0x2710, 0x00c8, 0x52e5, 0x8000, 0x782a,
+	0x0c7f, 0x1078, 0x6224, 0x0078, 0x52c6, 0x6104, 0xa186, 0x0003,
+	0x00c0, 0x52fc, 0x0e7e, 0x2071, 0x8800, 0x70cc, 0x0e7f, 0xd08c,
+	0x0040, 0x52fc, 0x0c7e, 0x0e7e, 0x2061, 0x0100, 0x2071, 0x8800,
+	0x1078, 0x3c73, 0x0e7f, 0x0c7f, 0x1078, 0x8781, 0x2009, 0x0014,
+	0x1078, 0x6939, 0x0c7f, 0x0078, 0x52c6, 0x2001, 0x8abe, 0x2003,
+	0x0000, 0x62c0, 0x82ff, 0x00c0, 0x5319, 0x782b, 0x0000, 0x7824,
+	0xa065, 0x1040, 0x12d2, 0x2009, 0x0013, 0x1078, 0x6990, 0x0c7f,
+	0x007c, 0x0c7e, 0x0d7e, 0x3900, 0xa082, 0x8bc4, 0x00c8, 0x5322,
+	0x1078, 0x683b, 0x7824, 0xa005, 0x1040, 0x12d2, 0x781c, 0xa06d,
+	0x1040, 0x12d2, 0x6800, 0xc0dc, 0x6802, 0x7924, 0x2160, 0x1078,
+	0x690e, 0x693c, 0x81ff, 0x1040, 0x12d2, 0x8109, 0x693e, 0x6854,
+	0xa015, 0x0040, 0x533e, 0x7a1e, 0x0078, 0x5340, 0x7918, 0x791e,
+	0x7807, 0x0000, 0x7827, 0x0000, 0x0d7f, 0x0c7f, 0x1078, 0x5888,
+	0x0078, 0x5317, 0x6104, 0xa186, 0x0002, 0x0040, 0x5355, 0xa186,
+	0x0004, 0x0040, 0x5355, 0x0078, 0x52d9, 0x7808, 0xac06, 0x0040,
+	0x52d9, 0x1078, 0x578f, 0x1078, 0x53e6, 0x0c7f, 0x1078, 0x5888,
+	0x0078, 0x52c6, 0x0c7e, 0x6027, 0x0002, 0x62c8, 0x82ff, 0x00c0,
+	0x537c, 0x62c4, 0x82ff, 0x00c0, 0x537c, 0x793c, 0xa1e5, 0x0000,
+	0x0040, 0x5376, 0x2009, 0x0049, 0x1078, 0x6939, 0x2011, 0x8ac1,
+	0x2013, 0x0000, 0x0c7f, 0x007c, 0x3908, 0xa192, 0x8bc4, 0x00c8,
+	0x5383, 0x1078, 0x683b, 0x6017, 0x0010, 0x793c, 0x81ff, 0x0040,
+	0x5376, 0x793c, 0xa188, 0x0007, 0x210c, 0xa18e, 0x0006, 0x00c0,
+	0x5395, 0x6017, 0x0012, 0x0078, 0x537a, 0x6017, 0x0016, 0x0078,
+	0x537a, 0x007e, 0x017e, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x600f,
+	0x0000, 0x2c08, 0x2061, 0x8aa2, 0x6020, 0x8000, 0x6022, 0x6010,
+	0xa005, 0x0040, 0x53b4, 0xa080, 0x0003, 0x2102, 0x6112, 0x127f,
+	0x0c7f, 0x017f, 0x007f, 0x007c, 0x6116, 0x6112, 0x0078, 0x53af,
+	0x0d7e, 0x2069, 0x8aa2, 0x6000, 0xd0d4, 0x0040, 0x53cd, 0x6820,
+	0x8000, 0x6822, 0xa086, 0x0001, 0x00c0, 0x53c8, 0x2c00, 0x681e,
+	0x6804, 0xa084, 0x0007, 0x0079, 0x5890, 0xc0d5, 0x6002, 0x6818,
+	0xa005, 0x0040, 0x53df, 0x6056, 0x605b, 0x0000, 0x007e, 0x2c00,
+	0x681a, 0x0d7f, 0x685a, 0x2069, 0x8aa2, 0x0078, 0x53bf, 0x6056,
+	0x605a, 0x2c00, 0x681a, 0x681e, 0x0078, 0x53bf, 0x007e, 0x017e,
 	0x0c7e, 0x127e, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061,
-	0x7936, 0x6020, 0x8000, 0x6022, 0x6008, 0xa005, 0x0040, 0x49a9,
+	0x8aa2, 0x6020, 0x8000, 0x6022, 0x6008, 0xa005, 0x0040, 0x5401,
 	0xa080, 0x0003, 0x2102, 0x610a, 0x127f, 0x0c7f, 0x017f, 0x007f,
-	0x007c, 0x610e, 0x610a, 0x0078, 0x49a4, 0x0c7e, 0x600f, 0x0000,
-	0x2c08, 0x2061, 0x7936, 0x6034, 0xa005, 0x0040, 0x49bd, 0xa080,
+	0x007c, 0x610e, 0x610a, 0x0078, 0x53fc, 0x0c7e, 0x600f, 0x0000,
+	0x2c08, 0x2061, 0x8aa2, 0x6034, 0xa005, 0x0040, 0x5415, 0xa080,
 	0x0003, 0x2102, 0x6136, 0x0c7f, 0x007c, 0x613a, 0x6136, 0x0078,
-	0x49bb, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x027e, 0x007e,
-	0x127e, 0x2071, 0x7936, 0x7638, 0x2660, 0x2678, 0x2091, 0x8000,
-	0x8cff, 0x0040, 0x4a23, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206,
-	0x00c0, 0x4a1e, 0x703c, 0xac06, 0x00c0, 0x49e3, 0x6003, 0x000a,
-	0x630a, 0x0078, 0x4a1e, 0x7038, 0xac36, 0x00c0, 0x49e9, 0x660c,
-	0x763a, 0x7034, 0xac36, 0x00c0, 0x49f7, 0x2c00, 0xaf36, 0x0040,
-	0x49f5, 0x2f00, 0x7036, 0x0078, 0x49f7, 0x7037, 0x0000, 0x660c,
-	0x067e, 0x2c00, 0xaf06, 0x0040, 0x4a00, 0x7e0e, 0x0078, 0x4a01,
-	0x2678, 0x600f, 0x0000, 0x1078, 0x6a58, 0x0040, 0x4a19, 0x6010,
-	0x2068, 0x601c, 0xa086, 0x0003, 0x00c0, 0x4a2c, 0x6837, 0x0103,
-	0x6b4a, 0x6847, 0x0000, 0x1078, 0x6c54, 0x1078, 0x3b92, 0x1078,
-	0x6ba9, 0x1078, 0x6bb6, 0x0c7f, 0x0078, 0x49d0, 0x2c78, 0x600c,
-	0x2060, 0x0078, 0x49d0, 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f,
-	0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0,
-	0x4a0e, 0x1078, 0x75fd, 0x0078, 0x4a19, 0x007e, 0x067e, 0x0c7e,
-	0x0d7e, 0x0f7e, 0x2031, 0x0000, 0x127e, 0x2091, 0x8000, 0x2079,
-	0x7936, 0x7838, 0xa065, 0x0040, 0x4a6c, 0x600c, 0x007e, 0x600f,
-	0x0000, 0x783c, 0xac06, 0x00c0, 0x4a53, 0x6003, 0x000a, 0x630a,
-	0x2c30, 0x0078, 0x4a69, 0x1078, 0x6a58, 0x0040, 0x4a67, 0x6010,
-	0x2068, 0x601c, 0xa086, 0x0003, 0x00c0, 0x4a75, 0x6837, 0x0103,
-	0x6b4a, 0x6847, 0x0000, 0x1078, 0x3b92, 0x1078, 0x6ba9, 0x1078,
-	0x6bb6, 0x007f, 0x0078, 0x4a42, 0x7e3a, 0x7e36, 0x127f, 0x0f7f,
-	0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c, 0x601c, 0xa086, 0x0006,
-	0x00c0, 0x4a5e, 0x1078, 0x75fd, 0x0078, 0x4a67, 0x027e, 0x1078,
-	0x4a92, 0x1078, 0x4b2b, 0x027f, 0x007c, 0x0f7e, 0x127e, 0x2079,
-	0x7936, 0x2091, 0x8000, 0x1078, 0x4bc2, 0x1078, 0x4c2a, 0x127f,
-	0x0f7f, 0x007c, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x007e,
-	0x127e, 0x2091, 0x8000, 0x2071, 0x7936, 0x7614, 0x2660, 0x2678,
-	0x8cff, 0x0040, 0x4b1a, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206,
-	0x00c0, 0x4b15, 0x7024, 0xac06, 0x00c0, 0x4ad8, 0x2069, 0x0100,
-	0x68c0, 0xa005, 0x0040, 0x4ad3, 0x1078, 0x569c, 0x68c3, 0x0000,
-	0x1078, 0x5b4a, 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04,
-	0xa384, 0x1000, 0x0040, 0x4ac8, 0x6803, 0x0100, 0x6803, 0x0000,
-	0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x4ad0, 0x6827, 0x0001,
-	0x037f, 0x0078, 0x4ad8, 0x6003, 0x0009, 0x630a, 0x0078, 0x4b15,
-	0x7014, 0xac36, 0x00c0, 0x4ade, 0x660c, 0x7616, 0x7010, 0xac36,
-	0x00c0, 0x4aec, 0x2c00, 0xaf36, 0x0040, 0x4aea, 0x2f00, 0x7012,
-	0x0078, 0x4aec, 0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06,
-	0x0040, 0x4af5, 0x7e0e, 0x0078, 0x4af6, 0x2678, 0x600f, 0x0000,
-	0x6010, 0x2068, 0x1078, 0x6a58, 0x0040, 0x4b0e, 0x601c, 0xa086,
-	0x0003, 0x00c0, 0x4b22, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000,
-	0x1078, 0x6c54, 0x1078, 0x3b92, 0x1078, 0x6ba9, 0x1078, 0x6bb6,
-	0x1078, 0x5a1a, 0x0c7f, 0x0078, 0x4aa0, 0x2c78, 0x600c, 0x2060,
-	0x0078, 0x4aa0, 0x127f, 0x007f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f,
-	0x0f7f, 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x4b03, 0x1078,
-	0x75fd, 0x0078, 0x4b0e, 0x0c7e, 0x007e, 0x127e, 0x2091, 0x8000,
-	0xa280, 0x7820, 0x2004, 0xa065, 0x0040, 0x4bbe, 0x0f7e, 0x0e7e,
-	0x0d7e, 0x067e, 0x2071, 0x7936, 0x6654, 0x7018, 0xac06, 0x00c0,
-	0x4b42, 0x761a, 0x701c, 0xac06, 0x00c0, 0x4b4e, 0x86ff, 0x00c0,
-	0x4b4d, 0x7018, 0x701e, 0x0078, 0x4b4e, 0x761e, 0x6058, 0xa07d,
-	0x0040, 0x4b53, 0x7e56, 0xa6ed, 0x0000, 0x0040, 0x4b59, 0x2f00,
-	0x685a, 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc,
-	0x6002, 0x1078, 0x37c5, 0x0040, 0x4bba, 0x7624, 0x86ff, 0x0040,
-	0x4baa, 0xa680, 0x0004, 0x2004, 0xad06, 0x00c0, 0x4baa, 0x0d7e,
-	0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x4ba1, 0x1078, 0x569c,
-	0x68c3, 0x0000, 0x1078, 0x5b4a, 0x7027, 0x0000, 0x037e, 0x2069,
-	0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x4b8a, 0x6803, 0x0100,
-	0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x4b92,
-	0x6827, 0x0001, 0x037f, 0x0d7f, 0x0c7e, 0x603c, 0xa005, 0x0040,
-	0x4b9b, 0x8001, 0x603e, 0x2660, 0x1078, 0x6bb6, 0x0c7f, 0x0078,
-	0x4baa, 0x0d7f, 0x0c7e, 0x2660, 0x6003, 0x0009, 0x630a, 0x0c7f,
-	0x0078, 0x4b61, 0x8dff, 0x0040, 0x4bb6, 0x6837, 0x0103, 0x6b4a,
-	0x6847, 0x0000, 0x1078, 0x6c54, 0x1078, 0x3b92, 0x1078, 0x5a1a,
-	0x0078, 0x4b61, 0x067f, 0x0d7f, 0x0e7f, 0x0f7f, 0x127f, 0x007f,
-	0x0c7f, 0x007c, 0x007e, 0x067e, 0x0c7e, 0x0d7e, 0x2031, 0x0000,
-	0x7814, 0xa065, 0x0040, 0x4c1a, 0x600c, 0x007e, 0x600f, 0x0000,
-	0x7824, 0xac06, 0x00c0, 0x4bff, 0x2069, 0x0100, 0x68c0, 0xa005,
-	0x0040, 0x4bf9, 0x1078, 0x569c, 0x68c3, 0x0000, 0x1078, 0x5b4a,
-	0x7827, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000,
-	0x0040, 0x4bee, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100,
-	0x6824, 0xd084, 0x0040, 0x4bf6, 0x6827, 0x0001, 0x037f, 0x0078,
-	0x4bff, 0x6003, 0x0009, 0x630a, 0x2c30, 0x0078, 0x4c17, 0x6010,
-	0x2068, 0x1078, 0x6a58, 0x0040, 0x4c13, 0x601c, 0xa086, 0x0003,
-	0x00c0, 0x4c21, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078,
-	0x3b92, 0x1078, 0x6ba9, 0x1078, 0x6bb6, 0x1078, 0x5a1a, 0x007f,
-	0x0078, 0x4bc9, 0x7e16, 0x7e12, 0x0d7f, 0x0c7f, 0x067f, 0x007f,
-	0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x4c0a, 0x1078, 0x75fd,
-	0x0078, 0x4c13, 0x007e, 0x067e, 0x0c7e, 0x0d7e, 0x7818, 0xa065,
-	0x0040, 0x4c96, 0x6054, 0x007e, 0x6057, 0x0000, 0x605b, 0x0000,
-	0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x1078, 0x37c5, 0x0040, 0x4c93,
-	0x7e24, 0x86ff, 0x0040, 0x4c85, 0xa680, 0x0004, 0x2004, 0xad06,
-	0x00c0, 0x4c85, 0x0d7e, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040,
-	0x4c7c, 0x1078, 0x569c, 0x68c3, 0x0000, 0x1078, 0x5b4a, 0x7827,
+	0x5413, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x027e, 0x017e,
+	0x007e, 0x127e, 0x2071, 0x8aa2, 0x7638, 0x2660, 0x2678, 0x2091,
+	0x8000, 0x8cff, 0x0040, 0x548c, 0x6018, 0xa080, 0x0028, 0x2004,
+	0xa206, 0x00c0, 0x5487, 0x88ff, 0x0040, 0x543a, 0x6020, 0xa106,
+	0x00c0, 0x5487, 0x703c, 0xac06, 0x00c0, 0x544c, 0x037e, 0x2019,
+	0x0001, 0x1078, 0x642d, 0x7033, 0x0000, 0x703f, 0x0000, 0x7043,
+	0x0000, 0x7047, 0x0000, 0x037f, 0x7038, 0xac36, 0x00c0, 0x5452,
+	0x660c, 0x763a, 0x7034, 0xac36, 0x00c0, 0x5460, 0x2c00, 0xaf36,
+	0x0040, 0x545e, 0x2f00, 0x7036, 0x0078, 0x5460, 0x7037, 0x0000,
+	0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x5469, 0x7e0e, 0x0078,
+	0x546a, 0x2678, 0x600f, 0x0000, 0x1078, 0x77ed, 0x0040, 0x5482,
+	0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x00c0, 0x5496, 0x6837,
+	0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x7a46, 0x1078, 0x4376,
+	0x1078, 0x799b, 0x1078, 0x79a8, 0x0c7f, 0x0078, 0x5429, 0x2c78,
+	0x600c, 0x2060, 0x0078, 0x5429, 0x127f, 0x007f, 0x017f, 0x027f,
+	0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x601c, 0xa086,
+	0x0006, 0x00c0, 0x5477, 0x1078, 0x86aa, 0x0078, 0x5482, 0x007e,
+	0x067e, 0x0c7e, 0x0d7e, 0x0f7e, 0x2031, 0x0000, 0x127e, 0x2091,
+	0x8000, 0x2079, 0x8aa2, 0x7838, 0xa065, 0x0040, 0x54de, 0x600c,
+	0x007e, 0x600f, 0x0000, 0x783c, 0xac06, 0x00c0, 0x54c5, 0x037e,
+	0x2019, 0x0001, 0x1078, 0x642d, 0x7833, 0x0000, 0x783f, 0x0000,
+	0x7843, 0x0000, 0x7847, 0x0000, 0x037f, 0x1078, 0x77ed, 0x0040,
+	0x54d9, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x00c0, 0x54e7,
+	0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x4376, 0x1078,
+	0x799b, 0x1078, 0x79a8, 0x007f, 0x0078, 0x54ac, 0x7e3a, 0x7e36,
+	0x127f, 0x0f7f, 0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c, 0x601c,
+	0xa086, 0x0006, 0x00c0, 0x54d0, 0x1078, 0x86aa, 0x0078, 0x54d9,
+	0x017e, 0x027e, 0x087e, 0x2041, 0x0000, 0x1078, 0x550a, 0x1078,
+	0x55ae, 0x087f, 0x027f, 0x017f, 0x007c, 0x0f7e, 0x127e, 0x2079,
+	0x8aa2, 0x2091, 0x8000, 0x1078, 0x5647, 0x1078, 0x56b1, 0x127f,
+	0x0f7f, 0x007c, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x017e,
+	0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0x8aa2, 0x7614, 0x2660,
+	0x2678, 0x8cff, 0x0040, 0x559c, 0x6018, 0xa080, 0x0028, 0x2004,
+	0xa206, 0x00c0, 0x5597, 0x88ff, 0x0040, 0x552a, 0x6020, 0xa106,
+	0x00c0, 0x5597, 0x7024, 0xac06, 0x00c0, 0x555a, 0x2069, 0x0100,
+	0x68c0, 0xa005, 0x0040, 0x5555, 0x1078, 0x516f, 0x1078, 0x6232,
+	0x68c3, 0x0000, 0x1078, 0x6741, 0x7027, 0x0000, 0x037e, 0x2069,
+	0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x554a, 0x6803, 0x0100,
+	0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x5552,
+	0x6827, 0x0001, 0x037f, 0x0078, 0x555a, 0x6003, 0x0009, 0x630a,
+	0x0078, 0x5597, 0x7014, 0xac36, 0x00c0, 0x5560, 0x660c, 0x7616,
+	0x7010, 0xac36, 0x00c0, 0x556e, 0x2c00, 0xaf36, 0x0040, 0x556c,
+	0x2f00, 0x7012, 0x0078, 0x556e, 0x7013, 0x0000, 0x660c, 0x067e,
+	0x2c00, 0xaf06, 0x0040, 0x5577, 0x7e0e, 0x0078, 0x5578, 0x2678,
+	0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x77ed, 0x0040, 0x5590,
+	0x601c, 0xa086, 0x0003, 0x00c0, 0x55a5, 0x6837, 0x0103, 0x6b4a,
+	0x6847, 0x0000, 0x1078, 0x7a46, 0x1078, 0x4376, 0x1078, 0x799b,
+	0x1078, 0x79a8, 0x1078, 0x6601, 0x0c7f, 0x0078, 0x5519, 0x2c78,
+	0x600c, 0x2060, 0x0078, 0x5519, 0x127f, 0x007f, 0x017f, 0x067f,
+	0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x601c, 0xa086, 0x0006,
+	0x00c0, 0x5585, 0x1078, 0x86aa, 0x0078, 0x5590, 0x0c7e, 0x007e,
+	0x127e, 0x2091, 0x8000, 0xa280, 0x8934, 0x2004, 0xa065, 0x0040,
+	0x5643, 0x0f7e, 0x0e7e, 0x0d7e, 0x067e, 0x2071, 0x8aa2, 0x6654,
+	0x7018, 0xac06, 0x00c0, 0x55c5, 0x761a, 0x701c, 0xac06, 0x00c0,
+	0x55d1, 0x86ff, 0x00c0, 0x55d0, 0x7018, 0x701e, 0x0078, 0x55d1,
+	0x761e, 0x6058, 0xa07d, 0x0040, 0x55d6, 0x7e56, 0xa6ed, 0x0000,
+	0x0040, 0x55dc, 0x2f00, 0x685a, 0x6057, 0x0000, 0x605b, 0x0000,
+	0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x1078, 0x3ed6, 0x0040, 0x563f,
+	0x7624, 0x86ff, 0x0040, 0x562f, 0xa680, 0x0004, 0x2004, 0xad06,
+	0x00c0, 0x562f, 0x0d7e, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040,
+	0x5626, 0x1078, 0x516f, 0x1078, 0x6232, 0x68c3, 0x0000, 0x1078,
+	0x6741, 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384,
+	0x1000, 0x0040, 0x560f, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069,
+	0x0100, 0x6824, 0xd084, 0x0040, 0x5617, 0x6827, 0x0001, 0x037f,
+	0x0d7f, 0x0c7e, 0x603c, 0xa005, 0x0040, 0x5620, 0x8001, 0x603e,
+	0x2660, 0x1078, 0x79a8, 0x0c7f, 0x0078, 0x562f, 0x0d7f, 0x0c7e,
+	0x2660, 0x6003, 0x0009, 0x630a, 0x0c7f, 0x0078, 0x55e4, 0x8dff,
+	0x0040, 0x563b, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078,
+	0x7a46, 0x1078, 0x4376, 0x1078, 0x6601, 0x0078, 0x55e4, 0x067f,
+	0x0d7f, 0x0e7f, 0x0f7f, 0x127f, 0x007f, 0x0c7f, 0x007c, 0x007e,
+	0x067e, 0x0c7e, 0x0d7e, 0x2031, 0x0000, 0x7814, 0xa065, 0x0040,
+	0x56a1, 0x600c, 0x007e, 0x600f, 0x0000, 0x7824, 0xac06, 0x00c0,
+	0x5686, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x5680, 0x1078,
+	0x516f, 0x1078, 0x6232, 0x68c3, 0x0000, 0x1078, 0x6741, 0x7827,
 	0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040,
-	0x4c65, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824,
-	0xd084, 0x0040, 0x4c6d, 0x6827, 0x0001, 0x037f, 0x0d7f, 0x0c7e,
-	0x603c, 0xa005, 0x0040, 0x4c76, 0x8001, 0x603e, 0x2660, 0x1078,
-	0x6bb6, 0x0c7f, 0x0078, 0x4c85, 0x0d7f, 0x0c7e, 0x2660, 0x6003,
-	0x0009, 0x630a, 0x0c7f, 0x0078, 0x4c3c, 0x8dff, 0x0040, 0x4c8f,
-	0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x3b92, 0x1078,
-	0x5a1a, 0x0078, 0x4c3c, 0x007f, 0x0078, 0x4c2f, 0x781e, 0x781a,
-	0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c, 0x0e7e, 0x0c7e, 0x2071,
-	0x7936, 0x7004, 0xa084, 0x0007, 0x0079, 0x4ca6, 0x4cb0, 0x4cb3,
-	0x4ccc, 0x4ce8, 0x4d2d, 0x4cb0, 0x4cb0, 0x4cae, 0x1078, 0x12cd,
-	0x0c7f, 0x0e7f, 0x007c, 0x7024, 0xa065, 0x0040, 0x4cc1, 0x7020,
-	0x8001, 0x7022, 0x600c, 0xa015, 0x0040, 0x4cc8, 0x7216, 0x600f,
-	0x0000, 0x7007, 0x0000, 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c,
-	0x7216, 0x7212, 0x0078, 0x4cc1, 0x6018, 0x2060, 0x1078, 0x37c5,
-	0x6000, 0xc0dc, 0x6002, 0x7020, 0x8001, 0x7022, 0x0040, 0x4cdd,
-	0x6054, 0xa015, 0x0040, 0x4ce4, 0x721e, 0x7007, 0x0000, 0x7027,
-	0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x7218, 0x721e, 0x0078, 0x4cdd,
-	0x7024, 0xa065, 0x0040, 0x4d2a, 0x700c, 0xac06, 0x00c0, 0x4cff,
-	0x1078, 0x5a1a, 0x600c, 0xa015, 0x0040, 0x4cfb, 0x720e, 0x600f,
-	0x0000, 0x0078, 0x4d28, 0x720e, 0x720a, 0x0078, 0x4d28, 0x7014,
-	0xac06, 0x00c0, 0x4d12, 0x1078, 0x5a1a, 0x600c, 0xa015, 0x0040,
-	0x4d0e, 0x7216, 0x600f, 0x0000, 0x0078, 0x4d28, 0x7216, 0x7212,
-	0x0078, 0x4d28, 0x6018, 0x2060, 0x1078, 0x37c5, 0x6000, 0xc0dc,
-	0x6002, 0x1078, 0x5a1a, 0x701c, 0xa065, 0x0040, 0x4d28, 0x6054,
-	0xa015, 0x0040, 0x4d26, 0x721e, 0x0078, 0x4d28, 0x7218, 0x721e,
-	0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x7024, 0xa065, 0x0040,
-	0x4d3a, 0x1078, 0x5a1a, 0x600c, 0xa015, 0x0040, 0x4d41, 0x720e,
-	0x600f, 0x0000, 0x1078, 0x5b4a, 0x7027, 0x0000, 0x0c7f, 0x0e7f,
-	0x007c, 0x720e, 0x720a, 0x0078, 0x4d3a, 0x0d7e, 0x2069, 0x7936,
-	0x6830, 0xa084, 0x0003, 0x0079, 0x4d4d, 0x4d53, 0x4d55, 0x4d7b,
-	0x4d53, 0x1078, 0x12cd, 0x0d7f, 0x007c, 0x0c7e, 0x6840, 0xa086,
-	0x0001, 0x0040, 0x4d71, 0x683c, 0xa065, 0x0040, 0x4d66, 0x600c,
-	0xa015, 0x0040, 0x4d6d, 0x6a3a, 0x600f, 0x0000, 0x6833, 0x0000,
-	0x683f, 0x0000, 0x0c7f, 0x0d7f, 0x007c, 0x683a, 0x6836, 0x0078,
-	0x4d66, 0x6843, 0x0000, 0x6838, 0xa065, 0x0040, 0x4d66, 0x6003,
-	0x0003, 0x0078, 0x4d66, 0x0c7e, 0x6843, 0x0000, 0x6847, 0x0000,
-	0x683c, 0xa065, 0x0040, 0x4d93, 0x600c, 0xa015, 0x0040, 0x4d8f,
-	0x6a3a, 0x600f, 0x0000, 0x683f, 0x0000, 0x0078, 0x4d93, 0x683f,
-	0x0000, 0x683a, 0x6836, 0x0c7f, 0x0d7f, 0x007c, 0x0d7e, 0x2069,
-	0x7936, 0x6804, 0xa084, 0x0007, 0x0079, 0x4d9e, 0x4da8, 0x4e45,
-	0x4e45, 0x4e45, 0x4e45, 0x4e47, 0x4e45, 0x4da6, 0x1078, 0x12cd,
-	0x6820, 0xa005, 0x00c0, 0x4dae, 0x0d7f, 0x007c, 0x0c7e, 0x680c,
-	0xa065, 0x0040, 0x4dbd, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000,
-	0x1078, 0x4e8d, 0x0c7f, 0x0d7f, 0x007c, 0x6814, 0xa065, 0x0040,
-	0x4dcb, 0x6807, 0x0001, 0x6826, 0x682b, 0x0000, 0x1078, 0x4e8d,
-	0x0c7f, 0x0d7f, 0x007c, 0x0e7e, 0x037e, 0x6a1c, 0xa2f5, 0x0000,
-	0x0040, 0x4e40, 0x704c, 0xa00d, 0x0040, 0x4dda, 0x7088, 0xa005,
-	0x0040, 0x4df2, 0x7054, 0xa075, 0x0040, 0x4de3, 0xa20e, 0x0040,
-	0x4e40, 0x0078, 0x4de8, 0x6818, 0xa20e, 0x0040, 0x4e40, 0x2070,
-	0x704c, 0xa00d, 0x0040, 0x4dda, 0x7088, 0xa005, 0x00c0, 0x4dda,
-	0x2e00, 0x681e, 0x733c, 0x7038, 0xa302, 0x00c8, 0x4dda, 0x1078,
-	0x5ce9, 0x0040, 0x4e40, 0x8318, 0x733e, 0x6112, 0x2e10, 0x621a,
-	0xa180, 0x0015, 0x2004, 0xa08a, 0x199a, 0x0048, 0x4e09, 0x2001,
-	0x1999, 0x8003, 0x801b, 0x831b, 0xa318, 0x6316, 0x037f, 0x0f7e,
-	0x2c78, 0x71a0, 0xd1bc, 0x0040, 0x4e22, 0x7100, 0xd1f4, 0x0040,
-	0x4e1e, 0x7114, 0xa18c, 0x00ff, 0x0078, 0x4e27, 0x2009, 0x0000,
-	0x0078, 0x4e27, 0xa1e0, 0x2329, 0x2c0c, 0xa18c, 0x00ff, 0x2061,
-	0x0100, 0x619a, 0x1078, 0x52de, 0x7300, 0xc3dd, 0x7302, 0x6807,
-	0x0002, 0x2f18, 0x6b26, 0x682b, 0x0000, 0x781f, 0x0003, 0x7803,
-	0x0001, 0x7807, 0x0040, 0x0f7f, 0x0e7f, 0x0c7f, 0x0d7f, 0x007c,
-	0x037f, 0x0e7f, 0x0c7f, 0x0078, 0x4e3e, 0x0d7f, 0x007c, 0x0c7e,
-	0x680c, 0xa065, 0x0040, 0x4e53, 0x6807, 0x0004, 0x6826, 0x682b,
-	0x0000, 0x1078, 0x4e8d, 0x0c7f, 0x0d7f, 0x007c, 0x0f7e, 0x0d7e,
-	0x2069, 0x7936, 0x6830, 0xa086, 0x0000, 0x00c0, 0x4e74, 0x6838,
-	0xa07d, 0x0040, 0x4e74, 0x6833, 0x0001, 0x683e, 0x6847, 0x0000,
-	0x127e, 0x0f7e, 0x2091, 0x2200, 0x027f, 0x1078, 0x1a44, 0x00c0,
-	0x4e77, 0x127f, 0x1078, 0x5571, 0x0d7f, 0x0f7f, 0x007c, 0x127f,
-	0x6843, 0x0000, 0x7803, 0x0002, 0x780c, 0xa015, 0x0040, 0x4e89,
-	0x6a3a, 0x780f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x0078,
-	0x4e74, 0x683a, 0x6836, 0x0078, 0x4e83, 0x601c, 0xa084, 0x000f,
-	0x1079, 0x4e93, 0x007c, 0x4e9c, 0x4ea1, 0x51a8, 0x529e, 0x4ea1,
-	0x51a8, 0x529e, 0x4e9c, 0x4ea1, 0x1078, 0x4c9d, 0x1078, 0x4d96,
-	0x007c, 0x157e, 0x137e, 0x147e, 0x0c7e, 0x0f7e, 0x6004, 0xa08a,
-	0x0030, 0x10c8, 0x12cd, 0x6118, 0x2178, 0x79a0, 0xd1bc, 0x0040,
-	0x4ebe, 0x7900, 0xd1f4, 0x0040, 0x4eba, 0x7914, 0xa18c, 0x00ff,
-	0x0078, 0x4ec3, 0x2009, 0x0000, 0x0078, 0x4ec3, 0xa1f8, 0x2329,
-	0x2f0c, 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0x1079,
-	0x4ecf, 0x0f7f, 0x0c7f, 0x147f, 0x137f, 0x157f, 0x007c, 0x4f01,
-	0x4f39, 0x4f51, 0x4fd0, 0x4ffd, 0x5005, 0x5026, 0x5037, 0x5048,
-	0x5050, 0x5061, 0x5050, 0x50a9, 0x5037, 0x50ca, 0x50d2, 0x5048,
-	0x50d2, 0x50e3, 0x4eff, 0x4eff, 0x4eff, 0x4eff, 0x4eff, 0x4eff,
-	0x4eff, 0x4eff, 0x4eff, 0x4eff, 0x4eff, 0x4eff, 0x5758, 0x576d,
-	0x5790, 0x57b4, 0x5026, 0x4eff, 0x5026, 0x5050, 0x4eff, 0x4f51,
-	0x4fd0, 0x4eff, 0x5c64, 0x5050, 0x4eff, 0x5c87, 0x5050, 0x1078,
-	0x12cd, 0x20a1, 0x020b, 0x1078, 0x50f8, 0x20a3, 0x5200, 0x20a3,
-	0x0000, 0x0d7e, 0x2069, 0x7751, 0x6804, 0xd084, 0x0040, 0x4f1b,
-	0x6828, 0x20a3, 0x0000, 0x017e, 0x1078, 0x2094, 0x21a2, 0x017f,
-	0x0d7f, 0x0078, 0x4f20, 0x0d7f, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x20a9, 0x0004, 0x2099, 0x7705, 0x53a6, 0x20a9, 0x0004, 0x2099,
-	0x7701, 0x53a6, 0x20a3, 0x0000, 0x6030, 0xa084, 0x00ff, 0x20a2,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x1078, 0x5688,
-	0x007c, 0x20a1, 0x020b, 0x1078, 0x50f8, 0x20a3, 0x0500, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x6030, 0xa084, 0x00ff, 0x20a2, 0x20a9,
-	0x0004, 0x2099, 0x7705, 0x53a6, 0x60c3, 0x0010, 0x1078, 0x5688,
-	0x007c, 0x20a1, 0x020b, 0x1078, 0x50f8, 0x7818, 0xa080, 0x0028,
-	0x2004, 0xa086, 0x007e, 0x00c0, 0x4f64, 0x20a3, 0x0400, 0x620c,
-	0xc2b4, 0x620e, 0x0078, 0x4f66, 0x20a3, 0x0300, 0x20a3, 0x0000,
-	0x7818, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x00c0, 0x4f9f,
-	0x2099, 0x7920, 0x33a6, 0x9398, 0x33a6, 0x9398, 0x3304, 0xa084,
-	0x3fff, 0x20a2, 0x9398, 0x33a6, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, 0x7705,
-	0x53a6, 0x20a9, 0x0004, 0x2099, 0x7701, 0x53a6, 0x20a9, 0x0010,
-	0x20a3, 0x0000, 0x00f0, 0x4f90, 0x2099, 0x7928, 0x33a6, 0x20a9,
-	0x0007, 0x20a3, 0x0000, 0x00f0, 0x4f99, 0x0078, 0x4fbf, 0x2099,
-	0x7920, 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0004, 0x2099, 0x7705,
-	0x53a6, 0x20a9, 0x0004, 0x2099, 0x7701, 0x53a6, 0x20a9, 0x0008,
-	0x20a3, 0x0000, 0x00f0, 0x4fb0, 0x20a9, 0x0008, 0x20a3, 0x0000,
-	0x00f0, 0x4fb6, 0x2099, 0x7928, 0x20a9, 0x0008, 0x53a6, 0x20a9,
-	0x0008, 0x20a3, 0x0000, 0x00f0, 0x4fc1, 0x20a9, 0x000a, 0x20a3,
-	0x0000, 0x00f0, 0x4fc7, 0x60c3, 0x0074, 0x1078, 0x5688, 0x007c,
-	0x20a1, 0x020b, 0x1078, 0x50f8, 0x20a3, 0x2010, 0x20a3, 0x0014,
-	0x20a3, 0x0800, 0x20a3, 0x2000, 0xa006, 0x20a2, 0x20a2, 0x20a2,
-	0x20a2, 0x20a2, 0x0f7e, 0x2079, 0x7751, 0x7904, 0x0f7f, 0xd1ac,
-	0x00c0, 0x4fec, 0xa085, 0x0020, 0xd1a4, 0x0040, 0x4ff1, 0xa085,
-	0x0010, 0xa085, 0x0002, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x60c3, 0x0014, 0x1078, 0x5688, 0x007c, 0x20a1, 0x020b, 0x1078,
-	0x50f8, 0x20a3, 0x5000, 0x0078, 0x4f66, 0x20a1, 0x020b, 0x1078,
-	0x50f8, 0x20a3, 0x2110, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x60c3, 0x0014, 0x1078, 0x5688, 0x007c, 0x20a1, 0x020b,
-	0x1078, 0x516f, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x60c3, 0x0004, 0x1078, 0x5688, 0x007c, 0x20a1,
-	0x020b, 0x1078, 0x516f, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3,
-	0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x1078, 0x5688, 0x007c,
-	0x20a1, 0x020b, 0x1078, 0x516f, 0x20a3, 0x0200, 0x0078, 0x4f66,
-	0x20a1, 0x020b, 0x1078, 0x516f, 0x20a3, 0x0100, 0x20a3, 0x0000,
-	0x20a3, 0x0003, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x5688,
-	0x007c, 0x0d7e, 0x20a1, 0x020b, 0x1078, 0x516f, 0x20a3, 0x0210,
-	0x20a3, 0x0014, 0x20a3, 0x0800, 0x7818, 0x2068, 0x6894, 0xa086,
-	0x0014, 0x00c0, 0x5087, 0x6998, 0xa184, 0xc000, 0x00c0, 0x5083,
-	0xd1ec, 0x0040, 0x507f, 0x20a3, 0x2100, 0x0078, 0x5089, 0x20a3,
-	0x0100, 0x0078, 0x5089, 0x20a3, 0x0400, 0x0078, 0x5089, 0x20a3,
-	0x0700, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x0f7e,
-	0x2079, 0x7751, 0x7904, 0x0f7f, 0xd1ac, 0x00c0, 0x5099, 0xa085,
-	0x0020, 0xd1a4, 0x0040, 0x509e, 0xa085, 0x0010, 0xa085, 0x0002,
-	0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x0014, 0x1078, 0x5688, 0x0d7f,
-	0x007c, 0x20a1, 0x020b, 0x1078, 0x516f, 0x20a3, 0x0210, 0x20a3,
-	0x0014, 0x20a3, 0x0000, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078,
-	0x5688, 0x007c, 0x20a1, 0x020b, 0x1078, 0x516f, 0x20a3, 0x0200,
-	0x0078, 0x4f07, 0x20a1, 0x020b, 0x1078, 0x516f, 0x20a3, 0x0100,
-	0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008,
-	0x1078, 0x5688, 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a1,
-	0x020b, 0x1078, 0x516f, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3,
-	0x000b, 0x20a3, 0x0000, 0x60c3, 0x0008, 0x1078, 0x5688, 0x007c,
-	0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
-	0x2014, 0xa286, 0x007e, 0x00c0, 0x510b, 0x20a3, 0x22ff, 0x20a3,
-	0xfffe, 0x0078, 0x5139, 0xa286, 0x007f, 0x00c0, 0x5116, 0x0d7e,
-	0x20a3, 0x22ff, 0x20a3, 0xfffd, 0x0078, 0x512d, 0xd2bc, 0x0040,
-	0x5135, 0xa286, 0x0080, 0x0d7e, 0x00c0, 0x5124, 0x20a3, 0x22ff,
-	0x20a3, 0xfffc, 0x0078, 0x512d, 0xa2e8, 0x7820, 0x2d6c, 0x6810,
-	0xa085, 0x2200, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x7719, 0x2da6,
-	0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x513d, 0x20a3, 0x2200, 0x6298,
-	0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0129, 0x20a3,
-	0x0000, 0x1078, 0x5677, 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3,
+	0x5675, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824,
+	0xd084, 0x0040, 0x567d, 0x6827, 0x0001, 0x037f, 0x0078, 0x5686,
+	0x6003, 0x0009, 0x630a, 0x2c30, 0x0078, 0x569e, 0x6010, 0x2068,
+	0x1078, 0x77ed, 0x0040, 0x569a, 0x601c, 0xa086, 0x0003, 0x00c0,
+	0x56a8, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x4376,
+	0x1078, 0x799b, 0x1078, 0x79a8, 0x1078, 0x6601, 0x007f, 0x0078,
+	0x564e, 0x7e16, 0x7e12, 0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c,
+	0x601c, 0xa086, 0x0006, 0x00c0, 0x5691, 0x1078, 0x86aa, 0x0078,
+	0x569a, 0x007e, 0x067e, 0x0c7e, 0x0d7e, 0x7818, 0xa065, 0x0040,
+	0x571f, 0x6054, 0x007e, 0x6057, 0x0000, 0x605b, 0x0000, 0x6000,
+	0xc0d4, 0xc0dc, 0x6002, 0x1078, 0x3ed6, 0x0040, 0x571c, 0x7e24,
+	0x86ff, 0x0040, 0x570e, 0xa680, 0x0004, 0x2004, 0xad06, 0x00c0,
+	0x570e, 0x0d7e, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x5705,
+	0x1078, 0x516f, 0x1078, 0x6232, 0x68c3, 0x0000, 0x1078, 0x6741,
+	0x7827, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000,
+	0x0040, 0x56ee, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100,
+	0x6824, 0xd084, 0x0040, 0x56f6, 0x6827, 0x0001, 0x037f, 0x0d7f,
+	0x0c7e, 0x603c, 0xa005, 0x0040, 0x56ff, 0x8001, 0x603e, 0x2660,
+	0x1078, 0x79a8, 0x0c7f, 0x0078, 0x570e, 0x0d7f, 0x0c7e, 0x2660,
+	0x6003, 0x0009, 0x630a, 0x0c7f, 0x0078, 0x56c3, 0x8dff, 0x0040,
+	0x5718, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x4376,
+	0x1078, 0x6601, 0x0078, 0x56c3, 0x007f, 0x0078, 0x56b6, 0x781e,
+	0x781a, 0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c, 0x0e7e, 0x0d7e,
+	0x067e, 0x6000, 0xd0dc, 0x0040, 0x5743, 0x604c, 0xa06d, 0x0040,
+	0x5743, 0x6848, 0xa606, 0x00c0, 0x5743, 0x2071, 0x8aa2, 0x7024,
+	0xa035, 0x0040, 0x5743, 0xa080, 0x0004, 0x2004, 0xad06, 0x00c0,
+	0x5743, 0x1078, 0x5747, 0x067f, 0x0d7f, 0x0e7f, 0x007c, 0x0f7e,
+	0x2079, 0x0100, 0x78c0, 0xa005, 0x00c0, 0x5756, 0x0c7e, 0x2660,
+	0x6003, 0x0009, 0x630a, 0x0c7f, 0x0078, 0x578d, 0x1078, 0x6232,
+	0x78c3, 0x0000, 0x1078, 0x6741, 0x7027, 0x0000, 0x037e, 0x2079,
+	0x0140, 0x7b04, 0xa384, 0x1000, 0x0040, 0x576a, 0x7803, 0x0100,
+	0x7803, 0x0000, 0x2079, 0x0100, 0x7824, 0xd084, 0x0040, 0x5772,
+	0x7827, 0x0001, 0x1078, 0x6741, 0x037f, 0x1078, 0x3ed6, 0x0c7e,
+	0x603c, 0xa005, 0x0040, 0x577e, 0x8001, 0x603e, 0x2660, 0x1078,
+	0x690e, 0x0c7f, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078,
+	0x7a46, 0x1078, 0x4376, 0x1078, 0x6601, 0x0f7f, 0x007c, 0x0e7e,
+	0x0c7e, 0x2071, 0x8aa2, 0x7004, 0xa084, 0x0007, 0x0079, 0x5798,
+	0x57a2, 0x57a5, 0x57be, 0x57da, 0x581f, 0x57a2, 0x57a2, 0x57a0,
+	0x1078, 0x12d2, 0x0c7f, 0x0e7f, 0x007c, 0x7024, 0xa065, 0x0040,
+	0x57b3, 0x7020, 0x8001, 0x7022, 0x600c, 0xa015, 0x0040, 0x57ba,
+	0x7216, 0x600f, 0x0000, 0x7007, 0x0000, 0x7027, 0x0000, 0x0c7f,
+	0x0e7f, 0x007c, 0x7216, 0x7212, 0x0078, 0x57b3, 0x6018, 0x2060,
+	0x1078, 0x3ed6, 0x6000, 0xc0dc, 0x6002, 0x7020, 0x8001, 0x7022,
+	0x0040, 0x57cf, 0x6054, 0xa015, 0x0040, 0x57d6, 0x721e, 0x7007,
+	0x0000, 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x7218, 0x721e,
+	0x0078, 0x57cf, 0x7024, 0xa065, 0x0040, 0x581c, 0x700c, 0xac06,
+	0x00c0, 0x57f1, 0x1078, 0x6601, 0x600c, 0xa015, 0x0040, 0x57ed,
+	0x720e, 0x600f, 0x0000, 0x0078, 0x581a, 0x720e, 0x720a, 0x0078,
+	0x581a, 0x7014, 0xac06, 0x00c0, 0x5804, 0x1078, 0x6601, 0x600c,
+	0xa015, 0x0040, 0x5800, 0x7216, 0x600f, 0x0000, 0x0078, 0x581a,
+	0x7216, 0x7212, 0x0078, 0x581a, 0x6018, 0x2060, 0x1078, 0x3ed6,
+	0x6000, 0xc0dc, 0x6002, 0x1078, 0x6601, 0x701c, 0xa065, 0x0040,
+	0x581a, 0x6054, 0xa015, 0x0040, 0x5818, 0x721e, 0x0078, 0x581a,
+	0x7218, 0x721e, 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x7024,
+	0xa065, 0x0040, 0x582c, 0x1078, 0x6601, 0x600c, 0xa015, 0x0040,
+	0x5833, 0x720e, 0x600f, 0x0000, 0x1078, 0x6741, 0x7027, 0x0000,
+	0x0c7f, 0x0e7f, 0x007c, 0x720e, 0x720a, 0x0078, 0x582c, 0x0d7e,
+	0x2069, 0x8aa2, 0x6830, 0xa084, 0x0003, 0x0079, 0x583f, 0x5845,
+	0x5847, 0x586d, 0x5845, 0x1078, 0x12d2, 0x0d7f, 0x007c, 0x0c7e,
+	0x6840, 0xa086, 0x0001, 0x0040, 0x5863, 0x683c, 0xa065, 0x0040,
+	0x5858, 0x600c, 0xa015, 0x0040, 0x585f, 0x6a3a, 0x600f, 0x0000,
+	0x6833, 0x0000, 0x683f, 0x0000, 0x0c7f, 0x0d7f, 0x007c, 0x683a,
+	0x6836, 0x0078, 0x5858, 0x6843, 0x0000, 0x6838, 0xa065, 0x0040,
+	0x5858, 0x6003, 0x0003, 0x0078, 0x5858, 0x0c7e, 0x6843, 0x0000,
+	0x6847, 0x0000, 0x683c, 0xa065, 0x0040, 0x5885, 0x600c, 0xa015,
+	0x0040, 0x5881, 0x6a3a, 0x600f, 0x0000, 0x683f, 0x0000, 0x0078,
+	0x5885, 0x683f, 0x0000, 0x683a, 0x6836, 0x0c7f, 0x0d7f, 0x007c,
+	0x0d7e, 0x2069, 0x8aa2, 0x6804, 0xa084, 0x0007, 0x0079, 0x5890,
+	0x589a, 0x5937, 0x5937, 0x5937, 0x5937, 0x5939, 0x5937, 0x5898,
+	0x1078, 0x12d2, 0x6820, 0xa005, 0x00c0, 0x58a0, 0x0d7f, 0x007c,
+	0x0c7e, 0x680c, 0xa065, 0x0040, 0x58af, 0x6807, 0x0004, 0x6826,
+	0x682b, 0x0000, 0x1078, 0x597f, 0x0c7f, 0x0d7f, 0x007c, 0x6814,
+	0xa065, 0x0040, 0x58bd, 0x6807, 0x0001, 0x6826, 0x682b, 0x0000,
+	0x1078, 0x597f, 0x0c7f, 0x0d7f, 0x007c, 0x0e7e, 0x037e, 0x6a1c,
+	0xa2f5, 0x0000, 0x0040, 0x5932, 0x704c, 0xa00d, 0x0040, 0x58cc,
+	0x7088, 0xa005, 0x0040, 0x58e4, 0x7054, 0xa075, 0x0040, 0x58d5,
+	0xa20e, 0x0040, 0x5932, 0x0078, 0x58da, 0x6818, 0xa20e, 0x0040,
+	0x5932, 0x2070, 0x704c, 0xa00d, 0x0040, 0x58cc, 0x7088, 0xa005,
+	0x00c0, 0x58cc, 0x2e00, 0x681e, 0x733c, 0x7038, 0xa302, 0x00c8,
+	0x58cc, 0x1078, 0x68dd, 0x0040, 0x5932, 0x8318, 0x733e, 0x6112,
+	0x2e10, 0x621a, 0xa180, 0x0015, 0x2004, 0xa08a, 0x199a, 0x0048,
+	0x58fb, 0x2001, 0x1999, 0x8003, 0x801b, 0x831b, 0xa318, 0x6316,
+	0x037f, 0x0f7e, 0x2c78, 0x71a0, 0xd1bc, 0x0040, 0x5914, 0x7100,
+	0xd1f4, 0x0040, 0x5910, 0x7114, 0xa18c, 0x00ff, 0x0078, 0x5919,
+	0x2009, 0x0000, 0x0078, 0x5919, 0xa1e0, 0x25b2, 0x2c0c, 0xa18c,
+	0x00ff, 0x2061, 0x0100, 0x619a, 0x1078, 0x5e16, 0x7300, 0xc3dd,
+	0x7302, 0x6807, 0x0002, 0x2f18, 0x6b26, 0x682b, 0x0000, 0x781f,
+	0x0003, 0x7803, 0x0001, 0x7807, 0x0040, 0x0f7f, 0x0e7f, 0x0c7f,
+	0x0d7f, 0x007c, 0x037f, 0x0e7f, 0x0c7f, 0x0078, 0x5930, 0x0d7f,
+	0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, 0x5945, 0x6807, 0x0004,
+	0x6826, 0x682b, 0x0000, 0x1078, 0x597f, 0x0c7f, 0x0d7f, 0x007c,
+	0x0f7e, 0x0d7e, 0x2069, 0x8aa2, 0x6830, 0xa086, 0x0000, 0x00c0,
+	0x5966, 0x6838, 0xa07d, 0x0040, 0x5966, 0x6833, 0x0001, 0x683e,
+	0x6847, 0x0000, 0x127e, 0x0f7e, 0x2091, 0x2200, 0x027f, 0x1078,
+	0x1b84, 0x00c0, 0x5969, 0x127f, 0x1078, 0x60fc, 0x0d7f, 0x0f7f,
+	0x007c, 0x127f, 0x6843, 0x0000, 0x7803, 0x0002, 0x780c, 0xa015,
+	0x0040, 0x597b, 0x6a3a, 0x780f, 0x0000, 0x6833, 0x0000, 0x683f,
+	0x0000, 0x0078, 0x5966, 0x683a, 0x6836, 0x0078, 0x5975, 0x601c,
+	0xa084, 0x000f, 0x1079, 0x5985, 0x007c, 0x598e, 0x5993, 0x5cc7,
+	0x5dd3, 0x5993, 0x5cc7, 0x5dd3, 0x598e, 0x5993, 0x1078, 0x578f,
+	0x1078, 0x5888, 0x007c, 0x157e, 0x137e, 0x147e, 0x0c7e, 0x0f7e,
+	0x6004, 0xa08a, 0x0040, 0x10c8, 0x12d2, 0x6118, 0x2178, 0x79a0,
+	0xd1bc, 0x0040, 0x59b0, 0x7900, 0xd1f4, 0x0040, 0x59ac, 0x7914,
+	0xa18c, 0x00ff, 0x0078, 0x59b5, 0x2009, 0x0000, 0x0078, 0x59b5,
+	0xa1f8, 0x25b2, 0x2f0c, 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100,
+	0x619a, 0x1079, 0x59c1, 0x0f7f, 0x0c7f, 0x147f, 0x137f, 0x157f,
+	0x007c, 0x5a08, 0x5a40, 0x5a58, 0x5ad7, 0x5b04, 0x5b0c, 0x5b2d,
+	0x5b3e, 0x5b4f, 0x5b57, 0x5b68, 0x5b57, 0x5bba, 0x5b3e, 0x5bdb,
+	0x5be3, 0x5b4f, 0x5be3, 0x5bf4, 0x5a01, 0x5a01, 0x5a01, 0x5a01,
+	0x5a01, 0x5a01, 0x5a01, 0x5a01, 0x5a01, 0x5a01, 0x5a01, 0x5a01,
+	0x62e5, 0x62fa, 0x631d, 0x6341, 0x5b2d, 0x5a01, 0x5b2d, 0x5b57,
+	0x5a01, 0x5a58, 0x5ad7, 0x5a01, 0x685b, 0x5b57, 0x5a01, 0x687b,
+	0x5b57, 0x5a01, 0x5a01, 0x5a03, 0x5a01, 0x5a01, 0x5a01, 0x5a01,
+	0x5a01, 0x5a01, 0x5a01, 0x5a01, 0x5a01, 0x5a01, 0x6356, 0x5a01,
+	0x5a01, 0x1078, 0x12d2, 0x6030, 0x609a, 0x1078, 0x621e, 0x007c,
+	0x20a1, 0x020b, 0x1078, 0x5c09, 0x20a3, 0x5200, 0x20a3, 0x0000,
+	0x0d7e, 0x2069, 0x8851, 0x6804, 0xd084, 0x0040, 0x5a22, 0x6828,
+	0x20a3, 0x0000, 0x017e, 0x1078, 0x225c, 0x21a2, 0x017f, 0x0d7f,
+	0x0078, 0x5a27, 0x0d7f, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9,
+	0x0004, 0x2099, 0x8805, 0x53a6, 0x20a9, 0x0004, 0x2099, 0x8801,
+	0x53a6, 0x20a3, 0x0000, 0x6030, 0xa084, 0x00ff, 0x20a2, 0x20a3,
+	0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x1078, 0x621e, 0x007c,
+	0x20a1, 0x020b, 0x1078, 0x5c09, 0x20a3, 0x0500, 0x20a3, 0x0000,
+	0x20a3, 0x0000, 0x6030, 0xa084, 0x00ff, 0x20a2, 0x20a9, 0x0004,
+	0x2099, 0x8805, 0x53a6, 0x60c3, 0x0010, 0x1078, 0x621e, 0x007c,
+	0x20a1, 0x020b, 0x1078, 0x5c09, 0x7818, 0xa080, 0x0028, 0x2004,
+	0xa086, 0x007e, 0x00c0, 0x5a6b, 0x20a3, 0x0400, 0x620c, 0xc2b4,
+	0x620e, 0x0078, 0x5a6d, 0x20a3, 0x0300, 0x20a3, 0x0000, 0x7818,
+	0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x00c0, 0x5aa6, 0x2099,
+	0x8a8c, 0x33a6, 0x9398, 0x33a6, 0x9398, 0x3304, 0xa084, 0x3fff,
+	0x20a2, 0x9398, 0x33a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
+	0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, 0x8805, 0x53a6,
+	0x20a9, 0x0004, 0x2099, 0x8801, 0x53a6, 0x20a9, 0x0010, 0x20a3,
+	0x0000, 0x00f0, 0x5a97, 0x2099, 0x8a94, 0x33a6, 0x20a9, 0x0007,
+	0x20a3, 0x0000, 0x00f0, 0x5aa0, 0x0078, 0x5ac6, 0x2099, 0x8a8c,
+	0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0004, 0x2099, 0x8805, 0x53a6,
+	0x20a9, 0x0004, 0x2099, 0x8801, 0x53a6, 0x20a9, 0x0008, 0x20a3,
+	0x0000, 0x00f0, 0x5ab7, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0,
+	0x5abd, 0x2099, 0x8a94, 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0008,
+	0x20a3, 0x0000, 0x00f0, 0x5ac8, 0x20a9, 0x000a, 0x20a3, 0x0000,
+	0x00f0, 0x5ace, 0x60c3, 0x0074, 0x1078, 0x621e, 0x007c, 0x20a1,
+	0x020b, 0x1078, 0x5c09, 0x20a3, 0x2010, 0x20a3, 0x0014, 0x20a3,
+	0x0800, 0x20a3, 0x2000, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2,
+	0x20a2, 0x0f7e, 0x2079, 0x8851, 0x7904, 0x0f7f, 0xd1ac, 0x00c0,
+	0x5af3, 0xa085, 0x0020, 0xd1a4, 0x0040, 0x5af8, 0xa085, 0x0010,
+	0xa085, 0x0002, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
+	0x0014, 0x1078, 0x621e, 0x007c, 0x20a1, 0x020b, 0x1078, 0x5c09,
+	0x20a3, 0x5000, 0x0078, 0x5a6d, 0x20a1, 0x020b, 0x1078, 0x5c09,
+	0x20a3, 0x2110, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0000,
+	0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000,
+	0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000,
+	0x60c3, 0x0014, 0x1078, 0x621e, 0x007c, 0x20a1, 0x020b, 0x1078,
+	0x5c87, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
+	0x0000, 0x60c3, 0x0004, 0x1078, 0x621e, 0x007c, 0x20a1, 0x020b,
+	0x1078, 0x5c87, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003,
+	0x20a3, 0x2a00, 0x60c3, 0x0008, 0x1078, 0x621e, 0x007c, 0x20a1,
+	0x020b, 0x1078, 0x5c87, 0x20a3, 0x0200, 0x0078, 0x5a6d, 0x20a1,
+	0x020b, 0x1078, 0x5c87, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3,
+	0x0003, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x621e, 0x007c,
+	0x0d7e, 0x20a1, 0x020b, 0x1078, 0x5c87, 0x20a3, 0x0210, 0x20a3,
+	0x0014, 0x20a3, 0x0800, 0x7818, 0x2068, 0x6894, 0xa086, 0x0014,
+	0x00c0, 0x5b8e, 0x6998, 0xa184, 0xc000, 0x00c0, 0x5b8a, 0xd1ec,
+	0x0040, 0x5b86, 0x20a3, 0x2100, 0x0078, 0x5b90, 0x20a3, 0x0100,
+	0x0078, 0x5b90, 0x20a3, 0x0400, 0x0078, 0x5b90, 0x20a3, 0x0700,
+	0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x0f7e, 0x2079,
+	0x8851, 0x7904, 0x0f7f, 0xd1ac, 0x00c0, 0x5ba0, 0xa085, 0x0020,
+	0xd1a4, 0x0040, 0x5ba5, 0xa085, 0x0010, 0x2009, 0x8873, 0x210c,
+	0xd184, 0x0040, 0x5baf, 0x699c, 0xd18c, 0x0040, 0x5bb1, 0xa085,
+	0x0002, 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x0014, 0x1078, 0x621e,
+	0x0d7f, 0x007c, 0x20a1, 0x020b, 0x1078, 0x5c87, 0x20a3, 0x0210,
+	0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0100, 0x20a3, 0x0000,
+	0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000,
+	0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014,
+	0x1078, 0x621e, 0x007c, 0x20a1, 0x020b, 0x1078, 0x5c87, 0x20a3,
+	0x0200, 0x0078, 0x5a0e, 0x20a1, 0x020b, 0x1078, 0x5c87, 0x20a3,
+	0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3,
+	0x0008, 0x1078, 0x621e, 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000,
+	0x20a1, 0x020b, 0x1078, 0x5c87, 0x20a3, 0x0100, 0x20a3, 0x0000,
+	0x20a3, 0x000b, 0x20a3, 0x0000, 0x60c3, 0x0008, 0x1078, 0x621e,
+	0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080,
+	0x0028, 0x2014, 0xa286, 0x007e, 0x00c0, 0x5c1c, 0x20a3, 0x22ff,
+	0x20a3, 0xfffe, 0x0078, 0x5c51, 0xa286, 0x007f, 0x00c0, 0x5c27,
+	0x0d7e, 0x20a3, 0x22ff, 0x20a3, 0xfffd, 0x0078, 0x5c3e, 0xd2bc,
+	0x0040, 0x5c46, 0xa286, 0x0080, 0x0d7e, 0x00c0, 0x5c35, 0x20a3,
+	0x22ff, 0x20a3, 0xfffc, 0x0078, 0x5c3e, 0xa2e8, 0x8934, 0x2d6c,
+	0x6810, 0xa085, 0x2200, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x881a,
+	0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x5c55, 0x0d7e, 0xa2e8,
+	0x8934, 0x2d6c, 0x6810, 0xa085, 0x2200, 0x20a2, 0x6814, 0x20a2,
+	0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0129, 0x20a3,
+	0x0000, 0x1078, 0x620d, 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3,
 	0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x027e,
 	0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a3, 0x02ff, 0x2011, 0xfffc,
-	0x22a2, 0x0d7e, 0x2069, 0x7719, 0x2da6, 0x8d68, 0x2da6, 0x0d7f,
-	0x20a3, 0x2029, 0x20a3, 0x0000, 0x0078, 0x5141, 0x20a3, 0x0100,
+	0x22a2, 0x0d7e, 0x2069, 0x881a, 0x2da6, 0x8d68, 0x2da6, 0x0d7f,
+	0x20a3, 0x2029, 0x20a3, 0x0000, 0x0078, 0x5c59, 0x20a3, 0x0100,
 	0x20a3, 0x0000, 0x20a3, 0xfc02, 0x20a3, 0x0000, 0x007c, 0x027e,
 	0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004,
-	0xa092, 0x007e, 0x0048, 0x518e, 0x0d7e, 0xa0e8, 0x7820, 0x2d6c,
-	0x6810, 0xa085, 0x2300, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x7719,
-	0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x5196, 0x20a3, 0x2300,
-	0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0198,
-	0x20a3, 0x0000, 0x1078, 0x5677, 0x22a2, 0x20a3, 0x0000, 0x7a08,
-	0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c,
-	0x0c7e, 0x0f7e, 0x6004, 0xa08a, 0x0085, 0x1048, 0x12cd, 0xa08a,
-	0x008c, 0x10c8, 0x12cd, 0x6118, 0x2178, 0x79a0, 0xd1bc, 0x0040,
-	0x51c6, 0x7900, 0xd1f4, 0x0040, 0x51c2, 0x7914, 0xa18c, 0x00ff,
-	0x0078, 0x51cb, 0x2009, 0x0000, 0x0078, 0x51cb, 0xa1f8, 0x2329,
-	0x2f0c, 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0xa082,
-	0x0085, 0x1079, 0x51d6, 0x0f7f, 0x0c7f, 0x007c, 0x51df, 0x51ea,
-	0x5204, 0x51dd, 0x51dd, 0x51dd, 0x51df, 0x1078, 0x12cd, 0x147e,
-	0x20a1, 0x020b, 0x1078, 0x5217, 0x60c3, 0x0000, 0x1078, 0x5688,
-	0x147f, 0x007c, 0x147e, 0x20a1, 0x020b, 0x1078, 0x5244, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, 0x2fa2, 0x20a3, 0x0000,
+	0xa092, 0x007e, 0x0048, 0x5ca6, 0x0d7e, 0xa0e8, 0x8934, 0x2d6c,
+	0x6810, 0xa085, 0x2300, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x881a,
+	0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x5cb5, 0x0d7e, 0xa0e8,
+	0x8934, 0x2d6c, 0x6810, 0xa085, 0x2300, 0x20a2, 0x6814, 0x20a2,
+	0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0198, 0x20a3,
+	0x0000, 0x1078, 0x620d, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2,
+	0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x0c7e,
+	0x0f7e, 0x6004, 0xa08a, 0x0085, 0x1048, 0x12d2, 0xa08a, 0x008c,
+	0x10c8, 0x12d2, 0x6118, 0x2178, 0x79a0, 0xd1bc, 0x0040, 0x5ce5,
+	0x7900, 0xd1f4, 0x0040, 0x5ce1, 0x7914, 0xa18c, 0x00ff, 0x0078,
+	0x5cea, 0x2009, 0x0000, 0x0078, 0x5cea, 0xa1f8, 0x25b2, 0x2f0c,
+	0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0xa082, 0x0085,
+	0x1079, 0x5cf5, 0x0f7f, 0x0c7f, 0x007c, 0x5cfe, 0x5d09, 0x5d24,
+	0x5cfc, 0x5cfc, 0x5cfc, 0x5cfe, 0x1078, 0x12d2, 0x147e, 0x20a1,
+	0x020b, 0x1078, 0x5d37, 0x60c3, 0x0000, 0x1078, 0x621e, 0x147f,
+	0x007c, 0x147e, 0x20a1, 0x020b, 0x1078, 0x5d6b, 0x20a3, 0x0000,
+	0x20a3, 0x0000, 0x7808, 0x20a2, 0x7810, 0x20a2, 0x20a3, 0x0000,
 	0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c,
-	0x1078, 0x5688, 0x147f, 0x007c, 0x147e, 0x20a1, 0x020b, 0x1078,
-	0x5271, 0x20a3, 0x0003, 0x20a3, 0x0300, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x60c3, 0x0004, 0x1078, 0x5688, 0x147f, 0x007c, 0x027e,
+	0x1078, 0x621e, 0x147f, 0x007c, 0x147e, 0x20a1, 0x020b, 0x1078,
+	0x5d9f, 0x20a3, 0x0003, 0x20a3, 0x0300, 0x20a3, 0x0000, 0x20a3,
+	0x0000, 0x60c3, 0x0004, 0x1078, 0x621e, 0x147f, 0x007c, 0x027e,
 	0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004,
-	0xa092, 0x007e, 0x0048, 0x5236, 0x0d7e, 0xa0e8, 0x7820, 0x2d6c,
-	0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x7719,
-	0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x523e, 0x20a3, 0x8100,
-	0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0009,
-	0x20a3, 0x0000, 0x0078, 0x5141, 0x027e, 0x20e1, 0x9080, 0x20e1,
-	0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e, 0x0048,
-	0x5263, 0x0d7e, 0xa0e8, 0x7820, 0x2d6c, 0x6810, 0xa085, 0x8400,
-	0x20a2, 0x6814, 0x20a2, 0x2069, 0x7719, 0x2da6, 0x8d68, 0x2da6,
-	0x0d7f, 0x0078, 0x526b, 0x20a3, 0x8400, 0x6298, 0x22a2, 0x20a3,
-	0x0000, 0x6230, 0x22a2, 0x20a3, 0x00d1, 0x20a3, 0x0000, 0x0078,
-	0x519a, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080,
-	0x0028, 0x2004, 0xa092, 0x007e, 0x0048, 0x5290, 0x0d7e, 0xa0e8,
-	0x7820, 0x2d6c, 0x6810, 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2,
-	0x2069, 0x7719, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x5298,
-	0x20a3, 0x8500, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2,
-	0x20a3, 0x00d1, 0x20a3, 0x0000, 0x0078, 0x519a, 0x0c7e, 0x0f7e,
-	0x2c78, 0x7804, 0xa08a, 0x0040, 0x1048, 0x12cd, 0xa08a, 0x0050,
-	0x10c8, 0x12cd, 0x7918, 0x2160, 0x61a0, 0xd1bc, 0x0040, 0x52bd,
-	0x6100, 0xd1f4, 0x0040, 0x52b9, 0x6114, 0xa18c, 0x00ff, 0x0078,
-	0x52c2, 0x2009, 0x0000, 0x0078, 0x52c2, 0xa1e0, 0x2329, 0x2c0c,
-	0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0xa082, 0x0040, 0x1079,
-	0x52cc, 0x0f7f, 0x0c7f, 0x007c, 0x52de, 0x53c4, 0x536c, 0x54ec,
-	0x52dc, 0x52dc, 0x52dc, 0x52dc, 0x52dc, 0x52dc, 0x52dc, 0x5933,
-	0x5944, 0x5955, 0x5966, 0x52dc, 0x1078, 0x12cd, 0x0d7e, 0x157e,
-	0x147e, 0x20a1, 0x020b, 0x1078, 0x532f, 0x7910, 0x2168, 0x6948,
-	0x21a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x694c, 0xa184, 0x0006,
-	0x8004, 0x20a2, 0xd1ac, 0x0040, 0x52f9, 0x20a3, 0x0002, 0x0078,
-	0x5305, 0xd1b4, 0x0040, 0x5300, 0x20a3, 0x0001, 0x0078, 0x5305,
-	0x20a3, 0x0000, 0x2230, 0x0078, 0x5307, 0x6a80, 0x6e7c, 0x20a9,
+	0xa092, 0x007e, 0x0048, 0x5d56, 0x0d7e, 0xa0e8, 0x8934, 0x2d6c,
+	0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x881a,
+	0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x5d65, 0x0d7e, 0xa0e8,
+	0x8934, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2,
+	0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0009, 0x20a3,
+	0x0000, 0x0078, 0x5c59, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000,
+	0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e, 0x0048, 0x5d8a,
+	0x0d7e, 0xa0e8, 0x8934, 0x2d6c, 0x6810, 0xa085, 0x8400, 0x20a2,
+	0x6814, 0x20a2, 0x2069, 0x881a, 0x2da6, 0x8d68, 0x2da6, 0x0d7f,
+	0x0078, 0x5d99, 0x0d7e, 0xa0e8, 0x8934, 0x2d6c, 0x6810, 0xa085,
+	0x8400, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230,
+	0x22a2, 0x20a3, 0x00d1, 0x20a3, 0x0000, 0x0078, 0x5cb9, 0x027e,
+	0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004,
+	0xa092, 0x007e, 0x0048, 0x5dbe, 0x0d7e, 0xa0e8, 0x8934, 0x2d6c,
+	0x6810, 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x881a,
+	0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x5dcd, 0x0d7e, 0xa0e8,
+	0x8934, 0x2d6c, 0x6810, 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2,
+	0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x00d1, 0x20a3,
+	0x0000, 0x0078, 0x5cb9, 0x0c7e, 0x0f7e, 0x2c78, 0x7804, 0xa08a,
+	0x0040, 0x1048, 0x12d2, 0xa08a, 0x0053, 0x10c8, 0x12d2, 0x7918,
+	0x2160, 0x61a0, 0xd1bc, 0x0040, 0x5df2, 0x6100, 0xd1f4, 0x0040,
+	0x5dee, 0x6114, 0xa18c, 0x00ff, 0x0078, 0x5df7, 0x2009, 0x0000,
+	0x0078, 0x5df7, 0xa1e0, 0x25b2, 0x2c0c, 0xa18c, 0x00ff, 0x2061,
+	0x0100, 0x619a, 0xa082, 0x0040, 0x1079, 0x5e01, 0x0f7f, 0x0c7f,
+	0x007c, 0x5e16, 0x5f1a, 0x5ebb, 0x6070, 0x5e14, 0x5e14, 0x5e14,
+	0x5e14, 0x5e14, 0x5e14, 0x5e14, 0x651a, 0x652b, 0x653c, 0x654d,
+	0x5e14, 0x5e14, 0x5e14, 0x6509, 0x1078, 0x12d2, 0x0d7e, 0x157e,
+	0x147e, 0x20a1, 0x020b, 0x1078, 0x5e77, 0x7910, 0x2168, 0x6948,
+	0x7922, 0x21a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x694c, 0xa184,
+	0x000f, 0x00c0, 0x5e2f, 0x2001, 0x0005, 0x0078, 0x5e39, 0xd184,
+	0x0040, 0x5e36, 0x2001, 0x0004, 0x0078, 0x5e39, 0xa084, 0x0006,
+	0x8004, 0x20a2, 0xd1ac, 0x0040, 0x5e41, 0x20a3, 0x0002, 0x0078,
+	0x5e4d, 0xd1b4, 0x0040, 0x5e48, 0x20a3, 0x0001, 0x0078, 0x5e4d,
+	0x20a3, 0x0000, 0x2230, 0x0078, 0x5e4f, 0x6a80, 0x6e7c, 0x20a9,
 	0x0008, 0xad80, 0x0017, 0x200c, 0x810f, 0x21a2, 0x8000, 0x00f0,
-	0x530b, 0x22a2, 0x26a2, 0x60c3, 0x0020, 0x20e1, 0x9080, 0x6014,
-	0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x2001, 0x7952, 0x2003,
-	0x07d0, 0x2001, 0x7951, 0x2003, 0x0009, 0x2001, 0x7957, 0x2003,
-	0x0002, 0x1078, 0x14fc, 0x147f, 0x157f, 0x0d7f, 0x007c, 0x20e1,
+	0x5e53, 0x22a2, 0x26a2, 0x60c3, 0x0020, 0x20e1, 0x9080, 0x6014,
+	0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x2001, 0x8abe, 0x2003,
+	0x07d0, 0x2001, 0x8abd, 0x2003, 0x0009, 0x2001, 0x8ac3, 0x2003,
+	0x0002, 0x1078, 0x1526, 0x147f, 0x157f, 0x0d7f, 0x007c, 0x20e1,
 	0x9080, 0x20e1, 0x4000, 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210,
 	0xa294, 0x00ff, 0x2202, 0x8217, 0x7818, 0xa080, 0x0028, 0x2004,
-	0xd0bc, 0x0040, 0x5355, 0x0d7e, 0xa0e8, 0x7820, 0x2d6c, 0x6810,
-	0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x7719, 0x2da6,
-	0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x535d, 0x20a3, 0x0600, 0x6198,
-	0x21a2, 0x20a3, 0x0000, 0x6130, 0x21a2, 0x20a3, 0x0829, 0x20a3,
-	0x0000, 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e,
-	0x20a1, 0x020b, 0x1078, 0x538c, 0x7810, 0x2068, 0x6860, 0x20a2,
-	0x685c, 0x20a2, 0x6880, 0x20a2, 0x687c, 0x20a2, 0xa006, 0x20a2,
-	0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x000c, 0x1078, 0x5688, 0x147f,
-	0x137f, 0x157f, 0x0d7f, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1,
-	0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x53aa,
-	0x0d7e, 0xa0e8, 0x7820, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2,
-	0x6814, 0x20a2, 0x2069, 0x7719, 0x2da6, 0x8d68, 0x2da6, 0x0d7f,
-	0x0078, 0x53b2, 0x20a3, 0x0500, 0x6298, 0x22a2, 0x20a3, 0x0000,
-	0x6230, 0x22a2, 0x20a3, 0x0889, 0x20a3, 0x0000, 0x1078, 0x5677,
-	0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x027f, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e,
-	0x20a1, 0x020b, 0x1078, 0x54b4, 0x7810, 0x2068, 0xa016, 0x22a2,
-	0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x7810, 0xa084, 0xf000, 0x00c0,
-	0x53e1, 0x7810, 0xa084, 0x0700, 0x8007, 0x1079, 0x53e9, 0x0078,
-	0x53e4, 0xa006, 0x1079, 0x53e9, 0x147f, 0x137f, 0x157f, 0x0d7f,
-	0x007c, 0x53f3, 0x5455, 0x5459, 0x547c, 0x5489, 0x549b, 0x549f,
-	0x53f1, 0x1078, 0x12cd, 0x017e, 0x037e, 0x694c, 0xa18c, 0x0003,
-	0xa186, 0x0000, 0x00c0, 0x5406, 0x6b78, 0x23a2, 0x6868, 0x20a2,
-	0x6864, 0x20a2, 0x037f, 0x017f, 0x0078, 0x5480, 0xa186, 0x0001,
-	0x00c0, 0x5450, 0x6b78, 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2,
+	0xd0bc, 0x0040, 0x5e9d, 0x0d7e, 0xa0e8, 0x8934, 0x2d6c, 0x6810,
+	0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x881a, 0x2da6,
+	0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x5eac, 0x0d7e, 0xa0e8, 0x8934,
+	0x2d6c, 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x0d7f,
+	0x20a3, 0x0000, 0x6130, 0x21a2, 0x20a3, 0x0829, 0x20a3, 0x0000,
+	0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000,
+	0x20a3, 0x0000, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x20a1,
+	0x020b, 0x1078, 0x5edb, 0x7810, 0x2068, 0x6860, 0x20a2, 0x685c,
+	0x20a2, 0x6880, 0x20a2, 0x687c, 0x20a2, 0xa006, 0x20a2, 0x20a2,
+	0x20a2, 0x20a2, 0x60c3, 0x000c, 0x1078, 0x621e, 0x147f, 0x137f,
+	0x157f, 0x0d7f, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000,
+	0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x5ef9, 0x0d7e,
+	0xa0e8, 0x8934, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, 0x6814,
+	0x20a2, 0x2069, 0x881a, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078,
+	0x5f08, 0x0d7e, 0xa0e8, 0x8934, 0x2d6c, 0x6810, 0xa085, 0x0500,
+	0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2,
+	0x20a3, 0x0889, 0x20a3, 0x0000, 0x1078, 0x620d, 0x22a2, 0x20a3,
+	0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000,
+	0x027f, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x20a1, 0x020b,
+	0x1078, 0x6031, 0x7810, 0x2068, 0xa016, 0x22a2, 0x22a2, 0x22a2,
+	0x22a2, 0x22a2, 0x7810, 0xa084, 0xf000, 0x00c0, 0x5f37, 0x7810,
+	0xa084, 0x0700, 0x8007, 0x1079, 0x5f3f, 0x0078, 0x5f3a, 0xa006,
+	0x1079, 0x5f3f, 0x147f, 0x137f, 0x157f, 0x0d7f, 0x007c, 0x5f49,
+	0x5fcf, 0x5fd3, 0x5ff6, 0x6003, 0x6018, 0x601c, 0x5f47, 0x1078,
+	0x12d2, 0x017e, 0x037e, 0x694c, 0xa18c, 0x0003, 0x0040, 0x5f54,
+	0xa186, 0x0003, 0x00c0, 0x5f5e, 0x6b78, 0x23a2, 0x6868, 0x20a2,
+	0x6864, 0x20a2, 0x037f, 0x017f, 0x0078, 0x5ffa, 0xa186, 0x0001,
+	0x10c0, 0x12d2, 0x6b78, 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2,
 	0x22a2, 0x6874, 0x20a2, 0x22a2, 0x687c, 0x20a2, 0x2009, 0x0018,
-	0xa384, 0x0300, 0x0040, 0x544f, 0xd3c4, 0x0040, 0x5421, 0x687c,
-	0xa108, 0xd3cc, 0x0040, 0x5426, 0x6874, 0xa108, 0x157e, 0x20a9,
+	0xa384, 0x0300, 0x0040, 0x5fc9, 0xd3c4, 0x0040, 0x5f79, 0x687c,
+	0xa108, 0xd3cc, 0x0040, 0x5f7e, 0x6874, 0xa108, 0x157e, 0x20a9,
 	0x000d, 0xad80, 0x0020, 0x201c, 0x831f, 0x23a2, 0x8000, 0x00f0,
-	0x542b, 0x157f, 0x22a2, 0x22a2, 0x22a2, 0xa184, 0x0003, 0x0040,
-	0x544f, 0x20a1, 0x020b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a3,
-	0x0700, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3,
-	0x0898, 0x20a2, 0x1078, 0x5677, 0x22a2, 0x20a3, 0x0000, 0x61c2,
-	0x037f, 0x017f, 0x1078, 0x5688, 0x007c, 0x20a3, 0x0008, 0x0078,
-	0x547e, 0x20a3, 0x0302, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0012,
-	0x22a2, 0x20a3, 0x0008, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3,
-	0x7000, 0x20a3, 0x0500, 0x22a2, 0x20a3, 0x000a, 0x22a2, 0x22a2,
-	0x20a3, 0x2500, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3,
-	0x0032, 0x1078, 0x5688, 0x007c, 0x20a3, 0x0028, 0x22a2, 0x22a2,
-	0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0018, 0x1078, 0x5688,
-	0x007c, 0x20a3, 0x0100, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2,
-	0x20a3, 0x0008, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0020,
-	0x1078, 0x5688, 0x007c, 0x20a3, 0x0008, 0x0078, 0x547e, 0x037e,
-	0x7b10, 0xa384, 0xff00, 0x7812, 0xa384, 0x00ff, 0x8001, 0x00c0,
-	0x54ad, 0x22a2, 0x037f, 0x0078, 0x547e, 0x20a3, 0x0800, 0x22a2,
-	0x20a2, 0x037f, 0x0078, 0x5480, 0x027e, 0x20e1, 0x9080, 0x20e1,
-	0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x54d2,
-	0x0d7e, 0xa0e8, 0x7820, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2,
-	0x6814, 0x20a2, 0x2069, 0x7719, 0x2da6, 0x8d68, 0x2da6, 0x0d7f,
-	0x0078, 0x54da, 0x20a3, 0x0700, 0x6298, 0x22a2, 0x20a3, 0x0000,
-	0x6230, 0x22a2, 0x20a3, 0x0898, 0x20a3, 0x0000, 0x1078, 0x5677,
+	0x5f83, 0x157f, 0x22a2, 0x22a2, 0x22a2, 0xa184, 0x0003, 0x0040,
+	0x5fc9, 0x20a1, 0x020b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x007e,
+	0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x5fb1, 0x0d7e,
+	0xa0e8, 0x8934, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814,
+	0x20a2, 0x2069, 0x881a, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078,
+	0x5fc0, 0x0d7e, 0xa0e8, 0x8934, 0x2d6c, 0x6810, 0xa085, 0x0700,
+	0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2,
+	0x007f, 0x20a3, 0x0898, 0x20a2, 0x1078, 0x620d, 0x22a2, 0x20a3,
+	0x0000, 0x61c2, 0x037f, 0x017f, 0x1078, 0x621e, 0x007c, 0x20a3,
+	0x0008, 0x0078, 0x5ff8, 0x20a3, 0x0302, 0x22a2, 0x22a2, 0x22a2,
+	0x20a3, 0x0012, 0x22a2, 0x20a3, 0x0008, 0x22a2, 0x22a2, 0x22a2,
+	0x22a2, 0x20a3, 0x7000, 0x20a3, 0x0500, 0x22a2, 0x20a3, 0x000a,
+	0x22a2, 0x22a2, 0x20a3, 0x2500, 0x22a2, 0x22a2, 0x22a2, 0x22a2,
+	0x22a2, 0x60c3, 0x0032, 0x1078, 0x621e, 0x007c, 0x20a3, 0x0028,
+	0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0018,
+	0x1078, 0x621e, 0x007c, 0x20a3, 0x0100, 0x22a2, 0x22a2, 0x22a2,
+	0x22a2, 0x22a2, 0x20a3, 0x0008, 0x22a2, 0x7824, 0xa084, 0x00ff,
+	0x20a2, 0x22a2, 0x22a2, 0x60c3, 0x0020, 0x1078, 0x621e, 0x007c,
+	0x20a3, 0x0008, 0x0078, 0x5ff8, 0x037e, 0x7b10, 0xa384, 0xff00,
+	0x7812, 0xa384, 0x00ff, 0x8001, 0x00c0, 0x602a, 0x22a2, 0x037f,
+	0x0078, 0x5ff8, 0x20a3, 0x0800, 0x22a2, 0x20a2, 0x037f, 0x0078,
+	0x5ffa, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080,
+	0x0028, 0x2004, 0xd0bc, 0x0040, 0x604f, 0x0d7e, 0xa0e8, 0x8934,
+	0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x2069,
+	0x881a, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x605e, 0x0d7e,
+	0xa0e8, 0x8934, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814,
+	0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0898,
+	0x20a3, 0x0000, 0x1078, 0x620d, 0x22a2, 0x20a3, 0x0000, 0x7a08,
+	0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c,
+	0x0d7e, 0x157e, 0x137e, 0x147e, 0x017e, 0x037e, 0x7810, 0xa084,
+	0x0700, 0x8007, 0x1079, 0x6083, 0x037f, 0x017f, 0x147f, 0x137f,
+	0x157f, 0x0d7f, 0x007c, 0x608b, 0x608b, 0x608d, 0x608b, 0x608b,
+	0x608b, 0x60b2, 0x608b, 0x1078, 0x12d2, 0x7910, 0xa18c, 0xf8ff,
+	0xa18d, 0x0600, 0x7912, 0x20a1, 0x020b, 0x2009, 0x0003, 0x1078,
+	0x60bc, 0x0d7e, 0x2069, 0x8851, 0x6804, 0xd0bc, 0x0040, 0x60a7,
+	0x682c, 0xa084, 0x00ff, 0x8007, 0x20a2, 0x0078, 0x60a9, 0x20a3,
+	0x3f00, 0x0d7f, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0001, 0x1078,
+	0x621e, 0x007c, 0x20a1, 0x020b, 0x2009, 0x0003, 0x1078, 0x60bc,
+	0x20a3, 0x7f00, 0x0078, 0x60aa, 0x027e, 0x20e1, 0x9080, 0x20e1,
+	0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x60da,
+	0x0d7e, 0xa0e8, 0x8934, 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2,
+	0x6814, 0x20a2, 0x2069, 0x881a, 0x2da6, 0x8d68, 0x2da6, 0x0d7f,
+	0x0078, 0x60e9, 0x0d7e, 0xa0e8, 0x8934, 0x2d6c, 0x6810, 0xa085,
+	0x0100, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230,
+	0x22a2, 0x20a3, 0x0888, 0xa18d, 0x0008, 0x21a2, 0x1078, 0x620d,
 	0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x027f, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e,
-	0x017e, 0x037e, 0x7810, 0xa084, 0x0700, 0x8007, 0x1079, 0x54ff,
-	0x037f, 0x017f, 0x147f, 0x137f, 0x157f, 0x0d7f, 0x007c, 0x5507,
-	0x5507, 0x5509, 0x5507, 0x5507, 0x5507, 0x552e, 0x5507, 0x1078,
-	0x12cd, 0x7910, 0xa18c, 0xf8ff, 0xa18d, 0x0600, 0x7912, 0x20a1,
-	0x020b, 0x2009, 0x0003, 0x1078, 0x5538, 0x0d7e, 0x2069, 0x7751,
-	0x6804, 0xd0bc, 0x0040, 0x5523, 0x682c, 0xa084, 0x00ff, 0x8007,
-	0x20a2, 0x0078, 0x5525, 0x20a3, 0x3f00, 0x0d7f, 0x22a2, 0x22a2,
-	0x22a2, 0x60c3, 0x0001, 0x1078, 0x5688, 0x007c, 0x20a1, 0x020b,
-	0x2009, 0x0003, 0x1078, 0x5538, 0x20a3, 0x7f00, 0x0078, 0x5526,
-	0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
-	0x2004, 0xd0bc, 0x0040, 0x5556, 0x0d7e, 0xa0e8, 0x7820, 0x2d6c,
-	0x6810, 0xa085, 0x0100, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x7719,
-	0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x555e, 0x20a3, 0x0100,
-	0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0888,
-	0xa18d, 0x0008, 0x21a2, 0x1078, 0x5677, 0x22a2, 0x20a3, 0x0000,
-	0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f,
-	0x007c, 0x0e7e, 0x0d7e, 0x0c7e, 0x057e, 0x047e, 0x037e, 0x2061,
-	0x0100, 0x2071, 0x7700, 0x6130, 0x7818, 0x2068, 0x68a0, 0x2028,
-	0xd0bc, 0x00c0, 0x558a, 0xa080, 0x2329, 0x2014, 0xa294, 0x00ff,
-	0x0078, 0x558e, 0x6910, 0x6a14, 0x7364, 0x7468, 0x781c, 0xa086,
-	0x0006, 0x0040, 0x55e2, 0xd5bc, 0x0040, 0x559e, 0xa185, 0x0100,
-	0x6062, 0x6266, 0x636a, 0x646e, 0x0078, 0x55a4, 0x6063, 0x0100,
-	0x6266, 0x606b, 0x0000, 0x616e, 0x6073, 0x0809, 0x6077, 0x0008,
-	0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f,
-	0x0000, 0x2f00, 0x6082, 0x7808, 0x6086, 0x7810, 0x2070, 0x7014,
-	0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008, 0x60ca, 0x686c,
-	0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xa582,
-	0x0080, 0x0048, 0x55d6, 0x6a00, 0xd2f4, 0x0040, 0x55d4, 0x6a14,
-	0xa294, 0x00ff, 0x0078, 0x55d6, 0x2011, 0x0000, 0x629e, 0x6017,
-	0x0016, 0x1078, 0x470b, 0x037f, 0x047f, 0x057f, 0x0c7f, 0x0d7f,
-	0x0e7f, 0x007c, 0x7810, 0x2070, 0x704c, 0xa084, 0x0003, 0xa086,
-	0x0002, 0x0040, 0x5631, 0xd5bc, 0x0040, 0x55f6, 0xa185, 0x0100,
-	0x6062, 0x6266, 0x636a, 0x646e, 0x0078, 0x55fc, 0x6063, 0x0100,
-	0x6266, 0x606b, 0x0000, 0x616e, 0x6073, 0x0880, 0x6077, 0x0008,
-	0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f,
-	0x0000, 0x2f00, 0x6086, 0x7808, 0x6082, 0x7060, 0x608a, 0x705c,
-	0x608e, 0x7080, 0x60c6, 0x707c, 0x60ca, 0x686c, 0x60ce, 0x60ab,
-	0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xa582, 0x0080, 0x0048,
-	0x562c, 0x6a00, 0xd2f4, 0x0040, 0x562a, 0x6a14, 0xa294, 0x00ff,
-	0x0078, 0x562c, 0x2011, 0x0000, 0x629e, 0x6017, 0x0012, 0x0078,
-	0x55d9, 0xd5bc, 0x0040, 0x563c, 0xa185, 0x0700, 0x6062, 0x6266,
-	0x636a, 0x646e, 0x0078, 0x5642, 0x6063, 0x0700, 0x6266, 0x606b,
-	0x0000, 0x616e, 0x6073, 0x0898, 0x6077, 0x0000, 0x688c, 0x8000,
-	0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00,
-	0x6086, 0x7808, 0x6082, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c,
-	0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af,
-	0x95d5, 0x60d7, 0x0000, 0xa582, 0x0080, 0x0048, 0x5672, 0x6a00,
-	0xd2f4, 0x0040, 0x5670, 0x6a14, 0xa294, 0x00ff, 0x0078, 0x5672,
-	0x2011, 0x0000, 0x629e, 0x6017, 0x0016, 0x0078, 0x55d9, 0x7a18,
-	0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202, 0x8217,
-	0x007c, 0x0d7e, 0x2069, 0x7936, 0x6843, 0x0001, 0x0d7f, 0x007c,
-	0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x1078, 0x5693,
-	0x1078, 0x46fb, 0x007c, 0x007e, 0x6014, 0xa084, 0x0004, 0xa085,
-	0x0009, 0x6016, 0x007f, 0x007c, 0x007e, 0x0c7e, 0x2061, 0x0100,
-	0x6014, 0xa084, 0x0004, 0xa085, 0x0008, 0x6016, 0x0c7f, 0x007f,
-	0x007c, 0x0c7e, 0x0d7e, 0x017e, 0x027e, 0x1078, 0x4706, 0x2061,
-	0x0100, 0x2069, 0x0140, 0x6904, 0xa194, 0x4000, 0x0040, 0x56e6,
-	0x1078, 0x569c, 0x6803, 0x1000, 0x6803, 0x0000, 0x0c7e, 0x2061,
-	0x7936, 0x6128, 0xa192, 0x0002, 0x00c8, 0x56d3, 0x8108, 0x612a,
-	0x6124, 0x0c7f, 0x81ff, 0x0040, 0x56e1, 0x1078, 0x46fb, 0x1078,
-	0x5693, 0x0078, 0x56e1, 0x6124, 0xa1e5, 0x0000, 0x0040, 0x56de,
-	0x1078, 0x76c7, 0x2009, 0x0014, 0x1078, 0x5d41, 0x0c7f, 0x0078,
-	0x56e1, 0x027f, 0x017f, 0x0d7f, 0x0c7f, 0x007c, 0x1078, 0x3591,
-	0x0078, 0x56e1, 0x0c7e, 0x0d7e, 0x0e7e, 0x017e, 0x027e, 0x1078,
-	0x4714, 0x2071, 0x7936, 0x713c, 0x81ff, 0x0040, 0x5714, 0x2061,
-	0x0100, 0x2069, 0x0140, 0x6904, 0xa194, 0x4000, 0x0040, 0x571a,
-	0x6803, 0x1000, 0x6803, 0x0000, 0x037e, 0x2019, 0x0001, 0x1078,
-	0x5880, 0x037f, 0x713c, 0x2160, 0x1078, 0x76c7, 0x2009, 0x004a,
-	0x1078, 0x5d41, 0x0078, 0x5714, 0x027f, 0x017f, 0x0e7f, 0x0d7f,
-	0x0c7f, 0x007c, 0x7144, 0xa192, 0x0002, 0x00c8, 0x5704, 0x8108,
-	0x7146, 0x1078, 0x470b, 0x0078, 0x5714, 0x0e7e, 0x0d7e, 0x0c7e,
-	0x067e, 0x057e, 0x047e, 0x007e, 0x127e, 0x2091, 0x8000, 0x6018,
-	0x2068, 0x6ca0, 0x2071, 0x7936, 0x7018, 0x2068, 0x8dff, 0x0040,
-	0x574f, 0x68a0, 0xa406, 0x0040, 0x5741, 0x6854, 0x2068, 0x0078,
-	0x5736, 0x6010, 0x2060, 0x643c, 0x6540, 0x6e48, 0x2d60, 0x1078,
-	0x3991, 0x0040, 0x574f, 0x1078, 0x5a1a, 0xa085, 0x0001, 0x127f,
-	0x007f, 0x047f, 0x057f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c,
-	0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x50f8, 0x20a3, 0x0f00,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, 0x60c3, 0x0008,
-	0x1078, 0x5688, 0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x20a1,
-	0x020b, 0x1078, 0x516f, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a9,
-	0x0006, 0x2011, 0x7740, 0x2019, 0x7741, 0x23a6, 0x22a6, 0xa398,
-	0x0002, 0xa290, 0x0002, 0x00f0, 0x577d, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x60c3, 0x001c, 0x1078, 0x5688, 0x147f, 0x157f, 0x007c,
-	0x157e, 0x147e, 0x017e, 0x027e, 0x20a1, 0x020b, 0x1078, 0x514f,
-	0x1078, 0x5166, 0x7810, 0x007e, 0xa080, 0x0015, 0x2098, 0x7808,
-	0xa088, 0x0002, 0x21a8, 0x53a6, 0xa080, 0x0004, 0x8003, 0x60c2,
-	0x007f, 0xa080, 0x0001, 0x2004, 0x7812, 0x1078, 0x5688, 0x027f,
-	0x017f, 0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b,
-	0x1078, 0x50f8, 0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x7808, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x5688, 0x147f, 0x157f,
-	0x007c, 0x0e7e, 0x0c7e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071,
-	0x7936, 0x700c, 0x2060, 0x8cff, 0x0040, 0x57e5, 0x1078, 0x6be3,
-	0x00c0, 0x57dc, 0x1078, 0x5f6d, 0x600c, 0x007e, 0x1078, 0x5d1a,
-	0x1078, 0x5a1a, 0x0c7f, 0x0078, 0x57d3, 0x700f, 0x0000, 0x700b,
-	0x0000, 0x127f, 0x007f, 0x0c7f, 0x0e7f, 0x007c, 0x127e, 0x157e,
-	0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x027e, 0x017e, 0x007e, 0x2091,
-	0x8000, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, 0x7936, 0x7024,
-	0x2060, 0x8cff, 0x0040, 0x583e, 0x1078, 0x569c, 0x68c3, 0x0000,
-	0x1078, 0x4706, 0x2009, 0x0013, 0x1078, 0x5d41, 0x20a9, 0x01f4,
-	0x6824, 0xd094, 0x0040, 0x5821, 0x6827, 0x0004, 0x7804, 0xa084,
-	0x4000, 0x0040, 0x5833, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078,
-	0x5833, 0xd084, 0x0040, 0x5828, 0x6827, 0x0001, 0x0078, 0x582a,
-	0x00f0, 0x5810, 0x7804, 0xa084, 0x1000, 0x0040, 0x5833, 0x7803,
+	0x20a3, 0x0000, 0x027f, 0x007c, 0x0e7e, 0x0d7e, 0x0c7e, 0x057e,
+	0x047e, 0x037e, 0x2061, 0x0100, 0x2071, 0x8800, 0x6130, 0x7818,
+	0x2068, 0x68a0, 0x2028, 0xd0bc, 0x00c0, 0x6113, 0x6910, 0x6a14,
+	0x6430, 0x0078, 0x6117, 0x6910, 0x6a14, 0x7368, 0x746c, 0x781c,
+	0xa086, 0x0006, 0x0040, 0x6176, 0xd5bc, 0x0040, 0x6127, 0xa185,
+	0x0100, 0x6062, 0x6266, 0x636a, 0x646e, 0x0078, 0x612e, 0xa185,
+	0x0100, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x6073, 0x0809,
+	0x6077, 0x0008, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007,
+	0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, 0x6086, 0x7810,
+	0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008,
+	0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7,
+	0x0000, 0xa582, 0x0080, 0x0048, 0x6160, 0x6a00, 0xd2f4, 0x0040,
+	0x615e, 0x6a14, 0xa294, 0x00ff, 0x0078, 0x6160, 0x2011, 0x0000,
+	0x629e, 0x6017, 0x0016, 0x2009, 0x07d0, 0x60c4, 0xa084, 0xfff0,
+	0xa005, 0x0040, 0x616d, 0x2009, 0x1b58, 0x1078, 0x5174, 0x037f,
+	0x047f, 0x057f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x7810, 0x2070,
+	0x704c, 0xa084, 0x0003, 0xa086, 0x0002, 0x0040, 0x61c6, 0xd5bc,
+	0x0040, 0x618a, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e,
+	0x0078, 0x6191, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000,
+	0x646e, 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084,
+	0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086,
+	0x7808, 0x6082, 0x7060, 0x608a, 0x705c, 0x608e, 0x7080, 0x60c6,
+	0x707c, 0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5,
+	0x60d7, 0x0000, 0xa582, 0x0080, 0x0048, 0x61c1, 0x6a00, 0xd2f4,
+	0x0040, 0x61bf, 0x6a14, 0xa294, 0x00ff, 0x0078, 0x61c1, 0x2011,
+	0x0000, 0x629e, 0x6017, 0x0012, 0x0078, 0x6163, 0xd5bc, 0x0040,
+	0x61d1, 0xa185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e, 0x0078,
+	0x61d8, 0xa185, 0x0700, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e,
+	0x6073, 0x0898, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff,
+	0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808,
+	0x6082, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008,
+	0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7,
+	0x0000, 0xa582, 0x0080, 0x0048, 0x6208, 0x6a00, 0xd2f4, 0x0040,
+	0x6206, 0x6a14, 0xa294, 0x00ff, 0x0078, 0x6208, 0x2011, 0x0000,
+	0x629e, 0x6017, 0x0016, 0x0078, 0x6163, 0x7a18, 0xa280, 0x0023,
+	0x2014, 0x8210, 0xa294, 0x00ff, 0x2202, 0x8217, 0x007c, 0x0d7e,
+	0x2069, 0x8aa2, 0x6843, 0x0001, 0x0d7f, 0x007c, 0x20e1, 0x9080,
+	0x60a3, 0x0056, 0x60a7, 0x9575, 0x1078, 0x6229, 0x1078, 0x5164,
+	0x007c, 0x007e, 0x6014, 0xa084, 0x0004, 0xa085, 0x0009, 0x6016,
+	0x007f, 0x007c, 0x007e, 0x0c7e, 0x2061, 0x0100, 0x6014, 0xa084,
+	0x0004, 0xa085, 0x0008, 0x6016, 0x0c7f, 0x007f, 0x007c, 0x0c7e,
+	0x0d7e, 0x017e, 0x027e, 0x1078, 0x516f, 0x2061, 0x0100, 0x2069,
+	0x0140, 0x6904, 0xa194, 0x4000, 0x0040, 0x627c, 0x1078, 0x6232,
+	0x6803, 0x1000, 0x6803, 0x0000, 0x0c7e, 0x2061, 0x8aa2, 0x6128,
+	0xa192, 0x0002, 0x00c8, 0x6269, 0x8108, 0x612a, 0x6124, 0x0c7f,
+	0x81ff, 0x0040, 0x6277, 0x1078, 0x5164, 0x1078, 0x6229, 0x0078,
+	0x6277, 0x6124, 0xa1e5, 0x0000, 0x0040, 0x6274, 0x1078, 0x8781,
+	0x2009, 0x0014, 0x1078, 0x6939, 0x0c7f, 0x0078, 0x6277, 0x027f,
+	0x017f, 0x0d7f, 0x0c7f, 0x007c, 0x1078, 0x3c73, 0x0078, 0x6277,
+	0x0c7e, 0x0d7e, 0x0e7e, 0x017e, 0x027e, 0x1078, 0x517c, 0x2071,
+	0x8aa2, 0x713c, 0x81ff, 0x0040, 0x62aa, 0x2061, 0x0100, 0x2069,
+	0x0140, 0x6904, 0xa194, 0x4000, 0x0040, 0x62b0, 0x6803, 0x1000,
+	0x6803, 0x0000, 0x037e, 0x2019, 0x0001, 0x1078, 0x642d, 0x037f,
+	0x713c, 0x2160, 0x1078, 0x8781, 0x2009, 0x004a, 0x1078, 0x6939,
+	0x0078, 0x62aa, 0x027f, 0x017f, 0x0e7f, 0x0d7f, 0x0c7f, 0x007c,
+	0x0078, 0x629a, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x057e, 0x047e,
+	0x007e, 0x127e, 0x2091, 0x8000, 0x6018, 0x2068, 0x6ca0, 0x2071,
+	0x8aa2, 0x7018, 0x2068, 0x8dff, 0x0040, 0x62dc, 0x68a0, 0xa406,
+	0x0040, 0x62ce, 0x6854, 0x2068, 0x0078, 0x62c3, 0x6010, 0x2060,
+	0x643c, 0x6540, 0x6e48, 0x2d60, 0x1078, 0x40da, 0x0040, 0x62dc,
+	0x1078, 0x6601, 0xa085, 0x0001, 0x127f, 0x007f, 0x047f, 0x057f,
+	0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x157e, 0x147e, 0x20a1,
+	0x020b, 0x1078, 0x5c09, 0x20a3, 0x0f00, 0x20a3, 0x0000, 0x20a3,
+	0x0000, 0x7808, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x621e, 0x147f,
+	0x157f, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x5c87,
+	0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a9, 0x0006, 0x2011, 0x8840,
+	0x2019, 0x8841, 0x23a6, 0x22a6, 0xa398, 0x0002, 0xa290, 0x0002,
+	0x00f0, 0x630a, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c,
+	0x1078, 0x621e, 0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x017e,
+	0x027e, 0x20a1, 0x020b, 0x1078, 0x5c67, 0x1078, 0x5c7e, 0x7810,
+	0x007e, 0xa080, 0x0015, 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8,
+	0x53a6, 0xa080, 0x0004, 0x8003, 0x60c2, 0x007f, 0xa080, 0x0001,
+	0x2004, 0x7812, 0x1078, 0x621e, 0x027f, 0x017f, 0x147f, 0x157f,
+	0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x5c09, 0x20a3,
+	0x6200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, 0x60c3,
+	0x0008, 0x1078, 0x621e, 0x147f, 0x157f, 0x007c, 0x157e, 0x147e,
+	0x017e, 0x027e, 0x20a1, 0x020b, 0x1078, 0x5c09, 0x7810, 0x007e,
+	0xa080, 0x0017, 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6,
+	0x8003, 0x60c2, 0x007f, 0xa080, 0x0001, 0x2004, 0x7812, 0x1078,
+	0x621e, 0x027f, 0x017f, 0x147f, 0x157f, 0x007c, 0x0e7e, 0x0c7e,
+	0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0x8aa2, 0x700c, 0x2060,
+	0x8cff, 0x0040, 0x6392, 0x1078, 0x79d5, 0x00c0, 0x6389, 0x1078,
+	0x6bc7, 0x600c, 0x007e, 0x1078, 0x690e, 0x1078, 0x6601, 0x0c7f,
+	0x0078, 0x6380, 0x700f, 0x0000, 0x700b, 0x0000, 0x127f, 0x007f,
+	0x0c7f, 0x0e7f, 0x007c, 0x127e, 0x157e, 0x0f7e, 0x0e7e, 0x0d7e,
+	0x0c7e, 0x027e, 0x017e, 0x007e, 0x2091, 0x8000, 0x2069, 0x0100,
+	0x2079, 0x0140, 0x2071, 0x8aa2, 0x7024, 0x2060, 0x8cff, 0x0040,
+	0x63eb, 0x1078, 0x6232, 0x68c3, 0x0000, 0x1078, 0x516f, 0x2009,
+	0x0013, 0x1078, 0x6939, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0040,
+	0x63ce, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x0040, 0x63e0,
+	0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0x63e0, 0xd084, 0x0040,
+	0x63d5, 0x6827, 0x0001, 0x0078, 0x63d7, 0x00f0, 0x63bd, 0x7804,
+	0xa084, 0x1000, 0x0040, 0x63e0, 0x7803, 0x0100, 0x7803, 0x0000,
+	0x6824, 0x007f, 0x017f, 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f,
+	0x157f, 0x127f, 0x007c, 0x2001, 0x8800, 0x2004, 0xa096, 0x0001,
+	0x0040, 0x6423, 0xa096, 0x0004, 0x0040, 0x6423, 0x6817, 0x0008,
+	0x68c3, 0x0000, 0x2011, 0x3c35, 0x1078, 0x50f2, 0x20a9, 0x01f4,
+	0x6824, 0xd094, 0x0040, 0x6411, 0x6827, 0x0004, 0x7804, 0xa084,
+	0x4000, 0x0040, 0x6423, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078,
+	0x6423, 0xd084, 0x0040, 0x6418, 0x6827, 0x0001, 0x0078, 0x641a,
+	0x00f0, 0x6400, 0x7804, 0xa084, 0x1000, 0x0040, 0x6423, 0x7803,
+	0x0100, 0x7803, 0x0000, 0x007f, 0x017f, 0x027f, 0x0c7f, 0x0d7f,
+	0x0e7f, 0x0f7f, 0x157f, 0x127f, 0x007c, 0x127e, 0x157e, 0x0f7e,
+	0x0e7e, 0x0d7e, 0x0c7e, 0x027e, 0x017e, 0x007e, 0x2091, 0x8000,
+	0x2069, 0x0100, 0x2079, 0x0140, 0x2071, 0x8aa2, 0x703c, 0x2060,
+	0x8cff, 0x0040, 0x64a4, 0x6817, 0x0010, 0x68c7, 0x0000, 0x68cb,
+	0x0000, 0x1078, 0x517c, 0x1078, 0x1d84, 0x047e, 0x057e, 0x2009,
+	0x017f, 0x212c, 0x200b, 0x00a5, 0x2021, 0x0169, 0x2404, 0xa084,
+	0x000f, 0xa086, 0x0004, 0x00c0, 0x6473, 0x68c7, 0x0000, 0x68cb,
+	0x0008, 0x0e7e, 0x0f7e, 0x2079, 0x0020, 0x2071, 0x8af9, 0x6814,
+	0xa084, 0x0004, 0xa085, 0x0012, 0x6816, 0x7803, 0x0008, 0x7003,
+	0x0000, 0x0f7f, 0x0e7f, 0x250a, 0x057f, 0x047f, 0xa39d, 0x0000,
+	0x00c0, 0x647e, 0x2009, 0x0049, 0x1078, 0x6939, 0x20a9, 0x03e8,
+	0x6824, 0xd094, 0x0040, 0x6491, 0x6827, 0x0004, 0x7804, 0xa084,
+	0x4000, 0x0040, 0x64a3, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078,
+	0x64a3, 0xd094, 0x0040, 0x6498, 0x6827, 0x0002, 0x0078, 0x649a,
+	0x00f0, 0x6480, 0x7804, 0xa084, 0x1000, 0x0040, 0x64a3, 0x7803,
 	0x0100, 0x7803, 0x0000, 0x6824, 0x007f, 0x017f, 0x027f, 0x0c7f,
-	0x0d7f, 0x0e7f, 0x0f7f, 0x157f, 0x127f, 0x007c, 0x2001, 0x7700,
-	0x2004, 0xa096, 0x0001, 0x0040, 0x5876, 0xa096, 0x0004, 0x0040,
-	0x5876, 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011, 0x3558, 0x1078,
-	0x4689, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0040, 0x5864, 0x6827,
-	0x0004, 0x7804, 0xa084, 0x4000, 0x0040, 0x5876, 0x7803, 0x1000,
-	0x7803, 0x0000, 0x0078, 0x5876, 0xd084, 0x0040, 0x586b, 0x6827,
-	0x0001, 0x0078, 0x586d, 0x00f0, 0x5853, 0x7804, 0xa084, 0x1000,
-	0x0040, 0x5876, 0x7803, 0x0100, 0x7803, 0x0000, 0x007f, 0x017f,
-	0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f, 0x127f, 0x007c,
-	0x127e, 0x157e, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x027e, 0x017e,
-	0x007e, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071,
-	0x7936, 0x703c, 0x2060, 0x8cff, 0x0040, 0x58ce, 0x6817, 0x0010,
-	0x68cb, 0x0000, 0x68c7, 0x0000, 0x1078, 0x4714, 0x1078, 0x1c13,
-	0xa39d, 0x0000, 0x00c0, 0x58a8, 0x2009, 0x0049, 0x1078, 0x5d41,
-	0x20a9, 0x03e8, 0x6824, 0xd094, 0x0040, 0x58bb, 0x6827, 0x0004,
-	0x7804, 0xa084, 0x4000, 0x0040, 0x58cd, 0x7803, 0x1000, 0x7803,
-	0x0000, 0x0078, 0x58cd, 0xd094, 0x0040, 0x58c2, 0x6827, 0x0002,
-	0x0078, 0x58c4, 0x00f0, 0x58aa, 0x7804, 0xa084, 0x1000, 0x0040,
-	0x58cd, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x007f, 0x017f,
-	0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f, 0x127f, 0x007c,
-	0x0d7e, 0x127e, 0x2091, 0x8000, 0x2069, 0x7936, 0x6a06, 0x127f,
-	0x0d7f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2069, 0x7936,
-	0x6a32, 0x127f, 0x0d7f, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x067e,
-	0x007e, 0x127e, 0x2071, 0x7936, 0x7614, 0x2660, 0x2678, 0x2091,
-	0x8000, 0x8cff, 0x0040, 0x592c, 0x601c, 0xa206, 0x00c0, 0x5927,
-	0x7014, 0xac36, 0x00c0, 0x5906, 0x660c, 0x7616, 0x7010, 0xac36,
-	0x00c0, 0x5914, 0x2c00, 0xaf36, 0x0040, 0x5912, 0x2f00, 0x7012,
-	0x0078, 0x5914, 0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06,
-	0x0040, 0x591d, 0x7e0e, 0x0078, 0x591e, 0x2678, 0x600f, 0x0000,
-	0x1078, 0x6bb6, 0x1078, 0x5a1a, 0x0c7f, 0x0078, 0x58f9, 0x2c78,
-	0x600c, 0x2060, 0x0078, 0x58f9, 0x127f, 0x007f, 0x067f, 0x0c7f,
-	0x0e7f, 0x0f7f, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078,
-	0x532f, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2,
-	0x20a3, 0x4000, 0x0078, 0x5975, 0x157e, 0x147e, 0x20a1, 0x020b,
-	0x1078, 0x532f, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2,
-	0x20a2, 0x20a3, 0x2000, 0x0078, 0x5975, 0x157e, 0x147e, 0x20a1,
-	0x020b, 0x1078, 0x532f, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2,
-	0x20a2, 0x20a2, 0x20a3, 0x0400, 0x0078, 0x5975, 0x157e, 0x147e,
-	0x20a1, 0x020b, 0x1078, 0x532f, 0x7810, 0x20a2, 0xa006, 0x20a2,
-	0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200, 0x1078, 0x5a25, 0x60c3,
-	0x0020, 0x1078, 0x5688, 0x147f, 0x157f, 0x007c, 0x127e, 0x0c7e,
-	0x2091, 0x8000, 0x2061, 0x0100, 0x6120, 0xd1b4, 0x00c0, 0x598d,
-	0xd1bc, 0x00c0, 0x59d7, 0x0078, 0x5a17, 0x2009, 0x017f, 0x200b,
-	0x00a1, 0x157e, 0x007e, 0x0d7e, 0x2069, 0x0140, 0x20a9, 0x001e,
-	0x2009, 0x0169, 0x6804, 0xa084, 0x4000, 0x0040, 0x59ce, 0x6020,
-	0xd0b4, 0x0040, 0x59ce, 0x6024, 0xd094, 0x00c0, 0x59ce, 0x2104,
-	0xa084, 0x000f, 0xa086, 0x0004, 0x00c0, 0x59ce, 0x00f0, 0x599a,
-	0x027e, 0x6198, 0xa18c, 0x00ff, 0x8107, 0x6130, 0xa18c, 0x00ff,
-	0xa10d, 0x6088, 0x628c, 0x618e, 0x608b, 0xbc91, 0x6043, 0x0001,
-	0x6043, 0x0000, 0x608a, 0x628e, 0x6024, 0xd094, 0x00c0, 0x59cd,
-	0x6a04, 0xa294, 0x4000, 0x00c0, 0x59c4, 0x027f, 0x0d7f, 0x007f,
-	0x157f, 0x2009, 0x017f, 0x200b, 0x0000, 0x0078, 0x5a17, 0x2009,
-	0x017f, 0x200b, 0x00a1, 0x157e, 0x007e, 0x0d7e, 0x2069, 0x0140,
-	0x20a9, 0x001e, 0x2009, 0x0169, 0x6804, 0xa084, 0x4000, 0x0040,
-	0x5a10, 0x6020, 0xd0bc, 0x0040, 0x5a10, 0x2104, 0xa084, 0x000f,
-	0xa086, 0x0004, 0x00c0, 0x5a10, 0x00f0, 0x59e4, 0x027e, 0x6164,
-	0xa18c, 0x00ff, 0x8107, 0x6130, 0xa18c, 0x00ff, 0xa10d, 0x6088,
-	0x628c, 0x608b, 0xbc91, 0x618e, 0x6043, 0x0001, 0x6043, 0x0000,
-	0x608a, 0x628e, 0x6a04, 0xa294, 0x4000, 0x00c0, 0x5a0a, 0x027f,
-	0x0d7f, 0x007f, 0x157f, 0x2009, 0x017f, 0x200b, 0x0000, 0x0c7f,
-	0x127f, 0x007c, 0x0e7e, 0x2071, 0x7936, 0x7020, 0xa005, 0x0040,
-	0x5a23, 0x8001, 0x7022, 0x0e7f, 0x007c, 0x20a9, 0x0008, 0x20a2,
-	0x00f0, 0x5a27, 0x20a2, 0x20a2, 0x007c, 0x0f7e, 0x0e7e, 0x0d7e,
-	0x0c7e, 0x077e, 0x067e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071,
-	0x7936, 0x7614, 0x2660, 0x2678, 0x2039, 0x0001, 0x87ff, 0x0040,
-	0x5abd, 0x8cff, 0x0040, 0x5abd, 0x601c, 0xa086, 0x0006, 0x00c0,
-	0x5ab8, 0x88ff, 0x0040, 0x5a54, 0x2800, 0xac06, 0x00c0, 0x5ab8,
-	0x2039, 0x0000, 0x0078, 0x5a58, 0x6018, 0xa206, 0x00c0, 0x5ab8,
-	0x7024, 0xac06, 0x00c0, 0x5a86, 0x2069, 0x0100, 0x68c0, 0xa005,
-	0x0040, 0x5a81, 0x6817, 0x0008, 0x68c3, 0x0000, 0x1078, 0x5b4a,
+	0x0d7f, 0x0e7f, 0x0f7f, 0x157f, 0x127f, 0x007c, 0x0d7e, 0x127e,
+	0x2091, 0x8000, 0x2069, 0x8aa2, 0x6a06, 0x127f, 0x0d7f, 0x007c,
+	0x0d7e, 0x127e, 0x2091, 0x8000, 0x2069, 0x8aa2, 0x6a32, 0x127f,
+	0x0d7f, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x067e, 0x007e, 0x127e,
+	0x2071, 0x8aa2, 0x7614, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff,
+	0x0040, 0x6502, 0x601c, 0xa206, 0x00c0, 0x64fd, 0x7014, 0xac36,
+	0x00c0, 0x64dc, 0x660c, 0x7616, 0x7010, 0xac36, 0x00c0, 0x64ea,
+	0x2c00, 0xaf36, 0x0040, 0x64e8, 0x2f00, 0x7012, 0x0078, 0x64ea,
+	0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x64f3,
+	0x7e0e, 0x0078, 0x64f4, 0x2678, 0x600f, 0x0000, 0x1078, 0x79a8,
+	0x1078, 0x6601, 0x0c7f, 0x0078, 0x64cf, 0x2c78, 0x600c, 0x2060,
+	0x0078, 0x64cf, 0x127f, 0x007f, 0x067f, 0x0c7f, 0x0e7f, 0x0f7f,
+	0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x5e77, 0x7810,
+	0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x1000,
+	0x0078, 0x655c, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x5e77,
+	0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3,
+	0x4000, 0x0078, 0x655c, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078,
+	0x5e77, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2,
+	0x20a3, 0x2000, 0x0078, 0x655c, 0x157e, 0x147e, 0x20a1, 0x020b,
+	0x1078, 0x5e77, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2,
+	0x20a2, 0x20a3, 0x0400, 0x0078, 0x655c, 0x157e, 0x147e, 0x20a1,
+	0x020b, 0x1078, 0x5e77, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2,
+	0x20a2, 0x20a2, 0x20a3, 0x0200, 0x1078, 0x660c, 0x60c3, 0x0020,
+	0x1078, 0x621e, 0x147f, 0x157f, 0x007c, 0x127e, 0x0c7e, 0x2091,
+	0x8000, 0x2061, 0x0100, 0x6120, 0xd1b4, 0x00c0, 0x6574, 0xd1bc,
+	0x00c0, 0x65be, 0x0078, 0x65fe, 0x2009, 0x017f, 0x200b, 0x00a1,
+	0x157e, 0x007e, 0x0d7e, 0x2069, 0x0140, 0x20a9, 0x001e, 0x2009,
+	0x0169, 0x6804, 0xa084, 0x4000, 0x0040, 0x65b5, 0x6020, 0xd0b4,
+	0x0040, 0x65b5, 0x6024, 0xd094, 0x00c0, 0x65b5, 0x2104, 0xa084,
+	0x000f, 0xa086, 0x0004, 0x00c0, 0x65b5, 0x00f0, 0x6581, 0x027e,
+	0x6198, 0xa18c, 0x00ff, 0x8107, 0x6130, 0xa18c, 0x00ff, 0xa10d,
+	0x6088, 0x628c, 0x618e, 0x608b, 0xbc91, 0x6043, 0x0001, 0x6043,
+	0x0000, 0x608a, 0x628e, 0x6024, 0xd094, 0x00c0, 0x65b4, 0x6a04,
+	0xa294, 0x4000, 0x00c0, 0x65ab, 0x027f, 0x0d7f, 0x007f, 0x157f,
+	0x2009, 0x017f, 0x200b, 0x0000, 0x0078, 0x65fe, 0x2009, 0x017f,
+	0x200b, 0x00a1, 0x157e, 0x007e, 0x0d7e, 0x2069, 0x0140, 0x20a9,
+	0x001e, 0x2009, 0x0169, 0x6804, 0xa084, 0x4000, 0x0040, 0x65f7,
+	0x6020, 0xd0bc, 0x0040, 0x65f7, 0x2104, 0xa084, 0x000f, 0xa086,
+	0x0004, 0x00c0, 0x65f7, 0x00f0, 0x65cb, 0x027e, 0x6164, 0xa18c,
+	0x00ff, 0x8107, 0x6130, 0xa18c, 0x00ff, 0xa10d, 0x6088, 0x628c,
+	0x608b, 0xbc91, 0x618e, 0x6043, 0x0001, 0x6043, 0x0000, 0x608a,
+	0x628e, 0x6a04, 0xa294, 0x4000, 0x00c0, 0x65f1, 0x027f, 0x0d7f,
+	0x007f, 0x157f, 0x2009, 0x017f, 0x200b, 0x0000, 0x0c7f, 0x127f,
+	0x007c, 0x0e7e, 0x2071, 0x8aa2, 0x7020, 0xa005, 0x0040, 0x660a,
+	0x8001, 0x7022, 0x0e7f, 0x007c, 0x20a9, 0x0008, 0x20a2, 0x00f0,
+	0x660e, 0x20a2, 0x20a2, 0x007c, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e,
+	0x077e, 0x067e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0x8aa2,
+	0x7614, 0x2660, 0x2678, 0x2039, 0x0001, 0x87ff, 0x0040, 0x66ad,
+	0x8cff, 0x0040, 0x66ad, 0x601c, 0xa086, 0x0006, 0x00c0, 0x66a8,
+	0x88ff, 0x0040, 0x663b, 0x2800, 0xac06, 0x00c0, 0x66a8, 0x2039,
+	0x0000, 0x0078, 0x6646, 0x6018, 0xa206, 0x00c0, 0x66a8, 0x85ff,
+	0x0040, 0x6646, 0x6020, 0xa106, 0x00c0, 0x66a8, 0x7024, 0xac06,
+	0x00c0, 0x6676, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x6671,
+	0x1078, 0x516f, 0x6817, 0x0008, 0x68c3, 0x0000, 0x1078, 0x6741,
 	0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000,
-	0x0040, 0x5a76, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100,
-	0x6824, 0xd084, 0x0040, 0x5a7e, 0x6827, 0x0001, 0x037f, 0x0078,
-	0x5a86, 0x6003, 0x0009, 0x630a, 0x0078, 0x5ab8, 0x7014, 0xac36,
-	0x00c0, 0x5a8c, 0x660c, 0x7616, 0x7010, 0xac36, 0x00c0, 0x5a9a,
-	0x2c00, 0xaf36, 0x0040, 0x5a98, 0x2f00, 0x7012, 0x0078, 0x5a9a,
-	0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x5aa3,
-	0x7e0e, 0x0078, 0x5aa4, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068,
-	0x1078, 0x6a58, 0x0040, 0x5aae, 0x1078, 0x75fd, 0x1078, 0x6bb6,
-	0x1078, 0x5a1a, 0x88ff, 0x00c0, 0x5ac7, 0x0c7f, 0x0078, 0x5a3e,
-	0x2c78, 0x600c, 0x2060, 0x0078, 0x5a3e, 0xa006, 0x127f, 0x007f,
+	0x0040, 0x6666, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100,
+	0x6824, 0xd084, 0x0040, 0x666e, 0x6827, 0x0001, 0x037f, 0x0078,
+	0x6676, 0x6003, 0x0009, 0x630a, 0x0078, 0x66a8, 0x7014, 0xac36,
+	0x00c0, 0x667c, 0x660c, 0x7616, 0x7010, 0xac36, 0x00c0, 0x668a,
+	0x2c00, 0xaf36, 0x0040, 0x6688, 0x2f00, 0x7012, 0x0078, 0x668a,
+	0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x6693,
+	0x7e0e, 0x0078, 0x6694, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068,
+	0x1078, 0x77ed, 0x0040, 0x669e, 0x1078, 0x86aa, 0x1078, 0x79a8,
+	0x1078, 0x6601, 0x88ff, 0x00c0, 0x66b7, 0x0c7f, 0x0078, 0x6625,
+	0x2c78, 0x600c, 0x2060, 0x0078, 0x6625, 0xa006, 0x127f, 0x007f,
 	0x067f, 0x077f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x6017,
-	0x0000, 0x0c7f, 0xa8c5, 0x0001, 0x0078, 0x5abe, 0x0f7e, 0x0e7e,
+	0x0000, 0x0c7f, 0xa8c5, 0x0001, 0x0078, 0x66ae, 0x0f7e, 0x0e7e,
 	0x0d7e, 0x0c7e, 0x067e, 0x027e, 0x007e, 0x127e, 0x2091, 0x8000,
-	0x2071, 0x7936, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0040, 0x5b39,
-	0x601c, 0xa086, 0x0006, 0x00c0, 0x5b34, 0x88ff, 0x0040, 0x5aee,
-	0x2800, 0xac06, 0x00c0, 0x5b34, 0x0078, 0x5af2, 0x6018, 0xa206,
-	0x00c0, 0x5b34, 0x703c, 0xac06, 0x00c0, 0x5b04, 0x037e, 0x2019,
-	0x0001, 0x1078, 0x5880, 0x7033, 0x0000, 0x703f, 0x0000, 0x7043,
-	0x0000, 0x7047, 0x0000, 0x037f, 0x7038, 0xac36, 0x00c0, 0x5b0a,
-	0x660c, 0x763a, 0x7034, 0xac36, 0x00c0, 0x5b18, 0x2c00, 0xaf36,
-	0x0040, 0x5b16, 0x2f00, 0x7036, 0x0078, 0x5b18, 0x7037, 0x0000,
-	0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x5b21, 0x7e0e, 0x0078,
-	0x5b22, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x6a58,
-	0x0040, 0x5b2c, 0x1078, 0x75fd, 0x1078, 0x6bb6, 0x88ff, 0x00c0,
-	0x5b43, 0x0c7f, 0x0078, 0x5add, 0x2c78, 0x600c, 0x2060, 0x0078,
-	0x5add, 0xa006, 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0d7f,
-	0x0e7f, 0x0f7f, 0x007c, 0x6017, 0x0000, 0x0c7f, 0xa8c5, 0x0001,
-	0x0078, 0x5b3a, 0x0e7e, 0x2071, 0x7936, 0x2001, 0x7700, 0x2004,
-	0xa086, 0x0002, 0x00c0, 0x5b58, 0x7007, 0x0005, 0x0078, 0x5b5a,
-	0x7007, 0x0000, 0x0e7f, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x067e,
-	0x027e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0x7936, 0x2c10,
-	0x7638, 0x2660, 0x2678, 0x8cff, 0x0040, 0x5b9a, 0x2200, 0xac06,
-	0x00c0, 0x5b95, 0x7038, 0xac36, 0x00c0, 0x5b78, 0x660c, 0x763a,
-	0x7034, 0xac36, 0x00c0, 0x5b86, 0x2c00, 0xaf36, 0x0040, 0x5b84,
-	0x2f00, 0x7036, 0x0078, 0x5b86, 0x7037, 0x0000, 0x660c, 0x2c00,
-	0xaf06, 0x0040, 0x5b8e, 0x7e0e, 0x0078, 0x5b8f, 0x2678, 0x600f,
-	0x0000, 0xa085, 0x0001, 0x0078, 0x5b9a, 0x2c78, 0x600c, 0x2060,
-	0x0078, 0x5b6b, 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0e7f,
-	0x0f7f, 0x007c, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x007e,
-	0x127e, 0x2091, 0x8000, 0x2071, 0x7936, 0x760c, 0x2660, 0x2678,
-	0x8cff, 0x0040, 0x5c33, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206,
-	0x00c0, 0x5c2e, 0x7024, 0xac06, 0x00c0, 0x5be1, 0x2069, 0x0100,
-	0x68c0, 0xa005, 0x0040, 0x5be1, 0x1078, 0x569c, 0x68c3, 0x0000,
-	0x1078, 0x5b4a, 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04,
-	0xa384, 0x1000, 0x0040, 0x5bd8, 0x6803, 0x0100, 0x6803, 0x0000,
-	0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x5be0, 0x6827, 0x0001,
-	0x037f, 0x700c, 0xac36, 0x00c0, 0x5be7, 0x660c, 0x760e, 0x7008,
-	0xac36, 0x00c0, 0x5bf5, 0x2c00, 0xaf36, 0x0040, 0x5bf3, 0x2f00,
-	0x700a, 0x0078, 0x5bf5, 0x700b, 0x0000, 0x660c, 0x067e, 0x2c00,
-	0xaf06, 0x0040, 0x5bfe, 0x7e0e, 0x0078, 0x5bff, 0x2678, 0x600f,
-	0x0000, 0x1078, 0x6bcf, 0x00c0, 0x5c09, 0x1078, 0x22d7, 0x0078,
-	0x5c25, 0x1078, 0x6be3, 0x00c0, 0x5c11, 0x1078, 0x5f6d, 0x0078,
-	0x5c25, 0x6010, 0x2068, 0x1078, 0x6a58, 0x0040, 0x5c25, 0x601c,
-	0xa086, 0x0003, 0x00c0, 0x5c3b, 0x6837, 0x0103, 0x6b4a, 0x6847,
-	0x0000, 0x1078, 0x3b92, 0x1078, 0x6ba9, 0x6003, 0x0000, 0x1078,
-	0x6bb6, 0x1078, 0x5a1a, 0x0c7f, 0x0078, 0x5bb0, 0x2c78, 0x600c,
-	0x2060, 0x0078, 0x5bb0, 0x127f, 0x007f, 0x067f, 0x0c7f, 0x0d7f,
-	0x0e7f, 0x0f7f, 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x5c1c,
-	0x1078, 0x75fd, 0x0078, 0x5c25, 0x037e, 0x157e, 0x137e, 0x147e,
-	0x3908, 0xa006, 0xa190, 0x0020, 0x221c, 0xa39e, 0x2149, 0x00c0,
-	0x5c55, 0x8210, 0x8000, 0x0078, 0x5c4c, 0xa005, 0x0040, 0x5c5f,
-	0x20a9, 0x0020, 0x2198, 0xa110, 0x22a0, 0x22c8, 0x53a3, 0x147f,
-	0x137f, 0x157f, 0x037f, 0x007c, 0x0d7e, 0x20a1, 0x020b, 0x1078,
-	0x516f, 0x20a3, 0x0200, 0x20a3, 0x0014, 0x60c3, 0x0014, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x20a3, 0x514c, 0x20a3, 0x4f47, 0x20a3,
-	0x4943, 0x20a3, 0x2020, 0x20a3, 0x0004, 0x20a3, 0x7878, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x1078, 0x5688, 0x0d7f, 0x007c, 0x20a1,
-	0x020b, 0x1078, 0x516f, 0x20a3, 0x0210, 0x20a3, 0x0018, 0x20a3,
-	0x0800, 0x7810, 0xa084, 0xff00, 0x20a2, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7810,
-	0xa084, 0x00ff, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
-	0x0018, 0x1078, 0x5688, 0x007c, 0x2061, 0x7e00, 0x2a70, 0x7060,
-	0x7046, 0x704b, 0x7e00, 0x007c, 0x0e7e, 0x127e, 0x2071, 0x7700,
-	0x2091, 0x8000, 0x7544, 0xa582, 0x0001, 0x0048, 0x5ce6, 0x7048,
-	0x2060, 0x6000, 0xa086, 0x0000, 0x0040, 0x5cd2, 0xace0, 0x0008,
-	0x7054, 0xac02, 0x00c8, 0x5cce, 0x0078, 0x5cc1, 0x2061, 0x7e00,
-	0x0078, 0x5cc1, 0x6003, 0x0008, 0x8529, 0x7546, 0xaca8, 0x0008,
-	0x7054, 0xa502, 0x00c8, 0x5ce2, 0x754a, 0xa085, 0x0001, 0x127f,
-	0x0e7f, 0x007c, 0x704b, 0x7e00, 0x0078, 0x5cdd, 0xa006, 0x0078,
-	0x5cdf, 0x0e7e, 0x2071, 0x7700, 0x7544, 0xa582, 0x0001, 0x0048,
-	0x5d17, 0x7048, 0x2060, 0x6000, 0xa086, 0x0000, 0x0040, 0x5d04,
-	0xace0, 0x0008, 0x7054, 0xac02, 0x00c8, 0x5d00, 0x0078, 0x5cf3,
-	0x2061, 0x7e00, 0x0078, 0x5cf3, 0x6003, 0x0008, 0x8529, 0x7546,
-	0xaca8, 0x0008, 0x7054, 0xa502, 0x00c8, 0x5d13, 0x754a, 0xa085,
-	0x0001, 0x0e7f, 0x007c, 0x704b, 0x7e00, 0x0078, 0x5d0f, 0xa006,
-	0x0078, 0x5d11, 0xac82, 0x7e00, 0x1048, 0x12cd, 0x2001, 0x7715,
-	0x2004, 0xac02, 0x10c8, 0x12cd, 0xa006, 0x6006, 0x600a, 0x600e,
-	0x6012, 0x6016, 0x601a, 0x601f, 0x0000, 0x6003, 0x0000, 0x2061,
-	0x7700, 0x6044, 0x8000, 0x6046, 0xa086, 0x0001, 0x0040, 0x5d39,
-	0x007c, 0x127e, 0x2091, 0x8000, 0x1078, 0x4d96, 0x127f, 0x0078,
-	0x5d38, 0x601c, 0xa084, 0x000f, 0x0079, 0x5d46, 0x5d4f, 0x5d57,
-	0x5d73, 0x5d8f, 0x6c60, 0x6c7c, 0x6c98, 0x5d4f, 0x5d57, 0xa18e,
-	0x0047, 0x00c0, 0x5d56, 0xa016, 0x1078, 0x156a, 0x007c, 0x067e,
-	0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12cd, 0x1079, 0x5d61, 0x067f,
-	0x007c, 0x5d71, 0x5e58, 0x5f88, 0x5d71, 0x5fdf, 0x5d71, 0x5d71,
-	0x5d71, 0x5e07, 0x6298, 0x5d71, 0x5d71, 0x5d71, 0x5d71, 0x5d71,
-	0x5d71, 0x1078, 0x12cd, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8,
-	0x12cd, 0x1079, 0x5d7d, 0x067f, 0x007c, 0x5d8d, 0x5d8d, 0x5d8d,
-	0x5d8d, 0x5d8d, 0x5d8d, 0x5d8d, 0x5d8d, 0x670c, 0x67d2, 0x5d8d,
-	0x6725, 0x677e, 0x6725, 0x677e, 0x5d8d, 0x1078, 0x12cd, 0x067e,
-	0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12cd, 0x1079, 0x5d99, 0x067f,
-	0x007c, 0x5da9, 0x62d6, 0x637c, 0x643e, 0x6596, 0x5da9, 0x5da9,
-	0x5da9, 0x62b4, 0x66c1, 0x66c5, 0x5da9, 0x5da9, 0x5da9, 0x5da9,
-	0x66eb, 0x1078, 0x12cd, 0x20a9, 0x000e, 0x2e98, 0x6010, 0x20a0,
-	0x53a3, 0x20a9, 0x0006, 0x3310, 0x3420, 0x9398, 0x94a0, 0x3318,
-	0x3428, 0x222e, 0x2326, 0xa290, 0x0002, 0xa5a8, 0x0002, 0xa398,
-	0x0002, 0xa4a0, 0x0002, 0x00f0, 0x5db9, 0x0e7e, 0x1078, 0x6a58,
-	0x0040, 0x5dd0, 0x6010, 0x2070, 0x7007, 0x0000, 0x7037, 0x0103,
-	0x0e7f, 0x1078, 0x5d1a, 0x007c, 0x0d7e, 0x037e, 0x7330, 0xa386,
-	0x0200, 0x00c0, 0x5de1, 0x6018, 0x2068, 0x6813, 0x00ff, 0x6817,
-	0xfffd, 0x6010, 0xa005, 0x0040, 0x5deb, 0x2068, 0x6807, 0x0000,
-	0x6837, 0x0103, 0x6b32, 0x1078, 0x5d1a, 0x037f, 0x0d7f, 0x007c,
-	0x0d7e, 0x20a9, 0x000e, 0x2e98, 0x6010, 0x20a0, 0x53a3, 0xa1b6,
-	0x0015, 0x00c0, 0x5e04, 0x6018, 0x2068, 0x7038, 0x680a, 0x703c,
-	0x680e, 0x6800, 0xc08d, 0x6802, 0x0d7f, 0x0078, 0x5dc5, 0x2100,
-	0xa1b2, 0x0030, 0x10c8, 0x12cd, 0x0079, 0x5e0e, 0x5e40, 0x5e4c,
-	0x5e40, 0x5e40, 0x5e40, 0x5e40, 0x5e3e, 0x5e3e, 0x5e3e, 0x5e3e,
-	0x5e3e, 0x5e3e, 0x5e3e, 0x5e3e, 0x5e3e, 0x5e3e, 0x5e3e, 0x5e3e,
-	0x5e3e, 0x5e3e, 0x5e3e, 0x5e3e, 0x5e3e, 0x5e3e, 0x5e3e, 0x5e3e,
-	0x5e3e, 0x5e3e, 0x5e3e, 0x5e3e, 0x5e3e, 0x5e40, 0x5e3e, 0x5e40,
-	0x5e40, 0x5e3e, 0x5e3e, 0x5e3e, 0x5e3e, 0x5e3e, 0x5e40, 0x5e3e,
-	0x5e3e, 0x5e3e, 0x5e3e, 0x5e3e, 0x5e3e, 0x5e3e, 0x1078, 0x12cd,
-	0x6003, 0x0001, 0x6106, 0x1078, 0x498e, 0x127e, 0x2091, 0x8000,
-	0x1078, 0x4d96, 0x127f, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078,
-	0x498e, 0x127e, 0x2091, 0x8000, 0x1078, 0x4d96, 0x127f, 0x007c,
-	0x6004, 0xa0b2, 0x0030, 0x10c8, 0x12cd, 0xa1b6, 0x0013, 0x00c0,
-	0x5e64, 0x2008, 0x0079, 0x5eeb, 0xa1b6, 0x0027, 0x00c0, 0x5eb9,
-	0x1078, 0x4c9d, 0x6004, 0x1078, 0x6bcf, 0x0040, 0x5e7d, 0x1078,
-	0x6be3, 0x0040, 0x5eb1, 0xa08e, 0x0021, 0x0040, 0x5eb5, 0xa08e,
-	0x0022, 0x0040, 0x5eb1, 0x0078, 0x5eac, 0x1078, 0x22d7, 0x2001,
-	0x0007, 0x1078, 0x37f4, 0x6018, 0xa080, 0x0028, 0x200c, 0x1078,
-	0x5f6d, 0xa186, 0x007e, 0x00c0, 0x5e92, 0x2001, 0x772f, 0x2014,
-	0xc285, 0x2202, 0x017e, 0x027e, 0x037e, 0x2110, 0x2019, 0x0028,
-	0x1078, 0x4a7e, 0x1078, 0x49c1, 0x0c7e, 0x6018, 0xa065, 0x0040,
-	0x5ea3, 0x1078, 0x3a36, 0x0c7f, 0x2c08, 0x1078, 0x747b, 0x037f,
-	0x027f, 0x017f, 0x1078, 0x3834, 0x1078, 0x5d1a, 0x1078, 0x4d96,
-	0x007c, 0x1078, 0x5f6d, 0x0078, 0x5eac, 0x1078, 0x5f7c, 0x0078,
-	0x5eac, 0xa186, 0x0014, 0x00c0, 0x5eb0, 0x1078, 0x4c9d, 0x1078,
-	0x22b5, 0x1078, 0x6bcf, 0x00c0, 0x5ed8, 0x1078, 0x22d7, 0x6018,
-	0xa080, 0x0028, 0x200c, 0x1078, 0x5f6d, 0xa186, 0x007e, 0x00c0,
-	0x5ed6, 0x2001, 0x772f, 0x200c, 0xc185, 0x2102, 0x0078, 0x5eac,
-	0x1078, 0x6be3, 0x00c0, 0x5ee0, 0x1078, 0x5f6d, 0x0078, 0x5eac,
-	0x6004, 0xa08e, 0x0021, 0x0040, 0x5edc, 0xa08e, 0x0022, 0x1040,
-	0x5f7c, 0x0078, 0x5eac, 0x5f1d, 0x5f1f, 0x5f23, 0x5f27, 0x5f2b,
-	0x5f2f, 0x5f1b, 0x5f1b, 0x5f1b, 0x5f1b, 0x5f1b, 0x5f1b, 0x5f1b,
-	0x5f1b, 0x5f1b, 0x5f1b, 0x5f1b, 0x5f1b, 0x5f1b, 0x5f1b, 0x5f1b,
-	0x5f1b, 0x5f1b, 0x5f1b, 0x5f1b, 0x5f1b, 0x5f1b, 0x5f1b, 0x5f1b,
-	0x5f1b, 0x5f33, 0x5f39, 0x5f1b, 0x5f43, 0x5f39, 0x5f1b, 0x5f1b,
-	0x5f1b, 0x5f1b, 0x5f1b, 0x5f39, 0x5f39, 0x5f1b, 0x5f1b, 0x5f1b,
-	0x5f1b, 0x5f1b, 0x5f1b, 0x1078, 0x12cd, 0x0078, 0x5f39, 0x2001,
-	0x000b, 0x0078, 0x5f4c, 0x2001, 0x0003, 0x0078, 0x5f4c, 0x2001,
-	0x0005, 0x0078, 0x5f4c, 0x2001, 0x0001, 0x0078, 0x5f4c, 0x2001,
-	0x0009, 0x0078, 0x5f4c, 0x1078, 0x12cd, 0x0078, 0x5f4b, 0x1078,
-	0x37f4, 0x1078, 0x4c9d, 0x6003, 0x0002, 0x6017, 0x0028, 0x1078,
-	0x4d96, 0x0078, 0x5f4b, 0x1078, 0x4c9d, 0x6003, 0x0004, 0x6017,
-	0x0028, 0x1078, 0x4d96, 0x007c, 0x1078, 0x37f4, 0x1078, 0x4c9d,
-	0x6003, 0x0002, 0x037e, 0x2019, 0x775c, 0x2304, 0xa084, 0xff00,
-	0x00c0, 0x5f5e, 0x2019, 0x0028, 0x0078, 0x5f67, 0x8007, 0xa09a,
-	0x0004, 0x0048, 0x5f5a, 0x8003, 0x801b, 0x831b, 0xa318, 0x6316,
-	0x037f, 0x1078, 0x4d96, 0x0078, 0x5f4b, 0x0e7e, 0x1078, 0x6a58,
-	0x0040, 0x5f7a, 0x6010, 0x2070, 0x7007, 0x0000, 0x7037, 0x0103,
-	0x7033, 0x0100, 0x0e7f, 0x007c, 0x0e7e, 0xacf0, 0x0004, 0x2e74,
-	0x7000, 0x2070, 0x7037, 0x0103, 0x7023, 0x8001, 0x0e7f, 0x007c,
-	0x0d7e, 0x6618, 0x2668, 0x6804, 0xa084, 0x00ff, 0x0d7f, 0xa0b2,
-	0x000c, 0x10c8, 0x12cd, 0x6604, 0xa6b6, 0x0028, 0x00c0, 0x5f9c,
-	0x1078, 0x6c18, 0x0078, 0x5fce, 0x6604, 0xa6b6, 0x0029, 0x00c0,
-	0x5fa5, 0x1078, 0x6c32, 0x0078, 0x5fce, 0x6604, 0xa6b6, 0x001f,
-	0x00c0, 0x5fae, 0x1078, 0x5dab, 0x0078, 0x5fce, 0x6604, 0xa6b6,
-	0x0000, 0x00c0, 0x5fb7, 0x1078, 0x5df0, 0x0078, 0x5fce, 0x6604,
-	0xa6b6, 0x0022, 0x00c0, 0x5fc0, 0x1078, 0x5dd4, 0x0078, 0x5fce,
-	0xa1b6, 0x0015, 0x00c0, 0x5fc8, 0x1079, 0x5fd3, 0x0078, 0x5fce,
-	0xa1b6, 0x0016, 0x00c0, 0x5fcf, 0x1079, 0x6110, 0x007c, 0x1078,
-	0x5d4f, 0x0078, 0x5fce, 0x5ff7, 0x5ffa, 0x5ff7, 0x603b, 0x5ff7,
-	0x60ac, 0x5ff7, 0x5ff7, 0x5ff7, 0x60e8, 0x5ff7, 0x60fe, 0xa1b6,
-	0x0048, 0x0040, 0x5feb, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10,
-	0x1078, 0x156a, 0x007c, 0x0e7e, 0xacf0, 0x0004, 0x2e74, 0x7000,
-	0x2070, 0x7037, 0x0103, 0x0e7f, 0x1078, 0x5d1a, 0x007c, 0x0005,
-	0x0005, 0x007c, 0x0e7e, 0x2071, 0x7700, 0x7078, 0xa086, 0x0074,
-	0x00c0, 0x6024, 0x1078, 0x744f, 0x00c0, 0x6016, 0x0d7e, 0x6018,
-	0x2068, 0x1078, 0x6028, 0x0d7f, 0x2001, 0x0006, 0x1078, 0x37f4,
-	0x1078, 0x22d7, 0x1078, 0x5d1a, 0x0078, 0x6026, 0x2001, 0x000a,
-	0x1078, 0x37f4, 0x1078, 0x22d7, 0x6003, 0x0001, 0x6007, 0x0001,
-	0x1078, 0x498e, 0x0078, 0x6026, 0x1078, 0x609c, 0x0e7f, 0x007c,
-	0x6800, 0xd084, 0x0040, 0x603a, 0x2001, 0x0000, 0x1078, 0x37e0,
-	0x2069, 0x7751, 0x6804, 0xd0a4, 0x0040, 0x603a, 0x2001, 0x0006,
-	0x1078, 0x3802, 0x007c, 0x0d7e, 0x2011, 0x771e, 0x2204, 0xa086,
-	0x0074, 0x00c0, 0x6098, 0x1078, 0x61ea, 0x6018, 0x2068, 0xa080,
-	0x0028, 0x2014, 0xa286, 0x007e, 0x0040, 0x6063, 0xa286, 0x0080,
-	0x00c0, 0x608c, 0x6813, 0x00ff, 0x6817, 0xfffc, 0x6010, 0xa005,
-	0x0040, 0x6082, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6833,
-	0x0200, 0x0078, 0x6082, 0x0e7e, 0x0f7e, 0x6813, 0x00ff, 0x6817,
-	0xfffe, 0x2071, 0x772f, 0x2e04, 0xa085, 0x0003, 0x2072, 0x2071,
-	0x7c80, 0x2079, 0x0100, 0x2e04, 0xa084, 0x00ff, 0x2069, 0x7719,
-	0x206a, 0x78e6, 0x8e70, 0x2e04, 0x2069, 0x771a, 0x206a, 0x78ea,
-	0x0f7f, 0x0e7f, 0x2001, 0x0006, 0x1078, 0x37f4, 0x1078, 0x22d7,
-	0x1078, 0x5d1a, 0x0078, 0x609a, 0x2001, 0x0004, 0x1078, 0x37f4,
-	0x6003, 0x0001, 0x6007, 0x0003, 0x1078, 0x498e, 0x0078, 0x609a,
-	0x1078, 0x609c, 0x0d7f, 0x007c, 0x2001, 0x7700, 0x2004, 0xa086,
-	0x0003, 0x0040, 0x60a7, 0x2001, 0x0007, 0x1078, 0x37f4, 0x1078,
-	0x22d7, 0x1078, 0x5d1a, 0x007c, 0x0e7e, 0x2071, 0x7700, 0x7078,
-	0xa086, 0x0014, 0x00c0, 0x60e2, 0x7000, 0xa086, 0x0003, 0x00c0,
-	0x60bf, 0x6010, 0xa005, 0x00c0, 0x60bf, 0x1078, 0x2dd7, 0x0d7e,
-	0x6018, 0x2068, 0x1078, 0x38c8, 0x1078, 0x6028, 0x0d7f, 0x1078,
-	0x61f4, 0x00c0, 0x60e2, 0x2001, 0x0006, 0x1078, 0x37f4, 0x0e7e,
-	0x6010, 0xa005, 0x0040, 0x60db, 0x2070, 0x7007, 0x0000, 0x7037,
-	0x0103, 0x7033, 0x0200, 0x0e7f, 0x1078, 0x22d7, 0x1078, 0x5d1a,
-	0x0078, 0x60e6, 0x1078, 0x5f6d, 0x1078, 0x609c, 0x0e7f, 0x007c,
-	0x2011, 0x771e, 0x2204, 0xa086, 0x0014, 0x00c0, 0x60fb, 0x2001,
-	0x0002, 0x1078, 0x37f4, 0x6003, 0x0001, 0x6007, 0x0001, 0x1078,
-	0x498e, 0x0078, 0x60fd, 0x1078, 0x609c, 0x007c, 0x2011, 0x771e,
-	0x2204, 0xa086, 0x0004, 0x00c0, 0x610d, 0x2001, 0x0007, 0x1078,
-	0x37f4, 0x1078, 0x5d1a, 0x0078, 0x610f, 0x1078, 0x609c, 0x007c,
-	0x5ff7, 0x611c, 0x5ff7, 0x6142, 0x5ff7, 0x619d, 0x5ff7, 0x5ff7,
-	0x5ff7, 0x61b2, 0x5ff7, 0x61c5, 0x0c7e, 0x1078, 0x61d8, 0x00c0,
-	0x6131, 0x2001, 0x0000, 0x1078, 0x37e0, 0x2001, 0x0002, 0x1078,
-	0x37f4, 0x6003, 0x0001, 0x6007, 0x0002, 0x1078, 0x498e, 0x0078,
-	0x6140, 0x2009, 0x7c8f, 0x2104, 0xa084, 0xff00, 0xa086, 0x1900,
-	0x00c0, 0x613e, 0x1078, 0x5d1a, 0x0078, 0x6140, 0x1078, 0x609c,
-	0x0c7f, 0x007c, 0x1078, 0x61e7, 0x00c0, 0x6156, 0x2001, 0x0000,
-	0x1078, 0x37e0, 0x2001, 0x0002, 0x1078, 0x37f4, 0x6003, 0x0001,
-	0x6007, 0x0002, 0x1078, 0x498e, 0x0078, 0x6178, 0x1078, 0x5f6d,
-	0x2009, 0x7c8e, 0x2134, 0xa6b4, 0x00ff, 0xa686, 0x0005, 0x0040,
-	0x6179, 0x2009, 0x7c8f, 0x2104, 0xa084, 0xff00, 0xa086, 0x1900,
-	0x00c0, 0x6176, 0xa686, 0x0009, 0x0040, 0x6179, 0x2001, 0x0004,
-	0x1078, 0x37f4, 0x1078, 0x5d1a, 0x0078, 0x6178, 0x1078, 0x609c,
-	0x007c, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x6a58, 0x0040, 0x6187,
-	0x6838, 0xd0fc, 0x0040, 0x6187, 0x0d7f, 0x0078, 0x6176, 0x6018,
-	0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0040, 0x6198, 0x8001,
-	0x6842, 0x6017, 0x000a, 0x6007, 0x0016, 0x0d7f, 0x0078, 0x6178,
-	0x1078, 0x22b5, 0x0d7f, 0x0078, 0x6176, 0x1078, 0x61e7, 0x00c0,
-	0x61ad, 0x2001, 0x0004, 0x1078, 0x37f4, 0x6003, 0x0001, 0x6007,
-	0x0003, 0x1078, 0x498e, 0x0078, 0x61b1, 0x1078, 0x5f6d, 0x1078,
-	0x609c, 0x007c, 0x1078, 0x61e7, 0x00c0, 0x61c2, 0x2001, 0x0008,
-	0x1078, 0x37f4, 0x6003, 0x0001, 0x6007, 0x0005, 0x1078, 0x498e,
-	0x0078, 0x61c4, 0x1078, 0x609c, 0x007c, 0x1078, 0x61e7, 0x00c0,
-	0x61d5, 0x2001, 0x000a, 0x1078, 0x37f4, 0x6003, 0x0001, 0x6007,
-	0x0001, 0x1078, 0x498e, 0x0078, 0x61d7, 0x1078, 0x609c, 0x007c,
-	0x2009, 0x7c8e, 0x2104, 0xa086, 0x0003, 0x00c0, 0x61e6, 0x2009,
-	0x7c8f, 0x2104, 0xa084, 0xff00, 0xa086, 0x2a00, 0x007c, 0xa085,
-	0x0001, 0x007c, 0x0c7e, 0x017e, 0xac88, 0x0006, 0x2164, 0x1078,
-	0x385e, 0x017f, 0x0c7f, 0x007c, 0x0e7e, 0x2071, 0x7c8c, 0x7004,
-	0xa086, 0x0014, 0x00c0, 0x6217, 0x7008, 0xa086, 0x0800, 0x00c0,
-	0x6217, 0x700c, 0xd0ec, 0x0040, 0x6215, 0xa084, 0x0f00, 0xa086,
-	0x0100, 0x00c0, 0x6215, 0x7024, 0xd0a4, 0x0040, 0x6215, 0xd08c,
-	0x0040, 0x6215, 0xa006, 0x0078, 0x6217, 0xa085, 0x0001, 0x0e7f,
-	0x007c, 0x0e7e, 0x0d7e, 0x0c7e, 0x077e, 0x057e, 0x047e, 0x027e,
-	0x007e, 0x127e, 0x2091, 0x8000, 0x2029, 0x793f, 0x252c, 0x2021,
-	0x7945, 0x2424, 0x2061, 0x7e00, 0x2071, 0x7700, 0x7244, 0x7060,
-	0xa202, 0x00c8, 0x626e, 0x1078, 0x7659, 0x0040, 0x6266, 0x671c,
-	0xa786, 0x0001, 0x0040, 0x6266, 0xa786, 0x0007, 0x0040, 0x6266,
-	0x2500, 0xac06, 0x0040, 0x6266, 0x2400, 0xac06, 0x0040, 0x6266,
-	0x0c7e, 0x6000, 0xa086, 0x0004, 0x00c0, 0x6250, 0x1078, 0x166e,
-	0x6010, 0x2068, 0x1078, 0x6a58, 0x0040, 0x6263, 0xa786, 0x0003,
-	0x00c0, 0x6278, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078,
-	0x3b92, 0x1078, 0x6ba9, 0x1078, 0x6bb6, 0x0c7f, 0xace0, 0x0008,
-	0x7054, 0xac02, 0x00c8, 0x626e, 0x0078, 0x622e, 0x127f, 0x007f,
-	0x027f, 0x047f, 0x057f, 0x077f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c,
-	0xa786, 0x0006, 0x00c0, 0x625a, 0x1078, 0x75fd, 0x0078, 0x6263,
-	0x220c, 0x2304, 0xa106, 0x00c0, 0x628b, 0x8210, 0x8318, 0x00f0,
-	0x6280, 0xa006, 0x007c, 0x2304, 0xa102, 0x0048, 0x6293, 0x2001,
-	0x0001, 0x0078, 0x6295, 0x2001, 0x0000, 0xa18d, 0x0001, 0x007c,
-	0x6004, 0xa08a, 0x0030, 0x10c8, 0x12cd, 0x1078, 0x6bcf, 0x0040,
-	0x62a7, 0x1078, 0x6be3, 0x0040, 0x62b0, 0x0078, 0x62a9, 0x1078,
-	0x22d7, 0x1078, 0x4c9d, 0x1078, 0x5d1a, 0x1078, 0x4d96, 0x007c,
-	0x1078, 0x5f6d, 0x0078, 0x62a9, 0xa182, 0x0040, 0x0079, 0x62b8,
-	0x62c8, 0x62c8, 0x62c8, 0x62c8, 0x62c8, 0x62c8, 0x62c8, 0x62c8,
-	0x62c8, 0x62c8, 0x62c8, 0x62ca, 0x62ca, 0x62ca, 0x62ca, 0x62c8,
-	0x1078, 0x12cd, 0x6003, 0x0001, 0x6106, 0x1078, 0x4941, 0x127e,
-	0x2091, 0x8000, 0x1078, 0x4d96, 0x127f, 0x007c, 0xa186, 0x0013,
-	0x00c0, 0x62df, 0x6004, 0xa082, 0x0040, 0x0079, 0x6355, 0xa186,
-	0x0027, 0x00c0, 0x62fc, 0x1078, 0x4c9d, 0x1078, 0x22b5, 0x0d7e,
-	0x6110, 0x2168, 0x1078, 0x6a58, 0x0040, 0x62f6, 0x6837, 0x0103,
-	0x684b, 0x0029, 0x1078, 0x3b92, 0x1078, 0x6ba9, 0x0d7f, 0x1078,
-	0x5d1a, 0x1078, 0x4d96, 0x007c, 0xa186, 0x0014, 0x00c0, 0x6305,
-	0x6004, 0xa082, 0x0040, 0x0079, 0x6325, 0xa186, 0x0047, 0x10c0,
-	0x12cd, 0x2001, 0x0109, 0x2004, 0xd084, 0x0040, 0x6322, 0x127e,
-	0x2091, 0x2200, 0x007e, 0x017e, 0x027e, 0x1078, 0x4802, 0x027f,
-	0x017f, 0x007f, 0x127f, 0x6000, 0xa086, 0x0002, 0x00c0, 0x6322,
-	0x0078, 0x637c, 0x1078, 0x5d4f, 0x007c, 0x6337, 0x6335, 0x6335,
-	0x6335, 0x6335, 0x6335, 0x6335, 0x6335, 0x6335, 0x6335, 0x6335,
-	0x634e, 0x634e, 0x634e, 0x634e, 0x6335, 0x1078, 0x12cd, 0x1078,
-	0x4c9d, 0x0d7e, 0x6110, 0x2168, 0x1078, 0x6a58, 0x0040, 0x6348,
-	0x6837, 0x0103, 0x684b, 0x0006, 0x1078, 0x3b92, 0x1078, 0x6ba9,
-	0x0d7f, 0x1078, 0x5d1a, 0x1078, 0x4d96, 0x007c, 0x1078, 0x4c9d,
-	0x1078, 0x5d1a, 0x1078, 0x4d96, 0x007c, 0x6367, 0x6365, 0x6365,
-	0x6365, 0x6365, 0x6365, 0x6365, 0x6365, 0x6365, 0x6365, 0x6365,
-	0x6375, 0x6375, 0x6375, 0x6375, 0x6365, 0x1078, 0x12cd, 0x1078,
-	0x4c9d, 0x6003, 0x0002, 0x1078, 0x4d96, 0x6010, 0xa088, 0x0013,
-	0x2104, 0xa085, 0x0400, 0x200a, 0x007c, 0x1078, 0x4c9d, 0x6003,
-	0x000f, 0x1078, 0x4d96, 0x007c, 0xa182, 0x0040, 0x0079, 0x6380,
-	0x6390, 0x6390, 0x6390, 0x6390, 0x6390, 0x6392, 0x641b, 0x6433,
-	0x6390, 0x6390, 0x6390, 0x6390, 0x6390, 0x6390, 0x6390, 0x6390,
-	0x1078, 0x12cd, 0x0e7e, 0x0d7e, 0x2071, 0x7c8c, 0x6110, 0x2168,
-	0x7614, 0xa6b4, 0x0fff, 0x86ff, 0x0040, 0x63ff, 0xa68c, 0x00ff,
-	0xa186, 0x0002, 0x0040, 0x63c4, 0xa186, 0x0028, 0x00c0, 0x63ae,
-	0x1078, 0x6bbd, 0x684b, 0x001c, 0x0078, 0x63c6, 0xd6dc, 0x0040,
-	0x63b9, 0x684b, 0x0015, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0x0078,
-	0x63c6, 0xd6d4, 0x0040, 0x63c4, 0x684b, 0x0007, 0x7318, 0x6b62,
-	0x731c, 0x6b5e, 0x0078, 0x63c6, 0x684b, 0x0000, 0x6837, 0x0103,
-	0x6e46, 0xa01e, 0xd6c4, 0x0040, 0x63d9, 0x7328, 0x732c, 0x6b56,
-	0x037e, 0x2308, 0x2019, 0x7c98, 0xad90, 0x0019, 0x1078, 0x6841,
-	0x037f, 0xd6cc, 0x0040, 0x640f, 0x7124, 0x695a, 0xa192, 0x0021,
-	0x00c8, 0x63ed, 0x2071, 0x7c98, 0x831c, 0x2300, 0xae18, 0xad90,
-	0x001d, 0x1078, 0x6841, 0x0078, 0x640f, 0x6838, 0xd0fc, 0x0040,
-	0x63f6, 0x2009, 0x0020, 0x695a, 0x0078, 0x63e2, 0x0f7e, 0x2d78,
-	0x1078, 0x67d9, 0x0f7f, 0x1078, 0x682e, 0x0078, 0x6411, 0x684b,
-	0x0000, 0x6837, 0x0103, 0x6e46, 0x684c, 0xd0ac, 0x0040, 0x640f,
-	0x6810, 0x6914, 0xa115, 0x0040, 0x640f, 0x1078, 0x6587, 0x1078,
-	0x3b92, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x0d7f, 0x0e7f,
-	0x1078, 0x5d1a, 0x007c, 0x0f7e, 0x6003, 0x0003, 0x2079, 0x7c8c,
-	0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x7c12, 0x7b16,
-	0x7e0a, 0x7d0e, 0x0f7f, 0x2c10, 0x1078, 0x19c7, 0x1078, 0x49ad,
-	0x1078, 0x4e56, 0x007c, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005,
-	0x3d18, 0x3e20, 0x2c10, 0x1078, 0x156a, 0x007c, 0xa182, 0x0040,
-	0x0079, 0x6442, 0x6452, 0x6452, 0x6452, 0x6452, 0x6452, 0x6454,
-	0x64eb, 0x6452, 0x6452, 0x6501, 0x6563, 0x6452, 0x6452, 0x6452,
-	0x6452, 0x656e, 0x1078, 0x12cd, 0x077e, 0x0f7e, 0x0e7e, 0x0d7e,
-	0x2071, 0x7c8c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x7e46,
-	0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e,
-	0x86ff, 0x0040, 0x64e6, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0040,
-	0x6475, 0x7018, 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, 0x0040,
-	0x64e6, 0x1078, 0x1327, 0x1040, 0x12cd, 0x2d00, 0x784a, 0x7f4c,
-	0xc7cd, 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, 0x783c, 0x683e,
-	0x7840, 0x6842, 0x6e46, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0040,
-	0x64af, 0xa186, 0x0028, 0x00c0, 0x6499, 0x684b, 0x001c, 0x0078,
-	0x64b1, 0xd6dc, 0x0040, 0x64a4, 0x684b, 0x0015, 0x7318, 0x6b62,
-	0x731c, 0x6b5e, 0x0078, 0x64b1, 0xd6d4, 0x0040, 0x64af, 0x684b,
-	0x0007, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0x0078, 0x64b1, 0x684b,
-	0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, 0xa01e, 0xd6c4,
-	0x0040, 0x64c6, 0x7328, 0x732c, 0x6b56, 0x037e, 0x2308, 0x2019,
-	0x7c98, 0xad90, 0x0019, 0x1078, 0x6841, 0x037f, 0xd6cc, 0x0040,
-	0x64e6, 0x7124, 0x695a, 0xa192, 0x0021, 0x00c8, 0x64da, 0x2071,
-	0x7c98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x1078, 0x6841,
-	0x0078, 0x64e6, 0x7838, 0xd0fc, 0x0040, 0x64e3, 0x2009, 0x0020,
-	0x695a, 0x0078, 0x64cf, 0x2d78, 0x1078, 0x67d9, 0x0d7f, 0x0e7f,
-	0x0f7f, 0x077f, 0x007c, 0x0f7e, 0x6003, 0x0003, 0x2079, 0x7c8c,
-	0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x7c12, 0x7b16,
-	0x7e0a, 0x7d0e, 0x0f7f, 0x2c10, 0x1078, 0x19c7, 0x1078, 0x5681,
-	0x007c, 0x0d7e, 0x6003, 0x0002, 0x1078, 0x4d45, 0x1078, 0x4e56,
-	0x6110, 0x2168, 0x694c, 0xd1e4, 0x0040, 0x6561, 0xd1cc, 0x0040,
-	0x653c, 0x6948, 0x6838, 0xd0fc, 0x0040, 0x6534, 0x017e, 0x684c,
-	0x007e, 0x6850, 0x007e, 0xad90, 0x000d, 0xa198, 0x000d, 0x2009,
-	0x0020, 0x157e, 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, 0x00f0,
-	0x6523, 0x157f, 0x007f, 0x6852, 0x007f, 0x684e, 0x017f, 0x2168,
-	0x1078, 0x1350, 0x0078, 0x655f, 0x017e, 0x1078, 0x1350, 0x0d7f,
-	0x1078, 0x682e, 0x0078, 0x655f, 0x6837, 0x0103, 0x6944, 0xa184,
-	0x00ff, 0xa186, 0x0002, 0x0040, 0x655b, 0xa086, 0x0028, 0x00c0,
-	0x654d, 0x684b, 0x001c, 0x0078, 0x655d, 0xd1dc, 0x0040, 0x6554,
-	0x684b, 0x0015, 0x0078, 0x655d, 0xd1d4, 0x0040, 0x655b, 0x684b,
-	0x0007, 0x0078, 0x655d, 0x684b, 0x0000, 0x1078, 0x3b92, 0x1078,
-	0x5d1a, 0x0d7f, 0x007c, 0x2019, 0x0001, 0x1078, 0x5880, 0x6003,
-	0x0002, 0x1078, 0x4d45, 0x1078, 0x4e56, 0x007c, 0x1078, 0x4d45,
-	0x1078, 0x22b5, 0x0d7e, 0x6110, 0x2168, 0x1078, 0x6a58, 0x0040,
-	0x6581, 0x6837, 0x0103, 0x684b, 0x0029, 0x1078, 0x3b92, 0x1078,
-	0x6ba9, 0x0d7f, 0x1078, 0x5d1a, 0x1078, 0x4e56, 0x007c, 0x684b,
-	0x0015, 0xd1fc, 0x0040, 0x6593, 0x684b, 0x0007, 0x8002, 0x8000,
-	0x810a, 0xa189, 0x0000, 0x6962, 0x685e, 0x007c, 0xa182, 0x0040,
-	0x0079, 0x659a, 0x65aa, 0x65aa, 0x65aa, 0x65aa, 0x65aa, 0x65ac,
-	0x65aa, 0x6650, 0x6658, 0x65aa, 0x65aa, 0x65aa, 0x65aa, 0x65aa,
-	0x65aa, 0x65aa, 0x1078, 0x12cd, 0x077e, 0x0f7e, 0x0e7e, 0x0d7e,
-	0x2071, 0x7c8c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x7e46,
-	0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e,
-	0x86ff, 0x0040, 0x6642, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0040,
-	0x65cd, 0x7018, 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, 0x0040,
-	0x663f, 0x1078, 0x1327, 0x1040, 0x12cd, 0x2d00, 0x784a, 0x7f4c,
-	0xa7bd, 0x0200, 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, 0x783c,
-	0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x00ff, 0xa186, 0x0002,
-	0x0040, 0x6608, 0xa186, 0x0028, 0x00c0, 0x65f2, 0x684b, 0x001c,
-	0x0078, 0x660a, 0xd6dc, 0x0040, 0x65fd, 0x684b, 0x0015, 0x7318,
-	0x6b62, 0x731c, 0x6b5e, 0x0078, 0x660a, 0xd6d4, 0x0040, 0x6608,
-	0x684b, 0x0007, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0x0078, 0x660a,
-	0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, 0xa01e,
-	0xd6c4, 0x0040, 0x661f, 0x7328, 0x732c, 0x6b56, 0x037e, 0x2308,
-	0x2019, 0x7c98, 0xad90, 0x0019, 0x1078, 0x6841, 0x037f, 0xd6cc,
-	0x0040, 0x663f, 0x7124, 0x695a, 0xa192, 0x0021, 0x00c8, 0x6633,
-	0x2071, 0x7c98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x1078,
-	0x6841, 0x0078, 0x663f, 0x7838, 0xd0fc, 0x0040, 0x663c, 0x2009,
-	0x0020, 0x695a, 0x0078, 0x6628, 0x2d78, 0x1078, 0x67d9, 0xd6dc,
-	0x00c0, 0x6645, 0xa006, 0x0078, 0x6649, 0x2001, 0x0001, 0x7218,
-	0x731c, 0x1078, 0x15ae, 0x0d7f, 0x0e7f, 0x0f7f, 0x077f, 0x007c,
-	0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x156a, 0x007c,
-	0x0d7e, 0x6003, 0x0002, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0040,
-	0x66bf, 0xd1cc, 0x0040, 0x668f, 0x6948, 0x6838, 0xd0fc, 0x0040,
-	0x6687, 0x017e, 0x684c, 0x007e, 0x6850, 0x007e, 0xad90, 0x000d,
-	0xa198, 0x000d, 0x2009, 0x0020, 0x157e, 0x21a8, 0x2304, 0x2012,
-	0x8318, 0x8210, 0x00f0, 0x6676, 0x157f, 0x007f, 0x6852, 0x007f,
-	0x684e, 0x017f, 0x2168, 0x1078, 0x1350, 0x0078, 0x66bd, 0x017e,
-	0x1078, 0x1350, 0x0d7f, 0x1078, 0x682e, 0x0078, 0x66bd, 0x6837,
-	0x0103, 0x6944, 0xa184, 0x00ff, 0xa186, 0x0002, 0x0040, 0x66ae,
-	0xa086, 0x0028, 0x00c0, 0x66a0, 0x684b, 0x001c, 0x0078, 0x66bb,
-	0xd1dc, 0x0040, 0x66a7, 0x684b, 0x0015, 0x0078, 0x66bb, 0xd1d4,
-	0x0040, 0x66ae, 0x684b, 0x0007, 0x0078, 0x66bb, 0x684b, 0x0000,
-	0x684c, 0xd0ac, 0x0040, 0x66bb, 0x6810, 0x6914, 0xa115, 0x0040,
-	0x66bb, 0x1078, 0x6587, 0x1078, 0x3b92, 0x1078, 0x5d1a, 0x0d7f,
-	0x007c, 0x1078, 0x4c9d, 0x0078, 0x66c7, 0x1078, 0x4d45, 0x1078,
-	0x6a58, 0x0040, 0x66de, 0x0d7e, 0x6110, 0x2168, 0x6837, 0x0103,
-	0x2009, 0x770c, 0x210c, 0xd18c, 0x00c0, 0x66e7, 0xd184, 0x00c0,
-	0x66e3, 0x6108, 0x694a, 0x1078, 0x3b92, 0x0d7f, 0x1078, 0x5d1a,
-	0x1078, 0x4d96, 0x007c, 0x684b, 0x0004, 0x0078, 0x66db, 0x684b,
-	0x0004, 0x0078, 0x66db, 0xa182, 0x0040, 0x0079, 0x66ef, 0x66ff,
-	0x66ff, 0x66ff, 0x66ff, 0x66ff, 0x6701, 0x66ff, 0x6704, 0x66ff,
-	0x66ff, 0x66ff, 0x66ff, 0x66ff, 0x66ff, 0x66ff, 0x66ff, 0x1078,
-	0x12cd, 0x1078, 0x5d1a, 0x007c, 0x007e, 0x027e, 0xa016, 0x1078,
-	0x156a, 0x027f, 0x007f, 0x007c, 0xa182, 0x0085, 0x0079, 0x6710,
-	0x6719, 0x6717, 0x6717, 0x6717, 0x6717, 0x6717, 0x6717, 0x1078,
-	0x12cd, 0x6003, 0x0001, 0x6106, 0x1078, 0x4941, 0x127e, 0x2091,
-	0x8000, 0x1078, 0x4d96, 0x127f, 0x007c, 0xa186, 0x0013, 0x00c0,
-	0x672f, 0x6004, 0xa082, 0x0085, 0x2008, 0x0079, 0x6763, 0xa186,
-	0x0027, 0x00c0, 0x6750, 0x1078, 0x4c9d, 0x1078, 0x22b5, 0x0d7e,
-	0x6010, 0x2068, 0x1078, 0x6a58, 0x0040, 0x6746, 0x6837, 0x0103,
-	0x684b, 0x0029, 0x1078, 0x3b92, 0x1078, 0x6ba9, 0x0d7f, 0x1078,
-	0x5d1a, 0x1078, 0x4d96, 0x007c, 0x1078, 0x5d4f, 0x0078, 0x674b,
-	0xa186, 0x0014, 0x00c0, 0x674c, 0x1078, 0x4c9d, 0x0d7e, 0x6010,
-	0x2068, 0x1078, 0x6a58, 0x0040, 0x6746, 0x6837, 0x0103, 0x684b,
-	0x0006, 0x0078, 0x6742, 0x676c, 0x676a, 0x676a, 0x676a, 0x676a,
-	0x676a, 0x6775, 0x1078, 0x12cd, 0x1078, 0x4c9d, 0x6017, 0x0014,
-	0x6003, 0x000c, 0x1078, 0x4d96, 0x007c, 0x1078, 0x4c9d, 0x6017,
-	0x0014, 0x6003, 0x000e, 0x1078, 0x4d96, 0x007c, 0xa182, 0x008c,
-	0x00c8, 0x6788, 0xa182, 0x0085, 0x0048, 0x6788, 0x0079, 0x678b,
-	0x1078, 0x5d4f, 0x007c, 0x6792, 0x6792, 0x6792, 0x6792, 0x6794,
-	0x67b3, 0x6792, 0x1078, 0x12cd, 0x0d7e, 0x1078, 0x6ba9, 0x1078,
-	0x6a58, 0x0040, 0x67af, 0x6010, 0x2068, 0x6837, 0x0103, 0x6850,
-	0xd0b4, 0x0040, 0x67a7, 0x684b, 0x0006, 0x0078, 0x67ab, 0x684b,
-	0x0005, 0x1078, 0x6c5c, 0x6847, 0x0000, 0x1078, 0x3b92, 0x1078,
-	0x5d1a, 0x0d7f, 0x007c, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x6a58,
-	0x0040, 0x67ce, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0040, 0x67c4,
-	0x684b, 0x0006, 0x0078, 0x67c8, 0x684b, 0x0005, 0x1078, 0x6c5c,
-	0x6847, 0x0000, 0x1078, 0x3b92, 0x1078, 0x6ba9, 0x0d7f, 0x1078,
-	0x5d1a, 0x007c, 0x1078, 0x4c9d, 0x1078, 0x5d1a, 0x1078, 0x4d96,
+	0x2071, 0x8aa2, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0040, 0x6730,
+	0x601c, 0xa086, 0x0006, 0x00c0, 0x672b, 0x88ff, 0x0040, 0x66de,
+	0x2800, 0xac06, 0x00c0, 0x672b, 0x0078, 0x66e9, 0x6018, 0xa206,
+	0x00c0, 0x672b, 0x85ff, 0x0040, 0x66e9, 0x6020, 0xa106, 0x00c0,
+	0x672b, 0x703c, 0xac06, 0x00c0, 0x66fb, 0x037e, 0x2019, 0x0001,
+	0x1078, 0x642d, 0x7033, 0x0000, 0x703f, 0x0000, 0x7043, 0x0000,
+	0x7047, 0x0000, 0x037f, 0x7038, 0xac36, 0x00c0, 0x6701, 0x660c,
+	0x763a, 0x7034, 0xac36, 0x00c0, 0x670f, 0x2c00, 0xaf36, 0x0040,
+	0x670d, 0x2f00, 0x7036, 0x0078, 0x670f, 0x7037, 0x0000, 0x660c,
+	0x067e, 0x2c00, 0xaf06, 0x0040, 0x6718, 0x7e0e, 0x0078, 0x6719,
+	0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x77ed, 0x0040,
+	0x6723, 0x1078, 0x86aa, 0x1078, 0x79a8, 0x88ff, 0x00c0, 0x673a,
+	0x0c7f, 0x0078, 0x66cd, 0x2c78, 0x600c, 0x2060, 0x0078, 0x66cd,
+	0xa006, 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f,
+	0x0f7f, 0x007c, 0x6017, 0x0000, 0x0c7f, 0xa8c5, 0x0001, 0x0078,
+	0x6731, 0x0e7e, 0x2071, 0x8aa2, 0x2001, 0x8800, 0x2004, 0xa086,
+	0x0002, 0x00c0, 0x674f, 0x7007, 0x0005, 0x0078, 0x6751, 0x7007,
+	0x0000, 0x0e7f, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x067e, 0x027e,
+	0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0x8aa2, 0x2c10, 0x7638,
+	0x2660, 0x2678, 0x8cff, 0x0040, 0x6791, 0x2200, 0xac06, 0x00c0,
+	0x678c, 0x7038, 0xac36, 0x00c0, 0x676f, 0x660c, 0x763a, 0x7034,
+	0xac36, 0x00c0, 0x677d, 0x2c00, 0xaf36, 0x0040, 0x677b, 0x2f00,
+	0x7036, 0x0078, 0x677d, 0x7037, 0x0000, 0x660c, 0x2c00, 0xaf06,
+	0x0040, 0x6785, 0x7e0e, 0x0078, 0x6786, 0x2678, 0x600f, 0x0000,
+	0xa085, 0x0001, 0x0078, 0x6791, 0x2c78, 0x600c, 0x2060, 0x0078,
+	0x6762, 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0e7f, 0x0f7f,
+	0x007c, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x007e, 0x127e,
+	0x2091, 0x8000, 0x2071, 0x8aa2, 0x760c, 0x2660, 0x2678, 0x8cff,
+	0x0040, 0x682a, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x00c0,
+	0x6825, 0x7024, 0xac06, 0x00c0, 0x67d8, 0x2069, 0x0100, 0x68c0,
+	0xa005, 0x0040, 0x67d8, 0x1078, 0x6232, 0x68c3, 0x0000, 0x1078,
+	0x6741, 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384,
+	0x1000, 0x0040, 0x67cf, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069,
+	0x0100, 0x6824, 0xd084, 0x0040, 0x67d7, 0x6827, 0x0001, 0x037f,
+	0x700c, 0xac36, 0x00c0, 0x67de, 0x660c, 0x760e, 0x7008, 0xac36,
+	0x00c0, 0x67ec, 0x2c00, 0xaf36, 0x0040, 0x67ea, 0x2f00, 0x700a,
+	0x0078, 0x67ec, 0x700b, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06,
+	0x0040, 0x67f5, 0x7e0e, 0x0078, 0x67f6, 0x2678, 0x600f, 0x0000,
+	0x1078, 0x79c1, 0x00c0, 0x6800, 0x1078, 0x24e5, 0x0078, 0x681c,
+	0x1078, 0x79d5, 0x00c0, 0x6808, 0x1078, 0x6bc7, 0x0078, 0x681c,
+	0x6010, 0x2068, 0x1078, 0x77ed, 0x0040, 0x681c, 0x601c, 0xa086,
+	0x0003, 0x00c0, 0x6832, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000,
+	0x1078, 0x4376, 0x1078, 0x799b, 0x6003, 0x0000, 0x1078, 0x79a8,
+	0x1078, 0x6601, 0x0c7f, 0x0078, 0x67a7, 0x2c78, 0x600c, 0x2060,
+	0x0078, 0x67a7, 0x127f, 0x007f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f,
+	0x0f7f, 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x6813, 0x1078,
+	0x86aa, 0x0078, 0x681c, 0x037e, 0x157e, 0x137e, 0x147e, 0x3908,
+	0xa006, 0xa190, 0x0020, 0x221c, 0xa39e, 0x231e, 0x00c0, 0x684c,
+	0x8210, 0x8000, 0x0078, 0x6843, 0xa005, 0x0040, 0x6856, 0x20a9,
+	0x0020, 0x2198, 0xa110, 0x22a0, 0x22c8, 0x53a3, 0x147f, 0x137f,
+	0x157f, 0x037f, 0x007c, 0x0d7e, 0x20a1, 0x020b, 0x1078, 0x5c87,
+	0x20a3, 0x0200, 0x20a3, 0x0014, 0x60c3, 0x0014, 0x20a3, 0x0000,
+	0x20a3, 0x0000, 0x2099, 0x8a9c, 0x20a9, 0x0004, 0x53a6, 0x20a3,
+	0x0004, 0x20a3, 0x7878, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x1078,
+	0x621e, 0x0d7f, 0x007c, 0x20a1, 0x020b, 0x1078, 0x5c87, 0x20a3,
+	0x0210, 0x20a3, 0x0018, 0x20a3, 0x0800, 0x7810, 0xa084, 0xff00,
+	0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
+	0x0000, 0x20a3, 0x0000, 0x7810, 0xa084, 0x00ff, 0x20a2, 0x20a3,
+	0x0000, 0x20a3, 0x0000, 0x60c3, 0x0018, 0x1078, 0x621e, 0x007c,
+	0x2061, 0x8f00, 0x2a70, 0x7060, 0x7046, 0x704b, 0x8f00, 0x007c,
+	0x0e7e, 0x127e, 0x2071, 0x8800, 0x2091, 0x8000, 0x7544, 0xa582,
+	0x0001, 0x0048, 0x68da, 0x7048, 0x2060, 0x6000, 0xa086, 0x0000,
+	0x0040, 0x68c6, 0xace0, 0x000c, 0x7054, 0xac02, 0x00c8, 0x68c2,
+	0x0078, 0x68b5, 0x2061, 0x8f00, 0x0078, 0x68b5, 0x6003, 0x0008,
+	0x8529, 0x7546, 0xaca8, 0x000c, 0x7054, 0xa502, 0x00c8, 0x68d6,
+	0x754a, 0xa085, 0x0001, 0x127f, 0x0e7f, 0x007c, 0x704b, 0x8f00,
+	0x0078, 0x68d1, 0xa006, 0x0078, 0x68d3, 0x0e7e, 0x2071, 0x8800,
+	0x7544, 0xa582, 0x0001, 0x0048, 0x690b, 0x7048, 0x2060, 0x6000,
+	0xa086, 0x0000, 0x0040, 0x68f8, 0xace0, 0x000c, 0x7054, 0xac02,
+	0x00c8, 0x68f4, 0x0078, 0x68e7, 0x2061, 0x8f00, 0x0078, 0x68e7,
+	0x6003, 0x0008, 0x8529, 0x7546, 0xaca8, 0x000c, 0x7054, 0xa502,
+	0x00c8, 0x6907, 0x754a, 0xa085, 0x0001, 0x0e7f, 0x007c, 0x704b,
+	0x8f00, 0x0078, 0x6903, 0xa006, 0x0078, 0x6905, 0xac82, 0x8f00,
+	0x1048, 0x12d2, 0x2001, 0x8815, 0x2004, 0xac02, 0x10c8, 0x12d2,
+	0xa006, 0x6006, 0x600a, 0x600e, 0x6012, 0x6016, 0x601a, 0x601f,
+	0x0000, 0x6003, 0x0000, 0x6022, 0x6026, 0x602a, 0x602e, 0x2061,
+	0x8800, 0x6044, 0x8000, 0x6046, 0xa086, 0x0001, 0x0040, 0x6931,
+	0x007c, 0x127e, 0x2091, 0x8000, 0x1078, 0x5888, 0x127f, 0x0078,
+	0x6930, 0x601c, 0xa084, 0x000f, 0x0079, 0x693e, 0x6947, 0x6958,
+	0x6974, 0x6990, 0x7a52, 0x7a6e, 0x7a8a, 0x6947, 0x6958, 0xa186,
+	0x0013, 0x00c0, 0x6950, 0x1078, 0x578f, 0x1078, 0x5888, 0x007c,
+	0xa18e, 0x0047, 0x00c0, 0x6957, 0xa016, 0x1078, 0x1594, 0x007c,
+	0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12d2, 0x1079, 0x6962,
+	0x067f, 0x007c, 0x6972, 0x6a89, 0x6be6, 0x6972, 0x6c46, 0x6972,
+	0x6972, 0x6972, 0x6a28, 0x6f24, 0x6972, 0x6972, 0x6972, 0x6972,
+	0x6972, 0x6972, 0x1078, 0x12d2, 0x067e, 0x6000, 0xa0b2, 0x0010,
+	0x10c8, 0x12d2, 0x1079, 0x697e, 0x067f, 0x007c, 0x698e, 0x698e,
+	0x698e, 0x698e, 0x698e, 0x698e, 0x698e, 0x698e, 0x7419, 0x74f8,
+	0x698e, 0x7432, 0x7492, 0x7432, 0x7492, 0x698e, 0x1078, 0x12d2,
+	0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12d2, 0x1079, 0x699a,
+	0x067f, 0x007c, 0x69aa, 0x6f65, 0x7020, 0x70fa, 0x7257, 0x69aa,
+	0x69aa, 0x69aa, 0x6f40, 0x73c7, 0x73cb, 0x69aa, 0x69aa, 0x69aa,
+	0x69aa, 0x73f5, 0x1078, 0x12d2, 0x20a9, 0x000e, 0x2e98, 0x6010,
+	0x20a0, 0x53a3, 0x20a9, 0x0006, 0x3310, 0x3420, 0x9398, 0x94a0,
+	0x3318, 0x3428, 0x222e, 0x2326, 0xa290, 0x0002, 0xa5a8, 0x0002,
+	0xa398, 0x0002, 0xa4a0, 0x0002, 0x00f0, 0x69ba, 0x0e7e, 0x1078,
+	0x77ed, 0x0040, 0x69d1, 0x6010, 0x2070, 0x7007, 0x0000, 0x7037,
+	0x0103, 0x0e7f, 0x1078, 0x690e, 0x007c, 0x0d7e, 0x037e, 0x7330,
+	0xa386, 0x0200, 0x00c0, 0x69e2, 0x6018, 0x2068, 0x6813, 0x00ff,
+	0x6817, 0xfffd, 0x6010, 0xa005, 0x0040, 0x69ec, 0x2068, 0x6807,
+	0x0000, 0x6837, 0x0103, 0x6b32, 0x1078, 0x690e, 0x037f, 0x0d7f,
+	0x007c, 0x017e, 0x20a9, 0x002a, 0xae80, 0x000c, 0x2098, 0x6010,
+	0xa080, 0x0002, 0x20a0, 0x53a3, 0x20a9, 0x002a, 0x6010, 0xa080,
+	0x0001, 0x2004, 0xa080, 0x0002, 0x20a0, 0x53a3, 0x0e7e, 0x6010,
+	0x2004, 0x2070, 0x7037, 0x0103, 0x0e7f, 0x1078, 0x690e, 0x017f,
+	0x007c, 0x0d7e, 0x20a9, 0x000e, 0x2e98, 0x6010, 0x20a0, 0x53a3,
+	0xa1b6, 0x0015, 0x00c0, 0x6a25, 0x6018, 0x2068, 0x7038, 0x680a,
+	0x703c, 0x680e, 0x6800, 0xc08d, 0x6802, 0x0d7f, 0x0078, 0x69c6,
+	0x2100, 0xa1b2, 0x0040, 0x10c8, 0x12d2, 0x0079, 0x6a2f, 0x6a71,
+	0x6a7d, 0x6a71, 0x6a71, 0x6a71, 0x6a71, 0x6a6f, 0x6a6f, 0x6a6f,
+	0x6a6f, 0x6a6f, 0x6a6f, 0x6a6f, 0x6a6f, 0x6a6f, 0x6a6f, 0x6a6f,
+	0x6a6f, 0x6a6f, 0x6a6f, 0x6a6f, 0x6a6f, 0x6a6f, 0x6a6f, 0x6a6f,
+	0x6a6f, 0x6a6f, 0x6a6f, 0x6a6f, 0x6a6f, 0x6a6f, 0x6a71, 0x6a6f,
+	0x6a71, 0x6a71, 0x6a6f, 0x6a6f, 0x6a6f, 0x6a6f, 0x6a6f, 0x6a71,
+	0x6a6f, 0x6a6f, 0x6a6f, 0x6a6f, 0x6a6f, 0x6a6f, 0x6a6f, 0x6a6f,
+	0x6a6f, 0x6a71, 0x6a6f, 0x6a6f, 0x6a6f, 0x6a6f, 0x6a6f, 0x6a6f,
+	0x6a6f, 0x6a6f, 0x6a6f, 0x6a6f, 0x6a71, 0x6a6f, 0x6a6f, 0x1078,
+	0x12d2, 0x6003, 0x0001, 0x6106, 0x1078, 0x53e6, 0x127e, 0x2091,
+	0x8000, 0x1078, 0x5888, 0x127f, 0x007c, 0x6003, 0x0001, 0x6106,
+	0x1078, 0x53e6, 0x127e, 0x2091, 0x8000, 0x1078, 0x5888, 0x127f,
+	0x007c, 0x6004, 0xa0b2, 0x0040, 0x10c8, 0x12d2, 0xa1b6, 0x0013,
+	0x00c0, 0x6a95, 0x2008, 0x0079, 0x6b35, 0xa1b6, 0x0027, 0x00c0,
+	0x6af2, 0x1078, 0x578f, 0x6004, 0x1078, 0x79c1, 0x0040, 0x6ab2,
+	0x1078, 0x79d5, 0x0040, 0x6aea, 0xa08e, 0x0021, 0x0040, 0x6aee,
+	0xa08e, 0x0022, 0x0040, 0x6aea, 0xa08e, 0x003d, 0x0040, 0x6aee,
+	0x0078, 0x6ae5, 0x1078, 0x24e5, 0x2001, 0x0007, 0x1078, 0x3f05,
+	0x6018, 0xa080, 0x0028, 0x200c, 0x1078, 0x6bc7, 0xa186, 0x007e,
+	0x00c0, 0x6ac7, 0x2001, 0x8830, 0x2014, 0xc285, 0x2202, 0x017e,
+	0x027e, 0x037e, 0x2110, 0x2019, 0x0028, 0x1078, 0x54f0, 0x087e,
+	0x2041, 0x0000, 0x1078, 0x5419, 0x0c7e, 0x6018, 0xa065, 0x0040,
+	0x6adb, 0x1078, 0x418b, 0x0c7f, 0x2c08, 0x1078, 0x84d2, 0x087f,
+	0x037f, 0x027f, 0x017f, 0x1078, 0x3f76, 0x1078, 0x690e, 0x1078,
+	0x5888, 0x007c, 0x1078, 0x6bc7, 0x0078, 0x6ae5, 0x1078, 0x6bda,
+	0x0078, 0x6ae5, 0xa186, 0x0014, 0x00c0, 0x6ae9, 0x1078, 0x578f,
+	0x1078, 0x24bf, 0x1078, 0x79c1, 0x00c0, 0x6b11, 0x1078, 0x24e5,
+	0x6018, 0xa080, 0x0028, 0x200c, 0x1078, 0x6bc7, 0xa186, 0x007e,
+	0x00c0, 0x6b0f, 0x2001, 0x8830, 0x200c, 0xc185, 0x2102, 0x0078,
+	0x6ae5, 0x1078, 0x79d5, 0x00c0, 0x6b19, 0x1078, 0x6bc7, 0x0078,
+	0x6ae5, 0x6004, 0xa08e, 0x0032, 0x00c0, 0x6b2a, 0x0e7e, 0x0f7e,
+	0x2071, 0x8881, 0x2079, 0x0000, 0x1078, 0x27c9, 0x0f7f, 0x0e7f,
+	0x0078, 0x6ae5, 0x6004, 0xa08e, 0x0021, 0x0040, 0x6b15, 0xa08e,
+	0x0022, 0x1040, 0x6bda, 0x0078, 0x6ae5, 0x6b77, 0x6b79, 0x6b7d,
+	0x6b81, 0x6b85, 0x6b89, 0x6b75, 0x6b75, 0x6b75, 0x6b75, 0x6b75,
+	0x6b75, 0x6b75, 0x6b75, 0x6b75, 0x6b75, 0x6b75, 0x6b75, 0x6b75,
+	0x6b75, 0x6b75, 0x6b75, 0x6b75, 0x6b75, 0x6b75, 0x6b75, 0x6b75,
+	0x6b75, 0x6b75, 0x6b75, 0x6b8d, 0x6b93, 0x6b75, 0x6b9d, 0x6b93,
+	0x6b75, 0x6b75, 0x6b75, 0x6b75, 0x6b75, 0x6b93, 0x6b93, 0x6b75,
+	0x6b75, 0x6b75, 0x6b75, 0x6b75, 0x6b75, 0x6b75, 0x6b75, 0x6b75,
+	0x6b75, 0x6b75, 0x6b75, 0x6b75, 0x6b75, 0x6b75, 0x6b75, 0x6b75,
+	0x6b75, 0x6b75, 0x6b93, 0x6b75, 0x6b75, 0x1078, 0x12d2, 0x0078,
+	0x6b93, 0x2001, 0x000b, 0x0078, 0x6ba6, 0x2001, 0x0003, 0x0078,
+	0x6ba6, 0x2001, 0x0005, 0x0078, 0x6ba6, 0x2001, 0x0001, 0x0078,
+	0x6ba6, 0x2001, 0x0009, 0x0078, 0x6ba6, 0x1078, 0x12d2, 0x0078,
+	0x6ba5, 0x1078, 0x3f05, 0x1078, 0x578f, 0x6003, 0x0002, 0x6017,
+	0x0028, 0x1078, 0x5888, 0x0078, 0x6ba5, 0x1078, 0x578f, 0x6003,
+	0x0004, 0x6017, 0x0028, 0x1078, 0x5888, 0x007c, 0x1078, 0x3f05,
+	0x1078, 0x578f, 0x6003, 0x0002, 0x037e, 0x2019, 0x885c, 0x2304,
+	0xa084, 0xff00, 0x00c0, 0x6bb8, 0x2019, 0x0028, 0x0078, 0x6bc1,
+	0x8007, 0xa09a, 0x0004, 0x0048, 0x6bb4, 0x8003, 0x801b, 0x831b,
+	0xa318, 0x6316, 0x037f, 0x1078, 0x5888, 0x0078, 0x6ba5, 0x0e7e,
+	0x1078, 0x77ed, 0x0040, 0x6bd8, 0x6010, 0x2070, 0x7038, 0xd0fc,
+	0x0040, 0x6bd8, 0x7007, 0x0000, 0x7037, 0x0103, 0x7033, 0x0100,
+	0x0e7f, 0x007c, 0x0e7e, 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070,
+	0x7037, 0x0103, 0x7023, 0x8001, 0x0e7f, 0x007c, 0x0d7e, 0x6618,
+	0x2668, 0x6804, 0xa084, 0x00ff, 0x0d7f, 0xa0b2, 0x000c, 0x10c8,
+	0x12d2, 0x6604, 0xa6b6, 0x0028, 0x00c0, 0x6bfa, 0x1078, 0x7a0a,
+	0x0078, 0x6c35, 0x6604, 0xa6b6, 0x0029, 0x00c0, 0x6c03, 0x1078,
+	0x7a24, 0x0078, 0x6c35, 0x6604, 0xa6b6, 0x001f, 0x00c0, 0x6c0c,
+	0x1078, 0x69ac, 0x0078, 0x6c35, 0x6604, 0xa6b6, 0x0000, 0x00c0,
+	0x6c15, 0x1078, 0x6a11, 0x0078, 0x6c35, 0x6604, 0xa6b6, 0x0022,
+	0x00c0, 0x6c1e, 0x1078, 0x69d5, 0x0078, 0x6c35, 0x6604, 0xa6b6,
+	0x003d, 0x00c0, 0x6c27, 0x1078, 0x69f1, 0x0078, 0x6c35, 0xa1b6,
+	0x0015, 0x00c0, 0x6c2f, 0x1079, 0x6c3a, 0x0078, 0x6c35, 0xa1b6,
+	0x0016, 0x00c0, 0x6c36, 0x1079, 0x6d93, 0x007c, 0x1078, 0x6950,
+	0x0078, 0x6c35, 0x6c5e, 0x6c61, 0x6c5e, 0x6ca2, 0x6c5e, 0x6d2f,
+	0x6c5e, 0x6c5e, 0x6c5e, 0x6d6b, 0x6c5e, 0x6d81, 0xa1b6, 0x0048,
+	0x0040, 0x6c52, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078,
+	0x1594, 0x007c, 0x0e7e, 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070,
+	0x7037, 0x0103, 0x0e7f, 0x1078, 0x690e, 0x007c, 0x0005, 0x0005,
+	0x007c, 0x0e7e, 0x2071, 0x8800, 0x707c, 0xa086, 0x0074, 0x00c0,
+	0x6c8b, 0x1078, 0x84a6, 0x00c0, 0x6c7d, 0x0d7e, 0x6018, 0x2068,
+	0x1078, 0x6c8f, 0x0d7f, 0x2001, 0x0006, 0x1078, 0x3f05, 0x1078,
+	0x24e5, 0x1078, 0x690e, 0x0078, 0x6c8d, 0x2001, 0x000a, 0x1078,
+	0x3f05, 0x1078, 0x24e5, 0x6003, 0x0001, 0x6007, 0x0001, 0x1078,
+	0x53e6, 0x0078, 0x6c8d, 0x1078, 0x6d1f, 0x0e7f, 0x007c, 0x6800,
+	0xd084, 0x0040, 0x6ca1, 0x2001, 0x0000, 0x1078, 0x3ef1, 0x2069,
+	0x8851, 0x6804, 0xd0a4, 0x0040, 0x6ca1, 0x2001, 0x0006, 0x1078,
+	0x3f2c, 0x007c, 0x0d7e, 0x2011, 0x881f, 0x2204, 0xa086, 0x0074,
+	0x00c0, 0x6d1b, 0x1078, 0x6e79, 0x6018, 0x2068, 0xa080, 0x0028,
+	0x2014, 0xa286, 0x007e, 0x0040, 0x6cca, 0xa286, 0x0080, 0x00c0,
+	0x6cf3, 0x6813, 0x00ff, 0x6817, 0xfffc, 0x6010, 0xa005, 0x0040,
+	0x6ce9, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6833, 0x0200,
+	0x0078, 0x6ce9, 0x0e7e, 0x0f7e, 0x6813, 0x00ff, 0x6817, 0xfffe,
+	0x2071, 0x8830, 0x2e04, 0xa085, 0x0003, 0x2072, 0x2071, 0x8d80,
+	0x2079, 0x0100, 0x2e04, 0xa084, 0x00ff, 0x2069, 0x881a, 0x206a,
+	0x78e6, 0x8e70, 0x2e04, 0x2069, 0x881b, 0x206a, 0x78ea, 0x0f7f,
+	0x0e7f, 0x2001, 0x0006, 0x1078, 0x3f05, 0x1078, 0x24e5, 0x1078,
+	0x690e, 0x0078, 0x6d1d, 0x0e7e, 0x2071, 0x8830, 0x2e04, 0xd09c,
+	0x0040, 0x6d0e, 0x2071, 0x8d80, 0x7108, 0x720c, 0xa18c, 0x00ff,
+	0x00c0, 0x6d06, 0xa284, 0xff00, 0x0040, 0x6d0e, 0x6018, 0x2070,
+	0x70a0, 0xd0bc, 0x00c0, 0x6d0e, 0x7112, 0x7216, 0x0e7f, 0x2001,
+	0x0004, 0x1078, 0x3f05, 0x6003, 0x0001, 0x6007, 0x0003, 0x1078,
+	0x53e6, 0x0078, 0x6d1d, 0x1078, 0x6d1f, 0x0d7f, 0x007c, 0x2001,
+	0x8800, 0x2004, 0xa086, 0x0003, 0x0040, 0x6d2a, 0x2001, 0x0007,
+	0x1078, 0x3f05, 0x1078, 0x24e5, 0x1078, 0x690e, 0x007c, 0x0e7e,
+	0x2071, 0x8800, 0x707c, 0xa086, 0x0014, 0x00c0, 0x6d65, 0x7000,
+	0xa086, 0x0003, 0x00c0, 0x6d42, 0x6010, 0xa005, 0x00c0, 0x6d42,
+	0x1078, 0x31f8, 0x0d7e, 0x6018, 0x2068, 0x1078, 0x400a, 0x1078,
+	0x6c8f, 0x0d7f, 0x1078, 0x6e83, 0x00c0, 0x6d65, 0x2001, 0x0006,
+	0x1078, 0x3f05, 0x0e7e, 0x6010, 0xa005, 0x0040, 0x6d5e, 0x2070,
+	0x7007, 0x0000, 0x7037, 0x0103, 0x7033, 0x0200, 0x0e7f, 0x1078,
+	0x24e5, 0x1078, 0x690e, 0x0078, 0x6d69, 0x1078, 0x6bc7, 0x1078,
+	0x6d1f, 0x0e7f, 0x007c, 0x2011, 0x881f, 0x2204, 0xa086, 0x0014,
+	0x00c0, 0x6d7e, 0x2001, 0x0002, 0x1078, 0x3f05, 0x6003, 0x0001,
+	0x6007, 0x0001, 0x1078, 0x53e6, 0x0078, 0x6d80, 0x1078, 0x6d1f,
+	0x007c, 0x2011, 0x881f, 0x2204, 0xa086, 0x0004, 0x00c0, 0x6d90,
+	0x2001, 0x0007, 0x1078, 0x3f05, 0x1078, 0x690e, 0x0078, 0x6d92,
+	0x1078, 0x6d1f, 0x007c, 0x6c5e, 0x6d9f, 0x6c5e, 0x6dc7, 0x6c5e,
+	0x6e2c, 0x6c5e, 0x6c5e, 0x6c5e, 0x6e41, 0x6c5e, 0x6e54, 0x0d7e,
+	0x0c7e, 0x1078, 0x6e67, 0x00c0, 0x6db5, 0x2001, 0x0000, 0x1078,
+	0x3ef1, 0x2001, 0x0002, 0x1078, 0x3f05, 0x6003, 0x0001, 0x6007,
+	0x0002, 0x1078, 0x53e6, 0x0078, 0x6dc4, 0x2009, 0x8d8f, 0x2104,
+	0xa084, 0xff00, 0xa086, 0x1900, 0x00c0, 0x6dc2, 0x1078, 0x690e,
+	0x0078, 0x6dc4, 0x1078, 0x6d1f, 0x0c7f, 0x0d7f, 0x007c, 0x1078,
+	0x6e76, 0x00c0, 0x6ddb, 0x2001, 0x0000, 0x1078, 0x3ef1, 0x2001,
+	0x0002, 0x1078, 0x3f05, 0x6003, 0x0001, 0x6007, 0x0002, 0x1078,
+	0x53e6, 0x0078, 0x6e07, 0x1078, 0x6bc7, 0x2009, 0x8d8e, 0x2134,
+	0xa6b4, 0x00ff, 0xa686, 0x0005, 0x0040, 0x6e08, 0xa686, 0x000b,
+	0x0040, 0x6e05, 0x2009, 0x8d8f, 0x2104, 0xa084, 0xff00, 0x00c0,
+	0x6df5, 0xa686, 0x0009, 0x0040, 0x6e08, 0xa086, 0x1900, 0x00c0,
+	0x6e05, 0xa686, 0x0009, 0x0040, 0x6e08, 0x2001, 0x0004, 0x1078,
+	0x3f05, 0x1078, 0x690e, 0x0078, 0x6e07, 0x1078, 0x6d1f, 0x007c,
+	0x0d7e, 0x6010, 0x2068, 0x1078, 0x77ed, 0x0040, 0x6e16, 0x6838,
+	0xd0fc, 0x0040, 0x6e16, 0x0d7f, 0x0078, 0x6e05, 0x6018, 0x2068,
+	0x6840, 0xa084, 0x00ff, 0xa005, 0x0040, 0x6e27, 0x8001, 0x6842,
+	0x6017, 0x000a, 0x6007, 0x0016, 0x0d7f, 0x0078, 0x6e07, 0x1078,
+	0x24bf, 0x0d7f, 0x0078, 0x6e05, 0x1078, 0x6e76, 0x00c0, 0x6e3c,
+	0x2001, 0x0004, 0x1078, 0x3f05, 0x6003, 0x0001, 0x6007, 0x0003,
+	0x1078, 0x53e6, 0x0078, 0x6e40, 0x1078, 0x6bc7, 0x1078, 0x6d1f,
+	0x007c, 0x1078, 0x6e76, 0x00c0, 0x6e51, 0x2001, 0x0008, 0x1078,
+	0x3f05, 0x6003, 0x0001, 0x6007, 0x0005, 0x1078, 0x53e6, 0x0078,
+	0x6e53, 0x1078, 0x6d1f, 0x007c, 0x1078, 0x6e76, 0x00c0, 0x6e64,
+	0x2001, 0x000a, 0x1078, 0x3f05, 0x6003, 0x0001, 0x6007, 0x0001,
+	0x1078, 0x53e6, 0x0078, 0x6e66, 0x1078, 0x6d1f, 0x007c, 0x2009,
+	0x8d8e, 0x2104, 0xa086, 0x0003, 0x00c0, 0x6e75, 0x2009, 0x8d8f,
+	0x2104, 0xa084, 0xff00, 0xa086, 0x2a00, 0x007c, 0xa085, 0x0001,
+	0x007c, 0x0c7e, 0x017e, 0xac88, 0x0006, 0x2164, 0x1078, 0x3fa0,
+	0x017f, 0x0c7f, 0x007c, 0x0e7e, 0x2071, 0x8d8c, 0x7004, 0xa086,
+	0x0014, 0x00c0, 0x6ea3, 0x7008, 0xa086, 0x0800, 0x00c0, 0x6ea3,
+	0x700c, 0xd0ec, 0x0040, 0x6ea1, 0xa084, 0x0f00, 0xa086, 0x0100,
+	0x00c0, 0x6ea1, 0x7024, 0xd0a4, 0x0040, 0x6ea1, 0xa006, 0x0078,
+	0x6ea3, 0xa085, 0x0001, 0x0e7f, 0x007c, 0x0e7e, 0x0d7e, 0x0c7e,
+	0x077e, 0x057e, 0x047e, 0x027e, 0x007e, 0x127e, 0x2091, 0x8000,
+	0x2029, 0x8aab, 0x252c, 0x2021, 0x8ab1, 0x2424, 0x2061, 0x8f00,
+	0x2071, 0x8800, 0x7244, 0x7060, 0xa202, 0x00c8, 0x6efa, 0x1078,
+	0x870c, 0x0040, 0x6ef2, 0x671c, 0xa786, 0x0001, 0x0040, 0x6ef2,
+	0xa786, 0x0007, 0x0040, 0x6ef2, 0x2500, 0xac06, 0x0040, 0x6ef2,
+	0x2400, 0xac06, 0x0040, 0x6ef2, 0x0c7e, 0x6000, 0xa086, 0x0004,
+	0x00c0, 0x6edc, 0x1078, 0x16af, 0x6010, 0x2068, 0x1078, 0x77ed,
+	0x0040, 0x6eef, 0xa786, 0x0003, 0x00c0, 0x6f04, 0x6837, 0x0103,
+	0x6b4a, 0x6847, 0x0000, 0x1078, 0x4376, 0x1078, 0x799b, 0x1078,
+	0x79a8, 0x0c7f, 0xace0, 0x000c, 0x7054, 0xac02, 0x00c8, 0x6efa,
+	0x0078, 0x6eba, 0x127f, 0x007f, 0x027f, 0x047f, 0x057f, 0x077f,
+	0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0xa786, 0x0006, 0x00c0, 0x6ee6,
+	0x1078, 0x86aa, 0x0078, 0x6eef, 0x220c, 0x2304, 0xa106, 0x00c0,
+	0x6f17, 0x8210, 0x8318, 0x00f0, 0x6f0c, 0xa006, 0x007c, 0x2304,
+	0xa102, 0x0048, 0x6f1f, 0x2001, 0x0001, 0x0078, 0x6f21, 0x2001,
+	0x0000, 0xa18d, 0x0001, 0x007c, 0x6004, 0xa08a, 0x0040, 0x10c8,
+	0x12d2, 0x1078, 0x79c1, 0x0040, 0x6f33, 0x1078, 0x79d5, 0x0040,
+	0x6f3c, 0x0078, 0x6f35, 0x1078, 0x24e5, 0x1078, 0x578f, 0x1078,
+	0x690e, 0x1078, 0x5888, 0x007c, 0x1078, 0x6bc7, 0x0078, 0x6f35,
+	0xa182, 0x0040, 0x0079, 0x6f44, 0x6f57, 0x6f57, 0x6f57, 0x6f57,
+	0x6f57, 0x6f57, 0x6f57, 0x6f57, 0x6f57, 0x6f57, 0x6f57, 0x6f59,
+	0x6f59, 0x6f59, 0x6f59, 0x6f57, 0x6f57, 0x6f57, 0x6f59, 0x1078,
+	0x12d2, 0x6003, 0x0001, 0x6106, 0x1078, 0x5399, 0x127e, 0x2091,
+	0x8000, 0x1078, 0x5888, 0x127f, 0x007c, 0xa186, 0x0013, 0x00c0,
+	0x6f6e, 0x6004, 0xa082, 0x0040, 0x0079, 0x6ff6, 0xa186, 0x0027,
+	0x00c0, 0x6f8d, 0x1078, 0x578f, 0x1078, 0x24bf, 0x0d7e, 0x6110,
+	0x2168, 0x1078, 0x77ed, 0x0040, 0x6f87, 0x6837, 0x0103, 0x684b,
+	0x0029, 0x6847, 0x0000, 0x1078, 0x4376, 0x1078, 0x799b, 0x0d7f,
+	0x1078, 0x690e, 0x1078, 0x5888, 0x007c, 0xa186, 0x0014, 0x00c0,
+	0x6f96, 0x6004, 0xa082, 0x0040, 0x0079, 0x6fbe, 0xa186, 0x0046,
+	0x0040, 0x6fa2, 0xa186, 0x0045, 0x0040, 0x6fa2, 0xa186, 0x0047,
+	0x10c0, 0x12d2, 0x2001, 0x0109, 0x2004, 0xd084, 0x0040, 0x6fbb,
+	0x127e, 0x2091, 0x2200, 0x007e, 0x017e, 0x027e, 0x1078, 0x5273,
+	0x027f, 0x017f, 0x007f, 0x127f, 0x6000, 0xa086, 0x0002, 0x00c0,
+	0x6fbb, 0x0078, 0x7020, 0x1078, 0x6950, 0x007c, 0x6fd3, 0x6fd1,
+	0x6fd1, 0x6fd1, 0x6fd1, 0x6fd1, 0x6fd1, 0x6fd1, 0x6fd1, 0x6fd1,
+	0x6fd1, 0x6fef, 0x6fef, 0x6fef, 0x6fef, 0x6fd1, 0x6fd1, 0x6fd1,
+	0x6fef, 0x1078, 0x12d2, 0x1078, 0x578f, 0x0d7e, 0x6110, 0x2168,
+	0x1078, 0x77ed, 0x0040, 0x6fe9, 0x6837, 0x0103, 0x684b, 0x0006,
+	0x6847, 0x0000, 0x6850, 0xc0ec, 0x6852, 0x1078, 0x4376, 0x1078,
+	0x799b, 0x0d7f, 0x1078, 0x690e, 0x1078, 0x5888, 0x007c, 0x1078,
+	0x578f, 0x1078, 0x690e, 0x1078, 0x5888, 0x007c, 0x700b, 0x7009,
+	0x7009, 0x7009, 0x7009, 0x7009, 0x7009, 0x7009, 0x7009, 0x7009,
+	0x7009, 0x7019, 0x7019, 0x7019, 0x7019, 0x7009, 0x7009, 0x7009,
+	0x7019, 0x1078, 0x12d2, 0x1078, 0x578f, 0x6003, 0x0002, 0x1078,
+	0x5888, 0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a,
+	0x007c, 0x1078, 0x578f, 0x6003, 0x000f, 0x1078, 0x5888, 0x007c,
+	0xa182, 0x0040, 0x0079, 0x7024, 0x7037, 0x7037, 0x7037, 0x7037,
+	0x7037, 0x7039, 0x70cf, 0x70ef, 0x7037, 0x7037, 0x7037, 0x7037,
+	0x7037, 0x7037, 0x7037, 0x7037, 0x7037, 0x7037, 0x7037, 0x1078,
+	0x12d2, 0x0e7e, 0x0d7e, 0x2071, 0x8d8c, 0x6110, 0x2168, 0x7614,
+	0xa6b4, 0x0fff, 0x86ff, 0x0040, 0x70b3, 0xa68c, 0x0c00, 0x0040,
+	0x704d, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186,
+	0x0002, 0x0040, 0x706b, 0xa186, 0x0028, 0x00c0, 0x705d, 0x1078,
+	0x79af, 0x684b, 0x001c, 0x0078, 0x706d, 0xd6dc, 0x0040, 0x7064,
+	0x684b, 0x0015, 0x0078, 0x706d, 0xd6d4, 0x0040, 0x706b, 0x684b,
+	0x0007, 0x0078, 0x706d, 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46,
+	0xa01e, 0xd6c4, 0x0040, 0x708d, 0xa686, 0x0100, 0x00c0, 0x7081,
+	0x2001, 0x8d99, 0x2004, 0xa005, 0x00c0, 0x7081, 0xc6c4, 0x0078,
+	0x7042, 0x7328, 0x732c, 0x6b56, 0x037e, 0x2308, 0x2019, 0x8d98,
+	0xad90, 0x0019, 0x1078, 0x7589, 0x037f, 0xd6cc, 0x0040, 0x70c3,
+	0x7124, 0x695a, 0xa192, 0x0021, 0x00c8, 0x70a1, 0x2071, 0x8d98,
+	0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x1078, 0x7589, 0x0078,
+	0x70c3, 0x6838, 0xd0fc, 0x0040, 0x70aa, 0x2009, 0x0020, 0x695a,
+	0x0078, 0x7096, 0x0f7e, 0x2d78, 0x1078, 0x7521, 0x0f7f, 0x1078,
+	0x7576, 0x0078, 0x70c5, 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46,
+	0x684c, 0xd0ac, 0x0040, 0x70c3, 0x6810, 0x6914, 0xa115, 0x0040,
+	0x70c3, 0x1078, 0x7248, 0x1078, 0x4376, 0x6218, 0x2268, 0x6a3c,
+	0x8211, 0x6a3e, 0x0d7f, 0x0e7f, 0x1078, 0x690e, 0x007c, 0x0f7e,
+	0x6003, 0x0003, 0x2079, 0x8d8c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08,
+	0x6010, 0x2078, 0x784c, 0xd0ac, 0x0040, 0x70e2, 0x6003, 0x0002,
+	0x0f7f, 0x007c, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x0f7f, 0x2c10,
+	0x1078, 0x1b07, 0x1078, 0x5405, 0x1078, 0x5948, 0x007c, 0x6003,
+	0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078,
+	0x1594, 0x007c, 0xa182, 0x0040, 0x0079, 0x70fe, 0x7111, 0x7111,
+	0x7111, 0x7111, 0x7111, 0x7113, 0x71aa, 0x7111, 0x7111, 0x71c0,
+	0x7222, 0x7111, 0x7111, 0x7111, 0x7111, 0x722d, 0x7111, 0x7111,
+	0x7111, 0x1078, 0x12d2, 0x077e, 0x0f7e, 0x0e7e, 0x0d7e, 0x2071,
+	0x8d8c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x7e46, 0x7f4c,
+	0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x86ff,
+	0x0040, 0x71a5, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0040, 0x7134,
+	0x7018, 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, 0x0040, 0x71a5,
+	0x1078, 0x132b, 0x1040, 0x12d2, 0x2d00, 0x784a, 0x7f4c, 0xc7cd,
+	0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, 0x783c, 0x683e, 0x7840,
+	0x6842, 0x6e46, 0xa68c, 0x0c00, 0x0040, 0x7152, 0x7318, 0x6b62,
+	0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0040, 0x716e,
+	0xa186, 0x0028, 0x00c0, 0x7160, 0x684b, 0x001c, 0x0078, 0x7170,
+	0xd6dc, 0x0040, 0x7167, 0x684b, 0x0015, 0x0078, 0x7170, 0xd6d4,
+	0x0040, 0x716e, 0x684b, 0x0007, 0x0078, 0x7170, 0x684b, 0x0000,
+	0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, 0xa01e, 0xd6c4, 0x0040,
+	0x7185, 0x7328, 0x732c, 0x6b56, 0x037e, 0x2308, 0x2019, 0x8d98,
+	0xad90, 0x0019, 0x1078, 0x7589, 0x037f, 0xd6cc, 0x0040, 0x71a5,
+	0x7124, 0x695a, 0xa192, 0x0021, 0x00c8, 0x7199, 0x2071, 0x8d98,
+	0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x1078, 0x7589, 0x0078,
+	0x71a5, 0x7838, 0xd0fc, 0x0040, 0x71a2, 0x2009, 0x0020, 0x695a,
+	0x0078, 0x718e, 0x2d78, 0x1078, 0x7521, 0x0d7f, 0x0e7f, 0x0f7f,
+	0x077f, 0x007c, 0x0f7e, 0x6003, 0x0003, 0x2079, 0x8d8c, 0x7c04,
+	0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x7c12, 0x7b16, 0x7e0a,
+	0x7d0e, 0x0f7f, 0x2c10, 0x1078, 0x1b07, 0x1078, 0x6217, 0x007c,
+	0x0d7e, 0x6003, 0x0002, 0x1078, 0x5837, 0x1078, 0x5948, 0x6110,
+	0x2168, 0x694c, 0xd1e4, 0x0040, 0x7220, 0xd1cc, 0x0040, 0x71fb,
+	0x6948, 0x6838, 0xd0fc, 0x0040, 0x71f3, 0x017e, 0x684c, 0x007e,
+	0x6850, 0x007e, 0xad90, 0x000d, 0xa198, 0x000d, 0x2009, 0x0020,
+	0x157e, 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, 0x00f0, 0x71e2,
+	0x157f, 0x007f, 0x6852, 0x007f, 0x684e, 0x017f, 0x2168, 0x1078,
+	0x1354, 0x0078, 0x721e, 0x017e, 0x1078, 0x1354, 0x0d7f, 0x1078,
+	0x7576, 0x0078, 0x721e, 0x6837, 0x0103, 0x6944, 0xa184, 0x00ff,
+	0xa0b6, 0x0002, 0x0040, 0x721a, 0xa086, 0x0028, 0x00c0, 0x720c,
+	0x684b, 0x001c, 0x0078, 0x721c, 0xd1dc, 0x0040, 0x7213, 0x684b,
+	0x0015, 0x0078, 0x721c, 0xd1d4, 0x0040, 0x721a, 0x684b, 0x0007,
+	0x0078, 0x721c, 0x684b, 0x0000, 0x1078, 0x4376, 0x1078, 0x690e,
+	0x0d7f, 0x007c, 0x2019, 0x0001, 0x1078, 0x642d, 0x6003, 0x0002,
+	0x1078, 0x5837, 0x1078, 0x5948, 0x007c, 0x1078, 0x5837, 0x1078,
+	0x24bf, 0x0d7e, 0x6110, 0x2168, 0x1078, 0x77ed, 0x0040, 0x7242,
+	0x6837, 0x0103, 0x684b, 0x0029, 0x6847, 0x0000, 0x1078, 0x4376,
+	0x1078, 0x799b, 0x0d7f, 0x1078, 0x690e, 0x1078, 0x5948, 0x007c,
+	0x684b, 0x0015, 0xd1fc, 0x0040, 0x7254, 0x684b, 0x0007, 0x8002,
+	0x8000, 0x810a, 0xa189, 0x0000, 0x6962, 0x685e, 0x007c, 0xa182,
+	0x0040, 0x0079, 0x725b, 0x726e, 0x726e, 0x726e, 0x726e, 0x726e,
+	0x7270, 0x726e, 0x7324, 0x732c, 0x726e, 0x726e, 0x726e, 0x726e,
+	0x726e, 0x726e, 0x726e, 0x726e, 0x726e, 0x726e, 0x1078, 0x12d2,
+	0x077e, 0x0f7e, 0x0e7e, 0x0d7e, 0x2071, 0x8d8c, 0x6110, 0x2178,
+	0x7614, 0xa6b4, 0x0fff, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218,
+	0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x86ff, 0x0040, 0x7314, 0xa694,
+	0xff00, 0xa284, 0x0c00, 0x0040, 0x7291, 0x7018, 0x7862, 0x701c,
+	0x785e, 0xa284, 0x0300, 0x0040, 0x7311, 0xa686, 0x0100, 0x00c0,
+	0x72a3, 0x2001, 0x8d99, 0x2004, 0xa005, 0x00c0, 0x72a3, 0xc6c4,
+	0x7e46, 0x0078, 0x7284, 0x1078, 0x132b, 0x1040, 0x12d2, 0x2d00,
+	0x784a, 0x7f4c, 0xa7bd, 0x0200, 0x7f4e, 0x6837, 0x0103, 0x7838,
+	0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00,
+	0x0040, 0x72be, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff,
+	0xa186, 0x0002, 0x0040, 0x72da, 0xa186, 0x0028, 0x00c0, 0x72cc,
+	0x684b, 0x001c, 0x0078, 0x72dc, 0xd6dc, 0x0040, 0x72d3, 0x684b,
+	0x0015, 0x0078, 0x72dc, 0xd6d4, 0x0040, 0x72da, 0x684b, 0x0007,
+	0x0078, 0x72dc, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854,
+	0x6856, 0xa01e, 0xd6c4, 0x0040, 0x72f1, 0x7328, 0x732c, 0x6b56,
+	0x037e, 0x2308, 0x2019, 0x8d98, 0xad90, 0x0019, 0x1078, 0x7589,
+	0x037f, 0xd6cc, 0x0040, 0x7311, 0x7124, 0x695a, 0xa192, 0x0021,
+	0x00c8, 0x7305, 0x2071, 0x8d98, 0x831c, 0x2300, 0xae18, 0xad90,
+	0x001d, 0x1078, 0x7589, 0x0078, 0x7311, 0x7838, 0xd0fc, 0x0040,
+	0x730e, 0x2009, 0x0020, 0x695a, 0x0078, 0x72fa, 0x2d78, 0x1078,
+	0x7521, 0xd6dc, 0x00c0, 0x7317, 0xa006, 0x0078, 0x731d, 0x2001,
+	0x0001, 0x2071, 0x8d8c, 0x7218, 0x731c, 0x1078, 0x15e5, 0x0d7f,
+	0x0e7f, 0x0f7f, 0x077f, 0x007c, 0x20e1, 0x0005, 0x3d18, 0x3e20,
+	0x2c10, 0x1078, 0x1594, 0x007c, 0x0d7e, 0x6003, 0x0002, 0x6110,
+	0x2168, 0x694c, 0xd1e4, 0x0040, 0x73c5, 0xd1cc, 0x0040, 0x7395,
+	0x6948, 0x6838, 0xd0fc, 0x0040, 0x7371, 0x017e, 0x684c, 0x007e,
+	0x6850, 0x007e, 0x684c, 0xd0ac, 0x0040, 0x7357, 0x6810, 0x6914,
+	0xa115, 0x0040, 0x7357, 0x1078, 0x7248, 0x0f7e, 0x6948, 0x2178,
+	0x6848, 0x784a, 0x6860, 0x7862, 0x685c, 0x785e, 0x0f7f, 0x6948,
+	0xad90, 0x000d, 0xa198, 0x000d, 0x2009, 0x0020, 0x157e, 0x21a8,
+	0x2304, 0x2012, 0x8318, 0x8210, 0x00f0, 0x7360, 0x157f, 0x007f,
+	0x6852, 0x007f, 0x684e, 0x017f, 0x2168, 0x1078, 0x1354, 0x0078,
+	0x73c3, 0x017e, 0x684c, 0xd0ac, 0x0040, 0x7389, 0x6810, 0x6914,
+	0xa115, 0x0040, 0x7389, 0x1078, 0x7248, 0x0f7e, 0x6948, 0x2178,
+	0x6848, 0x784a, 0x6860, 0x7862, 0x685c, 0x785e, 0x684c, 0x784e,
+	0x0f7f, 0x6948, 0xa188, 0x0013, 0x684c, 0x200a, 0x1078, 0x1354,
+	0x0d7f, 0x1078, 0x7576, 0x0078, 0x73c3, 0x6837, 0x0103, 0x6944,
+	0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0040, 0x73b4, 0xa086, 0x0028,
+	0x00c0, 0x73a6, 0x684b, 0x001c, 0x0078, 0x73c1, 0xd1dc, 0x0040,
+	0x73ad, 0x684b, 0x0015, 0x0078, 0x73c1, 0xd1d4, 0x0040, 0x73b4,
+	0x684b, 0x0007, 0x0078, 0x73c1, 0x684b, 0x0000, 0x684c, 0xd0ac,
+	0x0040, 0x73c1, 0x6810, 0x6914, 0xa115, 0x0040, 0x73c1, 0x1078,
+	0x7248, 0x1078, 0x4376, 0x1078, 0x690e, 0x0d7f, 0x007c, 0x1078,
+	0x578f, 0x0078, 0x73cd, 0x1078, 0x5837, 0x1078, 0x77ed, 0x0040,
+	0x73e6, 0x0d7e, 0x6110, 0x2168, 0x6837, 0x0103, 0x2009, 0x880c,
+	0x210c, 0xd18c, 0x00c0, 0x73f1, 0xd184, 0x00c0, 0x73ed, 0x6108,
+	0x694a, 0x6847, 0x0000, 0x1078, 0x4376, 0x0d7f, 0x1078, 0x690e,
+	0x1078, 0x5888, 0x1078, 0x5948, 0x007c, 0x684b, 0x0004, 0x0078,
+	0x73e1, 0x684b, 0x0004, 0x0078, 0x73e1, 0xa182, 0x0040, 0x0079,
+	0x73f9, 0x740c, 0x740c, 0x740c, 0x740c, 0x740c, 0x740e, 0x740c,
+	0x7411, 0x740c, 0x740c, 0x740c, 0x740c, 0x740c, 0x740c, 0x740c,
+	0x740c, 0x740c, 0x740c, 0x740c, 0x1078, 0x12d2, 0x1078, 0x690e,
+	0x007c, 0x007e, 0x027e, 0xa016, 0x1078, 0x1594, 0x027f, 0x007f,
+	0x007c, 0xa182, 0x0085, 0x0079, 0x741d, 0x7426, 0x7424, 0x7424,
+	0x7424, 0x7424, 0x7424, 0x7424, 0x1078, 0x12d2, 0x6003, 0x000b,
+	0x6106, 0x1078, 0x5399, 0x127e, 0x2091, 0x8000, 0x1078, 0x5888,
+	0x127f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x743c, 0x6004, 0xa082,
+	0x0085, 0x2008, 0x0079, 0x7477, 0xa186, 0x0027, 0x00c0, 0x745f,
+	0x1078, 0x578f, 0x1078, 0x24bf, 0x0d7e, 0x6010, 0x2068, 0x1078,
+	0x77ed, 0x0040, 0x7455, 0x6837, 0x0103, 0x6847, 0x0000, 0x684b,
+	0x0029, 0x1078, 0x4376, 0x1078, 0x799b, 0x0d7f, 0x1078, 0x690e,
+	0x1078, 0x5888, 0x007c, 0x1078, 0x6950, 0x0078, 0x745a, 0xa186,
+	0x0014, 0x00c0, 0x745b, 0x1078, 0x578f, 0x0d7e, 0x6010, 0x2068,
+	0x1078, 0x77ed, 0x0040, 0x7455, 0x6837, 0x0103, 0x6847, 0x0000,
+	0x684b, 0x0006, 0x6850, 0xc0ec, 0x6852, 0x0078, 0x7451, 0x7480,
+	0x747e, 0x747e, 0x747e, 0x747e, 0x747e, 0x7489, 0x1078, 0x12d2,
+	0x1078, 0x578f, 0x6017, 0x0014, 0x6003, 0x000c, 0x1078, 0x5888,
+	0x007c, 0x1078, 0x578f, 0x6017, 0x0014, 0x6003, 0x000e, 0x1078,
+	0x5888, 0x007c, 0xa182, 0x008c, 0x00c8, 0x749c, 0xa182, 0x0085,
+	0x0048, 0x749c, 0x0079, 0x749f, 0x1078, 0x6950, 0x007c, 0x74a6,
+	0x74a6, 0x74a6, 0x74a6, 0x74a8, 0x74d0, 0x74a6, 0x1078, 0x12d2,
+	0x0d7e, 0x1078, 0x799b, 0x1078, 0x77ed, 0x0040, 0x74cc, 0x6010,
+	0x2068, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0040, 0x74bd, 0x684b,
+	0x0006, 0xc0ec, 0x6852, 0x0078, 0x74c8, 0xd0bc, 0x0040, 0x74c4,
+	0x684b, 0x0002, 0x0078, 0x74c8, 0x684b, 0x0005, 0x1078, 0x7a4e,
+	0x6847, 0x0000, 0x1078, 0x4376, 0x1078, 0x690e, 0x0d7f, 0x007c,
+	0x0d7e, 0x6010, 0x2068, 0x1078, 0x77ed, 0x0040, 0x74f4, 0x6837,
+	0x0103, 0x6850, 0xd0b4, 0x0040, 0x74e3, 0xc0ec, 0x6852, 0x684b,
+	0x0006, 0x0078, 0x74ee, 0xd0bc, 0x0040, 0x74ea, 0x684b, 0x0002,
+	0x0078, 0x74ee, 0x684b, 0x0005, 0x1078, 0x7a4e, 0x6847, 0x0000,
+	0x1078, 0x4376, 0x1078, 0x799b, 0x0d7f, 0x1078, 0x690e, 0x007c,
+	0x017e, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x77ed, 0x0040, 0x7508,
+	0x6837, 0x0103, 0x684b, 0x0028, 0x6847, 0x0000, 0x1078, 0x4376,
+	0x0d7f, 0x017f, 0xa186, 0x0013, 0x0040, 0x751a, 0xa186, 0x0014,
+	0x0040, 0x751a, 0xa186, 0x0027, 0x0040, 0x751a, 0x1078, 0x6950,
+	0x0078, 0x7520, 0x1078, 0x578f, 0x1078, 0x79a8, 0x1078, 0x5888,
 	0x007c, 0x057e, 0x067e, 0x0d7e, 0x0f7e, 0x2029, 0x0001, 0xa182,
-	0x0101, 0x00c8, 0x67e5, 0x0078, 0x67e7, 0x2009, 0x0100, 0x2130,
-	0x2069, 0x7c98, 0x831c, 0x2300, 0xad18, 0x2009, 0x0020, 0xaf90,
-	0x001d, 0x1078, 0x6841, 0xa6b2, 0x0020, 0x7804, 0xa06d, 0x0040,
-	0x67fb, 0x1078, 0x1350, 0x1078, 0x1327, 0x0040, 0x6825, 0x8528,
+	0x0101, 0x00c8, 0x752d, 0x0078, 0x752f, 0x2009, 0x0100, 0x2130,
+	0x2069, 0x8d98, 0x831c, 0x2300, 0xad18, 0x2009, 0x0020, 0xaf90,
+	0x001d, 0x1078, 0x7589, 0xa6b2, 0x0020, 0x7804, 0xa06d, 0x0040,
+	0x7543, 0x1078, 0x1354, 0x1078, 0x132b, 0x0040, 0x756d, 0x8528,
 	0x6837, 0x0110, 0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a, 0x003d,
-	0x00c8, 0x6811, 0x2608, 0xad90, 0x000f, 0x1078, 0x6841, 0x0078,
-	0x6825, 0xa6b2, 0x003c, 0x2009, 0x003c, 0x2d78, 0xad90, 0x000f,
-	0x1078, 0x6841, 0x0078, 0x67fb, 0x0f7f, 0x852f, 0xa5ad, 0x0003,
-	0x7d36, 0xa5ac, 0x0000, 0x0078, 0x682a, 0x0f7f, 0x852f, 0xa5ad,
+	0x00c8, 0x7559, 0x2608, 0xad90, 0x000f, 0x1078, 0x7589, 0x0078,
+	0x756d, 0xa6b2, 0x003c, 0x2009, 0x003c, 0x2d78, 0xad90, 0x000f,
+	0x1078, 0x7589, 0x0078, 0x7543, 0x0f7f, 0x852f, 0xa5ad, 0x0003,
+	0x7d36, 0xa5ac, 0x0000, 0x0078, 0x7572, 0x0f7f, 0x852f, 0xa5ad,
 	0x0003, 0x7d36, 0x0d7f, 0x067f, 0x057f, 0x007c, 0x0f7e, 0x8dff,
-	0x0040, 0x683f, 0x6804, 0xa07d, 0x0040, 0x683d, 0x6807, 0x0000,
-	0x1078, 0x3b92, 0x2f68, 0x0078, 0x6832, 0x1078, 0x3b92, 0x0f7f,
-	0x007c, 0x157e, 0xa184, 0x0001, 0x0040, 0x6847, 0x8108, 0x810c,
-	0x21a8, 0x2304, 0x8007, 0x2012, 0x8318, 0x8210, 0x00f0, 0x6849,
+	0x0040, 0x7587, 0x6804, 0xa07d, 0x0040, 0x7585, 0x6807, 0x0000,
+	0x1078, 0x4376, 0x2f68, 0x0078, 0x757a, 0x1078, 0x4376, 0x0f7f,
+	0x007c, 0x157e, 0xa184, 0x0001, 0x0040, 0x758f, 0x8108, 0x810c,
+	0x21a8, 0x2304, 0x8007, 0x2012, 0x8318, 0x8210, 0x00f0, 0x7591,
 	0x157f, 0x007c, 0x127e, 0x2091, 0x8000, 0x601c, 0xa084, 0x000f,
-	0x1079, 0x685c, 0x127f, 0x007c, 0x686b, 0x6864, 0x6866, 0x6884,
-	0x6864, 0x6866, 0x6866, 0x6866, 0x1078, 0x12cd, 0xa006, 0x007c,
-	0xa085, 0x0001, 0x007c, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x6a58,
-	0x0040, 0x6881, 0xa00e, 0x2001, 0x0005, 0x1078, 0x3c22, 0x1078,
-	0x6c5c, 0x1078, 0x3b92, 0x1078, 0x5d1a, 0xa085, 0x0001, 0x0d7f,
-	0x007c, 0xa006, 0x0078, 0x687f, 0x6000, 0xa08a, 0x0010, 0x10c8,
-	0x12cd, 0x1079, 0x688c, 0x007c, 0x689c, 0x68b9, 0x689e, 0x68ca,
-	0x68b5, 0x689c, 0x6866, 0x686b, 0x686b, 0x6866, 0x6866, 0x6866,
-	0x6866, 0x6866, 0x6866, 0x6866, 0x1078, 0x12cd, 0x0d7e, 0x6010,
-	0x2068, 0x1078, 0x6a58, 0x0040, 0x68a7, 0x1078, 0x6c5c, 0x0d7f,
-	0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x1078, 0x4941,
-	0x1078, 0x4d96, 0xa085, 0x0001, 0x007c, 0x1078, 0x166e, 0x0078,
-	0x689e, 0x0e7e, 0x2071, 0x7936, 0x7024, 0xac06, 0x00c0, 0x68c2,
-	0x1078, 0x57ee, 0x1078, 0x5725, 0x0e7f, 0x00c0, 0x689e, 0x1078,
-	0x6866, 0x007c, 0x037e, 0x0e7e, 0x2071, 0x7936, 0x703c, 0xac06,
-	0x00c0, 0x68da, 0x2019, 0x0000, 0x1078, 0x5880, 0x0e7f, 0x037f,
-	0x0078, 0x689e, 0x1078, 0x5b5c, 0x0e7f, 0x037f, 0x00c0, 0x689e,
-	0x1078, 0x6866, 0x007c, 0x0c7e, 0x601c, 0xa084, 0x000f, 0x1079,
-	0x68eb, 0x0c7f, 0x007c, 0x68fa, 0x6957, 0x69fc, 0x68fe, 0x68fa,
-	0x68fa, 0x72dd, 0x5d1a, 0x6957, 0x1078, 0x6be3, 0x00c0, 0x68fa,
-	0x1078, 0x5f6d, 0x007c, 0x6017, 0x0001, 0x007c, 0x6000, 0xa08a,
-	0x0010, 0x10c8, 0x12cd, 0x1079, 0x6906, 0x007c, 0x6916, 0x6918,
-	0x6938, 0x694a, 0x694a, 0x6916, 0x68fa, 0x68fa, 0x68fa, 0x694a,
-	0x694a, 0x6916, 0x6916, 0x6916, 0x6916, 0x6954, 0x1078, 0x12cd,
-	0x0e7e, 0x6010, 0x2070, 0x7050, 0xc0b5, 0x7052, 0x2071, 0x7936,
-	0x7024, 0xac06, 0x0040, 0x6934, 0x1078, 0x5725, 0x6007, 0x0085,
-	0x6003, 0x000b, 0x601f, 0x0002, 0x6017, 0x0014, 0x1078, 0x4941,
-	0x1078, 0x4d96, 0x0e7f, 0x007c, 0x6017, 0x0001, 0x0078, 0x6932,
-	0x0d7e, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, 0x0d7f, 0x6007,
-	0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x1078, 0x4941, 0x1078,
-	0x4d96, 0x007c, 0x0d7e, 0x6017, 0x0001, 0x6010, 0x2068, 0x6850,
-	0xc0b5, 0x6852, 0x0d7f, 0x007c, 0x1078, 0x5d1a, 0x007c, 0x6000,
-	0xa08a, 0x0010, 0x10c8, 0x12cd, 0x1079, 0x695f, 0x007c, 0x696f,
-	0x68fb, 0x6971, 0x696f, 0x6971, 0x696f, 0x696f, 0x696f, 0x68f4,
-	0x68f4, 0x696f, 0x696f, 0x696f, 0x696f, 0x696f, 0x696f, 0x1078,
-	0x12cd, 0x0d7e, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x0d7f,
-	0xa08a, 0x000c, 0x10c8, 0x12cd, 0x1079, 0x697f, 0x007c, 0x698b,
-	0x69aa, 0x698b, 0x69aa, 0x698b, 0x69aa, 0x698d, 0x6996, 0x698b,
-	0x69aa, 0x698b, 0x69a3, 0x1078, 0x12cd, 0x6004, 0xa08e, 0x0004,
-	0x0040, 0x69a5, 0xa08e, 0x0002, 0x0040, 0x69a5, 0x6004, 0x1078,
-	0x6be3, 0x0040, 0x69f4, 0xa08e, 0x0021, 0x0040, 0x69f8, 0xa08e,
-	0x0022, 0x0040, 0x69f4, 0x1078, 0x22b5, 0x1078, 0x5f6d, 0x1078,
-	0x5d1a, 0x007c, 0x0c7e, 0x0d7e, 0x6104, 0xa186, 0x0016, 0x0040,
-	0x69e4, 0xa186, 0x0002, 0x00c0, 0x69d3, 0x6018, 0x2068, 0x68a0,
-	0xd0bc, 0x00c0, 0x69d3, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0040,
-	0x69d3, 0x8001, 0x6842, 0x6013, 0x0000, 0x601f, 0x0007, 0x6017,
-	0x0398, 0x1078, 0x5cb4, 0x0040, 0x69d3, 0x2d00, 0x601a, 0x601f,
-	0x0001, 0x0078, 0x69e4, 0x0d7f, 0x0c7f, 0x1078, 0x5f6d, 0x1078,
-	0x22b5, 0x0e7e, 0x127e, 0x2091, 0x8000, 0x1078, 0x22d7, 0x127f,
-	0x0e7f, 0x1078, 0x5d1a, 0x007c, 0x2001, 0x0002, 0x1078, 0x37f4,
-	0x6003, 0x0001, 0x6007, 0x0002, 0x1078, 0x498e, 0x1078, 0x4d96,
-	0x0d7f, 0x0c7f, 0x0078, 0x69e3, 0x1078, 0x5f6d, 0x0078, 0x69a7,
-	0x1078, 0x5f7c, 0x0078, 0x69a7, 0x6000, 0xa08a, 0x0010, 0x10c8,
-	0x12cd, 0x1079, 0x6a04, 0x007c, 0x6a14, 0x6a14, 0x6a14, 0x6a14,
-	0x6a14, 0x6a14, 0x6a14, 0x6a14, 0x6a14, 0x68fa, 0x6a14, 0x68fb,
-	0x6a16, 0x68fb, 0x6a1f, 0x6a14, 0x1078, 0x12cd, 0x6007, 0x008b,
-	0x6003, 0x000d, 0x1078, 0x4941, 0x1078, 0x4d96, 0x007c, 0x1078,
-	0x6ba9, 0x1078, 0x6a58, 0x0040, 0x6a41, 0x1078, 0x22b5, 0x0d7e,
-	0x1078, 0x6a58, 0x0040, 0x6a34, 0x6010, 0x2068, 0x6837, 0x0103,
-	0x684b, 0x0006, 0x1078, 0x3b92, 0x0d7f, 0x601f, 0x0001, 0x6007,
-	0x0001, 0x6003, 0x0001, 0x1078, 0x498e, 0x1078, 0x4d96, 0x0078,
-	0x6a43, 0x1078, 0x5d1a, 0x007c, 0xa284, 0x0007, 0x00c0, 0x6a55,
-	0xa282, 0x7e00, 0x0048, 0x6a55, 0x2001, 0x7715, 0x2004, 0xa202,
-	0x00c8, 0x6a55, 0xa085, 0x0001, 0x007c, 0xa006, 0x0078, 0x6a54,
-	0x027e, 0x0e7e, 0x2071, 0x7700, 0x6210, 0x7058, 0xa202, 0x0048,
-	0x6a6a, 0x705c, 0xa202, 0x00c8, 0x6a6a, 0xa085, 0x0001, 0x0e7f,
-	0x027f, 0x007c, 0xa006, 0x0078, 0x6a67, 0x0e7e, 0x0c7e, 0x037e,
-	0x007e, 0x127e, 0x2091, 0x8000, 0x2061, 0x7e00, 0x2071, 0x7700,
-	0x7344, 0x7060, 0xa302, 0x00c8, 0x6a93, 0x601c, 0xa206, 0x00c0,
-	0x6a8b, 0x1078, 0x6be3, 0x00c0, 0x6a87, 0x1078, 0x5f6d, 0x0c7e,
-	0x1078, 0x5d1a, 0x0c7f, 0xace0, 0x0008, 0x7054, 0xac02, 0x00c8,
-	0x6a93, 0x0078, 0x6a78, 0x127f, 0x007f, 0x037f, 0x0c7f, 0x0e7f,
-	0x007c, 0x0e7e, 0x0c7e, 0x017e, 0xa188, 0x7820, 0x210c, 0x81ff,
-	0x0040, 0x6ab1, 0x2061, 0x7e00, 0x2071, 0x7700, 0x017e, 0x1078,
-	0x5cb4, 0x017f, 0x0040, 0x6ab4, 0x611a, 0x1078, 0x22b5, 0x1078,
-	0x5d1a, 0xa006, 0x0078, 0x6ab6, 0xa085, 0x0001, 0x017f, 0x0c7f,
-	0x0e7f, 0x007c, 0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000, 0x0c7e,
-	0x1078, 0x5cb4, 0x057f, 0x0040, 0x6ad3, 0x6612, 0x651a, 0x601f,
-	0x0003, 0x2009, 0x004b, 0x1078, 0x5d41, 0xa085, 0x0001, 0x127f,
-	0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x6acf, 0x0c7e, 0x057e,
-	0x127e, 0x2091, 0x8000, 0x62a0, 0x0c7e, 0x1078, 0x5cb4, 0x057f,
-	0x0040, 0x6afd, 0x6013, 0x0000, 0x651a, 0x601f, 0x0003, 0x0c7e,
-	0x2560, 0x1078, 0x3a36, 0x0c7f, 0x1078, 0x4a7e, 0x1078, 0x49c1,
-	0x2c08, 0x1078, 0x747b, 0x2009, 0x004c, 0x1078, 0x5d41, 0xa085,
-	0x0001, 0x127f, 0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x6af9,
-	0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000, 0x62a0, 0x0c7e, 0x1078,
-	0x5cb4, 0x057f, 0x0040, 0x6b28, 0x6612, 0x651a, 0x601f, 0x0003,
-	0x2019, 0x0005, 0x0c7e, 0x2560, 0x1078, 0x3a36, 0x0c7f, 0x1078,
-	0x4a7e, 0x1078, 0x49c1, 0x2c08, 0x1078, 0x747b, 0x2009, 0x004d,
-	0x1078, 0x5d41, 0xa085, 0x0001, 0x127f, 0x057f, 0x0c7f, 0x007c,
-	0xa006, 0x0078, 0x6b24, 0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000,
-	0x62a0, 0x0c7e, 0x1078, 0x5cb4, 0x057f, 0x0040, 0x6b53, 0x6612,
-	0x651a, 0x601f, 0x0003, 0x2019, 0x0005, 0x0c7e, 0x2560, 0x1078,
-	0x3a36, 0x0c7f, 0x1078, 0x4a7e, 0x1078, 0x49c1, 0x2c08, 0x1078,
-	0x747b, 0x2009, 0x004e, 0x1078, 0x5d41, 0xa085, 0x0001, 0x127f,
-	0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x6b4f, 0x0c7e, 0x127e,
-	0x2091, 0x8000, 0x0c7e, 0x1078, 0x5cb4, 0x017f, 0x0040, 0x6b6f,
-	0x660a, 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x001f,
-	0x1078, 0x5d41, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006,
-	0x0078, 0x6b6c, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078,
-	0x5cb4, 0x017f, 0x0040, 0x6b8b, 0x660a, 0x611a, 0x601f, 0x0008,
-	0x2d00, 0x6012, 0x2009, 0x0021, 0x1078, 0x5d41, 0xa085, 0x0001,
-	0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x6b88, 0x0c7e, 0x127e,
-	0x2091, 0x8000, 0x0c7e, 0x1078, 0x5cb4, 0x017f, 0x0040, 0x6ba6,
-	0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0000, 0x1078,
-	0x5d41, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078,
-	0x6ba3, 0x027e, 0x0d7e, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0040,
-	0x6bb3, 0x8211, 0x6a3e, 0x0d7f, 0x027f, 0x007c, 0x6013, 0x0000,
-	0x601f, 0x0007, 0x6017, 0x0014, 0x007c, 0x067e, 0x0c7e, 0x0d7e,
-	0x2031, 0x7752, 0x2634, 0xd6e4, 0x0040, 0x6bcb, 0x6618, 0x2660,
-	0x6e48, 0x1078, 0x3942, 0x0d7f, 0x0c7f, 0x067f, 0x007c, 0x007e,
-	0x017e, 0x6004, 0xa08e, 0x0002, 0x0040, 0x6be0, 0xa08e, 0x0003,
-	0x0040, 0x6be0, 0xa08e, 0x0004, 0x0040, 0x6be0, 0xa085, 0x0001,
-	0x017f, 0x007f, 0x007c, 0x007e, 0x017e, 0x6004, 0xa08e, 0x0000,
-	0x0040, 0x6bf8, 0xa08e, 0x001f, 0x0040, 0x6bf8, 0xa08e, 0x0028,
-	0x0040, 0x6bf8, 0xa08e, 0x0029, 0x0040, 0x6bf8, 0xa085, 0x0001,
-	0x017f, 0x007f, 0x007c, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e,
-	0x1078, 0x5cb4, 0x017f, 0x0040, 0x6c15, 0x611a, 0x601f, 0x0001,
-	0x2d00, 0x6012, 0x1078, 0x22b5, 0x2009, 0x0028, 0x1078, 0x5d41,
-	0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x6c12,
-	0xa186, 0x0015, 0x00c0, 0x6c2d, 0x2011, 0x771e, 0x2204, 0xa086,
-	0x0074, 0x00c0, 0x6c2d, 0x1078, 0x61ea, 0x6003, 0x0001, 0x6007,
-	0x0029, 0x1078, 0x498e, 0x0078, 0x6c31, 0x1078, 0x5f6d, 0x1078,
-	0x5d1a, 0x007c, 0xa186, 0x0015, 0x00c0, 0x6c4f, 0x2011, 0x771e,
-	0x2204, 0xa086, 0x0014, 0x00c0, 0x6c4f, 0x0d7e, 0x6018, 0x2068,
-	0x1078, 0x38c8, 0x0d7f, 0x1078, 0x61f4, 0x00c0, 0x6c4f, 0x2001,
-	0x0006, 0x1078, 0x37f4, 0x1078, 0x5dc5, 0x0078, 0x6c53, 0x1078,
-	0x5f6d, 0x1078, 0x5d1a, 0x007c, 0x6848, 0xa086, 0x0005, 0x00c0,
-	0x6c5b, 0x1078, 0x6c5c, 0x007c, 0x6850, 0xc0ad, 0x6852, 0x007c,
-	0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12cd, 0x1079, 0x6c6a,
-	0x067f, 0x007c, 0x6c7a, 0x6e51, 0x6f32, 0x6c7a, 0x6c7a, 0x6c7a,
-	0x6c7a, 0x6c7a, 0x6cb4, 0x6fa0, 0x6c7a, 0x6c7a, 0x6c7a, 0x6c7a,
-	0x6c7a, 0x6c7a, 0x1078, 0x12cd, 0x067e, 0x6000, 0xa0b2, 0x0010,
-	0x10c8, 0x12cd, 0x1079, 0x6c86, 0x067f, 0x007c, 0x6c96, 0x728c,
-	0x6c96, 0x6c96, 0x6c96, 0x6c96, 0x6c96, 0x6c96, 0x7267, 0x72d6,
-	0x6c96, 0x6c96, 0x6c96, 0x6c96, 0x6c96, 0x6c96, 0x1078, 0x12cd,
-	0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12cd, 0x1079, 0x6ca2,
-	0x067f, 0x007c, 0x6cb2, 0x70d8, 0x714a, 0x716c, 0x71b8, 0x6cb2,
-	0x6cb2, 0x7212, 0x6fac, 0x724f, 0x7253, 0x6cb2, 0x6cb2, 0x6cb2,
-	0x6cb2, 0x6cb2, 0x1078, 0x12cd, 0xa1b2, 0x0030, 0x10c8, 0x12cd,
-	0x2100, 0x0079, 0x6cbb, 0x6ceb, 0x6dc8, 0x6ceb, 0x6ceb, 0x6ceb,
-	0x6ceb, 0x6ceb, 0x6ceb, 0x6ceb, 0x6ceb, 0x6ceb, 0x6ceb, 0x6ceb,
-	0x6ceb, 0x6ceb, 0x6ceb, 0x6ceb, 0x6ceb, 0x6ceb, 0x6ceb, 0x6ceb,
-	0x6ceb, 0x6ceb, 0x6ced, 0x6d1c, 0x6d27, 0x6d4f, 0x6d55, 0x6d89,
-	0x6dc1, 0x6ceb, 0x6ceb, 0x6dd0, 0x6ceb, 0x6ceb, 0x6dd7, 0x6dde,
-	0x6ceb, 0x6ceb, 0x6ceb, 0x6ceb, 0x6ceb, 0x6dfb, 0x6ceb, 0x6ceb,
-	0x6e06, 0x6ceb, 0x6ceb, 0x1078, 0x12cd, 0x1078, 0x3b3e, 0x6618,
-	0x0c7e, 0x2660, 0x1078, 0x385e, 0x0c7f, 0xa6b0, 0x0001, 0x2634,
-	0xa684, 0x00ff, 0xa082, 0x0006, 0x0048, 0x6d0e, 0x1078, 0x73b7,
-	0x00c0, 0x6d49, 0x1078, 0x7355, 0x00c0, 0x6d0a, 0x6007, 0x0008,
-	0x0078, 0x6dc3, 0x6007, 0x0009, 0x0078, 0x6dc3, 0x1078, 0x754c,
-	0x0040, 0x6d18, 0x1078, 0x73b7, 0x0040, 0x6d02, 0x0078, 0x6d49,
-	0x6013, 0x1900, 0x0078, 0x6d0a, 0x6106, 0x1078, 0x7317, 0x6007,
-	0x0006, 0x0078, 0x6dc3, 0x6007, 0x0007, 0x0078, 0x6dc3, 0x0d7e,
-	0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006,
-	0x0040, 0x6d39, 0xa686, 0x0004, 0x0040, 0x6d39, 0x0d7f, 0x0078,
-	0x6d49, 0x1078, 0x7415, 0x00c0, 0x6d44, 0x1078, 0x38c8, 0x6007,
-	0x000a, 0x0d7f, 0x0078, 0x6dc3, 0x6007, 0x000b, 0x0d7f, 0x0078,
-	0x6dc3, 0x1078, 0x22b5, 0x6007, 0x0001, 0x0078, 0x6dc3, 0x1078,
-	0x22b5, 0x6007, 0x000c, 0x0078, 0x6dc3, 0x1078, 0x3b3e, 0x6618,
+	0x1079, 0x75a4, 0x127f, 0x007c, 0x75ba, 0x75ac, 0x75b5, 0x75d3,
+	0x75ac, 0x75b5, 0x75ae, 0x75b5, 0x1078, 0x12d2, 0x037e, 0x2019,
+	0x0010, 0x1078, 0x831c, 0x037f, 0x007c, 0xa006, 0x007c, 0xa085,
+	0x0001, 0x007c, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x77ed, 0x0040,
+	0x75d0, 0xa00e, 0x2001, 0x0005, 0x1078, 0x4454, 0x1078, 0x7a4e,
+	0x1078, 0x4376, 0x1078, 0x690e, 0xa085, 0x0001, 0x0d7f, 0x007c,
+	0xa006, 0x0078, 0x75ce, 0x6000, 0xa08a, 0x0010, 0x10c8, 0x12d2,
+	0x1079, 0x75db, 0x007c, 0x75eb, 0x7608, 0x75ed, 0x7619, 0x7604,
+	0x75eb, 0x75b5, 0x75ba, 0x75ba, 0x75b5, 0x75b5, 0x75b5, 0x75b5,
+	0x75b5, 0x75b5, 0x75b5, 0x1078, 0x12d2, 0x0d7e, 0x6010, 0x2068,
+	0x1078, 0x77ed, 0x0040, 0x75f6, 0x1078, 0x7a4e, 0x0d7f, 0x6007,
+	0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x1078, 0x5399, 0x1078,
+	0x5888, 0xa085, 0x0001, 0x007c, 0x1078, 0x16af, 0x0078, 0x75ed,
+	0x0e7e, 0x2071, 0x8aa2, 0x7024, 0xac06, 0x00c0, 0x7611, 0x1078,
+	0x639b, 0x1078, 0x62b2, 0x0e7f, 0x00c0, 0x75ed, 0x1078, 0x75b5,
+	0x007c, 0x037e, 0x0e7e, 0x2071, 0x8aa2, 0x703c, 0xac06, 0x00c0,
+	0x7629, 0x2019, 0x0000, 0x1078, 0x642d, 0x0e7f, 0x037f, 0x0078,
+	0x75ed, 0x1078, 0x6753, 0x0e7f, 0x037f, 0x00c0, 0x75ed, 0x1078,
+	0x75b5, 0x007c, 0x0c7e, 0x601c, 0xa084, 0x000f, 0x1079, 0x763a,
+	0x0c7f, 0x007c, 0x7649, 0x76ae, 0x777b, 0x764d, 0x7649, 0x7649,
+	0x8311, 0x690e, 0x76ae, 0x1078, 0x79d5, 0x00c0, 0x7649, 0x1078,
+	0x6bc7, 0x007c, 0x6017, 0x0001, 0x007c, 0x6010, 0xa080, 0x0019,
+	0x2c02, 0x6000, 0xa08a, 0x0010, 0x10c8, 0x12d2, 0x1079, 0x7659,
+	0x007c, 0x7669, 0x766b, 0x768b, 0x769d, 0x76aa, 0x7669, 0x7649,
+	0x7649, 0x7649, 0x769d, 0x769d, 0x7669, 0x7669, 0x7669, 0x7669,
+	0x76a7, 0x1078, 0x12d2, 0x0e7e, 0x6010, 0x2070, 0x7050, 0xc0b5,
+	0x7052, 0x2071, 0x8aa2, 0x7024, 0xac06, 0x0040, 0x7687, 0x1078,
+	0x62b2, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x6017,
+	0x0014, 0x1078, 0x5399, 0x1078, 0x5888, 0x0e7f, 0x007c, 0x6017,
+	0x0001, 0x0078, 0x7685, 0x0d7e, 0x6010, 0x2068, 0x6850, 0xc0b5,
+	0x6852, 0x0d7f, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002,
+	0x1078, 0x5399, 0x1078, 0x5888, 0x007c, 0x0d7e, 0x6017, 0x0001,
+	0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, 0x0d7f, 0x007c, 0x1078,
+	0x690e, 0x007c, 0x1078, 0x16af, 0x0078, 0x768b, 0x6000, 0xa08a,
+	0x0010, 0x10c8, 0x12d2, 0x1079, 0x76b6, 0x007c, 0x76c6, 0x764a,
+	0x76c8, 0x76c6, 0x76c8, 0x76c6, 0x76c6, 0x76c6, 0x7643, 0x7643,
+	0x76c6, 0x76c6, 0x76c6, 0x76c6, 0x76c6, 0x76c6, 0x1078, 0x12d2,
+	0x0d7e, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x0d7f, 0xa08a,
+	0x000c, 0x10c8, 0x12d2, 0x1079, 0x76d6, 0x007c, 0x76e2, 0x7714,
+	0x76e2, 0x7714, 0x76e2, 0x7714, 0x76e4, 0x76ed, 0x76e2, 0x7714,
+	0x76e2, 0x76fe, 0x1078, 0x12d2, 0x6004, 0xa08e, 0x0004, 0x0040,
+	0x770f, 0xa08e, 0x0002, 0x0040, 0x770f, 0x6004, 0x1078, 0x79d5,
+	0x0040, 0x775e, 0xa08e, 0x0021, 0x0040, 0x7762, 0xa08e, 0x0022,
+	0x0040, 0x775e, 0xa08e, 0x003d, 0x0040, 0x7762, 0xa08e, 0x0001,
+	0x00c0, 0x770d, 0x0d7e, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff,
+	0x0d7f, 0xa086, 0x0006, 0x0040, 0x770f, 0x1078, 0x24bf, 0x1078,
+	0x6bc7, 0x1078, 0x79a8, 0x007c, 0x0c7e, 0x0d7e, 0x6104, 0xa186,
+	0x0016, 0x0040, 0x774e, 0xa186, 0x0002, 0x00c0, 0x773d, 0x6018,
+	0x2068, 0x68a0, 0xd0bc, 0x00c0, 0x7766, 0x6840, 0xa084, 0x00ff,
+	0xa005, 0x0040, 0x773d, 0x8001, 0x6842, 0x6013, 0x0000, 0x601f,
+	0x0007, 0x6017, 0x0398, 0x1078, 0x68a8, 0x0040, 0x773d, 0x2d00,
+	0x601a, 0x601f, 0x0001, 0x0078, 0x774e, 0x0d7f, 0x0c7f, 0x1078,
+	0x6bc7, 0x1078, 0x24bf, 0x0e7e, 0x127e, 0x2091, 0x8000, 0x1078,
+	0x24e5, 0x127f, 0x0e7f, 0x1078, 0x79a8, 0x007c, 0x2001, 0x0002,
+	0x1078, 0x3f05, 0x6003, 0x0001, 0x6007, 0x0002, 0x1078, 0x53e6,
+	0x1078, 0x5888, 0x0d7f, 0x0c7f, 0x0078, 0x774d, 0x1078, 0x6bc7,
+	0x0078, 0x7711, 0x1078, 0x6bda, 0x0078, 0x7711, 0x0d7f, 0x0c7f,
+	0x1078, 0x6bc7, 0x1078, 0x24bf, 0x0e7e, 0x127e, 0x2091, 0x8000,
+	0x1078, 0x24e5, 0x6013, 0x0000, 0x601f, 0x0007, 0x6017, 0x0398,
+	0x127f, 0x0e7f, 0x007c, 0x6000, 0xa08a, 0x0010, 0x10c8, 0x12d2,
+	0x1079, 0x7783, 0x007c, 0x7793, 0x7793, 0x7793, 0x7793, 0x7793,
+	0x7793, 0x7793, 0x7793, 0x7793, 0x7649, 0x7793, 0x764a, 0x7795,
+	0x764a, 0x779e, 0x7793, 0x1078, 0x12d2, 0x6007, 0x008b, 0x6003,
+	0x000d, 0x1078, 0x5399, 0x1078, 0x5888, 0x007c, 0x1078, 0x799b,
+	0x1078, 0x77ed, 0x0040, 0x77d6, 0x1078, 0x24bf, 0x0d7e, 0x1078,
+	0x77ed, 0x0040, 0x77b8, 0x6010, 0x2068, 0x6837, 0x0103, 0x684b,
+	0x0006, 0x6847, 0x0000, 0x6850, 0xc0ed, 0x6852, 0x1078, 0x4376,
+	0x2c68, 0x1078, 0x68a8, 0x0040, 0x77c6, 0x6818, 0x601a, 0x0c7e,
+	0x2d60, 0x1078, 0x79a8, 0x0c7f, 0x0078, 0x77c7, 0x2d60, 0x0d7f,
+	0x6013, 0x0000, 0x601f, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001,
+	0x1078, 0x53e6, 0x1078, 0x5888, 0x0078, 0x77d8, 0x1078, 0x79a8,
+	0x007c, 0xa284, 0x0003, 0x00c0, 0x77ea, 0xa282, 0x8f00, 0x0048,
+	0x77ea, 0x2001, 0x8815, 0x2004, 0xa202, 0x00c8, 0x77ea, 0xa085,
+	0x0001, 0x007c, 0xa006, 0x0078, 0x77e9, 0x027e, 0x0e7e, 0x2071,
+	0x8800, 0x6210, 0x7058, 0xa202, 0x0048, 0x77ff, 0x705c, 0xa202,
+	0x00c8, 0x77ff, 0xa085, 0x0001, 0x0e7f, 0x027f, 0x007c, 0xa006,
+	0x0078, 0x77fc, 0x0e7e, 0x0c7e, 0x037e, 0x007e, 0x127e, 0x2091,
+	0x8000, 0x2061, 0x8f00, 0x2071, 0x8800, 0x7344, 0x7060, 0xa302,
+	0x00c8, 0x7828, 0x601c, 0xa206, 0x00c0, 0x7820, 0x1078, 0x79d5,
+	0x00c0, 0x781c, 0x1078, 0x6bc7, 0x0c7e, 0x1078, 0x690e, 0x0c7f,
+	0xace0, 0x000c, 0x7054, 0xac02, 0x00c8, 0x7828, 0x0078, 0x780d,
+	0x127f, 0x007f, 0x037f, 0x0c7f, 0x0e7f, 0x007c, 0x0e7e, 0x0c7e,
+	0x017e, 0xa188, 0x8934, 0x210c, 0x81ff, 0x0040, 0x7846, 0x2061,
+	0x8f00, 0x2071, 0x8800, 0x017e, 0x1078, 0x68a8, 0x017f, 0x0040,
+	0x7849, 0x611a, 0x1078, 0x24bf, 0x1078, 0x690e, 0xa006, 0x0078,
+	0x784b, 0xa085, 0x0001, 0x017f, 0x0c7f, 0x0e7f, 0x007c, 0x0c7e,
+	0x057e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, 0x68a8, 0x057f,
+	0x0040, 0x7868, 0x6612, 0x651a, 0x601f, 0x0003, 0x2009, 0x004b,
+	0x1078, 0x6939, 0xa085, 0x0001, 0x127f, 0x057f, 0x0c7f, 0x007c,
+	0xa006, 0x0078, 0x7864, 0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000,
+	0x62a0, 0x0c7e, 0x1078, 0x68a8, 0x057f, 0x0040, 0x7896, 0x6013,
+	0x0000, 0x651a, 0x601f, 0x0003, 0x0c7e, 0x2560, 0x1078, 0x418b,
+	0x0c7f, 0x1078, 0x54f0, 0x087e, 0x2041, 0x0000, 0x1078, 0x5419,
+	0x2c08, 0x1078, 0x84d2, 0x087f, 0x2009, 0x004c, 0x1078, 0x6939,
+	0xa085, 0x0001, 0x127f, 0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078,
+	0x7892, 0x0f7e, 0x0c7e, 0x047e, 0x0c7e, 0x1078, 0x68a8, 0x2c78,
+	0x0c7f, 0x0040, 0x78b5, 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003,
+	0x2021, 0x0005, 0x1078, 0x78f9, 0x0040, 0x78b5, 0x2f60, 0x2009,
+	0x004d, 0x1078, 0x6939, 0xa085, 0x0001, 0x047f, 0x0c7f, 0x0f7f,
+	0x007c, 0x0f7e, 0x0c7e, 0x047e, 0x0c7e, 0x1078, 0x68a8, 0x2c78,
+	0x0c7f, 0x0040, 0x78d5, 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003,
+	0x2021, 0x0005, 0x1078, 0x78f9, 0x0040, 0x78d5, 0x2f60, 0x2009,
+	0x004e, 0x1078, 0x6939, 0xa085, 0x0001, 0x047f, 0x0c7f, 0x0f7f,
+	0x007c, 0x0f7e, 0x0c7e, 0x047e, 0x0c7e, 0x1078, 0x68a8, 0x2c78,
+	0x0c7f, 0x0040, 0x78f5, 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003,
+	0x2021, 0x0004, 0x1078, 0x78f9, 0x0040, 0x78f5, 0x2f60, 0x2009,
+	0x0052, 0x1078, 0x6939, 0xa085, 0x0001, 0x047f, 0x0c7f, 0x0f7f,
+	0x007c, 0x097e, 0x087e, 0x127e, 0x2091, 0x8000, 0x1078, 0x4117,
+	0x0040, 0x7906, 0x2001, 0x78fe, 0x0078, 0x790c, 0x1078, 0x40dd,
+	0x0040, 0x7915, 0x2001, 0x7906, 0x007e, 0xa00e, 0x2400, 0x1078,
+	0x4454, 0x1078, 0x4376, 0x007f, 0x007a, 0x2418, 0x1078, 0x5726,
+	0x62a0, 0x2041, 0x0001, 0x2608, 0x1078, 0x550a, 0x1078, 0x5419,
+	0x2f08, 0x2648, 0x1078, 0x84d2, 0x613c, 0x81ff, 0x1040, 0x55ae,
+	0x127f, 0x087f, 0x097f, 0x007c, 0x0c7e, 0x127e, 0x2091, 0x8000,
+	0x0c7e, 0x1078, 0x68a8, 0x017f, 0x0040, 0x7945, 0x660a, 0x611a,
+	0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x001f, 0x1078, 0x6939,
+	0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x7942,
+	0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, 0x68a8, 0x017f,
+	0x0040, 0x7961, 0x660a, 0x611a, 0x601f, 0x0008, 0x2d00, 0x6012,
+	0x2009, 0x0021, 0x1078, 0x6939, 0xa085, 0x0001, 0x127f, 0x0c7f,
+	0x007c, 0xa006, 0x0078, 0x795e, 0x0c7e, 0x127e, 0x2091, 0x8000,
+	0x0c7e, 0x1078, 0x68a8, 0x017f, 0x0040, 0x797d, 0x660a, 0x611a,
+	0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x003d, 0x1078, 0x6939,
+	0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x797a,
+	0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, 0x68a8, 0x017f,
+	0x0040, 0x7998, 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009,
+	0x0000, 0x1078, 0x6939, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c,
+	0xa006, 0x0078, 0x7995, 0x027e, 0x0d7e, 0x6218, 0x2268, 0x6a3c,
+	0x82ff, 0x0040, 0x79a5, 0x8211, 0x6a3e, 0x0d7f, 0x027f, 0x007c,
+	0x6013, 0x0000, 0x601f, 0x0007, 0x6017, 0x0014, 0x007c, 0x067e,
+	0x0c7e, 0x0d7e, 0x2031, 0x8852, 0x2634, 0xd6e4, 0x0040, 0x79bd,
+	0x6618, 0x2660, 0x6e48, 0x1078, 0x408b, 0x0d7f, 0x0c7f, 0x067f,
+	0x007c, 0x007e, 0x017e, 0x6004, 0xa08e, 0x0002, 0x0040, 0x79d2,
+	0xa08e, 0x0003, 0x0040, 0x79d2, 0xa08e, 0x0004, 0x0040, 0x79d2,
+	0xa085, 0x0001, 0x017f, 0x007f, 0x007c, 0x007e, 0x017e, 0x6004,
+	0xa08e, 0x0000, 0x0040, 0x79ea, 0xa08e, 0x001f, 0x0040, 0x79ea,
+	0xa08e, 0x0028, 0x0040, 0x79ea, 0xa08e, 0x0029, 0x0040, 0x79ea,
+	0xa085, 0x0001, 0x017f, 0x007f, 0x007c, 0x0c7e, 0x127e, 0x2091,
+	0x8000, 0x0c7e, 0x1078, 0x68a8, 0x017f, 0x0040, 0x7a07, 0x611a,
+	0x601f, 0x0001, 0x2d00, 0x6012, 0x1078, 0x24bf, 0x2009, 0x0028,
+	0x1078, 0x6939, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006,
+	0x0078, 0x7a04, 0xa186, 0x0015, 0x00c0, 0x7a1f, 0x2011, 0x881f,
+	0x2204, 0xa086, 0x0074, 0x00c0, 0x7a1f, 0x1078, 0x6e79, 0x6003,
+	0x0001, 0x6007, 0x0029, 0x1078, 0x53e6, 0x0078, 0x7a23, 0x1078,
+	0x6bc7, 0x1078, 0x690e, 0x007c, 0xa186, 0x0015, 0x00c0, 0x7a41,
+	0x2011, 0x881f, 0x2204, 0xa086, 0x0014, 0x00c0, 0x7a41, 0x0d7e,
+	0x6018, 0x2068, 0x1078, 0x400a, 0x0d7f, 0x1078, 0x6e83, 0x00c0,
+	0x7a41, 0x2001, 0x0006, 0x1078, 0x3f05, 0x1078, 0x69c6, 0x0078,
+	0x7a45, 0x1078, 0x6bc7, 0x1078, 0x690e, 0x007c, 0x6848, 0xa086,
+	0x0005, 0x00c0, 0x7a4d, 0x1078, 0x7a4e, 0x007c, 0x6850, 0xc0ad,
+	0x6852, 0x007c, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12d2,
+	0x1079, 0x7a5c, 0x067f, 0x007c, 0x7a6c, 0x7d34, 0x7e2d, 0x7a6c,
+	0x7a6c, 0x7a6c, 0x7a6c, 0x7a6c, 0x7aa6, 0x7ea4, 0x7a6c, 0x7a6c,
+	0x7a6c, 0x7a6c, 0x7a6c, 0x7a6c, 0x1078, 0x12d2, 0x067e, 0x6000,
+	0xa0b2, 0x0010, 0x10c8, 0x12d2, 0x1079, 0x7a78, 0x067f, 0x007c,
+	0x7a88, 0x82ac, 0x7a88, 0x7a88, 0x7a88, 0x7a88, 0x7a88, 0x7a88,
+	0x8276, 0x82fa, 0x7a88, 0x7a88, 0x7a88, 0x7a88, 0x7a88, 0x7a88,
+	0x1078, 0x12d2, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12d2,
+	0x1079, 0x7a94, 0x067f, 0x007c, 0x7aa4, 0x7ff2, 0x80ac, 0x80d1,
+	0x8120, 0x7aa4, 0x81df, 0x819b, 0x7eb0, 0x824e, 0x8262, 0x7aa4,
+	0x7aa4, 0x7aa4, 0x7aa4, 0x7aa4, 0x1078, 0x12d2, 0xa1b2, 0x0040,
+	0x10c8, 0x12d2, 0x2100, 0x0079, 0x7aad, 0x7aed, 0x7c63, 0x7aed,
+	0x7aed, 0x7aed, 0x7c6b, 0x7aed, 0x7aed, 0x7aed, 0x7aed, 0x7aed,
+	0x7aed, 0x7aed, 0x7aed, 0x7aed, 0x7aed, 0x7aed, 0x7aed, 0x7aed,
+	0x7aed, 0x7aed, 0x7aed, 0x7aed, 0x7aef, 0x7b3d, 0x7b48, 0x7b82,
+	0x7b9d, 0x7bf4, 0x7c4f, 0x7aed, 0x7aed, 0x7c6f, 0x7aed, 0x7aed,
+	0x7c7e, 0x7c85, 0x7aed, 0x7aed, 0x7aed, 0x7aed, 0x7aed, 0x7cb3,
+	0x7aed, 0x7aed, 0x7cbe, 0x7aed, 0x7aed, 0x7aed, 0x7aed, 0x7aed,
+	0x7aed, 0x7aed, 0x7aed, 0x7aed, 0x7aed, 0x7aed, 0x7aed, 0x7aed,
+	0x7aed, 0x7aed, 0x7aed, 0x7aed, 0x7aed, 0x1078, 0x12d2, 0x1078,
+	0x42a2, 0x0e7e, 0x0c7e, 0x037e, 0x027e, 0x017e, 0x6218, 0x2270,
+	0x72a0, 0x027e, 0x2019, 0x0029, 0x1078, 0x54f0, 0x087e, 0x2041,
+	0x0000, 0x1078, 0x5419, 0x2c08, 0x1078, 0x84d2, 0x087f, 0x017f,
+	0x2e60, 0x1078, 0x418b, 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f,
+	0x6618, 0x0c7e, 0x2660, 0x1078, 0x3fa0, 0x0c7f, 0xa6b0, 0x0001,
+	0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0048, 0x7b2f, 0x1078,
+	0x8406, 0x00c0, 0x7b7c, 0x1078, 0x83a4, 0x00c0, 0x7b2b, 0x6007,
+	0x0008, 0x0078, 0x7c5e, 0x6007, 0x0009, 0x0078, 0x7c5e, 0x1078,
+	0x85aa, 0x0040, 0x7b39, 0x1078, 0x8406, 0x0040, 0x7b23, 0x0078,
+	0x7b7c, 0x6013, 0x1900, 0x0078, 0x7b2b, 0x6106, 0x1078, 0x834f,
+	0x6007, 0x0006, 0x0078, 0x7c5e, 0x6007, 0x0007, 0x0078, 0x7c5e,
+	0x1078, 0x8727, 0x00c0, 0x7cd3, 0x0d7e, 0x6618, 0x2668, 0x6e04,
+	0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x7b5e, 0xa686,
+	0x0004, 0x0040, 0x7b5e, 0x0d7f, 0x0078, 0x7b7c, 0x1078, 0x846c,
+	0x00c0, 0x7b77, 0xa686, 0x0006, 0x00c0, 0x7b70, 0x027e, 0x6218,
+	0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x1078, 0x2507, 0x027f,
+	0x1078, 0x400a, 0x6007, 0x000a, 0x0d7f, 0x0078, 0x7c5e, 0x6007,
+	0x000b, 0x0d7f, 0x0078, 0x7c5e, 0x1078, 0x24bf, 0x6007, 0x0001,
+	0x0078, 0x7c5e, 0x1078, 0x8727, 0x00c0, 0x7cd3, 0x6618, 0x0d7e,
+	0x2668, 0x6e04, 0x0d7f, 0xa686, 0x0707, 0x0040, 0x7b7c, 0x027e,
+	0x6218, 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x1078, 0x2507,
+	0x027f, 0x6007, 0x000c, 0x0078, 0x7c5e, 0x1078, 0x42a2, 0x6618,
 	0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0048,
-	0x6d76, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x00c0, 0x6d49,
-	0x1078, 0x7424, 0x00c0, 0x6d70, 0x6007, 0x000e, 0x0078, 0x6dc3,
-	0x1078, 0x22b5, 0x6007, 0x000f, 0x0078, 0x6dc3, 0x1078, 0x754c,
-	0x0040, 0x6d83, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040,
-	0x6d68, 0x0078, 0x6d49, 0x6013, 0x1900, 0x6007, 0x0009, 0x0078,
-	0x6dc3, 0x1078, 0x3b3e, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684,
-	0x00ff, 0xa082, 0x0006, 0x0048, 0x6dae, 0xa6b4, 0xff00, 0x8637,
-	0xa686, 0x0006, 0x00c0, 0x6d49, 0x1078, 0x744f, 0x00c0, 0x6da8,
-	0x1078, 0x7355, 0x00c0, 0x6da8, 0x6007, 0x0010, 0x0078, 0x6dc3,
-	0x1078, 0x22b5, 0x6007, 0x0011, 0x0078, 0x6dc3, 0x1078, 0x754c,
-	0x0040, 0x6dbb, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040,
-	0x6d9c, 0x0078, 0x6d49, 0x6013, 0x1900, 0x6007, 0x0009, 0x0078,
-	0x6dc3, 0x6007, 0x0012, 0x6003, 0x0001, 0x1078, 0x498e, 0x007c,
-	0x6007, 0x0001, 0x6003, 0x0001, 0x1078, 0x498e, 0x0078, 0x6dc7,
-	0x6007, 0x0020, 0x6003, 0x0001, 0x1078, 0x498e, 0x007c, 0x6007,
-	0x0023, 0x6003, 0x0001, 0x1078, 0x498e, 0x007c, 0x017e, 0x027e,
-	0x2011, 0x7c88, 0x2214, 0x2c08, 0x1078, 0x7614, 0x00c0, 0x6def,
-	0x2160, 0x6007, 0x0026, 0x6013, 0x1700, 0x0078, 0x6df4, 0x1078,
-	0x5d1a, 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, 0x1078, 0x498e,
-	0x027f, 0x017f, 0x007c, 0x6106, 0x1078, 0x6e0d, 0x6007, 0x002b,
-	0x0078, 0x6dc3, 0x6007, 0x002c, 0x0078, 0x6dc3, 0x6106, 0x1078,
-	0x6e12, 0x6007, 0x002e, 0x0078, 0x6dc3, 0x0d7e, 0x1078, 0x6e38,
-	0x0d7f, 0x007c, 0x0d7e, 0x1078, 0x6e47, 0x00c0, 0x6e31, 0x680c,
-	0xa08c, 0xff00, 0x6824, 0xa084, 0x00ff, 0xa115, 0x6212, 0xd1e4,
-	0x0040, 0x6e26, 0x2009, 0x0001, 0x0078, 0x6e2d, 0xd1ec, 0x0040,
-	0x6e31, 0x2009, 0x0000, 0xa294, 0x00ff, 0x1078, 0x22f9, 0x0078,
-	0x6e35, 0xa085, 0x0001, 0x0078, 0x6e36, 0xa006, 0x0d7f, 0x007c,
-	0x2069, 0x7c8d, 0x6800, 0xa082, 0x0010, 0x00c8, 0x6e45, 0x6013,
-	0x0000, 0xa085, 0x0001, 0x0078, 0x6e46, 0xa006, 0x007c, 0x6013,
-	0x0000, 0x2069, 0x7c8c, 0x6808, 0xa084, 0xff00, 0xa086, 0x0800,
-	0x007c, 0x6004, 0xa0b2, 0x0030, 0x10c8, 0x12cd, 0xa1b6, 0x0013,
-	0x00c0, 0x6e5d, 0x2008, 0x0079, 0x6e70, 0xa1b6, 0x0027, 0x0040,
-	0x6e65, 0xa1b6, 0x0014, 0x10c0, 0x12cd, 0x2001, 0x0007, 0x1078,
-	0x3802, 0x1078, 0x4c9d, 0x1078, 0x6bb6, 0x1078, 0x4d96, 0x007c,
-	0x6ea0, 0x6ea2, 0x6ea0, 0x6ea0, 0x6ea0, 0x6ea2, 0x6eaa, 0x6f0d,
-	0x6ed0, 0x6f0d, 0x6ee4, 0x6f0d, 0x6eaa, 0x6f0d, 0x6f05, 0x6f0d,
-	0x6f05, 0x6f0d, 0x6f0d, 0x6ea0, 0x6ea0, 0x6ea0, 0x6ea0, 0x6ea0,
-	0x6ea0, 0x6ea0, 0x6ea0, 0x6ea0, 0x6ea0, 0x6ea0, 0x6ea0, 0x6ea0,
-	0x6f0d, 0x6ea0, 0x6ea0, 0x6f0d, 0x6ea0, 0x6f0d, 0x6f0d, 0x6ea0,
-	0x6ea0, 0x6ea0, 0x6ea0, 0x6f0d, 0x6f0d, 0x6ea0, 0x6f0d, 0x6f0d,
-	0x1078, 0x12cd, 0x1078, 0x4c9d, 0x6003, 0x0002, 0x1078, 0x4d96,
-	0x0078, 0x6f13, 0x0f7e, 0x2079, 0x7751, 0x7804, 0x0f7f, 0xd0ac,
-	0x00c0, 0x6f0d, 0x2001, 0x0000, 0x1078, 0x37e0, 0x2001, 0x0002,
-	0x1078, 0x37f4, 0x1078, 0x4c9d, 0x601f, 0x0001, 0x6003, 0x0001,
-	0x6007, 0x0002, 0x1078, 0x498e, 0x1078, 0x4d96, 0x0c7e, 0x6118,
-	0x2160, 0x2009, 0x0001, 0x1078, 0x4696, 0x0c7f, 0x0078, 0x6f13,
-	0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa6b4, 0xff00, 0x8637,
-	0xa686, 0x0006, 0x0040, 0x6f0d, 0xa686, 0x0004, 0x0040, 0x6f0d,
-	0x2001, 0x0004, 0x0078, 0x6f0b, 0x2001, 0x7700, 0x2004, 0xa086,
-	0x0003, 0x00c0, 0x6eed, 0x1078, 0x2dd7, 0x2001, 0x0006, 0x1078,
-	0x6f14, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa6b4, 0xff00,
-	0x8637, 0xa686, 0x0006, 0x0040, 0x6f0d, 0x2001, 0x0006, 0x0078,
-	0x6f0b, 0x2001, 0x0004, 0x0078, 0x6f0b, 0x2001, 0x0006, 0x1078,
-	0x6f14, 0x0078, 0x6f0d, 0x1078, 0x3802, 0x1078, 0x4c9d, 0x1078,
-	0x5d1a, 0x1078, 0x4d96, 0x007c, 0x017e, 0x0d7e, 0x6118, 0x2168,
-	0x6900, 0xd184, 0x0040, 0x6f2f, 0x6104, 0xa18e, 0x000a, 0x00c0,
-	0x6f27, 0x699c, 0xd1a4, 0x00c0, 0x6f27, 0x2001, 0x0007, 0x1078,
-	0x37f4, 0x2001, 0x0000, 0x1078, 0x37e0, 0x1078, 0x22d7, 0x0d7f,
-	0x017f, 0x007c, 0x0d7e, 0x6618, 0x2668, 0x6804, 0xa084, 0xff00,
-	0x8007, 0x0d7f, 0xa0b2, 0x000c, 0x10c8, 0x12cd, 0xa1b6, 0x0015,
-	0x00c0, 0x6f46, 0x1079, 0x6f4d, 0x0078, 0x6f4c, 0xa1b6, 0x0016,
-	0x10c0, 0x12cd, 0x1079, 0x6f85, 0x007c, 0x5ff7, 0x5ff7, 0x5ff7,
-	0x5ff7, 0x5ff7, 0x5ff7, 0x5ff7, 0x6f59, 0x5ff7, 0x5ff7, 0x5ff7,
-	0x5ff7, 0x0f7e, 0x2079, 0x7751, 0x7804, 0x0f7f, 0xd0ac, 0x00c0,
-	0x6f75, 0x2001, 0x0000, 0x1078, 0x37e0, 0x2001, 0x0002, 0x1078,
-	0x37f4, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x1078,
-	0x498e, 0x1078, 0x4d96, 0x0078, 0x6f84, 0x2011, 0x7c83, 0x220c,
-	0x017e, 0x0c7e, 0x1078, 0x384c, 0x00c0, 0x6f84, 0x1078, 0x3637,
-	0x0c7f, 0x017f, 0x1078, 0x5d1a, 0x007c, 0x5ff7, 0x5ff7, 0x5ff7,
-	0x5ff7, 0x5ff7, 0x5ff7, 0x5ff7, 0x6f91, 0x5ff7, 0x5ff7, 0x5ff7,
-	0x5ff7, 0x1078, 0x61e7, 0x00c0, 0x6f9d, 0x6003, 0x0001, 0x6007,
-	0x0001, 0x1078, 0x498e, 0x0078, 0x6f9f, 0x1078, 0x5d1a, 0x007c,
-	0x6004, 0xa08a, 0x0030, 0x10c8, 0x12cd, 0x1078, 0x4c9d, 0x1078,
-	0x6bb6, 0x1078, 0x4d96, 0x007c, 0xa182, 0x0040, 0x0079, 0x6fb0,
-	0x6fc0, 0x6fc0, 0x6fc0, 0x6fc0, 0x6fc2, 0x6fc0, 0x6fc0, 0x6fc0,
-	0x6fc0, 0x6fc0, 0x6fc0, 0x6fc0, 0x6fc0, 0x6fc0, 0x6fc0, 0x6fc0,
-	0x1078, 0x12cd, 0x0d7e, 0x0e7e, 0x0f7e, 0x157e, 0x047e, 0x027e,
-	0x6106, 0x2071, 0x7c80, 0x7444, 0xa4a4, 0xe600, 0x0040, 0x7026,
-	0x2009, 0x0000, 0x0c7e, 0x1078, 0x4727, 0x2c68, 0x0c7f, 0x6a00,
-	0xa284, 0x0001, 0x0040, 0x7091, 0x1078, 0x47e6, 0x0040, 0x70bc,
-	0xa295, 0x0200, 0x6a02, 0x0078, 0x6feb, 0x2009, 0x0001, 0x2011,
-	0x0200, 0x1078, 0x47d0, 0x1078, 0x1327, 0x1040, 0x12cd, 0x6003,
-	0x0007, 0x2d00, 0x6837, 0x010d, 0x6803, 0x0000, 0x683b, 0x0000,
-	0x6c5a, 0x2c00, 0x685e, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130,
-	0x694a, 0xa084, 0xff00, 0x6846, 0x684f, 0x0000, 0x6857, 0x0036,
-	0x1078, 0x3b92, 0xa486, 0x2000, 0x00c0, 0x7014, 0x2019, 0x0017,
-	0x1078, 0x75d9, 0x0078, 0x707e, 0xa486, 0x0400, 0x00c0, 0x701e,
-	0x2019, 0x0002, 0x1078, 0x75d9, 0x0078, 0x707e, 0xa486, 0x0200,
-	0x00c0, 0x7024, 0x1078, 0x75ca, 0x0078, 0x707e, 0x2009, 0x0000,
-	0x0c7e, 0x1078, 0x4727, 0x2c68, 0x0c7f, 0x6a00, 0xa284, 0x0001,
-	0x0040, 0x70d4, 0xa284, 0x0300, 0x00c0, 0x70cc, 0x6804, 0xa005,
-	0x0040, 0x70bc, 0x8001, 0x6806, 0x6003, 0x0007, 0x1078, 0x130c,
-	0x0040, 0x7085, 0x6013, 0x0000, 0x6803, 0x0000, 0x6837, 0x0116,
-	0x683b, 0x0000, 0x2c00, 0x684a, 0x6018, 0x2078, 0x78a0, 0x8007,
-	0x7130, 0x6986, 0x6846, 0x6853, 0x003d, 0x7044, 0xa084, 0x0003,
-	0xa086, 0x0002, 0x00c0, 0x7060, 0x684f, 0x0040, 0x0078, 0x706a,
-	0xa086, 0x0001, 0x00c0, 0x7068, 0x684f, 0x0080, 0x0078, 0x706a,
-	0x684f, 0x0000, 0x20a9, 0x000a, 0x2001, 0x7c90, 0xad90, 0x0015,
-	0x200c, 0x810f, 0x2112, 0x8000, 0x8210, 0x00f0, 0x7070, 0x200c,
-	0x6982, 0x8000, 0x200c, 0x697e, 0x1078, 0x3b92, 0x027f, 0x047f,
-	0x157f, 0x0f7f, 0x0e7f, 0x0d7f, 0x007c, 0x6013, 0x0100, 0x6003,
-	0x0001, 0x6007, 0x0041, 0x1078, 0x4941, 0x1078, 0x4d96, 0x0078,
-	0x707e, 0x2069, 0x7c92, 0x2d04, 0xa084, 0xff00, 0xa086, 0x1200,
-	0x00c0, 0x70b0, 0x2069, 0x7c80, 0x686c, 0xa084, 0x00ff, 0x017e,
-	0x6110, 0xa18c, 0x0700, 0xa10d, 0x6112, 0x017f, 0x6003, 0x0001,
-	0x6007, 0x0043, 0x1078, 0x4941, 0x1078, 0x4d96, 0x0078, 0x707e,
-	0x6013, 0x0200, 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, 0x4941,
-	0x1078, 0x4d96, 0x0078, 0x707e, 0x6013, 0x0300, 0x0078, 0x70c2,
-	0x6013, 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, 0x4941,
-	0x1078, 0x4d96, 0x0078, 0x707e, 0x6013, 0x0500, 0x0078, 0x70c2,
-	0x6013, 0x0600, 0x0078, 0x7091, 0x6013, 0x0200, 0x0078, 0x7091,
-	0xa186, 0x0013, 0x00c0, 0x70ea, 0x6004, 0xa08a, 0x0040, 0x1048,
-	0x12cd, 0xa08a, 0x0050, 0x10c8, 0x12cd, 0xa082, 0x0040, 0x2008,
-	0x0079, 0x711b, 0xa186, 0x0047, 0x00c0, 0x70f0, 0x0078, 0x714a,
-	0xa186, 0x0027, 0x0040, 0x70f8, 0xa186, 0x0014, 0x10c0, 0x12cd,
-	0x6004, 0xa082, 0x0040, 0x2008, 0x0079, 0x70fe, 0x710e, 0x7110,
-	0x7110, 0x710e, 0x710e, 0x710e, 0x710e, 0x710e, 0x710e, 0x710e,
-	0x710e, 0x710e, 0x710e, 0x710e, 0x710e, 0x710e, 0x1078, 0x12cd,
-	0x2001, 0x0007, 0x1078, 0x3802, 0x1078, 0x4c9d, 0x1078, 0x6bb6,
-	0x1078, 0x4d96, 0x007c, 0x712b, 0x713b, 0x7134, 0x7144, 0x712b,
-	0x712b, 0x712b, 0x712b, 0x712b, 0x712b, 0x712b, 0x712b, 0x712b,
-	0x712b, 0x712b, 0x712b, 0x1078, 0x12cd, 0x6010, 0xa088, 0x0013,
-	0x2104, 0xa085, 0x0400, 0x200a, 0x1078, 0x4c9d, 0x6003, 0x0002,
-	0x1078, 0x4d96, 0x007c, 0x1078, 0x4c9d, 0x1078, 0x47a8, 0x1078,
-	0x5d1a, 0x1078, 0x4d96, 0x007c, 0x1078, 0x4c9d, 0x2009, 0x0041,
-	0x0078, 0x7212, 0xa182, 0x0040, 0x0079, 0x714e, 0x715e, 0x7160,
-	0x715e, 0x715e, 0x715e, 0x715e, 0x715e, 0x7161, 0x715e, 0x715e,
-	0x715e, 0x715e, 0x715e, 0x715e, 0x715e, 0x715e, 0x1078, 0x12cd,
-	0x007c, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20,
-	0x2c10, 0x1078, 0x156a, 0x007c, 0xa182, 0x0040, 0x0079, 0x7170,
-	0x7180, 0x7180, 0x7180, 0x7180, 0x7180, 0x7180, 0x7180, 0x7180,
-	0x7180, 0x7182, 0x71a5, 0x7180, 0x7180, 0x7180, 0x7180, 0x71a5,
-	0x1078, 0x12cd, 0x1078, 0x4d45, 0x1078, 0x4e56, 0x6010, 0x0d7e,
-	0x2068, 0x684c, 0xd0fc, 0x0040, 0x7198, 0xa08c, 0x0003, 0xa18e,
-	0x0002, 0x0040, 0x719e, 0x2009, 0x0041, 0x0d7f, 0x0078, 0x7212,
-	0x6003, 0x0007, 0x1078, 0x47a8, 0x0d7f, 0x007c, 0x1078, 0x47a8,
-	0x1078, 0x5d1a, 0x0d7f, 0x0078, 0x719d, 0x037e, 0x1078, 0x4d45,
-	0x1078, 0x4e56, 0x6010, 0x0d7e, 0x2068, 0x2019, 0x0004, 0x1078,
-	0x75fd, 0x1078, 0x6bb6, 0x6017, 0x0028, 0x0d7f, 0x037f, 0x007c,
-	0xa186, 0x0013, 0x00c0, 0x71c6, 0x6004, 0xa086, 0x0042, 0x10c0,
-	0x12cd, 0x1078, 0x4c9d, 0x1078, 0x4d96, 0x007c, 0xa186, 0x0027,
-	0x0040, 0x71ce, 0xa186, 0x0014, 0x00c0, 0x71de, 0x6004, 0xa086,
-	0x0042, 0x10c0, 0x12cd, 0x2001, 0x0007, 0x1078, 0x3802, 0x1078,
-	0x4c9d, 0x1078, 0x6bb6, 0x1078, 0x4d96, 0x007c, 0xa182, 0x0040,
-	0x0079, 0x71e2, 0x71f2, 0x71f2, 0x71f2, 0x71f2, 0x71f2, 0x71f2,
-	0x71f2, 0x71f4, 0x7200, 0x71f2, 0x71f2, 0x71f2, 0x71f2, 0x71f2,
-	0x71f2, 0x71f2, 0x1078, 0x12cd, 0x037e, 0x047e, 0x20e1, 0x0005,
-	0x3d18, 0x3e20, 0x2c10, 0x1078, 0x156a, 0x047f, 0x037f, 0x007c,
-	0x6010, 0x0d7e, 0x2068, 0x684c, 0xd0fc, 0x0040, 0x720c, 0x2009,
-	0x0041, 0x0d7f, 0x0078, 0x7212, 0x6003, 0x0007, 0x1078, 0x47a8,
-	0x0d7f, 0x007c, 0xa182, 0x0040, 0x0079, 0x7216, 0x7226, 0x7228,
-	0x7234, 0x7240, 0x7226, 0x7226, 0x7226, 0x7226, 0x7226, 0x7226,
-	0x7226, 0x7226, 0x7226, 0x7226, 0x7226, 0x7226, 0x1078, 0x12cd,
-	0x6003, 0x0001, 0x6106, 0x1078, 0x4941, 0x127e, 0x2091, 0x8000,
-	0x1078, 0x4d96, 0x127f, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078,
-	0x4941, 0x127e, 0x2091, 0x8000, 0x1078, 0x4d96, 0x127f, 0x007c,
-	0x6003, 0x0003, 0x6106, 0x2c10, 0x1078, 0x19c7, 0x127e, 0x2091,
-	0x8000, 0x1078, 0x49ad, 0x1078, 0x4e56, 0x127f, 0x007c, 0x1078,
-	0x4c9d, 0x0078, 0x7255, 0x1078, 0x4d45, 0x6110, 0x81ff, 0x0040,
-	0x7262, 0x0d7e, 0x2168, 0x037e, 0x2019, 0x0029, 0x1078, 0x75fd,
-	0x037f, 0x0d7f, 0x1078, 0x6bb6, 0x1078, 0x4d96, 0x007c, 0xa182,
-	0x0085, 0x0079, 0x726b, 0x7272, 0x7272, 0x7272, 0x7274, 0x7272,
-	0x7272, 0x7272, 0x1078, 0x12cd, 0x027e, 0x0e7e, 0x2071, 0x7c80,
-	0x7220, 0x1078, 0x7517, 0x0040, 0x7281, 0x6007, 0x0086, 0x0078,
-	0x7283, 0x6007, 0x0087, 0x6003, 0x0001, 0x1078, 0x4941, 0x1078,
-	0x4d96, 0x0e7f, 0x027f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x729d,
-	0x6004, 0xa08a, 0x0085, 0x1048, 0x12cd, 0xa08a, 0x008c, 0x10c8,
-	0x12cd, 0xa082, 0x0085, 0x0079, 0x72b0, 0xa186, 0x0027, 0x0040,
-	0x72a5, 0xa186, 0x0014, 0x10c0, 0x12cd, 0x2001, 0x0007, 0x1078,
-	0x3802, 0x1078, 0x4c9d, 0x1078, 0x6bb6, 0x1078, 0x4d96, 0x007c,
-	0x72b7, 0x72b9, 0x72b9, 0x72b7, 0x72b7, 0x72b7, 0x72b7, 0x1078,
-	0x12cd, 0x1078, 0x4c9d, 0x1078, 0x5d1a, 0x1078, 0x4d96, 0x007c,
-	0xa182, 0x0085, 0x1048, 0x12cd, 0xa182, 0x008c, 0x10c8, 0x12cd,
-	0xa182, 0x0085, 0x0079, 0x72cc, 0x72d3, 0x72d3, 0x72d3, 0x72d5,
-	0x72d3, 0x72d3, 0x72d3, 0x1078, 0x12cd, 0x007c, 0x1078, 0x4c9d,
-	0x1078, 0x6bb6, 0x1078, 0x4d96, 0x007c, 0x037e, 0x2019, 0x000b,
-	0x1078, 0x72e6, 0x601f, 0x0006, 0x037f, 0x007c, 0x127e, 0x037e,
-	0x087e, 0x2091, 0x8000, 0x2c40, 0x1078, 0x5a2d, 0x00c0, 0x7313,
-	0x1078, 0x5ace, 0x00c0, 0x7313, 0x6000, 0xa086, 0x0000, 0x0040,
-	0x7313, 0x601c, 0xa086, 0x0007, 0x0040, 0x7313, 0x0d7e, 0x6000,
-	0xa086, 0x0004, 0x00c0, 0x7306, 0x1078, 0x166e, 0x6010, 0x2068,
-	0x1078, 0x6a58, 0x0040, 0x730e, 0x1078, 0x75fd, 0x0d7f, 0x6013,
+	0x7be1, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0004, 0x0040, 0x7bb4,
+	0xa686, 0x0006, 0x00c0, 0x7b7c, 0x1078, 0x847b, 0x00c0, 0x7bbc,
+	0x6007, 0x000e, 0x0078, 0x7c5e, 0x047e, 0x6418, 0xa4a0, 0x0028,
+	0x2424, 0xa4a4, 0x00ff, 0x8427, 0x047e, 0x1078, 0x24bf, 0x047f,
+	0x017e, 0xa006, 0x2009, 0x8852, 0x210c, 0xd1a4, 0x0040, 0x7bdb,
+	0x2009, 0x0029, 0x1078, 0x86f5, 0x6018, 0x0d7e, 0x2068, 0x6800,
+	0xc0e5, 0x6802, 0x0d7f, 0x017f, 0x047f, 0x6007, 0x0001, 0x0078,
+	0x7c5e, 0x1078, 0x85aa, 0x0040, 0x7bee, 0xa6b4, 0xff00, 0x8637,
+	0xa686, 0x0006, 0x0040, 0x7bb4, 0x0078, 0x7b7c, 0x6013, 0x1900,
+	0x6007, 0x0009, 0x0078, 0x7c5e, 0x1078, 0x42a2, 0x6618, 0xa6b0,
+	0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0048, 0x7c3c,
+	0xa6b4, 0xff00, 0x8637, 0xa686, 0x0004, 0x0040, 0x7c0b, 0xa686,
+	0x0006, 0x00c0, 0x7b7c, 0x1078, 0x84a6, 0x00c0, 0x7c17, 0x1078,
+	0x83a4, 0x00c0, 0x7c17, 0x6007, 0x0010, 0x0078, 0x7c5e, 0x047e,
+	0x6418, 0xa4a0, 0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427, 0x047e,
+	0x1078, 0x24bf, 0x047f, 0x017e, 0xa006, 0x2009, 0x8852, 0x210c,
+	0xd1a4, 0x0040, 0x7c36, 0x2009, 0x0029, 0x1078, 0x86f5, 0x6018,
+	0x0d7e, 0x2068, 0x6800, 0xc0e5, 0x6802, 0x0d7f, 0x017f, 0x047f,
+	0x6007, 0x0001, 0x0078, 0x7c5e, 0x1078, 0x85aa, 0x0040, 0x7c49,
+	0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x7c0b, 0x0078,
+	0x7b7c, 0x6013, 0x1900, 0x6007, 0x0009, 0x0078, 0x7c5e, 0x7030,
+	0xa086, 0x6000, 0x0040, 0x7c5c, 0x1078, 0x8727, 0x00c0, 0x7cd3,
+	0x1078, 0x7cd6, 0x00c0, 0x7b7c, 0x6007, 0x0012, 0x6003, 0x0001,
+	0x1078, 0x53e6, 0x007c, 0x6007, 0x0001, 0x6003, 0x0001, 0x1078,
+	0x53e6, 0x0078, 0x7c62, 0x6007, 0x0005, 0x0078, 0x7c65, 0x1078,
+	0x8727, 0x00c0, 0x7cd3, 0x1078, 0x7cd6, 0x00c0, 0x7b7c, 0x6007,
+	0x0020, 0x6003, 0x0001, 0x1078, 0x53e6, 0x007c, 0x6007, 0x0023,
+	0x6003, 0x0001, 0x1078, 0x53e6, 0x007c, 0x1078, 0x8727, 0x00c0,
+	0x7cd3, 0x1078, 0x7cd6, 0x00c0, 0x7b7c, 0x017e, 0x027e, 0x2011,
+	0x8d90, 0x2214, 0x2c08, 0x1078, 0x86c1, 0x00c0, 0x7ca7, 0x2160,
+	0x6007, 0x0026, 0x6013, 0x1700, 0x2011, 0x8d89, 0x2214, 0xa296,
+	0xffff, 0x00c0, 0x7cac, 0x6007, 0x0025, 0x0078, 0x7cac, 0x1078,
+	0x690e, 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, 0x1078, 0x53e6,
+	0x027f, 0x017f, 0x007c, 0x6106, 0x1078, 0x7ce9, 0x6007, 0x002b,
+	0x0078, 0x7c5e, 0x6007, 0x002c, 0x0078, 0x7c5e, 0x1078, 0x8727,
+	0x00c0, 0x7cd3, 0x1078, 0x7cd6, 0x00c0, 0x7b7c, 0x6106, 0x1078,
+	0x7cee, 0x00c0, 0x7ccf, 0x6007, 0x002e, 0x0078, 0x7c5e, 0x6007,
+	0x002f, 0x0078, 0x7c5e, 0x1078, 0x690e, 0x007c, 0x0d7e, 0x6618,
+	0x2668, 0x6e04, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040,
+	0x7ce7, 0xa686, 0x0004, 0x0040, 0x7ce7, 0xa085, 0x0001, 0x0d7f,
+	0x007c, 0x0d7e, 0x1078, 0x7d1b, 0x0d7f, 0x007c, 0x0d7e, 0x1078,
+	0x7d2a, 0x00c0, 0x7d14, 0x680c, 0xa08c, 0xff00, 0x6824, 0xa084,
+	0x00ff, 0xa115, 0x6212, 0xd1e4, 0x0040, 0x7d02, 0x2009, 0x0001,
+	0x0078, 0x7d10, 0xd1ec, 0x0040, 0x7d14, 0x6920, 0xa18c, 0x00ff,
+	0x6824, 0x1078, 0x2245, 0x00c0, 0x7d14, 0x2110, 0x2009, 0x0000,
+	0x1078, 0x2507, 0x0078, 0x7d18, 0xa085, 0x0001, 0x0078, 0x7d19,
+	0xa006, 0x0d7f, 0x007c, 0x2069, 0x8d8d, 0x6800, 0xa082, 0x0010,
+	0x00c8, 0x7d28, 0x6013, 0x0000, 0xa085, 0x0001, 0x0078, 0x7d29,
+	0xa006, 0x007c, 0x6013, 0x0000, 0x2069, 0x8d8c, 0x6808, 0xa084,
+	0xff00, 0xa086, 0x0800, 0x007c, 0x6004, 0xa0b2, 0x0040, 0x10c8,
+	0x12d2, 0xa1b6, 0x0013, 0x00c0, 0x7d40, 0x2008, 0x0079, 0x7d53,
+	0xa1b6, 0x0027, 0x0040, 0x7d48, 0xa1b6, 0x0014, 0x10c0, 0x12d2,
+	0x2001, 0x0007, 0x1078, 0x3f2c, 0x1078, 0x578f, 0x1078, 0x79a8,
+	0x1078, 0x5888, 0x007c, 0x7d93, 0x7d95, 0x7d93, 0x7d93, 0x7d93,
+	0x7d95, 0x7d9d, 0x7e08, 0x7dcb, 0x7e08, 0x7ddf, 0x7e08, 0x7d9d,
+	0x7e08, 0x7e00, 0x7e08, 0x7e00, 0x7e08, 0x7e08, 0x7d93, 0x7d93,
+	0x7d93, 0x7d93, 0x7d93, 0x7d93, 0x7d93, 0x7d93, 0x7d93, 0x7d93,
+	0x7d93, 0x7d93, 0x7d93, 0x7e08, 0x7d93, 0x7d93, 0x7e08, 0x7d93,
+	0x7e08, 0x7e08, 0x7d93, 0x7d93, 0x7d93, 0x7d93, 0x7e08, 0x7e08,
+	0x7d93, 0x7e08, 0x7e08, 0x7d93, 0x7d93, 0x7d93, 0x7d93, 0x7d93,
+	0x7d93, 0x7d93, 0x7d93, 0x7d93, 0x7d93, 0x7d93, 0x7d93, 0x7d93,
+	0x7d93, 0x7d93, 0x7d93, 0x1078, 0x12d2, 0x1078, 0x578f, 0x6003,
+	0x0002, 0x1078, 0x5888, 0x0078, 0x7e0e, 0x0f7e, 0x2079, 0x8851,
+	0x7804, 0x0f7f, 0xd0ac, 0x00c0, 0x7e08, 0x2001, 0x0000, 0x1078,
+	0x3ef1, 0x6018, 0xa080, 0x0004, 0x2004, 0xa086, 0x00ff, 0x0040,
+	0x7e08, 0x2001, 0x0002, 0x1078, 0x3f05, 0x1078, 0x578f, 0x601f,
+	0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x1078, 0x53e6, 0x1078,
+	0x5888, 0x0c7e, 0x6118, 0x2160, 0x2009, 0x0001, 0x1078, 0x50ff,
+	0x0c7f, 0x0078, 0x7e0e, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f,
+	0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x7e08, 0xa686,
+	0x0004, 0x0040, 0x7e08, 0x2001, 0x0004, 0x0078, 0x7e06, 0x2001,
+	0x8800, 0x2004, 0xa086, 0x0003, 0x00c0, 0x7de8, 0x1078, 0x31f8,
+	0x2001, 0x0006, 0x1078, 0x7e0f, 0x6618, 0x0d7e, 0x2668, 0x6e04,
+	0x0d7f, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x7e08,
+	0x2001, 0x0006, 0x0078, 0x7e06, 0x2001, 0x0004, 0x0078, 0x7e06,
+	0x2001, 0x0006, 0x1078, 0x7e0f, 0x0078, 0x7e08, 0x1078, 0x3f2c,
+	0x1078, 0x578f, 0x1078, 0x690e, 0x1078, 0x5888, 0x007c, 0x017e,
+	0x0d7e, 0x6118, 0x2168, 0x6900, 0xd184, 0x0040, 0x7e2a, 0x6104,
+	0xa18e, 0x000a, 0x00c0, 0x7e22, 0x699c, 0xd1a4, 0x00c0, 0x7e22,
+	0x2001, 0x0007, 0x1078, 0x3f05, 0x2001, 0x0000, 0x1078, 0x3ef1,
+	0x1078, 0x24e5, 0x0d7f, 0x017f, 0x007c, 0x0d7e, 0x6618, 0x2668,
+	0x6804, 0xa084, 0xff00, 0x8007, 0x0d7f, 0xa0b2, 0x000c, 0x10c8,
+	0x12d2, 0xa1b6, 0x0015, 0x00c0, 0x7e41, 0x1079, 0x7e48, 0x0078,
+	0x7e47, 0xa1b6, 0x0016, 0x10c0, 0x12d2, 0x1079, 0x7e89, 0x007c,
+	0x6c5e, 0x6c5e, 0x6c5e, 0x6c5e, 0x6c5e, 0x6c5e, 0x6c5e, 0x7e54,
+	0x6c5e, 0x6c5e, 0x6c5e, 0x6c5e, 0x0f7e, 0x2079, 0x8851, 0x7804,
+	0x0f7f, 0xd0ac, 0x00c0, 0x7e70, 0x2001, 0x0000, 0x1078, 0x3ef1,
+	0x2001, 0x0002, 0x1078, 0x3f05, 0x601f, 0x0001, 0x6003, 0x0001,
+	0x6007, 0x0002, 0x1078, 0x53e6, 0x1078, 0x5888, 0x0078, 0x7e88,
+	0x2011, 0x8d83, 0x2204, 0x8211, 0x220c, 0x1078, 0x2245, 0x00c0,
+	0x7e88, 0x0c7e, 0x1078, 0x3f8e, 0x0040, 0x7e83, 0x0c7f, 0x1078,
+	0x690e, 0x0078, 0x7e88, 0x1078, 0x3d31, 0x0c7f, 0x1078, 0x690e,
+	0x007c, 0x6c5e, 0x6c5e, 0x6c5e, 0x6c5e, 0x6c5e, 0x6c5e, 0x6c5e,
+	0x7e95, 0x6c5e, 0x6c5e, 0x6c5e, 0x6c5e, 0x1078, 0x6e76, 0x00c0,
+	0x7ea1, 0x6003, 0x0001, 0x6007, 0x0001, 0x1078, 0x53e6, 0x0078,
+	0x7ea3, 0x1078, 0x690e, 0x007c, 0x6004, 0xa08a, 0x0040, 0x10c8,
+	0x12d2, 0x1078, 0x578f, 0x1078, 0x79a8, 0x1078, 0x5888, 0x007c,
+	0xa182, 0x0040, 0x0079, 0x7eb4, 0x7ec7, 0x7ec7, 0x7ec7, 0x7ec7,
+	0x7ec9, 0x7ec7, 0x7ec7, 0x7ec7, 0x7ec7, 0x7ec7, 0x7ec7, 0x7ec7,
+	0x7ec7, 0x7ec7, 0x7ec7, 0x7ec7, 0x7ec7, 0x7ec7, 0x7ec7, 0x1078,
+	0x12d2, 0x0d7e, 0x0e7e, 0x0f7e, 0x157e, 0x047e, 0x027e, 0x6106,
+	0x2071, 0x8d80, 0x7444, 0xa4a4, 0xff00, 0x0040, 0x7f3e, 0xa486,
+	0x2000, 0x0040, 0x7ef3, 0xa486, 0x0400, 0x0040, 0x7ef3, 0xa486,
+	0x1000, 0x0040, 0x7ee5, 0x0078, 0x7ef9, 0x2069, 0x8b24, 0x6a00,
+	0xd284, 0x0040, 0x7fab, 0x1078, 0x5253, 0x0040, 0x7fd6, 0xc2cd,
+	0x6a02, 0x0078, 0x7ef9, 0x2009, 0x0001, 0x2011, 0x0200, 0x1078,
+	0x5243, 0x1078, 0x132b, 0x1040, 0x12d2, 0x6003, 0x0007, 0x2d00,
+	0x6837, 0x010d, 0x6803, 0x0000, 0x683b, 0x0000, 0x6c5a, 0x2c00,
+	0x685e, 0x6008, 0x68b2, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130,
+	0x694a, 0x017e, 0xa084, 0xff00, 0x6846, 0x684f, 0x0000, 0x6857,
+	0x0036, 0x1078, 0x4376, 0x017f, 0xa486, 0x2000, 0x00c0, 0x7f26,
+	0x2019, 0x0017, 0x1078, 0x8683, 0x0078, 0x7f98, 0xa486, 0x0400,
+	0x00c0, 0x7f30, 0x2019, 0x0002, 0x1078, 0x8644, 0x0078, 0x7f98,
+	0xa486, 0x0200, 0x00c0, 0x7f36, 0x1078, 0x8631, 0xa486, 0x1000,
+	0x00c0, 0x7f3c, 0x1078, 0x8670, 0x0078, 0x7f98, 0x2069, 0x8b24,
+	0x6a00, 0xd284, 0x0040, 0x7fee, 0xa284, 0x0300, 0x00c0, 0x7fe6,
+	0x6804, 0xa005, 0x0040, 0x7fd6, 0x2d78, 0x6003, 0x0007, 0x1078,
+	0x1310, 0x0040, 0x7f9f, 0x7800, 0xd08c, 0x00c0, 0x7f5a, 0x7804,
+	0x8001, 0x7806, 0x6013, 0x0000, 0x6803, 0x0000, 0x6837, 0x0116,
+	0x683b, 0x0000, 0x6008, 0x68b2, 0x2c00, 0x684a, 0x6018, 0x2078,
+	0x78a0, 0x8007, 0x7130, 0x6986, 0x6846, 0x6853, 0x003d, 0x7244,
+	0xa294, 0x0003, 0xa286, 0x0002, 0x00c0, 0x7f7a, 0x684f, 0x0040,
+	0x0078, 0x7f84, 0xa286, 0x0001, 0x00c0, 0x7f82, 0x684f, 0x0080,
+	0x0078, 0x7f84, 0x684f, 0x0000, 0x20a9, 0x000a, 0x2001, 0x8d90,
+	0xad90, 0x0015, 0x200c, 0x810f, 0x2112, 0x8000, 0x8210, 0x00f0,
+	0x7f8a, 0x200c, 0x6982, 0x8000, 0x200c, 0x697e, 0x1078, 0x4376,
+	0x027f, 0x047f, 0x157f, 0x0f7f, 0x0e7f, 0x0d7f, 0x007c, 0x6013,
+	0x0100, 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, 0x5399, 0x1078,
+	0x5888, 0x0078, 0x7f98, 0x2069, 0x8d92, 0x2d04, 0xa084, 0xff00,
+	0xa086, 0x1200, 0x00c0, 0x7fca, 0x2069, 0x8d80, 0x686c, 0xa084,
+	0x00ff, 0x017e, 0x6110, 0xa18c, 0x0700, 0xa10d, 0x6112, 0x017f,
+	0x6003, 0x0001, 0x6007, 0x0043, 0x1078, 0x5399, 0x1078, 0x5888,
+	0x0078, 0x7f98, 0x6013, 0x0200, 0x6003, 0x0001, 0x6007, 0x0041,
+	0x1078, 0x5399, 0x1078, 0x5888, 0x0078, 0x7f98, 0x6013, 0x0300,
+	0x0078, 0x7fdc, 0x6013, 0x0100, 0x6003, 0x0001, 0x6007, 0x0041,
+	0x1078, 0x5399, 0x1078, 0x5888, 0x0078, 0x7f98, 0x6013, 0x0500,
+	0x0078, 0x7fdc, 0x6013, 0x0600, 0x0078, 0x7fab, 0x6013, 0x0200,
+	0x0078, 0x7fab, 0xa186, 0x0013, 0x00c0, 0x8004, 0x6004, 0xa08a,
+	0x0040, 0x1048, 0x12d2, 0xa08a, 0x0053, 0x10c8, 0x12d2, 0xa082,
+	0x0040, 0x2008, 0x0079, 0x806b, 0xa186, 0x0047, 0x00c0, 0x8026,
+	0x6004, 0xa086, 0x0041, 0x0040, 0x8034, 0x2001, 0x0109, 0x2004,
+	0xd084, 0x0040, 0x8034, 0x127e, 0x2091, 0x2200, 0x007e, 0x017e,
+	0x027e, 0x1078, 0x5273, 0x027f, 0x017f, 0x007f, 0x127f, 0x6000,
+	0xa086, 0x0002, 0x00c0, 0x8034, 0x0078, 0x80ac, 0xa186, 0x0027,
+	0x0040, 0x802e, 0xa186, 0x0014, 0x10c0, 0x12d2, 0x6004, 0xa082,
+	0x0040, 0x2008, 0x0079, 0x8037, 0x1078, 0x6950, 0x007c, 0x804a,
+	0x804c, 0x804c, 0x804a, 0x804a, 0x804a, 0x804a, 0x804a, 0x804a,
+	0x804a, 0x804a, 0x804a, 0x804a, 0x804a, 0x804a, 0x804a, 0x804a,
+	0x804a, 0x804a, 0x1078, 0x12d2, 0x1078, 0x578f, 0x1078, 0x5888,
+	0x037e, 0x0d7e, 0x6010, 0xa06d, 0x0040, 0x8068, 0xad84, 0xf000,
+	0x0040, 0x8068, 0x2019, 0x0004, 0x1078, 0x86aa, 0x6013, 0x0000,
+	0x6014, 0xa005, 0x00c0, 0x8066, 0x6017, 0x0014, 0x6003, 0x0007,
+	0x0d7f, 0x037f, 0x007c, 0x807e, 0x809d, 0x8087, 0x80a6, 0x807e,
+	0x807e, 0x807e, 0x807e, 0x807e, 0x807e, 0x807e, 0x807e, 0x807e,
+	0x807e, 0x807e, 0x807e, 0x807e, 0x807e, 0x807e, 0x1078, 0x12d2,
+	0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x1078,
+	0x578f, 0x6010, 0xa080, 0x0013, 0x2004, 0xd0b4, 0x0040, 0x8098,
+	0x6003, 0x0007, 0x2009, 0x0043, 0x1078, 0x6939, 0x0078, 0x809a,
+	0x6003, 0x0002, 0x1078, 0x5888, 0x007c, 0x1078, 0x578f, 0x1078,
+	0x5219, 0x1078, 0x690e, 0x1078, 0x5888, 0x007c, 0x1078, 0x578f,
+	0x2009, 0x0041, 0x0078, 0x819b, 0xa182, 0x0040, 0x0079, 0x80b0,
+	0x80c3, 0x80c5, 0x80c3, 0x80c3, 0x80c3, 0x80c3, 0x80c3, 0x80c6,
+	0x80c3, 0x80c3, 0x80c3, 0x80c3, 0x80c3, 0x80c3, 0x80c3, 0x80c3,
+	0x80c3, 0x80c3, 0x80c3, 0x1078, 0x12d2, 0x007c, 0x6003, 0x0004,
+	0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x1594,
+	0x007c, 0xa182, 0x0040, 0x0079, 0x80d5, 0x80e8, 0x80e8, 0x80e8,
+	0x80e8, 0x80e8, 0x80e8, 0x80e8, 0x80e8, 0x80e8, 0x80ea, 0x810d,
+	0x80e8, 0x80e8, 0x80e8, 0x80e8, 0x810d, 0x80e8, 0x80e8, 0x80e8,
+	0x1078, 0x12d2, 0x1078, 0x5837, 0x1078, 0x5948, 0x6010, 0x0d7e,
+	0x2068, 0x684c, 0xd0fc, 0x0040, 0x8100, 0xa08c, 0x0003, 0xa18e,
+	0x0002, 0x0040, 0x8106, 0x2009, 0x0041, 0x0d7f, 0x0078, 0x819b,
+	0x6003, 0x0007, 0x1078, 0x5219, 0x0d7f, 0x007c, 0x1078, 0x5219,
+	0x1078, 0x690e, 0x0d7f, 0x0078, 0x8105, 0x037e, 0x1078, 0x5837,
+	0x1078, 0x5948, 0x6010, 0x0d7e, 0x2068, 0x2019, 0x0004, 0x1078,
+	0x86aa, 0x1078, 0x79a8, 0x6017, 0x0028, 0x0d7f, 0x037f, 0x007c,
+	0xa186, 0x0013, 0x00c0, 0x812e, 0x6004, 0xa086, 0x0042, 0x10c0,
+	0x12d2, 0x1078, 0x578f, 0x1078, 0x5888, 0x007c, 0xa186, 0x0027,
+	0x0040, 0x8136, 0xa186, 0x0014, 0x00c0, 0x8146, 0x6004, 0xa086,
+	0x0042, 0x10c0, 0x12d2, 0x2001, 0x0007, 0x1078, 0x3f2c, 0x1078,
+	0x578f, 0x1078, 0x79a8, 0x1078, 0x5888, 0x007c, 0xa182, 0x0040,
+	0x0079, 0x814a, 0x815d, 0x815d, 0x815d, 0x815d, 0x815d, 0x815d,
+	0x815d, 0x815f, 0x816b, 0x815d, 0x815d, 0x815d, 0x815d, 0x815d,
+	0x815d, 0x815d, 0x815d, 0x815d, 0x815d, 0x1078, 0x12d2, 0x037e,
+	0x047e, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x1594,
+	0x047f, 0x037f, 0x007c, 0x6010, 0x0d7e, 0x2068, 0x6810, 0x6a14,
+	0xa20d, 0x00c0, 0x8182, 0x684c, 0xd0fc, 0x0040, 0x817c, 0x2009,
+	0x0041, 0x0d7f, 0x0078, 0x819b, 0x6003, 0x0007, 0x1078, 0x5219,
+	0x0d7f, 0x007c, 0x6003, 0x0006, 0x1078, 0x818a, 0x1078, 0x521b,
+	0x0d7f, 0x007c, 0xd2fc, 0x0040, 0x8196, 0x8002, 0x8000, 0x8212,
+	0xa291, 0x0000, 0x2009, 0x0009, 0x0078, 0x8198, 0x2009, 0x0015,
+	0x6a6a, 0x6866, 0x007c, 0xa182, 0x0040, 0x0079, 0x819f, 0x81b2,
+	0x81b4, 0x81c0, 0x81cc, 0x81b2, 0x81b2, 0x81b2, 0x81db, 0x81b2,
+	0x81b2, 0x81b2, 0x81b2, 0x81b2, 0x81b2, 0x81b2, 0x81b2, 0x81b2,
+	0x81b2, 0x81b2, 0x1078, 0x12d2, 0x6003, 0x0001, 0x6106, 0x1078,
+	0x5399, 0x127e, 0x2091, 0x8000, 0x1078, 0x5888, 0x127f, 0x007c,
+	0x6003, 0x0001, 0x6106, 0x1078, 0x5399, 0x127e, 0x2091, 0x8000,
+	0x1078, 0x5888, 0x127f, 0x007c, 0x6003, 0x0003, 0x6106, 0x2c10,
+	0x1078, 0x1b07, 0x127e, 0x2091, 0x8000, 0x1078, 0x5405, 0x1078,
+	0x5948, 0x127f, 0x007c, 0xa016, 0x1078, 0x1594, 0x007c, 0x127e,
+	0x2091, 0x8000, 0x037e, 0x0d7e, 0xa182, 0x0040, 0x1079, 0x81ec,
+	0x0d7f, 0x037f, 0x127f, 0x007c, 0x81fc, 0x81fe, 0x8213, 0x8232,
+	0x81fc, 0x81fc, 0x81fc, 0x824a, 0x81fc, 0x81fc, 0x81fc, 0x81fc,
+	0x81fc, 0x81fc, 0x81fc, 0x81fc, 0x1078, 0x12d2, 0x6010, 0x2068,
+	0x684c, 0xd0fc, 0x0040, 0x8228, 0xa09c, 0x0003, 0xa39e, 0x0003,
+	0x0040, 0x8228, 0x6003, 0x0001, 0x6106, 0x1078, 0x5399, 0x1078,
+	0x5888, 0x0078, 0x824d, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0040,
+	0x8228, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0040, 0x8228, 0x6003,
+	0x0001, 0x6106, 0x1078, 0x5399, 0x1078, 0x5888, 0x0078, 0x824d,
+	0x6013, 0x0000, 0x6017, 0x0000, 0x2019, 0x0004, 0x1078, 0x86aa,
+	0x0078, 0x824d, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0040, 0x8228,
+	0xa09c, 0x0003, 0xa39e, 0x0003, 0x0040, 0x8228, 0x6003, 0x0003,
+	0x6106, 0x2c10, 0x1078, 0x1b07, 0x1078, 0x5405, 0x1078, 0x5948,
+	0x0078, 0x824d, 0xa016, 0x1078, 0x1594, 0x007c, 0x1078, 0x578f,
+	0x6110, 0x81ff, 0x0040, 0x825d, 0x0d7e, 0x2168, 0x037e, 0x2019,
+	0x0029, 0x1078, 0x86aa, 0x037f, 0x0d7f, 0x1078, 0x79a8, 0x1078,
+	0x5888, 0x007c, 0x1078, 0x5837, 0x6110, 0x81ff, 0x0040, 0x8271,
+	0x0d7e, 0x2168, 0x037e, 0x2019, 0x0029, 0x1078, 0x86aa, 0x037f,
+	0x0d7f, 0x1078, 0x79a8, 0x1078, 0x5948, 0x007c, 0xa182, 0x0085,
+	0x0079, 0x827a, 0x8281, 0x8281, 0x8281, 0x8283, 0x8281, 0x8281,
+	0x8281, 0x1078, 0x12d2, 0x027e, 0x0e7e, 0x1078, 0x8727, 0x0040,
+	0x828d, 0x1078, 0x690e, 0x0078, 0x82a9, 0x2071, 0x8d80, 0x7224,
+	0x6212, 0x7220, 0x1078, 0x8575, 0x0040, 0x829a, 0x6007, 0x0086,
+	0x0078, 0x82a3, 0x6007, 0x0087, 0x7224, 0xa296, 0xffff, 0x00c0,
+	0x82a3, 0x6007, 0x0086, 0x6003, 0x0001, 0x1078, 0x5399, 0x1078,
+	0x5888, 0x0e7f, 0x027f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x82bd,
+	0x6004, 0xa08a, 0x0085, 0x1048, 0x12d2, 0xa08a, 0x008c, 0x10c8,
+	0x12d2, 0xa082, 0x0085, 0x0079, 0x82d4, 0xa186, 0x0027, 0x0040,
+	0x82c9, 0xa186, 0x0014, 0x0040, 0x82c9, 0x1078, 0x6950, 0x0078,
+	0x82d3, 0x2001, 0x0007, 0x1078, 0x3f2c, 0x1078, 0x578f, 0x1078,
+	0x79a8, 0x1078, 0x5888, 0x007c, 0x82db, 0x82dd, 0x82dd, 0x82db,
+	0x82db, 0x82db, 0x82db, 0x1078, 0x12d2, 0x1078, 0x578f, 0x1078,
+	0x690e, 0x1078, 0x5888, 0x007c, 0xa182, 0x0085, 0x1048, 0x12d2,
+	0xa182, 0x008c, 0x10c8, 0x12d2, 0xa182, 0x0085, 0x0079, 0x82f0,
+	0x82f7, 0x82f7, 0x82f7, 0x82f9, 0x82f7, 0x82f7, 0x82f7, 0x1078,
+	0x12d2, 0x007c, 0xa186, 0x0013, 0x0040, 0x830a, 0xa186, 0x0014,
+	0x0040, 0x830a, 0xa186, 0x0027, 0x0040, 0x830a, 0x1078, 0x6950,
+	0x0078, 0x8310, 0x1078, 0x578f, 0x1078, 0x79a8, 0x1078, 0x5888,
+	0x007c, 0x037e, 0x2019, 0x000b, 0x1078, 0x831c, 0x601f, 0x0006,
+	0x6003, 0x0007, 0x037f, 0x007c, 0x127e, 0x037e, 0x087e, 0x2091,
+	0x8000, 0x2c40, 0x1078, 0x6614, 0x00c0, 0x834b, 0x1078, 0x66be,
+	0x00c0, 0x834b, 0x6000, 0xa086, 0x0000, 0x0040, 0x834b, 0x601c,
+	0xa086, 0x0007, 0x0040, 0x834b, 0x0d7e, 0x6000, 0xa086, 0x0004,
+	0x00c0, 0x833e, 0x601f, 0x0007, 0x1078, 0x16af, 0x6010, 0x2068,
+	0x1078, 0x77ed, 0x0040, 0x8346, 0x1078, 0x86aa, 0x0d7f, 0x6013,
 	0x0000, 0x601f, 0x0007, 0x087f, 0x037f, 0x127f, 0x007c, 0x0f7e,
-	0x0c7e, 0x037e, 0x157e, 0x2079, 0x7c80, 0x7838, 0xa08c, 0x00ff,
-	0x783c, 0x1078, 0x207f, 0x00c0, 0x734e, 0x017e, 0x0c7e, 0x1078,
-	0x384c, 0x00c0, 0x734e, 0x2011, 0x7c90, 0xac98, 0x000a, 0x20a9,
-	0x0004, 0x1078, 0x6280, 0x00c0, 0x734e, 0x017f, 0x027f, 0x027e,
-	0x017e, 0x2019, 0x0029, 0x1078, 0x5ba2, 0x1078, 0x4a7e, 0x1078,
-	0x49c1, 0x017f, 0x1078, 0x747b, 0x1078, 0x3a36, 0x017f, 0x1078,
-	0x3637, 0x6612, 0x6516, 0xa006, 0x0078, 0x7350, 0x0c7f, 0x017f,
-	0x157f, 0x037f, 0x0c7f, 0x0f7f, 0x007c, 0x0c7e, 0x0d7e, 0x017e,
-	0x2009, 0x771e, 0x2104, 0xa086, 0x0074, 0x00c0, 0x73ac, 0x2069,
-	0x7c8e, 0x690c, 0xa182, 0x0100, 0x0048, 0x739c, 0x6908, 0xa184,
-	0x8000, 0x0040, 0x73a8, 0xa184, 0x0800, 0x0040, 0x73a8, 0x6910,
-	0xa18a, 0x0001, 0x0048, 0x73a0, 0x6914, 0x2069, 0x7cae, 0x6904,
-	0x81ff, 0x00c0, 0x7394, 0x690c, 0xa182, 0x0100, 0x0048, 0x739c,
-	0x6908, 0x81ff, 0x00c0, 0x7398, 0x6910, 0xa18a, 0x0001, 0x0048,
-	0x73a0, 0x6918, 0xa18a, 0x0001, 0x0048, 0x73a8, 0x0078, 0x73b2,
-	0x6013, 0x0100, 0x0078, 0x73ae, 0x6013, 0x0300, 0x0078, 0x73ae,
-	0x6013, 0x0500, 0x0078, 0x73ae, 0x6013, 0x0700, 0x0078, 0x73ae,
-	0x6013, 0x0900, 0x0078, 0x73ae, 0x6013, 0x0b00, 0x0078, 0x73ae,
-	0x6013, 0x0f00, 0x0078, 0x73ae, 0x6013, 0x2d00, 0xa085, 0x0001,
-	0x0078, 0x73b3, 0xa006, 0x017f, 0x0d7f, 0x0c7f, 0x007c, 0x0c7e,
-	0x0d7e, 0x027e, 0x037e, 0x157e, 0x6218, 0x2268, 0x6b04, 0xa394,
-	0x00ff, 0xa286, 0x0006, 0x0040, 0x73db, 0xa286, 0x0004, 0x0040,
-	0x73db, 0xa394, 0xff00, 0x8217, 0xa286, 0x0006, 0x0040, 0x73db,
-	0xa286, 0x0004, 0x0040, 0x73db, 0x0c7e, 0x2d60, 0x1078, 0x385e,
-	0x0c7f, 0x0078, 0x740e, 0x2011, 0x7c96, 0xad98, 0x000a, 0x20a9,
-	0x0004, 0x1078, 0x6280, 0x00c0, 0x740f, 0x2011, 0x7c9a, 0xad98,
-	0x0006, 0x20a9, 0x0004, 0x1078, 0x6280, 0x00c0, 0x740f, 0x047e,
-	0x017e, 0x6aa0, 0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, 0x7752,
-	0x210c, 0xd1a4, 0x0040, 0x7403, 0x2009, 0x0029, 0x1078, 0x7641,
-	0x6800, 0xc0e5, 0x6802, 0x2019, 0x0029, 0x1078, 0x4a7e, 0x1078,
-	0x49c1, 0x2c08, 0x1078, 0x747b, 0x017f, 0x047f, 0xa006, 0x157f,
-	0x037f, 0x027f, 0x0d7f, 0x0c7f, 0x007c, 0x0d7e, 0x2069, 0x7c8e,
-	0x6800, 0xa086, 0x0800, 0x0040, 0x7421, 0x6013, 0x0000, 0x0078,
-	0x7422, 0xa006, 0x0d7f, 0x007c, 0x0c7e, 0x0f7e, 0x017e, 0x027e,
-	0x037e, 0x157e, 0x2079, 0x7c8c, 0x7930, 0x7834, 0x1078, 0x207f,
-	0x00c0, 0x7448, 0x1078, 0x384c, 0x00c0, 0x7448, 0x2011, 0x7c90,
-	0xac98, 0x000a, 0x20a9, 0x0004, 0x1078, 0x6280, 0x00c0, 0x7448,
-	0x2011, 0x7c94, 0xac98, 0x0006, 0x20a9, 0x0004, 0x1078, 0x6280,
-	0x157f, 0x037f, 0x027f, 0x017f, 0x0f7f, 0x0c7f, 0x007c, 0x0c7e,
-	0x007e, 0x017e, 0x027e, 0x037e, 0x157e, 0x2011, 0x7c83, 0x2204,
-	0x8211, 0x220c, 0x1078, 0x207f, 0x00c0, 0x7474, 0x1078, 0x384c,
-	0x00c0, 0x7474, 0x2011, 0x7c96, 0xac98, 0x000a, 0x20a9, 0x0004,
-	0x1078, 0x6280, 0x00c0, 0x7474, 0x2011, 0x7c9a, 0xac98, 0x0006,
-	0x20a9, 0x0004, 0x1078, 0x6280, 0x157f, 0x037f, 0x027f, 0x017f,
-	0x007f, 0x0c7f, 0x007c, 0x0e7e, 0x0c7e, 0x077e, 0x067e, 0x057e,
-	0x047e, 0x027e, 0x127e, 0x2091, 0x8000, 0x2029, 0x793f, 0x252c,
-	0x2021, 0x7945, 0x2424, 0x2061, 0x7e00, 0x2071, 0x7700, 0x7644,
-	0x7060, 0x8001, 0xa602, 0x00c8, 0x74e0, 0x2100, 0xac06, 0x0040,
-	0x74d6, 0x1078, 0x7659, 0x0040, 0x74d6, 0x671c, 0xa786, 0x0001,
-	0x0040, 0x74f5, 0xa786, 0x0007, 0x0040, 0x74d6, 0x2500, 0xac06,
-	0x0040, 0x74d6, 0x2400, 0xac06, 0x0040, 0x74d6, 0x1078, 0x766d,
-	0x00c0, 0x74d6, 0x0d7e, 0x6000, 0xa086, 0x0004, 0x00c0, 0x74bc,
-	0x017e, 0x1078, 0x166e, 0x017f, 0x6010, 0x2068, 0x1078, 0x6a58,
-	0x0040, 0x74d3, 0xa786, 0x0003, 0x00c0, 0x74e9, 0x6837, 0x0103,
-	0x6b4a, 0x6847, 0x0000, 0x017e, 0x1078, 0x6c54, 0x1078, 0x3b92,
-	0x017f, 0x1078, 0x6ba9, 0x0d7f, 0x1078, 0x6bb6, 0xace0, 0x0008,
-	0x2001, 0x7715, 0x2004, 0xac02, 0x00c8, 0x74e0, 0x0078, 0x748d,
-	0x127f, 0x027f, 0x047f, 0x057f, 0x067f, 0x077f, 0x0c7f, 0x0e7f,
-	0x007c, 0xa786, 0x0006, 0x00c0, 0x74c6, 0xa386, 0x0005, 0x0040,
-	0x74d6, 0x1078, 0x75fd, 0x0078, 0x74d3, 0x1078, 0x766d, 0x00c0,
-	0x74d6, 0xa180, 0x0001, 0x2004, 0xa086, 0x0018, 0x00c0, 0x74d6,
-	0x6000, 0xa086, 0x0002, 0x00c0, 0x74d6, 0x1078, 0x6bcf, 0x0040,
-	0x7511, 0x1078, 0x6be3, 0x00c0, 0x74d6, 0x1078, 0x5f6d, 0x0078,
-	0x7513, 0x1078, 0x22d7, 0x1078, 0x6bb6, 0x0078, 0x74d6, 0x0c7e,
-	0x0e7e, 0x017e, 0x2c08, 0x2170, 0x1078, 0x7614, 0x017f, 0x0040,
-	0x7526, 0x601c, 0xa084, 0x000f, 0x1079, 0x7529, 0x0e7f, 0x0c7f,
-	0x007c, 0x7531, 0x7531, 0x7531, 0x7531, 0x7531, 0x7531, 0x7533,
-	0x7531, 0xa006, 0x007c, 0x047e, 0x017e, 0x7018, 0xa080, 0x0028,
-	0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00, 0x2009, 0x0020, 0x1078,
-	0x7641, 0x017f, 0x047f, 0x037e, 0x2019, 0x0002, 0x1078, 0x72e6,
-	0x037f, 0xa085, 0x0001, 0x007c, 0x2001, 0x0001, 0x1078, 0x37e0,
-	0x157e, 0x017e, 0x027e, 0x037e, 0x20a9, 0x0004, 0x2019, 0x7705,
-	0x2011, 0x7c96, 0x1078, 0x6280, 0x037f, 0x027f, 0x017f, 0x157f,
-	0xa005, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x077e, 0x067e, 0x027e,
-	0x127e, 0x2091, 0x8000, 0x2061, 0x7e00, 0x2079, 0x0001, 0x8fff,
-	0x0040, 0x75bd, 0x2071, 0x7700, 0x7644, 0x7060, 0x8001, 0xa602,
-	0x00c8, 0x75bd, 0x88ff, 0x0040, 0x7583, 0x2800, 0xac06, 0x00c0,
-	0x75b3, 0x2079, 0x0000, 0x1078, 0x7659, 0x0040, 0x75b3, 0x2400,
-	0xac06, 0x0040, 0x75b3, 0x671c, 0xa786, 0x0006, 0x00c0, 0x75b3,
-	0xa786, 0x0007, 0x0040, 0x75b3, 0x88ff, 0x00c0, 0x759b, 0x6018,
-	0xa206, 0x00c0, 0x75b3, 0x0d7e, 0x6000, 0xa086, 0x0004, 0x00c0,
-	0x75a3, 0x1078, 0x166e, 0x6010, 0x2068, 0x1078, 0x6a58, 0x0040,
-	0x75ad, 0x047e, 0x1078, 0x75fd, 0x047f, 0x0d7f, 0x1078, 0x6bb6,
-	0x88ff, 0x00c0, 0x75c6, 0xace0, 0x0008, 0x2001, 0x7715, 0x2004,
-	0xac02, 0x00c8, 0x75bd, 0x0078, 0x756f, 0xa006, 0x127f, 0x027f,
-	0x067f, 0x077f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0xa8c5, 0x0001,
-	0x0078, 0x75be, 0x087e, 0x2041, 0x0000, 0x2c20, 0x2019, 0x0002,
-	0x6218, 0x1078, 0x5a2d, 0x1078, 0x5ace, 0x1078, 0x7562, 0x087f,
-	0x007c, 0x027e, 0x047e, 0x087e, 0x0c7e, 0x157e, 0x2c20, 0x20a9,
-	0x007f, 0x2009, 0x0000, 0x017e, 0x037e, 0x1078, 0x384c, 0x00c0,
-	0x75f2, 0x2c10, 0x2041, 0x0000, 0x1078, 0x5a2d, 0x1078, 0x5ace,
-	0x1078, 0x7562, 0x037f, 0x017f, 0x8108, 0x00f0, 0x75e3, 0x157f,
-	0x0c7f, 0x087f, 0x047f, 0x027f, 0x007c, 0x017e, 0x0f7e, 0x8dff,
-	0x0040, 0x7611, 0x6800, 0xa07d, 0x0040, 0x760e, 0x6803, 0x0000,
-	0x6b52, 0x1078, 0x3b92, 0x2f68, 0x0078, 0x7602, 0x6b52, 0x1078,
-	0x3b92, 0x0f7f, 0x017f, 0x007c, 0x0e7e, 0x047e, 0x037e, 0x2061,
-	0x7e00, 0x2071, 0x7700, 0x7444, 0x7060, 0x8001, 0xa402, 0x00c8,
-	0x763c, 0x2100, 0xac06, 0x0040, 0x762e, 0x6000, 0xa086, 0x0000,
-	0x0040, 0x762e, 0x6008, 0xa206, 0x0040, 0x7638, 0xace0, 0x0008,
-	0x2001, 0x7715, 0x2004, 0xac02, 0x00c8, 0x763c, 0x0078, 0x7619,
-	0xa085, 0x0001, 0x0078, 0x763d, 0xa006, 0x037f, 0x047f, 0x0e7f,
-	0x007c, 0x0d7e, 0x007e, 0x1078, 0x1327, 0x007f, 0x1040, 0x12cd,
-	0x6837, 0x010d, 0x6803, 0x0000, 0x683b, 0x0000, 0x685b, 0x0000,
-	0x685e, 0x6956, 0x6c46, 0x684f, 0x0000, 0x1078, 0x3b92, 0x0d7f,
-	0x007c, 0x6700, 0xa786, 0x0000, 0x0040, 0x766c, 0xa786, 0x0001,
-	0x0040, 0x766c, 0xa786, 0x000a, 0x0040, 0x766c, 0xa786, 0x0009,
-	0x0040, 0x766c, 0xa085, 0x0001, 0x007c, 0x0e7e, 0x6018, 0x2070,
-	0x70a0, 0xa206, 0x0e7f, 0x007c, 0x127e, 0x007e, 0x0e7e, 0x2091,
-	0x8000, 0x2071, 0x7740, 0xd5a4, 0x0040, 0x7681, 0x7034, 0x8000,
-	0x7036, 0xd5b4, 0x0040, 0x7687, 0x7030, 0x8000, 0x7032, 0xd5ac,
-	0x0040, 0x768e, 0x2071, 0x774a, 0x1078, 0x76bd, 0x0e7f, 0x007f,
+	0x0c7e, 0x037e, 0x157e, 0x2079, 0x8d80, 0x7938, 0x783c, 0x1078,
+	0x2245, 0x00c0, 0x839d, 0x017e, 0x0c7e, 0x1078, 0x3f8e, 0x00c0,
+	0x839d, 0x2011, 0x8d90, 0xac98, 0x000a, 0x20a9, 0x0004, 0x1078,
+	0x6f0c, 0x00c0, 0x839d, 0x017f, 0x027f, 0x027e, 0x017e, 0x2019,
+	0x0029, 0x1078, 0x6799, 0x1078, 0x54f0, 0x087e, 0x2041, 0x0000,
+	0x1078, 0x5419, 0x087f, 0x017f, 0x087e, 0x2041, 0x0000, 0x1078,
+	0x84d2, 0x087f, 0x1078, 0x418b, 0x027e, 0x6204, 0xa294, 0xff00,
+	0x8217, 0xa286, 0x0006, 0x0040, 0x8391, 0xa286, 0x0004, 0x00c0,
+	0x8394, 0x62a0, 0x1078, 0x2566, 0x027f, 0x017f, 0x1078, 0x3d31,
+	0x6612, 0x6516, 0xa006, 0x0078, 0x839f, 0x0c7f, 0x017f, 0x157f,
+	0x037f, 0x0c7f, 0x0f7f, 0x007c, 0x0c7e, 0x0d7e, 0x017e, 0x2009,
+	0x881f, 0x2104, 0xa086, 0x0074, 0x00c0, 0x83fb, 0x2069, 0x8d8e,
+	0x690c, 0xa182, 0x0100, 0x0048, 0x83eb, 0x6908, 0xa184, 0x8000,
+	0x0040, 0x83f7, 0xa184, 0x0800, 0x0040, 0x83f7, 0x6910, 0xa18a,
+	0x0001, 0x0048, 0x83ef, 0x6914, 0x2069, 0x8dae, 0x6904, 0x81ff,
+	0x00c0, 0x83e3, 0x690c, 0xa182, 0x0100, 0x0048, 0x83eb, 0x6908,
+	0x81ff, 0x00c0, 0x83e7, 0x6910, 0xa18a, 0x0001, 0x0048, 0x83ef,
+	0x6918, 0xa18a, 0x0001, 0x0048, 0x83f7, 0x0078, 0x8401, 0x6013,
+	0x0100, 0x0078, 0x83fd, 0x6013, 0x0300, 0x0078, 0x83fd, 0x6013,
+	0x0500, 0x0078, 0x83fd, 0x6013, 0x0700, 0x0078, 0x83fd, 0x6013,
+	0x0900, 0x0078, 0x83fd, 0x6013, 0x0b00, 0x0078, 0x83fd, 0x6013,
+	0x0f00, 0x0078, 0x83fd, 0x6013, 0x2d00, 0xa085, 0x0001, 0x0078,
+	0x8402, 0xa006, 0x017f, 0x0d7f, 0x0c7f, 0x007c, 0x0c7e, 0x0d7e,
+	0x027e, 0x037e, 0x157e, 0x6218, 0x2268, 0x6b04, 0xa394, 0x00ff,
+	0xa286, 0x0006, 0x0040, 0x842a, 0xa286, 0x0004, 0x0040, 0x842a,
+	0xa394, 0xff00, 0x8217, 0xa286, 0x0006, 0x0040, 0x842a, 0xa286,
+	0x0004, 0x0040, 0x842a, 0x0c7e, 0x2d60, 0x1078, 0x3fa0, 0x0c7f,
+	0x0078, 0x8465, 0x2011, 0x8d96, 0xad98, 0x000a, 0x20a9, 0x0004,
+	0x1078, 0x6f0c, 0x00c0, 0x8466, 0x2011, 0x8d9a, 0xad98, 0x0006,
+	0x20a9, 0x0004, 0x1078, 0x6f0c, 0x00c0, 0x8466, 0x047e, 0x017e,
+	0x6aa0, 0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, 0x8852, 0x210c,
+	0xd1a4, 0x0040, 0x8452, 0x2009, 0x0029, 0x1078, 0x86f5, 0x6800,
+	0xc0e5, 0x6802, 0x2019, 0x0029, 0x1078, 0x54f0, 0x087e, 0x2041,
+	0x0000, 0x1078, 0x5419, 0x2c08, 0x1078, 0x84d2, 0x087f, 0x2001,
+	0x0007, 0x1078, 0x3f2c, 0x017f, 0x047f, 0xa006, 0x157f, 0x037f,
+	0x027f, 0x0d7f, 0x0c7f, 0x007c, 0x0d7e, 0x2069, 0x8d8e, 0x6800,
+	0xa086, 0x0800, 0x0040, 0x8478, 0x6013, 0x0000, 0x0078, 0x8479,
+	0xa006, 0x0d7f, 0x007c, 0x0c7e, 0x0f7e, 0x017e, 0x027e, 0x037e,
+	0x157e, 0x2079, 0x8d8c, 0x7930, 0x7834, 0x1078, 0x2245, 0x00c0,
+	0x849f, 0x1078, 0x3f8e, 0x00c0, 0x849f, 0x2011, 0x8d90, 0xac98,
+	0x000a, 0x20a9, 0x0004, 0x1078, 0x6f0c, 0x00c0, 0x849f, 0x2011,
+	0x8d94, 0xac98, 0x0006, 0x20a9, 0x0004, 0x1078, 0x6f0c, 0x157f,
+	0x037f, 0x027f, 0x017f, 0x0f7f, 0x0c7f, 0x007c, 0x0c7e, 0x007e,
+	0x017e, 0x027e, 0x037e, 0x157e, 0x2011, 0x8d83, 0x2204, 0x8211,
+	0x220c, 0x1078, 0x2245, 0x00c0, 0x84cb, 0x1078, 0x3f8e, 0x00c0,
+	0x84cb, 0x2011, 0x8d96, 0xac98, 0x000a, 0x20a9, 0x0004, 0x1078,
+	0x6f0c, 0x00c0, 0x84cb, 0x2011, 0x8d9a, 0xac98, 0x0006, 0x20a9,
+	0x0004, 0x1078, 0x6f0c, 0x157f, 0x037f, 0x027f, 0x017f, 0x007f,
+	0x0c7f, 0x007c, 0x0e7e, 0x0c7e, 0x077e, 0x067e, 0x057e, 0x047e,
+	0x027e, 0x127e, 0x2091, 0x8000, 0x2029, 0x8aab, 0x252c, 0x2021,
+	0x8ab1, 0x2424, 0x2061, 0x8f00, 0x2071, 0x8800, 0x7644, 0x7060,
+	0x8001, 0xa602, 0x00c8, 0x853e, 0x2100, 0xac06, 0x0040, 0x8534,
+	0x1078, 0x870c, 0x0040, 0x8534, 0x671c, 0xa786, 0x0001, 0x0040,
+	0x8553, 0xa786, 0x0007, 0x0040, 0x8534, 0x2500, 0xac06, 0x0040,
+	0x8534, 0x2400, 0xac06, 0x0040, 0x8534, 0x1078, 0x8720, 0x00c0,
+	0x8534, 0x88ff, 0x0040, 0x8510, 0x6020, 0xa906, 0x00c0, 0x8534,
+	0x0d7e, 0x6000, 0xa086, 0x0004, 0x00c0, 0x851a, 0x017e, 0x1078,
+	0x16af, 0x017f, 0x6010, 0x2068, 0x1078, 0x77ed, 0x0040, 0x8531,
+	0xa786, 0x0003, 0x00c0, 0x8547, 0x6837, 0x0103, 0x6b4a, 0x6847,
+	0x0000, 0x017e, 0x1078, 0x7a46, 0x1078, 0x4376, 0x017f, 0x1078,
+	0x799b, 0x0d7f, 0x1078, 0x79a8, 0xace0, 0x000c, 0x2001, 0x8815,
+	0x2004, 0xac02, 0x00c8, 0x853e, 0x0078, 0x84e4, 0x127f, 0x027f,
+	0x047f, 0x057f, 0x067f, 0x077f, 0x0c7f, 0x0e7f, 0x007c, 0xa786,
+	0x0006, 0x00c0, 0x8524, 0xa386, 0x0005, 0x0040, 0x8534, 0x1078,
+	0x86aa, 0x0078, 0x8531, 0x1078, 0x8720, 0x00c0, 0x8534, 0xa180,
+	0x0001, 0x2004, 0xa086, 0x0018, 0x00c0, 0x8534, 0x6000, 0xa086,
+	0x0002, 0x00c0, 0x8534, 0x1078, 0x79c1, 0x0040, 0x856f, 0x1078,
+	0x79d5, 0x00c0, 0x8534, 0x1078, 0x6bc7, 0x0078, 0x8571, 0x1078,
+	0x24e5, 0x1078, 0x79a8, 0x0078, 0x8534, 0x0c7e, 0x0e7e, 0x017e,
+	0x2c08, 0x2170, 0x1078, 0x86c1, 0x017f, 0x0040, 0x8584, 0x601c,
+	0xa084, 0x000f, 0x1079, 0x8587, 0x0e7f, 0x0c7f, 0x007c, 0x858f,
+	0x858f, 0x858f, 0x858f, 0x858f, 0x858f, 0x8591, 0x858f, 0xa006,
+	0x007c, 0x047e, 0x017e, 0x7018, 0xa080, 0x0028, 0x2024, 0xa4a4,
+	0x00ff, 0x8427, 0x2c00, 0x2009, 0x0020, 0x1078, 0x86f5, 0x017f,
+	0x047f, 0x037e, 0x2019, 0x0002, 0x1078, 0x831c, 0x037f, 0xa085,
+	0x0001, 0x007c, 0x2001, 0x0001, 0x1078, 0x3ef1, 0x157e, 0x017e,
+	0x027e, 0x037e, 0x20a9, 0x0004, 0x2019, 0x8805, 0x2011, 0x8d96,
+	0x1078, 0x6f0c, 0x037f, 0x027f, 0x017f, 0x157f, 0xa005, 0x007c,
+	0x0f7e, 0x0e7e, 0x0c7e, 0x077e, 0x067e, 0x027e, 0x127e, 0x2091,
+	0x8000, 0x2061, 0x8f00, 0x2079, 0x0001, 0x8fff, 0x0040, 0x8624,
+	0x2071, 0x8800, 0x7644, 0x7060, 0x8001, 0xa602, 0x00c8, 0x8624,
+	0x88ff, 0x0040, 0x85e1, 0x2800, 0xac06, 0x00c0, 0x861a, 0x2079,
+	0x0000, 0x1078, 0x870c, 0x0040, 0x861a, 0x2400, 0xac06, 0x0040,
+	0x861a, 0x671c, 0xa786, 0x0006, 0x00c0, 0x861a, 0xa786, 0x0007,
+	0x0040, 0x861a, 0x88ff, 0x00c0, 0x8600, 0x6018, 0xa206, 0x00c0,
+	0x861a, 0x85ff, 0x0040, 0x8600, 0x6020, 0xa106, 0x00c0, 0x861a,
+	0x0d7e, 0x6000, 0xa086, 0x0004, 0x00c0, 0x860a, 0x601f, 0x0007,
+	0x1078, 0x16af, 0x6010, 0x2068, 0x1078, 0x77ed, 0x0040, 0x8614,
+	0x047e, 0x1078, 0x86aa, 0x047f, 0x0d7f, 0x1078, 0x79a8, 0x88ff,
+	0x00c0, 0x862d, 0xace0, 0x000c, 0x2001, 0x8815, 0x2004, 0xac02,
+	0x00c8, 0x8624, 0x0078, 0x85cd, 0xa006, 0x127f, 0x027f, 0x067f,
+	0x077f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0xa8c5, 0x0001, 0x0078,
+	0x8625, 0x087e, 0x057e, 0x2041, 0x0000, 0x2029, 0x0001, 0x2c20,
+	0x2019, 0x0002, 0x6218, 0x1078, 0x6614, 0x1078, 0x66be, 0x1078,
+	0x85c0, 0x057f, 0x087f, 0x007c, 0x027e, 0x047e, 0x057e, 0x087e,
+	0x0c7e, 0x157e, 0x2c20, 0x2128, 0x20a9, 0x007f, 0x2009, 0x0000,
+	0x017e, 0x037e, 0x1078, 0x3f8e, 0x00c0, 0x8664, 0x2c10, 0x2041,
+	0x0000, 0x2508, 0x057e, 0x2029, 0x0001, 0x1078, 0x6614, 0x1078,
+	0x66be, 0x1078, 0x85c0, 0x057f, 0x037f, 0x017f, 0x8108, 0x00f0,
+	0x8650, 0x157f, 0x0c7f, 0x087f, 0x057f, 0x047f, 0x027f, 0x007c,
+	0x087e, 0x057e, 0x6218, 0x2041, 0x0000, 0x2029, 0x0001, 0x2019,
+	0x0048, 0x1078, 0x6614, 0x1078, 0x66be, 0x2c20, 0x1078, 0x85c0,
+	0x057f, 0x087f, 0x007c, 0x027e, 0x047e, 0x057e, 0x087e, 0x0c7e,
+	0x157e, 0x2c20, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x037e,
+	0x1078, 0x3f8e, 0x00c0, 0x869e, 0x2c10, 0x2041, 0x0000, 0x2828,
+	0x1078, 0x6614, 0x1078, 0x66be, 0x1078, 0x85c0, 0x037f, 0x017f,
+	0x8108, 0x00f0, 0x868e, 0x157f, 0x0c7f, 0x087f, 0x057f, 0x047f,
+	0x027f, 0x007c, 0x017e, 0x0f7e, 0x8dff, 0x0040, 0x86be, 0x6800,
+	0xa07d, 0x0040, 0x86bb, 0x6803, 0x0000, 0x6b52, 0x1078, 0x4376,
+	0x2f68, 0x0078, 0x86af, 0x6b52, 0x1078, 0x4376, 0x0f7f, 0x017f,
+	0x007c, 0x0e7e, 0x047e, 0x037e, 0x2061, 0x8f00, 0x2071, 0x8800,
+	0x7444, 0x7060, 0x8001, 0xa402, 0x00c8, 0x86f0, 0x2100, 0xac06,
+	0x0040, 0x86e2, 0x6000, 0xa086, 0x0000, 0x0040, 0x86e2, 0x6008,
+	0xa206, 0x00c0, 0x86e2, 0x6018, 0xa1a0, 0x0006, 0x2424, 0xa406,
+	0x0040, 0x86ec, 0xace0, 0x000c, 0x2001, 0x8815, 0x2004, 0xac02,
+	0x00c8, 0x86f0, 0x0078, 0x86c6, 0xa085, 0x0001, 0x0078, 0x86f1,
+	0xa006, 0x037f, 0x047f, 0x0e7f, 0x007c, 0x0d7e, 0x007e, 0x1078,
+	0x132b, 0x007f, 0x1040, 0x12d2, 0x6837, 0x010d, 0x685e, 0x6956,
+	0x6c46, 0x684f, 0x0000, 0xa006, 0x68b2, 0x6802, 0x683a, 0x685a,
+	0x1078, 0x4376, 0x0d7f, 0x007c, 0x6700, 0xa786, 0x0000, 0x0040,
+	0x871f, 0xa786, 0x0001, 0x0040, 0x871f, 0xa786, 0x000a, 0x0040,
+	0x871f, 0xa786, 0x0009, 0x0040, 0x871f, 0xa085, 0x0001, 0x007c,
+	0x0e7e, 0x6018, 0x2070, 0x70a0, 0xa206, 0x0e7f, 0x007c, 0x0e7e,
+	0x6018, 0x2070, 0x7000, 0xd0ec, 0x0e7f, 0x007c, 0x127e, 0x007e,
+	0x0e7e, 0x2091, 0x8000, 0x2071, 0x8840, 0xd5a4, 0x0040, 0x873b,
+	0x7034, 0x8000, 0x7036, 0xd5b4, 0x0040, 0x8741, 0x7030, 0x8000,
+	0x7032, 0xd5ac, 0x0040, 0x8748, 0x2071, 0x884a, 0x1078, 0x8777,
+	0x0e7f, 0x007f, 0x127f, 0x007c, 0x127e, 0x007e, 0x0e7e, 0x2091,
+	0x8000, 0x2071, 0x8840, 0xd5a4, 0x0040, 0x8759, 0x7034, 0x8000,
+	0x7036, 0xd5b4, 0x0040, 0x875f, 0x7030, 0x8000, 0x7032, 0xd5ac,
+	0x0040, 0x8766, 0x2071, 0x884a, 0x1078, 0x8777, 0x0e7f, 0x007f,
 	0x127f, 0x007c, 0x127e, 0x007e, 0x0e7e, 0x2091, 0x8000, 0x2071,
-	0x7740, 0xd5a4, 0x0040, 0x769f, 0x7034, 0x8000, 0x7036, 0xd5b4,
-	0x0040, 0x76a5, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0040, 0x76ac,
-	0x2071, 0x774a, 0x1078, 0x76bd, 0x0e7f, 0x007f, 0x127f, 0x007c,
-	0x127e, 0x007e, 0x0e7e, 0x2091, 0x8000, 0x2071, 0x7742, 0x1078,
-	0x76bd, 0x0e7f, 0x007f, 0x127f, 0x007c, 0x2e04, 0x8000, 0x2072,
-	0x00c8, 0x76c6, 0x8e70, 0x2e04, 0x8000, 0x2072, 0x007c, 0x0e7e,
-	0x2071, 0x7740, 0x1078, 0x76bd, 0x0e7f, 0x007c, 0x0e7e, 0x2071,
-	0x7744, 0x1078, 0x76bd, 0x0e7f, 0x007c, 0x0001, 0x0002, 0x0004,
-	0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400,
-	0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0x687d
+	0x8842, 0x1078, 0x8777, 0x0e7f, 0x007f, 0x127f, 0x007c, 0x2e04,
+	0x8000, 0x2072, 0x00c8, 0x8780, 0x8e70, 0x2e04, 0x8000, 0x2072,
+	0x007c, 0x0e7e, 0x2071, 0x8840, 0x1078, 0x8777, 0x0e7f, 0x007c,
+	0x0e7e, 0x2071, 0x8844, 0x1078, 0x8777, 0x0e7f, 0x007c, 0x0001,
+	0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100,
+	0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0x6f37
 };
 
-/*
- *	Firmware Version 2.00.16 (09:36 Jun 29, 1999)
- */
 
 unsigned short risc_code2200[] = { 
-	0x0470, 0x0000, 0x0000, 0x81bd, 0x0000, 0x0002, 0x0000, 0x0010,
-	0x0027, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2031, 0x3939,
+	0x0470, 0x0000, 0x0000, 0x7a68, 0x0000, 0x0002, 0x0000, 0x0028,
+	0x0007, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2031, 0x3939,
 	0x3920, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241,
 	0x5449, 0x4f4e, 0x2049, 0x5350, 0x3232, 0x3030, 0x2046, 0x6972,
 	0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030,
-	0x322e, 0x3030, 0x2e31, 0x3620, 0x2020, 0x2020, 0x2400, 0x20c1,
-	0x0005, 0x2001, 0x017f, 0x2003, 0x0000, 0x20c9, 0x96ff, 0x2091,
-	0x2000, 0x2059, 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x2490,
-	0x2051, 0x9200, 0x2a70, 0x2029, 0xb100, 0x2031, 0xffff, 0x2039,
-	0xb0f5, 0x2021, 0x0200, 0x0804, 0x136b, 0x20a1, 0x91bd, 0xa00e,
-	0x20a9, 0x0743, 0x41a4, 0x3400, 0x755e, 0x7662, 0x775a, 0x7466,
-	0x746a, 0x20a1, 0x9900, 0x7160, 0x810d, 0x810d, 0x810d, 0x810d,
+	0x322e, 0x3030, 0x2e34, 0x3020, 0x2020, 0x2020, 0x2400, 0x20c1,
+	0x0005, 0x2001, 0x017f, 0x2003, 0x0000, 0x20c9, 0x8fff, 0x2091,
+	0x2000, 0x2059, 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x236e,
+	0x2051, 0x8b00, 0x2a70, 0x2029, 0xaa00, 0x2031, 0xffff, 0x2039,
+	0xa9f5, 0x2021, 0x0200, 0x0804, 0x137d, 0x20a1, 0x8a68, 0xa00e,
+	0x20a9, 0x0798, 0x41a4, 0x3400, 0x755e, 0x7662, 0x775a, 0x7466,
+	0x746a, 0x20a1, 0x9200, 0x7160, 0x810d, 0x810d, 0x810d, 0x810d,
 	0xa18c, 0x000f, 0x2001, 0x0009, 0xa112, 0xa00e, 0x21a8, 0x41a4,
 	0x3400, 0x8211, 0x1dd8, 0x7160, 0x3400, 0xa102, 0x0120, 0x0218,
-	0x20a8, 0xa00e, 0x41a4, 0x3800, 0xd08c, 0x01d8, 0x2009, 0x9200,
+	0x20a8, 0xa00e, 0x41a4, 0x3800, 0xd08c, 0x01d8, 0x2009, 0x8b00,
 	0x810d, 0x810d, 0x810d, 0x810d, 0xa18c, 0x000f, 0x2001, 0x0001,
 	0xa112, 0x20a1, 0x1000, 0xa00e, 0x21a8, 0x41a4, 0x8211, 0x1de0,
-	0x2009, 0x9200, 0x3400, 0xa102, 0x0120, 0x0218, 0x20a8, 0xa00e,
-	0x41a4, 0x080c, 0x1322, 0x080c, 0x14b6, 0x080c, 0x1649, 0x080c,
-	0x1c81, 0x080c, 0x41d4, 0x080c, 0x7494, 0x080c, 0x1439, 0x080c,
-	0x2819, 0x080c, 0x4e42, 0x080c, 0x4757, 0x080c, 0x5874, 0x080c,
-	0x56c0, 0x080c, 0x2138, 0x080c, 0x5ed0, 0x080c, 0x532f, 0x080c,
-	0x206a, 0x080c, 0x210e, 0x2091, 0x3009, 0x7823, 0x0000, 0x1004,
-	0x10c7, 0x7820, 0xa086, 0x0002, 0x1150, 0x7823, 0x4000, 0x0e04,
-	0x10bf, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70,
-	0x7003, 0x0000, 0x2a70, 0x7000, 0xa08e, 0x0003, 0x1168, 0x080c,
-	0x36d4, 0x080c, 0x2840, 0x080c, 0x4e90, 0x080c, 0x493b, 0x080c,
-	0x58b1, 0x080c, 0x56d8, 0x0c70, 0x000b, 0x0c88, 0x10e8, 0x10e9,
-	0x11b8, 0x10e6, 0x123f, 0x131f, 0x1320, 0x1321, 0x080c, 0x13fe,
-	0x0005, 0x0126, 0x00f6, 0x2091, 0x8000, 0x080c, 0x4dc5, 0x0150,
-	0x080c, 0x4deb, 0x11f8, 0x2079, 0x0100, 0x7828, 0xa085, 0x1800,
-	0x782a, 0x00c0, 0x080c, 0x4d10, 0x7088, 0xa086, 0x0026, 0x1904,
-	0x119d, 0x2079, 0x0100, 0x7827, 0xffff, 0x782b, 0x1c2b, 0x2011,
-	0x4ce2, 0x080c, 0x5731, 0x2011, 0x8030, 0x2019, 0x0000, 0x7087,
-	0x0000, 0x00a8, 0x080c, 0x3a6a, 0x2079, 0x0100, 0x7844, 0xa005,
-	0x1904, 0x119d, 0x2011, 0x40af, 0x080c, 0x5731, 0x780f, 0x03ff,
+	0x2009, 0x8b00, 0x3400, 0xa102, 0x0120, 0x0218, 0x20a8, 0xa00e,
+	0x41a4, 0x080c, 0x1334, 0x080c, 0x14c2, 0x080c, 0x165b, 0x080c,
+	0x1bc1, 0x080c, 0x410c, 0x080c, 0x6cba, 0x080c, 0x144b, 0x080c,
+	0x273d, 0x080c, 0x4d5e, 0x080c, 0x45ef, 0x080c, 0x559c, 0x080c,
+	0x2029, 0x080c, 0x577b, 0x080c, 0x5212, 0x080c, 0x1f59, 0x080c,
+	0x1ffd, 0x2091, 0x3009, 0x7823, 0x0000, 0x1004, 0x10c5, 0x7820,
+	0xa086, 0x0002, 0x1150, 0x7823, 0x4000, 0x0e04, 0x10bd, 0x781b,
+	0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70, 0x7003, 0x0000,
+	0x2a70, 0x7000, 0xa08e, 0x0003, 0x1158, 0x080c, 0x3653, 0x080c,
+	0x2764, 0x080c, 0x4dac, 0x080c, 0x4788, 0x080c, 0x55b4, 0x0c80,
+	0x000b, 0x0c98, 0x10e4, 0x10e5, 0x11c0, 0x10e2, 0x1251, 0x1331,
+	0x1332, 0x1333, 0x080c, 0x1410, 0x0005, 0x0126, 0x00f6, 0x2091,
+	0x8000, 0x080c, 0x4c42, 0x0150, 0x080c, 0x4c68, 0x1518, 0x2079,
+	0x0100, 0x7828, 0xa085, 0x1800, 0x782a, 0x00e0, 0x080c, 0x4b8b,
+	0x7088, 0xa086, 0x0027, 0x1904, 0x11a5, 0x2079, 0x0100, 0x7827,
+	0xffff, 0x782b, 0x1e2b, 0x2011, 0x4b5d, 0x080c, 0x560d, 0x2011,
+	0x3fe7, 0x080c, 0x560d, 0x2011, 0x8030, 0x2019, 0x0000, 0x7087,
+	0x0000, 0x00a8, 0x080c, 0x399f, 0x2079, 0x0100, 0x7844, 0xa005,
+	0x1904, 0x11a5, 0x2011, 0x3fe7, 0x080c, 0x560d, 0x780f, 0x00ff,
 	0x7840, 0xa084, 0xfffb, 0x7842, 0x2011, 0x8010, 0x73c4, 0x080c,
-	0x3698, 0x080c, 0x706b, 0x2011, 0x0004, 0x080c, 0x82f3, 0x080c,
-	0x46a8, 0x080c, 0x4dc5, 0x0158, 0x080c, 0x41bd, 0x0140, 0x7087,
-	0x0001, 0x70bf, 0x0000, 0x080c, 0x3bfd, 0x0804, 0x119d, 0x70d3,
-	0x0000, 0x70cf, 0x0000, 0x706f, 0x0000, 0x7073, 0x0000, 0x080c,
-	0x11a0, 0x72c8, 0x080c, 0x4dc5, 0x1160, 0x2011, 0x0000, 0x2001,
-	0x0204, 0x2004, 0x2019, 0x94c8, 0x201a, 0x704f, 0xffff, 0x7053,
-	0x00ef, 0x2079, 0x9251, 0x7804, 0xd0ac, 0x0108, 0xc295, 0x72ca,
-	0x080c, 0x4dc5, 0x0118, 0xa296, 0x0004, 0x0500, 0x2011, 0x0001,
-	0x080c, 0x82f3, 0x080c, 0x854a, 0x7097, 0x0000, 0x709b, 0xffff,
-	0x7003, 0x0002, 0x00fe, 0x080c, 0x251c, 0x2011, 0x0005, 0x080c,
-	0x718f, 0x080c, 0x6462, 0x080c, 0x4dc5, 0x0130, 0x00c6, 0x2061,
-	0x0100, 0x60e3, 0x0008, 0x00ce, 0x012e, 0x00c8, 0x080c, 0x854a,
+	0x3617, 0x7238, 0xc284, 0x723a, 0x2001, 0x8b0c, 0x200c, 0xc1ac,
+	0x2102, 0x080c, 0x683e, 0x2011, 0x0004, 0x080c, 0x7b94, 0x080c,
+	0x4581, 0x080c, 0x4c42, 0x0158, 0x080c, 0x40f5, 0x0140, 0x7087,
+	0x0001, 0x70bf, 0x0000, 0x080c, 0x3b32, 0x0804, 0x11a5, 0x70d3,
+	0x0000, 0x70cf, 0x0000, 0x706f, 0x0000, 0x080c, 0x11a8, 0x72c8,
+	0x080c, 0x4c42, 0x1170, 0x2011, 0x0000, 0x2001, 0x0204, 0x2004,
+	0x2019, 0x8d8d, 0x201a, 0x704f, 0xffff, 0x7053, 0x00ef, 0x7073,
+	0x0000, 0x2079, 0x8b51, 0x7804, 0xd0ac, 0x0108, 0xc295, 0x72ca,
+	0x080c, 0x4c42, 0x0118, 0xa296, 0x0004, 0x0500, 0x2011, 0x0001,
+	0x080c, 0x7b94, 0x080c, 0x7deb, 0x7097, 0x0000, 0x709b, 0xffff,
+	0x7003, 0x0002, 0x00fe, 0x080c, 0x23fa, 0x2011, 0x0005, 0x080c,
+	0x695c, 0x080c, 0x5d10, 0x080c, 0x4c42, 0x0130, 0x00c6, 0x2061,
+	0x0100, 0x60e3, 0x0008, 0x00ce, 0x012e, 0x00c8, 0x080c, 0x7deb,
 	0x7097, 0x0000, 0x709b, 0xffff, 0x7003, 0x0002, 0x2011, 0x0005,
-	0x080c, 0x718f, 0x080c, 0x6462, 0x080c, 0x4dc5, 0x0130, 0x00c6,
+	0x080c, 0x695c, 0x080c, 0x5d10, 0x080c, 0x4c42, 0x0130, 0x00c6,
 	0x2061, 0x0100, 0x60e3, 0x0008, 0x00ce, 0x00fe, 0x012e, 0x0005,
-	0x00c6, 0x080c, 0x4dc5, 0x1118, 0x20a9, 0x0100, 0x0010, 0x20a9,
-	0x0082, 0x080c, 0x4dc5, 0x1118, 0x2009, 0x0000, 0x0010, 0x2009,
-	0x007e, 0x080c, 0x441f, 0x8108, 0x1f04, 0x11b1, 0x00ce, 0x0005,
+	0x00c6, 0x080c, 0x4c42, 0x1118, 0x20a9, 0x0100, 0x0010, 0x20a9,
+	0x0082, 0x080c, 0x4c42, 0x1118, 0x2009, 0x0000, 0x0010, 0x2009,
+	0x007e, 0x080c, 0x42f5, 0x8108, 0x1f04, 0x11b9, 0x00ce, 0x0005,
 	0x0126, 0x2091, 0x8000, 0x7098, 0xa086, 0xffff, 0x0130, 0x080c,
-	0x251c, 0x080c, 0x6462, 0x0804, 0x123d, 0x70c8, 0xd0ac, 0x1110,
-	0xd09c, 0x0558, 0xd084, 0x0548, 0x0006, 0x70c8, 0xa084, 0x0030,
-	0x000e, 0x1138, 0x00f6, 0x2079, 0x0100, 0x790c, 0xc1b5, 0x790e,
-	0x00fe, 0xd08c, 0x01d0, 0x70cc, 0xa086, 0xffff, 0x0190, 0x080c,
-	0x25fd, 0x080c, 0x6462, 0x70c8, 0xd094, 0x1904, 0x123d, 0x2011,
-	0x0001, 0x2019, 0x0000, 0x080c, 0x2631, 0x080c, 0x6462, 0x0804,
-	0x123d, 0x70d0, 0xa005, 0x1904, 0x123d, 0x7094, 0xa005, 0x1904,
-	0x123d, 0x70c8, 0xd0a4, 0x0110, 0xd0b4, 0x05f8, 0x2001, 0x9252,
-	0x2004, 0xd0ac, 0x01c0, 0x0156, 0x00c6, 0x20a9, 0x007f, 0x2009,
-	0x0000, 0x0016, 0x080c, 0x4434, 0x1118, 0x6000, 0xd0ec, 0x1138,
-	0x001e, 0x8108, 0x1f04, 0x1209, 0x00ce, 0x015e, 0x0020, 0x001e,
-	0x00ce, 0x015e, 0x0410, 0x00f6, 0x2079, 0x0100, 0x780c, 0xc0b5,
-	0x780e, 0x00fe, 0x7003, 0x0003, 0x709b, 0xffff, 0xa006, 0x080c,
-	0x23ba, 0x080c, 0x370a, 0x2001, 0x94e6, 0x2004, 0xa086, 0x0005,
-	0x1120, 0x2011, 0x0000, 0x080c, 0x718f, 0x2011, 0x0000, 0x080c,
-	0x7199, 0x080c, 0x6462, 0x080c, 0x651c, 0x012e, 0x0005, 0x0016,
-	0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, 0x2009, 0x00f7,
-	0x080c, 0x4186, 0x7940, 0xa18c, 0x0010, 0x7942, 0x7924, 0xd1b4,
-	0x0110, 0x7827, 0x0040, 0xd19c, 0x0110, 0x7827, 0x0008, 0x0006,
-	0x0036, 0x0156, 0x7954, 0xd1ac, 0x1904, 0x12a5, 0x080c, 0x4dd7,
-	0x0158, 0x080c, 0x4deb, 0x1128, 0x2001, 0x94d7, 0x2003, 0x0000,
-	0x0070, 0x080c, 0x4dcd, 0x0dc0, 0x2001, 0x94d7, 0x2003, 0xaaaa,
-	0x2001, 0x94d8, 0x2003, 0x0001, 0x080c, 0x4d10, 0x0058, 0x080c,
-	0x4dc5, 0x0140, 0x2009, 0x00f8, 0x080c, 0x4186, 0x7843, 0x0090,
-	0x7843, 0x0010, 0x20a9, 0x09c4, 0x7820, 0xd09c, 0x1138, 0x080c,
-	0x4dc5, 0x0138, 0x7824, 0xd0ac, 0x1904, 0x130d, 0x1f04, 0x1284,
-	0x0070, 0x7824, 0x080c, 0x4de1, 0x0118, 0xd0ac, 0x1904, 0x130d,
-	0xa084, 0x1800, 0x0d98, 0x7003, 0x0001, 0x0804, 0x130d, 0x2001,
-	0x0001, 0x080c, 0x23ba, 0x0804, 0x1318, 0x7850, 0xa084, 0x0180,
-	0x7852, 0x782f, 0x0020, 0x20a9, 0x0050, 0x1d04, 0x12ad, 0x2091,
-	0x6000, 0x1f04, 0x12ad, 0x7850, 0xa084, 0x0180, 0xa085, 0x0400,
-	0x7852, 0x782f, 0x0000, 0x080c, 0x4dd7, 0x0158, 0x080c, 0x4deb,
-	0x1128, 0x2001, 0x94d7, 0x2003, 0x0000, 0x0070, 0x080c, 0x4dcd,
-	0x0dc0, 0x2001, 0x94d7, 0x2003, 0xaaaa, 0x2001, 0x94d8, 0x2003,
-	0x0001, 0x080c, 0x4d10, 0x0020, 0x2009, 0x00f8, 0x080c, 0x4186,
-	0x20a9, 0x000e, 0xe000, 0x1f04, 0x12da, 0x7850, 0xa084, 0x0180,
-	0xa085, 0x1400, 0x7852, 0x080c, 0x4dc5, 0x0120, 0x7843, 0x0090,
-	0x7843, 0x0010, 0x2019, 0x61a8, 0x7820, 0xd09c, 0x1130, 0x080c,
-	0x4dc5, 0x0130, 0x7824, 0xd0ac, 0x11c0, 0x8319, 0x1da8, 0x0080,
-	0x7827, 0x1800, 0xe000, 0xe000, 0x7824, 0x080c, 0x4de1, 0x0110,
-	0xd0ac, 0x1158, 0xa084, 0x1800, 0x0d80, 0x7003, 0x0001, 0x0028,
-	0x2001, 0x0001, 0x080c, 0x23ba, 0x0028, 0x7827, 0x0048, 0x7828,
-	0xc09d, 0x782a, 0x7850, 0xa084, 0x0180, 0xa085, 0x0400, 0x7852,
-	0x015e, 0x003e, 0x000e, 0x012e, 0x00fe, 0x001e, 0x0005, 0x0005,
-	0x0005, 0x0005, 0x2a70, 0x2001, 0x94d7, 0x2003, 0x0000, 0x7087,
-	0x0000, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0218, 0x704f,
-	0xffff, 0x0010, 0x704f, 0x0000, 0x7057, 0xffff, 0x706f, 0x0000,
-	0x7073, 0x0000, 0x080c, 0x854a, 0x2061, 0x94c7, 0x6003, 0x0909,
-	0x6007, 0x0000, 0x600b, 0x8800, 0x600f, 0x0200, 0x6013, 0x00ff,
-	0x6017, 0x0003, 0x601b, 0x0000, 0x601f, 0x07d0, 0x2061, 0x94cf,
-	0x6003, 0x8800, 0x6007, 0x0000, 0x600b, 0x0000, 0x600f, 0x0200,
-	0x6013, 0x00ff, 0x6017, 0x0000, 0x601b, 0x0001, 0x601f, 0x0000,
-	0x2061, 0x94df, 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b, 0x4943,
-	0x600f, 0x2020, 0x0005, 0x04a0, 0x2011, 0x0000, 0x81ff, 0x0570,
-	0xa186, 0x0001, 0x1148, 0x2031, 0x8fff, 0x2039, 0xa501, 0x2021,
-	0x0100, 0x2029, 0xa500, 0x00e8, 0xa186, 0x0002, 0x1118, 0x2011,
-	0x0000, 0x00b8, 0xa186, 0x0005, 0x1118, 0x2011, 0x0001, 0x0088,
-	0xa186, 0x0009, 0x1118, 0x2011, 0x0002, 0x0058, 0xa186, 0x000a,
-	0x1118, 0x2011, 0x0002, 0x0028, 0xa186, 0x0055, 0x1110, 0x2011,
-	0x0003, 0x3800, 0xa084, 0xfffc, 0xa205, 0x20c0, 0x0804, 0x104d,
-	0xa00e, 0x2011, 0x0003, 0x2019, 0x13a7, 0x0804, 0x13f8, 0x2019,
-	0xaaaa, 0x2061, 0xffff, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c04,
-	0xa306, 0x2262, 0x1110, 0xc1b5, 0xc1a5, 0x2011, 0x0000, 0x2019,
-	0x13ba, 0x04f0, 0x2019, 0xaaaa, 0x2061, 0xffff, 0x2c14, 0x2362,
-	0xe000, 0xe000, 0x2c1c, 0x2061, 0x7fff, 0xe000, 0xe000, 0x2c04,
-	0x2061, 0xffff, 0x2262, 0xa306, 0x0110, 0xc18d, 0x0008, 0xc185,
-	0x2011, 0x0002, 0x2019, 0x13d5, 0x0418, 0x2061, 0xffff, 0x2019,
-	0xaaaa, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c04, 0x2262, 0xa306,
-	0x1180, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c1c, 0x2061, 0x7fff,
-	0x2c04, 0x2061, 0xffff, 0x2262, 0xa306, 0x1110, 0xc195, 0x0008,
-	0xc19d, 0x2011, 0x0001, 0x2019, 0x13f6, 0x0010, 0x0804, 0x136c,
-	0x3800, 0xa084, 0xfffc, 0xa205, 0x20c0, 0x0837, 0x2091, 0x8000,
-	0x0e04, 0x1400, 0x0006, 0x0016, 0x2079, 0x0000, 0x7818, 0xd084,
-	0x1de8, 0x001e, 0x792e, 0x000e, 0x782a, 0x000e, 0x7826, 0x3900,
-	0x783a, 0x7823, 0x8002, 0x781b, 0x0001, 0x2091, 0x5000, 0x0156,
-	0x0146, 0x20a9, 0x0010, 0x20a1, 0x95e6, 0x2091, 0x2000, 0x40a1,
-	0x20a9, 0x0010, 0x2091, 0x2200, 0x40a1, 0x20a9, 0x0010, 0x2091,
-	0x2400, 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2600, 0x40a1, 0x014e,
-	0x015e, 0x2079, 0x9200, 0x7803, 0x0005, 0x2091, 0x4080, 0x0cf8,
-	0x0005, 0x2071, 0x9200, 0x715c, 0x712e, 0x2021, 0x0001, 0xa190,
-	0x0030, 0xa298, 0x0030, 0x0240, 0x7060, 0xa302, 0x1228, 0x220a,
-	0x2208, 0x2310, 0x8420, 0x0ca8, 0x3800, 0xd08c, 0x0148, 0x7060,
-	0xa086, 0x9200, 0x0128, 0x7063, 0x9200, 0x2011, 0x1000, 0x0c48,
-	0x200b, 0x0000, 0x74aa, 0x74ae, 0x70df, 0x0010, 0x0005, 0x00e6,
-	0x0126, 0x2091, 0x8000, 0x2071, 0x9200, 0x70ac, 0x0016, 0x2008,
-	0x70dc, 0xa16a, 0x2100, 0x001e, 0x0268, 0x8001, 0x70ae, 0x702c,
-	0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x012e,
-	0x00ee, 0x0005, 0xa06e, 0x0cd8, 0x00e6, 0x2071, 0x9200, 0x0126,
-	0x2091, 0x8000, 0x70ac, 0x8001, 0x0260, 0x70ae, 0x702c, 0x2068,
-	0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x012e, 0x00ee,
-	0x0005, 0xa06e, 0x0cd8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071,
-	0x9200, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70ac, 0x8000, 0x70ae,
-	0x012e, 0x00ee, 0x0005, 0x8dff, 0x0138, 0x6804, 0x6807, 0x0000,
-	0x0006, 0x0c49, 0x00de, 0x0cb8, 0x0005, 0x00e6, 0x2071, 0x9200,
-	0x70ac, 0xa08a, 0x0010, 0xa00d, 0x00ee, 0x0005, 0x00e6, 0x2071,
-	0x9508, 0x7007, 0x0000, 0x701b, 0x0000, 0x701f, 0x0000, 0x2071,
-	0x0000, 0x7010, 0xa085, 0x8004, 0x7012, 0x00ee, 0x0005, 0x00e6,
-	0x2270, 0x700b, 0x0000, 0x2071, 0x9508, 0x7018, 0xa088, 0x9511,
-	0x220a, 0x8000, 0xa084, 0x0007, 0x701a, 0x7004, 0xa005, 0x1128,
-	0x00f6, 0x2079, 0x0010, 0x0081, 0x00fe, 0x00ee, 0x0005, 0x00e6,
-	0x2071, 0x9508, 0x7004, 0xa005, 0x1128, 0x00f6, 0x2079, 0x0010,
-	0x0019, 0x00fe, 0x00ee, 0x0005, 0x7000, 0x0002, 0x14f3, 0x1557,
-	0x1574, 0x1574, 0x1f79, 0x7018, 0x711c, 0xa106, 0x1118, 0x7007,
-	0x0000, 0x0005, 0x00d6, 0xa180, 0x9511, 0x2004, 0x700a, 0x2068,
-	0x8108, 0xa18c, 0x0007, 0x711e, 0x7803, 0x0026, 0x6824, 0x7832,
-	0x6828, 0x7836, 0x682c, 0x783a, 0x6830, 0x783e, 0x6810, 0x700e,
-	0x680c, 0x7016, 0x6804, 0x00de, 0xd084, 0x0120, 0x7007, 0x0001,
-	0x0029, 0x0005, 0x7007, 0x0002, 0x00b1, 0x0005, 0x0016, 0x0026,
-	0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x1210, 0x2110, 0xa006,
-	0x700e, 0x7212, 0x8203, 0x7822, 0x7803, 0x0020, 0x7803, 0x0041,
-	0x002e, 0x001e, 0x0005, 0x0016, 0x0026, 0x0136, 0x0146, 0x0156,
-	0x7014, 0x2098, 0x20a1, 0x0014, 0x7803, 0x0026, 0x710c, 0x2011,
-	0x0040, 0xa182, 0x0040, 0x1210, 0x2110, 0xa006, 0x700e, 0x22a8,
-	0x53a6, 0x8203, 0x7822, 0x7803, 0x0020, 0x3300, 0x7016, 0x7803,
-	0x0001, 0x015e, 0x014e, 0x013e, 0x002e, 0x001e, 0x0005, 0x0136,
-	0x0146, 0x0156, 0x2099, 0x930e, 0x20a1, 0x0018, 0x20a9, 0x0008,
-	0x53a3, 0x7803, 0x0020, 0x0126, 0x2091, 0x8000, 0x7803, 0x0041,
-	0x7007, 0x0003, 0x7000, 0xc084, 0x7002, 0x700b, 0x9309, 0x012e,
-	0x015e, 0x014e, 0x013e, 0x0005, 0x0136, 0x0146, 0x0156, 0x2001,
-	0x933d, 0x209c, 0x20a1, 0x0014, 0x7803, 0x0026, 0x2001, 0x933e,
-	0x20ac, 0x53a6, 0x2099, 0x933f, 0x20a1, 0x0018, 0x20a9, 0x0008,
-	0x53a3, 0x7803, 0x0020, 0x0126, 0x2091, 0x8000, 0x7803, 0x0001,
-	0x7007, 0x0004, 0x7000, 0xc08c, 0x7002, 0x700b, 0x933a, 0x012e,
-	0x015e, 0x014e, 0x013e, 0x0005, 0x0016, 0x00e6, 0x2071, 0x9508,
-	0x00f6, 0x2079, 0x0010, 0x7904, 0x7803, 0x0002, 0xd1fc, 0x0120,
-	0xa18c, 0x0700, 0x7004, 0x0023, 0x00fe, 0x00ee, 0x001e, 0x0005,
-	0x14ec, 0x15b8, 0x15e2, 0x1608, 0x1638, 0x1f96, 0x15b7, 0x0cf8,
-	0xa18c, 0x0700, 0x1508, 0x0136, 0x0146, 0x0156, 0x7014, 0x20a0,
-	0x2099, 0x0014, 0x7803, 0x0040, 0x7010, 0x20a8, 0x53a5, 0x3400,
-	0x7016, 0x015e, 0x014e, 0x013e, 0x700c, 0xa005, 0x0530, 0x080c,
-	0x151e, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0100, 0x7007,
-	0x0000, 0x080c, 0x14ec, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003,
-	0x0200, 0x0ca8, 0xa18c, 0x0700, 0x1130, 0x700c, 0xa005, 0x0168,
-	0x080c, 0x1533, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0200,
-	0x7007, 0x0000, 0x080c, 0x14ec, 0x0005, 0x00d6, 0x7008, 0x2068,
-	0x7830, 0x6826, 0x7834, 0x682a, 0x7838, 0x682e, 0x783c, 0x6832,
-	0x680b, 0x0100, 0x00de, 0x7007, 0x0000, 0x080c, 0x14ec, 0x0005,
-	0xa18c, 0x0700, 0x1540, 0x0136, 0x0146, 0x0156, 0x2001, 0x930c,
-	0x2004, 0xa080, 0x000d, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040,
-	0x20a9, 0x0020, 0x53a5, 0x2001, 0x930e, 0x2004, 0xd0bc, 0x0148,
-	0x2001, 0x9317, 0x2004, 0xa080, 0x000d, 0x20a0, 0x20a9, 0x0020,
-	0x53a5, 0x015e, 0x014e, 0x013e, 0x7007, 0x0000, 0x080c, 0x4f27,
-	0x080c, 0x14ec, 0x0005, 0x2011, 0x8003, 0x080c, 0x3698, 0x0cf8,
-	0xa18c, 0x0700, 0x1148, 0x2001, 0x933c, 0x2003, 0x0100, 0x7007,
-	0x0000, 0x080c, 0x14ec, 0x0005, 0x2011, 0x8004, 0x080c, 0x3698,
-	0x0cf8, 0x0126, 0x2091, 0x2200, 0x2079, 0x0030, 0x2071, 0x9519,
-	0x7003, 0x0000, 0x700f, 0x9520, 0x7013, 0x9520, 0x780f, 0x00f0,
-	0x012e, 0x0005, 0x6934, 0xa184, 0x0007, 0x0002, 0x1666, 0x16ab,
-	0x1666, 0x1666, 0x166a, 0x1693, 0x167a, 0x1671, 0xa085, 0x0001,
-	0x0804, 0x16c5, 0xa186, 0x0024, 0x05f0, 0xa186, 0x002c, 0x05d8,
-	0x0ca8, 0x684c, 0xd0bc, 0x0d90, 0x6860, 0x682e, 0x685c, 0x682a,
-	0x6858, 0x04c8, 0xa18c, 0x00ff, 0xa186, 0x001e, 0x1d38, 0x684c,
-	0xd0bc, 0x0d20, 0x6860, 0x682e, 0x685c, 0x682a, 0x6804, 0x681a,
-	0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x1f59, 0x2005,
-	0x6832, 0x6858, 0x0440, 0xa18c, 0x00ff, 0xa186, 0x0015, 0x1970,
-	0x684c, 0xd0ac, 0x0958, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004,
-	0xa084, 0x000f, 0xa080, 0x1f59, 0x2005, 0x6832, 0xa006, 0x682e,
-	0x682a, 0x6858, 0x0080, 0x684c, 0xd0ac, 0x0904, 0x1666, 0xa006,
-	0x682e, 0x682a, 0x6858, 0xa18c, 0x000f, 0xa188, 0x1f59, 0x210d,
-	0x6932, 0x2d08, 0x691a, 0x6826, 0x684c, 0xc0dd, 0x684e, 0xa006,
-	0x680a, 0x697c, 0x6912, 0x6980, 0x6916, 0x0005, 0x20e1, 0x0007,
-	0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, 0x82ff, 0x0178, 0xa280,
-	0x0004, 0x00d6, 0x206c, 0x684c, 0xd0dc, 0x1120, 0x080c, 0x165a,
-	0x190c, 0x13fe, 0x6808, 0x8000, 0x680a, 0x00de, 0x0126, 0x0046,
-	0x0036, 0x0026, 0x2091, 0x2200, 0x002e, 0x003e, 0x004e, 0x7000,
-	0xa005, 0x0178, 0x710c, 0x220a, 0x8108, 0x230a, 0x8108, 0x240a,
-	0x8108, 0xa182, 0x953b, 0x0210, 0x2009, 0x9520, 0x710e, 0x012e,
-	0x0005, 0x7206, 0x2001, 0x16f7, 0x0006, 0x2260, 0x0804, 0x17e8,
-	0x0126, 0x0026, 0x0036, 0x00c6, 0x0006, 0x2091, 0x2200, 0x000e,
-	0x004e, 0x003e, 0x002e, 0x00d6, 0x00c6, 0x2460, 0x6110, 0x2168,
-	0x6a62, 0x6b5e, 0xa005, 0x05b8, 0x6808, 0xa005, 0x0904, 0x177c,
-	0x7000, 0xa005, 0x1108, 0x0430, 0x700c, 0x7110, 0xa106, 0x1904,
-	0x1784, 0x7004, 0xa406, 0x11f0, 0x2001, 0x0005, 0x2004, 0xd08c,
-	0x0130, 0x0046, 0x080c, 0x1942, 0x004e, 0x2460, 0x0c28, 0x2001,
-	0x0207, 0x2004, 0xd09c, 0x1d80, 0x7804, 0xa084, 0x6000, 0x0120,
-	0xa086, 0x6000, 0x0108, 0x0c40, 0x7803, 0x0004, 0x7003, 0x0000,
-	0x7004, 0x2060, 0x6100, 0xa18e, 0x0004, 0x15f0, 0x2009, 0x0048,
-	0x080c, 0x7518, 0x04c8, 0x6808, 0xa005, 0x0570, 0x7000, 0xa005,
-	0x0558, 0x700c, 0x7110, 0xa106, 0x1118, 0x7004, 0xa406, 0x1520,
-	0x2001, 0x0005, 0x2004, 0xd08c, 0x0130, 0x0046, 0x080c, 0x1942,
-	0x004e, 0x2460, 0x0c40, 0x2001, 0x0207, 0x2004, 0xd09c, 0x1d80,
-	0x2001, 0x0005, 0x2004, 0xd08c, 0x1d80, 0x7804, 0xa084, 0x6000,
-	0x0118, 0xa086, 0x6000, 0x1d20, 0x7818, 0x6812, 0x781c, 0x6816,
-	0x7803, 0x0004, 0x7003, 0x0000, 0x6100, 0xa18e, 0x0004, 0x1120,
-	0x2009, 0x0048, 0x080c, 0x7518, 0x00ce, 0x00de, 0x012e, 0x0005,
-	0x00f6, 0x00e6, 0x0026, 0x0036, 0x0046, 0x080c, 0x1c26, 0x0026,
-	0x2071, 0x9519, 0x7000, 0xa086, 0x0000, 0x0580, 0x7004, 0xac06,
+	0x23fa, 0x080c, 0x5d10, 0x0804, 0x124f, 0x70c8, 0xd0ac, 0x1110,
+	0xd09c, 0x0520, 0xd084, 0x0510, 0x0006, 0x2001, 0x0103, 0x2003,
+	0x00ff, 0x000e, 0xd08c, 0x01d0, 0x70cc, 0xa086, 0xffff, 0x0190,
+	0x080c, 0x24f4, 0x080c, 0x5d10, 0x70c8, 0xd094, 0x1904, 0x124f,
+	0x2011, 0x0001, 0x2019, 0x0000, 0x080c, 0x2528, 0x080c, 0x5d10,
+	0x0804, 0x124f, 0x70d0, 0xa005, 0x1904, 0x124f, 0x7094, 0xa005,
+	0x1904, 0x124f, 0x70c8, 0xd0a4, 0x0118, 0xd0b4, 0x0904, 0x124f,
+	0x2001, 0x8b52, 0x2004, 0xd0ac, 0x01c0, 0x0156, 0x00c6, 0x20a9,
+	0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x430a, 0x1118, 0x6000,
+	0xd0ec, 0x1138, 0x001e, 0x8108, 0x1f04, 0x120b, 0x00ce, 0x015e,
+	0x0020, 0x001e, 0x00ce, 0x015e, 0x0490, 0x0006, 0x2001, 0x0103,
+	0x2003, 0x00ff, 0x000e, 0x7003, 0x0003, 0x709b, 0xffff, 0xa006,
+	0x080c, 0x2298, 0x080c, 0x3689, 0x00f6, 0x2079, 0x0100, 0x080c,
+	0x4c68, 0x0150, 0x080c, 0x4c42, 0x7828, 0x0118, 0xa084, 0xe1ff,
+	0x0010, 0xa084, 0xffdf, 0x782a, 0x00fe, 0x2001, 0x8dab, 0x2004,
+	0xa086, 0x0005, 0x1120, 0x2011, 0x0000, 0x080c, 0x695c, 0x2011,
+	0x0000, 0x080c, 0x6966, 0x080c, 0x5d10, 0x080c, 0x5dc2, 0x012e,
+	0x0005, 0x0016, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100,
+	0x2009, 0x00f7, 0x080c, 0x40be, 0x7940, 0xa18c, 0x0010, 0x7942,
+	0x7924, 0xd1b4, 0x0110, 0x7827, 0x0040, 0xd19c, 0x0110, 0x7827,
+	0x0008, 0x0006, 0x0036, 0x0156, 0x7954, 0xd1ac, 0x1904, 0x12b7,
+	0x080c, 0x4c54, 0x0158, 0x080c, 0x4c68, 0x1128, 0x2001, 0x8d9c,
+	0x2003, 0x0000, 0x0070, 0x080c, 0x4c4a, 0x0dc0, 0x2001, 0x8d9c,
+	0x2003, 0xaaaa, 0x2001, 0x8d9d, 0x2003, 0x0001, 0x080c, 0x4b8b,
+	0x0058, 0x080c, 0x4c42, 0x0140, 0x2009, 0x00f8, 0x080c, 0x40be,
+	0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, 0x09c4, 0x7820, 0xd09c,
+	0x1138, 0x080c, 0x4c42, 0x0138, 0x7824, 0xd0ac, 0x1904, 0x131f,
+	0x1f04, 0x1296, 0x0070, 0x7824, 0x080c, 0x4c5e, 0x0118, 0xd0ac,
+	0x1904, 0x131f, 0xa084, 0x1800, 0x0d98, 0x7003, 0x0001, 0x0804,
+	0x131f, 0x2001, 0x0001, 0x080c, 0x2298, 0x0804, 0x132a, 0x7850,
+	0xa084, 0x0180, 0x7852, 0x782f, 0x0020, 0x20a9, 0x0050, 0x1d04,
+	0x12bf, 0x2091, 0x6000, 0x1f04, 0x12bf, 0x7850, 0xa084, 0x0180,
+	0xa085, 0x0400, 0x7852, 0x782f, 0x0000, 0x080c, 0x4c54, 0x0158,
+	0x080c, 0x4c68, 0x1128, 0x2001, 0x8d9c, 0x2003, 0x0000, 0x0070,
+	0x080c, 0x4c4a, 0x0dc0, 0x2001, 0x8d9c, 0x2003, 0xaaaa, 0x2001,
+	0x8d9d, 0x2003, 0x0001, 0x080c, 0x4b8b, 0x0020, 0x2009, 0x00f8,
+	0x080c, 0x40be, 0x20a9, 0x000e, 0xe000, 0x1f04, 0x12ec, 0x7850,
+	0xa084, 0x0180, 0xa085, 0x1400, 0x7852, 0x080c, 0x4c42, 0x0120,
+	0x7843, 0x0090, 0x7843, 0x0010, 0x2019, 0x61a8, 0x7820, 0xd09c,
+	0x1130, 0x080c, 0x4c42, 0x0130, 0x7824, 0xd0ac, 0x11c0, 0x8319,
+	0x1da8, 0x0080, 0x7827, 0x1800, 0xe000, 0xe000, 0x7824, 0x080c,
+	0x4c5e, 0x0110, 0xd0ac, 0x1158, 0xa084, 0x1800, 0x0d80, 0x7003,
+	0x0001, 0x0028, 0x2001, 0x0001, 0x080c, 0x2298, 0x0028, 0x7827,
+	0x0048, 0x7828, 0xc09d, 0x782a, 0x7850, 0xa084, 0x0180, 0xa085,
+	0x0400, 0x7852, 0x015e, 0x003e, 0x000e, 0x012e, 0x00fe, 0x001e,
+	0x0005, 0x0005, 0x0005, 0x0005, 0x2a70, 0x2001, 0x8d9c, 0x2003,
+	0x0000, 0x7087, 0x0000, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002,
+	0x0218, 0x704f, 0xffff, 0x0010, 0x704f, 0x0000, 0x7057, 0xffff,
+	0x706f, 0x0000, 0x7073, 0x0000, 0x080c, 0x7deb, 0x2061, 0x8d8c,
+	0x6003, 0x0909, 0x6007, 0x0000, 0x600b, 0x8800, 0x600f, 0x0200,
+	0x6013, 0x00ff, 0x6017, 0x0003, 0x601b, 0x0000, 0x601f, 0x07d0,
+	0x2061, 0x8d94, 0x6003, 0x8800, 0x6007, 0x0000, 0x600b, 0x0000,
+	0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x0000, 0x601b, 0x0001,
+	0x601f, 0x0000, 0x2061, 0x8da4, 0x6003, 0x514c, 0x6007, 0x4f47,
+	0x600b, 0x4943, 0x600f, 0x2020, 0x0005, 0x04a0, 0x2011, 0x0000,
+	0x81ff, 0x0570, 0xa186, 0x0001, 0x1148, 0x2031, 0x8fff, 0x2039,
+	0x9e01, 0x2021, 0x0100, 0x2029, 0x9e00, 0x00e8, 0xa186, 0x0002,
+	0x1118, 0x2011, 0x0000, 0x00b8, 0xa186, 0x0005, 0x1118, 0x2011,
+	0x0001, 0x0088, 0xa186, 0x0009, 0x1118, 0x2011, 0x0002, 0x0058,
+	0xa186, 0x000a, 0x1118, 0x2011, 0x0002, 0x0028, 0xa186, 0x0055,
+	0x1110, 0x2011, 0x0003, 0x3800, 0xa084, 0xfffc, 0xa205, 0x20c0,
+	0x0804, 0x104d, 0xa00e, 0x2011, 0x0003, 0x2019, 0x13b9, 0x0804,
+	0x140a, 0x2019, 0xaaaa, 0x2061, 0xffff, 0x2c14, 0x2362, 0xe000,
+	0xe000, 0x2c04, 0xa306, 0x2262, 0x1110, 0xc1b5, 0xc1a5, 0x2011,
+	0x0000, 0x2019, 0x13cc, 0x04f0, 0x2019, 0xaaaa, 0x2061, 0xffff,
+	0x2c14, 0x2362, 0xe000, 0xe000, 0x2c1c, 0x2061, 0x7fff, 0xe000,
+	0xe000, 0x2c04, 0x2061, 0xffff, 0x2262, 0xa306, 0x0110, 0xc18d,
+	0x0008, 0xc185, 0x2011, 0x0002, 0x2019, 0x13e7, 0x0418, 0x2061,
+	0xffff, 0x2019, 0xaaaa, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c04,
+	0x2262, 0xa306, 0x1180, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c1c,
+	0x2061, 0x7fff, 0x2c04, 0x2061, 0xffff, 0x2262, 0xa306, 0x1110,
+	0xc195, 0x0008, 0xc19d, 0x2011, 0x0001, 0x2019, 0x1408, 0x0010,
+	0x0804, 0x137e, 0x3800, 0xa084, 0xfffc, 0xa205, 0x20c0, 0x0837,
+	0x2091, 0x8000, 0x0e04, 0x1412, 0x0006, 0x0016, 0x2079, 0x0000,
+	0x7818, 0xd084, 0x1de8, 0x001e, 0x792e, 0x000e, 0x782a, 0x000e,
+	0x7826, 0x3900, 0x783a, 0x7823, 0x8002, 0x781b, 0x0001, 0x2091,
+	0x5000, 0x0156, 0x0146, 0x20a9, 0x0010, 0x20a1, 0x8eaa, 0x2091,
+	0x2000, 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2200, 0x40a1, 0x20a9,
+	0x0010, 0x2091, 0x2400, 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2600,
+	0x40a1, 0x014e, 0x015e, 0x2079, 0x8b00, 0x7803, 0x0005, 0x2091,
+	0x4080, 0x0cf8, 0x0005, 0x2071, 0x8b00, 0x715c, 0x712e, 0x2021,
+	0x0001, 0xa190, 0x0030, 0xa298, 0x0030, 0x0240, 0x7060, 0xa302,
+	0x1228, 0x220a, 0x2208, 0x2310, 0x8420, 0x0ca8, 0x3800, 0xd08c,
+	0x0148, 0x7060, 0xa086, 0x8b00, 0x0128, 0x7063, 0x8b00, 0x2011,
+	0x1000, 0x0c48, 0x200b, 0x0000, 0x74aa, 0x74ae, 0x0005, 0x00e6,
+	0x0126, 0x2091, 0x8000, 0x2071, 0x8b00, 0x70ac, 0xa0ea, 0x0010,
+	0x0268, 0x8001, 0x70ae, 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b,
+	0x0000, 0x6807, 0x0000, 0x012e, 0x00ee, 0x0005, 0xa06e, 0x0cd8,
+	0x00e6, 0x2071, 0x8b00, 0x0126, 0x2091, 0x8000, 0x70ac, 0x8001,
+	0x0260, 0x70ae, 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000,
+	0x6807, 0x0000, 0x012e, 0x00ee, 0x0005, 0xa06e, 0x0cd8, 0x00e6,
+	0x0126, 0x2091, 0x8000, 0x2071, 0x8b00, 0x702c, 0x206a, 0x2d00,
+	0x702e, 0x70ac, 0x8000, 0x70ae, 0x012e, 0x00ee, 0x0005, 0x8dff,
+	0x0138, 0x6804, 0x6807, 0x0000, 0x0006, 0x0c49, 0x00de, 0x0cb8,
+	0x0005, 0x00e6, 0x2071, 0x8b00, 0x70ac, 0xa08a, 0x0010, 0xa00d,
+	0x00ee, 0x0005, 0x00e6, 0x2071, 0x8dcd, 0x7007, 0x0000, 0x701b,
+	0x0000, 0x701f, 0x0000, 0x2071, 0x0000, 0x7010, 0xa085, 0x8004,
+	0x7012, 0x00ee, 0x0005, 0x00e6, 0x2270, 0x700b, 0x0000, 0x2071,
+	0x8dcd, 0x7018, 0xa088, 0x8dd6, 0x220a, 0x8000, 0xa084, 0x0007,
+	0x701a, 0x7004, 0xa005, 0x1128, 0x00f6, 0x2079, 0x0010, 0x0081,
+	0x00fe, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x8dcd, 0x7004, 0xa005,
+	0x1128, 0x00f6, 0x2079, 0x0010, 0x0019, 0x00fe, 0x00ee, 0x0005,
+	0x7000, 0x0002, 0x14fe, 0x1562, 0x157f, 0x157f, 0x7018, 0x711c,
+	0xa106, 0x1118, 0x7007, 0x0000, 0x0005, 0x00d6, 0xa180, 0x8dd6,
+	0x2004, 0x700a, 0x2068, 0x8108, 0xa18c, 0x0007, 0x711e, 0x7803,
+	0x0026, 0x6824, 0x7832, 0x6828, 0x7836, 0x682c, 0x783a, 0x6830,
+	0x783e, 0x6810, 0x700e, 0x680c, 0x7016, 0x6804, 0x00de, 0xd084,
+	0x0120, 0x7007, 0x0001, 0x0029, 0x0005, 0x7007, 0x0002, 0x00b1,
+	0x0005, 0x0016, 0x0026, 0x710c, 0x2011, 0x0040, 0xa182, 0x0040,
+	0x1210, 0x2110, 0xa006, 0x700e, 0x7212, 0x8203, 0x7822, 0x7803,
+	0x0020, 0x7803, 0x0041, 0x002e, 0x001e, 0x0005, 0x0016, 0x0026,
+	0x0136, 0x0146, 0x0156, 0x7014, 0x2098, 0x20a1, 0x0014, 0x7803,
+	0x0026, 0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x1210, 0x2110,
+	0xa006, 0x700e, 0x22a8, 0x53a6, 0x8203, 0x7822, 0x7803, 0x0020,
+	0x3300, 0x7016, 0x7803, 0x0001, 0x015e, 0x014e, 0x013e, 0x002e,
+	0x001e, 0x0005, 0x0136, 0x0146, 0x0156, 0x2099, 0x8bf9, 0x20a1,
+	0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x0126, 0x2091,
+	0x8000, 0x7803, 0x0041, 0x7007, 0x0003, 0x7000, 0xc084, 0x7002,
+	0x700b, 0x8bf4, 0x012e, 0x015e, 0x014e, 0x013e, 0x0005, 0x0136,
+	0x0146, 0x0156, 0x2001, 0x8c28, 0x209c, 0x20a1, 0x0014, 0x7803,
+	0x0026, 0x2001, 0x8c29, 0x20ac, 0x53a6, 0x2099, 0x8c2a, 0x20a1,
+	0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x0126, 0x2091,
+	0x8000, 0x7803, 0x0001, 0x7007, 0x0004, 0x7000, 0xc08c, 0x7002,
+	0x700b, 0x8c25, 0x012e, 0x015e, 0x014e, 0x013e, 0x0005, 0x0016,
+	0x00e6, 0x2071, 0x8dcd, 0x00f6, 0x2079, 0x0010, 0x7904, 0x7803,
+	0x0002, 0xd1fc, 0x0120, 0xa18c, 0x0700, 0x7004, 0x0023, 0x00fe,
+	0x00ee, 0x001e, 0x0005, 0x14f8, 0x15c2, 0x15f0, 0x161a, 0x164a,
+	0x15c1, 0x0cf8, 0xa18c, 0x0700, 0x1528, 0x0136, 0x0146, 0x0156,
+	0x7014, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x7010, 0x20a8,
+	0x53a5, 0x3400, 0x7016, 0x015e, 0x014e, 0x013e, 0x700c, 0xa005,
+	0x0570, 0x7830, 0x7832, 0x7834, 0x7836, 0x080c, 0x1529, 0x0005,
+	0x7008, 0xa080, 0x0002, 0x2003, 0x0100, 0x7007, 0x0000, 0x080c,
+	0x14f8, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0200, 0x0ca8,
+	0xa18c, 0x0700, 0x1150, 0x700c, 0xa005, 0x0188, 0x7830, 0x7832,
+	0x7834, 0x7836, 0x080c, 0x153e, 0x0005, 0x7008, 0xa080, 0x0002,
+	0x2003, 0x0200, 0x7007, 0x0000, 0x080c, 0x14f8, 0x0005, 0x00d6,
+	0x7008, 0x2068, 0x7830, 0x6826, 0x7834, 0x682a, 0x7838, 0x682e,
+	0x783c, 0x6832, 0x680b, 0x0100, 0x00de, 0x7007, 0x0000, 0x080c,
+	0x14f8, 0x0005, 0xa18c, 0x0700, 0x1540, 0x0136, 0x0146, 0x0156,
+	0x2001, 0x8bf7, 0x2004, 0xa080, 0x000d, 0x20a0, 0x2099, 0x0014,
+	0x7803, 0x0040, 0x20a9, 0x0020, 0x53a5, 0x2001, 0x8bf9, 0x2004,
+	0xd0bc, 0x0148, 0x2001, 0x8c02, 0x2004, 0xa080, 0x000d, 0x20a0,
+	0x20a9, 0x0020, 0x53a5, 0x015e, 0x014e, 0x013e, 0x7007, 0x0000,
+	0x080c, 0x4e43, 0x080c, 0x14f8, 0x0005, 0x2011, 0x8003, 0x080c,
+	0x3617, 0x0cf8, 0xa18c, 0x0700, 0x1148, 0x2001, 0x8c27, 0x2003,
+	0x0100, 0x7007, 0x0000, 0x080c, 0x14f8, 0x0005, 0x2011, 0x8004,
+	0x080c, 0x3617, 0x0cf8, 0x0126, 0x2091, 0x2200, 0x2079, 0x0030,
+	0x2071, 0x8dde, 0x7003, 0x0000, 0x700f, 0x8de4, 0x7013, 0x8de4,
+	0x780f, 0x00f6, 0x012e, 0x0005, 0x6934, 0xa184, 0x0007, 0x0002,
+	0x1678, 0x16b6, 0x1678, 0x1678, 0x1678, 0x169e, 0x1685, 0x167c,
+	0xa085, 0x0001, 0x0804, 0x16d0, 0x684c, 0xd0bc, 0x0dc8, 0x6860,
+	0x682e, 0x685c, 0x682a, 0x6858, 0x04c8, 0xa18c, 0x00ff, 0xa186,
+	0x001e, 0x1d70, 0x684c, 0xd0bc, 0x0d58, 0x6860, 0x682e, 0x685c,
+	0x682a, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f,
+	0xa080, 0x1e76, 0x2005, 0x6832, 0x6858, 0x0440, 0xa18c, 0x00ff,
+	0xa186, 0x0015, 0x19a8, 0x684c, 0xd0ac, 0x0990, 0x6804, 0x681a,
+	0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x1e76, 0x2005,
+	0x6832, 0xa006, 0x682e, 0x682a, 0x6858, 0x0080, 0x684c, 0xd0ac,
+	0x0904, 0x1678, 0xa006, 0x682e, 0x682a, 0x6858, 0xa18c, 0x000f,
+	0xa188, 0x1e76, 0x210d, 0x6932, 0x2d08, 0x691a, 0x6826, 0x684c,
+	0xc0dd, 0x684e, 0xa006, 0x680a, 0x697c, 0x6912, 0x6980, 0x6916,
+	0x0005, 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001, 0x020a, 0x2004,
+	0x82ff, 0x0178, 0xa280, 0x0004, 0x00d6, 0x206c, 0x684c, 0xd0dc,
+	0x1120, 0x080c, 0x166c, 0x190c, 0x1410, 0x6808, 0x8000, 0x680a,
+	0x00de, 0x0126, 0x0046, 0x0036, 0x0026, 0x2091, 0x2200, 0x002e,
+	0x003e, 0x004e, 0x7000, 0xa005, 0x01d0, 0x710c, 0x220a, 0x8108,
+	0x230a, 0x8108, 0x240a, 0x8108, 0xa182, 0x8dff, 0x0210, 0x2009,
+	0x8de4, 0x710e, 0x7010, 0xa102, 0xa082, 0x0009, 0x0118, 0xa080,
+	0x001b, 0x1118, 0x2009, 0x0138, 0x200a, 0x012e, 0x0005, 0x7206,
+	0x2001, 0x170d, 0x0006, 0x2260, 0x0804, 0x180c, 0x0126, 0x0026,
+	0x0036, 0x00c6, 0x0006, 0x2091, 0x2200, 0x000e, 0x004e, 0x003e,
+	0x002e, 0x00d6, 0x00c6, 0x2460, 0x6110, 0x2168, 0x6a62, 0x6b5e,
+	0xa005, 0x05b8, 0x6808, 0xa005, 0x0904, 0x1792, 0x7000, 0xa005,
+	0x1108, 0x0430, 0x700c, 0x7110, 0xa106, 0x1904, 0x179a, 0x7004,
+	0xa406, 0x11f0, 0x2001, 0x0005, 0x2004, 0xd08c, 0x0130, 0x0046,
+	0x080c, 0x18ee, 0x004e, 0x2460, 0x0c28, 0x2001, 0x0207, 0x2004,
+	0xd09c, 0x1d80, 0x7804, 0xa084, 0x6000, 0x0120, 0xa086, 0x6000,
+	0x0108, 0x0c40, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060,
+	0x6100, 0xa18e, 0x0004, 0x15f0, 0x2009, 0x0048, 0x080c, 0x6d3f,
+	0x04c8, 0x6808, 0xa005, 0x0570, 0x7000, 0xa005, 0x0558, 0x700c,
+	0x7110, 0xa106, 0x1118, 0x7004, 0xa406, 0x1520, 0x2001, 0x0005,
+	0x2004, 0xd08c, 0x0130, 0x0046, 0x080c, 0x18ee, 0x004e, 0x2460,
+	0x0c40, 0x2001, 0x0207, 0x2004, 0xd09c, 0x1d80, 0x2001, 0x0005,
+	0x2004, 0xd08c, 0x1d80, 0x7804, 0xa084, 0x6000, 0x0118, 0xa086,
+	0x6000, 0x1d20, 0x7818, 0x6812, 0x781c, 0x6816, 0x7803, 0x0004,
+	0x7003, 0x0000, 0x6100, 0xa18e, 0x0004, 0x1120, 0x2009, 0x0048,
+	0x080c, 0x6d3f, 0x00ce, 0x00de, 0x012e, 0x0005, 0x00f6, 0x00e6,
+	0x0026, 0x0036, 0x0046, 0x0056, 0x080c, 0x1b5e, 0x0026, 0x0056,
+	0x2071, 0x8dde, 0x7000, 0xa086, 0x0000, 0x0580, 0x7004, 0xac06,
 	0x11f8, 0x2079, 0x0030, 0x7000, 0xa086, 0x0003, 0x01c8, 0x7804,
 	0xd0fc, 0x1198, 0x2001, 0x0207, 0x2004, 0xd09c, 0x1dc0, 0x7803,
 	0x0004, 0x7804, 0xd0ac, 0x1de8, 0x7803, 0x0002, 0x7803, 0x0009,
-	0x7003, 0x0003, 0x7007, 0x0000, 0x0018, 0x080c, 0x1942, 0x08d0,
-	0x0156, 0x20a9, 0x0009, 0x2009, 0x9520, 0x2104, 0xac06, 0x1108,
-	0x200a, 0xa188, 0x0003, 0x1f04, 0x17bd, 0x015e, 0x002e, 0x2001,
-	0x015d, 0x201c, 0x831a, 0x2302, 0x2001, 0x0138, 0x2202, 0x004e,
-	0x003e, 0x002e, 0x00ee, 0x00fe, 0x0005, 0x700c, 0x7110, 0xa106,
-	0x0904, 0x182c, 0x2104, 0x7006, 0x2060, 0x8108, 0x211c, 0x8108,
-	0x2124, 0x8108, 0xa182, 0x953b, 0x0210, 0x2009, 0x9520, 0x7112,
-	0x8cff, 0x05a0, 0x6010, 0x2068, 0x2d58, 0x6828, 0xa406, 0x1598,
-	0x682c, 0xa306, 0x1580, 0x684c, 0xd0f4, 0x1540, 0x6850, 0xd0f4,
-	0x1130, 0x7803, 0x0004, 0x6810, 0x781a, 0x6814, 0x781e, 0x6824,
-	0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, 0x000f,
-	0x6834, 0xa08c, 0x00ff, 0xa186, 0x0024, 0x0118, 0xa186, 0x002c,
-	0x1120, 0x2009, 0x0011, 0x00d9, 0x0038, 0x2009, 0x0011, 0x00b9,
-	0x0118, 0x2009, 0x0001, 0x0099, 0x2d58, 0x0005, 0x7803, 0x0004,
-	0x080c, 0x1be2, 0x0cd0, 0x601c, 0xa086, 0x0008, 0x1108, 0x0858,
-	0x080c, 0x1fa7, 0x1d98, 0x0838, 0x7003, 0x0000, 0x0005, 0x8aff,
-	0x0904, 0x191c, 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x11b8, 0xd0f4,
-	0x1538, 0x00d6, 0x2805, 0xac68, 0x2900, 0x0002, 0x18b6, 0x1867,
-	0x1867, 0x18b6, 0x18b9, 0x18ae, 0x18b6, 0x1867, 0x18b6, 0x1878,
-	0x1878, 0x18b6, 0x18b9, 0x18b6, 0x18a6, 0x1878, 0x7803, 0x0004,
-	0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0x00d6, 0xd99c,
-	0x0904, 0x1909, 0x2805, 0xac68, 0x6f08, 0x6e0c, 0x0804, 0x1909,
-	0xc0f4, 0x6852, 0x6b6c, 0x6a70, 0x00d6, 0x0804, 0x1910, 0x2d10,
-	0x00de, 0x00d6, 0x6834, 0x2268, 0xa084, 0x00ff, 0xa096, 0x0024,
-	0x0904, 0x18e9, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x0804, 0x1909,
-	0x2d10, 0x00de, 0x00d6, 0x6834, 0x2268, 0xa084, 0x00ff, 0xa096,
-	0x002c, 0x0904, 0x18c6, 0x7b0c, 0xd3bc, 0x01c0, 0x7004, 0x00e6,
-	0x2070, 0x701c, 0x00ee, 0xa086, 0x0008, 0x1180, 0x7b08, 0xa39c,
-	0x0fff, 0x2d20, 0x7a1c, 0x82ff, 0x1120, 0x7818, 0xa302, 0x0208,
-	0x7b18, 0xa016, 0x7a1e, 0x7b1a, 0x2468, 0x0010, 0x6b10, 0x6a14,
-	0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0804, 0x1909, 0x00de, 0x00d6,
-	0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x1140, 0x00de, 0x080c,
-	0x1f1b, 0x1904, 0x182f, 0xa00e, 0x0804, 0x191c, 0x00de, 0x080c,
-	0x13fe, 0x2d10, 0x00de, 0x00d6, 0x6834, 0x2268, 0xa084, 0x00ff,
-	0xa096, 0x0024, 0x0530, 0xa096, 0x002c, 0x1d80, 0x6b10, 0xa3a6,
-	0xffff, 0x1130, 0x2d10, 0x00de, 0x00d6, 0x080c, 0x59f4, 0x2268,
-	0x2d10, 0x00de, 0x00d6, 0x7314, 0x685c, 0xa086, 0x0001, 0x1120,
-	0x6868, 0xa005, 0x0108, 0x2018, 0x2268, 0x2011, 0x0000, 0x6d00,
-	0x6c04, 0x6f08, 0x6e0c, 0x780f, 0x00f0, 0xe000, 0xe000, 0xe000,
-	0x0400, 0x6b08, 0xa3a6, 0xffff, 0x1130, 0x2d10, 0x00de, 0x00d6,
-	0x080c, 0x59f4, 0x2268, 0x2d10, 0x00de, 0x00d6, 0x7314, 0x685c,
-	0xa086, 0x0001, 0x1120, 0x6868, 0xa005, 0x0108, 0x2018, 0x2268,
-	0x2011, 0x0000, 0x6d00, 0x6c04, 0x780f, 0x00f0, 0xe000, 0xe000,
-	0xe000, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902,
-	0x7000, 0x8000, 0x7002, 0x00de, 0x6828, 0xa300, 0x682a, 0x682c,
-	0xa201, 0x682e, 0x080c, 0x1f1b, 0x0005, 0x080c, 0x13fe, 0x7803,
-	0x0004, 0x7004, 0x2060, 0x00d6, 0x6010, 0x2068, 0x7003, 0x0000,
-	0x080c, 0x1c02, 0x080c, 0x82ee, 0x0170, 0x6808, 0x8001, 0x680a,
-	0x697c, 0x6912, 0x6980, 0x6916, 0x682b, 0xffff, 0x682f, 0xffff,
-	0x6850, 0xc0bd, 0x6852, 0x00de, 0x080c, 0x80f6, 0x0804, 0x1b4b,
-	0x080c, 0x13fe, 0x0126, 0x2091, 0x2200, 0x0006, 0x0016, 0x2b68,
-	0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, 0x1978,
-	0xa184, 0x0003, 0xa086, 0x0003, 0x0d58, 0x7000, 0x0002, 0x195f,
-	0x1961, 0x1aa6, 0x1b20, 0x1b3a, 0x195f, 0x195f, 0x195f, 0x080c,
-	0x13fe, 0x8001, 0x7002, 0xa184, 0x0880, 0x1904, 0x19a8, 0x6834,
-	0xa084, 0x00ff, 0xa086, 0x0024, 0x0130, 0x6834, 0xa084, 0x00ff,
-	0xa086, 0x002c, 0x1518, 0x6864, 0x8000, 0x6866, 0xd19c, 0x0140,
-	0x7004, 0x2060, 0x2009, 0x0102, 0x080c, 0x7518, 0x0804, 0x1a64,
-	0x8aff, 0x0130, 0x2009, 0x0001, 0x080c, 0x182f, 0x0804, 0x1b4b,
-	0x7004, 0x2060, 0x2009, 0x0106, 0x080c, 0x7518, 0x7007, 0x0000,
-	0x7803, 0x0009, 0x7003, 0x0003, 0x0804, 0x1b4b, 0xd19c, 0x1904,
-	0x1a49, 0x8aff, 0x0904, 0x1a49, 0x2009, 0x0001, 0x080c, 0x182f,
-	0x0904, 0x1b4b, 0x2009, 0x0001, 0x080c, 0x182f, 0x0804, 0x1b4b,
-	0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, 0x1904, 0x1a18, 0x6834,
-	0xa084, 0x00ff, 0xa086, 0x0024, 0x0130, 0x6834, 0xa084, 0x00ff,
-	0xa086, 0x002c, 0x1138, 0xd19c, 0x0128, 0x6864, 0x8000, 0x6866,
-	0x0804, 0x1978, 0x0026, 0x0036, 0x7c20, 0x7d24, 0x7e30, 0x7f34,
-	0x7818, 0x6812, 0x781c, 0x6816, 0x2001, 0x0201, 0x2004, 0xa005,
-	0x0140, 0x7808, 0xd0ec, 0x1128, 0x7803, 0x0009, 0x7003, 0x0004,
-	0x0070, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0024, 0x0140, 0x6834,
-	0xa084, 0x00ff, 0xa086, 0x002c, 0x0110, 0x080c, 0x1b4f, 0x6b28,
-	0x6a2c, 0x2400, 0x686e, 0xa31a, 0x2500, 0x6872, 0xa213, 0x6b2a,
-	0x6a2e, 0x003e, 0x002e, 0x6e1e, 0x6f22, 0x080c, 0x1f31, 0x2a00,
-	0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x6850, 0xc0fd, 0x6852,
-	0x6808, 0x8001, 0x680a, 0x1148, 0x684c, 0xd0e4, 0x0130, 0x7004,
-	0x2060, 0x2009, 0x0048, 0x080c, 0x7518, 0x7000, 0xa086, 0x0004,
-	0x0904, 0x1b4b, 0x7003, 0x0000, 0x080c, 0x17d5, 0x0804, 0x1b4b,
-	0x0056, 0x7d0c, 0xd5bc, 0x1110, 0x080c, 0x9171, 0x005e, 0x080c,
-	0x1c02, 0x7004, 0x7007, 0x0000, 0x2060, 0x601c, 0xa086, 0x0009,
-	0x1198, 0x790c, 0x0016, 0x2009, 0x0106, 0x080c, 0x7518, 0x001e,
-	0xd0ec, 0x1118, 0x2009, 0x0009, 0x0010, 0x2009, 0x0019, 0x7902,
-	0x7003, 0x0003, 0x0804, 0x1b4b, 0x682b, 0xffff, 0x682f, 0xffff,
-	0x6808, 0x8001, 0x680a, 0x697c, 0x791a, 0x6980, 0x791e, 0x0804,
-	0x1b4b, 0x7818, 0x6812, 0x7a1c, 0x6a16, 0xd19c, 0x0118, 0xa205,
-	0x1904, 0x19a8, 0x684c, 0xc0f5, 0x684e, 0x7814, 0xa005, 0x1180,
-	0x7003, 0x0000, 0x6808, 0x8001, 0x680a, 0x1130, 0x7004, 0x2060,
-	0x2009, 0x0048, 0x080c, 0x7518, 0x080c, 0x17d5, 0x0804, 0x1b4b,
-	0x7818, 0x6812, 0x781c, 0x6816, 0x7814, 0x7908, 0xa18c, 0x0fff,
-	0xa188, 0x0007, 0x8114, 0x8214, 0x8214, 0xa10a, 0x8104, 0x8004,
-	0x8004, 0xa20a, 0x810b, 0x810b, 0x810b, 0x080c, 0x1c40, 0x7803,
-	0x0004, 0x780f, 0xffff, 0x7803, 0x0001, 0x7804, 0xd0fc, 0x0de8,
-	0x7803, 0x0002, 0x7803, 0x0004, 0x780f, 0x00f0, 0x7004, 0x7007,
-	0x0000, 0x2060, 0x2009, 0x0048, 0x080c, 0x7518, 0x080c, 0x1c62,
-	0x0958, 0x7908, 0xd1ec, 0x1118, 0x2009, 0x0009, 0x0010, 0x2009,
-	0x0019, 0x7902, 0x7003, 0x0003, 0x0804, 0x1b4b, 0x8001, 0x7002,
-	0xd194, 0x0178, 0x7804, 0xd0fc, 0x1904, 0x194a, 0xd09c, 0x11a8,
-	0x8aff, 0x0904, 0x1b4b, 0x2009, 0x0001, 0x080c, 0x182f, 0x0804,
-	0x1b4b, 0xa184, 0x0888, 0x1148, 0x8aff, 0x0904, 0x1b4b, 0x2009,
-	0x0001, 0x080c, 0x182f, 0x0804, 0x1b4b, 0x7803, 0x0004, 0x7003,
-	0x0000, 0xd1bc, 0x1904, 0x1b0d, 0x0026, 0x0036, 0x7c20, 0x7d24,
-	0x7e30, 0x7f34, 0x7818, 0x6812, 0x781c, 0x6816, 0x2001, 0x0201,
-	0x2004, 0xa005, 0x0140, 0x7808, 0xd0ec, 0x1128, 0x7803, 0x0009,
-	0x7003, 0x0004, 0x0020, 0x0016, 0x080c, 0x1b4f, 0x001e, 0x6b28,
-	0x6a2c, 0x080c, 0x1f31, 0x00d6, 0x2805, 0xac68, 0x6034, 0xd09c,
-	0x1128, 0x6808, 0xa31a, 0x680c, 0xa213, 0x0020, 0x6810, 0xa31a,
-	0x6814, 0xa213, 0x00de, 0xd194, 0x0904, 0x19e9, 0x2a00, 0x6826,
-	0x2c00, 0x681a, 0x2800, 0x6832, 0x6808, 0x8001, 0x680a, 0x6b2a,
-	0x6a2e, 0x003e, 0x002e, 0x0804, 0x1a64, 0x0056, 0x7d0c, 0x080c,
-	0x9171, 0x005e, 0x080c, 0x1c02, 0x682b, 0xffff, 0x682f, 0xffff,
-	0x6808, 0x8001, 0x680a, 0x697c, 0x791a, 0x6980, 0x791e, 0x0458,
-	0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0xa00d, 0x0180, 0x6808,
-	0x8001, 0x680a, 0x1160, 0x7004, 0x2060, 0x2009, 0x0048, 0x601c,
-	0xa086, 0x0009, 0x1110, 0x080c, 0x13fe, 0x080c, 0x7518, 0x080c,
-	0x17d5, 0x0088, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060,
-	0x6010, 0xa005, 0x0da0, 0x2068, 0x6808, 0x8000, 0x680a, 0x6c28,
-	0x6b2c, 0x080c, 0x17e8, 0x001e, 0x000e, 0x012e, 0x0005, 0x700c,
-	0x7110, 0xa106, 0x0904, 0x1bd6, 0x7004, 0x0016, 0x210c, 0xa106,
-	0x001e, 0x0904, 0x1bd6, 0x00d6, 0x00c6, 0x216c, 0x2d00, 0xa005,
-	0x0904, 0x1bd4, 0x6810, 0x2068, 0x6834, 0xa084, 0x00ff, 0xa086,
-	0x0024, 0x0904, 0x1bd4, 0x6834, 0xa084, 0x00ff, 0xa086, 0x002c,
-	0x0904, 0x1bd4, 0x6850, 0xd0fc, 0x0558, 0x8108, 0x2104, 0x6b2c,
-	0xa306, 0x1904, 0x1bd4, 0x8108, 0x2104, 0x6a28, 0xa206, 0x1904,
-	0x1bd4, 0x6850, 0xc0fc, 0xc0f5, 0x6852, 0x686c, 0x7822, 0x6870,
-	0x7826, 0x681c, 0x7832, 0x6820, 0x7836, 0x6818, 0x2060, 0x6034,
-	0xd09c, 0x0150, 0x6830, 0x2005, 0x00d6, 0xac68, 0x6808, 0x783a,
-	0x680c, 0x783e, 0x00de, 0x0490, 0xa006, 0x783a, 0x783e, 0x0470,
-	0x8108, 0x2104, 0xa005, 0x1580, 0x8108, 0x2104, 0xa005, 0x1560,
-	0x6850, 0xc0f5, 0x6852, 0x6830, 0x2005, 0x6918, 0xa160, 0x6834,
-	0xd09c, 0x1170, 0x6008, 0x7822, 0x686e, 0x600c, 0x7826, 0x6872,
-	0x6000, 0x7832, 0x6004, 0x7836, 0xa006, 0x783a, 0x783e, 0x0070,
-	0x6010, 0x7822, 0x686e, 0x6014, 0x7826, 0x6872, 0x6000, 0x7832,
-	0x6004, 0x7836, 0x6008, 0x783a, 0x600c, 0x783e, 0x6810, 0x781a,
-	0x6814, 0x781e, 0x7803, 0x0011, 0x00ce, 0x00de, 0x0005, 0x2011,
-	0x0201, 0x2009, 0x003c, 0x2204, 0xa005, 0x1118, 0x8109, 0x1dd8,
-	0x0005, 0x0005, 0x0ca1, 0x01e0, 0x7908, 0xd1ec, 0x1160, 0x080c,
-	0x1c62, 0x0148, 0x7803, 0x0009, 0x7904, 0xd1fc, 0x0de8, 0x7803,
-	0x0006, 0x0c29, 0x0168, 0x780c, 0xd0a4, 0x1150, 0x7007, 0x0000,
-	0x080c, 0x1c62, 0x0130, 0x7803, 0x0019, 0x7003, 0x0003, 0x0008,
-	0x0009, 0x0005, 0x00c6, 0x0411, 0x20e1, 0x9028, 0x700c, 0x7110,
-	0xa106, 0x0190, 0x2104, 0xa005, 0x0130, 0x2060, 0x6010, 0x2060,
-	0x6008, 0x8001, 0x600a, 0xa188, 0x0003, 0xa182, 0x953b, 0x0210,
-	0x2009, 0x9520, 0x7112, 0x0c50, 0x2001, 0x015d, 0x200c, 0x810a,
-	0x2102, 0x2001, 0x0138, 0x2202, 0x00ce, 0x0005, 0x2001, 0x0138,
-	0x2014, 0x2003, 0x0000, 0x2021, 0xb015, 0x2001, 0x0141, 0x201c,
-	0xd3dc, 0x1168, 0x2001, 0x0109, 0x201c, 0xa39c, 0x0048, 0x1138,
-	0x2001, 0x0111, 0x201c, 0x83ff, 0x1110, 0x8421, 0x1d70, 0x0005,
-	0x3c00, 0x0006, 0x00e6, 0x2071, 0x0200, 0x7808, 0xa084, 0xf000,
-	0xa10d, 0x08e1, 0x20e1, 0x7000, 0x7324, 0x7420, 0x7028, 0x7028,
-	0x7426, 0x7037, 0x0001, 0x810f, 0x712e, 0x702f, 0x0100, 0x7037,
-	0x0008, 0x7326, 0x7422, 0x2001, 0x0138, 0x2202, 0x00ee, 0x000e,
+	0x7003, 0x0003, 0x7007, 0x0000, 0x0018, 0x080c, 0x18ee, 0x08d0,
+	0x0156, 0x20a9, 0x0009, 0x2009, 0x8de4, 0x2104, 0xac06, 0x1108,
+	0x200a, 0xa188, 0x0003, 0x1f04, 0x17d5, 0x015e, 0x005e, 0x002e,
+	0x2001, 0x015d, 0x201c, 0x831a, 0x2302, 0x2001, 0x0160, 0x2502,
+	0x2001, 0x0138, 0x2202, 0x005e, 0x004e, 0x003e, 0x002e, 0x00ee,
+	0x00fe, 0x0005, 0x700c, 0x7110, 0xa106, 0x0904, 0x1841, 0x2104,
+	0x7006, 0x2060, 0x8108, 0x211c, 0x8108, 0x2124, 0x8108, 0xa182,
+	0x8dff, 0x0210, 0x2009, 0x8de4, 0x7112, 0x700c, 0xa106, 0x1120,
+	0x2001, 0x0138, 0x2003, 0x0008, 0x8cff, 0x0538, 0x6010, 0x2068,
+	0x2d58, 0x6828, 0xa406, 0x1520, 0x682c, 0xa306, 0x1508, 0x684c,
+	0xd0f4, 0x11d8, 0x6850, 0xd0f4, 0x1130, 0x7803, 0x0004, 0x6810,
+	0x781a, 0x6814, 0x781e, 0x6824, 0x2050, 0x6818, 0x2060, 0x6830,
+	0x2040, 0x6034, 0xa0cc, 0x000f, 0x2009, 0x0011, 0x00a9, 0x0118,
+	0x2009, 0x0001, 0x0089, 0x2d58, 0x0005, 0x080c, 0x1b10, 0x0ce0,
+	0x601c, 0xa086, 0x0008, 0x1108, 0x08d0, 0x080c, 0x1e96, 0x1da8,
+	0x08b0, 0x7003, 0x0000, 0x0005, 0x8aff, 0x0904, 0x18c8, 0xa03e,
+	0x2730, 0x6850, 0xd0fc, 0x11b8, 0xd0f4, 0x1538, 0x00d6, 0x2805,
+	0xac68, 0x2900, 0x0002, 0x18b2, 0x187c, 0x187c, 0x18b2, 0x18b2,
+	0x18ab, 0x18b2, 0x187c, 0x18b2, 0x1881, 0x1881, 0x18b2, 0x18b2,
+	0x18b2, 0x18a3, 0x1881, 0x7803, 0x0004, 0xc0fc, 0x6852, 0x6b6c,
+	0x6a70, 0x6d1c, 0x6c20, 0x00d6, 0xd99c, 0x0904, 0x18b5, 0x2805,
+	0xac68, 0x6f08, 0x6e0c, 0x0804, 0x18b5, 0xc0f4, 0x6852, 0x6b6c,
+	0x6a70, 0x00d6, 0x0804, 0x18bc, 0x6b08, 0x6a0c, 0x6d00, 0x6c04,
+	0x04a0, 0x7b0c, 0xd3bc, 0x01c0, 0x7004, 0x00e6, 0x2070, 0x701c,
+	0x00ee, 0xa086, 0x0008, 0x1180, 0x7b08, 0xa39c, 0x0fff, 0x2d20,
+	0x7a1c, 0x82ff, 0x1120, 0x7818, 0xa302, 0x0208, 0x7b18, 0xa016,
+	0x7a1e, 0x7b1a, 0x2468, 0x0010, 0x6b10, 0x6a14, 0x6d00, 0x6c04,
+	0x6f08, 0x6e0c, 0x0090, 0x00de, 0x00d6, 0x6834, 0xa084, 0x00ff,
+	0xa086, 0x001e, 0x1138, 0x00de, 0x080c, 0x1e38, 0x1904, 0x1844,
+	0xa00e, 0x00b0, 0x00de, 0x080c, 0x1410, 0x7b22, 0x7a26, 0x7d32,
+	0x7c36, 0x7f3a, 0x7e3e, 0x7902, 0x7000, 0x8000, 0x7002, 0x00de,
+	0x6828, 0xa300, 0x682a, 0x682c, 0xa201, 0x682e, 0x080c, 0x1e38,
+	0x0005, 0x080c, 0x1410, 0x7803, 0x0004, 0x7004, 0x2060, 0x00d6,
+	0x6010, 0x2068, 0x7003, 0x0000, 0x080c, 0x1b30, 0x080c, 0x7b8f,
+	0x0170, 0x6808, 0x8001, 0x680a, 0x697c, 0x6912, 0x6980, 0x6916,
+	0x682b, 0xffff, 0x682f, 0xffff, 0x6850, 0xc0bd, 0x6852, 0x00de,
+	0x080c, 0x795f, 0x0804, 0x1a87, 0x080c, 0x1410, 0x0126, 0x2091,
+	0x2200, 0x0006, 0x0016, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803,
+	0x0002, 0xa184, 0x0700, 0x1978, 0xa184, 0x0003, 0xa086, 0x0003,
+	0x0d58, 0x7000, 0x0002, 0x190b, 0x190d, 0x19e8, 0x1a62, 0x1a76,
+	0x190b, 0x190b, 0x190b, 0x080c, 0x1410, 0x8001, 0x7002, 0xa184,
+	0x0880, 0x1190, 0xd19c, 0x1904, 0x198b, 0x8aff, 0x0904, 0x198b,
+	0x2009, 0x0001, 0x080c, 0x1844, 0x0904, 0x1a87, 0x2009, 0x0001,
+	0x080c, 0x1844, 0x0804, 0x1a87, 0x7803, 0x0004, 0x7003, 0x0000,
+	0xd1bc, 0x1904, 0x1975, 0x0026, 0x0036, 0x7c20, 0x7d24, 0x7e30,
+	0x7f34, 0x7818, 0x6812, 0x781c, 0x6816, 0x2001, 0x0201, 0x2004,
+	0xa005, 0x0140, 0x7808, 0xd0ec, 0x1128, 0x7803, 0x0009, 0x7003,
+	0x0004, 0x0010, 0x080c, 0x1a8b, 0x6b28, 0x6a2c, 0x2400, 0x686e,
+	0xa31a, 0x2500, 0x6872, 0xa213, 0x6b2a, 0x6a2e, 0x003e, 0x002e,
+	0x6e1e, 0x6f22, 0x080c, 0x1e4e, 0x2a00, 0x6826, 0x2c00, 0x681a,
+	0x2800, 0x6832, 0x6850, 0xc0fd, 0x6852, 0x6808, 0x8001, 0x680a,
+	0x1148, 0x684c, 0xd0e4, 0x0130, 0x7004, 0x2060, 0x2009, 0x0048,
+	0x080c, 0x6d3f, 0x7000, 0xa086, 0x0004, 0x0904, 0x1a87, 0x7003,
+	0x0000, 0x080c, 0x17f2, 0x0804, 0x1a87, 0x0056, 0x7d0c, 0xd5bc,
+	0x1110, 0x080c, 0x8a1c, 0x005e, 0x080c, 0x1b30, 0x682b, 0xffff,
+	0x682f, 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x791a, 0x6980,
+	0x791e, 0x0804, 0x1a87, 0x7818, 0x6812, 0x7a1c, 0x6a16, 0xd19c,
+	0x0118, 0xa205, 0x1904, 0x1924, 0x684c, 0xc0f5, 0x684e, 0x7814,
+	0xa005, 0x1180, 0x7003, 0x0000, 0x6808, 0x8001, 0x680a, 0x1130,
+	0x7004, 0x2060, 0x2009, 0x0048, 0x080c, 0x6d3f, 0x080c, 0x17f2,
+	0x0804, 0x1a87, 0x7818, 0x6812, 0x781c, 0x6816, 0x7814, 0x7908,
+	0xa18c, 0x0fff, 0xa188, 0x0007, 0x8114, 0x8214, 0x8214, 0xa10a,
+	0x8104, 0x8004, 0x8004, 0xa20a, 0x810b, 0x810b, 0x810b, 0x080c,
+	0x1b7d, 0x7803, 0x0004, 0x780f, 0xffff, 0x7803, 0x0001, 0x7804,
+	0xd0fc, 0x0de8, 0x7803, 0x0002, 0x7803, 0x0004, 0x780f, 0x00f6,
+	0x7004, 0x7007, 0x0000, 0x2060, 0x2009, 0x0048, 0x080c, 0x6d3f,
+	0x080c, 0x1ba2, 0x0958, 0x7908, 0xd1ec, 0x1118, 0x2009, 0x0009,
+	0x0010, 0x2009, 0x0019, 0x7902, 0x7003, 0x0003, 0x0804, 0x1a87,
+	0x8001, 0x7002, 0xd194, 0x0178, 0x7804, 0xd0fc, 0x1904, 0x18f6,
+	0xd09c, 0x11a8, 0x8aff, 0x0904, 0x1a87, 0x2009, 0x0001, 0x080c,
+	0x1844, 0x0804, 0x1a87, 0xa184, 0x0888, 0x1148, 0x8aff, 0x0904,
+	0x1a87, 0x2009, 0x0001, 0x080c, 0x1844, 0x0804, 0x1a87, 0x7803,
+	0x0004, 0x7003, 0x0000, 0xd1bc, 0x1904, 0x1a4f, 0x0026, 0x0036,
+	0x7c20, 0x7d24, 0x7e30, 0x7f34, 0x7818, 0x6812, 0x781c, 0x6816,
+	0x2001, 0x0201, 0x2004, 0xa005, 0x0140, 0x7808, 0xd0ec, 0x1128,
+	0x7803, 0x0009, 0x7003, 0x0004, 0x0020, 0x0016, 0x080c, 0x1a8b,
+	0x001e, 0x6b28, 0x6a2c, 0x080c, 0x1e4e, 0x00d6, 0x2805, 0xac68,
+	0x6034, 0xd09c, 0x1128, 0x6808, 0xa31a, 0x680c, 0xa213, 0x0020,
+	0x6810, 0xa31a, 0x6814, 0xa213, 0x00de, 0xd194, 0x0904, 0x1946,
+	0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x6808, 0x8001,
+	0x680a, 0x6b2a, 0x6a2e, 0x003e, 0x002e, 0x0804, 0x19a6, 0x0056,
+	0x7d0c, 0x080c, 0x8a1c, 0x005e, 0x080c, 0x1b30, 0x682b, 0xffff,
+	0x682f, 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x791a, 0x6980,
+	0x791e, 0x0428, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0xa00d,
+	0x0150, 0x6808, 0x8001, 0x680a, 0x1130, 0x7004, 0x2060, 0x2009,
+	0x0048, 0x080c, 0x6d3f, 0x080c, 0x17f2, 0x0088, 0x7803, 0x0004,
+	0x7003, 0x0000, 0x7004, 0x2060, 0x6010, 0xa005, 0x0da0, 0x2068,
+	0x6808, 0x8000, 0x680a, 0x6c28, 0x6b2c, 0x080c, 0x180c, 0x001e,
+	0x000e, 0x012e, 0x0005, 0x700c, 0x7110, 0xa106, 0x0904, 0x1b04,
+	0x7004, 0x0016, 0x210c, 0xa106, 0x001e, 0x0904, 0x1b04, 0x00d6,
+	0x00c6, 0x216c, 0x2d00, 0xa005, 0x0904, 0x1b02, 0x6810, 0x2068,
+	0x6850, 0xd0fc, 0x0558, 0x8108, 0x2104, 0x6b2c, 0xa306, 0x1904,
+	0x1b02, 0x8108, 0x2104, 0x6a28, 0xa206, 0x1904, 0x1b02, 0x6850,
+	0xc0fc, 0xc0f5, 0x6852, 0x686c, 0x7822, 0x6870, 0x7826, 0x681c,
+	0x7832, 0x6820, 0x7836, 0x6818, 0x2060, 0x6034, 0xd09c, 0x0150,
+	0x6830, 0x2005, 0x00d6, 0xac68, 0x6808, 0x783a, 0x680c, 0x783e,
+	0x00de, 0x0490, 0xa006, 0x783a, 0x783e, 0x0470, 0x8108, 0x2104,
+	0xa005, 0x1580, 0x8108, 0x2104, 0xa005, 0x1560, 0x6850, 0xc0f5,
+	0x6852, 0x6830, 0x2005, 0x6918, 0xa160, 0x6834, 0xd09c, 0x1170,
+	0x6008, 0x7822, 0x686e, 0x600c, 0x7826, 0x6872, 0x6000, 0x7832,
+	0x6004, 0x7836, 0xa006, 0x783a, 0x783e, 0x0070, 0x6010, 0x7822,
+	0x686e, 0x6014, 0x7826, 0x6872, 0x6000, 0x7832, 0x6004, 0x7836,
+	0x6008, 0x783a, 0x600c, 0x783e, 0x6810, 0x781a, 0x6814, 0x781e,
+	0x7803, 0x0011, 0x00ce, 0x00de, 0x0005, 0x2011, 0x0201, 0x2009,
+	0x003c, 0x2204, 0xa005, 0x1118, 0x8109, 0x1dd8, 0x0005, 0x0005,
+	0x0ca1, 0x01e0, 0x7908, 0xd1ec, 0x1160, 0x080c, 0x1ba2, 0x0148,
+	0x7803, 0x0009, 0x7904, 0xd1fc, 0x0de8, 0x7803, 0x0006, 0x0c29,
+	0x0168, 0x780c, 0xd0a4, 0x1150, 0x7007, 0x0000, 0x080c, 0x1ba2,
+	0x0130, 0x7803, 0x0019, 0x7003, 0x0003, 0x0008, 0x0009, 0x0005,
+	0x00c6, 0x0461, 0x20e1, 0x9028, 0x700c, 0x7110, 0xa106, 0x01c8,
+	0x2104, 0xa005, 0x0130, 0x2060, 0x6010, 0x2060, 0x6008, 0x8001,
+	0x600a, 0xa188, 0x0003, 0xa182, 0x8dff, 0x0210, 0x2009, 0x8de4,
+	0x7112, 0x700c, 0xa106, 0x1d40, 0x2001, 0x0138, 0x2003, 0x0008,
+	0x0c18, 0x2001, 0x015d, 0x200c, 0x810a, 0x2102, 0x2001, 0x0160,
+	0x2502, 0x2001, 0x0138, 0x2202, 0x00ce, 0x0005, 0x2001, 0x0138,
+	0x2014, 0x2003, 0x0000, 0x2001, 0x0160, 0x202c, 0x2003, 0x0000,
+	0x2021, 0xb015, 0x2001, 0x0141, 0x201c, 0xd3dc, 0x1168, 0x2001,
+	0x0109, 0x201c, 0xa39c, 0x0048, 0x1138, 0x2001, 0x0111, 0x201c,
+	0x83ff, 0x1110, 0x8421, 0x1d70, 0x0005, 0x3c00, 0x0006, 0x00e6,
+	0x2071, 0x0200, 0x7808, 0xa084, 0xf000, 0xa10d, 0x08b9, 0x20e1,
+	0x7000, 0x7324, 0x7420, 0x7028, 0x7028, 0x7426, 0x7037, 0x0001,
+	0x810f, 0x712e, 0x702f, 0x0100, 0x7037, 0x0008, 0x7326, 0x7422,
+	0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x00ee, 0x000e,
 	0x20e0, 0x0005, 0x3c00, 0x0006, 0x7908, 0xa18c, 0x0fff, 0xa182,
 	0x0009, 0x0218, 0xa085, 0x0001, 0x0088, 0x2001, 0x020a, 0x81ff,
 	0x0130, 0x20e1, 0x6000, 0x200c, 0x200c, 0x200c, 0x200c, 0x20e1,
 	0x7000, 0x200c, 0x200c, 0x7003, 0x0000, 0xa006, 0x000e, 0x20e0,
-	0x0005, 0x00e6, 0x2071, 0x953b, 0x7003, 0x0000, 0x00ee, 0x0005,
-	0x00d6, 0xa280, 0x0004, 0x206c, 0x694c, 0xd1dc, 0x1904, 0x1d0d,
-	0x6934, 0xa184, 0x0007, 0x0002, 0x1c9c, 0x1cf8, 0x1c9c, 0x1c9e,
-	0x1c9c, 0x1cdf, 0x1cbe, 0x1cad, 0x080c, 0x13fe, 0x2100, 0xa084,
-	0x00ff, 0xa086, 0x0013, 0x0904, 0x1cf8, 0x2100, 0xa084, 0x00ff,
-	0xa086, 0x001b, 0x0904, 0x1cf8, 0x0c78, 0x684c, 0xd0b4, 0x0904,
-	0x1e15, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, 0x687c,
-	0x680a, 0x6880, 0x680e, 0x6958, 0x0804, 0x1d00, 0x6834, 0xa084,
-	0x00ff, 0xa086, 0x001e, 0x19c0, 0x684c, 0xd0b4, 0x0904, 0x1e15,
-	0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, 0x680a,
-	0x6880, 0x680e, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084,
-	0x000f, 0xa080, 0x1f59, 0x2005, 0x6832, 0x6958, 0x0450, 0xa18c,
-	0x00ff, 0xa186, 0x0015, 0x1548, 0x684c, 0xd0b4, 0x0904, 0x1e15,
-	0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080,
-	0x1f59, 0x2005, 0x6832, 0x6958, 0xa006, 0x682e, 0x682a, 0x0088,
-	0x684c, 0xd0b4, 0x0904, 0x191d, 0x6958, 0xa006, 0x682e, 0x682a,
-	0x2d00, 0x681a, 0x6834, 0xa084, 0x000f, 0xa080, 0x1f59, 0x2005,
-	0x6832, 0x6926, 0x684c, 0xc0dd, 0x684e, 0x00de, 0x0005, 0x00f6,
-	0x2079, 0x0020, 0x7804, 0xd0fc, 0x190c, 0x1e3b, 0x00e6, 0x00d6,
-	0x2071, 0x953b, 0x7000, 0xa005, 0x1904, 0x1d81, 0x00c6, 0x7206,
-	0xa280, 0x0004, 0x205c, 0x7004, 0x2068, 0x7803, 0x0004, 0x6818,
-	0x00d6, 0x2068, 0x686c, 0x7812, 0x6890, 0x00f6, 0x20e1, 0x9040,
-	0x2079, 0x0200, 0x781a, 0x2079, 0x0100, 0x8004, 0x78d6, 0x00fe,
-	0x00de, 0x2b68, 0x6824, 0x2050, 0x6818, 0x2060, 0x6830, 0x2040,
-	0x6034, 0xa0cc, 0x000f, 0x6908, 0xa184, 0x0007, 0x0128, 0x0016,
-	0x2009, 0x0008, 0xa102, 0x001e, 0xa108, 0x791a, 0x7116, 0x701e,
-	0x680c, 0xa081, 0x0000, 0x781e, 0x701a, 0xa006, 0x700e, 0x7012,
-	0x7004, 0x692c, 0x6814, 0xa106, 0x1120, 0x6928, 0x6810, 0xa106,
-	0x0158, 0x0036, 0x0046, 0x6b14, 0x6c10, 0x080c, 0x1fa7, 0x004e,
-	0x003e, 0x0110, 0x00ce, 0x00a8, 0x8aff, 0x1120, 0x00ce, 0xa085,
-	0x0001, 0x0078, 0x0126, 0x2091, 0x8000, 0x2079, 0x0020, 0x2009,
-	0x0001, 0x0059, 0x0118, 0x2009, 0x0001, 0x0039, 0x012e, 0x00ce,
-	0xa006, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x0076, 0x0066, 0x0056,
-	0x0046, 0x0036, 0x0026, 0x8aff, 0x0904, 0x1e0e, 0x700c, 0x7214,
-	0xa23a, 0x7010, 0x7218, 0xa203, 0x0a04, 0x1e0d, 0xa705, 0x0904,
-	0x1e0d, 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x11a8, 0x00d6, 0x2805,
-	0xac68, 0x2900, 0x0002, 0x1ddc, 0x1dc1, 0x1dc1, 0x1ddc, 0x1ddc,
-	0x1dd5, 0x1ddc, 0x1dc1, 0x1ddc, 0x1dc6, 0x1dc6, 0x1ddc, 0x1ddc,
-	0x1ddc, 0x1dcd, 0x1dc6, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c,
-	0x6c20, 0xd99c, 0x05c8, 0x00d6, 0x2805, 0xac68, 0x6f08, 0x6e0c,
-	0x0490, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x0468, 0x6b10, 0x6a14,
-	0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0430, 0x00de, 0x00d6, 0x6834,
-	0xa084, 0x00ff, 0xa086, 0x001e, 0x1138, 0x00de, 0x080c, 0x1f1b,
-	0x1904, 0x1d8b, 0xa00e, 0x0490, 0x2d10, 0x00de, 0x00d6, 0x6834,
-	0xa084, 0x00ff, 0xa086, 0x0013, 0x2268, 0x09d8, 0x2d10, 0x00de,
-	0x00d6, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001b, 0x2268, 0x09b0,
-	0x00de, 0x080c, 0x13fe, 0x00de, 0x7b22, 0x7a26, 0x7d32, 0x7c36,
-	0x7f3a, 0x7e3e, 0x7902, 0x7000, 0x8000, 0x7002, 0x6828, 0xa300,
-	0x682a, 0x682c, 0xa201, 0x682e, 0x700c, 0xa300, 0x700e, 0x7010,
-	0xa201, 0x7012, 0x080c, 0x1f1b, 0x0008, 0xa006, 0x002e, 0x003e,
-	0x004e, 0x005e, 0x006e, 0x007e, 0x0005, 0x080c, 0x13fe, 0x2001,
-	0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003,
-	0x0000, 0x7004, 0x2060, 0x00d6, 0x6010, 0x2068, 0x080c, 0x82ee,
-	0x0118, 0x6850, 0xc0bd, 0x6852, 0x00de, 0x080c, 0x80f6, 0x20e1,
-	0x9040, 0x080c, 0x7366, 0x2011, 0x0000, 0x080c, 0x7199, 0x080c,
-	0x651c, 0x0804, 0x1ef0, 0x0126, 0x2091, 0x2400, 0x0006, 0x0016,
-	0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x2079, 0x0020, 0x2071, 0x953b,
-	0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700,
-	0x1930, 0x7000, 0x0002, 0x1ef0, 0x1e57, 0x1ec3, 0x1eee, 0x8001,
-	0x7002, 0xd19c, 0x1170, 0x8aff, 0x0540, 0x2009, 0x0001, 0x080c,
-	0x1d85, 0x0904, 0x1ef0, 0x2009, 0x0001, 0x080c, 0x1d85, 0x0804,
-	0x1ef0, 0x7803, 0x0004, 0xd194, 0x0148, 0x6850, 0xc0fc, 0x6852,
-	0x8aff, 0x1148, 0x684c, 0xc0f5, 0x684e, 0x0028, 0x080c, 0x1f31,
-	0x6850, 0xc0fd, 0x6852, 0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800,
-	0x6832, 0x7003, 0x0000, 0x0804, 0x1ef0, 0x711c, 0x81ff, 0x0190,
-	0x7918, 0x7922, 0x7827, 0x0000, 0x7803, 0x0001, 0x7000, 0x8000,
-	0x7002, 0x700c, 0xa100, 0x700e, 0x7010, 0xa081, 0x0000, 0x7012,
-	0x0804, 0x1ef0, 0x00f6, 0x0026, 0x781c, 0x0006, 0x7818, 0x0006,
-	0x2079, 0x0100, 0x7a14, 0xa284, 0x0004, 0xa085, 0x0012, 0x7816,
-	0x7820, 0xd0bc, 0x1de8, 0x79c8, 0x000e, 0xa102, 0x001e, 0x0006,
-	0x0016, 0x79c4, 0x000e, 0xa102, 0x78c6, 0x000e, 0x78ca, 0xa284,
-	0x0004, 0xa085, 0x0012, 0x7816, 0x002e, 0x00fe, 0x7803, 0x0008,
-	0x7003, 0x0000, 0x0468, 0x8001, 0x7002, 0xd194, 0x0168, 0x7804,
-	0xd0fc, 0x1904, 0x1e4b, 0xd19c, 0x11f8, 0x8aff, 0x0508, 0x2009,
-	0x0001, 0x080c, 0x1d85, 0x00e0, 0x0026, 0x0036, 0x6b28, 0x6a2c,
-	0x080c, 0x1f31, 0x00d6, 0x2805, 0xac68, 0x6034, 0xd09c, 0x1128,
-	0x6808, 0xa31a, 0x680c, 0xa213, 0x0020, 0x6810, 0xa31a, 0x6814,
-	0xa213, 0x00de, 0x0804, 0x1e76, 0x0804, 0x1e76, 0x080c, 0x13fe,
-	0x00ce, 0x00de, 0x00ee, 0x00fe, 0x001e, 0x000e, 0x012e, 0x0005,
-	0x00f6, 0x00e6, 0x2071, 0x953b, 0x7000, 0xa086, 0x0000, 0x01c0,
-	0x2079, 0x0020, 0x20e1, 0x9040, 0x7804, 0xd0fc, 0x0dd8, 0x080c,
-	0x1e3b, 0x7000, 0xa086, 0x0000, 0x1da8, 0x7803, 0x0004, 0x7804,
-	0xd0ac, 0x1de8, 0x20e1, 0x9040, 0x7803, 0x0002, 0x7003, 0x0000,
-	0x00ee, 0x00fe, 0x0005, 0x8840, 0x2805, 0xa005, 0x1170, 0x6004,
-	0xa005, 0x0168, 0x681a, 0x2060, 0x6034, 0xa084, 0x000f, 0xa080,
-	0x1f59, 0x2045, 0x88ff, 0x090c, 0x13fe, 0x8a51, 0x0005, 0x2050,
-	0x0005, 0x8a50, 0x8841, 0x2805, 0xa005, 0x1190, 0x2c00, 0xad06,
-	0x0120, 0x6000, 0xa005, 0x1108, 0x2d00, 0x2060, 0x681a, 0x6034,
-	0xa084, 0x000f, 0xa080, 0x1f69, 0x2045, 0x88ff, 0x090c, 0x13fe,
-	0x0005, 0x0000, 0x0011, 0x0015, 0x0019, 0x001d, 0x0021, 0x0025,
-	0x0029, 0x0000, 0x000f, 0x0015, 0x001b, 0x0021, 0x0027, 0x0000,
-	0x0000, 0x0000, 0x1f4e, 0x1f4a, 0x1f4e, 0x1f4e, 0x1f58, 0x0000,
-	0x1f4e, 0x0000, 0x1f55, 0x1f52, 0x1f55, 0x1f55, 0x0000, 0x1f58,
-	0x1f55, 0x0000, 0x1f50, 0x1f50, 0x0000, 0x1f50, 0x1f58, 0x0000,
-	0x1f50, 0x0000, 0x1f56, 0x1f56, 0x0000, 0x1f56, 0x0000, 0x1f58,
-	0x1f56, 0x0136, 0x0146, 0x0156, 0x2099, 0x9359, 0x20a1, 0x0018,
-	0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x0126, 0x2091, 0x8000,
-	0x7803, 0x0041, 0x7007, 0x0005, 0x7000, 0xc094, 0x7002, 0x700b,
-	0x9354, 0x012e, 0x015e, 0x014e, 0x013e, 0x0005, 0x2099, 0x0014,
-	0x7803, 0x0040, 0x2001, 0x9359, 0x2004, 0x2010, 0x080c, 0x59a7,
-	0x080c, 0x5949, 0x7007, 0x0000, 0x080c, 0x14ec, 0x0005, 0x00a6,
-	0x0096, 0x0086, 0x6858, 0xa055, 0x0904, 0x2036, 0x2d60, 0x6034,
-	0xa0cc, 0x000f, 0xa9c0, 0x1f59, 0xa986, 0x0007, 0x0130, 0xa986,
-	0x000e, 0x0118, 0xa986, 0x000f, 0x1120, 0x605c, 0xa422, 0x6060,
-	0xa31a, 0x2805, 0xa045, 0x1140, 0x0310, 0x0804, 0x2036, 0x6004,
-	0xa065, 0x0904, 0x2036, 0x0c18, 0x2805, 0xa005, 0x01a8, 0xac68,
-	0xd99c, 0x1128, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0020, 0x6810,
-	0xa422, 0x6814, 0xa31b, 0x0620, 0x2300, 0xa405, 0x0150, 0x8a51,
-	0x0904, 0x2036, 0x8840, 0x0c40, 0x6004, 0xa065, 0x0904, 0x2036,
-	0x0830, 0x8a51, 0x0904, 0x2036, 0x8840, 0x2805, 0xa005, 0x1158,
-	0x6004, 0xa065, 0x0904, 0x2036, 0x6034, 0xa0cc, 0x000f, 0xa9c0,
-	0x1f59, 0x2805, 0x2040, 0x2b68, 0x6850, 0xc0fc, 0x6852, 0x0458,
-	0x8422, 0x8420, 0x831a, 0xa399, 0x0000, 0x00d6, 0x2b68, 0x6c6e,
-	0x6b72, 0x00de, 0xd99c, 0x1168, 0x6908, 0x2400, 0xa122, 0x690c,
-	0x2300, 0xa11b, 0x0a0c, 0x13fe, 0x6800, 0xa420, 0x6804, 0xa319,
-	0x0060, 0x6910, 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b, 0x0a0c,
-	0x13fe, 0x6800, 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e, 0x6b22,
-	0x6850, 0xc0fd, 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832, 0x2a00,
-	0x6826, 0x000e, 0x000e, 0x000e, 0xa006, 0x0028, 0x008e, 0x009e,
-	0x00ae, 0xa085, 0x0001, 0x0005, 0x2001, 0x0005, 0x2004, 0xa084,
-	0x0007, 0x0002, 0x204a, 0x204b, 0x204e, 0x2051, 0x2056, 0x2059,
-	0x205e, 0x2063, 0x0005, 0x080c, 0x1e3b, 0x0005, 0x080c, 0x1942,
-	0x0005, 0x080c, 0x1942, 0x080c, 0x1e3b, 0x0005, 0x080c, 0x159c,
-	0x0005, 0x080c, 0x1e3b, 0x080c, 0x159c, 0x0005, 0x080c, 0x1942,
-	0x080c, 0x159c, 0x0005, 0x080c, 0x1942, 0x080c, 0x1e3b, 0x080c,
-	0x159c, 0x0005, 0x0126, 0x2091, 0x2600, 0x2079, 0x0200, 0x2071,
-	0x9780, 0x2069, 0x9200, 0x2009, 0x0004, 0x7912, 0x7817, 0x0004,
-	0x080c, 0x23e6, 0x781b, 0x0002, 0x783b, 0x001f, 0x20e1, 0x8700,
-	0x012e, 0x0005, 0x0126, 0x2091, 0x2600, 0x781c, 0xd0a4, 0x190c,
-	0x210b, 0xa084, 0x0007, 0x0002, 0x20a6, 0x2094, 0x2097, 0x209a,
-	0x209f, 0x20a1, 0x20a3, 0x20a5, 0x080c, 0x5338, 0x0078, 0x080c,
-	0x536c, 0x0060, 0x080c, 0x5338, 0x080c, 0x536c, 0x0038, 0x0041,
-	0x0028, 0x0031, 0x0018, 0x0021, 0x0008, 0x0011, 0x012e, 0x0005,
-	0x0006, 0x0016, 0x0026, 0x7930, 0xa184, 0x0003, 0x0118, 0x20e1,
-	0x9040, 0x00b8, 0xa184, 0x0030, 0x0150, 0x6a00, 0xa286, 0x0003,
-	0x1108, 0x0010, 0x080c, 0x4105, 0x20e1, 0x9010, 0x0050, 0xa184,
-	0x00c0, 0x0110, 0x080c, 0x13fe, 0xa184, 0x0300, 0x0110, 0x20e1,
-	0x9020, 0x7932, 0x002e, 0x001e, 0x000e, 0x0005, 0x0016, 0x00e6,
-	0x00f6, 0x2071, 0x9200, 0x7128, 0x2001, 0x94ca, 0x2102, 0x2001,
-	0x94d2, 0x2102, 0xa182, 0x0211, 0x1218, 0x2009, 0x0008, 0x0400,
-	0xa182, 0x0259, 0x1218, 0x2009, 0x0007, 0x00d0, 0xa182, 0x02c1,
-	0x1218, 0x2009, 0x0006, 0x00a0, 0xa182, 0x0349, 0x1218, 0x2009,
-	0x0005, 0x0070, 0xa182, 0x0421, 0x1218, 0x2009, 0x0004, 0x0040,
-	0xa182, 0x0581, 0x1218, 0x2009, 0x0003, 0x0010, 0x2009, 0x0002,
-	0x2079, 0x0200, 0x7912, 0x7817, 0x0004, 0x080c, 0x23e6, 0x00fe,
-	0x00ee, 0x001e, 0x0005, 0x7938, 0x080c, 0x13fe, 0x0126, 0x2091,
-	0x2400, 0x2061, 0x0100, 0x2071, 0x9200, 0x6024, 0x6026, 0x080c,
-	0x2425, 0x6050, 0xa084, 0xfe7f, 0x6052, 0x2009, 0x00ef, 0x6132,
-	0x6136, 0x080c, 0x2435, 0x60e7, 0x0000, 0x61ea, 0x60e3, 0x0008,
-	0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f, 0x0080, 0x602f, 0x0000,
-	0x6007, 0x0c9f, 0x600f, 0x03ff, 0x602b, 0x002f, 0x012e, 0x0005,
-	0x2001, 0x9230, 0x2003, 0x0000, 0x2001, 0x922f, 0x2003, 0x0001,
-	0x0005, 0x0126, 0x2091, 0x2400, 0x0006, 0x0016, 0x0026, 0x6124,
-	0x0066, 0x2031, 0x9232, 0x2634, 0xa6b4, 0x0028, 0x006e, 0x11c0,
-	0x6020, 0xd0bc, 0x01a8, 0xd1bc, 0x0198, 0x783c, 0xa005, 0x0180,
-	0x00e6, 0x0006, 0x2070, 0x701c, 0xa086, 0x0009, 0x000e, 0x00ee,
-	0x1138, 0x00e6, 0x783c, 0x2070, 0x7008, 0xd0fc, 0x00ee, 0x1130,
-	0xa184, 0x1c2c, 0x1118, 0xa184, 0x0007, 0x002a, 0xa195, 0x0004,
-	0xa284, 0x0007, 0x0002, 0x2195, 0x217b, 0x217e, 0x2181, 0x2186,
-	0x2188, 0x218c, 0x2190, 0x080c, 0x5ee3, 0x00b8, 0x080c, 0x5fbe,
-	0x00a0, 0x080c, 0x5fbe, 0x080c, 0x5ee3, 0x0078, 0x0099, 0x0068,
-	0x080c, 0x5ee3, 0x0079, 0x0048, 0x080c, 0x5fbe, 0x0059, 0x0028,
-	0x080c, 0x5fbe, 0x080c, 0x5ee3, 0x0029, 0x002e, 0x001e, 0x000e,
-	0x012e, 0x0005, 0xd19c, 0x1904, 0x238f, 0x080c, 0x4dc5, 0x01a0,
-	0x080c, 0x4deb, 0x15c0, 0x6024, 0xa084, 0x1800, 0x1108, 0x0498,
-	0x2001, 0x94d7, 0x2003, 0xaaaa, 0x2001, 0x94d8, 0x2003, 0x0001,
-	0x080c, 0x4d10, 0x0804, 0x238f, 0xd1ac, 0x1528, 0x6024, 0xd0dc,
-	0x1130, 0xd0e4, 0x1148, 0xd0d4, 0x1180, 0x0804, 0x238f, 0x2001,
-	0x94d8, 0x2003, 0x0000, 0x0068, 0xa085, 0x0001, 0x080c, 0x4e05,
-	0x2001, 0x94d8, 0x2003, 0x0002, 0x0020, 0x2001, 0x94d8, 0x2003,
-	0x0003, 0x0016, 0x2001, 0x9200, 0x2003, 0x0001, 0x080c, 0x4d10,
-	0x001e, 0x0804, 0x238f, 0x6220, 0xd1bc, 0x0568, 0xd2bc, 0x0558,
-	0x783c, 0xa005, 0x0540, 0x00e6, 0x2070, 0x7008, 0xd0fc, 0x00ee,
-	0x0510, 0x6028, 0xc0bc, 0x602a, 0x0026, 0x0036, 0x6288, 0x638c,
-	0x608b, 0xbc91, 0x608f, 0xffff, 0x6043, 0x0001, 0xe000, 0xe000,
-	0x6027, 0x0080, 0x6017, 0x0000, 0x6043, 0x0000, 0x628a, 0x638e,
-	0x003e, 0x002e, 0x0016, 0x2001, 0x9295, 0x200c, 0xc184, 0x2102,
-	0x001e, 0x0804, 0x23b6, 0xd1ac, 0x0904, 0x22d7, 0x080c, 0x4dc5,
-	0x1550, 0x6027, 0x0020, 0x0006, 0x0026, 0x0036, 0x2001, 0x94d8,
-	0x080c, 0x4de1, 0x11d8, 0x2011, 0x9225, 0x2204, 0xa005, 0x1140,
-	0x8000, 0x2012, 0x2011, 0x8036, 0x2019, 0x0001, 0x080c, 0x3698,
-	0x2001, 0x94d8, 0x2003, 0x0001, 0x2001, 0x9200, 0x2003, 0x0001,
-	0x080c, 0x4d10, 0x003e, 0x002e, 0x000e, 0x0005, 0x003e, 0x002e,
-	0x000e, 0x080c, 0x4ca5, 0x0016, 0x0046, 0x00c6, 0x644c, 0xa486,
-	0xf0f0, 0x1138, 0x2061, 0x0100, 0x644a, 0x6043, 0x0090, 0x6043,
-	0x0010, 0x74c6, 0xa48c, 0xff00, 0xa196, 0xff00, 0x01e8, 0x7050,
-	0xa084, 0x00ff, 0x810f, 0xa116, 0x01b8, 0x7130, 0xd18c, 0x11a0,
-	0x2011, 0x9252, 0x2214, 0xd2ec, 0x0118, 0xc18d, 0x7132, 0x0060,
-	0x6240, 0xa294, 0x0010, 0x0904, 0x22ad, 0x6248, 0xa294, 0xff00,
-	0xa296, 0xff00, 0x1904, 0x22ad, 0x70bc, 0xa005, 0x1138, 0x0036,
-	0x73c4, 0x2011, 0x8013, 0x080c, 0x3698, 0x003e, 0x7130, 0xc185,
-	0x7132, 0x2011, 0x9252, 0x220c, 0xd1a4, 0x01d0, 0x0016, 0x2009,
-	0x0001, 0x2011, 0x0100, 0x080c, 0x585b, 0x2019, 0x000e, 0x080c,
-	0x9071, 0xa484, 0x00ff, 0xa080, 0x2719, 0x200d, 0xa18c, 0xff00,
-	0x810f, 0x8127, 0xa006, 0x2009, 0x000e, 0x080c, 0x90d7, 0x001e,
-	0xd1ac, 0x1128, 0x2019, 0x0004, 0x080c, 0x264b, 0x0070, 0x0156,
-	0x20a9, 0x007f, 0x2009, 0x0000, 0x080c, 0x4434, 0x1110, 0x080c,
-	0x41e0, 0x8108, 0x1f04, 0x22a4, 0x015e, 0x00ce, 0x004e, 0x2011,
-	0x0003, 0x080c, 0x718f, 0x2011, 0x0002, 0x080c, 0x7199, 0x080c,
-	0x708d, 0x080c, 0x57a1, 0x0036, 0x2019, 0x0000, 0x080c, 0x7110,
-	0x003e, 0x60e3, 0x0000, 0x001e, 0x2001, 0x9200, 0x2014, 0xa296,
-	0x0004, 0x1128, 0xd19c, 0x1118, 0x6228, 0xc29d, 0x622a, 0x2003,
-	0x0001, 0x2001, 0x9222, 0x2003, 0x0000, 0x6027, 0x0020, 0xd194,
-	0x0904, 0x238f, 0x0016, 0x6220, 0xd2b4, 0x0904, 0x2340, 0x080c,
-	0x57a1, 0x080c, 0x6f1e, 0x6027, 0x0004, 0x00f6, 0x2019, 0x94ee,
-	0x2304, 0xa07d, 0x0570, 0x7804, 0xa086, 0x0032, 0x1550, 0x00d6,
-	0x00c6, 0x00e6, 0x2069, 0x0140, 0x618c, 0x6288, 0x7818, 0x608e,
-	0x7808, 0x608a, 0x6043, 0x0002, 0x2001, 0x0003, 0x8001, 0x1df0,
-	0x6043, 0x0000, 0x6803, 0x1000, 0x6803, 0x0000, 0x618e, 0x628a,
-	0x080c, 0x6389, 0x080c, 0x6462, 0x7810, 0x2070, 0x7037, 0x0103,
-	0x2f60, 0x080c, 0x74f2, 0x00ee, 0x00ce, 0x00de, 0x00fe, 0x001e,
-	0x0005, 0x00fe, 0x00d6, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000,
-	0x0120, 0x6803, 0x1000, 0x6803, 0x0000, 0x00de, 0x00c6, 0x2061,
-	0x94e5, 0x6028, 0xa09a, 0x0002, 0x1238, 0x8000, 0x602a, 0x00ce,
-	0x080c, 0x6f11, 0x0804, 0x238e, 0x2019, 0x94ee, 0x2304, 0xa065,
-	0x0120, 0x2009, 0x0027, 0x080c, 0x7518, 0x00ce, 0x0804, 0x238e,
-	0xd2bc, 0x0904, 0x238e, 0x080c, 0x57ae, 0x6017, 0x0010, 0x6027,
-	0x0004, 0x00d6, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0120,
-	0x6803, 0x1000, 0x6803, 0x0000, 0x00de, 0x00c6, 0x2061, 0x94e5,
-	0x6044, 0xa09a, 0x0002, 0x12e0, 0x8000, 0x6046, 0x603c, 0x00ce,
-	0xa005, 0x0560, 0x2009, 0x07d0, 0x080c, 0x57a6, 0xa080, 0x0007,
-	0x2004, 0xa086, 0x0006, 0x1118, 0x6017, 0x0012, 0x00f8, 0xa080,
-	0x0007, 0x2004, 0xa086, 0x0009, 0x0db8, 0x6017, 0x0016, 0x00b0,
-	0x0036, 0x2019, 0x0001, 0x080c, 0x7110, 0x003e, 0x2019, 0x94f4,
-	0x2304, 0xa065, 0x0150, 0x2009, 0x004f, 0x601c, 0xa086, 0x0009,
-	0x1110, 0x2009, 0x0105, 0x080c, 0x7518, 0x00ce, 0x001e, 0xd19c,
-	0x0528, 0x0016, 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, 0x080c,
-	0x718f, 0x2011, 0x0002, 0x080c, 0x7199, 0x080c, 0x708d, 0x080c,
-	0x57a1, 0x0036, 0x2019, 0x0000, 0x080c, 0x7110, 0x003e, 0x60e3,
-	0x0000, 0x080c, 0x918b, 0x080c, 0x91a6, 0x2001, 0x9200, 0x2003,
-	0x0004, 0x6027, 0x0008, 0x080c, 0x123f, 0x001e, 0xa18c, 0xffd0,
-	0x6126, 0x0005, 0x0006, 0x0016, 0x0026, 0x00e6, 0x00f6, 0x0126,
-	0x2091, 0x8000, 0x2071, 0x9200, 0x71bc, 0x70be, 0xa116, 0x01b8,
-	0x81ff, 0x0128, 0x2011, 0x8011, 0x080c, 0x3698, 0x0080, 0x2011,
-	0x8012, 0x080c, 0x3698, 0x0036, 0x00c6, 0x080c, 0x2480, 0x2061,
-	0x0100, 0x2019, 0x0028, 0x080c, 0x264b, 0x00ce, 0x003e, 0x012e,
-	0x00fe, 0x00ee, 0x002e, 0x001e, 0x000e, 0x0005, 0x00c6, 0x00f6,
-	0x0006, 0x0026, 0x2061, 0x0100, 0xa190, 0x23f9, 0x2205, 0x60f2,
-	0x2011, 0x2406, 0x2205, 0x60ee, 0x002e, 0x000e, 0x00fe, 0x00ce,
-	0x0005, 0x0840, 0x0840, 0x0840, 0x0580, 0x0420, 0x0348, 0x02c0,
-	0x0258, 0x0210, 0x01a8, 0x01a8, 0x01a8, 0x01a8, 0x0140, 0x00f8,
-	0x00d0, 0x00b0, 0x00a0, 0x2028, 0xa18c, 0x00ff, 0x2130, 0xa094,
-	0xff00, 0x1110, 0x81ff, 0x0118, 0x080c, 0x550c, 0x0038, 0xa080,
-	0x2719, 0x200d, 0xa18c, 0xff00, 0x810f, 0xa006, 0x0005, 0xa080,
-	0x2719, 0x200d, 0xa18c, 0x00ff, 0x0005, 0x00d6, 0x2069, 0x0140,
-	0x2001, 0x9214, 0x2003, 0x00ef, 0x20a9, 0x0010, 0xa006, 0x6852,
-	0x6856, 0x1f04, 0x2430, 0x00de, 0x0005, 0x0006, 0x00d6, 0x0026,
-	0x2069, 0x0140, 0x2001, 0x9214, 0x2102, 0x8114, 0x8214, 0x8214,
-	0x8214, 0x20a9, 0x0010, 0x6853, 0x0000, 0xa006, 0x82ff, 0x1128,
-	0xa184, 0x000f, 0xa080, 0x91ac, 0x2005, 0x6856, 0x8211, 0x1f04,
-	0x2445, 0x002e, 0x00de, 0x000e, 0x0005, 0x00c6, 0x2061, 0x9200,
-	0x6030, 0x0110, 0xc09d, 0x0008, 0xc09c, 0x6032, 0x00ce, 0x0005,
-	0x0156, 0x00d6, 0x0026, 0x0016, 0x0006, 0x2069, 0x0140, 0x6980,
-	0xa116, 0x0180, 0xa112, 0x1230, 0x8212, 0x8210, 0x22a8, 0x2001,
-	0x0402, 0x0018, 0x22a8, 0x2001, 0x0404, 0x680e, 0x1f04, 0x2475,
-	0x680f, 0x0000, 0x000e, 0x001e, 0x002e, 0x00de, 0x015e, 0x0005,
-	0x2001, 0x9252, 0x2004, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0xa006,
-	0x0046, 0x2020, 0x2009, 0x002e, 0x080c, 0x90d7, 0x004e, 0x0005,
-	0x24b0, 0x24b4, 0x24b8, 0x24be, 0x24c4, 0x24ca, 0x24d0, 0x24d8,
-	0x24df, 0x24e4, 0x24e9, 0x24f0, 0x24f7, 0x24fe, 0x2505, 0x250e,
-	0x2517, 0x2517, 0x2517, 0x2517, 0x2517, 0x2517, 0x2517, 0x2517,
-	0x2517, 0x2517, 0x2517, 0x2517, 0x2517, 0x2517, 0x2517, 0x2517,
-	0x0106, 0x0006, 0x0804, 0x2519, 0x0106, 0x0006, 0x0804, 0x2519,
-	0x0106, 0x0006, 0x080c, 0x2141, 0x0804, 0x2519, 0x0106, 0x0006,
-	0x080c, 0x2141, 0x0804, 0x2519, 0x0106, 0x0006, 0x080c, 0x203c,
-	0x0804, 0x2519, 0x0106, 0x0006, 0x080c, 0x203c, 0x0804, 0x2519,
-	0x0106, 0x0006, 0x080c, 0x2141, 0x080c, 0x203c, 0x0804, 0x2519,
-	0x0106, 0x0006, 0x080c, 0x2141, 0x080c, 0x203c, 0x04d0, 0x0106,
-	0x0006, 0x080c, 0x2082, 0x04a8, 0x0106, 0x0006, 0x080c, 0x2082,
-	0x0480, 0x0106, 0x0006, 0x080c, 0x2141, 0x080c, 0x2082, 0x0448,
-	0x0106, 0x0006, 0x080c, 0x2141, 0x080c, 0x2082, 0x0410, 0x0106,
-	0x0006, 0x080c, 0x203c, 0x080c, 0x2082, 0x00d8, 0x0106, 0x0006,
-	0x080c, 0x203c, 0x080c, 0x2082, 0x00a0, 0x0106, 0x0006, 0x080c,
-	0x2141, 0x080c, 0x203c, 0x080c, 0x2082, 0x0058, 0x0106, 0x0006,
-	0x080c, 0x2141, 0x080c, 0x203c, 0x080c, 0x2082, 0x0010, 0xe000,
-	0x0cf0, 0x000e, 0x010e, 0x000d, 0x00c6, 0x0026, 0x2041, 0x007e,
-	0x70c8, 0xd09c, 0x0110, 0x2041, 0x007f, 0xd094, 0x2001, 0x9214,
-	0x203c, 0x15d8, 0x7284, 0x82ff, 0x05c0, 0x0036, 0x7398, 0xa38e,
-	0xffff, 0x1110, 0x2019, 0x0001, 0x8314, 0xa2e0, 0x98c0, 0x2c04,
-	0xa38c, 0x0001, 0x0120, 0xa084, 0xff00, 0x8007, 0x0010, 0xa084,
-	0x00ff, 0xa70e, 0x01c8, 0xa08e, 0x00ff, 0x01d0, 0x2009, 0x0000,
-	0x080c, 0x240b, 0x080c, 0x4400, 0x1188, 0x6004, 0xa084, 0x00ff,
-	0xa086, 0x0006, 0x1120, 0x080c, 0x25b1, 0x0140, 0x0028, 0x080c,
-	0x26ad, 0x080c, 0x25d7, 0x0110, 0x8318, 0x08b0, 0x739a, 0x0010,
-	0x709b, 0xffff, 0x003e, 0x0804, 0x25ae, 0xa780, 0x2719, 0x203d,
-	0xa7bc, 0xff00, 0x873f, 0x7098, 0xa096, 0xffff, 0x0128, 0xa812,
-	0x12c8, 0x709b, 0xffff, 0x04b8, 0x2009, 0x0000, 0x70c8, 0xd09c,
-	0x0120, 0xd094, 0x0110, 0x2009, 0x007e, 0x2001, 0x94d7, 0x2004,
-	0xa005, 0x0120, 0x2009, 0x007e, 0x2041, 0x007f, 0x2100, 0xa802,
-	0x20a8, 0x0020, 0x2008, 0x2810, 0xa202, 0x20a8, 0x2700, 0x0156,
-	0x0016, 0xa106, 0x0180, 0x080c, 0x4400, 0x11a8, 0x6004, 0xa084,
-	0x00ff, 0xa086, 0x0006, 0x1118, 0x00a1, 0x0168, 0x0020, 0x080c,
-	0x26ad, 0x04a9, 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, 0x258e,
-	0x709b, 0xffff, 0x0018, 0x001e, 0x015e, 0x719a, 0x002e, 0x00ce,
-	0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x080c, 0x749c,
-	0x01c8, 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c,
-	0x43d1, 0x2001, 0x0000, 0x080c, 0x43e3, 0x0126, 0x2091, 0x8000,
-	0x7094, 0x8000, 0x7096, 0x012e, 0x2009, 0x0004, 0x080c, 0x7518,
-	0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x0016,
-	0x0076, 0x00d6, 0x00c6, 0x2c68, 0x080c, 0x749c, 0x01c8, 0x2d00,
-	0x601a, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x43d1, 0x2001,
-	0x0002, 0x080c, 0x43e3, 0x0126, 0x2091, 0x8000, 0x7094, 0x8000,
-	0x7096, 0x012e, 0x2009, 0x0002, 0x080c, 0x7518, 0xa085, 0x0001,
-	0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x0026, 0x2009,
-	0x0080, 0x080c, 0x4400, 0x1120, 0x0031, 0x0110, 0x70cf, 0xffff,
-	0x002e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68,
-	0x080c, 0x749c, 0x01c8, 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001,
-	0x0000, 0x080c, 0x43d1, 0x2001, 0x0002, 0x080c, 0x43e3, 0x0126,
-	0x2091, 0x8000, 0x70d0, 0x8000, 0x70d2, 0x012e, 0x2009, 0x0002,
-	0x080c, 0x7518, 0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e,
-	0x0005, 0x00c6, 0x00d6, 0x2009, 0x007f, 0x080c, 0x4400, 0x1180,
-	0x2c68, 0x080c, 0x749c, 0x0160, 0x2d00, 0x601a, 0x6312, 0x601f,
-	0x0001, 0x620a, 0x2009, 0x0022, 0x080c, 0x7518, 0xa085, 0x0001,
-	0x00de, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036, 0x0026,
-	0x080c, 0x6133, 0x080c, 0x60dc, 0x080c, 0x7a8c, 0x20a9, 0x007f,
-	0x2009, 0x0000, 0x0016, 0x080c, 0x4434, 0x1120, 0x080c, 0x460d,
-	0x080c, 0x41e0, 0x001e, 0x8108, 0x1f04, 0x265a, 0x002e, 0x003e,
-	0x006e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0026,
-	0x0016, 0x6218, 0x2270, 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c,
-	0x6127, 0x0086, 0x2041, 0x0000, 0x080c, 0x606d, 0x2c08, 0x080c,
-	0x8ee4, 0x008e, 0x001e, 0x2e60, 0x080c, 0x460d, 0x6210, 0x6314,
-	0x080c, 0x41e0, 0x6212, 0x6316, 0x001e, 0x002e, 0x003e, 0x00ce,
-	0x00ee, 0x0005, 0x00e6, 0x0006, 0x6018, 0xa080, 0x0028, 0x2004,
-	0xa086, 0x0080, 0x0150, 0x2071, 0x9200, 0x7094, 0xa005, 0x0110,
-	0x8001, 0x7096, 0x000e, 0x00ee, 0x0005, 0x2071, 0x9200, 0x70d0,
-	0xa005, 0x0dc0, 0x8001, 0x70d2, 0x0ca8, 0x6000, 0xc08c, 0x6002,
-	0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x0156,
-	0x2178, 0x81ff, 0x1118, 0x20a9, 0x0001, 0x0098, 0x2001, 0x9252,
+	0x0005, 0x00e6, 0x2071, 0x8dff, 0x7003, 0x0000, 0x00ee, 0x0005,
+	0x00d6, 0xa280, 0x0004, 0x206c, 0x694c, 0xd1dc, 0x1904, 0x1c3e,
+	0x6934, 0xa184, 0x0007, 0x0002, 0x1bdc, 0x1c29, 0x1bdc, 0x1bdc,
+	0x1bdc, 0x1c10, 0x1bef, 0x1bde, 0x080c, 0x1410, 0x684c, 0xd0b4,
+	0x0904, 0x1d32, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812,
+	0x687c, 0x680a, 0x6880, 0x680e, 0x6958, 0x0804, 0x1c31, 0x6834,
+	0xa084, 0x00ff, 0xa086, 0x001e, 0x1d38, 0x684c, 0xd0b4, 0x0904,
+	0x1d32, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, 0x687c,
+	0x680a, 0x6880, 0x680e, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004,
+	0xa084, 0x000f, 0xa080, 0x1e76, 0x2005, 0x6832, 0x6958, 0x0450,
+	0xa18c, 0x00ff, 0xa186, 0x0015, 0x1548, 0x684c, 0xd0b4, 0x0904,
+	0x1d32, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f,
+	0xa080, 0x1e76, 0x2005, 0x6832, 0x6958, 0xa006, 0x682e, 0x682a,
+	0x0088, 0x684c, 0xd0b4, 0x0904, 0x18c9, 0x6958, 0xa006, 0x682e,
+	0x682a, 0x2d00, 0x681a, 0x6834, 0xa084, 0x000f, 0xa080, 0x1e76,
+	0x2005, 0x6832, 0x6926, 0x684c, 0xc0dd, 0x684e, 0x00de, 0x0005,
+	0x00f6, 0x2079, 0x0020, 0x7804, 0xd0fc, 0x190c, 0x1d58, 0x00e6,
+	0x00d6, 0x2071, 0x8dff, 0x7000, 0xa005, 0x1904, 0x1cb2, 0x00c6,
+	0x7206, 0xa280, 0x0004, 0x205c, 0x7004, 0x2068, 0x7803, 0x0004,
+	0x6818, 0x00d6, 0x2068, 0x686c, 0x7812, 0x6890, 0x00f6, 0x20e1,
+	0x9040, 0x2079, 0x0200, 0x781a, 0x2079, 0x0100, 0x8004, 0x78d6,
+	0x00fe, 0x00de, 0x2b68, 0x6824, 0x2050, 0x6818, 0x2060, 0x6830,
+	0x2040, 0x6034, 0xa0cc, 0x000f, 0x6908, 0xa184, 0x0007, 0x0128,
+	0x0016, 0x2009, 0x0008, 0xa102, 0x001e, 0xa108, 0x791a, 0x7116,
+	0x701e, 0x680c, 0xa081, 0x0000, 0x781e, 0x701a, 0xa006, 0x700e,
+	0x7012, 0x7004, 0x692c, 0x6814, 0xa106, 0x1120, 0x6928, 0x6810,
+	0xa106, 0x0158, 0x0036, 0x0046, 0x6b14, 0x6c10, 0x080c, 0x1e96,
+	0x004e, 0x003e, 0x0110, 0x00ce, 0x00a8, 0x8aff, 0x1120, 0x00ce,
+	0xa085, 0x0001, 0x0078, 0x0126, 0x2091, 0x8000, 0x2079, 0x0020,
+	0x2009, 0x0001, 0x0059, 0x0118, 0x2009, 0x0001, 0x0039, 0x012e,
+	0x00ce, 0xa006, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x0076, 0x0066,
+	0x0056, 0x0046, 0x0036, 0x0026, 0x8aff, 0x0904, 0x1d2b, 0x700c,
+	0x7214, 0xa23a, 0x7010, 0x7218, 0xa203, 0x0a04, 0x1d2a, 0xa705,
+	0x0904, 0x1d2a, 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x11a8, 0x00d6,
+	0x2805, 0xac68, 0x2900, 0x0002, 0x1d0d, 0x1cf2, 0x1cf2, 0x1d0d,
+	0x1d0d, 0x1d06, 0x1d0d, 0x1cf2, 0x1d0d, 0x1cf7, 0x1cf7, 0x1d0d,
+	0x1d0d, 0x1d0d, 0x1cfe, 0x1cf7, 0xc0fc, 0x6852, 0x6b6c, 0x6a70,
+	0x6d1c, 0x6c20, 0xd99c, 0x0528, 0x00d6, 0x2805, 0xac68, 0x6f08,
+	0x6e0c, 0x00f0, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x00c8, 0x6b10,
+	0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0090, 0x00de, 0x00d6,
+	0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x1138, 0x00de, 0x080c,
+	0x1e38, 0x1904, 0x1cbc, 0xa00e, 0x00f0, 0x00de, 0x080c, 0x1410,
+	0x00de, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902,
+	0x7000, 0x8000, 0x7002, 0x6828, 0xa300, 0x682a, 0x682c, 0xa201,
+	0x682e, 0x700c, 0xa300, 0x700e, 0x7010, 0xa201, 0x7012, 0x080c,
+	0x1e38, 0x0008, 0xa006, 0x002e, 0x003e, 0x004e, 0x005e, 0x006e,
+	0x007e, 0x0005, 0x080c, 0x1410, 0x2001, 0x0105, 0x2003, 0x0010,
+	0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060,
+	0x00d6, 0x6010, 0x2068, 0x080c, 0x7b8f, 0x0118, 0x6850, 0xc0bd,
+	0x6852, 0x00de, 0x080c, 0x795f, 0x20e1, 0x9040, 0x080c, 0x6b33,
+	0x2011, 0x0000, 0x080c, 0x6966, 0x080c, 0x5dc2, 0x0804, 0x1e0d,
+	0x0126, 0x2091, 0x2400, 0x0006, 0x0016, 0x00f6, 0x00e6, 0x00d6,
+	0x00c6, 0x2079, 0x0020, 0x2071, 0x8dff, 0x2b68, 0x6818, 0x2060,
+	0x7904, 0x7803, 0x0002, 0xa184, 0x0700, 0x1930, 0x7000, 0x0002,
+	0x1e0d, 0x1d74, 0x1de0, 0x1e0b, 0x8001, 0x7002, 0xd19c, 0x1170,
+	0x8aff, 0x0540, 0x2009, 0x0001, 0x080c, 0x1cb6, 0x0904, 0x1e0d,
+	0x2009, 0x0001, 0x080c, 0x1cb6, 0x0804, 0x1e0d, 0x7803, 0x0004,
+	0xd194, 0x0148, 0x6850, 0xc0fc, 0x6852, 0x8aff, 0x1148, 0x684c,
+	0xc0f5, 0x684e, 0x0028, 0x080c, 0x1e4e, 0x6850, 0xc0fd, 0x6852,
+	0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, 0x0000,
+	0x0804, 0x1e0d, 0x711c, 0x81ff, 0x0190, 0x7918, 0x7922, 0x7827,
+	0x0000, 0x7803, 0x0001, 0x7000, 0x8000, 0x7002, 0x700c, 0xa100,
+	0x700e, 0x7010, 0xa081, 0x0000, 0x7012, 0x0804, 0x1e0d, 0x00f6,
+	0x0026, 0x781c, 0x0006, 0x7818, 0x0006, 0x2079, 0x0100, 0x7a14,
+	0xa284, 0x0184, 0xa085, 0x0012, 0x7816, 0x7820, 0xd0bc, 0x1de8,
+	0x79c8, 0x000e, 0xa102, 0x001e, 0x0006, 0x0016, 0x79c4, 0x000e,
+	0xa102, 0x78c6, 0x000e, 0x78ca, 0xa284, 0x0184, 0xa085, 0x0012,
+	0x7816, 0x002e, 0x00fe, 0x7803, 0x0008, 0x7003, 0x0000, 0x0468,
+	0x8001, 0x7002, 0xd194, 0x0168, 0x7804, 0xd0fc, 0x1904, 0x1d68,
+	0xd19c, 0x11f8, 0x8aff, 0x0508, 0x2009, 0x0001, 0x080c, 0x1cb6,
+	0x00e0, 0x0026, 0x0036, 0x6b28, 0x6a2c, 0x080c, 0x1e4e, 0x00d6,
+	0x2805, 0xac68, 0x6034, 0xd09c, 0x1128, 0x6808, 0xa31a, 0x680c,
+	0xa213, 0x0020, 0x6810, 0xa31a, 0x6814, 0xa213, 0x00de, 0x0804,
+	0x1d93, 0x0804, 0x1d93, 0x080c, 0x1410, 0x00ce, 0x00de, 0x00ee,
+	0x00fe, 0x001e, 0x000e, 0x012e, 0x0005, 0x00f6, 0x00e6, 0x2071,
+	0x8dff, 0x7000, 0xa086, 0x0000, 0x01c0, 0x2079, 0x0020, 0x20e1,
+	0x9040, 0x7804, 0xd0fc, 0x0dd8, 0x080c, 0x1d58, 0x7000, 0xa086,
+	0x0000, 0x1da8, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x1de8, 0x20e1,
+	0x9040, 0x7803, 0x0002, 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005,
+	0x8840, 0x2805, 0xa005, 0x1170, 0x6004, 0xa005, 0x0168, 0x681a,
+	0x2060, 0x6034, 0xa084, 0x000f, 0xa080, 0x1e76, 0x2045, 0x88ff,
+	0x090c, 0x1410, 0x8a51, 0x0005, 0x2050, 0x0005, 0x8a50, 0x8841,
+	0x2805, 0xa005, 0x1190, 0x2c00, 0xad06, 0x0120, 0x6000, 0xa005,
+	0x1108, 0x2d00, 0x2060, 0x681a, 0x6034, 0xa084, 0x000f, 0xa080,
+	0x1e86, 0x2045, 0x88ff, 0x090c, 0x1410, 0x0005, 0x0000, 0x0011,
+	0x0015, 0x0019, 0x001d, 0x0021, 0x0025, 0x0029, 0x0000, 0x000f,
+	0x0015, 0x001b, 0x0021, 0x0027, 0x0000, 0x0000, 0x0000, 0x1e6b,
+	0x1e67, 0x0000, 0x0000, 0x1e75, 0x0000, 0x1e6b, 0x0000, 0x1e72,
+	0x1e6f, 0x0000, 0x0000, 0x0000, 0x1e75, 0x1e72, 0x0000, 0x1e6d,
+	0x1e6d, 0x0000, 0x0000, 0x1e75, 0x0000, 0x1e6d, 0x0000, 0x1e73,
+	0x1e73, 0x0000, 0x0000, 0x0000, 0x1e75, 0x1e73, 0x00a6, 0x0096,
+	0x0086, 0x6858, 0xa055, 0x0904, 0x1f25, 0x2d60, 0x6034, 0xa0cc,
+	0x000f, 0xa9c0, 0x1e76, 0xa986, 0x0007, 0x0130, 0xa986, 0x000e,
+	0x0118, 0xa986, 0x000f, 0x1120, 0x605c, 0xa422, 0x6060, 0xa31a,
+	0x2805, 0xa045, 0x1140, 0x0310, 0x0804, 0x1f25, 0x6004, 0xa065,
+	0x0904, 0x1f25, 0x0c18, 0x2805, 0xa005, 0x01a8, 0xac68, 0xd99c,
+	0x1128, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0020, 0x6810, 0xa422,
+	0x6814, 0xa31b, 0x0620, 0x2300, 0xa405, 0x0150, 0x8a51, 0x0904,
+	0x1f25, 0x8840, 0x0c40, 0x6004, 0xa065, 0x0904, 0x1f25, 0x0830,
+	0x8a51, 0x0904, 0x1f25, 0x8840, 0x2805, 0xa005, 0x1158, 0x6004,
+	0xa065, 0x0904, 0x1f25, 0x6034, 0xa0cc, 0x000f, 0xa9c0, 0x1e76,
+	0x2805, 0x2040, 0x2b68, 0x6850, 0xc0fc, 0x6852, 0x0458, 0x8422,
+	0x8420, 0x831a, 0xa399, 0x0000, 0x00d6, 0x2b68, 0x6c6e, 0x6b72,
+	0x00de, 0xd99c, 0x1168, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300,
+	0xa11b, 0x0a0c, 0x1410, 0x6800, 0xa420, 0x6804, 0xa319, 0x0060,
+	0x6910, 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b, 0x0a0c, 0x1410,
+	0x6800, 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e, 0x6b22, 0x6850,
+	0xc0fd, 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832, 0x2a00, 0x6826,
+	0x000e, 0x000e, 0x000e, 0xa006, 0x0028, 0x008e, 0x009e, 0x00ae,
+	0xa085, 0x0001, 0x0005, 0x2001, 0x0005, 0x2004, 0xa084, 0x0007,
+	0x0002, 0x1f39, 0x1f3a, 0x1f3d, 0x1f40, 0x1f45, 0x1f48, 0x1f4d,
+	0x1f52, 0x0005, 0x080c, 0x1d58, 0x0005, 0x080c, 0x18ee, 0x0005,
+	0x080c, 0x18ee, 0x080c, 0x1d58, 0x0005, 0x080c, 0x15a7, 0x0005,
+	0x080c, 0x1d58, 0x080c, 0x15a7, 0x0005, 0x080c, 0x18ee, 0x080c,
+	0x15a7, 0x0005, 0x080c, 0x18ee, 0x080c, 0x1d58, 0x080c, 0x15a7,
+	0x0005, 0x0126, 0x2091, 0x2600, 0x2079, 0x0200, 0x2071, 0x9080,
+	0x2069, 0x8b00, 0x2009, 0x0004, 0x7912, 0x7817, 0x0004, 0x080c,
+	0x22c4, 0x781b, 0x0002, 0x783b, 0x001f, 0x20e1, 0x8700, 0x012e,
+	0x0005, 0x0126, 0x2091, 0x2600, 0x781c, 0xd0a4, 0x190c, 0x1ffa,
+	0xa084, 0x0007, 0x0002, 0x1f95, 0x1f83, 0x1f86, 0x1f89, 0x1f8e,
+	0x1f90, 0x1f92, 0x1f94, 0x080c, 0x521b, 0x0078, 0x080c, 0x5242,
+	0x0060, 0x080c, 0x521b, 0x080c, 0x5242, 0x0038, 0x0041, 0x0028,
+	0x0031, 0x0018, 0x0021, 0x0008, 0x0011, 0x012e, 0x0005, 0x0006,
+	0x0016, 0x0026, 0x7930, 0xa184, 0x0003, 0x0118, 0x20e1, 0x9040,
+	0x00b8, 0xa184, 0x0030, 0x0150, 0x6a00, 0xa286, 0x0003, 0x1108,
+	0x0010, 0x080c, 0x403d, 0x20e1, 0x9010, 0x0050, 0xa184, 0x00c0,
+	0x0110, 0x080c, 0x1410, 0xa184, 0x0300, 0x0110, 0x20e1, 0x9020,
+	0x7932, 0x002e, 0x001e, 0x000e, 0x0005, 0x0016, 0x00e6, 0x00f6,
+	0x2071, 0x8b00, 0x7128, 0x2001, 0x8d8f, 0x2102, 0x2001, 0x8d97,
+	0x2102, 0xa182, 0x0211, 0x1218, 0x2009, 0x0008, 0x0400, 0xa182,
+	0x0259, 0x1218, 0x2009, 0x0007, 0x00d0, 0xa182, 0x02c1, 0x1218,
+	0x2009, 0x0006, 0x00a0, 0xa182, 0x0349, 0x1218, 0x2009, 0x0005,
+	0x0070, 0xa182, 0x0421, 0x1218, 0x2009, 0x0004, 0x0040, 0xa182,
+	0x0581, 0x1218, 0x2009, 0x0003, 0x0010, 0x2009, 0x0002, 0x2079,
+	0x0200, 0x7912, 0x7817, 0x0004, 0x080c, 0x22c4, 0x00fe, 0x00ee,
+	0x001e, 0x0005, 0x7938, 0x080c, 0x1410, 0x0126, 0x2091, 0x2400,
+	0x2061, 0x0100, 0x2071, 0x8b00, 0x6024, 0x6026, 0x6053, 0x0030,
+	0x080c, 0x2303, 0x6050, 0xa084, 0xfe7f, 0x6052, 0x2009, 0x00ef,
+	0x6132, 0x6136, 0x080c, 0x2313, 0x60e7, 0x0000, 0x61ea, 0x60e3,
+	0x0008, 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f, 0x0080, 0x602f,
+	0x0000, 0x6007, 0x0e9f, 0x600f, 0x00ff, 0x602b, 0x002f, 0x012e,
+	0x0005, 0x2001, 0x8b30, 0x2003, 0x0000, 0x2001, 0x8b2f, 0x2003,
+	0x0001, 0x0005, 0x0126, 0x2091, 0x2400, 0x0006, 0x0016, 0x0026,
+	0x6124, 0xa184, 0x1e2c, 0x1118, 0xa184, 0x0007, 0x002a, 0xa195,
+	0x0004, 0xa284, 0x0007, 0x0002, 0x2066, 0x204c, 0x204f, 0x2052,
+	0x2057, 0x2059, 0x205d, 0x2061, 0x080c, 0x578e, 0x00b8, 0x080c,
+	0x5869, 0x00a0, 0x080c, 0x5869, 0x080c, 0x578e, 0x0078, 0x0099,
+	0x0068, 0x080c, 0x578e, 0x0079, 0x0048, 0x080c, 0x5869, 0x0059,
+	0x0028, 0x080c, 0x5869, 0x080c, 0x578e, 0x0029, 0x002e, 0x001e,
+	0x000e, 0x012e, 0x0005, 0xd19c, 0x1904, 0x226d, 0x080c, 0x4c42,
+	0x0560, 0x7000, 0xa086, 0x0003, 0x0198, 0x6024, 0xa084, 0x1800,
+	0x0178, 0x080c, 0x4c68, 0x0118, 0x080c, 0x4c54, 0x1148, 0x6027,
+	0x0020, 0x6043, 0x0000, 0x2001, 0x8d9c, 0x2003, 0xaaaa, 0x0458,
+	0x080c, 0x4c68, 0x1904, 0x20cf, 0x6024, 0xa084, 0x1800, 0x1108,
+	0x04f0, 0x2001, 0x8d9c, 0x2003, 0xaaaa, 0x2001, 0x8d9d, 0x2003,
+	0x0001, 0x080c, 0x4b8b, 0x0804, 0x226d, 0xd1ac, 0x1580, 0x6024,
+	0xd0dc, 0x1188, 0xd0e4, 0x11a0, 0xd0d4, 0x11d8, 0xd0cc, 0x0148,
+	0x7088, 0xa086, 0x0027, 0x1128, 0x6028, 0xc0cc, 0x602a, 0x080c,
+	0x4b52, 0x0804, 0x226d, 0x2001, 0x8d9d, 0x2003, 0x0000, 0x0068,
+	0xa085, 0x0001, 0x080c, 0x4c82, 0x2001, 0x8d9d, 0x2003, 0x0002,
+	0x0020, 0x080c, 0x4d10, 0x0804, 0x226d, 0x0016, 0x2001, 0x8b00,
+	0x2003, 0x0001, 0x080c, 0x4b8b, 0x001e, 0x0804, 0x226d, 0xd1ac,
+	0x0904, 0x21b5, 0x080c, 0x4c42, 0x1550, 0x6027, 0x0020, 0x0006,
+	0x0026, 0x0036, 0x2001, 0x8d9d, 0x080c, 0x4c5e, 0x11d8, 0x2011,
+	0x8b25, 0x2204, 0xa005, 0x1140, 0x8000, 0x2012, 0x2011, 0x8036,
+	0x2019, 0x0001, 0x080c, 0x3617, 0x2001, 0x8d9d, 0x2003, 0x0001,
+	0x2001, 0x8b00, 0x2003, 0x0001, 0x080c, 0x4b8b, 0x003e, 0x002e,
+	0x000e, 0x0005, 0x003e, 0x002e, 0x000e, 0x080c, 0x4b06, 0x0016,
+	0x0046, 0x00c6, 0x644c, 0xa486, 0xf0f0, 0x1138, 0x2061, 0x0100,
+	0x644a, 0x6043, 0x0090, 0x6043, 0x0010, 0x74c6, 0xa48c, 0xff00,
+	0x7034, 0xd084, 0x0178, 0xa186, 0xf800, 0x1160, 0x7038, 0xd084,
+	0x1148, 0xc085, 0x703a, 0x0036, 0x2418, 0x2011, 0x8016, 0x080c,
+	0x3617, 0x003e, 0xa196, 0xff00, 0x01e8, 0x7050, 0xa084, 0x00ff,
+	0x810f, 0xa116, 0x01b8, 0x7130, 0xd18c, 0x11a0, 0x2011, 0x8b52,
+	0x2214, 0xd2ec, 0x0118, 0xc18d, 0x7132, 0x0060, 0x6240, 0xa294,
+	0x0010, 0x0904, 0x218b, 0x6248, 0xa294, 0xff00, 0xa296, 0xff00,
+	0x1904, 0x218b, 0x7034, 0xd08c, 0x1140, 0x2001, 0x8b0c, 0x200c,
+	0xd1ac, 0x1904, 0x218b, 0xc1ad, 0x2102, 0x0036, 0x73c4, 0x2011,
+	0x8013, 0x080c, 0x3617, 0x003e, 0x7130, 0xc185, 0x7132, 0x2011,
+	0x8b52, 0x220c, 0xd1a4, 0x01d0, 0x0016, 0x2009, 0x0001, 0x2011,
+	0x0100, 0x080c, 0x5734, 0x2019, 0x000e, 0x080c, 0x891c, 0xa484,
+	0x00ff, 0xa080, 0x263d, 0x200d, 0xa18c, 0xff00, 0x810f, 0x8127,
+	0xa006, 0x2009, 0x000e, 0x080c, 0x8982, 0x001e, 0xd1ac, 0x1128,
+	0x2019, 0x0004, 0x080c, 0x2542, 0x0070, 0x0156, 0x20a9, 0x007f,
+	0x2009, 0x0000, 0x080c, 0x430a, 0x1110, 0x080c, 0x4118, 0x8108,
+	0x1f04, 0x2182, 0x015e, 0x00ce, 0x004e, 0x2011, 0x0003, 0x080c,
+	0x695c, 0x2011, 0x0002, 0x080c, 0x6966, 0x080c, 0x6862, 0x080c,
+	0x567a, 0x0036, 0x2019, 0x0000, 0x080c, 0x68e5, 0x003e, 0x60e3,
+	0x0000, 0x001e, 0x2001, 0x8b00, 0x2014, 0xa296, 0x0004, 0x1128,
+	0xd19c, 0x1118, 0x6228, 0xc29d, 0x622a, 0x2003, 0x0001, 0x2001,
+	0x8b22, 0x2003, 0x0000, 0x6027, 0x0020, 0xd194, 0x0904, 0x226d,
+	0x0016, 0x6220, 0xd2b4, 0x0904, 0x221e, 0x080c, 0x567a, 0x080c,
+	0x66f7, 0x6027, 0x0004, 0x00f6, 0x2019, 0x8db3, 0x2304, 0xa07d,
+	0x0570, 0x7804, 0xa086, 0x0032, 0x1550, 0x00d6, 0x00c6, 0x00e6,
+	0x2069, 0x0140, 0x618c, 0x6288, 0x7818, 0x608e, 0x7808, 0x608a,
+	0x6043, 0x0002, 0x2001, 0x0003, 0x8001, 0x1df0, 0x6043, 0x0000,
+	0x6803, 0x1000, 0x6803, 0x0000, 0x618e, 0x628a, 0x080c, 0x5c37,
+	0x080c, 0x5d10, 0x7810, 0x2070, 0x7037, 0x0103, 0x2f60, 0x080c,
+	0x6d18, 0x00ee, 0x00ce, 0x00de, 0x00fe, 0x001e, 0x0005, 0x00fe,
+	0x00d6, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0120, 0x6803,
+	0x1000, 0x6803, 0x0000, 0x00de, 0x00c6, 0x2061, 0x8daa, 0x6028,
+	0xa09a, 0x0002, 0x1238, 0x8000, 0x602a, 0x00ce, 0x080c, 0x66ea,
+	0x0804, 0x226c, 0x2019, 0x8db3, 0x2304, 0xa065, 0x0120, 0x2009,
+	0x0027, 0x080c, 0x6d3f, 0x00ce, 0x0804, 0x226c, 0xd2bc, 0x0904,
+	0x226c, 0x080c, 0x5687, 0x6014, 0xa084, 0x0184, 0xa085, 0x0010,
+	0x6016, 0x6027, 0x0004, 0x00d6, 0x2069, 0x0140, 0x6804, 0xa084,
+	0x4000, 0x0120, 0x6803, 0x1000, 0x6803, 0x0000, 0x00de, 0x00c6,
+	0x2061, 0x8daa, 0x6044, 0xa09a, 0x0002, 0x12f0, 0x8000, 0x6046,
+	0x603c, 0x00ce, 0xa005, 0x0540, 0x2009, 0x07d0, 0x080c, 0x567f,
+	0xa080, 0x0007, 0x2004, 0xa086, 0x0006, 0x1138, 0x6114, 0xa18c,
+	0x0184, 0xa18d, 0x0012, 0x6116, 0x00b8, 0x6114, 0xa18c, 0x0184,
+	0xa18d, 0x0016, 0x6116, 0x0080, 0x0036, 0x2019, 0x0001, 0x080c,
+	0x68e5, 0x003e, 0x2019, 0x8db9, 0x2304, 0xa065, 0x0120, 0x2009,
+	0x004f, 0x080c, 0x6d3f, 0x00ce, 0x001e, 0xd19c, 0x0528, 0x0016,
+	0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, 0x080c, 0x695c, 0x2011,
+	0x0002, 0x080c, 0x6966, 0x080c, 0x6862, 0x080c, 0x567a, 0x0036,
+	0x2019, 0x0000, 0x080c, 0x68e5, 0x003e, 0x60e3, 0x0000, 0x080c,
+	0x8a36, 0x080c, 0x8a51, 0x2001, 0x8b00, 0x2003, 0x0004, 0x6027,
+	0x0008, 0x080c, 0x1251, 0x001e, 0xa18c, 0xffd0, 0x6126, 0x0005,
+	0x0006, 0x0016, 0x0026, 0x00e6, 0x00f6, 0x0126, 0x2091, 0x8000,
+	0x2071, 0x8b00, 0x71bc, 0x70be, 0xa116, 0x01b8, 0x81ff, 0x0128,
+	0x2011, 0x8011, 0x080c, 0x3617, 0x0080, 0x2011, 0x8012, 0x080c,
+	0x3617, 0x0036, 0x00c6, 0x080c, 0x235e, 0x2061, 0x0100, 0x2019,
+	0x0028, 0x080c, 0x2542, 0x00ce, 0x003e, 0x012e, 0x00fe, 0x00ee,
+	0x002e, 0x001e, 0x000e, 0x0005, 0x00c6, 0x00f6, 0x0006, 0x0026,
+	0x2061, 0x0100, 0xa190, 0x22d7, 0x2205, 0x60f2, 0x2011, 0x22e4,
+	0x2205, 0x60ee, 0x002e, 0x000e, 0x00fe, 0x00ce, 0x0005, 0x0840,
+	0x0840, 0x0840, 0x0580, 0x0420, 0x0348, 0x02c0, 0x0258, 0x0210,
+	0x01a8, 0x01a8, 0x01a8, 0x01a8, 0x0140, 0x00f8, 0x00d0, 0x00b0,
+	0x00a0, 0x2028, 0xa18c, 0x00ff, 0x2130, 0xa094, 0xff00, 0x1110,
+	0x81ff, 0x0118, 0x080c, 0x53f4, 0x0038, 0xa080, 0x263d, 0x200d,
+	0xa18c, 0xff00, 0x810f, 0xa006, 0x0005, 0xa080, 0x263d, 0x200d,
+	0xa18c, 0x00ff, 0x0005, 0x00d6, 0x2069, 0x0140, 0x2001, 0x8b14,
+	0x2003, 0x00ef, 0x20a9, 0x0010, 0xa006, 0x6852, 0x6856, 0x1f04,
+	0x230e, 0x00de, 0x0005, 0x0006, 0x00d6, 0x0026, 0x2069, 0x0140,
+	0x2001, 0x8b14, 0x2102, 0x8114, 0x8214, 0x8214, 0x8214, 0x20a9,
+	0x0010, 0x6853, 0x0000, 0xa006, 0x82ff, 0x1128, 0xa184, 0x000f,
+	0xa080, 0x8a57, 0x2005, 0x6856, 0x8211, 0x1f04, 0x2323, 0x002e,
+	0x00de, 0x000e, 0x0005, 0x00c6, 0x2061, 0x8b00, 0x6030, 0x0110,
+	0xc09d, 0x0008, 0xc09c, 0x6032, 0x00ce, 0x0005, 0x0156, 0x00d6,
+	0x0026, 0x0016, 0x0006, 0x2069, 0x0140, 0x6980, 0xa116, 0x0180,
+	0xa112, 0x1230, 0x8212, 0x8210, 0x22a8, 0x2001, 0x0402, 0x0018,
+	0x22a8, 0x2001, 0x0404, 0x680e, 0x1f04, 0x2353, 0x680f, 0x0000,
+	0x000e, 0x001e, 0x002e, 0x00de, 0x015e, 0x0005, 0x2001, 0x8b52,
 	0x2004, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0xa006, 0x0046, 0x2020,
-	0x2009, 0x002d, 0x080c, 0x90d7, 0x004e, 0x20a9, 0x00ff, 0x2011,
-	0x0000, 0x0026, 0xa288, 0x936e, 0x210c, 0x81ff, 0x0508, 0x8fff,
-	0x0559, 0x2019, 0x0029, 0x080c, 0x6127, 0x0086, 0x2041, 0x0000,
-	0x080c, 0x606d, 0x00c6, 0x0026, 0x2160, 0x6204, 0xa294, 0x00ff,
-	0x2001, 0x0004, 0x8007, 0xa215, 0x6206, 0x002e, 0x00ce, 0x0016,
-	0x2c08, 0x080c, 0x8ee4, 0x001e, 0x008e, 0x2160, 0x080c, 0x460d,
-	0x002e, 0x8210, 0x1f04, 0x26d1, 0x015e, 0x001e, 0x002e, 0x003e,
-	0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0046, 0x0026, 0x0016, 0x2001,
-	0x9252, 0x2004, 0xd0c4, 0x0148, 0xd0a4, 0x0138, 0xa006, 0x2220,
-	0x8427, 0x2009, 0x0029, 0x080c, 0x90d7, 0x001e, 0x002e, 0x004e,
-	0x0005, 0x7eef, 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc,
-	0x80da, 0x7ad9, 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1,
-	0x79ce, 0x78cd, 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6,
-	0x77c5, 0x76c3, 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4,
-	0x72b3, 0x80b2, 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa,
-	0x6ea9, 0x80a7, 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d,
-	0x809b, 0x8098, 0x6797, 0x6690, 0x658f, 0x6488, 0x6384, 0x6282,
-	0x8081, 0x8080, 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074,
-	0x8073, 0x8072, 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a,
-	0x5b69, 0x8067, 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, 0x5559,
-	0x8056, 0x8055, 0x5454, 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d,
-	0x804c, 0x804b, 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043,
-	0x803c, 0x803a, 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932,
-	0x4831, 0x802e, 0x472d, 0x462c, 0x452b, 0x442a, 0x4329, 0x4227,
-	0x8026, 0x8025, 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18,
-	0x8017, 0x8010, 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000,
-	0x8000, 0x3800, 0x3700, 0x3600, 0x8000, 0x3500, 0x8000, 0x8000,
-	0x8000, 0x3400, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
-	0x3300, 0x3200, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
-	0x3100, 0x3000, 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00,
-	0x2c00, 0x8000, 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900,
-	0x2800, 0x8000, 0x2700, 0x2600, 0x2500, 0x2400, 0x2300, 0x2200,
-	0x8000, 0x8000, 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00,
-	0x8000, 0x8000, 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x1800, 0x8000, 0x1700, 0x1600,
-	0x1500, 0x8000, 0x1400, 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00,
-	0x8000, 0x8000, 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900,
-	0x8000, 0x8000, 0x0800, 0x0700, 0x8000, 0x0600, 0x8000, 0x8000,
-	0x8000, 0x0500, 0x0400, 0x0300, 0x8000, 0x0200, 0x8000, 0x8000,
-	0x8000, 0x0100, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
-	0x0000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
+	0x2009, 0x002e, 0x080c, 0x8982, 0x004e, 0x0005, 0x238e, 0x2392,
+	0x2396, 0x239c, 0x23a2, 0x23a8, 0x23ae, 0x23b6, 0x23bd, 0x23c2,
+	0x23c7, 0x23ce, 0x23d5, 0x23dc, 0x23e3, 0x23ec, 0x23f5, 0x23f5,
+	0x23f5, 0x23f5, 0x23f5, 0x23f5, 0x23f5, 0x23f5, 0x23f5, 0x23f5,
+	0x23f5, 0x23f5, 0x23f5, 0x23f5, 0x23f5, 0x23f5, 0x0106, 0x0006,
+	0x0804, 0x23f7, 0x0106, 0x0006, 0x0804, 0x23f7, 0x0106, 0x0006,
+	0x080c, 0x2032, 0x0804, 0x23f7, 0x0106, 0x0006, 0x080c, 0x2032,
+	0x0804, 0x23f7, 0x0106, 0x0006, 0x080c, 0x1f2b, 0x0804, 0x23f7,
+	0x0106, 0x0006, 0x080c, 0x1f2b, 0x0804, 0x23f7, 0x0106, 0x0006,
+	0x080c, 0x2032, 0x080c, 0x1f2b, 0x0804, 0x23f7, 0x0106, 0x0006,
+	0x080c, 0x2032, 0x080c, 0x1f2b, 0x04d0, 0x0106, 0x0006, 0x080c,
+	0x1f71, 0x04a8, 0x0106, 0x0006, 0x080c, 0x1f71, 0x0480, 0x0106,
+	0x0006, 0x080c, 0x2032, 0x080c, 0x1f71, 0x0448, 0x0106, 0x0006,
+	0x080c, 0x2032, 0x080c, 0x1f71, 0x0410, 0x0106, 0x0006, 0x080c,
+	0x1f2b, 0x080c, 0x1f71, 0x00d8, 0x0106, 0x0006, 0x080c, 0x1f2b,
+	0x080c, 0x1f71, 0x00a0, 0x0106, 0x0006, 0x080c, 0x2032, 0x080c,
+	0x1f2b, 0x080c, 0x1f71, 0x0058, 0x0106, 0x0006, 0x080c, 0x2032,
+	0x080c, 0x1f2b, 0x080c, 0x1f71, 0x0010, 0xe000, 0x0cf0, 0x000e,
+	0x010e, 0x000d, 0x00c6, 0x0026, 0x2041, 0x007e, 0x70c8, 0xd09c,
+	0x0110, 0x2041, 0x007f, 0xd094, 0x2001, 0x8b14, 0x203c, 0x1904,
+	0x2454, 0x7284, 0xd284, 0x0904, 0x2454, 0xd28c, 0x1904, 0x2454,
+	0x0036, 0x7398, 0xa38e, 0xffff, 0x1110, 0x2019, 0x0001, 0x8314,
+	0xa2e0, 0x91c0, 0x2c04, 0xa38c, 0x0001, 0x0120, 0xa084, 0xff00,
+	0x8007, 0x0010, 0xa084, 0x00ff, 0xa70e, 0x0528, 0xa08e, 0x00ff,
+	0x1160, 0x2011, 0x8b52, 0x2214, 0xd2ec, 0x1508, 0x7284, 0xc28d,
+	0x7286, 0x709b, 0xffff, 0x003e, 0x00f8, 0x2009, 0x0000, 0x080c,
+	0x22e9, 0x080c, 0x42d6, 0x1188, 0x6004, 0xa084, 0x00ff, 0xa086,
+	0x0006, 0x1120, 0x080c, 0x24a8, 0x0140, 0x0028, 0x080c, 0x25a4,
+	0x080c, 0x24ce, 0x0110, 0x8318, 0x0850, 0x739a, 0x0010, 0x709b,
+	0xffff, 0x003e, 0x0804, 0x24a5, 0xa780, 0x263d, 0x203d, 0xa7bc,
+	0xff00, 0x873f, 0x7098, 0xa096, 0xffff, 0x0128, 0xa812, 0x12c8,
+	0x709b, 0xffff, 0x04f8, 0x2009, 0x0000, 0x70c8, 0xd09c, 0x0120,
+	0xd094, 0x0110, 0x2009, 0x007e, 0x2001, 0x8d9c, 0x2004, 0xa005,
+	0x0120, 0x2009, 0x007e, 0x2041, 0x007f, 0x2100, 0xa802, 0x20a8,
+	0x0020, 0x2008, 0x2810, 0xa202, 0x20a8, 0x2700, 0x0156, 0x0016,
+	0xa106, 0x01c0, 0x080c, 0x42d6, 0x11e8, 0x6004, 0xa084, 0x00ff,
+	0xa086, 0x0006, 0x1120, 0x080c, 0x2610, 0x0160, 0x0020, 0x7284,
+	0xd28c, 0x0120, 0x0038, 0x00a1, 0x0168, 0x0020, 0x080c, 0x25a4,
+	0x04a9, 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, 0x247d, 0x709b,
+	0xffff, 0x0018, 0x001e, 0x015e, 0x719a, 0x002e, 0x00ce, 0x0005,
+	0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x080c, 0x6cc2, 0x01c8,
+	0x2d00, 0x601a, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x42a7,
+	0x2001, 0x0000, 0x080c, 0x42b9, 0x0126, 0x2091, 0x8000, 0x7094,
+	0x8000, 0x7096, 0x012e, 0x2009, 0x0004, 0x080c, 0x6d3f, 0xa085,
+	0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x0016, 0x0076,
+	0x00d6, 0x00c6, 0x2c68, 0x080c, 0x6cc2, 0x01c8, 0x2d00, 0x601a,
+	0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x42a7, 0x2001, 0x0002,
+	0x080c, 0x42b9, 0x0126, 0x2091, 0x8000, 0x7094, 0x8000, 0x7096,
+	0x012e, 0x2009, 0x0002, 0x080c, 0x6d3f, 0xa085, 0x0001, 0x00ce,
+	0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x0026, 0x2009, 0x0080,
+	0x080c, 0x42d6, 0x1120, 0x0031, 0x0110, 0x70cf, 0xffff, 0x002e,
+	0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x080c,
+	0x6cc2, 0x01c8, 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001, 0x0000,
+	0x080c, 0x42a7, 0x2001, 0x0002, 0x080c, 0x42b9, 0x0126, 0x2091,
+	0x8000, 0x70d0, 0x8000, 0x70d2, 0x012e, 0x2009, 0x0002, 0x080c,
+	0x6d3f, 0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005,
+	0x00c6, 0x00d6, 0x2009, 0x007f, 0x080c, 0x42d6, 0x1180, 0x2c68,
+	0x080c, 0x6cc2, 0x0160, 0x2d00, 0x601a, 0x6312, 0x601f, 0x0001,
+	0x620a, 0x2009, 0x0022, 0x080c, 0x6d3f, 0xa085, 0x0001, 0x00de,
+	0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036, 0x0026, 0x080c,
+	0x59e1, 0x080c, 0x598b, 0x080c, 0x72cc, 0x20a9, 0x007f, 0x2009,
+	0x0000, 0x0016, 0x080c, 0x430a, 0x1120, 0x080c, 0x44e6, 0x080c,
+	0x4118, 0x001e, 0x8108, 0x1f04, 0x2551, 0x002e, 0x003e, 0x006e,
+	0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016,
+	0x6218, 0x2270, 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, 0x59d5,
+	0x0086, 0x2041, 0x0000, 0x080c, 0x5911, 0x2c08, 0x080c, 0x878f,
+	0x008e, 0x001e, 0x2e60, 0x080c, 0x44e6, 0x6210, 0x6314, 0x080c,
+	0x4118, 0x6212, 0x6316, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee,
+	0x0005, 0x00e6, 0x0006, 0x6018, 0xa080, 0x0028, 0x2004, 0xa086,
+	0x0080, 0x0150, 0x2071, 0x8b00, 0x7094, 0xa005, 0x0110, 0x8001,
+	0x7096, 0x000e, 0x00ee, 0x0005, 0x2071, 0x8b00, 0x70d0, 0xa005,
+	0x0dc0, 0x8001, 0x70d2, 0x0ca8, 0x6000, 0xc08c, 0x6002, 0x0005,
+	0x00f6, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x0156, 0x2178,
+	0x81ff, 0x1118, 0x20a9, 0x0001, 0x0098, 0x2001, 0x8b52, 0x2004,
+	0xd0c4, 0x0150, 0xd0a4, 0x0140, 0xa006, 0x0046, 0x2020, 0x2009,
+	0x002d, 0x080c, 0x8982, 0x004e, 0x20a9, 0x00ff, 0x2011, 0x0000,
+	0x0026, 0xa288, 0x8c34, 0x210c, 0x81ff, 0x0508, 0x8fff, 0x0559,
+	0x2019, 0x0029, 0x080c, 0x59d5, 0x0086, 0x2041, 0x0000, 0x080c,
+	0x5911, 0x00c6, 0x0026, 0x2160, 0x6204, 0xa294, 0x00ff, 0x2001,
+	0x0004, 0x8007, 0xa215, 0x6206, 0x002e, 0x00ce, 0x0016, 0x2c08,
+	0x080c, 0x878f, 0x001e, 0x008e, 0x2160, 0x080c, 0x44e6, 0x002e,
+	0x8210, 0x1f04, 0x25c8, 0x015e, 0x001e, 0x002e, 0x003e, 0x00ce,
+	0x00ee, 0x00fe, 0x0005, 0x0046, 0x0026, 0x0016, 0x2001, 0x8b52,
+	0x2004, 0xd0c4, 0x0148, 0xd0a4, 0x0138, 0xa006, 0x2220, 0x8427,
+	0x2009, 0x0029, 0x080c, 0x8982, 0x001e, 0x002e, 0x004e, 0x0005,
+	0x0016, 0x0026, 0x0036, 0x00c6, 0x7284, 0x82ff, 0x01f8, 0xa290,
+	0x8b52, 0x2214, 0xd2ac, 0x11d0, 0x2100, 0x080c, 0x22fd, 0x81ff,
+	0x01b8, 0x2019, 0x0001, 0x8314, 0xa2e0, 0x91c0, 0x2c04, 0xd384,
+	0x0120, 0xa084, 0xff00, 0x8007, 0x0010, 0xa084, 0x00ff, 0xa116,
+	0x0138, 0xa096, 0x00ff, 0x0110, 0x8318, 0x0c68, 0xa085, 0x0001,
+	0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x7eef, 0x7de8, 0x7ce4,
+	0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, 0x7ad9, 0x80d6, 0x80d5,
+	0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, 0x78cd, 0x80cc, 0x80cb,
+	0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, 0x76c3, 0x80bc, 0x80ba,
+	0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, 0x80b2, 0x80b1, 0x80ae,
+	0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, 0x80a7, 0x6da6, 0x6ca5,
+	0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, 0x8098, 0x6797, 0x6690,
+	0x658f, 0x6488, 0x6384, 0x6282, 0x8081, 0x8080, 0x617c, 0x607a,
+	0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, 0x8072, 0x8071, 0x806e,
+	0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, 0x8067, 0x5a66, 0x5965,
+	0x5863, 0x575c, 0x565a, 0x5559, 0x8056, 0x8055, 0x5454, 0x5353,
+	0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, 0x804b, 0x4e4a, 0x4d49,
+	0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, 0x803a, 0x8039, 0x8036,
+	0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, 0x802e, 0x472d, 0x462c,
+	0x452b, 0x442a, 0x4329, 0x4227, 0x8026, 0x8025, 0x4123, 0x401f,
+	0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, 0x8010, 0x3b0f, 0x3a08,
+	0x8004, 0x3902, 0x8001, 0x8000, 0x8000, 0x3800, 0x3700, 0x3600,
+	0x8000, 0x3500, 0x8000, 0x8000, 0x8000, 0x3400, 0x8000, 0x8000,
+	0x8000, 0x8000, 0x8000, 0x8000, 0x3300, 0x3200, 0x8000, 0x8000,
+	0x8000, 0x8000, 0x8000, 0x8000, 0x3100, 0x3000, 0x8000, 0x8000,
+	0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, 0x8000, 0x8000, 0x8000,
+	0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, 0x8000, 0x2700, 0x2600,
+	0x2500, 0x2400, 0x2300, 0x2200, 0x8000, 0x8000, 0x2100, 0x2000,
+	0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, 0x8000, 0x1b00, 0x1a00,
+	0x8000, 0x1900, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
+	0x1800, 0x8000, 0x1700, 0x1600, 0x1500, 0x8000, 0x1400, 0x1300,
+	0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, 0x8000, 0x0e00, 0x0d00,
+	0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, 0x8000, 0x0800, 0x0700,
+	0x8000, 0x0600, 0x8000, 0x8000, 0x8000, 0x0500, 0x0400, 0x0300,
+	0x8000, 0x0200, 0x8000, 0x8000, 0x8000, 0x0100, 0x8000, 0x8000,
+	0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0x8000, 0x8000, 0x8000,
 	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
-	0x8000, 0x2071, 0x9296, 0x7003, 0x0002, 0xa006, 0x7012, 0x7016,
-	0x703a, 0x703e, 0x7033, 0x92a6, 0x7037, 0x92a6, 0x7007, 0x0001,
-	0x2061, 0x92e6, 0x6003, 0x0002, 0x0005, 0x1004, 0x283f, 0x0e04,
-	0x283f, 0x2071, 0x9296, 0x2b78, 0x7818, 0xd084, 0x1140, 0x2a60,
-	0x7820, 0xa08e, 0x0069, 0x1904, 0x2924, 0x0804, 0x28bd, 0x0005,
-	0x2071, 0x9296, 0x7004, 0x0002, 0x2848, 0x2849, 0x2852, 0x2863,
-	0x0005, 0x1004, 0x2851, 0x0e04, 0x2851, 0x2b78, 0x7818, 0xd084,
-	0x01e8, 0x0005, 0x2b78, 0x2061, 0x92e6, 0x6008, 0xa08e, 0x0100,
-	0x0128, 0xa086, 0x0200, 0x0904, 0x291e, 0x0005, 0x7014, 0x2068,
-	0x2a60, 0x7018, 0x0807, 0x7010, 0x2068, 0x6834, 0xa086, 0x0103,
-	0x0108, 0x0005, 0x2a60, 0x2b78, 0x7018, 0x0807, 0x2a60, 0x7820,
-	0xa08a, 0x0040, 0x1210, 0x61bc, 0x0042, 0x2100, 0xa08a, 0x003f,
-	0x1a04, 0x291b, 0x61bc, 0x0804, 0x28bd, 0x28ff, 0x292a, 0x2932,
-	0x2936, 0x293e, 0x2944, 0x2948, 0x2951, 0x2954, 0x295e, 0x2961,
-	0x291b, 0x291b, 0x291b, 0x2964, 0x291b, 0x2973, 0x298a, 0x29a1,
-	0x2a18, 0x2a1d, 0x2a46, 0x2a97, 0x2aa8, 0x2ac6, 0x2af2, 0x2afc,
-	0x2b09, 0x2b1c, 0x2b3c, 0x2b45, 0x2b7b, 0x2b81, 0x291b, 0x2ba4,
-	0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x2ba8, 0x2bae, 0x291b,
-	0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x2bb6,
-	0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x2bc3, 0x2bc9, 0x291b,
-	0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x0002, 0x2bdb, 0x2c2e,
-	0x2c88, 0x2c98, 0x291b, 0x2cb2, 0x309c, 0x291b, 0x291b, 0x291b,
-	0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x295e, 0x2961,
-	0x291b, 0x291b, 0x309e, 0x291b, 0x291b, 0x291b, 0x291b, 0x291b,
-	0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x30a2, 0x31e7,
-	0x31fb, 0x3215, 0x3276, 0x32c7, 0x32d2, 0x3309, 0x3318, 0x3327,
-	0x3336, 0x335e, 0x33a8, 0x340a, 0x3417, 0x3501, 0x35f6, 0x361f,
-	0x3716, 0x3732, 0x373e, 0x3777, 0x381e, 0x3878, 0x38ff, 0x3908,
-	0x390b, 0x3920, 0x393b, 0x39ab, 0x3a5b, 0x713c, 0x0000, 0x2021,
-	0x4000, 0x080c, 0x3675, 0x0126, 0x2091, 0x8000, 0x0e04, 0x290b,
-	0x7818, 0xd084, 0x0110, 0x012e, 0x0cb0, 0x7c22, 0x7926, 0x7a2a,
-	0x7b2e, 0x781b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, 0x2091,
-	0x5000, 0x012e, 0x0005, 0x2021, 0x4001, 0x0c18, 0x2021, 0x4002,
-	0x0c00, 0x2021, 0x4003, 0x08e8, 0x2021, 0x4005, 0x08d0, 0x2021,
-	0x4006, 0x08b8, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930,
-	0x0804, 0x3682, 0x7823, 0x0004, 0x7824, 0x0807, 0xa02e, 0x2520,
-	0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0804, 0x3685, 0x7924, 0x7828,
-	0x2114, 0x200a, 0x0804, 0x28ff, 0x7924, 0x2114, 0x0804, 0x28ff,
-	0x2099, 0x0009, 0x20a1, 0x0009, 0x20a9, 0x0007, 0x53a3, 0x0804,
-	0x28ff, 0x7824, 0x2060, 0x0090, 0x2009, 0x0002, 0x2011, 0x0000,
-	0x2019, 0x0010, 0x783b, 0x0027, 0x0804, 0x28ff, 0x7d38, 0x7c3c,
-	0x0858, 0x7d38, 0x7c3c, 0x08a0, 0x2061, 0x1000, 0xe10c, 0xa006,
-	0x2c15, 0xa200, 0x8c60, 0x8109, 0x1dd8, 0x2010, 0xa005, 0x0904,
-	0x28ff, 0x0804, 0x2921, 0x2069, 0x9251, 0x7824, 0x7930, 0xa11a,
-	0x1a04, 0x2927, 0x8019, 0x0904, 0x2927, 0x684a, 0x6942, 0x782c,
-	0x6852, 0x7828, 0x6856, 0xa006, 0x685a, 0x685e, 0x080c, 0x4e5d,
-	0x0804, 0x28ff, 0x2069, 0x9251, 0x7824, 0x7934, 0xa11a, 0x1a04,
-	0x2927, 0x8019, 0x0904, 0x2927, 0x684e, 0x6946, 0x782c, 0x6862,
-	0x7828, 0x6866, 0xa006, 0x686a, 0x686e, 0x080c, 0x47d8, 0x0804,
-	0x28ff, 0xa02e, 0x2520, 0x81ff, 0x1904, 0x2924, 0x7924, 0x7b28,
-	0x7a2c, 0x20a9, 0x0005, 0x20a1, 0x929d, 0x41a1, 0x080c, 0x3641,
-	0x0904, 0x2924, 0x2009, 0x0023, 0x080c, 0x3682, 0x701b, 0x29b9,
-	0x0005, 0x6834, 0x2008, 0xa084, 0x00ff, 0xa096, 0x0011, 0x0120,
-	0xa096, 0x0019, 0x1904, 0x2924, 0x810f, 0xa18c, 0x00ff, 0x0904,
-	0x2924, 0x710e, 0x700c, 0x8001, 0x0528, 0x700e, 0x080c, 0x3641,
-	0x0904, 0x2924, 0x2009, 0x0023, 0x2061, 0x92e6, 0x6224, 0x6328,
-	0x642c, 0x6530, 0xa290, 0x0046, 0xa399, 0x0000, 0xa4a1, 0x0000,
-	0xa5a9, 0x0000, 0x080c, 0x3682, 0x701b, 0x29e7, 0x0005, 0x6834,
-	0xa084, 0x00ff, 0xa096, 0x0002, 0x0120, 0xa096, 0x000a, 0x1904,
-	0x2924, 0x08c0, 0x7010, 0x2068, 0x6838, 0xc0fd, 0x683a, 0x080c,
-	0x4337, 0x1128, 0x7007, 0x0003, 0x701b, 0x2a01, 0x0005, 0x080c,
-	0x492c, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, 0x2099, 0x929d,
-	0x530a, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9,
-	0x0000, 0xad80, 0x000d, 0x2009, 0x0023, 0x012e, 0x0804, 0x3685,
-	0x61a4, 0x7824, 0x60a6, 0x0804, 0x28ff, 0x2091, 0x8000, 0x7823,
-	0x4000, 0x7827, 0x4953, 0x782b, 0x5020, 0x782f, 0x2020, 0x2009,
-	0x017f, 0x2104, 0x7832, 0x3f00, 0x7836, 0x2061, 0x0100, 0x6200,
-	0x2061, 0x0200, 0x603c, 0x8007, 0xa205, 0x783a, 0x2009, 0x04fd,
-	0x2104, 0x783e, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080,
-	0x2071, 0x0010, 0x20c1, 0x00f0, 0x0804, 0x0427, 0x81ff, 0x1904,
-	0x2924, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x080c, 0x4434, 0x1904,
-	0x2927, 0x7e38, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0210, 0x0804,
-	0x2927, 0x7c28, 0x7d2c, 0x080c, 0x45d4, 0xd28c, 0x1118, 0x080c,
-	0x457f, 0x0010, 0x080c, 0x45ad, 0x1518, 0x2061, 0x9900, 0x0126,
-	0x2091, 0x8000, 0x6000, 0xa086, 0x0000, 0x0148, 0x6010, 0xa06d,
-	0x0130, 0x683c, 0xa406, 0x1118, 0x6840, 0xa506, 0x0150, 0x012e,
-	0xace0, 0x000c, 0x2001, 0x9216, 0x2004, 0xac02, 0x1a04, 0x2924,
-	0x0c30, 0x080c, 0x80f6, 0x012e, 0x0904, 0x2924, 0x0804, 0x28ff,
-	0xa00e, 0x2001, 0x0005, 0x080c, 0x492c, 0x0126, 0x2091, 0x8000,
-	0x080c, 0x852d, 0x080c, 0x4809, 0x012e, 0x0804, 0x28ff, 0x81ff,
-	0x1904, 0x2924, 0x080c, 0x3656, 0x0904, 0x2927, 0x080c, 0x44d4,
-	0x0904, 0x2924, 0x080c, 0x45e0, 0x0904, 0x2924, 0x0804, 0x28ff,
-	0x81ff, 0x1904, 0x2924, 0x080c, 0x3666, 0x0904, 0x2927, 0x080c,
-	0x4644, 0x0904, 0x2924, 0x2019, 0x0005, 0x080c, 0x45fb, 0x0904,
-	0x2924, 0x7828, 0xa08a, 0x1000, 0x1a04, 0x2927, 0x8003, 0x800b,
-	0x810b, 0xa108, 0x080c, 0x573d, 0x0804, 0x28ff, 0x0126, 0x2091,
-	0x8000, 0x81ff, 0x1508, 0x2029, 0x00ff, 0x644c, 0x2400, 0xa506,
-	0x01b0, 0x2508, 0x080c, 0x4434, 0x1190, 0x080c, 0x4644, 0x01a0,
-	0x2019, 0x0004, 0x080c, 0x45fb, 0x0178, 0x7824, 0xa08a, 0x1000,
-	0x1270, 0x8003, 0x800b, 0x810b, 0xa108, 0x080c, 0x573d, 0x8529,
-	0x1e28, 0x012e, 0x0804, 0x28ff, 0x012e, 0x0804, 0x2924, 0x012e,
-	0x0804, 0x2927, 0x080c, 0x3656, 0x0904, 0x2927, 0x080c, 0x453a,
-	0x080c, 0x45d4, 0x0804, 0x28ff, 0x81ff, 0x1904, 0x2924, 0x080c,
-	0x3656, 0x0904, 0x2927, 0x080c, 0x452b, 0x080c, 0x45d4, 0x0804,
-	0x28ff, 0x81ff, 0x1904, 0x2924, 0x080c, 0x3656, 0x0904, 0x2927,
-	0x080c, 0x45af, 0x0904, 0x2924, 0x080c, 0x4373, 0x080c, 0x4578,
-	0x080c, 0x45d4, 0x0804, 0x28ff, 0x080c, 0x3656, 0x0904, 0x2927,
-	0x080c, 0x44d4, 0x0904, 0x2924, 0x62a0, 0x2019, 0x0005, 0x00c6,
-	0x080c, 0x460d, 0x2061, 0x0000, 0x080c, 0x6127, 0x0086, 0x2041,
-	0x0000, 0x080c, 0x606d, 0x2c08, 0x080c, 0x8ee4, 0x008e, 0x00ce,
-	0x080c, 0x45d4, 0x0804, 0x28ff, 0x080c, 0x3656, 0x0904, 0x2927,
-	0x080c, 0x45d4, 0x2208, 0x0804, 0x28ff, 0x0156, 0x00d6, 0x00e6,
-	0x2069, 0x9328, 0x6810, 0x6914, 0xa10a, 0x1210, 0x2009, 0x0000,
-	0x6816, 0x2011, 0x0000, 0x2019, 0x0000, 0x20a9, 0x007e, 0x2069,
-	0x936e, 0x2d04, 0xa075, 0x0130, 0x704c, 0x0071, 0xa210, 0x7080,
-	0x0059, 0xa318, 0x8d68, 0x1f04, 0x2b59, 0x2300, 0xa218, 0x00ee,
-	0x00de, 0x015e, 0x0804, 0x28ff, 0x00f6, 0x0016, 0xa07d, 0x0140,
-	0x2001, 0x0000, 0x8000, 0x2f0c, 0x81ff, 0x0110, 0x2178, 0x0cd0,
-	0x001e, 0x00fe, 0x0005, 0x2069, 0x9328, 0x6910, 0x62a8, 0x0804,
-	0x28ff, 0x81ff, 0x1904, 0x2924, 0x614c, 0xa190, 0x2719, 0x2215,
-	0xa294, 0x00ff, 0x636c, 0x83ff, 0x0108, 0x6270, 0x67c8, 0xd79c,
-	0x0118, 0x2031, 0x0001, 0x0060, 0xd7ac, 0x0118, 0x2031, 0x0003,
-	0x0038, 0xd7a4, 0x0118, 0x2031, 0x0002, 0x0010, 0x2031, 0x0000,
-	0x7e3a, 0x7f3e, 0x0804, 0x28ff, 0x613c, 0x6240, 0x0804, 0x28ff,
-	0x080c, 0x3666, 0x0904, 0x2927, 0x0804, 0x28ff, 0x080c, 0x3666,
-	0x0904, 0x2927, 0x6244, 0x6338, 0x0804, 0x28ff, 0x613c, 0x6240,
-	0x7824, 0x603e, 0x7b28, 0x6342, 0x2069, 0x9251, 0x831f, 0xa305,
-	0x6816, 0x0804, 0x28ff, 0x080c, 0x3666, 0x0904, 0x2927, 0x0804,
-	0x28ff, 0x080c, 0x3666, 0x0904, 0x2927, 0x7828, 0xa00d, 0x0904,
-	0x2927, 0x782c, 0xa005, 0x0904, 0x2927, 0x6244, 0x6146, 0x6338,
-	0x603a, 0x0804, 0x28ff, 0x2001, 0x9200, 0x2004, 0xa086, 0x0003,
-	0x1904, 0x2924, 0x00c6, 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c,
-	0x00ff, 0xa196, 0x00ff, 0x1130, 0x2001, 0x9214, 0x2004, 0xa085,
-	0xff00, 0x0078, 0xa182, 0x007f, 0x1698, 0xa188, 0x2719, 0x210d,
-	0xa18c, 0x00ff, 0x2001, 0x9214, 0x2004, 0xa116, 0x0548, 0x810f,
-	0xa105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0x749c, 0x000e,
-	0x01e0, 0x601a, 0x600b, 0xbc09, 0x601f, 0x0001, 0x080c, 0x3641,
+	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x2071, 0x8b81, 0x7003,
+	0x0002, 0xa006, 0x7012, 0x7016, 0x703a, 0x703e, 0x7033, 0x8b91,
+	0x7037, 0x8b91, 0x7007, 0x0001, 0x2061, 0x8bd1, 0x6003, 0x0002,
+	0x0005, 0x1004, 0x2763, 0x0e04, 0x2763, 0x2071, 0x8b81, 0x2b78,
+	0x7818, 0xd084, 0x1140, 0x2a60, 0x7820, 0xa08e, 0x0069, 0x1904,
+	0x2848, 0x0804, 0x27e1, 0x0005, 0x2071, 0x8b81, 0x7004, 0x0002,
+	0x276c, 0x276d, 0x2776, 0x2787, 0x0005, 0x1004, 0x2775, 0x0e04,
+	0x2775, 0x2b78, 0x7818, 0xd084, 0x01e8, 0x0005, 0x2b78, 0x2061,
+	0x8bd1, 0x6008, 0xa08e, 0x0100, 0x0128, 0xa086, 0x0200, 0x0904,
+	0x2842, 0x0005, 0x7014, 0x2068, 0x2a60, 0x7018, 0x0807, 0x7010,
+	0x2068, 0x6834, 0xa086, 0x0103, 0x0108, 0x0005, 0x2a60, 0x2b78,
+	0x7018, 0x0807, 0x2a60, 0x7820, 0xa08a, 0x0040, 0x1210, 0x61bc,
+	0x0042, 0x2100, 0xa08a, 0x003f, 0x1a04, 0x283f, 0x61bc, 0x0804,
+	0x27e1, 0x2823, 0x284e, 0x2856, 0x285a, 0x2862, 0x2868, 0x286c,
+	0x2875, 0x2878, 0x2882, 0x2885, 0x283f, 0x283f, 0x283f, 0x2888,
+	0x283f, 0x2897, 0x28ae, 0x28c5, 0x293c, 0x2941, 0x296a, 0x29bb,
+	0x29cc, 0x29ea, 0x2a21, 0x2a2b, 0x2a38, 0x2a4b, 0x2a6b, 0x2a74,
+	0x2aaa, 0x2ab0, 0x283f, 0x2ad3, 0x283f, 0x283f, 0x283f, 0x283f,
+	0x283f, 0x2ad7, 0x2ae1, 0x283f, 0x283f, 0x283f, 0x283f, 0x283f,
+	0x283f, 0x283f, 0x283f, 0x2ae9, 0x283f, 0x283f, 0x283f, 0x283f,
+	0x283f, 0x2af6, 0x2afe, 0x283f, 0x283f, 0x283f, 0x283f, 0x283f,
+	0x283f, 0x0002, 0x2b10, 0x2b63, 0x2bbd, 0x2bcd, 0x283f, 0x2be7,
+	0x2ff7, 0x393f, 0x283f, 0x283f, 0x283f, 0x283f, 0x283f, 0x283f,
+	0x283f, 0x283f, 0x2882, 0x2885, 0x283f, 0x283f, 0x2ff9, 0x283f,
+	0x283f, 0x283f, 0x283f, 0x283f, 0x283f, 0x283f, 0x283f, 0x283f,
+	0x283f, 0x283f, 0x2ffd, 0x314a, 0x315e, 0x3178, 0x31d9, 0x322a,
+	0x3235, 0x326c, 0x327b, 0x328a, 0x3299, 0x32c1, 0x330b, 0x336d,
+	0x337a, 0x3474, 0x356e, 0x3597, 0x3695, 0x36b1, 0x36bd, 0x36f6,
+	0x378d, 0x283f, 0x283f, 0x283f, 0x283f, 0x37f5, 0x3810, 0x3880,
+	0x3930, 0x713c, 0x0000, 0x2021, 0x4000, 0x080c, 0x35f4, 0x0126,
+	0x2091, 0x8000, 0x0e04, 0x282f, 0x7818, 0xd084, 0x0110, 0x012e,
+	0x0cb0, 0x7c22, 0x7926, 0x7a2a, 0x7b2e, 0x781b, 0x0001, 0x2091,
+	0x4080, 0x7007, 0x0001, 0x2091, 0x5000, 0x012e, 0x0005, 0x2021,
+	0x4001, 0x0c18, 0x2021, 0x4002, 0x0c00, 0x2021, 0x4003, 0x08e8,
+	0x2021, 0x4005, 0x08d0, 0x2021, 0x4006, 0x08b8, 0xa02e, 0x2520,
+	0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0804, 0x3601, 0x7823, 0x0004,
+	0x7824, 0x0807, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930,
+	0x0804, 0x3604, 0x7924, 0x7828, 0x2114, 0x200a, 0x0804, 0x2823,
+	0x7924, 0x2114, 0x0804, 0x2823, 0x2099, 0x0009, 0x20a1, 0x0009,
+	0x20a9, 0x0007, 0x53a3, 0x0804, 0x2823, 0x7824, 0x2060, 0x0090,
+	0x2009, 0x0002, 0x2011, 0x0000, 0x2019, 0x0028, 0x783b, 0x0007,
+	0x0804, 0x2823, 0x7d38, 0x7c3c, 0x0858, 0x7d38, 0x7c3c, 0x08a0,
+	0x2061, 0x1000, 0xe10c, 0xa006, 0x2c15, 0xa200, 0x8c60, 0x8109,
+	0x1dd8, 0x2010, 0xa005, 0x0904, 0x2823, 0x0804, 0x2845, 0x2069,
+	0x8b51, 0x7824, 0x7930, 0xa11a, 0x1a04, 0x284b, 0x8019, 0x0904,
+	0x284b, 0x684a, 0x6942, 0x782c, 0x6852, 0x7828, 0x6856, 0xa006,
+	0x685a, 0x685e, 0x080c, 0x4d79, 0x0804, 0x2823, 0x2069, 0x8b51,
+	0x7824, 0x7934, 0xa11a, 0x1a04, 0x284b, 0x8019, 0x0904, 0x284b,
+	0x684e, 0x6946, 0x782c, 0x6862, 0x7828, 0x6866, 0xa006, 0x686a,
+	0x686e, 0x080c, 0x4670, 0x0804, 0x2823, 0xa02e, 0x2520, 0x81ff,
+	0x1904, 0x2848, 0x7924, 0x7b28, 0x7a2c, 0x20a9, 0x0005, 0x20a1,
+	0x8b88, 0x41a1, 0x080c, 0x35c0, 0x0904, 0x2848, 0x2009, 0x0023,
+	0x080c, 0x3601, 0x701b, 0x28dd, 0x0005, 0x6834, 0x2008, 0xa084,
+	0x00ff, 0xa096, 0x0011, 0x0120, 0xa096, 0x0019, 0x1904, 0x2848,
+	0x810f, 0xa18c, 0x00ff, 0x0904, 0x2848, 0x710e, 0x700c, 0x8001,
+	0x0528, 0x700e, 0x080c, 0x35c0, 0x0904, 0x2848, 0x2009, 0x0023,
+	0x2061, 0x8bd1, 0x6224, 0x6328, 0x642c, 0x6530, 0xa290, 0x0046,
+	0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x080c, 0x3601,
+	0x701b, 0x290b, 0x0005, 0x6834, 0xa084, 0x00ff, 0xa096, 0x0002,
+	0x0120, 0xa096, 0x000a, 0x1904, 0x2848, 0x08c0, 0x7010, 0x2068,
+	0x6838, 0xc0fd, 0x683a, 0x080c, 0x420d, 0x1128, 0x7007, 0x0003,
+	0x701b, 0x2925, 0x0005, 0x080c, 0x4773, 0x0126, 0x2091, 0x8000,
+	0x20a9, 0x0005, 0x2099, 0x8b88, 0x530a, 0x2100, 0xa210, 0xa399,
+	0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0xad80, 0x000d, 0x2009,
+	0x0023, 0x012e, 0x0804, 0x3604, 0x61a4, 0x7824, 0x60a6, 0x0804,
+	0x2823, 0x2091, 0x8000, 0x7823, 0x4000, 0x7827, 0x4953, 0x782b,
+	0x5020, 0x782f, 0x2020, 0x2009, 0x017f, 0x2104, 0x7832, 0x3f00,
+	0x7836, 0x2061, 0x0100, 0x6200, 0x2061, 0x0200, 0x603c, 0x8007,
+	0xa205, 0x783a, 0x2009, 0x04fd, 0x2104, 0x783e, 0x781b, 0x0001,
+	0x2091, 0x5000, 0x2091, 0x4080, 0x2071, 0x0010, 0x20c1, 0x00f0,
+	0x0804, 0x0427, 0x81ff, 0x1904, 0x2848, 0x7924, 0x810f, 0xa18c,
+	0x00ff, 0x080c, 0x430a, 0x1904, 0x284b, 0x7e38, 0xa684, 0x3fff,
+	0xa082, 0x4000, 0x0210, 0x0804, 0x284b, 0x7c28, 0x7d2c, 0x080c,
+	0x44ad, 0xd28c, 0x1118, 0x080c, 0x4458, 0x0010, 0x080c, 0x4486,
+	0x1518, 0x2061, 0x9200, 0x0126, 0x2091, 0x8000, 0x6000, 0xa086,
+	0x0000, 0x0148, 0x6010, 0xa06d, 0x0130, 0x683c, 0xa406, 0x1118,
+	0x6840, 0xa506, 0x0150, 0x012e, 0xace0, 0x000c, 0x2001, 0x8b16,
+	0x2004, 0xac02, 0x1a04, 0x2848, 0x0c30, 0x080c, 0x795f, 0x012e,
+	0x0904, 0x2848, 0x0804, 0x2823, 0xa00e, 0x2001, 0x0005, 0x080c,
+	0x4773, 0x0126, 0x2091, 0x8000, 0x080c, 0x7dce, 0x080c, 0x46a1,
+	0x012e, 0x0804, 0x2823, 0x81ff, 0x1904, 0x2848, 0x080c, 0x35d5,
+	0x0904, 0x284b, 0x080c, 0x43ad, 0x0904, 0x2848, 0x080c, 0x44b9,
+	0x0904, 0x2848, 0x0804, 0x2823, 0x81ff, 0x1904, 0x2848, 0x080c,
+	0x35e5, 0x0904, 0x284b, 0x080c, 0x451d, 0x0904, 0x2848, 0x2019,
+	0x0005, 0x080c, 0x44d4, 0x0904, 0x2848, 0x7828, 0xa08a, 0x1000,
+	0x1a04, 0x284b, 0x8003, 0x800b, 0x810b, 0xa108, 0x080c, 0x5619,
+	0x0804, 0x2823, 0x0126, 0x2091, 0x8000, 0x81ff, 0x0118, 0x2009,
+	0x0001, 0x0448, 0x2029, 0x00ff, 0x644c, 0x2400, 0xa506, 0x01f0,
+	0x2508, 0x080c, 0x430a, 0x11d0, 0x080c, 0x451d, 0x1128, 0x2009,
+	0x0002, 0x62ac, 0x2518, 0x00b8, 0x2019, 0x0004, 0x080c, 0x44d4,
+	0x1118, 0x2009, 0x0006, 0x0078, 0x7824, 0xa08a, 0x1000, 0x1270,
+	0x8003, 0x800b, 0x810b, 0xa108, 0x080c, 0x5619, 0x8529, 0x1ae8,
+	0x012e, 0x0804, 0x2823, 0x012e, 0x0804, 0x2848, 0x012e, 0x0804,
+	0x284b, 0x080c, 0x35d5, 0x0904, 0x284b, 0x080c, 0x4413, 0x080c,
+	0x44ad, 0x0804, 0x2823, 0x81ff, 0x1904, 0x2848, 0x080c, 0x35d5,
+	0x0904, 0x284b, 0x080c, 0x4404, 0x080c, 0x44ad, 0x0804, 0x2823,
+	0x81ff, 0x1904, 0x2848, 0x080c, 0x35d5, 0x0904, 0x284b, 0x080c,
+	0x4488, 0x0904, 0x2848, 0x080c, 0x4249, 0x080c, 0x4451, 0x080c,
+	0x44ad, 0x0804, 0x2823, 0x080c, 0x35d5, 0x0904, 0x284b, 0x080c,
+	0x43ad, 0x0904, 0x2848, 0x62a0, 0x2019, 0x0005, 0x00c6, 0x080c,
+	0x44e6, 0x2061, 0x0000, 0x080c, 0x59d5, 0x0086, 0x2041, 0x0000,
+	0x080c, 0x5911, 0x2c08, 0x080c, 0x878f, 0x008e, 0x00ce, 0x080c,
+	0x44ad, 0x0804, 0x2823, 0x080c, 0x35d5, 0x0904, 0x284b, 0x080c,
+	0x44ad, 0x2208, 0x0804, 0x2823, 0x0156, 0x00d6, 0x00e6, 0x2069,
+	0x8c13, 0x6810, 0x6914, 0xa10a, 0x1210, 0x2009, 0x0000, 0x6816,
+	0x2011, 0x0000, 0x2019, 0x0000, 0x20a9, 0x007e, 0x2069, 0x8c34,
+	0x2d04, 0xa075, 0x0130, 0x704c, 0x0071, 0xa210, 0x7080, 0x0059,
+	0xa318, 0x8d68, 0x1f04, 0x2a88, 0x2300, 0xa218, 0x00ee, 0x00de,
+	0x015e, 0x0804, 0x2823, 0x00f6, 0x0016, 0xa07d, 0x0140, 0x2001,
+	0x0000, 0x8000, 0x2f0c, 0x81ff, 0x0110, 0x2178, 0x0cd0, 0x001e,
+	0x00fe, 0x0005, 0x2069, 0x8c13, 0x6910, 0x62a8, 0x0804, 0x2823,
+	0x81ff, 0x1904, 0x2848, 0x614c, 0xa190, 0x263d, 0x2215, 0xa294,
+	0x00ff, 0x636c, 0x83ff, 0x0108, 0x6270, 0x67c8, 0xd79c, 0x0118,
+	0x2031, 0x0001, 0x0060, 0xd7ac, 0x0118, 0x2031, 0x0003, 0x0038,
+	0xd7a4, 0x0118, 0x2031, 0x0002, 0x0010, 0x2031, 0x0000, 0x7e3a,
+	0x7f3e, 0x0804, 0x2823, 0x613c, 0x6240, 0x0804, 0x2823, 0x0126,
+	0x2091, 0x8000, 0x6134, 0xa006, 0x2010, 0x2018, 0x012e, 0x0804,
+	0x2823, 0x080c, 0x35e5, 0x0904, 0x284b, 0x6244, 0x6338, 0x0804,
+	0x2823, 0x613c, 0x6240, 0x7824, 0x603e, 0x7b28, 0x6342, 0x2069,
+	0x8b51, 0x831f, 0xa305, 0x6816, 0x0804, 0x2823, 0x0126, 0x2091,
+	0x8000, 0x7824, 0x6036, 0x012e, 0x0804, 0x2823, 0x080c, 0x35e5,
+	0x0904, 0x284b, 0x7828, 0xa00d, 0x0904, 0x284b, 0x782c, 0xa005,
+	0x0904, 0x284b, 0x6244, 0x6146, 0x6338, 0x603a, 0x0804, 0x2823,
+	0x2001, 0x8b00, 0x2004, 0xa086, 0x0003, 0x1904, 0x2848, 0x00c6,
+	0x2061, 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff,
+	0x1130, 0x2001, 0x8b14, 0x2004, 0xa085, 0xff00, 0x0078, 0xa182,
+	0x007f, 0x1698, 0xa188, 0x263d, 0x210d, 0xa18c, 0x00ff, 0x2001,
+	0x8b14, 0x2004, 0xa116, 0x0548, 0x810f, 0xa105, 0x0126, 0x2091,
+	0x8000, 0x0006, 0x080c, 0x6cc2, 0x000e, 0x01e0, 0x601a, 0x600b,
+	0xbc09, 0x601f, 0x0001, 0x080c, 0x35c0, 0x01d0, 0x6837, 0x0000,
+	0x7007, 0x0003, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x701b,
+	0x2bb6, 0x2d00, 0x6012, 0x2009, 0x0032, 0x080c, 0x6d3f, 0x012e,
+	0x00ce, 0x0005, 0x00ce, 0x0804, 0x2848, 0x00ce, 0x0804, 0x284b,
+	0x080c, 0x6d18, 0x0cb8, 0x2001, 0x8b00, 0x2004, 0xa086, 0x0003,
+	0x1904, 0x2848, 0x00c6, 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c,
+	0x00ff, 0xa196, 0x00ff, 0x1130, 0x2001, 0x8b14, 0x2004, 0xa085,
+	0xff00, 0x0078, 0xa182, 0x007f, 0x1698, 0xa188, 0x263d, 0x210d,
+	0xa18c, 0x00ff, 0x2001, 0x8b14, 0x2004, 0xa116, 0x0548, 0x810f,
+	0xa105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0x6cc2, 0x000e,
+	0x01e0, 0x601a, 0x600b, 0xbc05, 0x601f, 0x0001, 0x080c, 0x35c0,
 	0x01d0, 0x6837, 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838,
-	0xc0fd, 0x683a, 0x701b, 0x2c81, 0x2d00, 0x6012, 0x2009, 0x0032,
-	0x080c, 0x7518, 0x012e, 0x00ce, 0x0005, 0x00ce, 0x0804, 0x2924,
-	0x00ce, 0x0804, 0x2927, 0x080c, 0x74f2, 0x0cb8, 0x2001, 0x9200,
-	0x2004, 0xa086, 0x0003, 0x1904, 0x2924, 0x00c6, 0x2061, 0x0100,
-	0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff, 0x1130, 0x2001,
-	0x9214, 0x2004, 0xa085, 0xff00, 0x0078, 0xa182, 0x007f, 0x1698,
-	0xa188, 0x2719, 0x210d, 0xa18c, 0x00ff, 0x2001, 0x9214, 0x2004,
-	0xa116, 0x0548, 0x810f, 0xa105, 0x0126, 0x2091, 0x8000, 0x0006,
-	0x080c, 0x749c, 0x000e, 0x01e0, 0x601a, 0x600b, 0xbc05, 0x601f,
-	0x0001, 0x080c, 0x3641, 0x01d0, 0x6837, 0x0000, 0x7007, 0x0003,
-	0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x701b, 0x2c81, 0x2d00,
-	0x6012, 0x2009, 0x0032, 0x080c, 0x7518, 0x012e, 0x00ce, 0x0005,
-	0x00ce, 0x0804, 0x2924, 0x00ce, 0x0804, 0x2927, 0x080c, 0x74f2,
-	0x0cb8, 0x6830, 0xa086, 0x0100, 0x0904, 0x2924, 0x0804, 0x28ff,
-	0x2061, 0x9566, 0x0126, 0x2091, 0x8000, 0x6000, 0xd084, 0x0128,
-	0x6104, 0x6208, 0x012e, 0x0804, 0x28ff, 0x012e, 0x0804, 0x2927,
-	0x81ff, 0x1904, 0x2924, 0x080c, 0x4dc5, 0x0904, 0x2924, 0x0126,
-	0x2091, 0x8000, 0x6244, 0x6064, 0xa202, 0x0248, 0xa085, 0x0001,
-	0x080c, 0x2455, 0x080c, 0x3bfd, 0x012e, 0x0804, 0x28ff, 0x012e,
-	0x0804, 0x2927, 0x0126, 0x2091, 0x8000, 0x7824, 0xa084, 0x0007,
-	0x0002, 0x2cc4, 0x2ccd, 0x2cd4, 0x2cc1, 0x2cc1, 0x2cc1, 0x2cc1,
-	0x2cc1, 0x012e, 0x0804, 0x2927, 0x2009, 0x0114, 0x2104, 0xa085,
-	0x0800, 0x200a, 0x080c, 0x2e1e, 0x0070, 0x2009, 0x010b, 0x200b,
-	0x0010, 0x080c, 0x2e1e, 0x0038, 0x81ff, 0x0128, 0x012e, 0x2021,
-	0x400b, 0x0804, 0x2901, 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6,
-	0x00d6, 0x00e6, 0x00f6, 0x2009, 0x0101, 0x210c, 0x0016, 0x2001,
-	0x0138, 0x200c, 0x2003, 0x0001, 0x0016, 0x2001, 0x007a, 0x2034,
-	0x2001, 0x007b, 0x202c, 0xa006, 0x2048, 0x2050, 0x2058, 0x080c,
-	0x302f, 0x080c, 0x2f99, 0xa03e, 0x2720, 0x00f6, 0x00e6, 0x00c6,
-	0x2d60, 0x2071, 0x953b, 0x2079, 0x0020, 0x2011, 0x0001, 0x080c,
-	0x2f45, 0x080c, 0x2f45, 0x00ce, 0x00ee, 0x00fe, 0x080c, 0x2ea6,
-	0x080c, 0x2f6d, 0x080c, 0x2eea, 0x080c, 0x2e65, 0x080c, 0x2e96,
-	0x00f6, 0x2079, 0x0100, 0x7824, 0xd094, 0x01d8, 0x7817, 0x0010,
-	0x2079, 0x0140, 0x2001, 0x0109, 0x2004, 0xd0ac, 0x11a8, 0x7804,
-	0xd0dc, 0x0dc0, 0x2079, 0x0100, 0x7827, 0x0086, 0x7817, 0x0032,
-	0x7824, 0xd0ac, 0x1148, 0xd0bc, 0x0dd8, 0x7827, 0x0080, 0xa026,
-	0x7c16, 0x7824, 0xd0ac, 0x0130, 0x8b58, 0x080c, 0x2e06, 0x00fe,
-	0x0804, 0x2dd0, 0x00fe, 0x1d04, 0x2d55, 0x2091, 0x6000, 0x8420,
-	0xa486, 0x0064, 0x1150, 0x8948, 0x2001, 0x007a, 0x2602, 0x2001,
-	0x007b, 0x2502, 0x080c, 0x2e06, 0x0088, 0x87ff, 0x0140, 0x2001,
-	0x0201, 0x2004, 0xa005, 0x1904, 0x2d10, 0x8739, 0x0038, 0x2001,
-	0x9519, 0x2004, 0xa086, 0x0000, 0x1904, 0x2d10, 0x2001, 0x0033,
-	0x2003, 0x00f0, 0x8631, 0x1208, 0x8529, 0x2500, 0xa605, 0x0904,
-	0x2dd0, 0x7824, 0xd0bc, 0x0128, 0x2900, 0xaa05, 0xab05, 0x1904,
-	0x2dd0, 0x6033, 0x000d, 0x2001, 0x0030, 0x2003, 0x0004, 0x7824,
-	0xd0ac, 0x1148, 0x2001, 0x9519, 0x2003, 0x0003, 0x2001, 0x0030,
-	0x2003, 0x0009, 0x0040, 0x6027, 0x0001, 0x2001, 0x0075, 0x2004,
-	0xa005, 0x0108, 0x6026, 0x2c00, 0x601a, 0x20e1, 0x9040, 0x2d00,
-	0x681a, 0x6833, 0x000d, 0x7824, 0xd0a4, 0x1180, 0x6827, 0x0000,
-	0x00c6, 0x20a9, 0x0008, 0x2061, 0x0020, 0x6003, 0x0008, 0x2001,
-	0x0203, 0x2004, 0x1f04, 0x2da5, 0x00ce, 0x0040, 0x6827, 0x0001,
-	0x2001, 0x0074, 0x2004, 0xa005, 0x0108, 0x6826, 0x00f6, 0x00c6,
-	0x2079, 0x0100, 0x2061, 0x0020, 0x7827, 0x0002, 0x2001, 0x0072,
-	0x2004, 0xa084, 0xfff8, 0x601a, 0x0006, 0x2001, 0x0073, 0x2004,
-	0x601e, 0x78c6, 0x000e, 0x78ca, 0x00ce, 0x00fe, 0x0804, 0x2cfd,
-	0x2061, 0x0100, 0x6027, 0x0002, 0x20e1, 0x9028, 0x6050, 0xa084,
-	0xf7ef, 0x6052, 0x602f, 0x0000, 0x001e, 0x61e2, 0x001e, 0x6106,
-	0x7824, 0xa084, 0x0003, 0xa086, 0x0002, 0x0148, 0x602c, 0xc0ac,
-	0x602e, 0x604b, 0xf7f7, 0x6043, 0x0090, 0x6043, 0x0010, 0x2908,
-	0x2a10, 0x2b18, 0x2b00, 0xaa05, 0xa905, 0x00fe, 0x00ee, 0x00de,
-	0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x1118, 0x012e, 0x0804,
-	0x28ff, 0x012e, 0x2021, 0x400c, 0x0804, 0x2901, 0x2001, 0x0105,
-	0x2003, 0x0010, 0x2001, 0x0030, 0x2003, 0x0004, 0x2001, 0x0020,
-	0x2003, 0x0004, 0x2001, 0x9519, 0x2003, 0x0000, 0x2001, 0x953b,
-	0x2003, 0x0000, 0x20e1, 0xf000, 0xa026, 0x0005, 0x00f6, 0x2079,
-	0x0100, 0x7850, 0xa084, 0x0990, 0x7852, 0x782c, 0xa085, 0x0020,
-	0x782e, 0x20a9, 0x0008, 0x1d04, 0x2e2b, 0x2091, 0x6000, 0x1f04,
-	0x2e2b, 0x7850, 0xa085, 0x0400, 0x7852, 0x784b, 0xf7f7, 0x7843,
-	0x0090, 0x7843, 0x0010, 0x20a9, 0x000e, 0xe000, 0x1f04, 0x2e3d,
+	0xc0fd, 0x683a, 0x701b, 0x2bb6, 0x2d00, 0x6012, 0x2009, 0x0032,
+	0x080c, 0x6d3f, 0x012e, 0x00ce, 0x0005, 0x00ce, 0x0804, 0x2848,
+	0x00ce, 0x0804, 0x284b, 0x080c, 0x6d18, 0x0cb8, 0x6830, 0xa086,
+	0x0100, 0x0904, 0x2848, 0x0804, 0x2823, 0x2061, 0x8e2a, 0x0126,
+	0x2091, 0x8000, 0x6000, 0xd084, 0x0128, 0x6104, 0x6208, 0x012e,
+	0x0804, 0x2823, 0x012e, 0x0804, 0x284b, 0x81ff, 0x1904, 0x2848,
+	0x080c, 0x4c42, 0x0904, 0x2848, 0x0126, 0x2091, 0x8000, 0x6244,
+	0x6064, 0xa202, 0x0248, 0xa085, 0x0001, 0x080c, 0x2333, 0x080c,
+	0x3b32, 0x012e, 0x0804, 0x2823, 0x012e, 0x0804, 0x284b, 0x0126,
+	0x2091, 0x8000, 0x7824, 0xa084, 0x0007, 0x0002, 0x2bf9, 0x2c02,
+	0x2c09, 0x2bf6, 0x2bf6, 0x2bf6, 0x2bf6, 0x2bf6, 0x012e, 0x0804,
+	0x284b, 0x2009, 0x0114, 0x2104, 0xa085, 0x0800, 0x200a, 0x080c,
+	0x2d63, 0x0070, 0x2009, 0x010b, 0x200b, 0x0010, 0x080c, 0x2d63,
+	0x0038, 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, 0x2825,
+	0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6,
+	0x2009, 0x0101, 0x210c, 0x0016, 0x2001, 0x0138, 0x200c, 0x2003,
+	0x0001, 0x0016, 0x2001, 0x007a, 0x2034, 0x2001, 0x007b, 0x202c,
+	0xa006, 0x2048, 0x2050, 0x2058, 0x080c, 0x2f8a, 0x080c, 0x2ef4,
+	0xa03e, 0x2720, 0x00f6, 0x00e6, 0x00c6, 0x2d60, 0x2071, 0x8dff,
+	0x2079, 0x0020, 0x2011, 0x0001, 0x080c, 0x2ea0, 0x080c, 0x2ea0,
+	0x00ce, 0x00ee, 0x00fe, 0x080c, 0x2dfa, 0x080c, 0x2ec8, 0x080c,
+	0x2e45, 0x080c, 0x2db9, 0x080c, 0x2dea, 0x00f6, 0x2079, 0x0100,
+	0x7824, 0xd094, 0x0530, 0x7814, 0xa084, 0x0184, 0xa085, 0x0010,
+	0x7816, 0x2079, 0x0140, 0x080c, 0x2d41, 0x1110, 0x00fe, 0x0430,
+	0x7804, 0xd0dc, 0x0dc0, 0x2079, 0x0100, 0x7827, 0x0086, 0x7814,
+	0xa084, 0x0184, 0xa085, 0x0032, 0x7816, 0x080c, 0x2d41, 0x1110,
+	0x00fe, 0x00a0, 0x7824, 0xd0bc, 0x0dc0, 0x7827, 0x0080, 0xa026,
+	0x7c16, 0x7824, 0xd0ac, 0x0130, 0x8b58, 0x080c, 0x2d4b, 0x00fe,
+	0x0804, 0x2d0b, 0x00fe, 0x080c, 0x2d41, 0x1150, 0x8948, 0x2001,
+	0x007a, 0x2602, 0x2001, 0x007b, 0x2502, 0x080c, 0x2d4b, 0x0088,
+	0x87ff, 0x0140, 0x2001, 0x0201, 0x2004, 0xa005, 0x1904, 0x2c45,
+	0x8739, 0x0038, 0x2001, 0x8dde, 0x2004, 0xa086, 0x0000, 0x1904,
+	0x2c45, 0x2001, 0x0033, 0x2003, 0x00f6, 0x8631, 0x1208, 0x8529,
+	0x2500, 0xa605, 0x0904, 0x2d0b, 0x7824, 0xd0bc, 0x0128, 0x2900,
+	0xaa05, 0xab05, 0x1904, 0x2d0b, 0x6033, 0x000d, 0x2001, 0x0030,
+	0x2003, 0x0004, 0x7824, 0xd0ac, 0x1148, 0x2001, 0x8dde, 0x2003,
+	0x0003, 0x2001, 0x0030, 0x2003, 0x0009, 0x0040, 0x6027, 0x0001,
+	0x2001, 0x0075, 0x2004, 0xa005, 0x0108, 0x6026, 0x2c00, 0x601a,
+	0x20e1, 0x9040, 0x2d00, 0x681a, 0x6833, 0x000d, 0x7824, 0xd0a4,
+	0x1180, 0x6827, 0x0000, 0x00c6, 0x20a9, 0x0008, 0x2061, 0x0020,
+	0x6003, 0x0008, 0x2001, 0x0203, 0x2004, 0x1f04, 0x2ce0, 0x00ce,
+	0x0040, 0x6827, 0x0001, 0x2001, 0x0074, 0x2004, 0xa005, 0x0108,
+	0x6826, 0x00f6, 0x00c6, 0x2079, 0x0100, 0x2061, 0x0020, 0x7827,
+	0x0002, 0x2001, 0x0072, 0x2004, 0xa084, 0xfff8, 0x601a, 0x0006,
+	0x2001, 0x0073, 0x2004, 0x601e, 0x78c6, 0x000e, 0x78ca, 0x00ce,
+	0x00fe, 0x0804, 0x2c32, 0x2061, 0x0100, 0x6027, 0x0002, 0x001e,
+	0x61e2, 0x001e, 0x6106, 0x7824, 0xa084, 0x0003, 0xa086, 0x0002,
+	0x0188, 0x20e1, 0x9028, 0x6050, 0xa084, 0xf7ef, 0x6052, 0x602f,
+	0x0000, 0x602c, 0xc0ac, 0x602e, 0x604b, 0xf7f7, 0x6043, 0x0090,
+	0x6043, 0x0010, 0x2908, 0x2a10, 0x2b18, 0x2b00, 0xaa05, 0xa905,
+	0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e,
+	0x1118, 0x012e, 0x0804, 0x2823, 0x012e, 0x2021, 0x400c, 0x0804,
+	0x2825, 0xa085, 0x0001, 0x1d04, 0x2d4a, 0x2091, 0x6000, 0x8420,
+	0xa486, 0x0064, 0x0005, 0x2001, 0x0105, 0x2003, 0x0010, 0x2001,
+	0x0030, 0x2003, 0x0004, 0x2001, 0x0020, 0x2003, 0x0004, 0x2001,
+	0x8dde, 0x2003, 0x0000, 0x2001, 0x8dff, 0x2003, 0x0000, 0x20e1,
+	0xf000, 0xa026, 0x0005, 0x00f6, 0x2079, 0x0100, 0x7850, 0xa084,
+	0x0990, 0x7852, 0x782c, 0xa085, 0x0020, 0x782e, 0x20a9, 0x0008,
+	0x1d04, 0x2d70, 0x2091, 0x6000, 0x1f04, 0x2d70, 0x7850, 0xa085,
+	0x0400, 0x7852, 0x2001, 0x0009, 0x2004, 0xa084, 0x0003, 0xa086,
+	0x0001, 0x1118, 0x782c, 0xc0ac, 0x782e, 0x784b, 0xf7f7, 0x7843,
+	0x0090, 0x7843, 0x0010, 0x20a9, 0x000e, 0xe000, 0x1f04, 0x2d8d,
 	0x7850, 0xa085, 0x1400, 0x7852, 0x2019, 0x61a8, 0x7854, 0xe000,
 	0xe000, 0xd08c, 0x1110, 0x8319, 0x1dc8, 0x7827, 0x0048, 0x7850,
 	0xa085, 0x0400, 0x7852, 0x7843, 0x0040, 0x2019, 0x01f4, 0xe000,
-	0xe000, 0x8319, 0x1de0, 0x2001, 0x0140, 0x2003, 0x0100, 0x7843,
-	0x0000, 0x2003, 0x0000, 0x00fe, 0x0005, 0x7824, 0xd0ac, 0x11c8,
-	0x00f6, 0x00e6, 0x2071, 0x9519, 0x2079, 0x0030, 0x2001, 0x0201,
-	0x2004, 0xa005, 0x0160, 0x7000, 0xa086, 0x0000, 0x1140, 0x0051,
-	0xd0bc, 0x0108, 0x8738, 0x7003, 0x0003, 0x7803, 0x0019, 0x00ee,
-	0x00fe, 0x0005, 0x780c, 0xa08c, 0x0070, 0x0178, 0x2009, 0x007a,
-	0x260a, 0x2009, 0x007b, 0x250a, 0xd0b4, 0x0108, 0x8a50, 0xd0ac,
-	0x0108, 0x8948, 0xd0a4, 0x0108, 0x8b58, 0x0005, 0x00f6, 0x2079,
-	0x0200, 0x781c, 0xd084, 0x0140, 0x20e1, 0x0007, 0x20e1, 0x2000,
-	0x2001, 0x020a, 0x2004, 0x0ca8, 0x00fe, 0x0005, 0x00e6, 0x2071,
-	0x0100, 0x2009, 0x9214, 0x210c, 0x716e, 0x7063, 0x0100, 0x7166,
-	0x719e, 0x706b, 0x0000, 0x7073, 0x0809, 0x7077, 0x0008, 0x7078,
-	0xa080, 0x0100, 0x707a, 0x7080, 0x8000, 0x7082, 0x7087, 0xaaaa,
-	0xa006, 0x708a, 0x708e, 0x707e, 0x70d6, 0x70ab, 0x0036, 0x70af,
-	0x95d5, 0x7027, 0x0080, 0x7017, 0x0032, 0x080c, 0x2f6d, 0x7024,
-	0xd0ac, 0x1120, 0xd0bc, 0x0dc8, 0x7027, 0x0080, 0x00f6, 0x00e6,
-	0x2071, 0x9519, 0x2079, 0x0030, 0x2011, 0x0011, 0x080c, 0x2f45,
-	0x2011, 0x0001, 0x080c, 0x2f45, 0x00ee, 0x00fe, 0x7017, 0x0000,
-	0x00ee, 0x0005, 0x00f6, 0x00e6, 0x2071, 0x9519, 0x2079, 0x0030,
-	0x7904, 0xd1fc, 0x0904, 0x2f42, 0x7803, 0x0002, 0xa026, 0xd19c,
-	0x1904, 0x2f3e, 0x7000, 0x0002, 0x2f42, 0x2f00, 0x2f24, 0x2f3e,
-	0xd1bc, 0x1150, 0xd1dc, 0x1150, 0x8001, 0x7002, 0x2011, 0x0001,
-	0x04e1, 0x05c0, 0x04d1, 0x04b0, 0x780f, 0x0000, 0x7820, 0x7924,
-	0x7803, 0x0004, 0x7822, 0x7926, 0x2001, 0x0201, 0x200c, 0x81ff,
-	0x0de8, 0x080c, 0x2e82, 0x2009, 0x0001, 0x7808, 0xd0ec, 0x0110,
-	0x2009, 0x0011, 0x7902, 0x00f0, 0x8001, 0x7002, 0xa184, 0x0880,
-	0x1138, 0x7804, 0xd0fc, 0x1940, 0x2011, 0x0001, 0x00b1, 0x0090,
-	0x6030, 0xa092, 0x0004, 0xa086, 0x0009, 0x1120, 0x6000, 0x601a,
-	0x2011, 0x0025, 0x6232, 0xd1dc, 0x1988, 0x0870, 0x7803, 0x0004,
-	0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x6024, 0xa005, 0x0520,
-	0x8001, 0x6026, 0x6018, 0x6130, 0xa140, 0x2804, 0x7832, 0x8840,
-	0x2804, 0x7836, 0x8840, 0x2804, 0x7822, 0x8840, 0x2804, 0x7826,
-	0x8840, 0x7a02, 0x7000, 0x8000, 0x7002, 0x6018, 0xa802, 0xa08a,
-	0x0029, 0x1138, 0x6018, 0xa080, 0x0001, 0x2004, 0x601a, 0x2001,
-	0x000d, 0x6032, 0xa085, 0x0001, 0x0005, 0x00f6, 0x00e6, 0x00c6,
-	0x2071, 0x953b, 0x2079, 0x0020, 0x7904, 0xd1fc, 0x01f0, 0x7803,
-	0x0002, 0x2d60, 0xa026, 0x7000, 0x0002, 0x2f95, 0x2f80, 0x2f8c,
-	0x8001, 0x7002, 0xd19c, 0x1188, 0x2011, 0x0001, 0x080c, 0x2f45,
-	0x0160, 0x080c, 0x2f45, 0x0048, 0x8001, 0x7002, 0x7804, 0xd0fc,
-	0x1d30, 0x2011, 0x0001, 0x080c, 0x2f45, 0x00ce, 0x00ee, 0x00fe,
-	0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2061, 0x0200, 0x601b, 0x0004,
-	0x2061, 0x0100, 0x60cf, 0x0400, 0x6004, 0xc0ac, 0xa085, 0x0200,
-	0x6006, 0x2001, 0x0074, 0x2004, 0xa005, 0x01f8, 0x2038, 0x2001,
-	0x0076, 0x2024, 0x2001, 0x0077, 0x201c, 0x080c, 0x3089, 0x6833,
-	0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, 0x0007, 0x0220, 0x2138,
-	0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, 0x6818, 0xa080, 0x000d,
-	0x04a1, 0x1d90, 0x2d00, 0x681a, 0x0088, 0x080c, 0x3089, 0x6833,
-	0x000d, 0x2070, 0x6827, 0x0001, 0x2d00, 0x681a, 0x2001, 0x0076,
-	0x2004, 0x2072, 0x2001, 0x0077, 0x2004, 0x7006, 0x2061, 0x0020,
-	0x2079, 0x0100, 0x6013, 0x0400, 0x20e1, 0x9040, 0x2001, 0x0072,
-	0x2004, 0xa084, 0xfff8, 0x700a, 0x601a, 0x0006, 0x2001, 0x0073,
-	0x2004, 0x700e, 0x601e, 0x78c6, 0x000e, 0x78ca, 0xa006, 0x603a,
-	0x603e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0010,
-	0x20a0, 0x2099, 0x0014, 0x7003, 0x0026, 0x7432, 0x7336, 0xa006,
-	0x703a, 0x703e, 0x810b, 0x810b, 0x21a8, 0x810b, 0x7122, 0x7003,
-	0x0041, 0x7004, 0xd0fc, 0x0de8, 0x7003, 0x0002, 0x7003, 0x0040,
-	0x53a5, 0x7430, 0x7334, 0x87ff, 0x0180, 0x00c6, 0x00d6, 0x2d60,
-	0x00c6, 0x080c, 0x3641, 0x00ce, 0x6018, 0x2070, 0x2d00, 0x7006,
-	0x601a, 0x00de, 0x00ce, 0xa085, 0x0001, 0x00ee, 0x0005, 0x00e6,
-	0x2001, 0x0075, 0x2004, 0xa005, 0x0508, 0x2038, 0x2001, 0x0078,
-	0x2024, 0x2001, 0x0079, 0x201c, 0x080c, 0x3089, 0x2d60, 0x6833,
-	0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, 0x0007, 0x0220, 0x2138,
-	0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, 0x6818, 0xa080, 0x000d,
-	0x080c, 0x2ffd, 0x1d88, 0x2d00, 0x681a, 0x00d8, 0x0491, 0x2d60,
-	0x6033, 0x000d, 0x2070, 0x6027, 0x0001, 0x2c00, 0x601a, 0x2001,
-	0x0078, 0x2004, 0x2072, 0x2001, 0x0079, 0x2004, 0x7006, 0x2001,
-	0x0072, 0x2004, 0xa084, 0xfff8, 0x700a, 0x2001, 0x0073, 0x2004,
-	0x700e, 0x2001, 0x0030, 0x2003, 0x0004, 0x7824, 0xd0ac, 0x1178,
-	0x2001, 0x0101, 0x200c, 0xc1ed, 0x2102, 0x6027, 0x0000, 0x2001,
-	0x9519, 0x2003, 0x0003, 0x2001, 0x0030, 0x2003, 0x0009, 0x00ee,
-	0x0005, 0x080c, 0x147c, 0x0178, 0xa006, 0x6802, 0x7010, 0xa005,
-	0x1120, 0x2d00, 0x7012, 0x7016, 0x0020, 0x7014, 0x6802, 0x2d00,
-	0x7016, 0xad80, 0x000d, 0x0005, 0x0804, 0x28ff, 0x7d38, 0x7c3c,
-	0x0804, 0x29a3, 0x080c, 0x3641, 0x0904, 0x2924, 0x080c, 0x4dc5,
-	0x0110, 0x080c, 0x41c5, 0x2009, 0x001c, 0x7a2c, 0x7b28, 0x7c3c,
-	0x7d38, 0x080c, 0x3682, 0x701b, 0x30b6, 0x0005, 0xade8, 0x000d,
-	0x6800, 0xa005, 0x0904, 0x2927, 0x6804, 0xd0ac, 0x0118, 0xd0a4,
-	0x0904, 0x2927, 0xd094, 0x00c6, 0x2061, 0x0100, 0x6104, 0xa18d,
-	0x0020, 0x6106, 0x00ce, 0xd08c, 0x00c6, 0x2061, 0x0100, 0x6104,
-	0x0118, 0xa18d, 0x0010, 0x0010, 0xa18c, 0xffef, 0x6106, 0x00ce,
-	0x2009, 0x0100, 0x210c, 0xa18a, 0x0002, 0x0268, 0xd084, 0x0158,
-	0x6a28, 0xa28a, 0x007f, 0x1a04, 0x2927, 0xa288, 0x2719, 0x210d,
-	0xa18c, 0x00ff, 0x6156, 0xd0dc, 0x0130, 0x6828, 0xa08a, 0x007f,
-	0x1a04, 0x2927, 0x604e, 0x6808, 0xa08a, 0x0100, 0x0a04, 0x2927,
-	0xa08a, 0x0841, 0x1a04, 0x2927, 0xa084, 0x0007, 0x1904, 0x2927,
-	0x680c, 0xa005, 0x0904, 0x2927, 0x6810, 0xa005, 0x0904, 0x2927,
-	0x6848, 0x6940, 0xa10a, 0x1a04, 0x2927, 0x8001, 0x0904, 0x2927,
-	0x684c, 0x6944, 0xa10a, 0x1a04, 0x2927, 0x8001, 0x0904, 0x2927,
-	0x6804, 0xd0fc, 0x01f8, 0x080c, 0x3641, 0x0904, 0x2924, 0x2009,
-	0x0014, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0xa290, 0x0038, 0xa399,
-	0x0000, 0x080c, 0x3682, 0x701b, 0x312e, 0x0005, 0xade8, 0x000d,
-	0x20a9, 0x0014, 0x2d98, 0x2069, 0x926d, 0x2da0, 0x53a3, 0x7010,
-	0xa0e8, 0x000d, 0x20a9, 0x001c, 0x2d98, 0x2069, 0x9251, 0x2da0,
-	0x53a3, 0x6814, 0xa08c, 0x00ff, 0x613e, 0x8007, 0xa084, 0x00ff,
-	0x6042, 0x080c, 0x4e5d, 0x080c, 0x4780, 0x080c, 0x47d8, 0x6000,
-	0xa086, 0x0000, 0x1904, 0x31e5, 0x6808, 0x602a, 0x080c, 0x20ce,
-	0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f,
-	0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0148, 0x6830,
-	0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, 0x0010,
-	0xa084, 0xf0ff, 0x6006, 0x610a, 0x620e, 0x6312, 0x080c, 0x57bc,
-	0x6904, 0xd1fc, 0x0520, 0x00c6, 0x2009, 0x0000, 0x20a9, 0x0001,
-	0x6b70, 0xd384, 0x01c8, 0x0020, 0x839d, 0x12b0, 0x3508, 0x8109,
-	0x080c, 0x532a, 0x6878, 0x6016, 0x6874, 0x2008, 0xa084, 0xff00,
-	0x8007, 0x600a, 0xa184, 0x00ff, 0x6006, 0x8108, 0x1118, 0x6003,
-	0x0003, 0x0010, 0x6003, 0x0001, 0x1f04, 0x3184, 0x00ce, 0x2069,
-	0x9251, 0x2001, 0x94d7, 0x6a80, 0xa294, 0x0030, 0xa28e, 0x0000,
-	0x0178, 0xa28e, 0x0010, 0x0118, 0xa28e, 0x0020, 0x0148, 0x2003,
-	0xaaaa, 0x2001, 0x0204, 0x2004, 0x2009, 0x94c8, 0x200a, 0x0008,
-	0x2102, 0x00c6, 0x2061, 0x0100, 0x602f, 0x0040, 0x602f, 0x0000,
-	0x00ce, 0x080c, 0x4dc5, 0x0128, 0x080c, 0x3912, 0x0110, 0x080c,
-	0x2455, 0x60c0, 0xa005, 0x01a8, 0x6003, 0x0001, 0x2091, 0x301d,
-	0x080c, 0x4dc5, 0x1158, 0x2011, 0x4ce2, 0x080c, 0x5731, 0x2001,
-	0x94d8, 0x2003, 0x0000, 0x080c, 0x4d10, 0x0038, 0x080c, 0x4105,
-	0x0020, 0x6003, 0x0004, 0x2091, 0x301d, 0x0804, 0x28ff, 0x6000,
-	0xa086, 0x0000, 0x0904, 0x2924, 0x2069, 0x9251, 0x7830, 0x6842,
-	0x7834, 0x6846, 0x2d00, 0x2009, 0x001c, 0x7a2c, 0x7b28, 0x7c3c,
-	0x7d38, 0x0804, 0x3685, 0x81ff, 0x1904, 0x2924, 0x080c, 0x4dc5,
-	0x1158, 0x2001, 0x94d8, 0x2003, 0x0001, 0x2001, 0x9200, 0x2003,
-	0x0001, 0x080c, 0x4d10, 0x0038, 0xa006, 0x080c, 0x2455, 0x080c,
-	0x41c5, 0x080c, 0x4105, 0x0804, 0x28ff, 0x81ff, 0x1904, 0x2924,
-	0x080c, 0x4dc5, 0x1110, 0x0804, 0x2924, 0x6184, 0x81ff, 0x0198,
-	0x703f, 0x0000, 0x2001, 0x98c0, 0x2009, 0x0040, 0x7a2c, 0x7b28,
-	0x7c3c, 0x7d38, 0x0126, 0x2091, 0x8000, 0x080c, 0x3685, 0x701b,
-	0x28fd, 0x012e, 0x0005, 0x703f, 0x0001, 0x00d6, 0x2069, 0x98c0,
-	0x20a9, 0x0040, 0x20a1, 0x98c0, 0x2019, 0xffff, 0x43a4, 0x654c,
-	0xa588, 0x2719, 0x210d, 0xa18c, 0x00ff, 0x216a, 0xa00e, 0x2011,
-	0x0002, 0x2100, 0xa506, 0x01a8, 0x080c, 0x4434, 0x1190, 0x6014,
-	0x821c, 0x0238, 0xa398, 0x98c0, 0xa085, 0xff00, 0x8007, 0x201a,
-	0x0038, 0xa398, 0x98c0, 0x2324, 0xa4a4, 0xff00, 0xa405, 0x201a,
-	0x8210, 0x8108, 0xa182, 0x0080, 0x1208, 0x0c18, 0x8201, 0x8007,
-	0x2d0c, 0xa105, 0x206a, 0x00de, 0x20a9, 0x0040, 0x20a1, 0x98c0,
-	0x2099, 0x98c0, 0x080c, 0x4166, 0x0804, 0x3222, 0x080c, 0x3666,
-	0x0904, 0x2927, 0x00c6, 0x080c, 0x3641, 0x00ce, 0x0904, 0x2924,
-	0x080c, 0x4dc5, 0x0500, 0x2001, 0x9252, 0x2004, 0xd0b4, 0x01d8,
-	0x6000, 0xd08c, 0x11c0, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006,
-	0x1190, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, 0x8476,
-	0x0904, 0x2924, 0x7007, 0x0003, 0x701b, 0x329f, 0x0005, 0x080c,
-	0x3666, 0x0904, 0x2927, 0x20a9, 0x002d, 0x2c98, 0xade8, 0x0002,
-	0x2da0, 0x53a3, 0x20a9, 0x0004, 0xac80, 0x0006, 0x2098, 0xad80,
-	0x0006, 0x20a0, 0x080c, 0x4166, 0x20a9, 0x0004, 0xac80, 0x000a,
-	0x2098, 0xad80, 0x000a, 0x20a0, 0x080c, 0x4166, 0x2d00, 0x2009,
-	0x002f, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3685, 0x81ff,
-	0x1904, 0x2924, 0x080c, 0x3656, 0x0904, 0x2927, 0x080c, 0x45e9,
-	0x0804, 0x28ff, 0x81ff, 0x1904, 0x2924, 0x7828, 0xa08a, 0x1000,
-	0x1a04, 0x2927, 0x080c, 0x3666, 0x0904, 0x2927, 0x080c, 0x4644,
-	0x0904, 0x2924, 0x2019, 0x0004, 0x080c, 0x45fb, 0x7924, 0x810f,
-	0x7a28, 0x0011, 0x0804, 0x28ff, 0xa186, 0x00ff, 0x0110, 0x0071,
-	0x0060, 0x2029, 0x007e, 0x2061, 0x9200, 0x644c, 0x2400, 0xa506,
-	0x0110, 0x2508, 0x0019, 0x8529, 0x1ec8, 0x0005, 0x080c, 0x4434,
-	0x1138, 0x2200, 0x8003, 0x800b, 0x810b, 0xa108, 0x080c, 0x573d,
-	0x0005, 0x81ff, 0x1904, 0x2924, 0x080c, 0x3656, 0x0904, 0x2927,
-	0x080c, 0x44d4, 0x0904, 0x2924, 0x080c, 0x45f2, 0x0804, 0x28ff,
-	0x81ff, 0x1904, 0x2924, 0x080c, 0x3656, 0x0904, 0x2927, 0x080c,
-	0x44d4, 0x0904, 0x2924, 0x080c, 0x45e0, 0x0804, 0x28ff, 0x6100,
-	0x2001, 0x94d8, 0x2014, 0xa282, 0x0003, 0x1210, 0x0804, 0x28ff,
-	0x2011, 0x0000, 0x0804, 0x28ff, 0x0804, 0x28ff, 0x080c, 0x3666,
-	0x0904, 0x2927, 0x6004, 0xa086, 0x0707, 0x0904, 0x2927, 0x2001,
-	0x9200, 0x2004, 0xa086, 0x0003, 0x1904, 0x2924, 0x00d6, 0xace8,
-	0x000a, 0x7924, 0xd184, 0x0110, 0xace8, 0x0006, 0x680c, 0x8007,
-	0x783e, 0x6808, 0x8007, 0x783a, 0x6b04, 0x831f, 0x6a00, 0x8217,
-	0x00de, 0x6100, 0xa18c, 0x0200, 0x0804, 0x28ff, 0x7824, 0xa09c,
-	0x00ff, 0xa39a, 0x0003, 0x1a04, 0x2924, 0x624c, 0xa294, 0x00ff,
-	0xa084, 0xff00, 0x8007, 0xa206, 0x1150, 0x2001, 0x9240, 0x2009,
-	0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3685, 0x81ff,
-	0x1904, 0x2924, 0x080c, 0x3666, 0x0904, 0x2927, 0x6004, 0xa084,
-	0x00ff, 0xa086, 0x0006, 0x1904, 0x2924, 0x00c6, 0x080c, 0x3641,
-	0x00ce, 0x0904, 0x2924, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a,
-	0x080c, 0x8428, 0x0904, 0x2924, 0x7007, 0x0003, 0x701b, 0x3399,
-	0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x2924, 0xad80, 0x000e,
-	0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3685,
-	0x7824, 0xa084, 0x00ff, 0xa086, 0x00ff, 0x0118, 0x81ff, 0x1904,
-	0x2924, 0x080c, 0x4dc5, 0x0128, 0xa006, 0x080c, 0x2455, 0x080c,
-	0x41c5, 0x7828, 0xa08a, 0x1000, 0x1a04, 0x2927, 0x7924, 0xa18c,
-	0xff00, 0x810f, 0xa186, 0x00ff, 0x0138, 0xa182, 0x007f, 0x1a04,
-	0x2927, 0x2100, 0x080c, 0x241f, 0x0026, 0x00c6, 0x0126, 0x2091,
-	0x8000, 0x2061, 0x94f8, 0x601b, 0x0000, 0x601f, 0x0000, 0x080c,
-	0x4dc5, 0x1158, 0x2001, 0x94d8, 0x2003, 0x0001, 0x2001, 0x9200,
-	0x2003, 0x0001, 0x080c, 0x4d10, 0x00a0, 0x2061, 0x0100, 0x2001,
-	0x9214, 0x2004, 0xa084, 0x00ff, 0x810f, 0xa105, 0x604a, 0x6043,
-	0x0090, 0x6043, 0x0010, 0x2009, 0x001e, 0x2011, 0x412a, 0x080c,
-	0x57b3, 0x7924, 0xa18c, 0xff00, 0x810f, 0x080c, 0x4dc5, 0x1110,
-	0x2009, 0x00ff, 0x7a28, 0x080c, 0x32ec, 0x012e, 0x00ce, 0x002e,
-	0x0804, 0x28ff, 0x7924, 0xa18c, 0xff00, 0x810f, 0x00c6, 0x080c,
-	0x4400, 0x2c08, 0x00ce, 0x1904, 0x2927, 0x0804, 0x28ff, 0x81ff,
-	0x1904, 0x2924, 0x60c8, 0xd0ac, 0x1118, 0xd09c, 0x0904, 0x2924,
-	0x080c, 0x3641, 0x0904, 0x2924, 0x7924, 0x7a2c, 0x7b28, 0x7c3c,
-	0x7d38, 0x080c, 0x3682, 0x701b, 0x342e, 0x0005, 0x2009, 0x0080,
-	0x080c, 0x4434, 0x1130, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006,
-	0x0120, 0x2021, 0x400a, 0x0804, 0x2901, 0x00d6, 0xade8, 0x000d,
-	0x6900, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x6e18, 0x6820, 0xa0be,
-	0x0100, 0x0904, 0x34a1, 0xa0be, 0x0112, 0x0904, 0x34a1, 0xa0be,
-	0x0113, 0x0904, 0x34a1, 0xa0be, 0x0114, 0x0904, 0x34a1, 0xa0be,
-	0x0117, 0x0904, 0x34a1, 0xa0be, 0x011a, 0x0904, 0x34a1, 0xa0be,
-	0x0121, 0x05b0, 0xa0be, 0x0131, 0x0598, 0xa0be, 0x0171, 0x05c8,
-	0xa0be, 0x0173, 0x05b0, 0xa0be, 0x01a1, 0x1120, 0x6830, 0x8007,
-	0x6832, 0x04a0, 0xa0be, 0x0212, 0x0540, 0xa0be, 0x0213, 0x0528,
-	0xa0be, 0x0214, 0x01b0, 0xa0be, 0x0217, 0x0168, 0xa0be, 0x021a,
-	0x1120, 0x6838, 0x8007, 0x683a, 0x00e0, 0xa0be, 0x0300, 0x01c8,
-	0x00de, 0x0804, 0x2927, 0xad80, 0x0010, 0x20a9, 0x0007, 0x080c,
-	0x34dd, 0xad80, 0x000e, 0x20a9, 0x0001, 0x080c, 0x34dd, 0x0048,
-	0xad80, 0x000c, 0x080c, 0x34eb, 0x0048, 0xad80, 0x000e, 0x080c,
-	0x34eb, 0xad80, 0x000c, 0x20a9, 0x0001, 0x04b9, 0x00c6, 0x080c,
-	0x3641, 0x0540, 0x6838, 0xc0fd, 0x683a, 0x6837, 0x0119, 0x6853,
-	0x0000, 0x684f, 0x0020, 0x685b, 0x0001, 0x810b, 0x697e, 0x6883,
-	0x0000, 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, 0x6996, 0x689b, 0x0000,
-	0x00ce, 0x00de, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823,
-	0x0000, 0x080c, 0x8442, 0x0904, 0x2924, 0x7007, 0x0003, 0x701b,
-	0x34d6, 0x0005, 0x00ce, 0x00de, 0x0804, 0x2924, 0x6820, 0xa086,
-	0x8001, 0x0904, 0x2924, 0x0804, 0x28ff, 0x0016, 0x2008, 0x2044,
-	0x8000, 0x204c, 0x8000, 0x290a, 0x8108, 0x280a, 0x8108, 0x1f04,
-	0x34df, 0x001e, 0x0005, 0x0016, 0x00a6, 0x00b6, 0x2008, 0x2044,
-	0x8000, 0x204c, 0x8000, 0x2054, 0x8000, 0x205c, 0x2b0a, 0x8108,
-	0x2a0a, 0x8108, 0x290a, 0x8108, 0x280a, 0x00be, 0x00ae, 0x001e,
-	0x0005, 0x81ff, 0x1904, 0x2924, 0x7924, 0x2140, 0xa18c, 0xff00,
-	0x810f, 0x60c8, 0xd0ac, 0x1120, 0xa182, 0x0080, 0x0a04, 0x2927,
-	0xa182, 0x00ff, 0x1a04, 0x2927, 0x7a2c, 0x7b28, 0x606c, 0xa306,
-	0x1140, 0x6070, 0xa24e, 0x0904, 0x2927, 0xa9cc, 0xff00, 0x0904,
-	0x2927, 0x00c6, 0x080c, 0x359b, 0x2c68, 0x00ce, 0x01c0, 0xa0c6,
-	0x4000, 0x1108, 0x0088, 0xa0c6, 0x4007, 0x1110, 0x2408, 0x0060,
-	0xa0c6, 0x4008, 0x1118, 0x2708, 0x2610, 0x0030, 0xa0c6, 0x4009,
-	0x1108, 0x0010, 0x2001, 0x4006, 0x2020, 0x0804, 0x2901, 0x2d00,
-	0x7022, 0x0016, 0x00b6, 0x00c6, 0x00e6, 0x2c70, 0x080c, 0x749c,
-	0x05b8, 0x2d00, 0x601a, 0x2e58, 0x00ee, 0x00e6, 0x00c6, 0x080c,
-	0x3641, 0x00ce, 0x2b70, 0x1140, 0x080c, 0x74f2, 0x00ee, 0x00ce,
-	0x00be, 0x001e, 0x0804, 0x2924, 0x6837, 0x0000, 0x683b, 0x0000,
-	0x2d00, 0x6012, 0x6833, 0x0000, 0x6838, 0xc0fd, 0xd88c, 0x0108,
-	0xc0f5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x266c, 0x012e,
-	0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x43d1, 0x2001, 0x0002,
-	0x080c, 0x43e3, 0x2009, 0x0002, 0x080c, 0x7518, 0xa085, 0x0001,
-	0x00ee, 0x00ce, 0x00be, 0x001e, 0x0904, 0x2924, 0x7007, 0x0003,
-	0x701b, 0x358b, 0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x2924,
-	0x7020, 0x2060, 0x2009, 0x0000, 0x080c, 0x46a5, 0x1110, 0x2009,
-	0x0001, 0x0804, 0x28ff, 0x00e6, 0x00d6, 0x2029, 0x0000, 0x2001,
-	0x9232, 0x2004, 0xd0ac, 0x0138, 0x2021, 0x0000, 0x20a9, 0x00ff,
-	0x2071, 0x936e, 0x0030, 0x2021, 0x0080, 0x20a9, 0x007f, 0x2071,
-	0x93ee, 0x2e04, 0xa005, 0x1130, 0x2100, 0xa406, 0x1548, 0x2428,
+	0xe000, 0x8319, 0x1de0, 0x2001, 0x0140, 0x2003, 0x0100, 0x7827,
+	0x0020, 0x7843, 0x0000, 0x2003, 0x0000, 0x7827, 0x0048, 0x00fe,
+	0x0005, 0x7824, 0xd0ac, 0x11c8, 0x00f6, 0x00e6, 0x2071, 0x8dde,
+	0x2079, 0x0030, 0x2001, 0x0201, 0x2004, 0xa005, 0x0160, 0x7000,
+	0xa086, 0x0000, 0x1140, 0x0051, 0xd0bc, 0x0108, 0x8738, 0x7003,
+	0x0003, 0x7803, 0x0019, 0x00ee, 0x00fe, 0x0005, 0x780c, 0xa08c,
+	0x0070, 0x0178, 0x2009, 0x007a, 0x260a, 0x2009, 0x007b, 0x250a,
+	0xd0b4, 0x0108, 0x8a50, 0xd0ac, 0x0108, 0x8948, 0xd0a4, 0x0108,
+	0x8b58, 0x0005, 0x00f6, 0x2079, 0x0200, 0x781c, 0xd084, 0x0140,
+	0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, 0x0ca8,
+	0x00fe, 0x0005, 0x00e6, 0x2071, 0x0100, 0x2009, 0x8b14, 0x210c,
+	0x716e, 0x7063, 0x0100, 0x7166, 0x719e, 0x706b, 0x0000, 0x7073,
+	0x0809, 0x7077, 0x0008, 0x7078, 0xa080, 0x0100, 0x707a, 0x7080,
+	0x8000, 0x7082, 0x7087, 0xaaaa, 0xa006, 0x708a, 0x708e, 0x707e,
+	0x70d6, 0x70ab, 0x0036, 0x70af, 0x95d5, 0x7027, 0x0080, 0x7014,
+	0xa084, 0x0184, 0xa085, 0x0032, 0x7016, 0x080c, 0x2ec8, 0x080c,
+	0x2d41, 0x1110, 0x8421, 0x0028, 0x7024, 0xd0bc, 0x0db0, 0x7027,
+	0x0080, 0x00f6, 0x00e6, 0x2071, 0x8dde, 0x2079, 0x0030, 0x2011,
+	0x0011, 0x080c, 0x2ea0, 0x2011, 0x0001, 0x080c, 0x2ea0, 0x00ee,
+	0x00fe, 0x7017, 0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x2071,
+	0x8dde, 0x2079, 0x0030, 0x7904, 0xd1fc, 0x0904, 0x2e9d, 0x7803,
+	0x0002, 0xa026, 0xd19c, 0x1904, 0x2e99, 0x7000, 0x0002, 0x2e9d,
+	0x2e5b, 0x2e7f, 0x2e99, 0xd1bc, 0x1150, 0xd1dc, 0x1150, 0x8001,
+	0x7002, 0x2011, 0x0001, 0x04e1, 0x05c0, 0x04d1, 0x04b0, 0x780f,
+	0x0000, 0x7820, 0x7924, 0x7803, 0x0004, 0x7822, 0x7926, 0x2001,
+	0x0201, 0x200c, 0x81ff, 0x0de8, 0x080c, 0x2dd6, 0x2009, 0x0001,
+	0x7808, 0xd0ec, 0x0110, 0x2009, 0x0011, 0x7902, 0x00f0, 0x8001,
+	0x7002, 0xa184, 0x0880, 0x1138, 0x7804, 0xd0fc, 0x1940, 0x2011,
+	0x0001, 0x00b1, 0x0090, 0x6030, 0xa092, 0x0004, 0xa086, 0x0009,
+	0x1120, 0x6000, 0x601a, 0x2011, 0x0025, 0x6232, 0xd1dc, 0x1988,
+	0x0870, 0x7803, 0x0004, 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005,
+	0x6024, 0xa005, 0x0520, 0x8001, 0x6026, 0x6018, 0x6130, 0xa140,
+	0x2804, 0x7832, 0x8840, 0x2804, 0x7836, 0x8840, 0x2804, 0x7822,
+	0x8840, 0x2804, 0x7826, 0x8840, 0x7a02, 0x7000, 0x8000, 0x7002,
+	0x6018, 0xa802, 0xa08a, 0x0029, 0x1138, 0x6018, 0xa080, 0x0001,
+	0x2004, 0x601a, 0x2001, 0x000d, 0x6032, 0xa085, 0x0001, 0x0005,
+	0x00f6, 0x00e6, 0x00c6, 0x2071, 0x8dff, 0x2079, 0x0020, 0x7904,
+	0xd1fc, 0x01f0, 0x7803, 0x0002, 0x2d60, 0xa026, 0x7000, 0x0002,
+	0x2ef0, 0x2edb, 0x2ee7, 0x8001, 0x7002, 0xd19c, 0x1188, 0x2011,
+	0x0001, 0x080c, 0x2ea0, 0x0160, 0x080c, 0x2ea0, 0x0048, 0x8001,
+	0x7002, 0x7804, 0xd0fc, 0x1d30, 0x2011, 0x0001, 0x080c, 0x2ea0,
+	0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2061,
+	0x0200, 0x601b, 0x0004, 0x2061, 0x0100, 0x60cf, 0x0400, 0x6004,
+	0xc0ac, 0xa085, 0x0200, 0x6006, 0x2001, 0x0074, 0x2004, 0xa005,
+	0x01f8, 0x2038, 0x2001, 0x0076, 0x2024, 0x2001, 0x0077, 0x201c,
+	0x080c, 0x2fe4, 0x6833, 0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a,
+	0x0007, 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0xa03e,
+	0x6818, 0xa080, 0x000d, 0x04a1, 0x1d90, 0x2d00, 0x681a, 0x0088,
+	0x080c, 0x2fe4, 0x6833, 0x000d, 0x2070, 0x6827, 0x0001, 0x2d00,
+	0x681a, 0x2001, 0x0076, 0x2004, 0x2072, 0x2001, 0x0077, 0x2004,
+	0x7006, 0x2061, 0x0020, 0x2079, 0x0100, 0x6013, 0x0400, 0x20e1,
+	0x9040, 0x2001, 0x0072, 0x2004, 0xa084, 0xfff8, 0x700a, 0x601a,
+	0x0006, 0x2001, 0x0073, 0x2004, 0x700e, 0x601e, 0x78c6, 0x000e,
+	0x78ca, 0xa006, 0x603a, 0x603e, 0x00ce, 0x00ee, 0x00fe, 0x0005,
+	0x00e6, 0x2071, 0x0010, 0x20a0, 0x2099, 0x0014, 0x7003, 0x0026,
+	0x7432, 0x7336, 0xa006, 0x703a, 0x703e, 0x810b, 0x810b, 0x21a8,
+	0x810b, 0x7122, 0x7003, 0x0041, 0x7004, 0xd0fc, 0x0de8, 0x7003,
+	0x0002, 0x7003, 0x0040, 0x53a5, 0x7430, 0x7334, 0x87ff, 0x0180,
+	0x00c6, 0x00d6, 0x2d60, 0x00c6, 0x080c, 0x35c0, 0x00ce, 0x6018,
+	0x2070, 0x2d00, 0x7006, 0x601a, 0x00de, 0x00ce, 0xa085, 0x0001,
+	0x00ee, 0x0005, 0x00e6, 0x2001, 0x0075, 0x2004, 0xa005, 0x0508,
+	0x2038, 0x2001, 0x0078, 0x2024, 0x2001, 0x0079, 0x201c, 0x080c,
+	0x2fe4, 0x2d60, 0x6833, 0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a,
+	0x0007, 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0xa03e,
+	0x6818, 0xa080, 0x000d, 0x080c, 0x2f58, 0x1d88, 0x2d00, 0x681a,
+	0x00d8, 0x0491, 0x2d60, 0x6033, 0x000d, 0x2070, 0x6027, 0x0001,
+	0x2c00, 0x601a, 0x2001, 0x0078, 0x2004, 0x2072, 0x2001, 0x0079,
+	0x2004, 0x7006, 0x2001, 0x0072, 0x2004, 0xa084, 0xfff8, 0x700a,
+	0x2001, 0x0073, 0x2004, 0x700e, 0x2001, 0x0030, 0x2003, 0x0004,
+	0x7824, 0xd0ac, 0x1178, 0x2001, 0x0101, 0x200c, 0xc1ed, 0x2102,
+	0x6027, 0x0000, 0x2001, 0x8dde, 0x2003, 0x0003, 0x2001, 0x0030,
+	0x2003, 0x0009, 0x00ee, 0x0005, 0x080c, 0x1488, 0x0178, 0xa006,
+	0x6802, 0x7010, 0xa005, 0x1120, 0x2d00, 0x7012, 0x7016, 0x0020,
+	0x7014, 0x6802, 0x2d00, 0x7016, 0xad80, 0x000d, 0x0005, 0x0804,
+	0x2823, 0x7d38, 0x7c3c, 0x0804, 0x28c7, 0x080c, 0x35c0, 0x0904,
+	0x2848, 0x080c, 0x4c42, 0x0110, 0x080c, 0x40fd, 0x2009, 0x001c,
+	0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3601, 0x701b, 0x3011,
+	0x0005, 0xade8, 0x000d, 0x6800, 0xa005, 0x0904, 0x284b, 0x6804,
+	0xd0ac, 0x0118, 0xd0a4, 0x0904, 0x284b, 0xd094, 0x00c6, 0x2061,
+	0x0100, 0x6104, 0x0138, 0x6200, 0xa292, 0x0005, 0x0218, 0xa18c,
+	0xffdf, 0x0010, 0xa18d, 0x0020, 0x6106, 0x00ce, 0xd08c, 0x00c6,
+	0x2061, 0x0100, 0x6104, 0x0118, 0xa18d, 0x0010, 0x0010, 0xa18c,
+	0xffef, 0x6106, 0x00ce, 0x2009, 0x0100, 0x210c, 0xa18a, 0x0002,
+	0x0268, 0xd084, 0x0158, 0x6a28, 0xa28a, 0x007f, 0x1a04, 0x284b,
+	0xa288, 0x263d, 0x210d, 0xa18c, 0x00ff, 0x6156, 0xd0dc, 0x0130,
+	0x6828, 0xa08a, 0x007f, 0x1a04, 0x284b, 0x604e, 0x6808, 0xa08a,
+	0x0100, 0x0a04, 0x284b, 0xa08a, 0x0841, 0x1a04, 0x284b, 0xa084,
+	0x0007, 0x1904, 0x284b, 0x680c, 0xa005, 0x0904, 0x284b, 0x6810,
+	0xa005, 0x0904, 0x284b, 0x6848, 0x6940, 0xa10a, 0x1a04, 0x284b,
+	0x8001, 0x0904, 0x284b, 0x684c, 0x6944, 0xa10a, 0x1a04, 0x284b,
+	0x8001, 0x0904, 0x284b, 0x6804, 0xd0fc, 0x01f8, 0x080c, 0x35c0,
+	0x0904, 0x2848, 0x2009, 0x0014, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
+	0xa290, 0x0038, 0xa399, 0x0000, 0x080c, 0x3601, 0x701b, 0x3091,
+	0x0005, 0xade8, 0x000d, 0x20a9, 0x0014, 0x2d98, 0x2069, 0x8b6d,
+	0x2da0, 0x53a3, 0x7010, 0xa0e8, 0x000d, 0x20a9, 0x001c, 0x2d98,
+	0x2069, 0x8b51, 0x2da0, 0x53a3, 0x6814, 0xa08c, 0x00ff, 0x613e,
+	0x8007, 0xa084, 0x00ff, 0x6042, 0x080c, 0x4d79, 0x080c, 0x4618,
+	0x080c, 0x4670, 0x6000, 0xa086, 0x0000, 0x1904, 0x3148, 0x6808,
+	0x602a, 0x080c, 0x1fbd, 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007,
+	0x810f, 0x8217, 0x831f, 0x6016, 0x611a, 0x621e, 0x6322, 0x6c04,
+	0xd4f4, 0x0148, 0x6830, 0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f,
+	0x8217, 0x831f, 0x0010, 0xa084, 0xf0ff, 0x6006, 0x610a, 0x620e,
+	0x6312, 0x080c, 0x5695, 0x6904, 0xd1fc, 0x0520, 0x00c6, 0x2009,
+	0x0000, 0x20a9, 0x0001, 0x6b70, 0xd384, 0x01c8, 0x0020, 0x839d,
+	0x12b0, 0x3508, 0x8109, 0x080c, 0x520d, 0x6878, 0x6016, 0x6874,
+	0x2008, 0xa084, 0xff00, 0x8007, 0x600a, 0xa184, 0x00ff, 0x6006,
+	0x8108, 0x1118, 0x6003, 0x0003, 0x0010, 0x6003, 0x0001, 0x1f04,
+	0x30e7, 0x00ce, 0x2069, 0x8b51, 0x2001, 0x8d9c, 0x6a80, 0xa294,
+	0x0030, 0xa28e, 0x0000, 0x0178, 0xa28e, 0x0010, 0x0118, 0xa28e,
+	0x0020, 0x0148, 0x2003, 0xaaaa, 0x2001, 0x0204, 0x2004, 0x2009,
+	0x8d8d, 0x200a, 0x0008, 0x2102, 0x00c6, 0x2061, 0x0100, 0x602f,
+	0x0040, 0x602f, 0x0000, 0x00ce, 0x080c, 0x4c42, 0x0128, 0x080c,
+	0x37e7, 0x0110, 0x080c, 0x2333, 0x60c0, 0xa005, 0x01a8, 0x6003,
+	0x0001, 0x2091, 0x301d, 0x080c, 0x4c42, 0x1158, 0x2011, 0x4b5d,
+	0x080c, 0x560d, 0x2001, 0x8d9d, 0x2003, 0x0000, 0x080c, 0x4b8b,
+	0x0038, 0x080c, 0x403d, 0x0020, 0x6003, 0x0004, 0x2091, 0x301d,
+	0x0804, 0x2823, 0x6000, 0xa086, 0x0000, 0x0904, 0x2848, 0x2069,
+	0x8b51, 0x7830, 0x6842, 0x7834, 0x6846, 0x2d00, 0x2009, 0x001c,
+	0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3604, 0x81ff, 0x1904,
+	0x2848, 0x080c, 0x4c42, 0x1158, 0x2001, 0x8d9d, 0x2003, 0x0001,
+	0x2001, 0x8b00, 0x2003, 0x0001, 0x080c, 0x4b8b, 0x0038, 0xa006,
+	0x080c, 0x2333, 0x080c, 0x40fd, 0x080c, 0x403d, 0x0804, 0x2823,
+	0x81ff, 0x1904, 0x2848, 0x080c, 0x4c42, 0x1110, 0x0804, 0x2848,
+	0x6184, 0x81ff, 0x0198, 0x703f, 0x0000, 0x2001, 0x91c0, 0x2009,
+	0x0040, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0126, 0x2091, 0x8000,
+	0x080c, 0x3604, 0x701b, 0x2821, 0x012e, 0x0005, 0x703f, 0x0001,
+	0x00d6, 0x2069, 0x91c0, 0x20a9, 0x0040, 0x20a1, 0x91c0, 0x2019,
+	0xffff, 0x43a4, 0x654c, 0xa588, 0x263d, 0x210d, 0xa18c, 0x00ff,
+	0x216a, 0xa00e, 0x2011, 0x0002, 0x2100, 0xa506, 0x01a8, 0x080c,
+	0x430a, 0x1190, 0x6014, 0x821c, 0x0238, 0xa398, 0x91c0, 0xa085,
+	0xff00, 0x8007, 0x201a, 0x0038, 0xa398, 0x91c0, 0x2324, 0xa4a4,
+	0xff00, 0xa405, 0x201a, 0x8210, 0x8108, 0xa182, 0x0080, 0x1208,
+	0x0c18, 0x8201, 0x8007, 0x2d0c, 0xa105, 0x206a, 0x00de, 0x20a9,
+	0x0040, 0x20a1, 0x91c0, 0x2099, 0x91c0, 0x080c, 0x409e, 0x0804,
+	0x3185, 0x080c, 0x35e5, 0x0904, 0x284b, 0x00c6, 0x080c, 0x35c0,
+	0x00ce, 0x0904, 0x2848, 0x080c, 0x4c42, 0x0500, 0x2001, 0x8b52,
+	0x2004, 0xd0b4, 0x01d8, 0x6000, 0xd08c, 0x11c0, 0x6004, 0xa084,
+	0x00ff, 0xa086, 0x0006, 0x1190, 0x6837, 0x0000, 0x6838, 0xc0fd,
+	0x683a, 0x080c, 0x7d17, 0x0904, 0x2848, 0x7007, 0x0003, 0x701b,
+	0x3202, 0x0005, 0x080c, 0x35e5, 0x0904, 0x284b, 0x20a9, 0x002b,
+	0x2c98, 0xade8, 0x0002, 0x2da0, 0x53a3, 0x20a9, 0x0004, 0xac80,
+	0x0006, 0x2098, 0xad80, 0x0006, 0x20a0, 0x080c, 0x409e, 0x20a9,
+	0x0004, 0xac80, 0x000a, 0x2098, 0xad80, 0x000a, 0x20a0, 0x080c,
+	0x409e, 0x2d00, 0x2009, 0x002b, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
+	0x0804, 0x3604, 0x81ff, 0x1904, 0x2848, 0x080c, 0x35d5, 0x0904,
+	0x284b, 0x080c, 0x44c2, 0x0804, 0x2823, 0x81ff, 0x1904, 0x2848,
+	0x7828, 0xa08a, 0x1000, 0x1a04, 0x284b, 0x080c, 0x35e5, 0x0904,
+	0x284b, 0x080c, 0x451d, 0x0904, 0x2848, 0x2019, 0x0004, 0x080c,
+	0x44d4, 0x7924, 0x810f, 0x7a28, 0x0011, 0x0804, 0x2823, 0xa186,
+	0x00ff, 0x0110, 0x0071, 0x0060, 0x2029, 0x007e, 0x2061, 0x8b00,
+	0x644c, 0x2400, 0xa506, 0x0110, 0x2508, 0x0019, 0x8529, 0x1ec8,
+	0x0005, 0x080c, 0x430a, 0x1138, 0x2200, 0x8003, 0x800b, 0x810b,
+	0xa108, 0x080c, 0x5619, 0x0005, 0x81ff, 0x1904, 0x2848, 0x080c,
+	0x35d5, 0x0904, 0x284b, 0x080c, 0x43ad, 0x0904, 0x2848, 0x080c,
+	0x44cb, 0x0804, 0x2823, 0x81ff, 0x1904, 0x2848, 0x080c, 0x35d5,
+	0x0904, 0x284b, 0x080c, 0x43ad, 0x0904, 0x2848, 0x080c, 0x44b9,
+	0x0804, 0x2823, 0x6100, 0x2001, 0x8d9d, 0x2014, 0xa282, 0x0003,
+	0x1210, 0x0804, 0x2823, 0x2011, 0x0000, 0x0804, 0x2823, 0x0804,
+	0x2823, 0x080c, 0x35e5, 0x0904, 0x284b, 0x6004, 0xa086, 0x0707,
+	0x0904, 0x284b, 0x2001, 0x8b00, 0x2004, 0xa086, 0x0003, 0x1904,
+	0x2848, 0x00d6, 0xace8, 0x000a, 0x7924, 0xd184, 0x0110, 0xace8,
+	0x0006, 0x680c, 0x8007, 0x783e, 0x6808, 0x8007, 0x783a, 0x6b04,
+	0x831f, 0x6a00, 0x8217, 0x00de, 0x6100, 0xa18c, 0x0200, 0x0804,
+	0x2823, 0x7824, 0xa09c, 0x00ff, 0xa39a, 0x0003, 0x1a04, 0x2848,
+	0x624c, 0xa294, 0x00ff, 0xa084, 0xff00, 0x8007, 0xa206, 0x1150,
+	0x2001, 0x8b40, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
+	0x0804, 0x3604, 0x81ff, 0x1904, 0x2848, 0x080c, 0x35e5, 0x0904,
+	0x284b, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1904, 0x2848,
+	0x00c6, 0x080c, 0x35c0, 0x00ce, 0x0904, 0x2848, 0x6837, 0x0000,
+	0x6838, 0xc0fd, 0x683a, 0x080c, 0x7cc9, 0x0904, 0x2848, 0x7007,
+	0x0003, 0x701b, 0x32fc, 0x0005, 0x6830, 0xa086, 0x0100, 0x0904,
+	0x2848, 0xad80, 0x000e, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c,
+	0x7d38, 0x0804, 0x3604, 0x7824, 0xa084, 0x00ff, 0xa086, 0x00ff,
+	0x0118, 0x81ff, 0x1904, 0x2848, 0x080c, 0x4c42, 0x0128, 0xa006,
+	0x080c, 0x2333, 0x080c, 0x40fd, 0x7828, 0xa08a, 0x1000, 0x1a04,
+	0x284b, 0x7924, 0xa18c, 0xff00, 0x810f, 0xa186, 0x00ff, 0x0138,
+	0xa182, 0x007f, 0x1a04, 0x284b, 0x2100, 0x080c, 0x22fd, 0x0026,
+	0x00c6, 0x0126, 0x2091, 0x8000, 0x2061, 0x8dbd, 0x601b, 0x0000,
+	0x601f, 0x0000, 0x080c, 0x4c42, 0x1158, 0x2001, 0x8d9d, 0x2003,
+	0x0001, 0x2001, 0x8b00, 0x2003, 0x0001, 0x080c, 0x4b8b, 0x00a0,
+	0x2061, 0x0100, 0x2001, 0x8b14, 0x2004, 0xa084, 0x00ff, 0x810f,
+	0xa105, 0x604a, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x001e,
+	0x2011, 0x4062, 0x080c, 0x568c, 0x7924, 0xa18c, 0xff00, 0x810f,
+	0x080c, 0x4c42, 0x1110, 0x2009, 0x00ff, 0x7a28, 0x080c, 0x324f,
+	0x012e, 0x00ce, 0x002e, 0x0804, 0x2823, 0x7924, 0xa18c, 0xff00,
+	0x810f, 0x00c6, 0x080c, 0x42d6, 0x2c08, 0x00ce, 0x1904, 0x284b,
+	0x0804, 0x2823, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2848,
+	0x60c8, 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804,
+	0x2848, 0x080c, 0x35c0, 0x1120, 0x2009, 0x0002, 0x0804, 0x2848,
+	0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3601, 0x701b,
+	0x339a, 0x0005, 0x2009, 0x0080, 0x080c, 0x430a, 0x1130, 0x6004,
+	0xa084, 0x00ff, 0xa086, 0x0006, 0x0120, 0x2021, 0x400a, 0x0804,
+	0x2825, 0x00d6, 0xade8, 0x000d, 0x6900, 0x6a08, 0x6b0c, 0x6c10,
+	0x6d14, 0x6e18, 0x6820, 0xa0be, 0x0100, 0x0904, 0x340d, 0xa0be,
+	0x0112, 0x0904, 0x340d, 0xa0be, 0x0113, 0x0904, 0x340d, 0xa0be,
+	0x0114, 0x0904, 0x340d, 0xa0be, 0x0117, 0x0904, 0x340d, 0xa0be,
+	0x011a, 0x0904, 0x340d, 0xa0be, 0x0121, 0x05b0, 0xa0be, 0x0131,
+	0x0598, 0xa0be, 0x0171, 0x05c8, 0xa0be, 0x0173, 0x05b0, 0xa0be,
+	0x01a1, 0x1120, 0x6830, 0x8007, 0x6832, 0x04a0, 0xa0be, 0x0212,
+	0x0540, 0xa0be, 0x0213, 0x0528, 0xa0be, 0x0214, 0x01b0, 0xa0be,
+	0x0217, 0x0168, 0xa0be, 0x021a, 0x1120, 0x6838, 0x8007, 0x683a,
+	0x00e0, 0xa0be, 0x0300, 0x01c8, 0x00de, 0x0804, 0x284b, 0xad80,
+	0x0010, 0x20a9, 0x0007, 0x080c, 0x3450, 0xad80, 0x000e, 0x20a9,
+	0x0001, 0x080c, 0x3450, 0x0048, 0xad80, 0x000c, 0x080c, 0x345e,
+	0x0048, 0xad80, 0x000e, 0x080c, 0x345e, 0xad80, 0x000c, 0x20a9,
+	0x0001, 0x04f1, 0x00c6, 0x080c, 0x35c0, 0x0558, 0x6838, 0xc0fd,
+	0x683a, 0x6837, 0x0119, 0x6853, 0x0000, 0x684f, 0x0020, 0x685b,
+	0x0001, 0x810b, 0x697e, 0x6883, 0x0000, 0x6a86, 0x6b8a, 0x6c8e,
+	0x6d92, 0x6996, 0x689b, 0x0000, 0x00ce, 0x00de, 0x6837, 0x0000,
+	0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000, 0x080c, 0x7ce3, 0x1120,
+	0x2009, 0x0003, 0x0804, 0x2848, 0x7007, 0x0003, 0x701b, 0x3447,
+	0x0005, 0x00ce, 0x00de, 0x2009, 0x0002, 0x0804, 0x2848, 0x6820,
+	0xa086, 0x8001, 0x1904, 0x2823, 0x2009, 0x0004, 0x0804, 0x2848,
+	0x0016, 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x290a, 0x8108,
+	0x280a, 0x8108, 0x1f04, 0x3452, 0x001e, 0x0005, 0x0016, 0x00a6,
+	0x00b6, 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x2054, 0x8000,
+	0x205c, 0x2b0a, 0x8108, 0x2a0a, 0x8108, 0x290a, 0x8108, 0x280a,
+	0x00be, 0x00ae, 0x001e, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001,
+	0x0804, 0x2848, 0x7924, 0x2140, 0xa18c, 0xff00, 0x810f, 0x60c8,
+	0xd0ac, 0x1120, 0xa182, 0x0080, 0x0a04, 0x284b, 0xa182, 0x00ff,
+	0x1a04, 0x284b, 0x7a2c, 0x7b28, 0x606c, 0xa306, 0x1140, 0x6070,
+	0xa24e, 0x0904, 0x284b, 0xa9cc, 0xff00, 0x0904, 0x284b, 0x00c6,
+	0x080c, 0x3513, 0x2c68, 0x00ce, 0x01c0, 0xa0c6, 0x4000, 0x1108,
+	0x0088, 0xa0c6, 0x4007, 0x1110, 0x2408, 0x0060, 0xa0c6, 0x4008,
+	0x1118, 0x2708, 0x2610, 0x0030, 0xa0c6, 0x4009, 0x1108, 0x0010,
+	0x2001, 0x4006, 0x2020, 0x0804, 0x2825, 0x2d00, 0x7022, 0x0016,
+	0x00b6, 0x00c6, 0x00e6, 0x2c70, 0x080c, 0x6cc2, 0x05a0, 0x2d00,
+	0x601a, 0x2e58, 0x00ee, 0x00e6, 0x00c6, 0x080c, 0x35c0, 0x00ce,
+	0x2b70, 0x1150, 0x080c, 0x6d18, 0x00ee, 0x00ce, 0x00be, 0x001e,
+	0x2009, 0x0002, 0x0804, 0x2848, 0x6837, 0x0000, 0x2d00, 0x6012,
+	0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x0126, 0x2091, 0x8000,
+	0x080c, 0x2563, 0x012e, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c,
+	0x42a7, 0x2001, 0x0002, 0x080c, 0x42b9, 0x2009, 0x0002, 0x080c,
+	0x6d3f, 0xa085, 0x0001, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x1120,
+	0x2009, 0x0003, 0x0804, 0x2848, 0x7007, 0x0003, 0x701b, 0x3501,
+	0x0005, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, 0x0904, 0x2848,
+	0x7020, 0x2060, 0x2009, 0x0000, 0x080c, 0x457e, 0x1110, 0x2009,
+	0x0001, 0x0804, 0x2823, 0x00e6, 0x00d6, 0x2029, 0x0000, 0x2001,
+	0x8b32, 0x2004, 0xd0ac, 0x0138, 0x2021, 0x0000, 0x20a9, 0x00ff,
+	0x2071, 0x8c34, 0x0030, 0x2021, 0x0080, 0x20a9, 0x007f, 0x2071,
+	0x8cb4, 0x2e04, 0xa005, 0x1130, 0x2100, 0xa406, 0x1548, 0x2428,
 	0xc5fd, 0x0430, 0x2068, 0x6f10, 0x2700, 0xa306, 0x11b0, 0x6e14,
 	0x2600, 0xa206, 0x1190, 0x2400, 0xa106, 0x1160, 0x2d60, 0xd884,
 	0x0540, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1510, 0x2001,
 	0x4000, 0x0400, 0x2001, 0x4007, 0x00e8, 0x2400, 0xa106, 0x1140,
 	0x6e14, 0x87ff, 0x1110, 0x86ff, 0x09d0, 0x2001, 0x4008, 0x0090,
-	0x8420, 0x8e70, 0x1f04, 0x35b1, 0x85ff, 0x1130, 0x2001, 0x4009,
-	0x0048, 0x2001, 0x0001, 0x0030, 0x080c, 0x4400, 0x1dd0, 0x6312,
+	0x8420, 0x8e70, 0x1f04, 0x3529, 0x85ff, 0x1130, 0x2001, 0x4009,
+	0x0048, 0x2001, 0x0001, 0x0030, 0x080c, 0x42d6, 0x1dd0, 0x6312,
 	0x6216, 0xa006, 0xa005, 0x00de, 0x00ee, 0x0005, 0x81ff, 0x1904,
-	0x2924, 0x080c, 0x3641, 0x0904, 0x2924, 0x6837, 0x0000, 0x6838,
-	0xc0fd, 0x683a, 0x7824, 0xa005, 0x0904, 0x2927, 0xa096, 0x00ff,
-	0x0120, 0xa092, 0x0004, 0x1a04, 0x2927, 0x2010, 0x2d18, 0x080c,
-	0x2631, 0x0904, 0x2924, 0x7007, 0x0003, 0x701b, 0x3618, 0x0005,
-	0x6830, 0xa086, 0x0100, 0x0904, 0x2924, 0x0804, 0x28ff, 0x7924,
+	0x2848, 0x080c, 0x35c0, 0x0904, 0x2848, 0x6837, 0x0000, 0x6838,
+	0xc0fd, 0x683a, 0x7824, 0xa005, 0x0904, 0x284b, 0xa096, 0x00ff,
+	0x0120, 0xa092, 0x0004, 0x1a04, 0x284b, 0x2010, 0x2d18, 0x080c,
+	0x2528, 0x0904, 0x2848, 0x7007, 0x0003, 0x701b, 0x3590, 0x0005,
+	0x6830, 0xa086, 0x0100, 0x0904, 0x2848, 0x0804, 0x2823, 0x7924,
 	0xa18c, 0xff00, 0x810f, 0x60c8, 0xd0ac, 0x1120, 0xa182, 0x0080,
-	0x0a04, 0x2927, 0xa182, 0x00ff, 0x1a04, 0x2927, 0x0126, 0x2091,
-	0x8000, 0x080c, 0x831a, 0x1150, 0xa190, 0x936e, 0x2204, 0xa065,
-	0x0128, 0x080c, 0x41e0, 0x012e, 0x0804, 0x28ff, 0x012e, 0x0804,
-	0x2924, 0x080c, 0x147c, 0x0188, 0xa006, 0x6802, 0x7010, 0xa005,
-	0x1120, 0x2d00, 0x7012, 0x7016, 0x0030, 0x7014, 0x6802, 0x2060,
-	0x2d00, 0x6006, 0x7016, 0xad80, 0x000d, 0x0005, 0x7924, 0x810f,
-	0xa18c, 0x00ff, 0x080c, 0x4434, 0x1130, 0x7e28, 0xa684, 0x3fff,
-	0xa082, 0x4000, 0x0208, 0xa066, 0x8cff, 0x0005, 0x7e24, 0x860f,
-	0xa18c, 0x00ff, 0x080c, 0x4434, 0x1128, 0xa6b4, 0x00ff, 0xa682,
-	0x4000, 0x0208, 0xa066, 0x8cff, 0x0005, 0x0016, 0x7110, 0x81ff,
-	0x0128, 0x2168, 0x6904, 0x080c, 0x1493, 0x0cc8, 0x7112, 0x7116,
-	0x001e, 0x0005, 0x2031, 0x0001, 0x0010, 0x2031, 0x0000, 0x2061,
-	0x92e6, 0x6606, 0x6112, 0x600e, 0x6226, 0x632a, 0x642e, 0x6532,
-	0x2c10, 0x080c, 0x14c7, 0x7007, 0x0002, 0x701b, 0x28ff, 0x0005,
-	0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0000, 0x2001, 0x92a4,
-	0x2004, 0xa005, 0x1168, 0x0e04, 0x36b0, 0x7818, 0xd084, 0x1140,
-	0x7a22, 0x7b26, 0x7c2a, 0x781b, 0x0001, 0x2091, 0x4080, 0x0408,
-	0x0016, 0x00c6, 0x00e6, 0x2071, 0x9296, 0x7138, 0xa182, 0x0010,
-	0x0218, 0x7030, 0x2060, 0x0078, 0x7030, 0xa0e0, 0x0004, 0xac82,
-	0x92e6, 0x0210, 0x2061, 0x92a6, 0x2c00, 0x7032, 0x81ff, 0x1108,
-	0x7036, 0x8108, 0x713a, 0x2262, 0x6306, 0x640a, 0x00ee, 0x00ce,
-	0x001e, 0x012e, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x9296, 0x7038,
-	0xa005, 0x0570, 0x0126, 0x2091, 0x8000, 0x0e04, 0x3707, 0x00f6,
-	0x2079, 0x0000, 0x7818, 0xd084, 0x1508, 0x00c6, 0x7034, 0x2060,
-	0x2c04, 0x7822, 0x6004, 0x7826, 0x6008, 0x782a, 0x781b, 0x0001,
-	0x2091, 0x4080, 0x7038, 0x8001, 0x703a, 0xa005, 0x1130, 0x7033,
-	0x92a6, 0x7037, 0x92a6, 0x00ce, 0x0048, 0xac80, 0x0004, 0xa0fa,
-	0x92e6, 0x0210, 0x2001, 0x92a6, 0x7036, 0x00ce, 0x00fe, 0x012e,
-	0x00ee, 0x0005, 0x0026, 0x2001, 0x9252, 0x2004, 0xd0c4, 0x0120,
-	0x2011, 0x8014, 0x080c, 0x3698, 0x002e, 0x0005, 0x81ff, 0x1904,
-	0x2924, 0x0126, 0x2091, 0x8000, 0x6030, 0xc08d, 0x6032, 0x080c,
-	0x4dc5, 0x1158, 0x2001, 0x94d8, 0x2003, 0x0001, 0x2001, 0x9200,
-	0x2003, 0x0001, 0x080c, 0x4d10, 0x0010, 0x080c, 0x4105, 0x012e,
-	0x0804, 0x28ff, 0x7824, 0x2008, 0xa18c, 0xfffd, 0x1128, 0x61d4,
-	0xa10d, 0x61d6, 0x0804, 0x28ff, 0x0804, 0x2927, 0x81ff, 0x1904,
-	0x2924, 0x6000, 0xa086, 0x0003, 0x1904, 0x2924, 0x2001, 0x9252,
-	0x2004, 0xd0a4, 0x1904, 0x2924, 0x080c, 0x3666, 0x0904, 0x2927,
-	0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1120, 0x7828, 0xa005,
-	0x0904, 0x28ff, 0x00c6, 0x080c, 0x3641, 0x00ce, 0x0904, 0x2924,
-	0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c,
-	0x84d7, 0x0904, 0x2924, 0x7007, 0x0003, 0x701b, 0x3770, 0x0005,
-	0x6830, 0xa086, 0x0100, 0x0904, 0x2924, 0x0804, 0x28ff, 0x2001,
-	0x9200, 0x2004, 0xa086, 0x0003, 0x1904, 0x2924, 0x7f24, 0x7a2c,
-	0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3641, 0x0904, 0x2924, 0x2009,
-	0x0000, 0x2031, 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, 0xad80,
-	0x0005, 0x7026, 0x20a0, 0x080c, 0x4434, 0x15e0, 0x6004, 0xa0c4,
-	0x00ff, 0xa8c6, 0x0006, 0x0150, 0xa0c4, 0xff00, 0xa8c6, 0x0600,
-	0x0128, 0xa084, 0x00ff, 0xa082, 0x0006, 0x1660, 0xd784, 0x0150,
-	0xac80, 0x0006, 0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3, 0x080c,
-	0x34eb, 0x0048, 0xac80, 0x000a, 0x2098, 0x3400, 0x20a9, 0x0004,
-	0x53a3, 0x080c, 0x34eb, 0xa186, 0x007e, 0x0178, 0xa186, 0x0080,
-	0x0160, 0x6004, 0xa084, 0x00ff, 0xa0c2, 0x0006, 0x1210, 0xc1fd,
-	0x0020, 0x080c, 0x46a5, 0x1108, 0xc1fd, 0x21a2, 0xc1fc, 0x94a0,
-	0xa6b0, 0x0005, 0x8108, 0x2001, 0x9232, 0x2004, 0xd0ac, 0x0118,
-	0xa186, 0x0100, 0x0040, 0xd78c, 0x0120, 0xa186, 0x0100, 0x0148,
-	0x0018, 0xa186, 0x007e, 0x0128, 0xa686, 0x0028, 0x0150, 0x0804,
-	0x3793, 0x86ff, 0x1120, 0x7120, 0x810b, 0x0804, 0x28ff, 0x702f,
-	0x0001, 0x711e, 0x7020, 0xa600, 0x7022, 0x772a, 0x2061, 0x92e6,
-	0x6007, 0x0000, 0x6612, 0x7024, 0x600e, 0x6226, 0x632a, 0x642e,
-	0x6532, 0x2c10, 0x080c, 0x14c7, 0x7007, 0x0002, 0x701b, 0x3809,
-	0x0005, 0x702c, 0xa005, 0x1170, 0x711c, 0x7024, 0x20a0, 0x7728,
-	0x2031, 0x0000, 0x2061, 0x92e6, 0x6224, 0x6328, 0x642c, 0x6530,
-	0x0804, 0x3793, 0x7120, 0x810b, 0x0804, 0x28ff, 0x2029, 0x007e,
-	0x7924, 0x7a28, 0x7b2c, 0x7c38, 0xa184, 0xff00, 0x8007, 0xa0e2,
-	0x0020, 0x0a04, 0x2927, 0xa502, 0x0a04, 0x2927, 0xa184, 0x00ff,
-	0xa0e2, 0x0020, 0x0a04, 0x2927, 0xa502, 0x0a04, 0x2927, 0xa284,
-	0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x2927, 0xa502, 0x0a04,
-	0x2927, 0xa284, 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x2927, 0xa502,
-	0x0a04, 0x2927, 0xa384, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04,
-	0x2927, 0xa502, 0x0a04, 0x2927, 0xa384, 0x00ff, 0xa0e2, 0x0020,
-	0x0a04, 0x2927, 0xa502, 0x0a04, 0x2927, 0xa484, 0xff00, 0x8007,
-	0xa0e2, 0x0020, 0x0a04, 0x2927, 0xa502, 0x0a04, 0x2927, 0xa484,
-	0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x2927, 0xa502, 0x0a04, 0x2927,
-	0x2061, 0x94df, 0x6102, 0x6206, 0x630a, 0x640e, 0x0804, 0x28ff,
-	0x080c, 0x3641, 0x0904, 0x2924, 0x2009, 0x0015, 0x7a2c, 0x7b28,
-	0x7c3c, 0x7d38, 0x080c, 0x3682, 0x701b, 0x3887, 0x0005, 0xade8,
-	0x000d, 0x6800, 0xa005, 0x0904, 0x2927, 0x6804, 0x2008, 0xa18c,
-	0xfff8, 0x1904, 0x2927, 0x680c, 0xa005, 0x0904, 0x2927, 0xa082,
-	0xff01, 0x1a04, 0x2927, 0x6810, 0xa082, 0x005c, 0x0a04, 0x2927,
-	0x6824, 0x2008, 0xa082, 0x0008, 0x0a04, 0x2927, 0xa182, 0x0400,
-	0x1a04, 0x2927, 0x080c, 0x5a84, 0x6944, 0x6820, 0xa102, 0x0a04,
-	0x2927, 0x6828, 0x6944, 0x810c, 0xa102, 0x0a04, 0x2927, 0x6840,
-	0xa082, 0x000f, 0x1a04, 0x2927, 0x00d6, 0x080c, 0x145f, 0x0904,
-	0x2924, 0x2d00, 0x00de, 0x684e, 0x00d6, 0x6848, 0xa005, 0x0148,
-	0x2008, 0x2069, 0x9200, 0x68dc, 0xa108, 0x68a8, 0xa102, 0x1208,
-	0x69de, 0x00de, 0x20a9, 0x0015, 0x2d98, 0x2069, 0x9281, 0x2da0,
-	0x53a3, 0x080c, 0x5957, 0x0904, 0x2924, 0x080c, 0x5885, 0x1904,
-	0x2924, 0x00c6, 0x2061, 0x0100, 0x6104, 0xa18d, 0x8000, 0x6106,
-	0x610c, 0xa18d, 0x0100, 0x610e, 0x2061, 0x0140, 0x610c, 0xa18d,
-	0x0100, 0x6902, 0x6b10, 0x2061, 0x9519, 0x6316, 0x080c, 0x4716,
-	0x2001, 0x9295, 0x2003, 0x0000, 0x00ce, 0x0804, 0x28ff, 0xe000,
-	0xe000, 0xe000, 0xe000, 0xe000, 0xe000, 0xe000, 0x0804, 0x28ff,
-	0x7824, 0x0804, 0x28ff, 0x7824, 0x00e6, 0x2071, 0x9281, 0x00ee,
-	0x0804, 0x28ff, 0x0006, 0x2001, 0x9252, 0x2004, 0xd0cc, 0x000e,
-	0x0005, 0x0006, 0x2001, 0x9271, 0x2004, 0xd0bc, 0x000e, 0x0005,
-	0x6164, 0x7a24, 0x6300, 0x82ff, 0x1118, 0x7926, 0x0804, 0x28ff,
-	0x83ff, 0x1904, 0x2927, 0x2001, 0xfff0, 0xa200, 0x1a04, 0x2927,
-	0x2019, 0xffff, 0x6068, 0xa302, 0xa200, 0x0a04, 0x2927, 0x7926,
-	0x6266, 0x0804, 0x28ff, 0x2001, 0x9200, 0x2004, 0xa086, 0x0003,
-	0x1904, 0x2924, 0x7c28, 0x7d24, 0x7e38, 0x7f2c, 0x080c, 0x3641,
-	0x0904, 0x2924, 0x2009, 0x0000, 0x2019, 0x0000, 0x7023, 0x0000,
-	0x702f, 0x0000, 0xad80, 0x0003, 0x7026, 0x20a0, 0xa1e0, 0x936e,
-	0x2c64, 0x8cff, 0x01b8, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006,
-	0x0130, 0x6004, 0xa084, 0xff00, 0xa086, 0x0600, 0x1158, 0x6014,
-	0x20a2, 0x94a0, 0x6010, 0x8007, 0xa105, 0x8007, 0x20a2, 0x94a0,
-	0xa398, 0x0002, 0x8108, 0xa182, 0x00ff, 0x0120, 0xa386, 0x002a,
-	0x0148, 0x08e0, 0x83ff, 0x1120, 0x7120, 0x810c, 0x0804, 0x28ff,
-	0x702f, 0x0001, 0x711e, 0x7020, 0xa300, 0x7022, 0x2061, 0x92e6,
-	0x6007, 0x0000, 0x6312, 0x7024, 0x600e, 0x6426, 0x652a, 0x662e,
-	0x6732, 0x2c10, 0x080c, 0x14c7, 0x7007, 0x0002, 0x701b, 0x3999,
-	0x0005, 0x702c, 0xa005, 0x1158, 0x711c, 0x7024, 0x20a0, 0x2019,
-	0x0000, 0x6424, 0x6528, 0x662c, 0x6730, 0x0804, 0x3956, 0x7120,
-	0x810c, 0x0804, 0x28ff, 0x81ff, 0x1904, 0x2924, 0x60c8, 0xd0ac,
-	0x1118, 0xd09c, 0x0904, 0x2924, 0x080c, 0x3641, 0x0904, 0x2924,
-	0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3682, 0x701b,
-	0x39c2, 0x0005, 0x00d6, 0xade8, 0x000d, 0x6828, 0xa0be, 0x7000,
-	0x0148, 0xa0be, 0x7100, 0x0130, 0xa0be, 0x7200, 0x0118, 0x00de,
-	0x0804, 0x2927, 0x6820, 0x6924, 0x080c, 0x240b, 0x1500, 0x080c,
-	0x4400, 0x11e8, 0x7122, 0x6612, 0x6516, 0x6e18, 0x00c6, 0x080c,
-	0x3641, 0x01a8, 0x080c, 0x3641, 0x0190, 0x00ce, 0x00de, 0x6837,
-	0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000, 0x080c, 0x845c,
-	0x0904, 0x2924, 0x7007, 0x0003, 0x701b, 0x39fa, 0x0005, 0x00de,
-	0x0804, 0x2924, 0x7120, 0x080c, 0x441f, 0x6820, 0xa086, 0x8001,
-	0x0904, 0x2924, 0x2d00, 0x701e, 0x6804, 0xa080, 0x0002, 0x0006,
-	0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c, 0x4166, 0x000e, 0xade8,
-	0x000d, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x2061, 0x92e6, 0x6007,
-	0x0000, 0x6e00, 0x6f28, 0xa7c6, 0x7000, 0x1108, 0x0018, 0xa7c6,
-	0x7100, 0x1140, 0xa6c2, 0x0004, 0x0a04, 0x2927, 0x2009, 0x0004,
-	0x0804, 0x3685, 0xa7c6, 0x7200, 0x1904, 0x2927, 0xa6c2, 0x0054,
-	0x0a04, 0x2927, 0x600e, 0x6013, 0x002a, 0x6226, 0x632a, 0x642e,
-	0x6532, 0x2c10, 0x080c, 0x14c7, 0x7007, 0x0002, 0x701b, 0x3a41,
-	0x0005, 0x701c, 0x2068, 0x6804, 0xa080, 0x0001, 0x2004, 0xa080,
-	0x0002, 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c, 0x4166,
-	0x000e, 0x2009, 0x002a, 0x2061, 0x92e6, 0x6224, 0x6328, 0x642c,
-	0x6530, 0x0804, 0x3685, 0x81ff, 0x1904, 0x2924, 0x080c, 0x3656,
-	0x0904, 0x2927, 0x080c, 0x44d4, 0x0904, 0x2924, 0x080c, 0x4604,
-	0x0804, 0x28ff, 0x0126, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071,
-	0x9200, 0x6044, 0xd0a4, 0x11b0, 0xd084, 0x0118, 0x080c, 0x3bd7,
-	0x0068, 0xd08c, 0x0118, 0x080c, 0x3af8, 0x0040, 0xd094, 0x0118,
-	0x080c, 0x3ad0, 0x0018, 0xd09c, 0x0108, 0x0061, 0x00ee, 0x00ce,
-	0x012e, 0x0005, 0x0016, 0x6128, 0xd19c, 0x1110, 0xc19d, 0x612a,
-	0x001e, 0x0ca0, 0x624c, 0xa286, 0xf0f0, 0x1150, 0x6048, 0xa086,
-	0xf0f0, 0x0130, 0x624a, 0x6043, 0x0090, 0x6043, 0x0010, 0x0478,
-	0xa294, 0xff00, 0xa296, 0xf700, 0x0160, 0x6240, 0xa295, 0x0100,
-	0x6242, 0xa294, 0x0010, 0x0128, 0x2009, 0x00f7, 0x080c, 0x4186,
-	0x00f0, 0x6040, 0xa084, 0x0010, 0xa085, 0x0040, 0x6042, 0x6043,
-	0x0000, 0x7077, 0x0000, 0x7093, 0x0001, 0x70b3, 0x0000, 0x70cb,
-	0x0000, 0x2009, 0x98c0, 0x200b, 0x0000, 0x7087, 0x0000, 0x707b,
-	0x000f, 0x2009, 0x000f, 0x2011, 0x40a8, 0x080c, 0x57b3, 0x0005,
-	0x0156, 0x7078, 0xa005, 0x1510, 0x2011, 0x40a8, 0x080c, 0x5731,
-	0x6040, 0xa094, 0x0010, 0xa285, 0x0020, 0x6042, 0x20a9, 0x00c8,
-	0x6044, 0xd08c, 0x1168, 0x1f04, 0x3ae0, 0x6242, 0x708b, 0x0000,
-	0x6040, 0xa094, 0x0010, 0xa285, 0x0080, 0x6042, 0x6242, 0x0030,
-	0x6242, 0x708b, 0x0000, 0x707f, 0x0000, 0x0000, 0x015e, 0x0005,
-	0x707c, 0xa08a, 0x0003, 0x1210, 0x0023, 0x0010, 0x080c, 0x13fe,
-	0x0005, 0x3b04, 0x3b54, 0x3bd6, 0x00f6, 0x707f, 0x0001, 0x20e1,
-	0xa000, 0xe000, 0x20e1, 0x8700, 0x080c, 0x20ce, 0x20e1, 0x9080,
-	0x20e1, 0x4000, 0x2079, 0x9700, 0x207b, 0x2200, 0x7807, 0x00ef,
-	0x780b, 0x0000, 0x780f, 0x00ef, 0x7813, 0x0138, 0x7817, 0x0000,
-	0x781b, 0x0000, 0x781f, 0x0000, 0x7823, 0xffff, 0x7827, 0xffff,
-	0x782b, 0x0000, 0x782f, 0x0000, 0x2079, 0x970c, 0x207b, 0x1101,
-	0x7807, 0x0000, 0x2099, 0x9205, 0x20a1, 0x970e, 0x20a9, 0x0004,
-	0x53a3, 0x2079, 0x9712, 0x207b, 0x0000, 0x7807, 0x0000, 0x2099,
-	0x9700, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x60c3, 0x000c,
-	0x600f, 0x0000, 0x080c, 0x40ec, 0x00fe, 0x7083, 0x0000, 0x6043,
-	0x0008, 0x6043, 0x0000, 0x0005, 0x00d6, 0x7080, 0x7083, 0x0000,
-	0xa025, 0x0904, 0x3bbe, 0x6020, 0xd0b4, 0x1904, 0x3bbc, 0x7190,
-	0x81ff, 0x0904, 0x3ba6, 0xa486, 0x000c, 0x1904, 0x3bb1, 0xa480,
-	0x0018, 0x8004, 0x20a8, 0x2011, 0x9780, 0x2019, 0x9700, 0x220c,
-	0x2304, 0xa106, 0x1188, 0x8210, 0x8318, 0x1f04, 0x3b6f, 0x6043,
-	0x0004, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006, 0x707f,
-	0x0002, 0x708b, 0x0002, 0x04c0, 0x2069, 0x9780, 0x6930, 0xa18e,
-	0x1101, 0x1538, 0x6834, 0xa005, 0x1520, 0x6900, 0xa18c, 0x00ff,
-	0x1118, 0x6804, 0xa005, 0x0190, 0x2011, 0x978e, 0x2019, 0x9205,
-	0x20a9, 0x0004, 0x220c, 0x2304, 0xa102, 0x0230, 0x1190, 0x8210,
-	0x8318, 0x1f04, 0x3b9a, 0x0068, 0x7093, 0x0000, 0x20e1, 0x9080,
-	0x20e1, 0x4000, 0x2099, 0x9780, 0x20a1, 0x020b, 0x20a9, 0x0014,
-	0x53a6, 0x6043, 0x0008, 0x6043, 0x0000, 0x6020, 0xd0b4, 0x1120,
-	0x60c3, 0x000c, 0x080c, 0x40ec, 0x00de, 0x0005, 0x6040, 0xa085,
-	0x0100, 0x6042, 0x6020, 0xd0b4, 0x1db8, 0x60c3, 0x000c, 0x2011,
-	0x94ef, 0x2013, 0x0000, 0x7083, 0x0000, 0x20e1, 0x9080, 0x60a3,
-	0x0056, 0x60a7, 0x9575, 0x080c, 0x6f15, 0x0c30, 0x0005, 0x7088,
-	0xa08a, 0x001d, 0x1210, 0x0023, 0x0010, 0x080c, 0x13fe, 0x0005,
-	0x3c0a, 0x3c19, 0x3c43, 0x3c58, 0x3c7e, 0x3ca6, 0x3ccc, 0x3cfd,
-	0x3d23, 0x3d4b, 0x3d86, 0x3dae, 0x3dca, 0x3de0, 0x3e00, 0x3e13,
-	0x3e1b, 0x3e45, 0x3e6b, 0x3e93, 0x3eb9, 0x3eea, 0x3f25, 0x3f54,
-	0x3f70, 0x3faf, 0x3fcf, 0x3fe8, 0x3fe9, 0x00c6, 0x2061, 0x9200,
-	0x6003, 0x0007, 0x2061, 0x0100, 0x6004, 0xa084, 0xfff9, 0x6006,
-	0x00ce, 0x0005, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0002,
-	0x708b, 0x0001, 0x2009, 0x07d0, 0x2011, 0x40af, 0x080c, 0x5725,
-	0x0005, 0x00f6, 0x7080, 0xa086, 0x0014, 0x1518, 0x6043, 0x0000,
-	0x6020, 0xd0b4, 0x11f0, 0x2079, 0x9780, 0x7a30, 0xa296, 0x1102,
-	0x11b0, 0x7834, 0xa005, 0x1198, 0x7a38, 0xd2fc, 0x0138, 0x70b0,
-	0xa005, 0x1120, 0x080c, 0x419d, 0x70b3, 0x0001, 0x2011, 0x40af,
-	0x080c, 0x5731, 0x708b, 0x0010, 0x080c, 0x3e1b, 0x0010, 0x7083,
-	0x0000, 0x00fe, 0x0005, 0x708b, 0x0003, 0x6043, 0x0004, 0x080c,
-	0x416e, 0x20a3, 0x1102, 0x20a3, 0x0000, 0x20a9, 0x000a, 0x20a3,
-	0x0000, 0x1f04, 0x3c4f, 0x60c3, 0x0014, 0x080c, 0x40ec, 0x0005,
-	0x00f6, 0x7080, 0xa005, 0x0500, 0x2011, 0x40af, 0x080c, 0x5731,
-	0xa086, 0x0014, 0x11b8, 0x2079, 0x9780, 0x7a30, 0xa296, 0x1102,
-	0x1188, 0x7834, 0xa005, 0x1170, 0x7a38, 0xd2fc, 0x0138, 0x70b0,
-	0xa005, 0x1120, 0x080c, 0x419d, 0x70b3, 0x0001, 0x708b, 0x0004,
-	0x0029, 0x0010, 0x080c, 0x41b6, 0x00fe, 0x0005, 0x708b, 0x0005,
-	0x080c, 0x416e, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011,
-	0x978e, 0x080c, 0x41bd, 0x1160, 0x7074, 0xa005, 0x1148, 0x714c,
-	0xa186, 0xffff, 0x0128, 0x080c, 0x4074, 0x0110, 0x080c, 0x419d,
-	0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x60c3, 0x0014, 0x080c, 0x40ec, 0x0005, 0x00f6, 0x7080,
-	0xa005, 0x0500, 0x2011, 0x40af, 0x080c, 0x5731, 0xa086, 0x0014,
-	0x11b8, 0x2079, 0x9780, 0x7a30, 0xa296, 0x1103, 0x1188, 0x7834,
-	0xa005, 0x1170, 0x7a38, 0xd2fc, 0x0138, 0x70b0, 0xa005, 0x1120,
-	0x080c, 0x419d, 0x70b3, 0x0001, 0x708b, 0x0006, 0x0029, 0x0010,
-	0x080c, 0x41b6, 0x00fe, 0x0005, 0x708b, 0x0007, 0x080c, 0x416e,
-	0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, 0x978e, 0x080c,
-	0x41bd, 0x11a8, 0x7074, 0xa005, 0x1190, 0x7154, 0xa186, 0xffff,
-	0x0170, 0xa180, 0x2719, 0x200d, 0xa18c, 0xff00, 0x810f, 0x080c,
-	0x4074, 0x0128, 0x080c, 0x3919, 0x0110, 0x080c, 0x2455, 0x20a9,
-	0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x60c3, 0x0014, 0x080c, 0x40ec, 0x0005, 0x00f6, 0x7080, 0xa005,
-	0x0500, 0x2011, 0x40af, 0x080c, 0x5731, 0xa086, 0x0014, 0x11b8,
-	0x2079, 0x9780, 0x7a30, 0xa296, 0x1104, 0x1188, 0x7834, 0xa005,
-	0x1170, 0x7a38, 0xd2fc, 0x0138, 0x70b0, 0xa005, 0x1120, 0x080c,
-	0x419d, 0x70b3, 0x0001, 0x708b, 0x0008, 0x0029, 0x0010, 0x080c,
-	0x41b6, 0x00fe, 0x0005, 0x708b, 0x0009, 0x080c, 0x416e, 0x20a3,
-	0x1105, 0x20a3, 0x0100, 0x3430, 0x080c, 0x41bd, 0x1150, 0x7074,
-	0xa005, 0x1138, 0x080c, 0x3fea, 0x1170, 0xa085, 0x0001, 0x080c,
-	0x2455, 0x20a9, 0x0008, 0x2099, 0x978e, 0x26a0, 0x53a6, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x40ec, 0x0010,
-	0x080c, 0x3bfd, 0x0005, 0x00f6, 0x7080, 0xa005, 0x05a8, 0x2011,
-	0x40af, 0x080c, 0x5731, 0xa086, 0x0014, 0x1560, 0x2079, 0x9780,
-	0x7a30, 0xa296, 0x1105, 0x1530, 0x7834, 0x2011, 0x0100, 0xa21e,
+	0x0a04, 0x284b, 0xa182, 0x00ff, 0x1a04, 0x284b, 0x0126, 0x2091,
+	0x8000, 0x080c, 0x7bbb, 0x1188, 0xa190, 0x8c34, 0x2204, 0xa065,
+	0x0160, 0x080c, 0x4118, 0x2001, 0x8b32, 0x2004, 0xd0ac, 0x0110,
+	0x6017, 0x0000, 0x012e, 0x0804, 0x2823, 0x012e, 0x0804, 0x2848,
+	0x080c, 0x1488, 0x0188, 0xa006, 0x6802, 0x7010, 0xa005, 0x1120,
+	0x2d00, 0x7012, 0x7016, 0x0030, 0x7014, 0x6802, 0x2060, 0x2d00,
+	0x6006, 0x7016, 0xad80, 0x000d, 0x0005, 0x7924, 0x810f, 0xa18c,
+	0x00ff, 0x080c, 0x430a, 0x1130, 0x7e28, 0xa684, 0x3fff, 0xa082,
+	0x4000, 0x0208, 0xa066, 0x8cff, 0x0005, 0x7e24, 0x860f, 0xa18c,
+	0x00ff, 0x080c, 0x430a, 0x1128, 0xa6b4, 0x00ff, 0xa682, 0x4000,
+	0x0208, 0xa066, 0x8cff, 0x0005, 0x0016, 0x7110, 0x81ff, 0x0128,
+	0x2168, 0x6904, 0x080c, 0x149f, 0x0cc8, 0x7112, 0x7116, 0x001e,
+	0x0005, 0x2031, 0x0001, 0x0010, 0x2031, 0x0000, 0x2061, 0x8bd1,
+	0x6606, 0x6112, 0x600e, 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10,
+	0x080c, 0x14d3, 0x7007, 0x0002, 0x701b, 0x2823, 0x0005, 0x00f6,
+	0x0126, 0x2091, 0x8000, 0x2079, 0x0000, 0x2001, 0x8b8f, 0x2004,
+	0xa005, 0x1168, 0x0e04, 0x362f, 0x7818, 0xd084, 0x1140, 0x7a22,
+	0x7b26, 0x7c2a, 0x781b, 0x0001, 0x2091, 0x4080, 0x0408, 0x0016,
+	0x00c6, 0x00e6, 0x2071, 0x8b81, 0x7138, 0xa182, 0x0010, 0x0218,
+	0x7030, 0x2060, 0x0078, 0x7030, 0xa0e0, 0x0004, 0xac82, 0x8bd1,
+	0x0210, 0x2061, 0x8b91, 0x2c00, 0x7032, 0x81ff, 0x1108, 0x7036,
+	0x8108, 0x713a, 0x2262, 0x6306, 0x640a, 0x00ee, 0x00ce, 0x001e,
+	0x012e, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x8b81, 0x7038, 0xa005,
+	0x0570, 0x0126, 0x2091, 0x8000, 0x0e04, 0x3686, 0x00f6, 0x2079,
+	0x0000, 0x7818, 0xd084, 0x1508, 0x00c6, 0x7034, 0x2060, 0x2c04,
+	0x7822, 0x6004, 0x7826, 0x6008, 0x782a, 0x781b, 0x0001, 0x2091,
+	0x4080, 0x7038, 0x8001, 0x703a, 0xa005, 0x1130, 0x7033, 0x8b91,
+	0x7037, 0x8b91, 0x00ce, 0x0048, 0xac80, 0x0004, 0xa0fa, 0x8bd1,
+	0x0210, 0x2001, 0x8b91, 0x7036, 0x00ce, 0x00fe, 0x012e, 0x00ee,
+	0x0005, 0x0026, 0x2001, 0x8b52, 0x2004, 0xd0c4, 0x0120, 0x2011,
+	0x8014, 0x080c, 0x3617, 0x002e, 0x0005, 0x81ff, 0x1904, 0x2848,
+	0x0126, 0x2091, 0x8000, 0x6030, 0xc08d, 0x6032, 0x080c, 0x4c42,
+	0x1158, 0x2001, 0x8d9d, 0x2003, 0x0001, 0x2001, 0x8b00, 0x2003,
+	0x0001, 0x080c, 0x4b8b, 0x0010, 0x080c, 0x403d, 0x012e, 0x0804,
+	0x2823, 0x7824, 0x2008, 0xa18c, 0xfffd, 0x1128, 0x61d4, 0xa10d,
+	0x61d6, 0x0804, 0x2823, 0x0804, 0x284b, 0x81ff, 0x1904, 0x2848,
+	0x6000, 0xa086, 0x0003, 0x1904, 0x2848, 0x2001, 0x8b52, 0x2004,
+	0xd0a4, 0x1904, 0x2848, 0x080c, 0x35e5, 0x0904, 0x284b, 0x6004,
+	0xa084, 0x00ff, 0xa086, 0x0006, 0x1120, 0x7828, 0xa005, 0x0904,
+	0x2823, 0x00c6, 0x080c, 0x35c0, 0x00ce, 0x0904, 0x2848, 0x6837,
+	0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, 0x7d78,
+	0x0904, 0x2848, 0x7007, 0x0003, 0x701b, 0x36ef, 0x0005, 0x6830,
+	0xa086, 0x0100, 0x0904, 0x2848, 0x0804, 0x2823, 0x2001, 0x8b00,
+	0x2004, 0xa086, 0x0003, 0x1904, 0x2848, 0x7f24, 0x7a2c, 0x7b28,
+	0x7c3c, 0x7d38, 0x080c, 0x35c0, 0x0904, 0x2848, 0x2009, 0x0000,
+	0x2031, 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, 0xad80, 0x0005,
+	0x7026, 0x20a0, 0x080c, 0x430a, 0x1560, 0x6004, 0xa0c4, 0x00ff,
+	0xa8c6, 0x0006, 0x0128, 0xa0c4, 0xff00, 0xa8c6, 0x0600, 0x1508,
+	0x2001, 0x8b52, 0x2004, 0xd0ac, 0x1118, 0x080c, 0x457e, 0x01c8,
+	0xd784, 0x0150, 0xac80, 0x0006, 0x2098, 0x3400, 0x20a9, 0x0004,
+	0x53a3, 0x080c, 0x345e, 0x0048, 0xac80, 0x000a, 0x2098, 0x3400,
+	0x20a9, 0x0004, 0x53a3, 0x080c, 0x345e, 0x21a2, 0x94a0, 0xa6b0,
+	0x0005, 0x8108, 0x2001, 0x8b32, 0x2004, 0xd0ac, 0x0118, 0xa186,
+	0x0100, 0x0040, 0xd78c, 0x0120, 0xa186, 0x0100, 0x0148, 0x0018,
+	0xa186, 0x007e, 0x0128, 0xa686, 0x0028, 0x0150, 0x0804, 0x3712,
+	0x86ff, 0x1120, 0x7120, 0x810b, 0x0804, 0x2823, 0x702f, 0x0001,
+	0x711e, 0x7020, 0xa600, 0x7022, 0x772a, 0x2061, 0x8bd1, 0x6007,
+	0x0000, 0x6612, 0x7024, 0x600e, 0x6226, 0x632a, 0x642e, 0x6532,
+	0x2c10, 0x080c, 0x14d3, 0x7007, 0x0002, 0x701b, 0x3778, 0x0005,
+	0x702c, 0xa005, 0x1170, 0x711c, 0x7024, 0x20a0, 0x7728, 0x2031,
+	0x0000, 0x2061, 0x8bd1, 0x6224, 0x6328, 0x642c, 0x6530, 0x0804,
+	0x3712, 0x7120, 0x810b, 0x0804, 0x2823, 0x2029, 0x007e, 0x7924,
+	0x7a28, 0x7b2c, 0x7c38, 0xa184, 0xff00, 0x8007, 0xa0e2, 0x0020,
+	0x0a04, 0x284b, 0xa502, 0x0a04, 0x284b, 0xa184, 0x00ff, 0xa0e2,
+	0x0020, 0x0a04, 0x284b, 0xa502, 0x0a04, 0x284b, 0xa284, 0xff00,
+	0x8007, 0xa0e2, 0x0020, 0x0a04, 0x284b, 0xa502, 0x0a04, 0x284b,
+	0xa284, 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x284b, 0xa502, 0x0a04,
+	0x284b, 0xa384, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x284b,
+	0xa502, 0x0a04, 0x284b, 0xa384, 0x00ff, 0xa0e2, 0x0020, 0x0a04,
+	0x284b, 0xa502, 0x0a04, 0x284b, 0xa484, 0xff00, 0x8007, 0xa0e2,
+	0x0020, 0x0a04, 0x284b, 0xa502, 0x0a04, 0x284b, 0xa484, 0x00ff,
+	0xa0e2, 0x0020, 0x0a04, 0x284b, 0xa502, 0x0a04, 0x284b, 0x2061,
+	0x8da4, 0x6102, 0x6206, 0x630a, 0x640e, 0x0804, 0x2823, 0x0006,
+	0x2001, 0x8b52, 0x2004, 0xd0cc, 0x000e, 0x0005, 0x0006, 0x2001,
+	0x8b71, 0x2004, 0xd0bc, 0x000e, 0x0005, 0x6164, 0x7a24, 0x6300,
+	0x82ff, 0x1118, 0x7926, 0x0804, 0x2823, 0x83ff, 0x1904, 0x284b,
+	0x2001, 0xfff0, 0xa200, 0x1a04, 0x284b, 0x2019, 0xffff, 0x6068,
+	0xa302, 0xa200, 0x0a04, 0x284b, 0x7926, 0x6266, 0x0804, 0x2823,
+	0x2001, 0x8b00, 0x2004, 0xa086, 0x0003, 0x1904, 0x2848, 0x7c28,
+	0x7d24, 0x7e38, 0x7f2c, 0x080c, 0x35c0, 0x0904, 0x2848, 0x2009,
+	0x0000, 0x2019, 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, 0xad80,
+	0x0003, 0x7026, 0x20a0, 0xa1e0, 0x8c34, 0x2c64, 0x8cff, 0x01b8,
+	0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0130, 0x6004, 0xa084,
+	0xff00, 0xa086, 0x0600, 0x1158, 0x6014, 0x20a2, 0x94a0, 0x6010,
+	0x8007, 0xa105, 0x8007, 0x20a2, 0x94a0, 0xa398, 0x0002, 0x8108,
+	0xa182, 0x00ff, 0x0120, 0xa386, 0x002a, 0x0148, 0x08e0, 0x83ff,
+	0x1120, 0x7120, 0x810c, 0x0804, 0x2823, 0x702f, 0x0001, 0x711e,
+	0x7020, 0xa300, 0x7022, 0x2061, 0x8bd1, 0x6007, 0x0000, 0x6312,
+	0x7024, 0x600e, 0x6426, 0x652a, 0x662e, 0x6732, 0x2c10, 0x080c,
+	0x14d3, 0x7007, 0x0002, 0x701b, 0x386e, 0x0005, 0x702c, 0xa005,
+	0x1158, 0x711c, 0x7024, 0x20a0, 0x2019, 0x0000, 0x6424, 0x6528,
+	0x662c, 0x6730, 0x0804, 0x382b, 0x7120, 0x810c, 0x0804, 0x2823,
+	0x81ff, 0x1904, 0x2848, 0x60c8, 0xd0ac, 0x1118, 0xd09c, 0x0904,
+	0x2848, 0x080c, 0x35c0, 0x0904, 0x2848, 0x7924, 0x7a2c, 0x7b28,
+	0x7c3c, 0x7d38, 0x080c, 0x3601, 0x701b, 0x3897, 0x0005, 0x00d6,
+	0xade8, 0x000d, 0x6828, 0xa0be, 0x7000, 0x0148, 0xa0be, 0x7100,
+	0x0130, 0xa0be, 0x7200, 0x0118, 0x00de, 0x0804, 0x284b, 0x6820,
+	0x6924, 0x080c, 0x22e9, 0x1500, 0x080c, 0x42d6, 0x11e8, 0x7122,
+	0x6612, 0x6516, 0x6e18, 0x00c6, 0x080c, 0x35c0, 0x01a8, 0x080c,
+	0x35c0, 0x0190, 0x00ce, 0x00de, 0x6837, 0x0000, 0x6838, 0xc0fd,
+	0x683a, 0x6823, 0x0000, 0x080c, 0x7cfd, 0x0904, 0x2848, 0x7007,
+	0x0003, 0x701b, 0x38cf, 0x0005, 0x00de, 0x0804, 0x2848, 0x7120,
+	0x080c, 0x42f5, 0x6820, 0xa086, 0x8001, 0x0904, 0x2848, 0x2d00,
+	0x701e, 0x6804, 0xa080, 0x0002, 0x0006, 0x20a9, 0x002a, 0x2098,
+	0x20a0, 0x080c, 0x409e, 0x000e, 0xade8, 0x000d, 0x6a08, 0x6b0c,
+	0x6c10, 0x6d14, 0x2061, 0x8bd1, 0x6007, 0x0000, 0x6e00, 0x6f28,
+	0xa7c6, 0x7000, 0x1108, 0x0018, 0xa7c6, 0x7100, 0x1140, 0xa6c2,
+	0x0004, 0x0a04, 0x284b, 0x2009, 0x0004, 0x0804, 0x3604, 0xa7c6,
+	0x7200, 0x1904, 0x284b, 0xa6c2, 0x0054, 0x0a04, 0x284b, 0x600e,
+	0x6013, 0x002a, 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x080c,
+	0x14d3, 0x7007, 0x0002, 0x701b, 0x3916, 0x0005, 0x701c, 0x2068,
+	0x6804, 0xa080, 0x0001, 0x2004, 0xa080, 0x0002, 0x0006, 0x20a9,
+	0x002a, 0x2098, 0x20a0, 0x080c, 0x409e, 0x000e, 0x2009, 0x002a,
+	0x2061, 0x8bd1, 0x6224, 0x6328, 0x642c, 0x6530, 0x0804, 0x3604,
+	0x81ff, 0x1904, 0x2848, 0x080c, 0x35d5, 0x0904, 0x284b, 0x080c,
+	0x43ad, 0x0904, 0x2848, 0x080c, 0x44dd, 0x0804, 0x2823, 0x7824,
+	0xd084, 0x0904, 0x31d9, 0x080c, 0x35e5, 0x0904, 0x284b, 0x00c6,
+	0x080c, 0x35c0, 0x00ce, 0x0904, 0x2848, 0x6004, 0xa084, 0x00ff,
+	0xa086, 0x0006, 0x11f0, 0x2001, 0x8b52, 0x2004, 0xd0b4, 0x0904,
+	0x3206, 0x6000, 0xd08c, 0x1904, 0x3206, 0x6837, 0x0000, 0x6838,
+	0xc0fd, 0x683a, 0x080c, 0x7d17, 0x0904, 0x2848, 0x7007, 0x0003,
+	0x701b, 0x396b, 0x0005, 0x080c, 0x35e5, 0x0904, 0x284b, 0x0804,
+	0x3206, 0x2009, 0x8b2f, 0x210c, 0x81ff, 0x1904, 0x2848, 0x2001,
+	0x8b00, 0x2004, 0xa086, 0x0003, 0x1904, 0x2848, 0x2001, 0x8b52,
+	0x2004, 0xd0ac, 0x1904, 0x2848, 0x6837, 0x0000, 0x6833, 0x0000,
+	0x6838, 0xc0fd, 0x683a, 0x080c, 0x7d78, 0x0904, 0x2848, 0x7007,
+	0x0003, 0x701b, 0x3994, 0x0005, 0x6830, 0xa086, 0x0100, 0x0904,
+	0x2848, 0x080c, 0x35e5, 0x0904, 0x284b, 0x0804, 0x3953, 0x0126,
+	0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0x8b00, 0x6044, 0xd0a4,
+	0x11b0, 0xd084, 0x0118, 0x080c, 0x3b0c, 0x0068, 0xd08c, 0x0118,
+	0x080c, 0x3a2d, 0x0040, 0xd094, 0x0118, 0x080c, 0x3a05, 0x0018,
+	0xd09c, 0x0108, 0x0061, 0x00ee, 0x00ce, 0x012e, 0x0005, 0x0016,
+	0x6128, 0xd19c, 0x1110, 0xc19d, 0x612a, 0x001e, 0x0ca0, 0x624c,
+	0xa286, 0xf0f0, 0x1150, 0x6048, 0xa086, 0xf0f0, 0x0130, 0x624a,
+	0x6043, 0x0090, 0x6043, 0x0010, 0x0478, 0xa294, 0xff00, 0xa296,
+	0xf700, 0x0160, 0x6240, 0xa295, 0x0100, 0x6242, 0xa294, 0x0010,
+	0x0128, 0x2009, 0x00f7, 0x080c, 0x40be, 0x00f0, 0x6040, 0xa084,
+	0x0010, 0xa085, 0x0040, 0x6042, 0x6043, 0x0000, 0x7077, 0x0000,
+	0x7093, 0x0001, 0x70b3, 0x0000, 0x70cb, 0x0000, 0x2009, 0x91c0,
+	0x200b, 0x0000, 0x7087, 0x0000, 0x707b, 0x000f, 0x2009, 0x000f,
+	0x2011, 0x3fe0, 0x080c, 0x568c, 0x0005, 0x0156, 0x7078, 0xa005,
+	0x1510, 0x2011, 0x3fe0, 0x080c, 0x560d, 0x6040, 0xa094, 0x0010,
+	0xa285, 0x0020, 0x6042, 0x20a9, 0x00c8, 0x6044, 0xd08c, 0x1168,
+	0x1f04, 0x3a15, 0x6242, 0x708b, 0x0000, 0x6040, 0xa094, 0x0010,
+	0xa285, 0x0080, 0x6042, 0x6242, 0x0030, 0x6242, 0x708b, 0x0000,
+	0x707f, 0x0000, 0x0000, 0x015e, 0x0005, 0x707c, 0xa08a, 0x0003,
+	0x1210, 0x0023, 0x0010, 0x080c, 0x1410, 0x0005, 0x3a39, 0x3a89,
+	0x3b0b, 0x00f6, 0x707f, 0x0001, 0x20e1, 0xa000, 0xe000, 0x20e1,
+	0x8700, 0x080c, 0x1fbd, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2079,
+	0x9000, 0x207b, 0x2200, 0x7807, 0x00ef, 0x780b, 0x0000, 0x780f,
+	0x00ef, 0x7813, 0x0138, 0x7817, 0x0000, 0x781b, 0x0000, 0x781f,
+	0x0000, 0x7823, 0xffff, 0x7827, 0xffff, 0x782b, 0x0000, 0x782f,
+	0x0000, 0x2079, 0x900c, 0x207b, 0x1101, 0x7807, 0x0000, 0x2099,
+	0x8b05, 0x20a1, 0x900e, 0x20a9, 0x0004, 0x53a3, 0x2079, 0x9012,
+	0x207b, 0x0000, 0x7807, 0x0000, 0x2099, 0x9000, 0x20a1, 0x020b,
+	0x20a9, 0x0014, 0x53a6, 0x60c3, 0x000c, 0x600f, 0x0000, 0x080c,
+	0x4024, 0x00fe, 0x7083, 0x0000, 0x6043, 0x0008, 0x6043, 0x0000,
+	0x0005, 0x00d6, 0x7080, 0x7083, 0x0000, 0xa025, 0x0904, 0x3af3,
+	0x6020, 0xd0b4, 0x1904, 0x3af1, 0x7190, 0x81ff, 0x0904, 0x3adb,
+	0xa486, 0x000c, 0x1904, 0x3ae6, 0xa480, 0x0018, 0x8004, 0x20a8,
+	0x2011, 0x9080, 0x2019, 0x9000, 0x220c, 0x2304, 0xa106, 0x1188,
+	0x8210, 0x8318, 0x1f04, 0x3aa4, 0x6043, 0x0004, 0x608b, 0xbc94,
+	0x608f, 0xf0f0, 0x6043, 0x0006, 0x707f, 0x0002, 0x708b, 0x0002,
+	0x04c0, 0x2069, 0x9080, 0x6930, 0xa18e, 0x1101, 0x1538, 0x6834,
+	0xa005, 0x1520, 0x6900, 0xa18c, 0x00ff, 0x1118, 0x6804, 0xa005,
+	0x0190, 0x2011, 0x908e, 0x2019, 0x8b05, 0x20a9, 0x0004, 0x220c,
+	0x2304, 0xa102, 0x0230, 0x1190, 0x8210, 0x8318, 0x1f04, 0x3acf,
+	0x0068, 0x7093, 0x0000, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099,
+	0x9080, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x6043, 0x0008,
+	0x6043, 0x0000, 0x6020, 0xd0b4, 0x1120, 0x60c3, 0x000c, 0x080c,
+	0x4024, 0x00de, 0x0005, 0x6040, 0xa085, 0x0100, 0x6042, 0x6020,
+	0xd0b4, 0x1db8, 0x60c3, 0x000c, 0x2011, 0x8db4, 0x2013, 0x0000,
+	0x7083, 0x0000, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575,
+	0x080c, 0x66ee, 0x0c30, 0x0005, 0x7088, 0xa08a, 0x001d, 0x1210,
+	0x0023, 0x0010, 0x080c, 0x1410, 0x0005, 0x3b3f, 0x3b4e, 0x3b78,
+	0x3b8d, 0x3bb3, 0x3bdb, 0x3c01, 0x3c32, 0x3c58, 0x3c80, 0x3cbb,
+	0x3ce3, 0x3cff, 0x3d15, 0x3d35, 0x3d48, 0x3d50, 0x3d7a, 0x3da0,
+	0x3dc8, 0x3dee, 0x3e1f, 0x3e5b, 0x3e8a, 0x3ea6, 0x3ee5, 0x3f05,
+	0x3f1e, 0x3f1f, 0x00c6, 0x2061, 0x8b00, 0x6003, 0x0007, 0x2061,
+	0x0100, 0x6004, 0xa084, 0xfff9, 0x6006, 0x00ce, 0x0005, 0x608b,
+	0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0002, 0x708b, 0x0001, 0x2009,
+	0x07d0, 0x2011, 0x3fe7, 0x080c, 0x5601, 0x0005, 0x00f6, 0x7080,
+	0xa086, 0x0014, 0x1518, 0x6043, 0x0000, 0x6020, 0xd0b4, 0x11f0,
+	0x2079, 0x9080, 0x7a30, 0xa296, 0x1102, 0x11b0, 0x7834, 0xa005,
+	0x1198, 0x7a38, 0xd2fc, 0x0138, 0x70b0, 0xa005, 0x1120, 0x080c,
+	0x40d5, 0x70b3, 0x0001, 0x2011, 0x3fe7, 0x080c, 0x560d, 0x708b,
+	0x0010, 0x080c, 0x3d50, 0x0010, 0x7083, 0x0000, 0x00fe, 0x0005,
+	0x708b, 0x0003, 0x6043, 0x0004, 0x080c, 0x40a6, 0x20a3, 0x1102,
+	0x20a3, 0x0000, 0x20a9, 0x000a, 0x20a3, 0x0000, 0x1f04, 0x3b84,
+	0x60c3, 0x0014, 0x080c, 0x4024, 0x0005, 0x00f6, 0x7080, 0xa005,
+	0x0500, 0x2011, 0x3fe7, 0x080c, 0x560d, 0xa086, 0x0014, 0x11b8,
+	0x2079, 0x9080, 0x7a30, 0xa296, 0x1102, 0x1188, 0x7834, 0xa005,
 	0x1170, 0x7a38, 0xd2fc, 0x0138, 0x70b0, 0xa005, 0x1120, 0x080c,
-	0x419d, 0x70b3, 0x0001, 0x708b, 0x000a, 0x00c1, 0x00a8, 0xa005,
-	0x1188, 0x7a38, 0xd2fc, 0x0138, 0x70b0, 0xa005, 0x1120, 0x080c,
-	0x419d, 0x70b3, 0x0001, 0x7087, 0x0000, 0x708b, 0x000e, 0x080c,
-	0x3e00, 0x0010, 0x080c, 0x41b6, 0x00fe, 0x0005, 0x708b, 0x000b,
-	0x2011, 0x970e, 0x22a0, 0x20a9, 0x0040, 0x2019, 0xffff, 0x43a4,
-	0x20a9, 0x0002, 0x2009, 0x0000, 0x41a4, 0x080c, 0x416e, 0x20a3,
-	0x1106, 0x20a3, 0x0000, 0x080c, 0x41bd, 0x0118, 0x2013, 0x0000,
-	0x0020, 0x7050, 0xa085, 0x0100, 0x2012, 0x2298, 0x20a9, 0x0042,
-	0x53a6, 0x60c3, 0x0084, 0x080c, 0x40ec, 0x0005, 0x00f6, 0x7080,
-	0xa005, 0x01b0, 0x2011, 0x40af, 0x080c, 0x5731, 0xa086, 0x0084,
-	0x1168, 0x2079, 0x9780, 0x7a30, 0xa296, 0x1106, 0x1138, 0x7834,
-	0xa005, 0x1120, 0x708b, 0x000c, 0x0029, 0x0010, 0x080c, 0x41b6,
-	0x00fe, 0x0005, 0x708b, 0x000d, 0x080c, 0x416e, 0x20a3, 0x1107,
-	0x20a3, 0x0000, 0x2099, 0x978e, 0x20a9, 0x0040, 0x53a6, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, 0x080c, 0x40ec, 0x0005,
-	0x00f6, 0x7080, 0xa005, 0x01d0, 0x2011, 0x40af, 0x080c, 0x5731,
-	0xa086, 0x0084, 0x1188, 0x2079, 0x9780, 0x7a30, 0xa296, 0x1107,
-	0x1158, 0x7834, 0xa005, 0x1140, 0x7087, 0x0001, 0x080c, 0x4160,
-	0x708b, 0x000e, 0x0029, 0x0010, 0x080c, 0x41b6, 0x00fe, 0x0005,
-	0x708b, 0x000f, 0x7083, 0x0000, 0x608b, 0xbc85, 0x608f, 0xb5b5,
-	0x6043, 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011, 0x40af,
-	0x080c, 0x5725, 0x0005, 0x7080, 0xa005, 0x0120, 0x2011, 0x40af,
-	0x080c, 0x5731, 0x0005, 0x708b, 0x0011, 0x716c, 0x81ff, 0x0170,
-	0x2009, 0x0000, 0x7070, 0xa084, 0x00ff, 0x080c, 0x240b, 0xa186,
-	0x0080, 0x0120, 0x2011, 0x978e, 0x080c, 0x4074, 0x20e1, 0x9080,
-	0x20e1, 0x4000, 0x2099, 0x9780, 0x20a1, 0x020b, 0x7480, 0xa480,
-	0x0018, 0xa080, 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6,
-	0x60c3, 0x0014, 0x080c, 0x40ec, 0x0005, 0x00f6, 0x7080, 0xa005,
-	0x0500, 0x2011, 0x40af, 0x080c, 0x5731, 0xa086, 0x0014, 0x11b8,
-	0x2079, 0x9780, 0x7a30, 0xa296, 0x1103, 0x1188, 0x7834, 0xa005,
-	0x1170, 0x7a38, 0xd2fc, 0x0138, 0x70b0, 0xa005, 0x1120, 0x080c,
-	0x419d, 0x70b3, 0x0001, 0x708b, 0x0012, 0x0029, 0x0010, 0x7083,
-	0x0000, 0x00fe, 0x0005, 0x708b, 0x0013, 0x080c, 0x417a, 0x20a3,
-	0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, 0x978e, 0x080c, 0x41bd,
+	0x40d5, 0x70b3, 0x0001, 0x708b, 0x0004, 0x0029, 0x0010, 0x080c,
+	0x40ee, 0x00fe, 0x0005, 0x708b, 0x0005, 0x080c, 0x40a6, 0x20a3,
+	0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, 0x908e, 0x080c, 0x40f5,
 	0x1160, 0x7074, 0xa005, 0x1148, 0x714c, 0xa186, 0xffff, 0x0128,
-	0x080c, 0x4074, 0x0110, 0x080c, 0x419d, 0x20a9, 0x0008, 0x2298,
+	0x080c, 0x3fab, 0x0110, 0x080c, 0x40d5, 0x20a9, 0x0008, 0x2298,
 	0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014,
-	0x080c, 0x40ec, 0x0005, 0x00f6, 0x7080, 0xa005, 0x0500, 0x2011,
-	0x40af, 0x080c, 0x5731, 0xa086, 0x0014, 0x11b8, 0x2079, 0x9780,
-	0x7a30, 0xa296, 0x1104, 0x1188, 0x7834, 0xa005, 0x1170, 0x7a38,
-	0xd2fc, 0x0138, 0x70b0, 0xa005, 0x1120, 0x080c, 0x419d, 0x70b3,
-	0x0001, 0x708b, 0x0014, 0x0029, 0x0010, 0x7083, 0x0000, 0x00fe,
-	0x0005, 0x708b, 0x0015, 0x080c, 0x417a, 0x20a3, 0x1104, 0x20a3,
-	0x0000, 0x3430, 0x2011, 0x978e, 0x080c, 0x41bd, 0x11a8, 0x7074,
-	0xa005, 0x1190, 0x7154, 0xa186, 0xffff, 0x0170, 0xa180, 0x2719,
-	0x200d, 0xa18c, 0xff00, 0x810f, 0x080c, 0x4074, 0x0128, 0x080c,
-	0x3919, 0x0110, 0x080c, 0x2455, 0x20a9, 0x0008, 0x2298, 0x26a0,
+	0x080c, 0x4024, 0x0005, 0x00f6, 0x7080, 0xa005, 0x0500, 0x2011,
+	0x3fe7, 0x080c, 0x560d, 0xa086, 0x0014, 0x11b8, 0x2079, 0x9080,
+	0x7a30, 0xa296, 0x1103, 0x1188, 0x7834, 0xa005, 0x1170, 0x7a38,
+	0xd2fc, 0x0138, 0x70b0, 0xa005, 0x1120, 0x080c, 0x40d5, 0x70b3,
+	0x0001, 0x708b, 0x0006, 0x0029, 0x0010, 0x080c, 0x40ee, 0x00fe,
+	0x0005, 0x708b, 0x0007, 0x080c, 0x40a6, 0x20a3, 0x1104, 0x20a3,
+	0x0000, 0x3430, 0x2011, 0x908e, 0x080c, 0x40f5, 0x11a8, 0x7074,
+	0xa005, 0x1190, 0x7154, 0xa186, 0xffff, 0x0170, 0xa180, 0x263d,
+	0x200d, 0xa18c, 0xff00, 0x810f, 0x080c, 0x3fab, 0x0128, 0x080c,
+	0x37ee, 0x0110, 0x080c, 0x2333, 0x20a9, 0x0008, 0x2298, 0x26a0,
 	0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c,
-	0x40ec, 0x0005, 0x00f6, 0x7080, 0xa005, 0x05a8, 0x2011, 0x40af,
-	0x080c, 0x5731, 0xa086, 0x0014, 0x1560, 0x2079, 0x9780, 0x7a30,
-	0xa296, 0x1105, 0x1530, 0x7834, 0x2011, 0x0100, 0xa21e, 0x1178,
-	0x7a38, 0xd2f4, 0x0110, 0x70cb, 0x0008, 0xd2fc, 0x0138, 0x70b0,
-	0xa005, 0x1120, 0x080c, 0x419d, 0x70b3, 0x0001, 0x0070, 0xa005,
-	0x1180, 0x7a38, 0xd2fc, 0x0138, 0x70b0, 0xa005, 0x1120, 0x080c,
-	0x419d, 0x70b3, 0x0001, 0x7087, 0x0000, 0x708b, 0x0016, 0x0029,
-	0x0010, 0x7083, 0x0000, 0x00fe, 0x0005, 0x20e1, 0x9080, 0x20e1,
-	0x4000, 0x2099, 0x9780, 0x20a1, 0x020b, 0x20a9, 0x000e, 0x53a6,
-	0x3430, 0x2011, 0x978e, 0x708b, 0x0017, 0x080c, 0x41bd, 0x1150,
-	0x7074, 0xa005, 0x1138, 0x080c, 0x3fea, 0x1170, 0xa085, 0x0001,
-	0x080c, 0x2455, 0x20a9, 0x0008, 0x2099, 0x978e, 0x26a0, 0x53a6,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x40ec,
-	0x0010, 0x080c, 0x3bfd, 0x0005, 0x00f6, 0x7080, 0xa005, 0x01b0,
-	0x2011, 0x40af, 0x080c, 0x5731, 0xa086, 0x0084, 0x1168, 0x2079,
-	0x9780, 0x7a30, 0xa296, 0x1106, 0x1138, 0x7834, 0xa005, 0x1120,
-	0x708b, 0x0018, 0x0029, 0x0010, 0x7083, 0x0000, 0x00fe, 0x0005,
-	0x708b, 0x0019, 0x080c, 0x417a, 0x20a3, 0x1106, 0x20a3, 0x0000,
-	0x3430, 0x2099, 0x978e, 0x2039, 0x970e, 0x27a0, 0x20a9, 0x0040,
-	0x53a3, 0x080c, 0x41bd, 0x11e8, 0x2728, 0x2514, 0x8207, 0xa084,
-	0x00ff, 0x8000, 0x2018, 0xa294, 0x00ff, 0x8007, 0xa205, 0x202a,
-	0x7050, 0x2310, 0x8214, 0xa2a0, 0x970e, 0x2414, 0xa38c, 0x0001,
-	0x0118, 0xa294, 0xff00, 0x0018, 0xa294, 0x00ff, 0x8007, 0xa215,
-	0x2222, 0x2798, 0x26a0, 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x60c3, 0x0084, 0x080c, 0x40ec, 0x0005, 0x00f6,
-	0x7080, 0xa005, 0x01d0, 0x2011, 0x40af, 0x080c, 0x5731, 0xa086,
-	0x0084, 0x1188, 0x2079, 0x9780, 0x7a30, 0xa296, 0x1107, 0x1158,
-	0x7834, 0xa005, 0x1140, 0x7087, 0x0001, 0x080c, 0x4160, 0x708b,
-	0x001a, 0x0029, 0x0010, 0x7083, 0x0000, 0x00fe, 0x0005, 0x708b,
-	0x001b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0x9780, 0x20a1,
-	0x020b, 0x7480, 0xa480, 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8,
-	0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0084, 0x080c, 0x40ec, 0x0005,
-	0x0005, 0x0005, 0x0086, 0x0096, 0x2029, 0x9252, 0x252c, 0x20a9,
-	0x0008, 0x2041, 0x970e, 0x28a0, 0x2099, 0x978e, 0x53a3, 0x20a9,
-	0x0008, 0x2011, 0x0007, 0xd5d4, 0x0110, 0x2011, 0x0000, 0x2800,
-	0xa200, 0x200c, 0xa1a6, 0xffff, 0x1148, 0xd5d4, 0x0110, 0x8210,
-	0x0008, 0x8211, 0x1f04, 0x3fff, 0x0804, 0x406c, 0x82ff, 0x1160,
-	0xd5d4, 0x0120, 0xa1a6, 0x3fff, 0x0d90, 0x0020, 0xa1a6, 0x3fff,
-	0x0904, 0x406c, 0xa18d, 0xc000, 0x20a9, 0x0010, 0x2019, 0x0001,
-	0xd5d4, 0x0110, 0x2019, 0x0010, 0x2120, 0xd5d4, 0x0110, 0x8423,
-	0x0008, 0x8424, 0x1240, 0xd5d4, 0x0110, 0x8319, 0x0008, 0x8318,
-	0x1f04, 0x4025, 0x04c8, 0x23a8, 0x2021, 0x0001, 0x8426, 0x8425,
-	0x1f04, 0x4037, 0x2328, 0x8529, 0xa2be, 0x0007, 0x0158, 0x0006,
-	0x2039, 0x0007, 0x2200, 0xa73a, 0x000e, 0x27a8, 0xa5a8, 0x0010,
-	0x1f04, 0x4046, 0x754e, 0xa5c8, 0x2719, 0x292d, 0xa5ac, 0x00ff,
-	0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x2435, 0x001e, 0x60e7,
-	0x0000, 0x65ea, 0x2018, 0x2304, 0xa405, 0x201a, 0x7077, 0x0001,
-	0x26a0, 0x2898, 0x20a9, 0x0008, 0x53a6, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0xa085, 0x0001, 0x0028, 0xa006, 0x0018, 0xa006, 0x080c,
-	0x13fe, 0x009e, 0x008e, 0x0005, 0x2118, 0x2021, 0x0000, 0x2001,
-	0x0007, 0xa39a, 0x0010, 0x0218, 0x8420, 0x8001, 0x0cd0, 0x2118,
-	0x84ff, 0x0120, 0xa39a, 0x0010, 0x8421, 0x1de0, 0x2021, 0x0001,
-	0x83ff, 0x0118, 0x8423, 0x8319, 0x1de8, 0xa238, 0x2704, 0xa42c,
-	0x11b0, 0xa405, 0x203a, 0x714e, 0xa1a0, 0x2719, 0x242d, 0xa5ac,
-	0x00ff, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x2435, 0x001e,
+	0x4024, 0x0005, 0x00f6, 0x7080, 0xa005, 0x0500, 0x2011, 0x3fe7,
+	0x080c, 0x560d, 0xa086, 0x0014, 0x11b8, 0x2079, 0x9080, 0x7a30,
+	0xa296, 0x1104, 0x1188, 0x7834, 0xa005, 0x1170, 0x7a38, 0xd2fc,
+	0x0138, 0x70b0, 0xa005, 0x1120, 0x080c, 0x40d5, 0x70b3, 0x0001,
+	0x708b, 0x0008, 0x0029, 0x0010, 0x080c, 0x40ee, 0x00fe, 0x0005,
+	0x708b, 0x0009, 0x080c, 0x40a6, 0x20a3, 0x1105, 0x20a3, 0x0100,
+	0x3430, 0x080c, 0x40f5, 0x1150, 0x7074, 0xa005, 0x1138, 0x080c,
+	0x3f20, 0x1170, 0xa085, 0x0001, 0x080c, 0x2333, 0x20a9, 0x0008,
+	0x2099, 0x908e, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000,
+	0x60c3, 0x0014, 0x080c, 0x4024, 0x0010, 0x080c, 0x3b32, 0x0005,
+	0x00f6, 0x7080, 0xa005, 0x05a8, 0x2011, 0x3fe7, 0x080c, 0x560d,
+	0xa086, 0x0014, 0x1560, 0x2079, 0x9080, 0x7a30, 0xa296, 0x1105,
+	0x1530, 0x7834, 0x2011, 0x0100, 0xa21e, 0x1170, 0x7a38, 0xd2fc,
+	0x0138, 0x70b0, 0xa005, 0x1120, 0x080c, 0x40d5, 0x70b3, 0x0001,
+	0x708b, 0x000a, 0x00c1, 0x00a8, 0xa005, 0x1188, 0x7a38, 0xd2fc,
+	0x0138, 0x70b0, 0xa005, 0x1120, 0x080c, 0x40d5, 0x70b3, 0x0001,
+	0x7087, 0x0000, 0x708b, 0x000e, 0x080c, 0x3d35, 0x0010, 0x080c,
+	0x40ee, 0x00fe, 0x0005, 0x708b, 0x000b, 0x2011, 0x900e, 0x22a0,
+	0x20a9, 0x0040, 0x2019, 0xffff, 0x43a4, 0x20a9, 0x0002, 0x2009,
+	0x0000, 0x41a4, 0x080c, 0x40a6, 0x20a3, 0x1106, 0x20a3, 0x0000,
+	0x080c, 0x40f5, 0x0118, 0x2013, 0x0000, 0x0020, 0x7050, 0xa085,
+	0x0100, 0x2012, 0x2298, 0x20a9, 0x0042, 0x53a6, 0x60c3, 0x0084,
+	0x080c, 0x4024, 0x0005, 0x00f6, 0x7080, 0xa005, 0x01b0, 0x2011,
+	0x3fe7, 0x080c, 0x560d, 0xa086, 0x0084, 0x1168, 0x2079, 0x9080,
+	0x7a30, 0xa296, 0x1106, 0x1138, 0x7834, 0xa005, 0x1120, 0x708b,
+	0x000c, 0x0029, 0x0010, 0x080c, 0x40ee, 0x00fe, 0x0005, 0x708b,
+	0x000d, 0x080c, 0x40a6, 0x20a3, 0x1107, 0x20a3, 0x0000, 0x2099,
+	0x908e, 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000,
+	0x60c3, 0x0084, 0x080c, 0x4024, 0x0005, 0x00f6, 0x7080, 0xa005,
+	0x01d0, 0x2011, 0x3fe7, 0x080c, 0x560d, 0xa086, 0x0084, 0x1188,
+	0x2079, 0x9080, 0x7a30, 0xa296, 0x1107, 0x1158, 0x7834, 0xa005,
+	0x1140, 0x7087, 0x0001, 0x080c, 0x4098, 0x708b, 0x000e, 0x0029,
+	0x0010, 0x080c, 0x40ee, 0x00fe, 0x0005, 0x708b, 0x000f, 0x7083,
+	0x0000, 0x608b, 0xbc85, 0x608f, 0xb5b5, 0x6043, 0x0005, 0x6043,
+	0x0004, 0x2009, 0x07d0, 0x2011, 0x3fe7, 0x080c, 0x5601, 0x0005,
+	0x7080, 0xa005, 0x0120, 0x2011, 0x3fe7, 0x080c, 0x560d, 0x0005,
+	0x708b, 0x0011, 0x716c, 0x81ff, 0x0170, 0x2009, 0x0000, 0x7070,
+	0xa084, 0x00ff, 0x080c, 0x22e9, 0xa186, 0x0080, 0x0120, 0x2011,
+	0x908e, 0x080c, 0x3fab, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099,
+	0x9080, 0x20a1, 0x020b, 0x7480, 0xa480, 0x0018, 0xa080, 0x0007,
+	0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0014, 0x080c,
+	0x4024, 0x0005, 0x00f6, 0x7080, 0xa005, 0x0500, 0x2011, 0x3fe7,
+	0x080c, 0x560d, 0xa086, 0x0014, 0x11b8, 0x2079, 0x9080, 0x7a30,
+	0xa296, 0x1103, 0x1188, 0x7834, 0xa005, 0x1170, 0x7a38, 0xd2fc,
+	0x0138, 0x70b0, 0xa005, 0x1120, 0x080c, 0x40d5, 0x70b3, 0x0001,
+	0x708b, 0x0012, 0x0029, 0x0010, 0x7083, 0x0000, 0x00fe, 0x0005,
+	0x708b, 0x0013, 0x080c, 0x40b2, 0x20a3, 0x1103, 0x20a3, 0x0000,
+	0x3430, 0x2011, 0x908e, 0x080c, 0x40f5, 0x1160, 0x7074, 0xa005,
+	0x1148, 0x714c, 0xa186, 0xffff, 0x0128, 0x080c, 0x3fab, 0x0110,
+	0x080c, 0x40d5, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3,
+	0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4024, 0x0005,
+	0x00f6, 0x7080, 0xa005, 0x0500, 0x2011, 0x3fe7, 0x080c, 0x560d,
+	0xa086, 0x0014, 0x11b8, 0x2079, 0x9080, 0x7a30, 0xa296, 0x1104,
+	0x1188, 0x7834, 0xa005, 0x1170, 0x7a38, 0xd2fc, 0x0138, 0x70b0,
+	0xa005, 0x1120, 0x080c, 0x40d5, 0x70b3, 0x0001, 0x708b, 0x0014,
+	0x0029, 0x0010, 0x7083, 0x0000, 0x00fe, 0x0005, 0x708b, 0x0015,
+	0x080c, 0x40b2, 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011,
+	0x908e, 0x080c, 0x40f5, 0x11a8, 0x7074, 0xa005, 0x1190, 0x7154,
+	0xa186, 0xffff, 0x0170, 0xa180, 0x263d, 0x200d, 0xa18c, 0xff00,
+	0x810f, 0x080c, 0x3fab, 0x0128, 0x080c, 0x37ee, 0x0110, 0x080c,
+	0x2333, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000,
+	0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4024, 0x0005, 0x00f6,
+	0x7080, 0xa005, 0x05b0, 0x2011, 0x3fe7, 0x080c, 0x560d, 0xa086,
+	0x0014, 0x1568, 0x2079, 0x9080, 0x7a30, 0xa296, 0x1105, 0x1538,
+	0x7834, 0x2011, 0x0100, 0xa21e, 0x1158, 0x7a38, 0xd2fc, 0x0138,
+	0x70b0, 0xa005, 0x1120, 0x080c, 0x40d5, 0x70b3, 0x0001, 0x0070,
+	0xa005, 0x11a8, 0x7a38, 0xd2fc, 0x0138, 0x70b0, 0xa005, 0x1120,
+	0x080c, 0x40d5, 0x70b3, 0x0001, 0x7087, 0x0000, 0x7a38, 0xd2f4,
+	0x0110, 0x70cb, 0x0008, 0x708b, 0x0016, 0x0029, 0x0010, 0x7083,
+	0x0000, 0x00fe, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099,
+	0x9080, 0x20a1, 0x020b, 0x20a9, 0x000e, 0x53a6, 0x3430, 0x2011,
+	0x908e, 0x708b, 0x0017, 0x080c, 0x40f5, 0x1150, 0x7074, 0xa005,
+	0x1138, 0x080c, 0x3f20, 0x1170, 0xa085, 0x0001, 0x080c, 0x2333,
+	0x20a9, 0x0008, 0x2099, 0x908e, 0x26a0, 0x53a6, 0x20a3, 0x0000,
+	0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4024, 0x0010, 0x080c,
+	0x3b32, 0x0005, 0x00f6, 0x7080, 0xa005, 0x01b0, 0x2011, 0x3fe7,
+	0x080c, 0x560d, 0xa086, 0x0084, 0x1168, 0x2079, 0x9080, 0x7a30,
+	0xa296, 0x1106, 0x1138, 0x7834, 0xa005, 0x1120, 0x708b, 0x0018,
+	0x0029, 0x0010, 0x7083, 0x0000, 0x00fe, 0x0005, 0x708b, 0x0019,
+	0x080c, 0x40b2, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x3430, 0x2099,
+	0x908e, 0x2039, 0x900e, 0x27a0, 0x20a9, 0x0040, 0x53a3, 0x080c,
+	0x40f5, 0x11e8, 0x2728, 0x2514, 0x8207, 0xa084, 0x00ff, 0x8000,
+	0x2018, 0xa294, 0x00ff, 0x8007, 0xa205, 0x202a, 0x7050, 0x2310,
+	0x8214, 0xa2a0, 0x900e, 0x2414, 0xa38c, 0x0001, 0x0118, 0xa294,
+	0xff00, 0x0018, 0xa294, 0x00ff, 0x8007, 0xa215, 0x2222, 0x2798,
+	0x26a0, 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000,
+	0x60c3, 0x0084, 0x080c, 0x4024, 0x0005, 0x00f6, 0x7080, 0xa005,
+	0x01d0, 0x2011, 0x3fe7, 0x080c, 0x560d, 0xa086, 0x0084, 0x1188,
+	0x2079, 0x9080, 0x7a30, 0xa296, 0x1107, 0x1158, 0x7834, 0xa005,
+	0x1140, 0x7087, 0x0001, 0x080c, 0x4098, 0x708b, 0x001a, 0x0029,
+	0x0010, 0x7083, 0x0000, 0x00fe, 0x0005, 0x708b, 0x001b, 0x20e1,
+	0x9080, 0x20e1, 0x4000, 0x2099, 0x9080, 0x20a1, 0x020b, 0x7480,
+	0xa480, 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8,
+	0x53a6, 0x60c3, 0x0084, 0x080c, 0x4024, 0x0005, 0x0005, 0x0005,
+	0x0086, 0x0096, 0x2029, 0x8b52, 0x252c, 0x20a9, 0x0008, 0x2041,
+	0x900e, 0x28a0, 0x2099, 0x908e, 0x53a3, 0x20a9, 0x0008, 0x2011,
+	0x0007, 0xd5d4, 0x0110, 0x2011, 0x0000, 0x2800, 0xa200, 0x200c,
+	0xa1a6, 0xffff, 0x1148, 0xd5d4, 0x0110, 0x8210, 0x0008, 0x8211,
+	0x1f04, 0x3f35, 0x0804, 0x3fa3, 0x82ff, 0x1160, 0xd5d4, 0x0120,
+	0xa1a6, 0x3fff, 0x0d90, 0x0020, 0xa1a6, 0x3fff, 0x0904, 0x3fa3,
+	0xa18d, 0xc000, 0x20a9, 0x0010, 0x2019, 0x0001, 0xd5d4, 0x0110,
+	0x2019, 0x0010, 0x2120, 0xd5d4, 0x0110, 0x8423, 0x0008, 0x8424,
+	0x1240, 0xd5d4, 0x0110, 0x8319, 0x0008, 0x8318, 0x1f04, 0x3f5b,
+	0x04d0, 0x23a8, 0x2021, 0x0001, 0x8426, 0x8425, 0x1f04, 0x3f6d,
+	0x2328, 0x8529, 0xa2be, 0x0007, 0x0158, 0x0006, 0x2039, 0x0007,
+	0x2200, 0xa73a, 0x000e, 0x27a8, 0xa5a8, 0x0010, 0x1f04, 0x3f7c,
+	0x754e, 0xa5c8, 0x263d, 0x292d, 0xa5ac, 0x00ff, 0x7572, 0x6532,
+	0x6536, 0x0016, 0x2508, 0x080c, 0x2313, 0x001e, 0x60e7, 0x0000,
+	0x65ea, 0x2018, 0x2304, 0xa405, 0x201a, 0x7077, 0x0001, 0x26a0,
+	0x2898, 0x20a9, 0x0008, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000,
+	0xa085, 0x0001, 0x0028, 0xa006, 0x0018, 0xa006, 0x080c, 0x1410,
+	0x009e, 0x008e, 0x0005, 0x2118, 0x2021, 0x0000, 0x2001, 0x0007,
+	0xa39a, 0x0010, 0x0218, 0x8420, 0x8001, 0x0cd0, 0x2118, 0x84ff,
+	0x0120, 0xa39a, 0x0010, 0x8421, 0x1de0, 0x2021, 0x0001, 0x83ff,
+	0x0118, 0x8423, 0x8319, 0x1de8, 0xa238, 0x2704, 0xa42c, 0x11b8,
+	0xa405, 0x203a, 0x714e, 0xa1a0, 0x263d, 0x242d, 0xa5ac, 0x00ff,
+	0x7572, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x2313, 0x001e,
 	0x60e7, 0x0000, 0x65ea, 0x7077, 0x0001, 0xa084, 0x0000, 0x0005,
-	0x00e6, 0x2071, 0x9200, 0x707b, 0x0000, 0x00ee, 0x0005, 0x00e6,
-	0x00f6, 0x2079, 0x0100, 0x2071, 0x0140, 0x080c, 0x6f1e, 0x7004,
+	0x00e6, 0x2071, 0x8b00, 0x707b, 0x0000, 0x00ee, 0x0005, 0x00e6,
+	0x00f6, 0x2079, 0x0100, 0x2071, 0x0140, 0x080c, 0x66f7, 0x7004,
 	0xa084, 0x4000, 0x0120, 0x7003, 0x1000, 0x7003, 0x0000, 0x080c,
-	0x4dcd, 0x01b0, 0x080c, 0x4deb, 0x1198, 0x2001, 0x94d7, 0x2003,
-	0xaaaa, 0x2001, 0x0204, 0x2004, 0x0016, 0x2009, 0x94c8, 0x200a,
-	0x001e, 0x2001, 0x94d8, 0x2003, 0x0000, 0x080c, 0x4d10, 0x0080,
-	0x0126, 0x2091, 0x8000, 0x2071, 0x9222, 0x2073, 0x0000, 0x7840,
+	0x4c4a, 0x01b0, 0x080c, 0x4c68, 0x1198, 0x2001, 0x8d9c, 0x2003,
+	0xaaaa, 0x2001, 0x0204, 0x2004, 0x0016, 0x2009, 0x8d8d, 0x200a,
+	0x001e, 0x2001, 0x8d9d, 0x2003, 0x0000, 0x080c, 0x4b8b, 0x0080,
+	0x0126, 0x2091, 0x8000, 0x2071, 0x8b22, 0x2073, 0x0000, 0x7840,
 	0x0026, 0xa094, 0x0010, 0xa285, 0x0080, 0x7842, 0x7a42, 0x002e,
 	0x012e, 0x00fe, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x2011,
-	0x94ef, 0x2013, 0x0000, 0x7083, 0x0000, 0x012e, 0x20e1, 0x9080,
-	0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x6f15, 0x2009, 0x07d0,
-	0x2011, 0x40af, 0x080c, 0x57b3, 0x0005, 0x0016, 0x0026, 0x00c6,
-	0x0126, 0x2091, 0x8000, 0x2009, 0x00f7, 0x080c, 0x4186, 0x2061,
-	0x94f8, 0x601b, 0x0000, 0x601f, 0x0000, 0x2061, 0x9200, 0x6003,
+	0x8db4, 0x2013, 0x0000, 0x7083, 0x0000, 0x012e, 0x20e1, 0x9080,
+	0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x66ee, 0x2009, 0x07d0,
+	0x2011, 0x3fe7, 0x080c, 0x568c, 0x0005, 0x0016, 0x0026, 0x00c6,
+	0x0126, 0x2091, 0x8000, 0x2009, 0x00f7, 0x080c, 0x40be, 0x2061,
+	0x8dbd, 0x601b, 0x0000, 0x601f, 0x0000, 0x2061, 0x8b00, 0x6003,
 	0x0001, 0x2061, 0x0100, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009,
-	0x001e, 0x2011, 0x412a, 0x080c, 0x5725, 0x012e, 0x00ce, 0x002e,
+	0x001e, 0x2011, 0x4062, 0x080c, 0x5601, 0x012e, 0x00ce, 0x002e,
 	0x001e, 0x0005, 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071,
-	0x0100, 0x080c, 0x6f1e, 0x2071, 0x0140, 0x7004, 0xa084, 0x4000,
-	0x0120, 0x7003, 0x1000, 0x7003, 0x0000, 0x080c, 0x4dcd, 0x01b0,
-	0x080c, 0x4deb, 0x1198, 0x2001, 0x94d7, 0x2003, 0xaaaa, 0x2001,
-	0x0204, 0x2004, 0x0016, 0x2009, 0x94c8, 0x200a, 0x001e, 0x2001,
-	0x94d8, 0x2003, 0x0000, 0x080c, 0x4d10, 0x0030, 0x2001, 0x0001,
-	0x080c, 0x23ba, 0x080c, 0x4105, 0x012e, 0x000e, 0x00ee, 0x0005,
-	0x20a9, 0x0040, 0x20a1, 0x98c0, 0x2099, 0x978e, 0x3304, 0x8007,
-	0x20a2, 0x9398, 0x94a0, 0x1f04, 0x4166, 0x0005, 0x20e1, 0x9080,
-	0x20e1, 0x4000, 0x2099, 0x9700, 0x20a1, 0x020b, 0x20a9, 0x000c,
-	0x53a6, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0x9780,
+	0x0100, 0x080c, 0x66f7, 0x2071, 0x0140, 0x7004, 0xa084, 0x4000,
+	0x0120, 0x7003, 0x1000, 0x7003, 0x0000, 0x080c, 0x4c4a, 0x01b0,
+	0x080c, 0x4c68, 0x1198, 0x2001, 0x8d9c, 0x2003, 0xaaaa, 0x2001,
+	0x0204, 0x2004, 0x0016, 0x2009, 0x8d8d, 0x200a, 0x001e, 0x2001,
+	0x8d9d, 0x2003, 0x0000, 0x080c, 0x4b8b, 0x0030, 0x2001, 0x0001,
+	0x080c, 0x2298, 0x080c, 0x403d, 0x012e, 0x000e, 0x00ee, 0x0005,
+	0x20a9, 0x0040, 0x20a1, 0x91c0, 0x2099, 0x908e, 0x3304, 0x8007,
+	0x20a2, 0x9398, 0x94a0, 0x1f04, 0x409e, 0x0005, 0x20e1, 0x9080,
+	0x20e1, 0x4000, 0x2099, 0x9000, 0x20a1, 0x020b, 0x20a9, 0x000c,
+	0x53a6, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0x9080,
 	0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, 0x0005, 0x00c6, 0x0006,
-	0x2061, 0x0100, 0x810f, 0x2001, 0x922f, 0x2004, 0xa005, 0x1138,
-	0x2001, 0x9214, 0x2004, 0xa084, 0x00ff, 0xa105, 0x0010, 0xa185,
+	0x2061, 0x0100, 0x810f, 0x2001, 0x8b2f, 0x2004, 0xa005, 0x1138,
+	0x2001, 0x8b14, 0x2004, 0xa084, 0x00ff, 0xa105, 0x0010, 0xa185,
 	0x00f7, 0x604a, 0x000e, 0x00ce, 0x0005, 0x0016, 0x0046, 0x2001,
-	0x9252, 0x2004, 0xd0a4, 0x0158, 0xa006, 0x2020, 0x2009, 0x002a,
-	0x080c, 0x90d7, 0x2001, 0x920c, 0x200c, 0xc195, 0x2102, 0x2019,
-	0x002a, 0x080c, 0x264b, 0x004e, 0x001e, 0x0005, 0x080c, 0x4105,
-	0x708b, 0x0000, 0x7083, 0x0000, 0x0005, 0x0006, 0x2001, 0x920c,
+	0x8b52, 0x2004, 0xd0a4, 0x0158, 0xa006, 0x2020, 0x2009, 0x002a,
+	0x080c, 0x8982, 0x2001, 0x8b0c, 0x200c, 0xc195, 0x2102, 0x2019,
+	0x002a, 0x080c, 0x2542, 0x004e, 0x001e, 0x0005, 0x080c, 0x403d,
+	0x708b, 0x0000, 0x7083, 0x0000, 0x0005, 0x0006, 0x2001, 0x8b0c,
 	0x2004, 0xd09c, 0x0100, 0x000e, 0x0005, 0x0006, 0x0016, 0x0126,
 	0x2091, 0x8000, 0x2001, 0x0101, 0x200c, 0xa18d, 0x0006, 0x2102,
 	0x012e, 0x001e, 0x000e, 0x0005, 0x0156, 0x20a9, 0x00ff, 0x2009,
-	0x936e, 0xa006, 0x200a, 0x8108, 0x1f04, 0x41da, 0x015e, 0x0005,
-	0x00d6, 0x0036, 0x0156, 0x0136, 0x0146, 0x2069, 0x9251, 0xa006,
-	0x6002, 0x6007, 0x0707, 0x600a, 0x600e, 0x6012, 0xa198, 0x2719,
+	0x8c34, 0xa006, 0x200a, 0x8108, 0x1f04, 0x4112, 0x015e, 0x0005,
+	0x00d6, 0x0036, 0x0156, 0x0136, 0x0146, 0x2069, 0x8b51, 0xa006,
+	0x6002, 0x6007, 0x0707, 0x600a, 0x600e, 0x6012, 0xa198, 0x263d,
 	0x231d, 0xa39c, 0x00ff, 0x6316, 0x20a9, 0x0004, 0xac98, 0x0006,
 	0x23a0, 0x40a4, 0x20a9, 0x0004, 0xac98, 0x000a, 0x23a0, 0x40a4,
 	0x603e, 0x6042, 0x604e, 0x6052, 0x6056, 0x605a, 0x605e, 0x6062,
 	0x6066, 0x606a, 0x606e, 0x6072, 0x6076, 0x607a, 0x607e, 0x6082,
 	0x6086, 0x608a, 0x608e, 0x6092, 0x6096, 0x609a, 0x609e, 0x61a2,
-	0x00d6, 0x60a4, 0xa06d, 0x0110, 0x080c, 0x1493, 0x60a7, 0x0000,
-	0x60a8, 0xa06d, 0x0110, 0x080c, 0x1493, 0x60ab, 0x0000, 0x00de,
-	0xa006, 0x604a, 0x6810, 0x603a, 0x680c, 0x6046, 0xa006, 0x60b2,
-	0x60ae, 0x60b6, 0x60bb, 0x0520, 0x6814, 0xa084, 0x00ff, 0x6042,
-	0x014e, 0x013e, 0x015e, 0x003e, 0x00de, 0x0005, 0x0126, 0x2091,
-	0x8000, 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082, 0x4000, 0x1a04,
-	0x42cf, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x1a04, 0x42d4,
-	0x2001, 0x920c, 0x2004, 0xa084, 0x0003, 0x1904, 0x42bd, 0xa188,
-	0x936e, 0x2104, 0xa065, 0x0904, 0x42a9, 0x6004, 0xa084, 0x00ff,
-	0xa08e, 0x0006, 0x1904, 0x42ae, 0x60a4, 0xa00d, 0x0118, 0x080c,
-	0x4630, 0x05d0, 0x60a8, 0xa00d, 0x0188, 0x080c, 0x467a, 0x1170,
-	0x694c, 0xd1fc, 0x1118, 0x080c, 0x43c4, 0x0448, 0x080c, 0x4386,
-	0x694c, 0xd1ec, 0x1520, 0x080c, 0x452b, 0x0408, 0x694c, 0xa184,
-	0xa000, 0x0178, 0xd1ec, 0x0140, 0xd1fc, 0x0118, 0x080c, 0x453a,
-	0x0028, 0x080c, 0x453a, 0x0028, 0xd1fc, 0x0118, 0x080c, 0x4386,
-	0x0070, 0x6050, 0xa00d, 0x0130, 0x2d00, 0x200a, 0x6803, 0x0000,
-	0x6052, 0x0028, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x080c,
-	0x6015, 0xa006, 0x012e, 0x0005, 0x2001, 0x0005, 0x2009, 0x0000,
-	0x0478, 0x2001, 0x0028, 0x2009, 0x0000, 0x0450, 0xa082, 0x0006,
-	0x1260, 0x2001, 0x9232, 0x2004, 0xd0ac, 0x1120, 0x60a0, 0xd0bc,
-	0x0904, 0x4264, 0x2001, 0x0028, 0x0078, 0x2009, 0x920c, 0x210c,
-	0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001,
-	0x0004, 0x0010, 0x2001, 0x0029, 0x2009, 0x0000, 0x0048, 0x2001,
-	0x0029, 0x2009, 0x0000, 0x0020, 0x2001, 0x0029, 0x2009, 0x0000,
-	0xa005, 0x012e, 0x0005, 0x00e6, 0x0126, 0x2091, 0x8000, 0x6844,
-	0x0006, 0x000e, 0x0006, 0x000e, 0xa084, 0xff00, 0xa08e, 0xff00,
-	0x1120, 0x2001, 0x94c6, 0x2064, 0x0098, 0x6844, 0x8007, 0xa084,
-	0x00ff, 0x2008, 0xa182, 0x00ff, 0x16c8, 0xa188, 0x936e, 0x2104,
-	0xa065, 0x01f0, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x11d8,
-	0x2c70, 0x080c, 0x749c, 0x0580, 0x2e00, 0x601a, 0x2d00, 0x6012,
-	0x601f, 0x0009, 0x600b, 0x0000, 0x6844, 0xa08e, 0xff00, 0x1110,
-	0x600b, 0x8000, 0x2009, 0x0100, 0x080c, 0x7518, 0xa006, 0x00c8,
-	0x2001, 0x0028, 0x00a8, 0xa082, 0x0006, 0x0e10, 0x2009, 0x920c,
-	0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118,
-	0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x0010, 0x2001, 0x0029,
-	0xa005, 0x012e, 0x00ee, 0x0005, 0x2001, 0x002c, 0x0cc8, 0x6944,
-	0x6e48, 0xa684, 0x3fff, 0xa082, 0x4000, 0x1678, 0xa18c, 0xff00,
-	0x810f, 0xa182, 0x00ff, 0x12e0, 0xa188, 0x936e, 0x2104, 0xa065,
-	0x01b8, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x11b0, 0x684c,
-	0xd0ec, 0x0120, 0x080c, 0x453a, 0x0489, 0x0030, 0x0479, 0x684c,
-	0xd0fc, 0x0110, 0x080c, 0x452b, 0x080c, 0x4578, 0xa006, 0x0088,
-	0x2001, 0x0028, 0x2009, 0x0000, 0x0060, 0xa082, 0x0006, 0x0e38,
-	0x2001, 0x0029, 0x2009, 0x0000, 0x0020, 0x2001, 0x0029, 0x2009,
-	0x0000, 0xa005, 0x0005, 0x0126, 0x2091, 0x8000, 0x6050, 0xa00d,
-	0x0138, 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, 0x012e, 0x0005,
-	0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x0cc0, 0x0126, 0x2091,
-	0x8000, 0x604c, 0xa005, 0x0170, 0x00e6, 0x2071, 0x94e5, 0x7004,
-	0xa086, 0x0002, 0x0168, 0x00ee, 0x604c, 0x6802, 0x2d00, 0x604e,
-	0x012e, 0x0005, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x0cc0,
-	0x701c, 0xac06, 0x1d80, 0x604c, 0x2070, 0x7000, 0x6802, 0x2d00,
-	0x7002, 0x00ee, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x604c,
-	0xa06d, 0x0130, 0x6800, 0xa005, 0x1108, 0x6052, 0x604e, 0xad05,
-	0x012e, 0x0005, 0x604c, 0xa06d, 0x0130, 0x6800, 0xa005, 0x1108,
-	0x6052, 0x604e, 0xad05, 0x0005, 0x6803, 0x0000, 0x6084, 0xa00d,
-	0x0120, 0x2d00, 0x200a, 0x6086, 0x0005, 0x2d00, 0x6086, 0x6082,
-	0x0cd8, 0x0126, 0x00c6, 0x0026, 0x2091, 0x8000, 0x6218, 0x2260,
-	0x6200, 0xa005, 0x0110, 0xc285, 0x0008, 0xc284, 0x6202, 0x002e,
-	0x00ce, 0x012e, 0x0005, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6218,
-	0x2260, 0x6204, 0xa294, 0xff00, 0xa215, 0x6206, 0x00ce, 0x012e,
+	0x00d6, 0x60a4, 0xa06d, 0x0110, 0x080c, 0x149f, 0x60a7, 0x0000,
+	0x60a8, 0xa06d, 0x0110, 0x080c, 0x149f, 0x60ab, 0x0000, 0x00de,
+	0xa006, 0x604a, 0x6810, 0x603a, 0x680c, 0x6046, 0x6814, 0xa084,
+	0x00ff, 0x6042, 0x014e, 0x013e, 0x015e, 0x003e, 0x00de, 0x0005,
+	0x0126, 0x2091, 0x8000, 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082,
+	0x4000, 0x1a04, 0x4201, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff,
+	0x1a04, 0x4206, 0x2001, 0x8b0c, 0x2004, 0xa084, 0x0003, 0x1904,
+	0x41ef, 0xa188, 0x8c34, 0x2104, 0xa065, 0x0904, 0x41db, 0x6004,
+	0xa084, 0x00ff, 0xa08e, 0x0006, 0x1904, 0x41e0, 0x60a4, 0xa00d,
+	0x0118, 0x080c, 0x4509, 0x05d0, 0x60a8, 0xa00d, 0x0188, 0x080c,
+	0x4553, 0x1170, 0x694c, 0xd1fc, 0x1118, 0x080c, 0x429a, 0x0448,
+	0x080c, 0x425c, 0x694c, 0xd1ec, 0x1520, 0x080c, 0x4404, 0x0408,
+	0x694c, 0xa184, 0xa000, 0x0178, 0xd1ec, 0x0140, 0xd1fc, 0x0118,
+	0x080c, 0x4413, 0x0028, 0x080c, 0x4413, 0x0028, 0xd1fc, 0x0118,
+	0x080c, 0x425c, 0x0070, 0x6050, 0xa00d, 0x0130, 0x2d00, 0x200a,
+	0x6803, 0x0000, 0x6052, 0x0028, 0x2d00, 0x6052, 0x604e, 0x6803,
+	0x0000, 0x080c, 0x58b9, 0xa006, 0x012e, 0x0005, 0x2001, 0x0005,
+	0x2009, 0x0000, 0x0478, 0x2001, 0x0028, 0x2009, 0x0000, 0x0450,
+	0xa082, 0x0006, 0x1260, 0x2001, 0x8b32, 0x2004, 0xd0ac, 0x1120,
+	0x60a0, 0xd0bc, 0x0904, 0x4196, 0x2001, 0x0028, 0x0078, 0x2009,
+	0x8b0c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184,
+	0x0118, 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x2009, 0x0000,
+	0x0048, 0x2001, 0x0029, 0x2009, 0x0000, 0x0020, 0x2001, 0x0029,
+	0x2009, 0x0000, 0xa005, 0x012e, 0x0005, 0x6944, 0x6e48, 0xa684,
+	0x3fff, 0xa082, 0x4000, 0x1678, 0xa18c, 0xff00, 0x810f, 0xa182,
+	0x00ff, 0x12e0, 0xa188, 0x8c34, 0x2104, 0xa065, 0x01b8, 0x6004,
+	0xa084, 0x00ff, 0xa08e, 0x0006, 0x11b0, 0x684c, 0xd0ec, 0x0120,
+	0x080c, 0x4413, 0x0489, 0x0030, 0x0479, 0x684c, 0xd0fc, 0x0110,
+	0x080c, 0x4404, 0x080c, 0x4451, 0xa006, 0x0088, 0x2001, 0x0028,
+	0x2009, 0x0000, 0x0060, 0xa082, 0x0006, 0x0e38, 0x2001, 0x0029,
+	0x2009, 0x0000, 0x0020, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005,
+	0x0005, 0x0126, 0x2091, 0x8000, 0x6050, 0xa00d, 0x0138, 0x2d00,
+	0x200a, 0x6803, 0x0000, 0x6052, 0x012e, 0x0005, 0x2d00, 0x6052,
+	0x604e, 0x6803, 0x0000, 0x0cc0, 0x0126, 0x2091, 0x8000, 0x604c,
+	0xa005, 0x0170, 0x00e6, 0x2071, 0x8daa, 0x7004, 0xa086, 0x0002,
+	0x0168, 0x00ee, 0x604c, 0x6802, 0x2d00, 0x604e, 0x012e, 0x0005,
+	0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x0cc0, 0x701c, 0xac06,
+	0x1d80, 0x604c, 0x2070, 0x7000, 0x6802, 0x2d00, 0x7002, 0x00ee,
+	0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x604c, 0xa06d, 0x0130,
+	0x6800, 0xa005, 0x1108, 0x6052, 0x604e, 0xad05, 0x012e, 0x0005,
+	0x604c, 0xa06d, 0x0130, 0x6800, 0xa005, 0x1108, 0x6052, 0x604e,
+	0xad05, 0x0005, 0x6803, 0x0000, 0x6084, 0xa00d, 0x0120, 0x2d00,
+	0x200a, 0x6086, 0x0005, 0x2d00, 0x6086, 0x6082, 0x0cd8, 0x0126,
+	0x00c6, 0x0026, 0x2091, 0x8000, 0x6218, 0x2260, 0x6200, 0xa005,
+	0x0110, 0xc285, 0x0008, 0xc284, 0x6202, 0x002e, 0x00ce, 0x012e,
 	0x0005, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6218, 0x2260, 0x6204,
-	0xa294, 0x00ff, 0x8007, 0xa215, 0x6206, 0x00ce, 0x012e, 0x0005,
-	0x0026, 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001, 0x00b0, 0xa190,
-	0x936e, 0x2204, 0xa065, 0x1180, 0x0016, 0x00d6, 0x080c, 0x145f,
-	0x2d60, 0x00de, 0x001e, 0x0d80, 0x2c00, 0x2012, 0x60a7, 0x0000,
-	0x60ab, 0x0000, 0x080c, 0x41e0, 0xa006, 0x002e, 0x0005, 0x0026,
-	0xa182, 0x00ff, 0x0218, 0xa085, 0x0001, 0x0060, 0x00d6, 0xa190,
-	0x936e, 0x2204, 0xa06d, 0x0120, 0x2013, 0x0000, 0x080c, 0x1493,
-	0x00de, 0xa006, 0x002e, 0x0005, 0x0016, 0xa182, 0x00ff, 0x0218,
-	0xa085, 0x0001, 0x0030, 0xa188, 0x936e, 0x2104, 0xa065, 0x0dc0,
-	0xa006, 0x001e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x600b,
-	0x0000, 0x600f, 0x0000, 0x6000, 0xc08c, 0x6002, 0x080c, 0x4dc5,
-	0x1520, 0x60a0, 0xa086, 0x007e, 0x2069, 0x9790, 0x0130, 0x2001,
-	0x9232, 0x2004, 0xd0ac, 0x11c8, 0x0098, 0x2d04, 0xd0e4, 0x01a8,
-	0x00d6, 0x2069, 0x978e, 0x00c6, 0x2061, 0x94d9, 0x6810, 0x2062,
-	0x6814, 0x6006, 0x6818, 0x600a, 0x681c, 0x600e, 0x00ce, 0x00de,
-	0x8d69, 0x2d04, 0x2069, 0x0140, 0x6886, 0x2069, 0x978e, 0x6808,
-	0x605e, 0x6810, 0x6062, 0x6138, 0xa10a, 0x0208, 0x603a, 0x6814,
-	0x6066, 0x2099, 0x9796, 0xac88, 0x000a, 0x21a0, 0x20a9, 0x0004,
-	0x53a3, 0x2099, 0x979a, 0xac88, 0x0006, 0x21a0, 0x20a9, 0x0004,
-	0x53a3, 0x2069, 0x97ae, 0x6808, 0x606a, 0x690c, 0x616e, 0x6810,
-	0x6072, 0x6818, 0x6076, 0xa182, 0x0211, 0x1218, 0x2009, 0x0008,
-	0x0400, 0xa182, 0x0259, 0x1218, 0x2009, 0x0007, 0x00d0, 0xa182,
-	0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, 0xa182, 0x0349, 0x1218,
-	0x2009, 0x0005, 0x0070, 0xa182, 0x0421, 0x1218, 0x2009, 0x0004,
-	0x0040, 0xa182, 0x0581, 0x1218, 0x2009, 0x0003, 0x0010, 0x2009,
-	0x0002, 0x6192, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x00e6,
-	0x2071, 0x978d, 0x2e04, 0x6896, 0x2071, 0x978e, 0x7004, 0x689a,
-	0x701c, 0x689e, 0x00ee, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000,
-	0x60a4, 0xa06d, 0x01c0, 0x6900, 0x81ff, 0x1540, 0x6a04, 0xa282,
-	0x0010, 0x1648, 0xad88, 0x0004, 0x20a9, 0x0010, 0x2104, 0xa086,
-	0xffff, 0x0128, 0x8108, 0x1f04, 0x44e6, 0x080c, 0x13fe, 0x260a,
-	0x8210, 0x6a06, 0x0098, 0x080c, 0x145f, 0x01a8, 0x2d00, 0x60a6,
-	0x6803, 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff,
-	0x8108, 0x1f04, 0x44fe, 0x6807, 0x0001, 0x6e12, 0xa085, 0x0001,
-	0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8, 0x0126, 0x2091, 0x8000,
-	0x00d6, 0x60a4, 0xa00d, 0x01a0, 0x2168, 0x6800, 0xa005, 0x1160,
-	0x080c, 0x4630, 0x1168, 0x200b, 0xffff, 0x6804, 0xa08a, 0x0002,
-	0x0218, 0x8001, 0x6806, 0x0020, 0x080c, 0x1493, 0x60a7, 0x0000,
-	0x00de, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x468d,
-	0x0010, 0x080c, 0x4373, 0x080c, 0x45af, 0x1dd8, 0x080c, 0x4578,
-	0x012e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a8, 0xa06d,
-	0x01c0, 0x6950, 0x81ff, 0x1540, 0x6a54, 0xa282, 0x0010, 0x1670,
-	0xad88, 0x0018, 0x20a9, 0x0010, 0x2104, 0xa086, 0xffff, 0x0128,
-	0x8108, 0x1f04, 0x454c, 0x080c, 0x13fe, 0x260a, 0x8210, 0x6a56,
-	0x0098, 0x080c, 0x145f, 0x01d0, 0x2d00, 0x60aa, 0x6853, 0x0000,
-	0xad88, 0x0018, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, 0x1f04,
-	0x4564, 0x6857, 0x0001, 0x6e62, 0x0010, 0x080c, 0x43c4, 0x0089,
-	0x1de0, 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8,
-	0x0126, 0x2091, 0x8000, 0x080c, 0x6015, 0x012e, 0x0005, 0xa01e,
-	0x0010, 0x2019, 0x0001, 0xa00e, 0x0126, 0x2091, 0x8000, 0x604c,
-	0x2068, 0x6000, 0xd0dc, 0x1170, 0x8dff, 0x01e8, 0x83ff, 0x0120,
-	0x6848, 0xa606, 0x0158, 0x0030, 0x683c, 0xa406, 0x1118, 0x6840,
-	0xa506, 0x0120, 0x2d08, 0x6800, 0x2068, 0x0c70, 0x6a00, 0x604c,
-	0xad06, 0x1110, 0x624e, 0x0018, 0xa180, 0x0000, 0x2202, 0x82ff,
-	0x1110, 0x6152, 0x8dff, 0x012e, 0x0005, 0xa01e, 0x0010, 0x2019,
-	0x0001, 0xa00e, 0x6080, 0x2068, 0x8dff, 0x01e8, 0x83ff, 0x0120,
-	0x6848, 0xa606, 0x0158, 0x0030, 0x683c, 0xa406, 0x1118, 0x6840,
-	0xa506, 0x0120, 0x2d08, 0x6800, 0x2068, 0x0c70, 0x6a00, 0x6080,
-	0xad06, 0x1110, 0x6282, 0x0018, 0xa180, 0x0000, 0x2202, 0x82ff,
-	0x1110, 0x6186, 0x8dff, 0x0005, 0xa016, 0x080c, 0x462a, 0x1110,
-	0x2011, 0x0001, 0x080c, 0x4674, 0x1110, 0xa295, 0x0002, 0x0005,
-	0x080c, 0x46a5, 0x0118, 0x080c, 0x83ab, 0x0010, 0xa085, 0x0001,
-	0x0005, 0x080c, 0x46a5, 0x0118, 0x080c, 0x8338, 0x0010, 0xa085,
-	0x0001, 0x0005, 0x080c, 0x46a5, 0x0118, 0x080c, 0x837e, 0x0010,
-	0xa085, 0x0001, 0x0005, 0x080c, 0x46a5, 0x0118, 0x080c, 0x8352,
-	0x0010, 0xa085, 0x0001, 0x0005, 0x080c, 0x46a5, 0x0118, 0x080c,
-	0x83d8, 0x0010, 0xa085, 0x0001, 0x0005, 0x0126, 0x0006, 0x00d6,
-	0x2091, 0x8000, 0x6080, 0xa06d, 0x0168, 0x6800, 0x0006, 0x6837,
-	0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x8527, 0x080c, 0x4809,
-	0x000e, 0x0c88, 0x6083, 0x0000, 0x6087, 0x0000, 0x00de, 0x000e,
-	0x012e, 0x0005, 0x60a4, 0xa00d, 0x1118, 0xa085, 0x0001, 0x0005,
-	0x00e6, 0x2170, 0x7000, 0xa005, 0x1160, 0x20a9, 0x0010, 0xae88,
-	0x0004, 0x2104, 0xa606, 0x0128, 0x8108, 0x1f04, 0x4639, 0xa085,
-	0x0001, 0xa006, 0x00ee, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000,
-	0x60a4, 0xa06d, 0x1128, 0x080c, 0x145f, 0x01a0, 0x2d00, 0x60a6,
-	0x6803, 0x0001, 0x6807, 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010,
-	0x200b, 0xffff, 0x8108, 0x1f04, 0x4658, 0xa085, 0x0001, 0x012e,
-	0x00de, 0x0005, 0xa006, 0x0cd8, 0x00d6, 0x0126, 0x2091, 0x8000,
-	0x60a4, 0xa06d, 0x0130, 0x60a7, 0x0000, 0x080c, 0x1493, 0xa085,
-	0x0001, 0x012e, 0x00de, 0x0005, 0x60a8, 0xa00d, 0x1118, 0xa085,
-	0x0001, 0x0005, 0x00e6, 0x2170, 0x7050, 0xa005, 0x1160, 0x20a9,
-	0x0010, 0xae88, 0x0018, 0x2104, 0xa606, 0x0128, 0x8108, 0x1f04,
-	0x4683, 0xa085, 0x0001, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000,
-	0x0c19, 0x1188, 0x200b, 0xffff, 0x00d6, 0x60a8, 0x2068, 0x6854,
-	0xa08a, 0x0002, 0x0218, 0x8001, 0x6856, 0x0020, 0x080c, 0x1493,
-	0x60ab, 0x0000, 0x00de, 0x012e, 0x0005, 0x609c, 0xd0a4, 0x0005,
-	0x00f6, 0x2079, 0x9251, 0x7804, 0xd0a4, 0x0518, 0x0156, 0x00c6,
-	0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x4434, 0x1168,
-	0x6004, 0xa084, 0xff00, 0x8007, 0xa096, 0x0004, 0x0118, 0xa086,
-	0x0006, 0x1118, 0x6000, 0xc0ed, 0x6002, 0x001e, 0x8108, 0x1f04,
-	0x46b4, 0x00ce, 0x015e, 0x2009, 0x07d0, 0x2011, 0x46d3, 0x080c,
-	0x57b3, 0x00fe, 0x0005, 0x2011, 0x46d3, 0x080c, 0x5731, 0x0156,
-	0x00c6, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x4434,
-	0x1530, 0x6000, 0xd0ec, 0x0518, 0x0046, 0x62a0, 0xa294, 0x00ff,
-	0x8227, 0xa006, 0x2009, 0x0029, 0x080c, 0x90d7, 0x6000, 0xc0e5,
-	0xc0ec, 0x6002, 0x6004, 0xa084, 0x00ff, 0xa085, 0x0700, 0x6006,
-	0x2019, 0x0029, 0x080c, 0x6127, 0x0086, 0x2041, 0x0000, 0x080c,
-	0x606d, 0x2009, 0x0000, 0x080c, 0x8ee4, 0x008e, 0x004e, 0x001e,
-	0x8108, 0x1f04, 0x46dd, 0x00ce, 0x015e, 0x0005, 0x00c6, 0x6018,
-	0x2060, 0x6000, 0xc0ec, 0x6002, 0x00ce, 0x0005, 0x00c6, 0x00d6,
-	0x080c, 0x145f, 0x2d60, 0x090c, 0x13fe, 0x2009, 0x00ff, 0x080c,
-	0x41e0, 0x6007, 0x0006, 0x6013, 0x00ff, 0x6017, 0xffff, 0x606f,
-	0x0200, 0x606c, 0x6093, 0x0002, 0x60bb, 0x0520, 0x60a3, 0x00ff,
-	0x60b7, 0x0000, 0x60af, 0x0000, 0x2c08, 0x2001, 0x94c6, 0x2102,
-	0x00de, 0x00ce, 0x0005, 0x0156, 0x00e6, 0x00d6, 0x00c6, 0x20a9,
-	0x00ff, 0x2009, 0x0000, 0x0016, 0x080c, 0x4434, 0x1138, 0x2c70,
-	0x70ac, 0xa005, 0x0118, 0x2060, 0x080c, 0x5cf4, 0x001e, 0x8108,
-	0x1f04, 0x4743, 0x00ce, 0x00de, 0x00ee, 0x015e, 0x0005, 0x2071,
-	0x9328, 0x7003, 0x0001, 0x7007, 0x0000, 0x7013, 0x0000, 0x7017,
+	0xa294, 0xff00, 0xa215, 0x6206, 0x00ce, 0x012e, 0x0005, 0x0126,
+	0x00c6, 0x2091, 0x8000, 0x6218, 0x2260, 0x6204, 0xa294, 0x00ff,
+	0x8007, 0xa215, 0x6206, 0x00ce, 0x012e, 0x0005, 0x0026, 0xa182,
+	0x00ff, 0x0218, 0xa085, 0x0001, 0x00b0, 0xa190, 0x8c34, 0x2204,
+	0xa065, 0x1180, 0x0016, 0x00d6, 0x080c, 0x146f, 0x2d60, 0x00de,
+	0x001e, 0x0d80, 0x2c00, 0x2012, 0x60a7, 0x0000, 0x60ab, 0x0000,
+	0x080c, 0x4118, 0xa006, 0x002e, 0x0005, 0x0026, 0xa182, 0x00ff,
+	0x0218, 0xa085, 0x0001, 0x0060, 0x00d6, 0xa190, 0x8c34, 0x2204,
+	0xa06d, 0x0120, 0x2013, 0x0000, 0x080c, 0x149f, 0x00de, 0xa006,
+	0x002e, 0x0005, 0x0016, 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001,
+	0x0030, 0xa188, 0x8c34, 0x2104, 0xa065, 0x0dc0, 0xa006, 0x001e,
+	0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x600b, 0x0000, 0x600f,
+	0x0000, 0x6000, 0xc08c, 0x6002, 0x080c, 0x4c42, 0x1538, 0x60a0,
+	0xa086, 0x007e, 0x2069, 0x9090, 0x0130, 0x2001, 0x8b32, 0x2004,
+	0xd0ac, 0x11e0, 0x0098, 0x2d04, 0xd0e4, 0x01c0, 0x00d6, 0x2069,
+	0x908e, 0x00c6, 0x2061, 0x8d9e, 0x6810, 0x2062, 0x6814, 0x6006,
+	0x6818, 0x600a, 0x681c, 0x600e, 0x00ce, 0x00de, 0x8d69, 0x2d04,
+	0x2069, 0x0140, 0x6886, 0x2069, 0x8b00, 0x689e, 0x2069, 0x908e,
+	0x6808, 0x605e, 0x6810, 0x6062, 0x6138, 0xa10a, 0x0208, 0x603a,
+	0x6814, 0x6066, 0x2099, 0x9096, 0xac88, 0x000a, 0x21a0, 0x20a9,
+	0x0004, 0x53a3, 0x2099, 0x909a, 0xac88, 0x0006, 0x21a0, 0x20a9,
+	0x0004, 0x53a3, 0x2069, 0x90ae, 0x6808, 0x606a, 0x690c, 0x616e,
+	0x6810, 0x6072, 0x6818, 0x6076, 0xa182, 0x0211, 0x1218, 0x2009,
+	0x0008, 0x0400, 0xa182, 0x0259, 0x1218, 0x2009, 0x0007, 0x00d0,
+	0xa182, 0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, 0xa182, 0x0349,
+	0x1218, 0x2009, 0x0005, 0x0070, 0xa182, 0x0421, 0x1218, 0x2009,
+	0x0004, 0x0040, 0xa182, 0x0581, 0x1218, 0x2009, 0x0003, 0x0010,
+	0x2009, 0x0002, 0x6192, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005,
+	0x00e6, 0x2071, 0x908d, 0x2e04, 0x6896, 0x2071, 0x908e, 0x7004,
+	0x689a, 0x701c, 0x689e, 0x00ee, 0x0005, 0x00d6, 0x0126, 0x2091,
+	0x8000, 0x60a4, 0xa06d, 0x01c0, 0x6900, 0x81ff, 0x1540, 0x6a04,
+	0xa282, 0x0010, 0x1648, 0xad88, 0x0004, 0x20a9, 0x0010, 0x2104,
+	0xa086, 0xffff, 0x0128, 0x8108, 0x1f04, 0x43bf, 0x080c, 0x1410,
+	0x260a, 0x8210, 0x6a06, 0x0098, 0x080c, 0x1488, 0x01a8, 0x2d00,
+	0x60a6, 0x6803, 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b,
+	0xffff, 0x8108, 0x1f04, 0x43d7, 0x6807, 0x0001, 0x6e12, 0xa085,
+	0x0001, 0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8, 0x0126, 0x2091,
+	0x8000, 0x00d6, 0x60a4, 0xa00d, 0x01a0, 0x2168, 0x6800, 0xa005,
+	0x1160, 0x080c, 0x4509, 0x1168, 0x200b, 0xffff, 0x6804, 0xa08a,
+	0x0002, 0x0218, 0x8001, 0x6806, 0x0020, 0x080c, 0x149f, 0x60a7,
+	0x0000, 0x00de, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c,
+	0x4566, 0x0010, 0x080c, 0x4249, 0x080c, 0x4488, 0x1dd8, 0x080c,
+	0x4451, 0x012e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a8,
+	0xa06d, 0x01c0, 0x6950, 0x81ff, 0x1540, 0x6a54, 0xa282, 0x0010,
+	0x1670, 0xad88, 0x0018, 0x20a9, 0x0010, 0x2104, 0xa086, 0xffff,
+	0x0128, 0x8108, 0x1f04, 0x4425, 0x080c, 0x1410, 0x260a, 0x8210,
+	0x6a56, 0x0098, 0x080c, 0x1488, 0x01d0, 0x2d00, 0x60aa, 0x6853,
+	0x0000, 0xad88, 0x0018, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108,
+	0x1f04, 0x443d, 0x6857, 0x0001, 0x6e62, 0x0010, 0x080c, 0x429a,
+	0x0089, 0x1de0, 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, 0xa006,
+	0x0cd8, 0x0126, 0x2091, 0x8000, 0x080c, 0x58b9, 0x012e, 0x0005,
+	0xa01e, 0x0010, 0x2019, 0x0001, 0xa00e, 0x0126, 0x2091, 0x8000,
+	0x604c, 0x2068, 0x6000, 0xd0dc, 0x1170, 0x8dff, 0x01e8, 0x83ff,
+	0x0120, 0x6848, 0xa606, 0x0158, 0x0030, 0x683c, 0xa406, 0x1118,
+	0x6840, 0xa506, 0x0120, 0x2d08, 0x6800, 0x2068, 0x0c70, 0x6a00,
+	0x604c, 0xad06, 0x1110, 0x624e, 0x0018, 0xa180, 0x0000, 0x2202,
+	0x82ff, 0x1110, 0x6152, 0x8dff, 0x012e, 0x0005, 0xa01e, 0x0010,
+	0x2019, 0x0001, 0xa00e, 0x6080, 0x2068, 0x8dff, 0x01e8, 0x83ff,
+	0x0120, 0x6848, 0xa606, 0x0158, 0x0030, 0x683c, 0xa406, 0x1118,
+	0x6840, 0xa506, 0x0120, 0x2d08, 0x6800, 0x2068, 0x0c70, 0x6a00,
+	0x6080, 0xad06, 0x1110, 0x6282, 0x0018, 0xa180, 0x0000, 0x2202,
+	0x82ff, 0x1110, 0x6186, 0x8dff, 0x0005, 0xa016, 0x080c, 0x4503,
+	0x1110, 0x2011, 0x0001, 0x080c, 0x454d, 0x1110, 0xa295, 0x0002,
+	0x0005, 0x080c, 0x457e, 0x0118, 0x080c, 0x7c4c, 0x0010, 0xa085,
+	0x0001, 0x0005, 0x080c, 0x457e, 0x0118, 0x080c, 0x7bd9, 0x0010,
+	0xa085, 0x0001, 0x0005, 0x080c, 0x457e, 0x0118, 0x080c, 0x7c1f,
+	0x0010, 0xa085, 0x0001, 0x0005, 0x080c, 0x457e, 0x0118, 0x080c,
+	0x7bf3, 0x0010, 0xa085, 0x0001, 0x0005, 0x080c, 0x457e, 0x0118,
+	0x080c, 0x7c79, 0x0010, 0xa085, 0x0001, 0x0005, 0x0126, 0x0006,
+	0x00d6, 0x2091, 0x8000, 0x6080, 0xa06d, 0x0168, 0x6800, 0x0006,
+	0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x7dc8, 0x080c,
+	0x46a1, 0x000e, 0x0c88, 0x6083, 0x0000, 0x6087, 0x0000, 0x00de,
+	0x000e, 0x012e, 0x0005, 0x60a4, 0xa00d, 0x1118, 0xa085, 0x0001,
+	0x0005, 0x00e6, 0x2170, 0x7000, 0xa005, 0x1160, 0x20a9, 0x0010,
+	0xae88, 0x0004, 0x2104, 0xa606, 0x0128, 0x8108, 0x1f04, 0x4512,
+	0xa085, 0x0001, 0xa006, 0x00ee, 0x0005, 0x00d6, 0x0126, 0x2091,
+	0x8000, 0x60a4, 0xa06d, 0x1128, 0x080c, 0x1488, 0x01a0, 0x2d00,
+	0x60a6, 0x6803, 0x0001, 0x6807, 0x0000, 0xad88, 0x0004, 0x20a9,
+	0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, 0x4531, 0xa085, 0x0001,
+	0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8, 0x00d6, 0x0126, 0x2091,
+	0x8000, 0x60a4, 0xa06d, 0x0130, 0x60a7, 0x0000, 0x080c, 0x149f,
+	0xa085, 0x0001, 0x012e, 0x00de, 0x0005, 0x60a8, 0xa00d, 0x1118,
+	0xa085, 0x0001, 0x0005, 0x00e6, 0x2170, 0x7050, 0xa005, 0x1160,
+	0x20a9, 0x0010, 0xae88, 0x0018, 0x2104, 0xa606, 0x0128, 0x8108,
+	0x1f04, 0x455c, 0xa085, 0x0001, 0x00ee, 0x0005, 0x0126, 0x2091,
+	0x8000, 0x0c19, 0x1188, 0x200b, 0xffff, 0x00d6, 0x60a8, 0x2068,
+	0x6854, 0xa08a, 0x0002, 0x0218, 0x8001, 0x6856, 0x0020, 0x080c,
+	0x149f, 0x60ab, 0x0000, 0x00de, 0x012e, 0x0005, 0x609c, 0xd0a4,
+	0x0005, 0x00f6, 0x2079, 0x8b51, 0x7804, 0xd0a4, 0x0518, 0x0156,
+	0x00c6, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x430a,
+	0x1168, 0x6004, 0xa084, 0xff00, 0x8007, 0xa096, 0x0004, 0x0118,
+	0xa086, 0x0006, 0x1118, 0x6000, 0xc0ed, 0x6002, 0x001e, 0x8108,
+	0x1f04, 0x458d, 0x00ce, 0x015e, 0x2009, 0x07d0, 0x2011, 0x45ac,
+	0x080c, 0x568c, 0x00fe, 0x0005, 0x2011, 0x45ac, 0x080c, 0x560d,
+	0x0156, 0x00c6, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c,
+	0x430a, 0x1530, 0x6000, 0xd0ec, 0x0518, 0x0046, 0x62a0, 0xa294,
+	0x00ff, 0x8227, 0xa006, 0x2009, 0x0029, 0x080c, 0x8982, 0x6000,
+	0xc0e5, 0xc0ec, 0x6002, 0x6004, 0xa084, 0x00ff, 0xa085, 0x0700,
+	0x6006, 0x2019, 0x0029, 0x080c, 0x59d5, 0x0086, 0x2041, 0x0000,
+	0x080c, 0x5911, 0x2009, 0x0000, 0x080c, 0x878f, 0x008e, 0x004e,
+	0x001e, 0x8108, 0x1f04, 0x45b6, 0x00ce, 0x015e, 0x0005, 0x00c6,
+	0x6018, 0x2060, 0x6000, 0xc0ec, 0x6002, 0x00ce, 0x0005, 0x2071,
+	0x8c13, 0x7003, 0x0001, 0x7007, 0x0000, 0x7013, 0x0000, 0x7017,
 	0x0000, 0x701b, 0x0000, 0x701f, 0x0000, 0x704b, 0x0001, 0x704f,
 	0x0000, 0x705b, 0x0020, 0x705f, 0x0040, 0x707f, 0x0000, 0x2071,
-	0x94b6, 0x7003, 0x9328, 0x7007, 0x0000, 0x700b, 0x0000, 0x700f,
-	0x9496, 0x7013, 0x0020, 0x7017, 0x0040, 0x7037, 0x0000, 0x0005,
-	0x0016, 0x00e6, 0x2071, 0x946e, 0xa00e, 0x7186, 0x718a, 0x7097,
-	0x0001, 0x2001, 0x9252, 0x2004, 0xd0fc, 0x1148, 0x2001, 0x9252,
+	0x8d7c, 0x7003, 0x8c13, 0x7007, 0x0000, 0x700b, 0x0000, 0x700f,
+	0x8d5c, 0x7013, 0x0020, 0x7017, 0x0040, 0x7037, 0x0000, 0x0005,
+	0x0016, 0x00e6, 0x2071, 0x8d34, 0xa00e, 0x7186, 0x718a, 0x7097,
+	0x0001, 0x2001, 0x8b52, 0x2004, 0xd0fc, 0x1148, 0x2001, 0x8b52,
 	0x2004, 0xa00e, 0xd09c, 0x0108, 0x8108, 0x7102, 0x04f0, 0x2001,
-	0x9271, 0x200c, 0xa184, 0x000f, 0x2009, 0x9272, 0x210c, 0x0002,
-	0x478e, 0x47b0, 0x47b7, 0x47c1, 0x47c6, 0x478e, 0x478e, 0x478e,
-	0x478e, 0x478e, 0x478e, 0x478e, 0x478e, 0x478e, 0x478e, 0x478e,
+	0x8b71, 0x200c, 0xa184, 0x000f, 0x2009, 0x8b72, 0x210c, 0x0002,
+	0x4626, 0x4648, 0x464f, 0x4659, 0x465e, 0x4626, 0x4626, 0x4626,
+	0x4626, 0x4626, 0x4626, 0x4626, 0x4626, 0x4626, 0x4626, 0x4626,
 	0x708f, 0x0005, 0x7007, 0x0122, 0x2001, 0x0002, 0x0030, 0x708f,
 	0x0002, 0x7007, 0x0121, 0x2001, 0x0003, 0x7002, 0x7097, 0x0001,
 	0x0088, 0x7007, 0x0122, 0x2001, 0x0002, 0x0020, 0x7007, 0x0121,
 	0x2001, 0x0003, 0x7002, 0xa006, 0x7096, 0x708e, 0xa184, 0xff00,
 	0x8007, 0x709a, 0xa184, 0x00ff, 0x7092, 0x00ee, 0x001e, 0x0005,
-	0x00e6, 0x2071, 0x9328, 0x684c, 0xa005, 0x1130, 0x7028, 0xc085,
+	0x00e6, 0x2071, 0x8c13, 0x684c, 0xa005, 0x1130, 0x7028, 0xc085,
 	0x702a, 0xa085, 0x0001, 0x0418, 0x6a60, 0x7236, 0x6b64, 0x733a,
 	0x6868, 0x703e, 0x7076, 0x686c, 0x7042, 0x707a, 0x684c, 0x702e,
 	0x6844, 0x7032, 0x2009, 0x000d, 0x200a, 0x8007, 0x8006, 0x8006,
 	0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, 0x726e,
 	0x7372, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0xa006, 0x00ee,
-	0x0005, 0x0156, 0x00e6, 0x0026, 0x6838, 0xd0fc, 0x1904, 0x4861,
-	0x6804, 0xa00d, 0x0188, 0x00d6, 0x2071, 0x9200, 0xa016, 0x702c,
+	0x0005, 0x0156, 0x00e6, 0x0026, 0x6838, 0xd0fc, 0x1904, 0x46f9,
+	0x6804, 0xa00d, 0x0188, 0x00d6, 0x2071, 0x8b00, 0xa016, 0x702c,
 	0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e,
-	0x70ac, 0xa200, 0x70ae, 0x00de, 0x2071, 0x9328, 0x701c, 0xa005,
-	0x1904, 0x4871, 0x20a9, 0x0032, 0x0f04, 0x486f, 0x0e04, 0x482c,
-	0x2071, 0x946e, 0x7200, 0x82ff, 0x05d0, 0x6934, 0xa186, 0x0103,
-	0x1904, 0x487f, 0x6948, 0x6844, 0xa105, 0x1538, 0x2009, 0x8020,
-	0x2200, 0x0002, 0x486f, 0x4846, 0x48e6, 0x48f3, 0x2071, 0x0000,
-	0x20a9, 0x0032, 0x0f04, 0x486f, 0x7018, 0xd084, 0x1dd8, 0x7122,
+	0x70ac, 0xa200, 0x70ae, 0x00de, 0x2071, 0x8c13, 0x701c, 0xa005,
+	0x1904, 0x4709, 0x20a9, 0x0032, 0x0f04, 0x4707, 0x0e04, 0x46c4,
+	0x2071, 0x8d34, 0x7200, 0x82ff, 0x05d0, 0x6934, 0xa186, 0x0103,
+	0x1904, 0x4717, 0x6948, 0x6844, 0xa105, 0x1538, 0x2009, 0x8020,
+	0x2200, 0x0002, 0x4707, 0x46de, 0x472f, 0x473b, 0x2071, 0x0000,
+	0x20a9, 0x0032, 0x0f04, 0x4707, 0x7018, 0xd084, 0x1dd8, 0x7122,
 	0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080,
-	0x2071, 0x9200, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70ac, 0x8000,
+	0x2071, 0x8b00, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70ac, 0x8000,
 	0x70ae, 0x002e, 0x00ee, 0x015e, 0x0005, 0x6844, 0xa086, 0x0100,
 	0x1130, 0x6868, 0xa005, 0x1118, 0x2009, 0x8020, 0x0888, 0x2071,
-	0x9328, 0x2d08, 0x206b, 0x0000, 0x7010, 0x8000, 0x7012, 0x7018,
+	0x8c13, 0x2d08, 0x206b, 0x0000, 0x7010, 0x8000, 0x7012, 0x7018,
 	0xa06d, 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, 0x0c10, 0xa18c,
-	0x00ff, 0xa186, 0x0013, 0x01e0, 0xa186, 0x001b, 0x01c8, 0xa186,
-	0x0023, 0x01e8, 0xa186, 0x0017, 0x0130, 0xa186, 0x001e, 0x0118,
-	0xa18e, 0x001f, 0x19e0, 0x684c, 0xd0cc, 0x09c8, 0x6850, 0xa084,
-	0x00ff, 0xa086, 0x0001, 0x1998, 0x2009, 0x8021, 0x0804, 0x4840,
-	0x6848, 0xa005, 0x1960, 0x2009, 0x8022, 0x0804, 0x4840, 0x2071,
-	0x0000, 0x7018, 0xd084, 0x1918, 0x00e6, 0x2071, 0x9281, 0x7140,
-	0x00ee, 0x6838, 0xa102, 0x0a04, 0x486f, 0x684c, 0xa005, 0x1158,
-	0x00e6, 0x2071, 0x9281, 0x7004, 0x00ee, 0xd08c, 0x1904, 0x486f,
-	0x2001, 0x8024, 0x0040, 0x6848, 0xd084, 0x1118, 0x2001, 0x8023,
-	0x0010, 0x2001, 0x8027, 0x7022, 0x6840, 0x7026, 0x683c, 0x702a,
-	0x6850, 0x702e, 0x0026, 0x0036, 0x6b38, 0x2e10, 0xa290, 0x0072,
-	0x2d00, 0xa080, 0x0015, 0x200c, 0x2112, 0x8000, 0x200c, 0x8210,
-	0x8319, 0x1dd0, 0x003e, 0x002e, 0x0804, 0x4854, 0x7084, 0x8008,
-	0xa092, 0x001e, 0x1a04, 0x486f, 0x7186, 0xae90, 0x0003, 0xa210,
-	0x683c, 0x2012, 0x0080, 0x7084, 0x8008, 0xa092, 0x000f, 0x1a04,
-	0x486f, 0x7186, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012,
-	0x8210, 0x6840, 0x2012, 0x7088, 0xa10a, 0x0a04, 0x4858, 0x718c,
-	0x7084, 0xa10a, 0x0a04, 0x4858, 0x2071, 0x0000, 0x7018, 0xd084,
-	0x1904, 0x4858, 0x2071, 0x946e, 0x7000, 0xa086, 0x0002, 0x1150,
-	0x080c, 0x4b12, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080,
-	0x0804, 0x4858, 0x080c, 0x4b3c, 0x2071, 0x0000, 0x701b, 0x0001,
-	0x2091, 0x4080, 0x0804, 0x4858, 0x0006, 0x6837, 0x0103, 0x20a9,
-	0x001c, 0xad80, 0x0011, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x000e,
-	0x684a, 0x6952, 0x0005, 0x2071, 0x9328, 0x7004, 0x0002, 0x4948,
-	0x4958, 0x4afd, 0x4afe, 0x4b0b, 0x4b11, 0x4949, 0x4aee, 0x4a9a,
-	0x0005, 0x0126, 0x2091, 0x8000, 0x0e04, 0x4956, 0x2009, 0x000d,
-	0x7030, 0x200a, 0x2091, 0x4080, 0x7007, 0x0001, 0x012e, 0x0005,
-	0x2069, 0x94f8, 0x683c, 0xa005, 0x03f8, 0x11f0, 0x0126, 0x2091,
-	0x8000, 0x2069, 0x0000, 0x6934, 0x2001, 0x9334, 0x2004, 0xa10a,
-	0x0170, 0x0e04, 0x497c, 0x2069, 0x0000, 0x6818, 0xd084, 0x1158,
-	0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, 0x4080, 0x2069,
-	0x94f8, 0x683f, 0xffff, 0x012e, 0x2069, 0x9200, 0x6844, 0x6964,
-	0xa102, 0x2069, 0x946e, 0x688a, 0x6984, 0x701c, 0xa06d, 0x0120,
-	0x81ff, 0x0904, 0x49d1, 0x00a0, 0x81ff, 0x0904, 0x4a6f, 0x2071,
-	0x946e, 0x7184, 0x7088, 0xa10a, 0x1258, 0x7190, 0x2071, 0x94f8,
-	0x7038, 0xa005, 0x0128, 0x1b04, 0x4a6f, 0x713a, 0x0804, 0x4a6f,
-	0x2071, 0x946e, 0x718c, 0x0126, 0x2091, 0x8000, 0x7084, 0xa10a,
-	0x0a04, 0x4a70, 0x0e04, 0x4a2d, 0x2071, 0x0000, 0x7018, 0xd084,
-	0x1904, 0x4a2d, 0x2001, 0xffff, 0x2071, 0x94f8, 0x703a, 0x2071,
-	0x946e, 0x7000, 0xa086, 0x0002, 0x1150, 0x080c, 0x4b12, 0x2071,
-	0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0804, 0x4a2d, 0x080c,
-	0x4b3c, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0804,
-	0x4a2d, 0x2071, 0x946e, 0x7000, 0xa005, 0x0904, 0x4a51, 0x6934,
-	0xa186, 0x0103, 0x1904, 0x4a30, 0x6948, 0x6844, 0xa105, 0x1904,
-	0x4a47, 0x2071, 0x946e, 0x7000, 0x0002, 0x4a51, 0x4a11, 0x49e9,
-	0x49fb, 0x7084, 0x8008, 0xa092, 0x001e, 0x1a04, 0x4a6f, 0xae90,
-	0x0003, 0xa210, 0x683c, 0x2012, 0x7186, 0x2071, 0x9328, 0x080c,
-	0x4b95, 0x0804, 0x4a6f, 0x7084, 0x8008, 0xa092, 0x000f, 0x1a04,
-	0x4a6f, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012, 0x8210,
-	0x6840, 0x2012, 0x7186, 0x2071, 0x9328, 0x080c, 0x4b95, 0x0804,
-	0x4a6f, 0x2009, 0x8020, 0x0126, 0x2091, 0x8000, 0x0e04, 0x4a2d,
-	0x2071, 0x0000, 0x7018, 0xd084, 0x1180, 0x7122, 0x683c, 0x7026,
-	0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, 0x012e, 0x2071,
-	0x9328, 0x080c, 0x4b95, 0x0804, 0x4a6f, 0x012e, 0x0804, 0x4a6f,
-	0xa18c, 0x00ff, 0xa186, 0x0017, 0x0130, 0xa186, 0x001e, 0x0118,
-	0xa18e, 0x001f, 0x11b0, 0x684c, 0xd0cc, 0x0198, 0x6850, 0xa084,
-	0x00ff, 0xa086, 0x0001, 0x1168, 0x2009, 0x8021, 0x0860, 0x6844,
-	0xa086, 0x0100, 0x1130, 0x6868, 0xa005, 0x1118, 0x2009, 0x8020,
-	0x0810, 0x2071, 0x9328, 0x080c, 0x4ba7, 0x01c8, 0x2071, 0x9328,
-	0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, 0x0003, 0x1130,
-	0x810f, 0xa18c, 0x00ff, 0x8101, 0x0108, 0x710e, 0x7007, 0x0003,
-	0x080c, 0x4bc0, 0x7050, 0xa086, 0x0100, 0x0904, 0x4afe, 0x0005,
-	0x2071, 0x9328, 0x080c, 0x4ba7, 0x0518, 0x2071, 0x946e, 0x7084,
-	0x700a, 0x20a9, 0x0020, 0x2099, 0x946f, 0x20a1, 0x9496, 0x53a3,
-	0x7087, 0x0000, 0x2071, 0x9328, 0x2069, 0x94b6, 0x706c, 0x6826,
-	0x7070, 0x682a, 0x7074, 0x682e, 0x7078, 0x6832, 0x2d10, 0x080c,
-	0x14c7, 0x7007, 0x0008, 0x2001, 0xffff, 0x2071, 0x94f8, 0x703a,
-	0x012e, 0x08a8, 0x2069, 0x94b6, 0x6808, 0xa08e, 0x0000, 0x0904,
-	0x4aed, 0xa08e, 0x0200, 0x0904, 0x4aeb, 0xa08e, 0x0100, 0x1904,
-	0x4aed, 0x0126, 0x2091, 0x8000, 0x0e04, 0x4ae9, 0x2069, 0x0000,
-	0x6818, 0xd084, 0x15b0, 0x702c, 0x7130, 0x8108, 0xa102, 0x0230,
-	0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, 0x0048, 0x706c, 0xa080,
-	0x0040, 0x706e, 0x1220, 0x7070, 0xa081, 0x0000, 0x7072, 0x7132,
-	0x6936, 0x2001, 0x9493, 0x2004, 0xa005, 0x1190, 0x6934, 0x2069,
-	0x946e, 0x689c, 0x699e, 0x2069, 0x94f8, 0xa102, 0x1118, 0x683c,
-	0xa005, 0x1368, 0x2001, 0x9494, 0x200c, 0x810d, 0x693e, 0x0038,
-	0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, 0x4080, 0x7007,
-	0x0001, 0x012e, 0x0010, 0x7007, 0x0005, 0x0005, 0x701c, 0xa06d,
-	0x0158, 0x080c, 0x4ba7, 0x0140, 0x7007, 0x0003, 0x080c, 0x4bc0,
-	0x7050, 0xa086, 0x0100, 0x0110, 0x0005, 0x0005, 0x7050, 0xa09e,
-	0x0100, 0x1118, 0x7007, 0x0004, 0x0030, 0xa086, 0x0200, 0x1110,
-	0x7007, 0x0005, 0x0005, 0x080c, 0x4b61, 0x7006, 0x080c, 0x4b95,
-	0x0005, 0x0005, 0x00e6, 0x0156, 0x2071, 0x946e, 0x7184, 0x81ff,
-	0x0500, 0xa006, 0x7086, 0xae80, 0x0003, 0x2071, 0x0000, 0x21a8,
-	0x2014, 0x7226, 0x8000, 0x0f04, 0x4b36, 0x2014, 0x722a, 0x8000,
-	0x0f04, 0x4b36, 0x2014, 0x722e, 0x8000, 0x0f04, 0x4b36, 0x2014,
-	0x723a, 0x8000, 0x0f04, 0x4b36, 0x2014, 0x723e, 0xa180, 0x8030,
-	0x7022, 0x015e, 0x00ee, 0x0005, 0x00e6, 0x0156, 0x2071, 0x946e,
-	0x7184, 0x81ff, 0x01d8, 0xa006, 0x7086, 0xae80, 0x0003, 0x2071,
-	0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x2014, 0x722a, 0x8000,
-	0x0f04, 0x4b58, 0x2014, 0x723a, 0x8000, 0x2014, 0x723e, 0x0018,
-	0x2001, 0x8020, 0x0010, 0xa180, 0x8042, 0x7022, 0x015e, 0x00ee,
-	0x0005, 0x702c, 0x7130, 0x8108, 0xa102, 0x0230, 0xa00e, 0x7034,
-	0x706e, 0x7038, 0x7072, 0x0048, 0x706c, 0xa080, 0x0040, 0x706e,
-	0x1220, 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x700c, 0x8001,
-	0x700e, 0x11a0, 0x0126, 0x2091, 0x8000, 0x0e04, 0x4b91, 0x2001,
-	0x000d, 0x2102, 0x2091, 0x4080, 0x2001, 0x0001, 0x012e, 0x0005,
-	0x2001, 0x000d, 0x2102, 0x2001, 0x0001, 0x0005, 0x2001, 0x0007,
-	0x0005, 0x2001, 0x0006, 0x012e, 0x0005, 0x701c, 0xa06d, 0x0170,
-	0x0126, 0x2091, 0x8000, 0x7010, 0x8001, 0x7012, 0x2d04, 0x701e,
-	0xa005, 0x1108, 0x701a, 0x012e, 0x080c, 0x1493, 0x0005, 0x2019,
-	0x000d, 0x2304, 0x230c, 0xa10e, 0x0130, 0x2304, 0x230c, 0xa10e,
-	0x0110, 0xa006, 0x0060, 0x732c, 0x8319, 0x7130, 0xa102, 0x1118,
-	0x2300, 0xa005, 0x0020, 0x0210, 0xa302, 0x0008, 0x8002, 0x0005,
-	0x2d00, 0x7026, 0xa080, 0x000d, 0x7056, 0x7053, 0x0000, 0x0126,
-	0x2091, 0x8000, 0x2009, 0x9508, 0x2104, 0xc08d, 0x200a, 0x012e,
-	0x080c, 0x14df, 0x0005, 0x7088, 0xa08a, 0x0027, 0x1220, 0xa082,
-	0x001d, 0x0033, 0x0010, 0x080c, 0x13fe, 0x6027, 0x1e00, 0x0005,
-	0x4c57, 0x4be9, 0x4bff, 0x4c27, 0x4c4a, 0x4c7c, 0x4c8e, 0x4bff,
-	0x4c68, 0x6803, 0x0010, 0x6124, 0xd1e4, 0x1180, 0x080c, 0x4cd7,
-	0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1cc, 0x0140, 0x708b, 0x0020,
+	0x00ff, 0xa186, 0x0017, 0x0130, 0xa186, 0x001e, 0x0118, 0xa18e,
+	0x001f, 0x1d28, 0x684c, 0xd0cc, 0x0d10, 0x6850, 0xa084, 0x00ff,
+	0xa086, 0x0001, 0x19e0, 0x2009, 0x8021, 0x0804, 0x46d8, 0x7084,
+	0x8008, 0xa092, 0x001e, 0x1a98, 0x7186, 0xae90, 0x0003, 0xa210,
+	0x683c, 0x2012, 0x0078, 0x7084, 0x8008, 0xa092, 0x000f, 0x1a38,
+	0x7186, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012, 0x8210,
+	0x6840, 0x2012, 0x7088, 0xa10a, 0x0a04, 0x46f0, 0x718c, 0x7084,
+	0xa10a, 0x0a04, 0x46f0, 0x2071, 0x0000, 0x7018, 0xd084, 0x1904,
+	0x46f0, 0x2071, 0x8d34, 0x7000, 0xa086, 0x0002, 0x1150, 0x080c,
+	0x495f, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0804,
+	0x46f0, 0x080c, 0x4989, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091,
+	0x4080, 0x0804, 0x46f0, 0x0006, 0x684c, 0x0006, 0x6837, 0x0103,
+	0x20a9, 0x001c, 0xad80, 0x0011, 0x20a0, 0x2001, 0x0000, 0x40a4,
+	0x000e, 0xa084, 0x00ff, 0x684e, 0x000e, 0x684a, 0x6952, 0x0005,
+	0x2071, 0x8c13, 0x7004, 0x0002, 0x4795, 0x47a5, 0x494a, 0x494b,
+	0x4958, 0x495e, 0x4796, 0x493b, 0x48e7, 0x0005, 0x0126, 0x2091,
+	0x8000, 0x0e04, 0x47a3, 0x2009, 0x000d, 0x7030, 0x200a, 0x2091,
+	0x4080, 0x7007, 0x0001, 0x012e, 0x0005, 0x2069, 0x8dbd, 0x683c,
+	0xa005, 0x03f8, 0x11f0, 0x0126, 0x2091, 0x8000, 0x2069, 0x0000,
+	0x6934, 0x2001, 0x8c1f, 0x2004, 0xa10a, 0x0170, 0x0e04, 0x47c8,
+	0x2069, 0x0000, 0x6818, 0xd084, 0x1158, 0x2009, 0x8040, 0x6922,
+	0x681b, 0x0001, 0x2091, 0x4080, 0x2069, 0x8dbd, 0x683f, 0xffff,
+	0x012e, 0x2069, 0x8b00, 0x6844, 0x6964, 0xa102, 0x2069, 0x8d34,
+	0x688a, 0x6984, 0x701c, 0xa06d, 0x0120, 0x81ff, 0x0904, 0x481e,
+	0x00a0, 0x81ff, 0x0904, 0x48bc, 0x2071, 0x8d34, 0x7184, 0x7088,
+	0xa10a, 0x1258, 0x7190, 0x2071, 0x8dbd, 0x7038, 0xa005, 0x0128,
+	0x1b04, 0x48bc, 0x713a, 0x0804, 0x48bc, 0x2071, 0x8d34, 0x718c,
+	0x0126, 0x2091, 0x8000, 0x7084, 0xa10a, 0x0a04, 0x48bd, 0x0e04,
+	0x487a, 0x2071, 0x0000, 0x7018, 0xd084, 0x1904, 0x487a, 0x2001,
+	0xffff, 0x2071, 0x8dbd, 0x703a, 0x2071, 0x8d34, 0x7000, 0xa086,
+	0x0002, 0x1150, 0x080c, 0x495f, 0x2071, 0x0000, 0x701b, 0x0001,
+	0x2091, 0x4080, 0x0804, 0x487a, 0x080c, 0x4989, 0x2071, 0x0000,
+	0x701b, 0x0001, 0x2091, 0x4080, 0x0804, 0x487a, 0x2071, 0x8d34,
+	0x7000, 0xa005, 0x0904, 0x489e, 0x6934, 0xa186, 0x0103, 0x1904,
+	0x487d, 0x6948, 0x6844, 0xa105, 0x1904, 0x4894, 0x2071, 0x8d34,
+	0x7000, 0x0002, 0x489e, 0x485e, 0x4836, 0x4848, 0x7084, 0x8008,
+	0xa092, 0x001e, 0x1a04, 0x48bc, 0xae90, 0x0003, 0xa210, 0x683c,
+	0x2012, 0x7186, 0x2071, 0x8c13, 0x080c, 0x49e2, 0x0804, 0x48bc,
+	0x7084, 0x8008, 0xa092, 0x000f, 0x1a04, 0x48bc, 0xae90, 0x0003,
+	0x8003, 0xa210, 0x683c, 0x2012, 0x8210, 0x6840, 0x2012, 0x7186,
+	0x2071, 0x8c13, 0x080c, 0x49e2, 0x0804, 0x48bc, 0x2009, 0x8020,
+	0x0126, 0x2091, 0x8000, 0x0e04, 0x487a, 0x2071, 0x0000, 0x7018,
+	0xd084, 0x1180, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a, 0x701b,
+	0x0001, 0x2091, 0x4080, 0x012e, 0x2071, 0x8c13, 0x080c, 0x49e2,
+	0x0804, 0x48bc, 0x012e, 0x0804, 0x48bc, 0xa18c, 0x00ff, 0xa186,
+	0x0017, 0x0130, 0xa186, 0x001e, 0x0118, 0xa18e, 0x001f, 0x11b0,
+	0x684c, 0xd0cc, 0x0198, 0x6850, 0xa084, 0x00ff, 0xa086, 0x0001,
+	0x1168, 0x2009, 0x8021, 0x0860, 0x6844, 0xa086, 0x0100, 0x1130,
+	0x6868, 0xa005, 0x1118, 0x2009, 0x8020, 0x0810, 0x2071, 0x8c13,
+	0x080c, 0x49f4, 0x01c8, 0x2071, 0x8c13, 0x700f, 0x0001, 0x6934,
+	0xa184, 0x00ff, 0xa086, 0x0003, 0x1130, 0x810f, 0xa18c, 0x00ff,
+	0x8101, 0x0108, 0x710e, 0x7007, 0x0003, 0x080c, 0x4a0d, 0x7050,
+	0xa086, 0x0100, 0x0904, 0x494b, 0x0005, 0x2071, 0x8c13, 0x080c,
+	0x49f4, 0x0518, 0x2071, 0x8d34, 0x7084, 0x700a, 0x20a9, 0x0020,
+	0x2099, 0x8d35, 0x20a1, 0x8d5c, 0x53a3, 0x7087, 0x0000, 0x2071,
+	0x8c13, 0x2069, 0x8d7c, 0x706c, 0x6826, 0x7070, 0x682a, 0x7074,
+	0x682e, 0x7078, 0x6832, 0x2d10, 0x080c, 0x14d3, 0x7007, 0x0008,
+	0x2001, 0xffff, 0x2071, 0x8dbd, 0x703a, 0x012e, 0x08a8, 0x2069,
+	0x8d7c, 0x6808, 0xa08e, 0x0000, 0x0904, 0x493a, 0xa08e, 0x0200,
+	0x0904, 0x4938, 0xa08e, 0x0100, 0x1904, 0x493a, 0x0126, 0x2091,
+	0x8000, 0x0e04, 0x4936, 0x2069, 0x0000, 0x6818, 0xd084, 0x15b0,
+	0x702c, 0x7130, 0x8108, 0xa102, 0x0230, 0xa00e, 0x7034, 0x706e,
+	0x7038, 0x7072, 0x0048, 0x706c, 0xa080, 0x0040, 0x706e, 0x1220,
+	0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x6936, 0x2001, 0x8d59,
+	0x2004, 0xa005, 0x1190, 0x6934, 0x2069, 0x8d34, 0x689c, 0x699e,
+	0x2069, 0x8dbd, 0xa102, 0x1118, 0x683c, 0xa005, 0x1368, 0x2001,
+	0x8d5a, 0x200c, 0x810d, 0x693e, 0x0038, 0x2009, 0x8040, 0x6922,
+	0x681b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, 0x012e, 0x0010,
+	0x7007, 0x0005, 0x0005, 0x701c, 0xa06d, 0x0158, 0x080c, 0x49f4,
+	0x0140, 0x7007, 0x0003, 0x080c, 0x4a0d, 0x7050, 0xa086, 0x0100,
+	0x0110, 0x0005, 0x0005, 0x7050, 0xa09e, 0x0100, 0x1118, 0x7007,
+	0x0004, 0x0030, 0xa086, 0x0200, 0x1110, 0x7007, 0x0005, 0x0005,
+	0x080c, 0x49ae, 0x7006, 0x080c, 0x49e2, 0x0005, 0x0005, 0x00e6,
+	0x0156, 0x2071, 0x8d34, 0x7184, 0x81ff, 0x0500, 0xa006, 0x7086,
+	0xae80, 0x0003, 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000,
+	0x0f04, 0x4983, 0x2014, 0x722a, 0x8000, 0x0f04, 0x4983, 0x2014,
+	0x722e, 0x8000, 0x0f04, 0x4983, 0x2014, 0x723a, 0x8000, 0x0f04,
+	0x4983, 0x2014, 0x723e, 0xa180, 0x8030, 0x7022, 0x015e, 0x00ee,
+	0x0005, 0x00e6, 0x0156, 0x2071, 0x8d34, 0x7184, 0x81ff, 0x01d8,
+	0xa006, 0x7086, 0xae80, 0x0003, 0x2071, 0x0000, 0x21a8, 0x2014,
+	0x7226, 0x8000, 0x2014, 0x722a, 0x8000, 0x0f04, 0x49a5, 0x2014,
+	0x723a, 0x8000, 0x2014, 0x723e, 0x0018, 0x2001, 0x8020, 0x0010,
+	0xa180, 0x8042, 0x7022, 0x015e, 0x00ee, 0x0005, 0x702c, 0x7130,
+	0x8108, 0xa102, 0x0230, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072,
+	0x0048, 0x706c, 0xa080, 0x0040, 0x706e, 0x1220, 0x7070, 0xa081,
+	0x0000, 0x7072, 0x7132, 0x700c, 0x8001, 0x700e, 0x11a0, 0x0126,
+	0x2091, 0x8000, 0x0e04, 0x49de, 0x2001, 0x000d, 0x2102, 0x2091,
+	0x4080, 0x2001, 0x0001, 0x012e, 0x0005, 0x2001, 0x000d, 0x2102,
+	0x2001, 0x0001, 0x0005, 0x2001, 0x0007, 0x0005, 0x2001, 0x0006,
+	0x012e, 0x0005, 0x701c, 0xa06d, 0x0170, 0x0126, 0x2091, 0x8000,
+	0x7010, 0x8001, 0x7012, 0x2d04, 0x701e, 0xa005, 0x1108, 0x701a,
+	0x012e, 0x080c, 0x149f, 0x0005, 0x2019, 0x000d, 0x2304, 0x230c,
+	0xa10e, 0x0130, 0x2304, 0x230c, 0xa10e, 0x0110, 0xa006, 0x0060,
+	0x732c, 0x8319, 0x7130, 0xa102, 0x1118, 0x2300, 0xa005, 0x0020,
+	0x0210, 0xa302, 0x0008, 0x8002, 0x0005, 0x2d00, 0x7026, 0xa080,
+	0x000d, 0x7056, 0x7053, 0x0000, 0x0126, 0x2091, 0x8000, 0x2009,
+	0x8dcd, 0x2104, 0xc08d, 0x200a, 0x012e, 0x080c, 0x14eb, 0x0005,
+	0x7088, 0xa08a, 0x0028, 0x1220, 0xa082, 0x001d, 0x0033, 0x0010,
+	0x080c, 0x1410, 0x6027, 0x1e00, 0x0005, 0x4ab8, 0x4a4a, 0x4a60,
+	0x4a88, 0x4aab, 0x4add, 0x4aef, 0x4a60, 0x4ac9, 0x4a37, 0x00d6,
+	0x2069, 0x0200, 0x6804, 0xa005, 0x1158, 0x6808, 0xa005, 0x1140,
+	0x708b, 0x0027, 0x7003, 0x0003, 0x6028, 0xa085, 0x0400, 0x602a,
+	0x00de, 0x0005, 0x6803, 0x0010, 0x6124, 0xd1e4, 0x1180, 0x080c,
+	0x4b52, 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1cc, 0x0140, 0x708b,
+	0x0020, 0x0028, 0x708b, 0x001d, 0x0010, 0x708b, 0x001f, 0x0005,
+	0x6803, 0x0008, 0x6124, 0xd1cc, 0x11e8, 0xd1dc, 0x11c0, 0xd1e4,
+	0x1198, 0xa184, 0x1e00, 0x11d8, 0x60e3, 0x0001, 0x600c, 0xc0b4,
+	0x600e, 0x080c, 0x4c72, 0x6803, 0x0000, 0x708b, 0x0027, 0x2001,
+	0x8b25, 0x2003, 0x0000, 0x0058, 0x708b, 0x001e, 0x0040, 0x708b,
+	0x001d, 0x0028, 0x708b, 0x0020, 0x0010, 0x708b, 0x001f, 0x0005,
+	0x60e3, 0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, 0x4c72, 0x6803,
+	0x0000, 0x6124, 0xd1d4, 0x11a0, 0xd1dc, 0x1178, 0xd1e4, 0x1150,
+	0xa184, 0x1e00, 0x1178, 0x708b, 0x0027, 0x2001, 0x8b25, 0x2003,
+	0x0000, 0x0040, 0x708b, 0x001e, 0x0028, 0x708b, 0x001d, 0x0010,
+	0x708b, 0x001f, 0x0005, 0x6803, 0x0020, 0x6124, 0xd1dc, 0x1128,
+	0xd1e4, 0x0128, 0x708b, 0x001e, 0x0010, 0x708b, 0x001d, 0x0005,
+	0x080c, 0x4b7e, 0x6124, 0xd1dc, 0x1158, 0x080c, 0x4b52, 0xd1d4,
+	0x1128, 0xd1e4, 0x0128, 0x708b, 0x001e, 0x0010, 0x708b, 0x001f,
+	0x0005, 0x6803, 0x0020, 0x6124, 0xd1d4, 0x1160, 0xd1cc, 0x1150,
+	0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x708b, 0x001e, 0x0028, 0x708b,
+	0x001d, 0x0010, 0x708b, 0x0021, 0x0005, 0x080c, 0x4b7e, 0x6124,
+	0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x708b, 0x001e,
 	0x0028, 0x708b, 0x001d, 0x0010, 0x708b, 0x001f, 0x0005, 0x6803,
-	0x0008, 0x6124, 0xd1cc, 0x11e8, 0xd1dc, 0x11c0, 0xd1e4, 0x1198,
-	0xa184, 0x1e00, 0x11d8, 0x60e3, 0x0001, 0x600c, 0xc0b4, 0x600e,
-	0x080c, 0x4df5, 0x6803, 0x0000, 0x708b, 0x0026, 0x2001, 0x9225,
-	0x2003, 0x0000, 0x0058, 0x708b, 0x001e, 0x0040, 0x708b, 0x001d,
-	0x0028, 0x708b, 0x0020, 0x0010, 0x708b, 0x001f, 0x0005, 0x60e3,
-	0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, 0x4df5, 0x6803, 0x0000,
-	0x6124, 0xd1d4, 0x11a0, 0xd1dc, 0x1178, 0xd1e4, 0x1150, 0xa184,
-	0x1e00, 0x1178, 0x708b, 0x0026, 0x2001, 0x9225, 0x2003, 0x0000,
-	0x0040, 0x708b, 0x001e, 0x0028, 0x708b, 0x001d, 0x0010, 0x708b,
-	0x001f, 0x0005, 0x6803, 0x0020, 0x6124, 0xd1dc, 0x1128, 0xd1e4,
-	0x0128, 0x708b, 0x001e, 0x0010, 0x708b, 0x001d, 0x0005, 0x080c,
-	0x4d03, 0x6124, 0xd1dc, 0x1158, 0x080c, 0x4cd7, 0xd1d4, 0x1128,
-	0xd1e4, 0x0128, 0x708b, 0x001e, 0x0010, 0x708b, 0x001f, 0x0005,
-	0x6803, 0x0020, 0x6124, 0xd1d4, 0x1160, 0xd1cc, 0x1150, 0xd1dc,
-	0x1128, 0xd1e4, 0x0140, 0x708b, 0x001e, 0x0028, 0x708b, 0x001d,
-	0x0010, 0x708b, 0x0021, 0x0005, 0x080c, 0x4d03, 0x6124, 0xd1d4,
-	0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x708b, 0x001e, 0x0028,
-	0x708b, 0x001d, 0x0010, 0x708b, 0x001f, 0x0005, 0x6803, 0x0010,
-	0x6124, 0xd1d4, 0x1178, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4,
-	0x0158, 0x708b, 0x001e, 0x0040, 0x708b, 0x001d, 0x0028, 0x708b,
-	0x0020, 0x0010, 0x708b, 0x001f, 0x0005, 0x00c6, 0x00d6, 0x00e6,
-	0x0126, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x9200, 0x2091,
-	0x8000, 0x080c, 0x4de1, 0x0150, 0x080c, 0x4dd7, 0x1138, 0x2001,
-	0x0001, 0x080c, 0x23ba, 0x080c, 0x4d9a, 0x00a0, 0x080c, 0x4d00,
-	0x0178, 0x2001, 0x0001, 0x080c, 0x23ba, 0x7088, 0xa086, 0x001e,
-	0x0120, 0x7088, 0xa086, 0x0022, 0x1118, 0x708b, 0x0025, 0x0010,
-	0x708b, 0x0021, 0x012e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0016,
-	0x0026, 0x2009, 0x0064, 0x2011, 0x4ce2, 0x080c, 0x57b3, 0x002e,
-	0x001e, 0x0005, 0x00e6, 0x00f6, 0x0016, 0x080c, 0x6f1e, 0x2071,
-	0x9200, 0x080c, 0x4ca5, 0x001e, 0x00fe, 0x00ee, 0x0005, 0x0026,
-	0x00e6, 0x2011, 0x4ce2, 0x2071, 0x94f8, 0x701c, 0xa206, 0x1118,
-	0x7018, 0xa005, 0x0110, 0xa085, 0x0001, 0x00ee, 0x002e, 0x0005,
-	0x6020, 0xd09c, 0x0005, 0x6803, 0x0040, 0x0156, 0x20a9, 0x002d,
-	0x1d04, 0x4d08, 0x2091, 0x6000, 0x1f04, 0x4d08, 0x015e, 0x0005,
-	0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071,
-	0x9200, 0x2001, 0x94d8, 0x200c, 0xa186, 0x0000, 0x0158, 0xa186,
-	0x0001, 0x0158, 0xa186, 0x0002, 0x0158, 0xa186, 0x0003, 0x0158,
-	0x0804, 0x4d88, 0x708b, 0x0022, 0x0048, 0x708b, 0x0021, 0x0030,
-	0x708b, 0x0023, 0x0038, 0x708b, 0x0024, 0x0020, 0xa085, 0x0001,
-	0x080c, 0x4e05, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001,
-	0x080c, 0x2460, 0x0026, 0x2011, 0x0003, 0x080c, 0x718f, 0x002e,
-	0x7000, 0xa08e, 0x0004, 0x0118, 0x602b, 0x0028, 0x0010, 0x602b,
-	0x0020, 0x0156, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, 0x6024,
-	0xd0ac, 0x0118, 0x012e, 0x015e, 0x04c8, 0x6803, 0x0080, 0x6803,
-	0x0000, 0x6904, 0xd1d4, 0x1130, 0x6803, 0x0100, 0x1f04, 0x4d57,
-	0x080c, 0x4e12, 0x012e, 0x015e, 0x080c, 0x4dd7, 0x01a8, 0x6044,
-	0xa005, 0x0168, 0x6050, 0x0006, 0xa085, 0x0020, 0x6052, 0x080c,
-	0x4e12, 0xa006, 0x8001, 0x1df0, 0x000e, 0x6052, 0x0028, 0x6804,
-	0xd0d4, 0x1110, 0x080c, 0x4e12, 0x2001, 0x94d8, 0x2003, 0x0004,
-	0x080c, 0x4bd3, 0x080c, 0x4dd7, 0x0148, 0x6804, 0xd0d4, 0x1130,
-	0xd0dc, 0x1100, 0x2001, 0x94d8, 0x2003, 0x0000, 0x00ee, 0x00de,
-	0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069,
-	0x0140, 0x2071, 0x9200, 0x2001, 0x94d7, 0x2003, 0x0000, 0x2001,
-	0x94c8, 0x2003, 0x0000, 0x708b, 0x0000, 0x60e3, 0x0000, 0x6887,
-	0x0000, 0x2001, 0x0000, 0x080c, 0x2460, 0x6803, 0x0000, 0x6043,
-	0x0090, 0x6027, 0xffff, 0x602b, 0x002f, 0x2001, 0x9225, 0x2003,
-	0x0000, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0006, 0x2001, 0x94d7,
-	0x2004, 0xa086, 0xaaaa, 0x000e, 0x0005, 0x0006, 0x2001, 0x9271,
-	0x2004, 0xa084, 0x0030, 0xa086, 0x0000, 0x000e, 0x0005, 0x0006,
-	0x2001, 0x9271, 0x2004, 0xa084, 0x0030, 0xa086, 0x0030, 0x000e,
-	0x0005, 0x0006, 0x2001, 0x9271, 0x2004, 0xa084, 0x0030, 0xa086,
-	0x0010, 0x000e, 0x0005, 0x0006, 0x2001, 0x9271, 0x2004, 0xa084,
-	0x0030, 0xa086, 0x0020, 0x000e, 0x0005, 0x2001, 0x920c, 0x2004,
-	0xd0a4, 0x0150, 0x080c, 0x2480, 0x0036, 0x2019, 0x0028, 0x080c,
-	0x264b, 0x003e, 0xa006, 0x0009, 0x0005, 0x00e6, 0x2071, 0x920c,
-	0x2e04, 0x0118, 0xa085, 0x0010, 0x0010, 0xa084, 0xffef, 0x2072,
-	0x00ee, 0x0005, 0x6050, 0x0006, 0x60f0, 0x0006, 0x60ec, 0x0006,
-	0x600c, 0x0006, 0x6004, 0x0006, 0x6028, 0x0006, 0x602f, 0x0100,
-	0x602f, 0x0000, 0x602f, 0x0080, 0x602f, 0x0000, 0x000e, 0x602a,
-	0x000e, 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x000e, 0x60f2,
-	0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x2460,
-	0x6803, 0x0080, 0x6803, 0x0000, 0x6803, 0x0020, 0x000e, 0x6052,
-	0x6050, 0x0005, 0x2071, 0x92f6, 0x7003, 0x0000, 0x7007, 0x0000,
-	0x700f, 0x0000, 0x702b, 0x0001, 0x704f, 0x0000, 0x7053, 0x0001,
-	0x705f, 0x0020, 0x7063, 0x0040, 0x7083, 0x0000, 0x708b, 0x0000,
-	0x708f, 0x0001, 0x70bf, 0x0000, 0x0005, 0x00e6, 0x2071, 0x92f6,
-	0x6848, 0xa005, 0x1130, 0x7028, 0xc085, 0x702a, 0xa085, 0x0001,
-	0x0428, 0x6a50, 0x7236, 0x6b54, 0x733a, 0x6858, 0x703e, 0x707a,
-	0x685c, 0x7042, 0x707e, 0x6848, 0x702e, 0x6840, 0x7032, 0x2009,
-	0x000c, 0x200a, 0x8007, 0x8006, 0x8006, 0xa08c, 0x003f, 0xa084,
-	0xffc0, 0xa210, 0x2100, 0xa319, 0x7272, 0x7376, 0x7028, 0xc084,
-	0x702a, 0x7007, 0x0001, 0x700f, 0x0000, 0xa006, 0x00ee, 0x0005,
-	0x2b78, 0x2071, 0x92f6, 0x7004, 0x0043, 0x700c, 0x0002, 0x4e9c,
-	0x4e93, 0x4e93, 0x4e93, 0x4e93, 0x0005, 0x4ef2, 0x4ef3, 0x4f25,
-	0x4f26, 0x4ef0, 0x4f5a, 0x4f5f, 0x4f90, 0x4f91, 0x4fac, 0x4fad,
-	0x4fae, 0x4faf, 0x4fb0, 0x4fb1, 0x502d, 0x5054, 0x700c, 0x0002,
-	0x4eb5, 0x4ef0, 0x4ef0, 0x4ef1, 0x4ef1, 0x7830, 0x7930, 0xa106,
-	0x0120, 0x7830, 0x7930, 0xa106, 0x1510, 0x7030, 0xa10a, 0x01f8,
-	0x1210, 0x712c, 0xa10a, 0xa18a, 0x0002, 0x12d0, 0x080c, 0x145f,
-	0x01b0, 0x2d00, 0x705a, 0x7063, 0x0040, 0x2001, 0x0003, 0x7057,
-	0x0000, 0x0126, 0x0006, 0x2091, 0x8000, 0x2009, 0x9508, 0x2104,
-	0xc085, 0x200a, 0x000e, 0x700e, 0x012e, 0x080c, 0x14df, 0x0005,
-	0x080c, 0x145f, 0x0de0, 0x2d00, 0x705a, 0x080c, 0x145f, 0x1108,
-	0x0c10, 0x2d00, 0x7086, 0x7063, 0x0080, 0x2001, 0x0004, 0x08f8,
-	0x0005, 0x0005, 0x0005, 0x700c, 0x0002, 0x4efa, 0x4efd, 0x4f0b,
-	0x4f24, 0x4f24, 0x080c, 0x4eae, 0x0005, 0x0126, 0x8001, 0x700e,
-	0x7058, 0x0006, 0x080c, 0x5311, 0x0120, 0x2091, 0x8000, 0x080c,
-	0x4eae, 0x00de, 0x0048, 0x0126, 0x8001, 0x700e, 0x080c, 0x5311,
-	0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000,
-	0x6834, 0xa084, 0x00ff, 0xa08a, 0x0020, 0x1218, 0x00db, 0x012e,
-	0x0005, 0x012e, 0x080c, 0x4fb2, 0x0005, 0x0005, 0x0005, 0x00e6,
-	0x2071, 0x92f6, 0x700c, 0x0002, 0x4f31, 0x4f31, 0x4f31, 0x4f33,
-	0x4f36, 0x00ee, 0x0005, 0x700f, 0x0001, 0x0010, 0x700f, 0x0002,
-	0x00ee, 0x0005, 0x4fb2, 0x4fb2, 0x4fce, 0x4fb2, 0x50e0, 0x4fb2,
-	0x4fb2, 0x4fb2, 0x4fb2, 0x4fb2, 0x4fce, 0x5119, 0x515c, 0x51a5,
-	0x51b9, 0x4fb2, 0x4fb2, 0x4fea, 0x4fce, 0x4ffe, 0x4fb2, 0x5013,
-	0x5243, 0x525e, 0x4fb2, 0x4fea, 0x4fb2, 0x4ffe, 0x4fb2, 0x4fb2,
-	0x5013, 0x525e, 0x7020, 0x2068, 0x080c, 0x1493, 0x0005, 0x700c,
-	0x0002, 0x4f66, 0x4f69, 0x4f77, 0x4f8f, 0x4f8f, 0x080c, 0x4eae,
-	0x0005, 0x0126, 0x8001, 0x700e, 0x7058, 0x0006, 0x080c, 0x5311,
-	0x0120, 0x2091, 0x8000, 0x080c, 0x4eae, 0x00de, 0x0048, 0x0126,
-	0x8001, 0x700e, 0x080c, 0x5311, 0x7058, 0x2068, 0x7084, 0x705a,
+	0x0010, 0x6124, 0xd1d4, 0x1178, 0xd1cc, 0x1150, 0xd1dc, 0x1128,
+	0xd1e4, 0x0158, 0x708b, 0x001e, 0x0040, 0x708b, 0x001d, 0x0028,
+	0x708b, 0x0020, 0x0010, 0x708b, 0x001f, 0x0005, 0x00c6, 0x00d6,
+	0x00e6, 0x0126, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x8b00,
+	0x2091, 0x8000, 0x080c, 0x4c42, 0x11b8, 0x7088, 0xa086, 0x0027,
+	0x1198, 0x6027, 0x0200, 0xe000, 0xe000, 0x6024, 0xd0cc, 0x0148,
+	0x2001, 0x8d9d, 0x2003, 0x0001, 0x2001, 0x8b00, 0x2003, 0x0001,
+	0x0420, 0x6028, 0xc0cd, 0x602a, 0x080c, 0x4c5e, 0x0150, 0x080c,
+	0x4c54, 0x1138, 0x2001, 0x0001, 0x080c, 0x2298, 0x080c, 0x4c15,
+	0x00a0, 0x080c, 0x4b7b, 0x0178, 0x2001, 0x0001, 0x080c, 0x2298,
+	0x7088, 0xa086, 0x001e, 0x0120, 0x7088, 0xa086, 0x0022, 0x1118,
+	0x708b, 0x0025, 0x0010, 0x708b, 0x0021, 0x012e, 0x00ee, 0x00de,
+	0x00ce, 0x0005, 0x0016, 0x0026, 0x2009, 0x0064, 0x2011, 0x4b5d,
+	0x080c, 0x5601, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00f6, 0x0016,
+	0x080c, 0x66f7, 0x2071, 0x8b00, 0x080c, 0x4b06, 0x001e, 0x00fe,
+	0x00ee, 0x0005, 0x0026, 0x00e6, 0x2011, 0x4b5d, 0x2071, 0x8dbd,
+	0x701c, 0xa206, 0x1118, 0x7018, 0xa005, 0x0110, 0xa085, 0x0001,
+	0x00ee, 0x002e, 0x0005, 0x6020, 0xd09c, 0x0005, 0x6803, 0x0040,
+	0x0156, 0x20a9, 0x002d, 0x1d04, 0x4b83, 0x2091, 0x6000, 0x1f04,
+	0x4b83, 0x015e, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100,
+	0x2069, 0x0140, 0x2071, 0x8b00, 0x2001, 0x8d9d, 0x200c, 0xa186,
+	0x0000, 0x0158, 0xa186, 0x0001, 0x0158, 0xa186, 0x0002, 0x0158,
+	0xa186, 0x0003, 0x0158, 0x0804, 0x4c03, 0x708b, 0x0022, 0x0048,
+	0x708b, 0x0021, 0x0030, 0x708b, 0x0023, 0x0038, 0x708b, 0x0024,
+	0x0020, 0xa085, 0x0001, 0x080c, 0x4c82, 0x60e3, 0x0000, 0x6887,
+	0x0001, 0x2001, 0x0001, 0x080c, 0x233e, 0x0026, 0x2011, 0x0003,
+	0x080c, 0x695c, 0x002e, 0x7000, 0xa08e, 0x0004, 0x0118, 0x602b,
+	0x0028, 0x0010, 0x602b, 0x0020, 0x0156, 0x0126, 0x2091, 0x8000,
+	0x20a9, 0x0005, 0x6024, 0xd0ac, 0x0118, 0x012e, 0x015e, 0x04c8,
+	0x6803, 0x0080, 0x6803, 0x0000, 0x6904, 0xd1d4, 0x1130, 0x6803,
+	0x0100, 0x1f04, 0x4bd2, 0x080c, 0x4c8f, 0x012e, 0x015e, 0x080c,
+	0x4c54, 0x01a8, 0x6044, 0xa005, 0x0168, 0x6050, 0x0006, 0xa085,
+	0x0020, 0x6052, 0x080c, 0x4c8f, 0xa006, 0x8001, 0x1df0, 0x000e,
+	0x6052, 0x0028, 0x6804, 0xd0d4, 0x1110, 0x080c, 0x4c8f, 0x2001,
+	0x8d9d, 0x2003, 0x0004, 0x080c, 0x4a20, 0x080c, 0x4c54, 0x0148,
+	0x6804, 0xd0d4, 0x1130, 0xd0dc, 0x1100, 0x2001, 0x8d9d, 0x2003,
+	0x0000, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6,
+	0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x8b00, 0x2001, 0x8d9c,
+	0x2003, 0x0000, 0x2001, 0x8d8d, 0x2003, 0x0000, 0x708b, 0x0000,
+	0x60e3, 0x0000, 0x6887, 0x0000, 0x2001, 0x0000, 0x080c, 0x233e,
+	0x6803, 0x0000, 0x6043, 0x0090, 0x6043, 0x0010, 0x2001, 0x8b25,
+	0x2003, 0x0000, 0x6027, 0xffff, 0x602b, 0x182f, 0x00ee, 0x00de,
+	0x00ce, 0x0005, 0x0006, 0x2001, 0x8d9c, 0x2004, 0xa086, 0xaaaa,
+	0x000e, 0x0005, 0x0006, 0x2001, 0x8b71, 0x2004, 0xa084, 0x0030,
+	0xa086, 0x0000, 0x000e, 0x0005, 0x0006, 0x2001, 0x8b71, 0x2004,
+	0xa084, 0x0030, 0xa086, 0x0030, 0x000e, 0x0005, 0x0006, 0x2001,
+	0x8b71, 0x2004, 0xa084, 0x0030, 0xa086, 0x0010, 0x000e, 0x0005,
+	0x0006, 0x2001, 0x8b71, 0x2004, 0xa084, 0x0030, 0xa086, 0x0020,
+	0x000e, 0x0005, 0x2001, 0x8b0c, 0x2004, 0xd0a4, 0x0150, 0x080c,
+	0x235e, 0x0036, 0x2019, 0x0028, 0x080c, 0x2542, 0x003e, 0xa006,
+	0x0009, 0x0005, 0x00e6, 0x2071, 0x8b0c, 0x2e04, 0x0118, 0xa085,
+	0x0010, 0x0010, 0xa084, 0xffef, 0x2072, 0x00ee, 0x0005, 0x6050,
+	0x0006, 0x60f0, 0x0006, 0x60ec, 0x0006, 0x600c, 0x0006, 0x6004,
+	0x0006, 0x6028, 0x0006, 0x602f, 0x0100, 0x602f, 0x0000, 0x602f,
+	0x0080, 0x602f, 0x0000, 0x000e, 0x602a, 0x000e, 0x6006, 0x000e,
+	0x600e, 0x000e, 0x60ee, 0x000e, 0x60f2, 0x60e3, 0x0000, 0x6887,
+	0x0001, 0x2001, 0x0001, 0x080c, 0x233e, 0x6803, 0x0080, 0x6803,
+	0x0000, 0x6803, 0x0020, 0x000e, 0x6052, 0x6050, 0x0005, 0x0156,
+	0x0016, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140,
+	0x2071, 0x8b00, 0x6028, 0xa084, 0xe1ff, 0x602a, 0x6027, 0x0200,
+	0x6803, 0x0010, 0x20a9, 0x04e2, 0x6024, 0xd0cc, 0x1188, 0x1d04,
+	0x4cd4, 0x2091, 0x6000, 0x1f04, 0x4cd4, 0x2001, 0x8d9d, 0x2003,
+	0x0001, 0x2001, 0x8b00, 0x2003, 0x0001, 0xa085, 0x0001, 0x0410,
+	0x6803, 0x0000, 0x20a9, 0x04e2, 0x6027, 0x1e00, 0x2009, 0x1e00,
+	0xe000, 0x6024, 0xa10c, 0x0138, 0x1d04, 0x4cec, 0x2091, 0x6000,
+	0x1f04, 0x4cec, 0x0c10, 0x6028, 0xa085, 0x1e00, 0x602a, 0x60e3,
+	0x0000, 0x709c, 0x6886, 0x2001, 0x8d8d, 0x2004, 0x080c, 0x233e,
+	0x60e2, 0xa006, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x015e, 0x0005,
+	0x0156, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071,
+	0x8b00, 0x2069, 0x0200, 0x6804, 0xa005, 0x1118, 0x6808, 0xa005,
+	0x0158, 0x6028, 0xa084, 0xfbff, 0x602a, 0x6027, 0x0400, 0x708b,
+	0x0026, 0x7003, 0x0001, 0x0460, 0x2069, 0x0140, 0x6803, 0x0008,
+	0x20a9, 0x04e2, 0x6027, 0x1e00, 0x2009, 0x1e00, 0xe000, 0x6024,
+	0xa10c, 0x0188, 0x1d04, 0x4d32, 0x2091, 0x6000, 0x1f04, 0x4d32,
+	0x2001, 0x8d9d, 0x2003, 0x0001, 0x2001, 0x8b00, 0x2003, 0x0001,
+	0xa085, 0x0001, 0x0068, 0x6803, 0x0000, 0x60e3, 0x0000, 0x709c,
+	0x6886, 0x2001, 0x8d8d, 0x2004, 0x080c, 0x233e, 0x60e2, 0xa006,
+	0x00ee, 0x00de, 0x00ce, 0x001e, 0x015e, 0x0005, 0x2071, 0x8be1,
+	0x7003, 0x0000, 0x7007, 0x0000, 0x700f, 0x0000, 0x702b, 0x0001,
+	0x704f, 0x0000, 0x7053, 0x0001, 0x705f, 0x0020, 0x7063, 0x0040,
+	0x7083, 0x0000, 0x708b, 0x0000, 0x708f, 0x0001, 0x70bf, 0x0000,
+	0x0005, 0x00e6, 0x2071, 0x8be1, 0x6848, 0xa005, 0x1130, 0x7028,
+	0xc085, 0x702a, 0xa085, 0x0001, 0x0428, 0x6a50, 0x7236, 0x6b54,
+	0x733a, 0x6858, 0x703e, 0x707a, 0x685c, 0x7042, 0x707e, 0x6848,
+	0x702e, 0x6840, 0x7032, 0x2009, 0x000c, 0x200a, 0x8007, 0x8006,
+	0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319,
+	0x7272, 0x7376, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700f,
+	0x0000, 0xa006, 0x00ee, 0x0005, 0x2b78, 0x2071, 0x8be1, 0x7004,
+	0x0043, 0x700c, 0x0002, 0x4db8, 0x4daf, 0x4daf, 0x4daf, 0x4daf,
+	0x0005, 0x4e0e, 0x4e0f, 0x4e41, 0x4e42, 0x4e0c, 0x4e76, 0x4e7b,
+	0x4eac, 0x4ead, 0x4ec8, 0x4ec9, 0x4eca, 0x4ecb, 0x4ecc, 0x4ecd,
+	0x4f32, 0x4f59, 0x700c, 0x0002, 0x4dd1, 0x4e0c, 0x4e0c, 0x4e0d,
+	0x4e0d, 0x7830, 0x7930, 0xa106, 0x0120, 0x7830, 0x7930, 0xa106,
+	0x1510, 0x7030, 0xa10a, 0x01f8, 0x1210, 0x712c, 0xa10a, 0xa18a,
+	0x0002, 0x12d0, 0x080c, 0x146f, 0x01b0, 0x2d00, 0x705a, 0x7063,
+	0x0040, 0x2001, 0x0003, 0x7057, 0x0000, 0x0126, 0x0006, 0x2091,
+	0x8000, 0x2009, 0x8dcd, 0x2104, 0xc085, 0x200a, 0x000e, 0x700e,
+	0x012e, 0x080c, 0x14eb, 0x0005, 0x080c, 0x146f, 0x0de0, 0x2d00,
+	0x705a, 0x080c, 0x146f, 0x1108, 0x0c10, 0x2d00, 0x7086, 0x7063,
+	0x0080, 0x2001, 0x0004, 0x08f8, 0x0005, 0x0005, 0x0005, 0x700c,
+	0x0002, 0x4e16, 0x4e19, 0x4e27, 0x4e40, 0x4e40, 0x080c, 0x4dca,
+	0x0005, 0x0126, 0x8001, 0x700e, 0x7058, 0x0006, 0x080c, 0x51f4,
+	0x0120, 0x2091, 0x8000, 0x080c, 0x4dca, 0x00de, 0x0048, 0x0126,
+	0x8001, 0x700e, 0x080c, 0x51f4, 0x7058, 0x2068, 0x7084, 0x705a,
 	0x6803, 0x0000, 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a,
-	0x001a, 0x1218, 0x003b, 0x012e, 0x0005, 0x012e, 0x0419, 0x0005,
-	0x0005, 0x0005, 0x4fb2, 0x4fce, 0x50cc, 0x4fb2, 0x4fce, 0x4fb2,
-	0x4fce, 0x4fce, 0x4fb2, 0x4fce, 0x50cc, 0x4fce, 0x4fce, 0x4fce,
-	0x4fce, 0x4fce, 0x4fb2, 0x4fce, 0x50cc, 0x4fb2, 0x4fb2, 0x4fce,
-	0x4fb2, 0x4fb2, 0x4fb2, 0x4fce, 0x0005, 0x0005, 0x0005, 0x0005,
-	0x0005, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0d5,
-	0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x4809, 0x012e, 0x0005,
-	0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0e5, 0x683a, 0x0126,
-	0x2091, 0x8000, 0x080c, 0x4809, 0x012e, 0x0005, 0x7007, 0x0001,
-	0x6838, 0xa084, 0x00ff, 0xc0ed, 0x683a, 0x0126, 0x2091, 0x8000,
-	0x080c, 0x4809, 0x012e, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084,
-	0x00ff, 0xc0dd, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x4809,
-	0x012e, 0x0005, 0x6834, 0x8007, 0xa084, 0x00ff, 0x0988, 0x8001,
-	0x1120, 0x7007, 0x0001, 0x0804, 0x508d, 0x7007, 0x0006, 0x7012,
-	0x2d00, 0x7016, 0x701a, 0x704b, 0x508d, 0x0005, 0x6834, 0x8007,
-	0xa084, 0x00ff, 0x0904, 0x4fc0, 0x8001, 0x1120, 0x7007, 0x0001,
-	0x0804, 0x50ac, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a,
-	0x704b, 0x50ac, 0x0005, 0x2d00, 0x7016, 0x701a, 0x20a9, 0x0004,
-	0xa080, 0x0024, 0x2098, 0x20a1, 0x9321, 0x53a3, 0x6858, 0x7012,
-	0xa082, 0x0401, 0x1a04, 0x4fdc, 0x6884, 0xa08a, 0x0003, 0x1a04,
-	0x4fdc, 0xa080, 0x507e, 0x2005, 0x70c6, 0x7010, 0xa015, 0x0904,
-	0x5072, 0x080c, 0x145f, 0x1118, 0x7007, 0x000f, 0x0005, 0x2d00,
-	0x7022, 0x70c4, 0x2060, 0x2c05, 0x6836, 0xe004, 0xad00, 0x7096,
-	0xe008, 0xa20a, 0x1210, 0xa00e, 0x2200, 0x7112, 0xe20c, 0x8003,
-	0x800b, 0xa296, 0x0004, 0x0108, 0xa108, 0x719a, 0x810b, 0x719e,
-	0xae90, 0x0022, 0x080c, 0x14c7, 0x7090, 0xa08e, 0x0100, 0x0170,
-	0xa086, 0x0200, 0x0118, 0x7007, 0x0010, 0x0005, 0x7020, 0x2068,
-	0x080c, 0x1493, 0x7014, 0x2068, 0x0804, 0x4fdc, 0x7020, 0x2068,
-	0x7018, 0x6802, 0x6807, 0x0000, 0x2d08, 0x2068, 0x6906, 0x711a,
-	0x0804, 0x502d, 0x7014, 0x2068, 0x7007, 0x0001, 0x6834, 0xa084,
-	0x00ff, 0xa086, 0x001e, 0x0904, 0x5276, 0x0078, 0x5081, 0x5085,
-	0x5089, 0x0002, 0x0011, 0x0007, 0x0004, 0x000a, 0x000f, 0x0005,
-	0x0006, 0x0012, 0x000f, 0x0005, 0x0006, 0x2009, 0x922f, 0x210c,
-	0x81ff, 0x11a8, 0x6838, 0xa084, 0x00ff, 0x683a, 0x6853, 0x0000,
-	0x080c, 0x423e, 0x1108, 0x0005, 0x080c, 0x492c, 0x0126, 0x2091,
-	0x8000, 0x080c, 0x8527, 0x080c, 0x4809, 0x012e, 0x0ca0, 0x2001,
-	0x0028, 0x2009, 0x0000, 0x0c80, 0x2009, 0x922f, 0x210c, 0x81ff,
-	0x11a8, 0x6858, 0xa005, 0x01a8, 0x6838, 0xa084, 0x00ff, 0x683a,
-	0x6853, 0x0000, 0x080c, 0x42db, 0x1108, 0x0005, 0x684a, 0x0126,
-	0x2091, 0x8000, 0x080c, 0x4809, 0x012e, 0x0cb8, 0x2001, 0x0028,
-	0x0ca8, 0x2001, 0x0000, 0x0c90, 0x7018, 0x6802, 0x2d08, 0x2068,
-	0x6906, 0x711a, 0x7010, 0x8001, 0x7012, 0x0118, 0x7007, 0x0006,
-	0x0030, 0x7014, 0x2068, 0x7007, 0x0001, 0x7048, 0x080f, 0x0005,
-	0x7007, 0x0001, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x6848, 0xa084,
-	0x00ff, 0x20a9, 0x0001, 0xa096, 0x0001, 0x01b0, 0x2009, 0x0000,
-	0x20a9, 0x007e, 0xa096, 0x0002, 0x0178, 0xa005, 0x11f8, 0x6944,
-	0x810f, 0xa18c, 0x00ff, 0x080c, 0x4434, 0x11c0, 0x0066, 0x6e50,
-	0x080c, 0x450d, 0x006e, 0x0090, 0x0046, 0x2011, 0x920c, 0x2224,
-	0xc484, 0xc48c, 0x2412, 0x004e, 0x00c6, 0x080c, 0x4434, 0x1110,
-	0x080c, 0x4664, 0x8108, 0x1f04, 0x510d, 0x00ce, 0x080c, 0x1493,
-	0x0005, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0x9252,
-	0x2004, 0xd0a4, 0x0580, 0x2061, 0x9566, 0x6100, 0xd184, 0x0178,
-	0x6858, 0xa084, 0x00ff, 0x1550, 0x6000, 0xd084, 0x0520, 0x6004,
-	0xa005, 0x1538, 0x6003, 0x0000, 0x600b, 0x0000, 0x00c8, 0x2011,
-	0x0001, 0x6860, 0xa005, 0x1110, 0x2001, 0x001e, 0x8000, 0x6016,
-	0x6858, 0xa084, 0x00ff, 0x0178, 0x6006, 0x6858, 0x8007, 0xa084,
-	0x00ff, 0x0148, 0x600a, 0x6858, 0x8000, 0x1108, 0xc28d, 0x6202,
-	0x012e, 0x0804, 0x5300, 0x012e, 0x0804, 0x52fa, 0x012e, 0x0804,
-	0x52f4, 0x012e, 0x0804, 0x52f7, 0x0126, 0x2091, 0x8000, 0x7007,
-	0x0001, 0x2001, 0x9252, 0x2004, 0xd0a4, 0x05e0, 0x2061, 0x9566,
-	0x6000, 0xd084, 0x05b8, 0x6204, 0x6308, 0xd08c, 0x1530, 0x6c48,
-	0xa484, 0x0003, 0x0170, 0x6958, 0xa18c, 0x00ff, 0x8001, 0x1120,
-	0x2100, 0xa210, 0x0620, 0x0028, 0x8001, 0x1508, 0x2100, 0xa212,
-	0x02f0, 0xa484, 0x000c, 0x0188, 0x6958, 0x810f, 0xa18c, 0x00ff,
-	0xa082, 0x0004, 0x1120, 0x2100, 0xa318, 0x0288, 0x0030, 0xa082,
-	0x0004, 0x1168, 0x2100, 0xa31a, 0x0250, 0x6860, 0xa005, 0x0110,
-	0x8000, 0x6016, 0x6206, 0x630a, 0x012e, 0x0804, 0x5300, 0x012e,
-	0x0804, 0x52fd, 0x012e, 0x0804, 0x52fa, 0x0126, 0x2091, 0x8000,
-	0x7007, 0x0001, 0x2061, 0x9566, 0x6300, 0xd38c, 0x1120, 0x6308,
-	0x8318, 0x0220, 0x630a, 0x012e, 0x0804, 0x530e, 0x012e, 0x0804,
-	0x52fd, 0x0126, 0x00c6, 0x2091, 0x8000, 0x7007, 0x0001, 0x684c,
-	0xd0ac, 0x0148, 0x00c6, 0x2061, 0x9566, 0x6000, 0xa084, 0xfcff,
-	0x6002, 0x00ce, 0x04d8, 0x6858, 0xa005, 0x0904, 0x521a, 0x685c,
-	0xa065, 0x0904, 0x5216, 0x2001, 0x922f, 0x2004, 0xa005, 0x0118,
-	0x080c, 0x849b, 0x0030, 0x6013, 0x0400, 0x2009, 0x0041, 0x080c,
-	0x7518, 0x6958, 0xa18c, 0xf600, 0xa186, 0x2000, 0x01b8, 0xa186,
-	0x0400, 0x01a0, 0xa186, 0x1000, 0x0140, 0xa186, 0x4000, 0x01b0,
-	0x6118, 0x2104, 0xc0fc, 0x200a, 0x0088, 0x00c6, 0x2061, 0x9566,
-	0x6000, 0xa084, 0xfdff, 0x6002, 0x00ce, 0x0040, 0x0026, 0x2009,
-	0x0000, 0x2011, 0xfdff, 0x080c, 0x585b, 0x002e, 0x684c, 0xd0c4,
-	0x0148, 0x2061, 0x9566, 0x6000, 0xd08c, 0x1120, 0x6008, 0x8000,
-	0x0208, 0x600a, 0x00ce, 0x012e, 0x0804, 0x5300, 0x00ce, 0x012e,
-	0x0804, 0x52fa, 0x6954, 0xa186, 0x002e, 0x0d40, 0xa186, 0x002d,
-	0x0d28, 0xa186, 0x002a, 0x1130, 0x2001, 0x920c, 0x200c, 0xc194,
-	0x2102, 0x08e0, 0xa186, 0x0020, 0x0170, 0xa186, 0x0029, 0x1d30,
-	0x6944, 0xa18c, 0xff00, 0x810f, 0x080c, 0x4434, 0x1978, 0x6000,
-	0xc0e4, 0x6002, 0x0858, 0x685c, 0xa065, 0x09c0, 0x2001, 0x94dd,
-	0x2004, 0x6016, 0x0818, 0x2061, 0x9566, 0x6000, 0xd084, 0x0190,
-	0xd08c, 0x1904, 0x530e, 0x0126, 0x2091, 0x8000, 0x6204, 0x8210,
-	0x0220, 0x6206, 0x012e, 0x0804, 0x530e, 0x012e, 0x6853, 0x0016,
-	0x0804, 0x5307, 0x6853, 0x0007, 0x0804, 0x5307, 0x6834, 0x8007,
-	0xa084, 0x00ff, 0x1118, 0x080c, 0x4fc0, 0x0078, 0x2030, 0x8001,
-	0x1120, 0x7007, 0x0001, 0x0051, 0x0040, 0x7007, 0x0006, 0x7012,
-	0x2d00, 0x7016, 0x701a, 0x704b, 0x5276, 0x0005, 0x00e6, 0x0126,
-	0x2091, 0x8000, 0x2009, 0x922f, 0x210c, 0x81ff, 0x1904, 0x52e9,
-	0x2009, 0x920c, 0x210c, 0xd194, 0x1904, 0x52f1, 0x6848, 0x2070,
-	0xae82, 0x9900, 0x0a04, 0x52dd, 0x2001, 0x9216, 0x2004, 0xae02,
-	0x1a04, 0x52dd, 0x2061, 0x9566, 0x6100, 0xa184, 0x0001, 0x0578,
-	0xa184, 0x0100, 0x1904, 0x52e0, 0xa184, 0x0200, 0x1904, 0x52e3,
-	0x601c, 0xa005, 0x1904, 0x52e6, 0x711c, 0xa186, 0x0006, 0x1520,
-	0x7018, 0xa005, 0x05f0, 0x2004, 0xd0e4, 0x15f0, 0xd0fc, 0x1598,
-	0x6853, 0x0000, 0x6803, 0x0000, 0x2d08, 0x7010, 0xa005, 0x1138,
-	0x7112, 0x2e60, 0x080c, 0x57ca, 0x012e, 0x00ee, 0x0005, 0x2068,
-	0x6800, 0xa005, 0x1de0, 0x6902, 0x012e, 0x00ee, 0x0005, 0x012e,
-	0x00ee, 0x6853, 0x0006, 0x04d8, 0x6944, 0xa18c, 0xff00, 0x810f,
-	0x080c, 0x4434, 0x11c8, 0x6000, 0xd0e4, 0x11b0, 0x711c, 0xa186,
-	0x0007, 0x1118, 0x6853, 0x0002, 0x0088, 0x6853, 0x0008, 0x0070,
-	0x6853, 0x000e, 0x0058, 0x6853, 0x0017, 0x0040, 0x6853, 0x0035,
-	0x0028, 0x6853, 0x0028, 0x0010, 0x6853, 0x0029, 0x012e, 0x00ee,
-	0x00b0, 0x6853, 0x002a, 0x0cd0, 0x2009, 0x003e, 0x0058, 0x2009,
-	0x0004, 0x0040, 0x2009, 0x0006, 0x0028, 0x2009, 0x0016, 0x0010,
-	0x2009, 0x0001, 0x6854, 0xa084, 0xff00, 0xa105, 0x6856, 0x0126,
-	0x2091, 0x8000, 0x080c, 0x4809, 0x012e, 0x0005, 0x080c, 0x1493,
-	0x0005, 0x702c, 0x7130, 0x8108, 0xa102, 0x0230, 0xa00e, 0x7034,
-	0x7072, 0x7038, 0x7076, 0x0058, 0x7070, 0xa080, 0x0040, 0x7072,
-	0x1230, 0x7074, 0xa081, 0x0000, 0x7076, 0xa085, 0x0001, 0x7932,
-	0x7132, 0x0005, 0x00d6, 0x080c, 0x57c1, 0x00de, 0x0005, 0x00d6,
-	0x2011, 0x0004, 0x2204, 0xa085, 0x8002, 0x2012, 0x00de, 0x0005,
-	0x20e1, 0x0002, 0x3d08, 0x20e1, 0x2000, 0x3d00, 0xa084, 0x7000,
-	0x0118, 0xa086, 0x1000, 0x1520, 0x20e1, 0x0004, 0x3d60, 0xd1bc,
-	0x1170, 0x2100, 0xa084, 0xff00, 0xa086, 0x0500, 0x1140, 0x0026,
-	0x2c10, 0x080c, 0x566e, 0x002e, 0x0198, 0x0070, 0x3e60, 0xac84,
-	0x0003, 0x1170, 0xac82, 0x9900, 0x0258, 0x6858, 0xac02, 0x1240,
-	0x2009, 0x0047, 0x080c, 0x7518, 0x7a1c, 0xd284, 0x1988, 0x0005,
-	0xa016, 0x080c, 0x16c6, 0x0cc0, 0x0156, 0x0136, 0x0146, 0x20e1,
-	0x3000, 0x3d20, 0x3e28, 0xa584, 0x0070, 0x1528, 0xa484, 0x7000,
-	0xa086, 0x1000, 0x11a0, 0x04a1, 0x01f0, 0x20e1, 0x3000, 0x7828,
-	0x7828, 0x080c, 0x53cc, 0x014e, 0x013e, 0x015e, 0x2009, 0x94ed,
-	0x2104, 0xa005, 0x1108, 0x0005, 0x080c, 0x6462, 0x0ce0, 0xa484,
-	0x7000, 0x1148, 0x00e9, 0x0190, 0x7000, 0xa084, 0xff00, 0xa086,
-	0x8100, 0x0d18, 0x0058, 0xd5a4, 0x0140, 0x080c, 0x1c26, 0x20e1,
-	0x9010, 0x2001, 0x0138, 0x2202, 0x0038, 0x0051, 0x080c, 0x9157,
-	0x20e1, 0x3000, 0x7828, 0x7828, 0x014e, 0x013e, 0x015e, 0x08d8,
-	0xa484, 0x01ff, 0x6882, 0xa005, 0x0160, 0xa080, 0x001f, 0xa084,
-	0x03f8, 0x80ac, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5,
-	0x0005, 0x20a9, 0x000c, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a,
-	0x53a5, 0xa085, 0x0001, 0x0ca0, 0x7000, 0xa084, 0xff00, 0xa08c,
-	0xf000, 0x8007, 0xa196, 0x0000, 0x1118, 0x0804, 0x5571, 0x0005,
-	0xa196, 0x2000, 0x1148, 0x6900, 0xa18e, 0x0001, 0x1118, 0x080c,
-	0x3a6a, 0x0ca8, 0x0039, 0x0c98, 0xa196, 0x8000, 0x1d80, 0x080c,
-	0x55f9, 0x0c68, 0x00c6, 0x6a80, 0x82ff, 0x0904, 0x5506, 0x7110,
-	0xa18c, 0xff00, 0x810f, 0xa196, 0x0001, 0x0120, 0xa196, 0x0023,
-	0x1904, 0x5506, 0xa08e, 0x0023, 0x1558, 0x080c, 0x565c, 0x0904,
-	0x5506, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200, 0x1150, 0x7034,
-	0xa005, 0x1904, 0x5506, 0x2009, 0x0015, 0x080c, 0x7518, 0x0804,
-	0x5506, 0xa08e, 0x0210, 0x1130, 0x2009, 0x0015, 0x080c, 0x7518,
-	0x0804, 0x5506, 0xa08e, 0x0100, 0x1904, 0x5506, 0x7034, 0xa005,
-	0x1904, 0x5506, 0x2009, 0x0016, 0x080c, 0x7518, 0x0804, 0x5506,
-	0xa08e, 0x0022, 0x1904, 0x5506, 0x7030, 0xa08e, 0x0300, 0x1568,
-	0x68c8, 0xd0a4, 0x0510, 0xc0b5, 0x68ca, 0x7100, 0xa18c, 0x00ff,
-	0x696e, 0x7004, 0x6872, 0x00f6, 0x2079, 0x0100, 0x79e6, 0x78ea,
-	0x0006, 0xa084, 0x00ff, 0x0016, 0x2008, 0x080c, 0x2435, 0x7932,
-	0x7936, 0x001e, 0x000e, 0x00fe, 0x080c, 0x240b, 0x694e, 0x703c,
-	0x00e6, 0x2071, 0x0140, 0x7086, 0x00ee, 0x7034, 0xa005, 0x1904,
-	0x5506, 0x2009, 0x0017, 0x0804, 0x54d9, 0xa08e, 0x0400, 0x1158,
-	0x7034, 0xa005, 0x1904, 0x5506, 0x68c8, 0xc0a5, 0x68ca, 0x2009,
-	0x0030, 0x0804, 0x54d9, 0xa08e, 0x0500, 0x1140, 0x7034, 0xa005,
-	0x1904, 0x5506, 0x2009, 0x0018, 0x0804, 0x54d9, 0xa08e, 0x2010,
-	0x1120, 0x2009, 0x0019, 0x0804, 0x54d9, 0xa08e, 0x2110, 0x1120,
-	0x2009, 0x001a, 0x0804, 0x54d9, 0xa08e, 0x5200, 0x1140, 0x7034,
-	0xa005, 0x1904, 0x5506, 0x2009, 0x001b, 0x0804, 0x54d9, 0xa08e,
-	0x5000, 0x1140, 0x7034, 0xa005, 0x1904, 0x5506, 0x2009, 0x001c,
-	0x0804, 0x54d9, 0xa08e, 0x1200, 0x1138, 0x7034, 0xa005, 0x1904,
-	0x5506, 0x2009, 0x0024, 0x04a8, 0xa08c, 0xff00, 0xa18e, 0x2400,
+	0x0020, 0x1218, 0x00db, 0x012e, 0x0005, 0x012e, 0x080c, 0x4ece,
+	0x0005, 0x0005, 0x0005, 0x00e6, 0x2071, 0x8be1, 0x700c, 0x0002,
+	0x4e4d, 0x4e4d, 0x4e4d, 0x4e4f, 0x4e52, 0x00ee, 0x0005, 0x700f,
+	0x0001, 0x0010, 0x700f, 0x0002, 0x00ee, 0x0005, 0x4ece, 0x4ece,
+	0x4eea, 0x4ece, 0x4fc5, 0x4ece, 0x4ece, 0x4ece, 0x4ece, 0x4ece,
+	0x4eea, 0x4ffe, 0x5041, 0x508a, 0x509e, 0x4ece, 0x4ece, 0x4f06,
+	0x4eea, 0x4ece, 0x4ece, 0x4f1a, 0x5128, 0x5143, 0x4ece, 0x4f06,
+	0x4ece, 0x4ece, 0x4ece, 0x4ece, 0x4f1a, 0x5143, 0x7020, 0x2068,
+	0x080c, 0x149f, 0x0005, 0x700c, 0x0002, 0x4e82, 0x4e85, 0x4e93,
+	0x4eab, 0x4eab, 0x080c, 0x4dca, 0x0005, 0x0126, 0x8001, 0x700e,
+	0x7058, 0x0006, 0x080c, 0x51f4, 0x0120, 0x2091, 0x8000, 0x080c,
+	0x4dca, 0x00de, 0x0048, 0x0126, 0x8001, 0x700e, 0x080c, 0x51f4,
+	0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000,
+	0x6834, 0xa084, 0x00ff, 0xa08a, 0x001a, 0x1218, 0x003b, 0x012e,
+	0x0005, 0x012e, 0x0419, 0x0005, 0x0005, 0x0005, 0x4ece, 0x4eea,
+	0x4fb1, 0x4ece, 0x4eea, 0x4ece, 0x4eea, 0x4eea, 0x4ece, 0x4eea,
+	0x4fb1, 0x4eea, 0x4eea, 0x4eea, 0x4eea, 0x4eea, 0x4ece, 0x4eea,
+	0x4fb1, 0x4ece, 0x4ece, 0x4eea, 0x4ece, 0x4ece, 0x4ece, 0x4eea,
+	0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x7007, 0x0001,
+	0x6838, 0xa084, 0x00ff, 0xc0d5, 0x683a, 0x0126, 0x2091, 0x8000,
+	0x080c, 0x46a1, 0x012e, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084,
+	0x00ff, 0xc0e5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x46a1,
+	0x012e, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0ed,
+	0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x46a1, 0x012e, 0x0005,
+	0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0dd, 0x683a, 0x0126,
+	0x2091, 0x8000, 0x080c, 0x46a1, 0x012e, 0x0005, 0x6834, 0x8007,
+	0xa084, 0x00ff, 0x0988, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804,
+	0x4f92, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b,
+	0x4f92, 0x0005, 0x2d00, 0x7016, 0x701a, 0x20a9, 0x0004, 0xa080,
+	0x0024, 0x2098, 0x20a1, 0x8c0c, 0x53a3, 0x6858, 0x7012, 0xa082,
+	0x0401, 0x1a70, 0x6884, 0xa08a, 0x0003, 0x1a50, 0xa080, 0x4f83,
+	0x2005, 0x70c6, 0x7010, 0xa015, 0x0904, 0x4f77, 0x080c, 0x146f,
+	0x1118, 0x7007, 0x000f, 0x0005, 0x2d00, 0x7022, 0x70c4, 0x2060,
+	0x2c05, 0x6836, 0xe004, 0xad00, 0x7096, 0xe008, 0xa20a, 0x1210,
+	0xa00e, 0x2200, 0x7112, 0xe20c, 0x8003, 0x800b, 0xa296, 0x0004,
+	0x0108, 0xa108, 0x719a, 0x810b, 0x719e, 0xae90, 0x0022, 0x080c,
+	0x14d3, 0x7090, 0xa08e, 0x0100, 0x0170, 0xa086, 0x0200, 0x0118,
+	0x7007, 0x0010, 0x0005, 0x7020, 0x2068, 0x080c, 0x149f, 0x7014,
+	0x2068, 0x0804, 0x4ef8, 0x7020, 0x2068, 0x7018, 0x6802, 0x6807,
+	0x0000, 0x2d08, 0x2068, 0x6906, 0x711a, 0x0804, 0x4f32, 0x7014,
+	0x2068, 0x7007, 0x0001, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e,
+	0x0904, 0x515b, 0x0078, 0x4f86, 0x4f8a, 0x4f8e, 0x0002, 0x0011,
+	0x0007, 0x0004, 0x000a, 0x000f, 0x0005, 0x0006, 0x0012, 0x000f,
+	0x0005, 0x0006, 0x2009, 0x8b2f, 0x210c, 0x81ff, 0x11a8, 0x6838,
+	0xa084, 0x00ff, 0x683a, 0x6853, 0x0000, 0x080c, 0x4170, 0x1108,
+	0x0005, 0x080c, 0x4773, 0x0126, 0x2091, 0x8000, 0x080c, 0x7dc8,
+	0x080c, 0x46a1, 0x012e, 0x0ca0, 0x2001, 0x0028, 0x2009, 0x0000,
+	0x0c80, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906, 0x711a, 0x7010,
+	0x8001, 0x7012, 0x0118, 0x7007, 0x0006, 0x0030, 0x7014, 0x2068,
+	0x7007, 0x0001, 0x7048, 0x080f, 0x0005, 0x7007, 0x0001, 0x6944,
+	0x810f, 0xa18c, 0x00ff, 0x6848, 0xa084, 0x00ff, 0x20a9, 0x0001,
+	0xa096, 0x0001, 0x01b0, 0x2009, 0x0000, 0x20a9, 0x007e, 0xa096,
+	0x0002, 0x0178, 0xa005, 0x11f8, 0x6944, 0x810f, 0xa18c, 0x00ff,
+	0x080c, 0x430a, 0x11c0, 0x0066, 0x6e50, 0x080c, 0x43e6, 0x006e,
+	0x0090, 0x0046, 0x2011, 0x8b0c, 0x2224, 0xc484, 0xc48c, 0x2412,
+	0x004e, 0x00c6, 0x080c, 0x430a, 0x1110, 0x080c, 0x453d, 0x8108,
+	0x1f04, 0x4ff2, 0x00ce, 0x080c, 0x149f, 0x0005, 0x0126, 0x2091,
+	0x8000, 0x7007, 0x0001, 0x2001, 0x8b52, 0x2004, 0xd0a4, 0x0580,
+	0x2061, 0x8e2a, 0x6100, 0xd184, 0x0178, 0x6858, 0xa084, 0x00ff,
+	0x1550, 0x6000, 0xd084, 0x0520, 0x6004, 0xa005, 0x1538, 0x6003,
+	0x0000, 0x600b, 0x0000, 0x00c8, 0x2011, 0x0001, 0x6860, 0xa005,
+	0x1110, 0x2001, 0x001e, 0x8000, 0x6016, 0x6858, 0xa084, 0x00ff,
+	0x0178, 0x6006, 0x6858, 0x8007, 0xa084, 0x00ff, 0x0148, 0x600a,
+	0x6858, 0x8000, 0x1108, 0xc28d, 0x6202, 0x012e, 0x0804, 0x51e3,
+	0x012e, 0x0804, 0x51dd, 0x012e, 0x0804, 0x51d7, 0x012e, 0x0804,
+	0x51da, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0x8b52,
+	0x2004, 0xd0a4, 0x05e0, 0x2061, 0x8e2a, 0x6000, 0xd084, 0x05b8,
+	0x6204, 0x6308, 0xd08c, 0x1530, 0x6c48, 0xa484, 0x0003, 0x0170,
+	0x6958, 0xa18c, 0x00ff, 0x8001, 0x1120, 0x2100, 0xa210, 0x0620,
+	0x0028, 0x8001, 0x1508, 0x2100, 0xa212, 0x02f0, 0xa484, 0x000c,
+	0x0188, 0x6958, 0x810f, 0xa18c, 0x00ff, 0xa082, 0x0004, 0x1120,
+	0x2100, 0xa318, 0x0288, 0x0030, 0xa082, 0x0004, 0x1168, 0x2100,
+	0xa31a, 0x0250, 0x6860, 0xa005, 0x0110, 0x8000, 0x6016, 0x6206,
+	0x630a, 0x012e, 0x0804, 0x51e3, 0x012e, 0x0804, 0x51e0, 0x012e,
+	0x0804, 0x51dd, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x2061,
+	0x8e2a, 0x6300, 0xd38c, 0x1120, 0x6308, 0x8318, 0x0220, 0x630a,
+	0x012e, 0x0804, 0x51f1, 0x012e, 0x0804, 0x51e0, 0x0126, 0x00c6,
+	0x2091, 0x8000, 0x7007, 0x0001, 0x684c, 0xd0ac, 0x0148, 0x00c6,
+	0x2061, 0x8e2a, 0x6000, 0xa084, 0xfcff, 0x6002, 0x00ce, 0x04d8,
+	0x6858, 0xa005, 0x0904, 0x50ff, 0x685c, 0xa065, 0x0904, 0x50fb,
+	0x2001, 0x8b2f, 0x2004, 0xa005, 0x0118, 0x080c, 0x7d3c, 0x0068,
+	0x6013, 0x0400, 0x6027, 0x0000, 0x694c, 0xd1a4, 0x0110, 0x6950,
+	0x6126, 0x2009, 0x0041, 0x080c, 0x6d3f, 0x6958, 0xa18c, 0xff00,
+	0xa186, 0x2000, 0x0180, 0xa186, 0x0400, 0x0168, 0xa186, 0x1000,
+	0x0108, 0x0088, 0x00c6, 0x2061, 0x8e2a, 0x6000, 0xa084, 0xfdff,
+	0x6002, 0x00ce, 0x0040, 0x0026, 0x2009, 0x0000, 0x2011, 0xfdff,
+	0x080c, 0x5734, 0x002e, 0x684c, 0xd0c4, 0x0148, 0x2061, 0x8e2a,
+	0x6000, 0xd08c, 0x1120, 0x6008, 0x8000, 0x0208, 0x600a, 0x00ce,
+	0x012e, 0x0804, 0x51e3, 0x00ce, 0x012e, 0x0804, 0x51dd, 0x6954,
+	0xa186, 0x002e, 0x0d40, 0xa186, 0x002d, 0x0d28, 0xa186, 0x002a,
+	0x1130, 0x2001, 0x8b0c, 0x200c, 0xc194, 0x2102, 0x08e0, 0xa186,
+	0x0020, 0x0170, 0xa186, 0x0029, 0x1d30, 0x6944, 0xa18c, 0xff00,
+	0x810f, 0x080c, 0x430a, 0x1978, 0x6000, 0xc0e4, 0x6002, 0x0858,
+	0x685c, 0xa065, 0x09c0, 0x2001, 0x8da2, 0x2004, 0x6016, 0x0818,
+	0x2061, 0x8e2a, 0x6000, 0xd084, 0x0190, 0xd08c, 0x1904, 0x51f1,
+	0x0126, 0x2091, 0x8000, 0x6204, 0x8210, 0x0220, 0x6206, 0x012e,
+	0x0804, 0x51f1, 0x012e, 0x6853, 0x0016, 0x0804, 0x51ea, 0x6853,
+	0x0007, 0x0804, 0x51ea, 0x6834, 0x8007, 0xa084, 0x00ff, 0x1118,
+	0x080c, 0x4edc, 0x0078, 0x2030, 0x8001, 0x1120, 0x7007, 0x0001,
+	0x0051, 0x0040, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a,
+	0x704b, 0x515b, 0x0005, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2009,
+	0x8b2f, 0x210c, 0x81ff, 0x1904, 0x51cc, 0x2009, 0x8b0c, 0x210c,
+	0xd194, 0x1904, 0x51d4, 0x6848, 0x2070, 0xae82, 0x9200, 0x0a04,
+	0x51c0, 0x2001, 0x8b16, 0x2004, 0xae02, 0x1a04, 0x51c0, 0x2061,
+	0x8e2a, 0x6100, 0xa184, 0x0001, 0x0568, 0xa184, 0x0100, 0x1904,
+	0x51c3, 0xa184, 0x0200, 0x1904, 0x51c6, 0x601c, 0xa005, 0x1904,
+	0x51c9, 0x711c, 0xa186, 0x0006, 0x1510, 0x7018, 0xa005, 0x05e0,
+	0x2004, 0xd0e4, 0x15e0, 0x6853, 0x0000, 0x6803, 0x0000, 0x2d08,
+	0x7010, 0xa005, 0x1138, 0x7112, 0x2e60, 0x080c, 0x56a3, 0x012e,
+	0x00ee, 0x0005, 0x2068, 0x6800, 0xa005, 0x1de0, 0x6902, 0x012e,
+	0x00ee, 0x0005, 0x012e, 0x00ee, 0x6853, 0x0006, 0x04d8, 0x6944,
+	0xa18c, 0xff00, 0x810f, 0x080c, 0x430a, 0x11c8, 0x6000, 0xd0e4,
+	0x11b0, 0x711c, 0xa186, 0x0007, 0x1118, 0x6853, 0x0002, 0x0088,
+	0x6853, 0x0008, 0x0070, 0x6853, 0x000e, 0x0058, 0x6853, 0x0017,
+	0x0040, 0x6853, 0x0035, 0x0028, 0x6853, 0x0028, 0x0010, 0x6853,
+	0x0029, 0x012e, 0x00ee, 0x00b0, 0x6853, 0x002a, 0x0cd0, 0x2009,
+	0x003e, 0x0058, 0x2009, 0x0004, 0x0040, 0x2009, 0x0006, 0x0028,
+	0x2009, 0x0016, 0x0010, 0x2009, 0x0001, 0x6854, 0xa084, 0xff00,
+	0xa105, 0x6856, 0x0126, 0x2091, 0x8000, 0x080c, 0x46a1, 0x012e,
+	0x0005, 0x080c, 0x149f, 0x0005, 0x702c, 0x7130, 0x8108, 0xa102,
+	0x0230, 0xa00e, 0x7034, 0x7072, 0x7038, 0x7076, 0x0058, 0x7070,
+	0xa080, 0x0040, 0x7072, 0x1230, 0x7074, 0xa081, 0x0000, 0x7076,
+	0xa085, 0x0001, 0x7932, 0x7132, 0x0005, 0x00d6, 0x080c, 0x569a,
+	0x00de, 0x0005, 0x00d6, 0x2011, 0x0004, 0x2204, 0xa085, 0x8002,
+	0x2012, 0x00de, 0x0005, 0x20e1, 0x0002, 0x3d08, 0x20e1, 0x2000,
+	0x3d00, 0xa084, 0x7000, 0x0118, 0xa086, 0x1000, 0x11b8, 0x20e1,
+	0x0004, 0x3d60, 0xd1bc, 0x1108, 0x3e60, 0xac84, 0x0003, 0x1170,
+	0xac82, 0x9200, 0x0258, 0x6858, 0xac02, 0x1240, 0x2009, 0x0047,
+	0x080c, 0x6d3f, 0x7a1c, 0xd284, 0x19f0, 0x0005, 0xa016, 0x080c,
+	0x16d1, 0x0cc0, 0x0156, 0x0136, 0x0146, 0x20e1, 0x3000, 0x3d20,
+	0x3e28, 0xa584, 0x0070, 0x1530, 0xa484, 0x7000, 0xa086, 0x1000,
+	0x11a8, 0x080c, 0x5295, 0x01f0, 0x20e1, 0x3000, 0x7828, 0x7828,
+	0x080c, 0x52b1, 0x014e, 0x013e, 0x015e, 0x2009, 0x8db2, 0x2104,
+	0xa005, 0x1108, 0x0005, 0x080c, 0x5d10, 0x0ce0, 0xa484, 0x7000,
+	0x1508, 0x0459, 0x01a8, 0x7000, 0xa084, 0xff00, 0xa086, 0x8100,
+	0x0d18, 0x0070, 0xd5a4, 0x0158, 0x080c, 0x1b5e, 0x20e1, 0x9010,
+	0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0038, 0x00a9,
+	0x080c, 0x8a02, 0x20e1, 0x3000, 0x7828, 0x7828, 0x014e, 0x013e,
+	0x015e, 0x08c0, 0x0051, 0x0da0, 0x080c, 0x8a02, 0x20e1, 0x3000,
+	0x7828, 0x7828, 0x080c, 0x5556, 0x0c88, 0xa484, 0x01ff, 0x6882,
+	0xa005, 0x0160, 0xa080, 0x001f, 0xa084, 0x03f8, 0x80ac, 0x20e1,
+	0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x0005, 0x20a9, 0x000c,
+	0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0xa085, 0x0001,
+	0x0ca0, 0x7000, 0xa084, 0xff00, 0xa08c, 0xf000, 0x8007, 0xa196,
+	0x0000, 0x1118, 0x0804, 0x5459, 0x0005, 0xa196, 0x2000, 0x1148,
+	0x6900, 0xa18e, 0x0001, 0x1118, 0x080c, 0x399f, 0x0ca8, 0x0039,
+	0x0c98, 0xa196, 0x8000, 0x1d80, 0x080c, 0x54e1, 0x0c68, 0x00c6,
+	0x6a80, 0x82ff, 0x0904, 0x53ee, 0x7110, 0xa18c, 0xff00, 0x810f,
+	0xa196, 0x0001, 0x0120, 0xa196, 0x0023, 0x1904, 0x53ee, 0xa08e,
+	0x0023, 0x1558, 0x080c, 0x5544, 0x0904, 0x53ee, 0x7124, 0x610a,
+	0x7030, 0xa08e, 0x0200, 0x1150, 0x7034, 0xa005, 0x1904, 0x53ee,
+	0x2009, 0x0015, 0x080c, 0x6d3f, 0x0804, 0x53ee, 0xa08e, 0x0210,
+	0x1130, 0x2009, 0x0015, 0x080c, 0x6d3f, 0x0804, 0x53ee, 0xa08e,
+	0x0100, 0x1904, 0x53ee, 0x7034, 0xa005, 0x1904, 0x53ee, 0x2009,
+	0x0016, 0x080c, 0x6d3f, 0x0804, 0x53ee, 0xa08e, 0x0022, 0x1904,
+	0x53ee, 0x7030, 0xa08e, 0x0300, 0x1580, 0x68c8, 0xd0a4, 0x0528,
+	0xc0b5, 0x68ca, 0x7100, 0xa18c, 0x00ff, 0x696e, 0x7004, 0x6872,
+	0x00f6, 0x2079, 0x0100, 0x79e6, 0x78ea, 0x0006, 0xa084, 0x00ff,
+	0x0016, 0x2008, 0x080c, 0x2313, 0x7932, 0x7936, 0x001e, 0x000e,
+	0x00fe, 0x080c, 0x22e9, 0x694e, 0x703c, 0x00e6, 0x2071, 0x0140,
+	0x7086, 0x2071, 0x8b00, 0x709e, 0x00ee, 0x7034, 0xa005, 0x1904,
+	0x53ee, 0x2009, 0x0017, 0x0804, 0x53c1, 0xa08e, 0x0400, 0x1158,
+	0x7034, 0xa005, 0x1904, 0x53ee, 0x68c8, 0xc0a5, 0x68ca, 0x2009,
+	0x0030, 0x0804, 0x53c1, 0xa08e, 0x0500, 0x1140, 0x7034, 0xa005,
+	0x1904, 0x53ee, 0x2009, 0x0018, 0x0804, 0x53c1, 0xa08e, 0x2010,
+	0x1120, 0x2009, 0x0019, 0x0804, 0x53c1, 0xa08e, 0x2110, 0x1120,
+	0x2009, 0x001a, 0x0804, 0x53c1, 0xa08e, 0x5200, 0x1140, 0x7034,
+	0xa005, 0x1904, 0x53ee, 0x2009, 0x001b, 0x0804, 0x53c1, 0xa08e,
+	0x5000, 0x1140, 0x7034, 0xa005, 0x1904, 0x53ee, 0x2009, 0x001c,
+	0x0804, 0x53c1, 0xa08e, 0x1200, 0x1138, 0x7034, 0xa005, 0x1904,
+	0x53ee, 0x2009, 0x0024, 0x04a8, 0xa08c, 0xff00, 0xa18e, 0x2400,
 	0x1118, 0x2009, 0x002d, 0x0468, 0xa08c, 0xff00, 0xa18e, 0x5300,
 	0x1118, 0x2009, 0x002a, 0x0428, 0xa08e, 0x0f00, 0x1118, 0x2009,
 	0x0020, 0x00f8, 0xa08e, 0x5300, 0x1108, 0x00c8, 0xa08e, 0x6104,
-	0x11b0, 0x2011, 0x978d, 0x8208, 0x2204, 0xa082, 0x0004, 0x20a8,
+	0x11b0, 0x2011, 0x908d, 0x8208, 0x2204, 0xa082, 0x0004, 0x20a8,
 	0x95ac, 0x95ac, 0x2011, 0x8015, 0x211c, 0x8108, 0x2124, 0x080c,
-	0x3698, 0x8108, 0x1f04, 0x54ca, 0x2009, 0x0023, 0x0010, 0x2009,
-	0x001d, 0x0016, 0x2011, 0x9783, 0x2204, 0x8211, 0x220c, 0x080c,
-	0x240b, 0x1530, 0x080c, 0x4400, 0x1518, 0x6612, 0x6516, 0x86ff,
+	0x3617, 0x8108, 0x1f04, 0x53b2, 0x2009, 0x0023, 0x0010, 0x2009,
+	0x001d, 0x0016, 0x2011, 0x9083, 0x2204, 0x8211, 0x220c, 0x080c,
+	0x22e9, 0x1530, 0x080c, 0x42d6, 0x1518, 0x6612, 0x6516, 0x86ff,
 	0x0180, 0x001e, 0x0016, 0xa186, 0x0017, 0x1158, 0x686c, 0xa606,
 	0x1140, 0x6870, 0xa506, 0xa084, 0xff00, 0x1118, 0x6000, 0xc0f5,
-	0x6002, 0x00c6, 0x080c, 0x749c, 0x0168, 0x001e, 0x611a, 0x601f,
-	0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0x7518, 0x00ce, 0x0005,
+	0x6002, 0x00c6, 0x080c, 0x6cc2, 0x0168, 0x001e, 0x611a, 0x601f,
+	0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0x6d3f, 0x00ce, 0x0005,
 	0x001e, 0x0ce0, 0x00ce, 0x0ce0, 0x00e6, 0x00d6, 0x2028, 0x2130,
 	0xa696, 0x00ff, 0x1518, 0xa596, 0xfffd, 0x1120, 0x2009, 0x007f,
-	0x0804, 0x556d, 0xa596, 0xfffe, 0x1120, 0x2009, 0x007e, 0x0804,
-	0x556d, 0xa596, 0xfffc, 0x1120, 0x2009, 0x0080, 0x0804, 0x556d,
+	0x0804, 0x5455, 0xa596, 0xfffe, 0x1120, 0x2009, 0x007e, 0x0804,
+	0x5455, 0xa596, 0xfffc, 0x1120, 0x2009, 0x0080, 0x0804, 0x5455,
 	0xa594, 0xff00, 0xa296, 0xfc00, 0x1148, 0x2011, 0x0000, 0x2021,
-	0x0081, 0x20a9, 0x007e, 0x2071, 0x93ef, 0x00a0, 0x2011, 0x0000,
-	0x2019, 0x9232, 0x231c, 0xd3ac, 0x0138, 0x2021, 0x0000, 0x20a9,
-	0x00ff, 0x2071, 0x936e, 0x0030, 0x2021, 0x0081, 0x20a9, 0x007e,
-	0x2071, 0x93ef, 0x2e1c, 0x83ff, 0x1128, 0x82ff, 0x1198, 0x2410,
+	0x0081, 0x20a9, 0x007e, 0x2071, 0x8cb5, 0x00a0, 0x2011, 0x0000,
+	0x2019, 0x8b32, 0x231c, 0xd3ac, 0x0138, 0x2021, 0x0000, 0x20a9,
+	0x00ff, 0x2071, 0x8c34, 0x0030, 0x2021, 0x0081, 0x20a9, 0x007e,
+	0x2071, 0x8cb5, 0x2e1c, 0x83ff, 0x1128, 0x82ff, 0x1198, 0x2410,
 	0xc2fd, 0x0080, 0x2368, 0x6f10, 0x0006, 0x2100, 0xa706, 0x000e,
 	0x6b14, 0x1120, 0xa346, 0x1110, 0x2408, 0x0078, 0x87ff, 0x1110,
-	0x83ff, 0x0d58, 0x8420, 0x8e70, 0x1f04, 0x554a, 0x82ff, 0x1118,
+	0x83ff, 0x0d58, 0x8420, 0x8e70, 0x1f04, 0x5432, 0x82ff, 0x1118,
 	0xa085, 0x0001, 0x0018, 0xc2fc, 0x2208, 0xa006, 0x00de, 0x00ee,
-	0x0005, 0xa084, 0x0007, 0x000a, 0x0005, 0x557d, 0x557d, 0x557d,
-	0x557d, 0x557d, 0x557e, 0x5593, 0x55e6, 0x0005, 0x7110, 0xd1bc,
-	0x0188, 0x7120, 0x2160, 0xac8c, 0x0003, 0x1160, 0xac8a, 0x9900,
+	0x0005, 0xa084, 0x0007, 0x000a, 0x0005, 0x5465, 0x5465, 0x5465,
+	0x5465, 0x5465, 0x5466, 0x547b, 0x54ce, 0x0005, 0x7110, 0xd1bc,
+	0x0188, 0x7120, 0x2160, 0xac8c, 0x0003, 0x1160, 0xac8a, 0x9200,
 	0x0248, 0x6858, 0xac02, 0x1230, 0x7124, 0x610a, 0x2009, 0x0046,
-	0x080c, 0x7518, 0x0005, 0x00c6, 0x7110, 0xd1bc, 0x1904, 0x55e4,
-	0x2011, 0x9783, 0x2204, 0x8211, 0x220c, 0x080c, 0x240b, 0x1904,
-	0x55e4, 0x080c, 0x4434, 0x1904, 0x55e4, 0x6000, 0xd0ec, 0x15e0,
+	0x080c, 0x6d3f, 0x0005, 0x00c6, 0x7110, 0xd1bc, 0x1904, 0x54cc,
+	0x2011, 0x9083, 0x2204, 0x8211, 0x220c, 0x080c, 0x22e9, 0x1904,
+	0x54cc, 0x080c, 0x430a, 0x1904, 0x54cc, 0x6000, 0xd0ec, 0x15e0,
 	0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006, 0x0160, 0x080c,
-	0x4dc5, 0x11d0, 0x6204, 0xa294, 0x00ff, 0xa286, 0x0006, 0x11a0,
-	0xa295, 0x0600, 0x6206, 0x00c6, 0x080c, 0x749c, 0x001e, 0x0520,
+	0x4c42, 0x11d0, 0x6204, 0xa294, 0x00ff, 0xa286, 0x0006, 0x11a0,
+	0xa295, 0x0600, 0x6206, 0x00c6, 0x080c, 0x6cc2, 0x001e, 0x0520,
 	0x611a, 0x601f, 0x0006, 0x7120, 0x610a, 0x7130, 0x6122, 0x2009,
-	0x0044, 0x080c, 0x7518, 0x00c0, 0x00c6, 0x080c, 0x749c, 0x001e,
+	0x0044, 0x080c, 0x6d3f, 0x00c0, 0x00c6, 0x080c, 0x6cc2, 0x001e,
 	0x0198, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0xa286, 0x0004,
 	0x1118, 0x6007, 0x0005, 0x0010, 0x6007, 0x0001, 0x6003, 0x0001,
-	0x080c, 0x603e, 0x080c, 0x6462, 0x00ce, 0x0005, 0x7110, 0xd1bc,
-	0x0178, 0x7020, 0x2060, 0xac84, 0x0003, 0x1150, 0xac82, 0x9900,
-	0x0238, 0x6858, 0xac02, 0x1220, 0x2009, 0x0045, 0x080c, 0x7518,
+	0x080c, 0x58e2, 0x080c, 0x5d10, 0x00ce, 0x0005, 0x7110, 0xd1bc,
+	0x0178, 0x7020, 0x2060, 0xac84, 0x0003, 0x1150, 0xac82, 0x9200,
+	0x0238, 0x6858, 0xac02, 0x1220, 0x2009, 0x0045, 0x080c, 0x6d3f,
 	0x0005, 0x7110, 0xa18c, 0xff00, 0x810f, 0xa18e, 0x0000, 0x1138,
-	0xa084, 0x000f, 0xa08a, 0x0006, 0x1a0c, 0x13fe, 0x000b, 0x0005,
-	0x560e, 0x560f, 0x560e, 0x560e, 0x5644, 0x5650, 0x0005, 0x7110,
-	0xd1bc, 0x1588, 0x700c, 0x7108, 0x080c, 0x240b, 0x1560, 0x080c,
-	0x4400, 0x1548, 0x6612, 0x6516, 0x6204, 0xa294, 0xff00, 0x8217,
+	0xa084, 0x000f, 0xa08a, 0x0006, 0x1a0c, 0x1410, 0x000b, 0x0005,
+	0x54f6, 0x54f7, 0x54f6, 0x54f6, 0x552c, 0x5538, 0x0005, 0x7110,
+	0xd1bc, 0x1588, 0x700c, 0x7108, 0x080c, 0x22e9, 0x1560, 0x080c,
+	0x42d6, 0x1548, 0x6612, 0x6516, 0x6204, 0xa294, 0xff00, 0x8217,
 	0xa286, 0x0004, 0x0118, 0xa286, 0x0006, 0x1178, 0x00c6, 0x080c,
-	0x749c, 0x001e, 0x01c0, 0x611a, 0x601f, 0x0005, 0x7120, 0x610a,
-	0x2009, 0x0088, 0x080c, 0x7518, 0x0070, 0x00c6, 0x080c, 0x749c,
+	0x6cc2, 0x001e, 0x01c0, 0x611a, 0x601f, 0x0005, 0x7120, 0x610a,
+	0x2009, 0x0088, 0x080c, 0x6d3f, 0x0070, 0x00c6, 0x080c, 0x6cc2,
 	0x001e, 0x0148, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0x2009,
-	0x0001, 0x080c, 0x7518, 0x0005, 0x7110, 0xd1bc, 0x0140, 0x00a1,
-	0x0130, 0x7124, 0x610a, 0x2009, 0x0089, 0x080c, 0x7518, 0x0005,
+	0x0001, 0x080c, 0x6d3f, 0x0005, 0x7110, 0xd1bc, 0x0140, 0x00a1,
+	0x0130, 0x7124, 0x610a, 0x2009, 0x0089, 0x080c, 0x6d3f, 0x0005,
 	0x7110, 0xd1bc, 0x0140, 0x0041, 0x0130, 0x7124, 0x610a, 0x2009,
-	0x008a, 0x080c, 0x7518, 0x0005, 0x7020, 0x2060, 0xac84, 0x0003,
-	0x1158, 0xac82, 0x9900, 0x0240, 0x2001, 0x9216, 0x2004, 0xac02,
+	0x008a, 0x080c, 0x6d3f, 0x0005, 0x7020, 0x2060, 0xac84, 0x0003,
+	0x1158, 0xac82, 0x9200, 0x0240, 0x2001, 0x8b16, 0x2004, 0xac02,
 	0x1218, 0xa085, 0x0001, 0x0005, 0xa006, 0x0ce8, 0x00c6, 0x00d6,
-	0x00e6, 0x20e1, 0x0000, 0x3d08, 0xa18c, 0x00ff, 0xa18e, 0x00ff,
-	0x1150, 0x3e00, 0xa086, 0xffff, 0x1130, 0x2001, 0x94c6, 0x2064,
-	0x2009, 0x00ff, 0x0060, 0x20e1, 0x0001, 0x3d08, 0x3e00, 0x0156,
-	0x080c, 0x240b, 0x015e, 0x1578, 0x080c, 0x4434, 0x1560, 0x2138,
-	0x873f, 0x2c00, 0x2070, 0x20e1, 0x0003, 0x3d18, 0x831f, 0xa39c,
-	0x00ff, 0x0036, 0x0036, 0x003e, 0x003e, 0x20e1, 0x2000, 0x3d00,
-	0xa084, 0x7000, 0xa086, 0x1000, 0x0120, 0x080c, 0x5cc0, 0x1198,
-	0x0040, 0x080c, 0x749c, 0x0178, 0x2e00, 0x601a, 0x620a, 0x601f,
-	0x0009, 0x2009, 0x0101, 0x080c, 0x7518, 0xa085, 0x0001, 0x00ee,
-	0x00de, 0x00ce, 0x0005, 0xa006, 0x00ee, 0x00de, 0x00ce, 0x0005,
-	0x2071, 0x94f8, 0x7003, 0x0003, 0x700f, 0x0361, 0xa006, 0x701a,
-	0x7012, 0x7017, 0x9900, 0x7007, 0x0000, 0x7026, 0x702b, 0x6f2b,
-	0x7032, 0x7037, 0x6f69, 0x703b, 0xffff, 0x703f, 0xffff, 0x0005,
-	0x2071, 0x94f8, 0x1d04, 0x5720, 0x2091, 0x6000, 0x700c, 0x8001,
-	0x700e, 0x1120, 0x700f, 0x0361, 0x7007, 0x0001, 0x0126, 0x2091,
-	0x8000, 0x7024, 0xa00d, 0x0158, 0x7020, 0x8001, 0x7022, 0x1138,
-	0x7023, 0x0009, 0x8109, 0x7126, 0x1110, 0x7028, 0x080f, 0x7030,
-	0xa00d, 0x0158, 0x702c, 0x8001, 0x702e, 0x1138, 0x702f, 0x0009,
-	0x8109, 0x7132, 0x1110, 0x7034, 0x080f, 0x7038, 0xa005, 0x0118,
-	0x0310, 0x8001, 0x703a, 0x703c, 0xa005, 0x0118, 0x0310, 0x8001,
-	0x703e, 0x7018, 0xa00d, 0x0158, 0x7008, 0x8001, 0x700a, 0x1138,
-	0x700b, 0x0009, 0x8109, 0x711a, 0x1110, 0x701c, 0x080f, 0x012e,
-	0x7004, 0x0002, 0x5746, 0x5747, 0x575f, 0x00e6, 0x2071, 0x94f8,
-	0x7018, 0xa005, 0x1120, 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee,
-	0x0005, 0x00e6, 0x0006, 0x2071, 0x94f8, 0x701c, 0xa206, 0x1110,
-	0x701a, 0x701e, 0x000e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x94f8,
-	0x6088, 0xa102, 0x0208, 0x618a, 0x00ee, 0x0005, 0x0005, 0x7110,
-	0x080c, 0x4434, 0x1158, 0x6088, 0x8001, 0x0240, 0x608a, 0x1130,
-	0x0126, 0x2091, 0x8000, 0x080c, 0x6462, 0x012e, 0x8108, 0xa182,
-	0x00ff, 0x0218, 0xa00e, 0x7007, 0x0002, 0x7112, 0x0005, 0x7014,
-	0x2060, 0x0126, 0x2091, 0x8000, 0x6014, 0xa005, 0x0518, 0x8001,
-	0x6016, 0x1500, 0x611c, 0xa186, 0x0003, 0x0130, 0xa186, 0x0006,
-	0x0118, 0xa186, 0x0009, 0x11a0, 0x6010, 0x2068, 0x6854, 0xa08a,
-	0x199a, 0x0270, 0xa082, 0x1999, 0x6856, 0xa08a, 0x199a, 0x0210,
-	0x2001, 0x1999, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x0010,
-	0x080c, 0x8185, 0x012e, 0xac88, 0x000c, 0x7116, 0x2001, 0x9217,
-	0x2004, 0xa102, 0x0220, 0x7017, 0x9900, 0x7007, 0x0000, 0x0005,
-	0x00e6, 0x2071, 0x94f8, 0x7027, 0x07d0, 0x7023, 0x0009, 0x00ee,
-	0x0005, 0x2001, 0x9501, 0x2003, 0x0000, 0x0005, 0x00e6, 0x2071,
-	0x94f8, 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005, 0x2011, 0x9504,
-	0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, 0x94f8, 0x711a, 0x721e,
-	0x700b, 0x0009, 0x00ee, 0x0005, 0x00c6, 0x2061, 0x9566, 0x00ce,
-	0x0005, 0xa184, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x9566,
-	0x2060, 0x0005, 0x6854, 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999,
-	0xa005, 0x1150, 0x00c6, 0x2061, 0x9566, 0x6014, 0x00ce, 0xa005,
-	0x1138, 0x2001, 0x001e, 0x0020, 0xa08e, 0xffff, 0x1108, 0xa006,
-	0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x684c, 0xa08c, 0x00c0,
-	0xa18e, 0x00c0, 0x0588, 0xd0b4, 0x1138, 0xd0bc, 0x11f0, 0x2009,
-	0x0006, 0x080c, 0x5838, 0x0005, 0xd0fc, 0x0140, 0xa084, 0x0003,
-	0xa08e, 0x0003, 0x05b8, 0xa08e, 0x0000, 0x15a0, 0x2009, 0x9273,
-	0x2104, 0xd084, 0x0128, 0x2009, 0x0042, 0x080c, 0x7518, 0x0005,
-	0x2009, 0x0043, 0x080c, 0x7518, 0x0005, 0xd0fc, 0x0140, 0xa084,
-	0x0003, 0xa08e, 0x0003, 0x01f0, 0xa08e, 0x0000, 0x11d8, 0x2009,
-	0x0042, 0x080c, 0x7518, 0x0005, 0xd0fc, 0x0168, 0xa084, 0x0003,
-	0xa08e, 0x0003, 0x0178, 0xa08e, 0x0002, 0x0138, 0x2009, 0x0041,
-	0x080c, 0x7518, 0x0005, 0x0051, 0x0ce8, 0x2009, 0x0043, 0x080c,
-	0x7518, 0x0cc0, 0x2009, 0x0004, 0x0019, 0x0005, 0x2009, 0x0001,
-	0x6010, 0xa0ec, 0xf000, 0x01f0, 0x2068, 0x6952, 0x6800, 0x6012,
-	0xa186, 0x0001, 0x1188, 0x694c, 0xa18c, 0x8100, 0xa18e, 0x8100,
-	0x1158, 0x00c6, 0x2061, 0x9566, 0x6200, 0xd28c, 0x1120, 0x6204,
-	0x8210, 0x0208, 0x6206, 0x00ce, 0x080c, 0x4809, 0x6010, 0xa06d,
-	0x190c, 0x57ca, 0x0005, 0x0156, 0x00c6, 0x2061, 0x9566, 0x6000,
-	0x81ff, 0x0110, 0xa205, 0x0008, 0xa204, 0x6002, 0x00ce, 0x015e,
-	0x0005, 0x6800, 0xd08c, 0x1138, 0x6808, 0xa005, 0x0120, 0x8001,
-	0x680a, 0xa085, 0x0001, 0x0005, 0x2071, 0x9349, 0x7003, 0x0006,
-	0x7007, 0x0000, 0x700f, 0x0000, 0x7013, 0x0001, 0x702f, 0x0006,
-	0x7033, 0x0001, 0x7063, 0x0000, 0x0005, 0x00e6, 0x2071, 0x9349,
-	0x6a2c, 0x721e, 0x6b30, 0x7322, 0x6834, 0x7026, 0x705a, 0x6838,
-	0x702a, 0x705e, 0x6824, 0x7016, 0x683c, 0x701a, 0x2009, 0x0070,
-	0x200a, 0xa005, 0x0150, 0x2009, 0x0000, 0xa188, 0x000c, 0x8001,
-	0x1de0, 0x2100, 0xa210, 0x1208, 0x8318, 0x7252, 0x7356, 0x7010,
-	0xc084, 0x7012, 0x7007, 0x0001, 0x700f, 0x0000, 0xa006, 0x00ee,
-	0x0005, 0x2b78, 0x2071, 0x9349, 0x7004, 0x004b, 0x700c, 0x0002,
-	0x58bb, 0x58b4, 0x58b4, 0x0005, 0x58c5, 0x5913, 0x5914, 0x5915,
-	0x5916, 0x5929, 0x592a, 0x700c, 0x0cba, 0x2f00, 0xa080, 0x0070,
-	0x2004, 0x2f08, 0xa188, 0x0070, 0x210c, 0xa106, 0x0150, 0x2f00,
-	0xa080, 0x0070, 0x2004, 0x2f08, 0xa188, 0x0070, 0x210c, 0xa106,
-	0x15c8, 0x7018, 0xa10a, 0x05b0, 0x1210, 0x7114, 0xa10a, 0xa192,
-	0x000a, 0x0210, 0x2009, 0x000a, 0x00d6, 0x0016, 0x2001, 0x9281,
-	0xa080, 0x0011, 0x2014, 0x2001, 0x9363, 0xa080, 0x0005, 0x2004,
-	0xa100, 0xa202, 0x001e, 0x00de, 0x02e8, 0x080c, 0x5976, 0x2200,
-	0xa102, 0x0208, 0x2208, 0x713a, 0x080c, 0x5a67, 0x2100, 0x7042,
-	0x2001, 0x0002, 0x7037, 0x0000, 0x0126, 0x0006, 0x2091, 0x8000,
-	0x2009, 0x9508, 0x2104, 0xc095, 0x200a, 0x000e, 0x700e, 0x012e,
-	0x080c, 0x14df, 0x0005, 0x0005, 0x0005, 0x0005, 0x700c, 0x0002,
-	0x591b, 0x591e, 0x5928, 0x080c, 0x58c3, 0x0005, 0x0126, 0x8001,
-	0x700e, 0x7138, 0x0041, 0x2091, 0x8000, 0x080c, 0x58c3, 0x012e,
-	0x0005, 0x0005, 0x0005, 0x7018, 0xa100, 0x7214, 0xa21a, 0x1130,
-	0x701c, 0x7052, 0x7020, 0x7056, 0xa006, 0x0068, 0x0006, 0x080c,
-	0x5a67, 0x2100, 0x7250, 0xa210, 0x7252, 0x1220, 0x7054, 0xa081,
-	0x0000, 0x7056, 0x000e, 0x2f08, 0xa188, 0x0070, 0x200a, 0x701a,
-	0x0005, 0x00e6, 0x2071, 0x9349, 0x700c, 0x0002, 0x5951, 0x5951,
-	0x5953, 0x00ee, 0x0005, 0x700f, 0x0001, 0x00ee, 0x0005, 0x00d6,
-	0x00e6, 0x2071, 0x9363, 0xa006, 0x7006, 0x700e, 0x701a, 0x701e,
-	0x7022, 0x702a, 0x7026, 0x080c, 0x5b1b, 0x0170, 0x080c, 0x5b4d,
-	0x0158, 0x2d00, 0x7002, 0x700a, 0x701a, 0x7013, 0x0001, 0x701f,
-	0x0007, 0x00ee, 0x00de, 0x0005, 0xa00e, 0x0cd8, 0x00e6, 0x00d6,
-	0x00c6, 0x2071, 0x9363, 0x721c, 0x2100, 0xa202, 0x1618, 0x080c,
-	0x5b4d, 0x090c, 0x13fe, 0x7018, 0xa005, 0x1160, 0x2d00, 0x7002,
-	0x700a, 0x701a, 0xa006, 0x7006, 0x700e, 0x6806, 0x6802, 0x7012,
-	0x701e, 0x0038, 0x2060, 0x6806, 0x2d00, 0x6002, 0x701a, 0x6803,
-	0x0000, 0x7010, 0x8000, 0x7012, 0x701c, 0xa080, 0x0007, 0x701e,
-	0x721c, 0x08d0, 0x721c, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x0156,
-	0x0136, 0x0146, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x9363,
-	0x7300, 0xa398, 0x0003, 0x7104, 0x080c, 0x5a67, 0x810c, 0x2100,
-	0xa318, 0x8003, 0x2228, 0x2021, 0x0054, 0xa402, 0xa532, 0x0208,
-	0x2028, 0x2500, 0x8004, 0x20a8, 0x23a0, 0xe000, 0xe000, 0xe000,
-	0x53a5, 0x2508, 0x080c, 0x5a70, 0x2130, 0x7014, 0xa600, 0x7016,
-	0x2600, 0x711c, 0xa102, 0x701e, 0x7004, 0xa600, 0x2008, 0xa082,
-	0x0007, 0x1180, 0x7000, 0x2004, 0xa005, 0x1140, 0x2009, 0x0001,
-	0x0026, 0x080c, 0x5976, 0x002e, 0x7000, 0x2004, 0x7002, 0x7007,
-	0x0000, 0x0008, 0x7106, 0x2500, 0xa212, 0x1910, 0x012e, 0x00ee,
-	0x014e, 0x013e, 0x015e, 0x0005, 0x0016, 0x0026, 0x00e6, 0x00d6,
-	0x04e9, 0x15c8, 0x2170, 0x2805, 0xac68, 0x2900, 0x0002, 0x5a0f,
-	0x5a0f, 0x5a13, 0x5a0f, 0x5a13, 0x5a0f, 0x5a0f, 0x5a0f, 0x5a0f,
-	0x5a0f, 0x5a1c, 0x5a0f, 0x5a1c, 0x5a0f, 0x5a0f, 0x5a0f, 0x080c,
-	0x13fe, 0xa005, 0x00d8, 0x7000, 0x6802, 0x7004, 0x6806, 0x7010,
-	0x680a, 0x680f, 0x0000, 0x0060, 0x7010, 0x6812, 0x6817, 0x0000,
-	0x7000, 0x6802, 0x7004, 0x6806, 0x7008, 0x680a, 0x700c, 0x680e,
-	0x00de, 0x685c, 0x8000, 0x685e, 0x00d6, 0xa006, 0x00de, 0x00ee,
-	0x002e, 0x001e, 0x0005, 0xa085, 0x0001, 0x0cc0, 0x00e6, 0x0036,
-	0x2071, 0x9363, 0x7014, 0xa005, 0x0538, 0x8001, 0x7016, 0x7008,
-	0xa080, 0x0003, 0x710c, 0x2110, 0x0411, 0x810c, 0xa118, 0x8210,
-	0xa282, 0x0007, 0x11b0, 0x7008, 0x2004, 0xa005, 0x0178, 0x00d6,
-	0x0006, 0x7008, 0x2068, 0x080c, 0x5b5c, 0x000e, 0x2068, 0x6807,
-	0x0000, 0x700a, 0x00de, 0x7010, 0x8001, 0x7012, 0x700f, 0x0000,
-	0x0008, 0x720e, 0x2308, 0xa006, 0x003e, 0x00ee, 0x0005, 0x0006,
-	0x810b, 0x810b, 0x2100, 0x810b, 0xa100, 0x2008, 0x000e, 0x0005,
-	0x0006, 0x0026, 0x2100, 0xa005, 0x0160, 0xa092, 0x000c, 0x0248,
-	0x2009, 0x0000, 0x8108, 0xa082, 0x000c, 0x1de0, 0x002e, 0x000e,
-	0x0005, 0x2009, 0x0000, 0x0cd0, 0x2d00, 0xa0b8, 0x0008, 0x690c,
-	0x6810, 0x2019, 0x0001, 0x2031, 0x5ab2, 0xa112, 0x0220, 0x0118,
-	0x8318, 0x2208, 0x0cd0, 0x6808, 0xa005, 0x0108, 0x8318, 0x233a,
-	0x6804, 0xd084, 0x2300, 0x2021, 0x0001, 0x1150, 0xa082, 0x0003,
-	0x0967, 0x0a67, 0x8420, 0xa082, 0x0007, 0x0967, 0x0a67, 0x0cd0,
-	0xa082, 0x0002, 0x0967, 0x0a67, 0x8420, 0xa082, 0x0005, 0x0967,
-	0x0a67, 0x0cd0, 0x6c1a, 0x2d00, 0xa0b8, 0x0007, 0x00e6, 0x2071,
-	0x9200, 0x7128, 0x6810, 0x2019, 0x0001, 0xa10a, 0x0118, 0x0210,
-	0x8318, 0x0cd8, 0x2031, 0x5ac5, 0x0870, 0x6c16, 0x00ee, 0x0005,
-	0x00e6, 0x00c6, 0x0126, 0x2091, 0x8000, 0x2e00, 0x2060, 0x2071,
-	0x9363, 0x2009, 0x0001, 0x0026, 0x080c, 0x5976, 0x002e, 0x7300,
-	0xa398, 0x0003, 0x7104, 0x080c, 0x5a67, 0x810c, 0x2100, 0xa318,
-	0x6834, 0xa084, 0x00ff, 0xa086, 0x0024, 0x00d6, 0x2368, 0x1138,
-	0x6000, 0x6802, 0x6004, 0x6806, 0x6008, 0x6812, 0x0050, 0x6000,
-	0x6802, 0x6004, 0x6806, 0x6008, 0x680a, 0x600c, 0x680e, 0x6010,
-	0x6812, 0x00de, 0x7014, 0x8000, 0x7016, 0x711c, 0x8109, 0x711e,
-	0x7004, 0x8000, 0x2008, 0xa082, 0x0007, 0x1180, 0x7000, 0x2004,
-	0xa005, 0x1140, 0x2009, 0x0001, 0x0026, 0x080c, 0x5976, 0x002e,
-	0x7000, 0x2004, 0x7002, 0x7007, 0x0000, 0x0008, 0x7106, 0x012e,
-	0x00ce, 0x00ee, 0x0005, 0x00d6, 0x0046, 0x0126, 0x2091, 0x8000,
-	0x2001, 0x9281, 0xa080, 0x0011, 0x2004, 0x8003, 0x2020, 0x080c,
-	0x145f, 0x01d0, 0x2d00, 0x7026, 0x6803, 0x0000, 0x6807, 0x0000,
-	0x080c, 0x145f, 0x0188, 0x7024, 0x6802, 0x6807, 0x0000, 0x2d00,
-	0x7026, 0xa4a2, 0x0007, 0x0110, 0x0208, 0x0c90, 0xa085, 0x0001,
-	0x012e, 0x004e, 0x00de, 0x0005, 0x7024, 0xa005, 0x0dc8, 0x2068,
-	0x2024, 0x080c, 0x1493, 0x2400, 0x0cc0, 0x0126, 0x2091, 0x8000,
-	0x7024, 0x2068, 0xa005, 0x0130, 0x2004, 0x7026, 0x6803, 0x0000,
-	0x6807, 0x0000, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x7024,
-	0x6802, 0x2d00, 0x7026, 0x012e, 0x0005, 0x00f6, 0x00e6, 0x00d6,
-	0x00c6, 0x0086, 0x0046, 0x0056, 0x0026, 0x2031, 0x0000, 0x2001,
-	0x934a, 0x2004, 0xa005, 0x0904, 0x5bee, 0x2071, 0x9281, 0x20e1,
-	0x0002, 0x3d08, 0xd19c, 0x0140, 0x2069, 0x9200, 0x6a28, 0x761c,
-	0x7114, 0x2041, 0x0000, 0x0028, 0x7118, 0x720c, 0x7620, 0x7008,
-	0x2040, 0x080c, 0x5d03, 0x0904, 0x5bee, 0x7004, 0xd084, 0x1128,
-	0x2021, 0x0024, 0x2029, 0x0002, 0x0020, 0x2021, 0x002c, 0x2029,
-	0x000a, 0x080c, 0x147c, 0x0904, 0x5bee, 0x2d00, 0x2060, 0x6436,
-	0x0016, 0x20e1, 0x0001, 0x3d08, 0x3e00, 0xa18c, 0x00ff, 0x6142,
-	0x603e, 0x001e, 0x6746, 0x2700, 0xa086, 0xff00, 0x1118, 0x6063,
-	0x0000, 0x0010, 0x6063, 0x0003, 0xa006, 0x6002, 0x602a, 0x602e,
-	0x6006, 0x603a, 0x604a, 0x6052, 0x6056, 0x605e, 0x6066, 0x604e,
-	0x2800, 0x606a, 0x604c, 0xc0ad, 0x604e, 0x665a, 0x2c00, 0x2078,
-	0x0479, 0x607f, 0xffff, 0x6083, 0x0000, 0x8109, 0x0180, 0x080c,
-	0x147c, 0x01c0, 0x2d00, 0x7806, 0x2f00, 0x6802, 0x6d36, 0xa006,
-	0x2d00, 0x2520, 0x00e9, 0x2d00, 0x2078, 0x8109, 0x1d80, 0x2c00,
-	0xa005, 0x002e, 0x005e, 0x004e, 0x008e, 0x00ce, 0x00de, 0x00ee,
-	0x00fe, 0x0005, 0x2c00, 0x2068, 0x080c, 0x14a3, 0x2600, 0x2071,
-	0x9363, 0x7120, 0xa102, 0x0a0c, 0x13fe, 0x7022, 0xa006, 0x0c48,
-	0x00d6, 0x00c6, 0x0136, 0x0146, 0x0156, 0x0016, 0x2068, 0x2400,
-	0xa084, 0x000f, 0xa080, 0x1f59, 0x2005, 0x2005, 0xad60, 0x2c00,
-	0x2d08, 0xa188, 0x0030, 0xa102, 0x20a8, 0x2c00, 0x20a0, 0x2001,
-	0xffff, 0x40a4, 0x001e, 0x015e, 0x014e, 0x013e, 0x00ce, 0x00de,
-	0x0005, 0x00c6, 0x00e6, 0x00f6, 0x6858, 0x2071, 0x9363, 0x7120,
-	0xa102, 0x0a0c, 0x13fe, 0x7022, 0x6960, 0x694e, 0x697c, 0x2009,
-	0xffff, 0x7818, 0xa102, 0xe000, 0x0006, 0x0006, 0x0006, 0x0006,
-	0x0006, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x6852, 0x684b,
-	0x0000, 0x6868, 0xa005, 0x0118, 0x6848, 0xc085, 0x684a, 0x2d00,
-	0xa080, 0x0015, 0x2038, 0x2031, 0x0018, 0x6864, 0x2020, 0x683a,
-	0x685c, 0xa08a, 0x00ff, 0x1a0c, 0x13fe, 0x2028, 0x2d00, 0x2060,
-	0x2078, 0x6934, 0xa18c, 0x000f, 0xa188, 0x1f59, 0x2145, 0x685c,
-	0x2050, 0xa005, 0x0530, 0x2805, 0xac70, 0x6834, 0xa084, 0x00ff,
-	0xa086, 0x0024, 0x1110, 0x7008, 0x0040, 0x6834, 0xa084, 0x00ff,
-	0xa086, 0x002c, 0x190c, 0x13fe, 0x7010, 0x0006, 0x2400, 0xa005,
-	0x000e, 0x0168, 0x203a, 0x8738, 0x8631, 0x090c, 0x13fe, 0x8421,
-	0x8529, 0x0138, 0x080c, 0x1f1b, 0x090c, 0x13fe, 0x08e0, 0x080c,
-	0x5ac8, 0x6837, 0x0023, 0x00fe, 0x00ee, 0x00ce, 0x0005, 0x00e6,
-	0x00c6, 0x00a6, 0x0086, 0x0056, 0x6858, 0x2071, 0x9363, 0x7120,
-	0xa102, 0x0a0c, 0x13fe, 0x7022, 0x2d00, 0x2060, 0x6934, 0xa18c,
-	0x000f, 0xa188, 0x1f59, 0x2145, 0x685c, 0x2050, 0xa005, 0x01d0,
-	0x2028, 0x2805, 0xac70, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0024,
-	0x1110, 0x7008, 0x0008, 0x7010, 0x0006, 0xa086, 0xffff, 0x000e,
-	0x0110, 0x080c, 0x5ac8, 0x8529, 0x0128, 0x080c, 0x1f1b, 0x090c,
-	0x13fe, 0x0c38, 0x005e, 0x008e, 0x00ae, 0x00ce, 0x00ee, 0x0005,
-	0x70ac, 0xa005, 0x0138, 0x2060, 0x6008, 0xa306, 0x0110, 0x600c,
-	0x0cc0, 0x0005, 0xa085, 0x0001, 0x0ce0, 0x70ac, 0x600e, 0x2c00,
-	0x70ae, 0x0005, 0x00f6, 0x00d6, 0x0036, 0x70ac, 0xa005, 0x090c,
-	0x13fe, 0x2068, 0x2079, 0x0000, 0x2c08, 0xa11e, 0x1118, 0x680c,
-	0x70ae, 0x0060, 0xa106, 0x0140, 0x2d00, 0x2078, 0x680c, 0xa005,
-	0x090c, 0x13fe, 0x2068, 0x0cb0, 0x6b0c, 0x7b0e, 0x600f, 0x0000,
-	0x003e, 0x00de, 0x00fe, 0x0005, 0x00e6, 0x080c, 0x5c87, 0x6018,
-	0x2070, 0xa006, 0x70b2, 0x70b6, 0x080c, 0x14a3, 0x0899, 0x080c,
-	0x74f2, 0x00ee, 0x0005, 0x00d6, 0x0026, 0x0016, 0x2061, 0x9363,
-	0x6020, 0x6414, 0xa600, 0xa42a, 0x02c8, 0x6022, 0x2069, 0x9281,
-	0x6828, 0x6114, 0xa102, 0x1260, 0x2011, 0x8025, 0x080c, 0x3698,
-	0xa080, 0x0013, 0x2004, 0xa080, 0x0000, 0x200c, 0x8108, 0x2102,
-	0xa085, 0x0001, 0x001e, 0x002e, 0x00de, 0x0005, 0x2069, 0x9281,
-	0x6804, 0xd09c, 0x0120, 0x2011, 0x8026, 0x080c, 0x3698, 0x2001,
-	0x9281, 0xa080, 0x0013, 0x2004, 0xa080, 0x0001, 0x200c, 0x8108,
-	0x2102, 0xa006, 0x2031, 0x0000, 0x0c28, 0x0066, 0x6000, 0xa0b2,
-	0x0010, 0x1a0c, 0x13fe, 0x0013, 0x006e, 0x0005, 0x5d56, 0x5d56,
-	0x5d56, 0x5d58, 0x5db1, 0x5d56, 0x5d56, 0x5d56, 0x5de6, 0x5d56,
-	0x5e34, 0x5d56, 0x5d56, 0x5d56, 0x5d56, 0x5d56, 0x080c, 0x13fe,
-	0xa182, 0x0100, 0x0002, 0x5d6a, 0x5d6a, 0x5d6a, 0x5d6c, 0x5d85,
-	0x5d9d, 0x5d6a, 0x5d6a, 0x5d6a, 0x5d6a, 0x5d6a, 0x5d6a, 0x5d6a,
-	0x5d6a, 0x5d6a, 0x080c, 0x13fe, 0x00d6, 0x080c, 0x641b, 0x080c,
-	0x651c, 0x6110, 0x2168, 0x684b, 0x0000, 0x00d6, 0x6018, 0x2068,
-	0x6008, 0x68b6, 0x68bb, 0x0500, 0xa006, 0x68b2, 0x00de, 0x080c,
-	0x4809, 0x080c, 0x74f2, 0x00de, 0x0005, 0x080c, 0x641b, 0x00f6,
-	0x00d6, 0x6110, 0x2178, 0x080c, 0x82ee, 0x0140, 0x784b, 0x0006,
-	0xa006, 0x70b2, 0x70b6, 0x2f68, 0x080c, 0x4809, 0x00de, 0x00fe,
-	0x080c, 0x74f2, 0x080c, 0x651c, 0x0005, 0x080c, 0x641b, 0x080c,
-	0x266c, 0x00d6, 0x6110, 0x2168, 0x080c, 0x82ee, 0x0120, 0x684b,
-	0x0029, 0x080c, 0x4809, 0x00de, 0x080c, 0x74f2, 0x080c, 0x651c,
-	0x0005, 0xa182, 0x0100, 0x0002, 0x5dc3, 0x5dc5, 0x5dcd, 0x5dc3,
-	0x5dc3, 0x5dc3, 0x5de1, 0x5dc3, 0x5dc3, 0x5dc3, 0x5dc3, 0x5dc3,
-	0x5dc3, 0x5dc3, 0x5dc3, 0x080c, 0x13fe, 0x20e1, 0x0005, 0x3d18,
-	0x3e20, 0x2c10, 0x080c, 0x16c6, 0x0005, 0x00d6, 0x00e6, 0x6110,
-	0x2168, 0x080c, 0x5c19, 0x080c, 0x4809, 0x6018, 0x2070, 0xa006,
-	0x70b2, 0x70b6, 0x080c, 0x5cd2, 0x00ee, 0x00de, 0x080c, 0x74f2,
-	0x0005, 0x080c, 0x5cf4, 0x080c, 0x473b, 0x0005, 0xa182, 0x0100,
-	0x0002, 0x5dfb, 0x5e16, 0x5df9, 0x5df9, 0x5df9, 0x5df9, 0x5df9,
-	0x5df9, 0x5df9, 0x5df9, 0x5df9, 0x5df9, 0x5df9, 0x5df9, 0x5df9,
-	0x5df9, 0x080c, 0x13fe, 0x00d6, 0x6003, 0x0003, 0x6106, 0x6010,
-	0x2068, 0x687c, 0x680a, 0x6880, 0x680e, 0x6813, 0x0000, 0x6817,
-	0x0000, 0x00de, 0x2c10, 0x080c, 0x1c88, 0x080c, 0x605b, 0x0126,
-	0x2091, 0x8000, 0x080c, 0x651c, 0x012e, 0x0005, 0x6003, 0x0004,
-	0x630a, 0x080c, 0x5b65, 0x0168, 0x6012, 0x600f, 0x0000, 0x080c,
-	0x5ccd, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x16c6,
-	0x0005, 0x2011, 0x0000, 0x080c, 0x16c6, 0x70b3, 0x0000, 0x70b7,
-	0x0000, 0x080c, 0x74f2, 0x0005, 0x00d6, 0x080c, 0x641b, 0x080c,
-	0x651c, 0x6110, 0x2168, 0x684b, 0x0000, 0x00d6, 0x6018, 0x2068,
-	0x6008, 0x68b6, 0x68bb, 0x0500, 0xa006, 0x68b2, 0x00de, 0x080c,
-	0x4809, 0x080c, 0x74f2, 0x00de, 0x0005, 0x6000, 0xa08a, 0x0010,
-	0x1a0c, 0x13fe, 0x000b, 0x0005, 0x5e64, 0x5e64, 0x5e64, 0x5e66,
-	0x5e7f, 0x5e64, 0x5e64, 0x5e64, 0x5e64, 0x5e64, 0x5e64, 0x5e64,
-	0x5e64, 0x5e64, 0x5e64, 0x5e64, 0x080c, 0x13fe, 0x080c, 0x7366,
-	0x190c, 0x13fe, 0x6110, 0x2168, 0x684b, 0x0006, 0x00d6, 0x6018,
-	0x2068, 0x6008, 0x68b6, 0x68bb, 0x0500, 0xa006, 0x68b2, 0x00de,
-	0x080c, 0x4809, 0x080c, 0x74f2, 0x00de, 0x0005, 0x0005, 0x0005,
-	0x6000, 0xa08a, 0x0010, 0x1a0c, 0x13fe, 0x000b, 0x0005, 0x5e97,
-	0x5e97, 0x5e97, 0x5e99, 0x5e9b, 0x5e97, 0x5e97, 0x5e97, 0x5e97,
-	0x5e97, 0x5e97, 0x5e97, 0x5e97, 0x5e97, 0x5e97, 0x5e97, 0x080c,
-	0x13fe, 0x080c, 0x13fe, 0x00d6, 0x6010, 0x2068, 0x080c, 0x5cf4,
-	0x00de, 0x0005, 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e,
-	0x1208, 0xa200, 0x1f04, 0x5ea6, 0x8086, 0x818e, 0x0005, 0x0156,
-	0x20a9, 0x0010, 0xa005, 0x01b8, 0xa11a, 0x12a8, 0x8213, 0x818d,
-	0x0228, 0xa11a, 0x1220, 0x1f04, 0x5eb6, 0x0028, 0xa11a, 0x2308,
-	0x8210, 0x1f04, 0x5eb6, 0x0006, 0x3200, 0xa084, 0xefff, 0x2080,
-	0x000e, 0x015e, 0x0005, 0x0006, 0x3200, 0xa085, 0x1000, 0x0cb8,
-	0x0126, 0x2091, 0x2400, 0x2079, 0x94e5, 0x012e, 0x00d6, 0x2069,
-	0x94e5, 0x6803, 0x0005, 0x2069, 0x0004, 0x2d04, 0xa085, 0x8001,
-	0x206a, 0x00de, 0x0005, 0x00c6, 0x6027, 0x0001, 0x7804, 0xa084,
-	0x0007, 0x0002, 0x5ef4, 0x5f15, 0x5f68, 0x5efa, 0x5f15, 0x5ef4,
-	0x5ef2, 0x5ef2, 0x080c, 0x13fe, 0x080c, 0x57a1, 0x080c, 0x6462,
-	0x00ce, 0x0005, 0x62c0, 0x82ff, 0x1110, 0x00ce, 0x0005, 0x2011,
-	0x40af, 0x080c, 0x5731, 0x7828, 0xa092, 0x0002, 0x1228, 0x8000,
-	0x782a, 0x080c, 0x40fc, 0x0c88, 0x080c, 0x40af, 0x7807, 0x0003,
-	0x7827, 0x0000, 0x782b, 0x0000, 0x0c40, 0x080c, 0x57a1, 0x3c00,
-	0x0006, 0x2011, 0x0209, 0x20e1, 0x4000, 0x2214, 0x000e, 0x20e0,
-	0x82ff, 0x0178, 0x62c0, 0x82ff, 0x1160, 0x782b, 0x0000, 0x7824,
-	0xa065, 0x090c, 0x13fe, 0x2009, 0x0013, 0x080c, 0x7518, 0x00ce,
-	0x0005, 0x3900, 0xa082, 0x9606, 0x1210, 0x080c, 0x7432, 0x00c6,
-	0x7824, 0xa065, 0x090c, 0x13fe, 0x7804, 0xa086, 0x0004, 0x0904,
-	0x5fa8, 0x7828, 0xa092, 0x2710, 0x1230, 0x8000, 0x782a, 0x00ce,
-	0x080c, 0x6f11, 0x0c20, 0x6104, 0xa186, 0x0003, 0x1188, 0x00e6,
-	0x2071, 0x9200, 0x70d4, 0x00ee, 0xd08c, 0x0150, 0x00c6, 0x00e6,
-	0x2061, 0x0100, 0x2071, 0x9200, 0x080c, 0x4105, 0x00ee, 0x00ce,
-	0x080c, 0x91a0, 0x2009, 0x0014, 0x080c, 0x7518, 0x00ce, 0x0838,
-	0x2001, 0x9501, 0x2003, 0x0000, 0x62c0, 0x82ff, 0x1160, 0x782b,
-	0x0000, 0x7824, 0xa065, 0x090c, 0x13fe, 0x2009, 0x0013, 0x080c,
-	0x7563, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x3900, 0xa082, 0x9606,
-	0x1210, 0x080c, 0x7432, 0x7824, 0xa005, 0x090c, 0x13fe, 0x781c,
-	0xa06d, 0x090c, 0x13fe, 0x6800, 0xc0dc, 0x6802, 0x7924, 0x2160,
-	0x080c, 0x74f2, 0x693c, 0x81ff, 0x090c, 0x13fe, 0x8109, 0x693e,
-	0x6854, 0xa015, 0x0110, 0x7a1e, 0x0010, 0x7918, 0x791e, 0x7807,
-	0x0000, 0x7827, 0x0000, 0x00de, 0x00ce, 0x080c, 0x6462, 0x0888,
-	0x6104, 0xa186, 0x0002, 0x0128, 0xa186, 0x0004, 0x0110, 0x0804,
-	0x5f41, 0x7808, 0xac06, 0x0904, 0x5f41, 0x080c, 0x6389, 0x080c,
-	0x603e, 0x00ce, 0x080c, 0x6462, 0x0804, 0x5f2f, 0x00c6, 0x6027,
-	0x0002, 0x62c8, 0x60c4, 0xa205, 0x11a0, 0x793c, 0xa1e5, 0x0000,
-	0x0150, 0x2009, 0x0049, 0x601c, 0xa086, 0x0009, 0x1110, 0x2009,
-	0x0103, 0x080c, 0x7518, 0x2011, 0x9504, 0x2013, 0x0000, 0x00ce,
-	0x0005, 0x3908, 0xa192, 0x9606, 0x1210, 0x080c, 0x7432, 0x6017,
-	0x0010, 0x793c, 0x81ff, 0x0d78, 0x793c, 0xa188, 0x0007, 0x210c,
-	0xa18e, 0x0006, 0x1118, 0x6017, 0x0012, 0x0c48, 0x793c, 0xa188,
-	0x0007, 0x210c, 0xa18e, 0x0009, 0x0db0, 0x6017, 0x0016, 0x08f8,
-	0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000,
-	0x2c08, 0x2061, 0x94e5, 0x6020, 0x8000, 0x6022, 0x6010, 0xa005,
-	0x0148, 0xa080, 0x0003, 0x2102, 0x6112, 0x012e, 0x00ce, 0x001e,
-	0x000e, 0x0005, 0x6116, 0x6112, 0x0cc0, 0x00d6, 0x2069, 0x94e5,
-	0x6000, 0xd0d4, 0x0168, 0x6820, 0x8000, 0x6822, 0xa086, 0x0001,
-	0x1110, 0x2c00, 0x681e, 0x6804, 0xa084, 0x0007, 0x0804, 0x646f,
-	0xc0d5, 0x6002, 0x6818, 0xa005, 0x0158, 0x6056, 0x605b, 0x0000,
-	0x0006, 0x2c00, 0x681a, 0x00de, 0x685a, 0x2069, 0x94e5, 0x0c18,
-	0x6056, 0x605a, 0x2c00, 0x681a, 0x681e, 0x08e8, 0x0006, 0x0016,
-	0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061,
-	0x94e5, 0x6020, 0x8000, 0x6022, 0x6008, 0xa005, 0x0148, 0xa080,
-	0x0003, 0x2102, 0x610a, 0x012e, 0x00ce, 0x001e, 0x000e, 0x0005,
-	0x610e, 0x610a, 0x0cc0, 0x00c6, 0x600f, 0x0000, 0x2c08, 0x2061,
-	0x94e5, 0x6034, 0xa005, 0x0130, 0xa080, 0x0003, 0x2102, 0x6136,
-	0x00ce, 0x0005, 0x613a, 0x6136, 0x0cd8, 0x00f6, 0x00e6, 0x00d6,
-	0x00c6, 0x0066, 0x0026, 0x0016, 0x0006, 0x0126, 0x2071, 0x94e5,
-	0x7638, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0904, 0x60cb,
-	0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904, 0x60c6, 0x88ff,
-	0x0118, 0x6020, 0xa106, 0x15d0, 0x703c, 0xac06, 0x1120, 0x6003,
-	0x000a, 0x630a, 0x0498, 0x7038, 0xac36, 0x1110, 0x660c, 0x763a,
-	0x7034, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7036,
-	0x0010, 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110,
-	0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0x82ee, 0x0188,
-	0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x11f8, 0x6837, 0x0103,
-	0x6b4a, 0x6847, 0x0000, 0x080c, 0x8527, 0x080c, 0x4809, 0x080c,
-	0x848f, 0x080c, 0x849b, 0x00ce, 0x0804, 0x607d, 0x2c78, 0x600c,
-	0x2060, 0x0804, 0x607d, 0x012e, 0x000e, 0x001e, 0x002e, 0x006e,
-	0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006,
-	0x19e8, 0x080c, 0x9097, 0x0c28, 0x0006, 0x0066, 0x00c6, 0x00d6,
-	0x00f6, 0x2031, 0x0000, 0x0126, 0x2091, 0x8000, 0x2079, 0x94e5,
-	0x7838, 0xa065, 0x0510, 0x600c, 0x0006, 0x600f, 0x0000, 0x783c,
-	0xac06, 0x1128, 0x6003, 0x000a, 0x630a, 0x2c30, 0x00a0, 0x080c,
-	0x82ee, 0x0178, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x11b0,
-	0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x4809, 0x080c,
-	0x848f, 0x080c, 0x849b, 0x000e, 0x08e0, 0x7e3a, 0x7e36, 0x012e,
+	0x00f6, 0x7000, 0xa084, 0xf000, 0xa086, 0xc000, 0x0598, 0x080c,
+	0x6cc2, 0x0580, 0x00c6, 0x0046, 0x2011, 0x9083, 0x2204, 0x8211,
+	0x220c, 0x080c, 0x22e9, 0x1568, 0x080c, 0x42d6, 0x1550, 0x6612,
+	0x6516, 0x2c00, 0x004e, 0x00ce, 0x601a, 0x080c, 0x1488, 0x01f0,
+	0x2d00, 0x6026, 0x6803, 0x0000, 0x6837, 0x0000, 0x6c3a, 0xadf8,
+	0x000f, 0x20a9, 0x000e, 0x2fa0, 0x2e98, 0x53a3, 0x6013, 0x0205,
+	0x6007, 0x003e, 0x601f, 0x0001, 0x6003, 0x0001, 0x080c, 0x58e2,
+	0x080c, 0x5d10, 0x00fe, 0x00de, 0x00ce, 0x0005, 0x080c, 0x6d18,
+	0x0cc8, 0x004e, 0x00ce, 0x0cd0, 0x2071, 0x8dbd, 0x7003, 0x0003,
+	0x700f, 0x0361, 0xa006, 0x701a, 0x7012, 0x7017, 0x9200, 0x7007,
+	0x0000, 0x7026, 0x702b, 0x6704, 0x7032, 0x7037, 0x6745, 0x703b,
+	0xffff, 0x703f, 0xffff, 0x0005, 0x2071, 0x8dbd, 0x1d04, 0x55fc,
+	0x2091, 0x6000, 0x700c, 0x8001, 0x700e, 0x1120, 0x700f, 0x0361,
+	0x7007, 0x0001, 0x0126, 0x2091, 0x8000, 0x7024, 0xa00d, 0x0158,
+	0x7020, 0x8001, 0x7022, 0x1138, 0x7023, 0x0009, 0x8109, 0x7126,
+	0x1110, 0x7028, 0x080f, 0x7030, 0xa00d, 0x0158, 0x702c, 0x8001,
+	0x702e, 0x1138, 0x702f, 0x0009, 0x8109, 0x7132, 0x1110, 0x7034,
+	0x080f, 0x7038, 0xa005, 0x0118, 0x0310, 0x8001, 0x703a, 0x703c,
+	0xa005, 0x0118, 0x0310, 0x8001, 0x703e, 0x7018, 0xa00d, 0x0158,
+	0x7008, 0x8001, 0x700a, 0x1138, 0x700b, 0x0009, 0x8109, 0x711a,
+	0x1110, 0x701c, 0x080f, 0x012e, 0x7004, 0x0002, 0x5622, 0x5623,
+	0x563b, 0x00e6, 0x2071, 0x8dbd, 0x7018, 0xa005, 0x1120, 0x711a,
+	0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071,
+	0x8dbd, 0x701c, 0xa206, 0x1110, 0x701a, 0x701e, 0x000e, 0x00ee,
+	0x0005, 0x00e6, 0x2071, 0x8dbd, 0x6088, 0xa102, 0x0208, 0x618a,
+	0x00ee, 0x0005, 0x0005, 0x7110, 0x080c, 0x430a, 0x1158, 0x6088,
+	0x8001, 0x0240, 0x608a, 0x1130, 0x0126, 0x2091, 0x8000, 0x080c,
+	0x5d10, 0x012e, 0x8108, 0xa182, 0x00ff, 0x0218, 0xa00e, 0x7007,
+	0x0002, 0x7112, 0x0005, 0x7014, 0x2060, 0x0126, 0x2091, 0x8000,
+	0x6014, 0xa005, 0x0500, 0x8001, 0x6016, 0x11e8, 0x611c, 0xa186,
+	0x0003, 0x0118, 0xa186, 0x0006, 0x11a0, 0x6010, 0x2068, 0x6854,
+	0xa08a, 0x199a, 0x0270, 0xa082, 0x1999, 0x6856, 0xa08a, 0x199a,
+	0x0210, 0x2001, 0x1999, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116,
+	0x0010, 0x080c, 0x79ec, 0x012e, 0xac88, 0x000c, 0x7116, 0x2001,
+	0x8b17, 0x2004, 0xa102, 0x0220, 0x7017, 0x9200, 0x7007, 0x0000,
+	0x0005, 0x00e6, 0x2071, 0x8dbd, 0x7027, 0x07d0, 0x7023, 0x0009,
+	0x00ee, 0x0005, 0x2001, 0x8dc6, 0x2003, 0x0000, 0x0005, 0x00e6,
+	0x2071, 0x8dbd, 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005, 0x2011,
+	0x8dc9, 0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, 0x8dbd, 0x711a,
+	0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x00c6, 0x2061, 0x8e2a,
+	0x00ce, 0x0005, 0xa184, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080,
+	0x8e2a, 0x2060, 0x0005, 0x6854, 0xa08a, 0x199a, 0x0210, 0x2001,
+	0x1999, 0xa005, 0x1150, 0x00c6, 0x2061, 0x8e2a, 0x6014, 0x00ce,
+	0xa005, 0x1138, 0x2001, 0x001e, 0x0020, 0xa08e, 0xffff, 0x1108,
+	0xa006, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x684c, 0xa08c,
+	0x00c0, 0xa18e, 0x00c0, 0x0588, 0xd0b4, 0x1138, 0xd0bc, 0x11f0,
+	0x2009, 0x0006, 0x080c, 0x5711, 0x0005, 0xd0fc, 0x0140, 0xa084,
+	0x0003, 0xa08e, 0x0003, 0x05b8, 0xa08e, 0x0000, 0x15a0, 0x2009,
+	0x8b73, 0x2104, 0xd084, 0x0128, 0x2009, 0x0042, 0x080c, 0x6d3f,
+	0x0005, 0x2009, 0x0043, 0x080c, 0x6d3f, 0x0005, 0xd0fc, 0x0140,
+	0xa084, 0x0003, 0xa08e, 0x0003, 0x01f0, 0xa08e, 0x0000, 0x11d8,
+	0x2009, 0x0042, 0x080c, 0x6d3f, 0x0005, 0xd0fc, 0x0168, 0xa084,
+	0x0003, 0xa08e, 0x0003, 0x0178, 0xa08e, 0x0002, 0x0138, 0x2009,
+	0x0041, 0x080c, 0x6d3f, 0x0005, 0x0051, 0x0ce8, 0x2009, 0x0043,
+	0x080c, 0x6d3f, 0x0cc0, 0x2009, 0x0004, 0x0019, 0x0005, 0x2009,
+	0x0001, 0x6010, 0xa0ec, 0xf000, 0x01f0, 0x2068, 0x6952, 0x6800,
+	0x6012, 0xa186, 0x0001, 0x1188, 0x694c, 0xa18c, 0x8100, 0xa18e,
+	0x8100, 0x1158, 0x00c6, 0x2061, 0x8e2a, 0x6200, 0xd28c, 0x1120,
+	0x6204, 0x8210, 0x0208, 0x6206, 0x00ce, 0x080c, 0x46a1, 0x6010,
+	0xa06d, 0x190c, 0x56a3, 0x0005, 0x0156, 0x00c6, 0x2061, 0x8e2a,
+	0x6000, 0x81ff, 0x0110, 0xa205, 0x0008, 0xa204, 0x6002, 0x00ce,
+	0x015e, 0x0005, 0x6800, 0xd08c, 0x1138, 0x6808, 0xa005, 0x0120,
+	0x8001, 0x680a, 0xa085, 0x0001, 0x0005, 0x20a9, 0x0010, 0xa006,
+	0x8004, 0x8086, 0x818e, 0x1208, 0xa200, 0x1f04, 0x5751, 0x8086,
+	0x818e, 0x0005, 0x0156, 0x20a9, 0x0010, 0xa005, 0x01b8, 0xa11a,
+	0x12a8, 0x8213, 0x818d, 0x0228, 0xa11a, 0x1220, 0x1f04, 0x5761,
+	0x0028, 0xa11a, 0x2308, 0x8210, 0x1f04, 0x5761, 0x0006, 0x3200,
+	0xa084, 0xefff, 0x2080, 0x000e, 0x015e, 0x0005, 0x0006, 0x3200,
+	0xa085, 0x1000, 0x0cb8, 0x0126, 0x2091, 0x2400, 0x2079, 0x8daa,
+	0x012e, 0x00d6, 0x2069, 0x8daa, 0x6803, 0x0005, 0x2069, 0x0004,
+	0x2d04, 0xa085, 0x8001, 0x206a, 0x00de, 0x0005, 0x00c6, 0x6027,
+	0x0001, 0x7804, 0xa084, 0x0007, 0x0002, 0x579f, 0x57c0, 0x5813,
+	0x57a5, 0x57c0, 0x579f, 0x579d, 0x579d, 0x080c, 0x1410, 0x080c,
+	0x567a, 0x080c, 0x5d10, 0x00ce, 0x0005, 0x62c0, 0x82ff, 0x1110,
+	0x00ce, 0x0005, 0x2011, 0x3fe7, 0x080c, 0x560d, 0x7828, 0xa092,
+	0x0002, 0x1228, 0x8000, 0x782a, 0x080c, 0x4034, 0x0c88, 0x080c,
+	0x3fe7, 0x7807, 0x0003, 0x7827, 0x0000, 0x782b, 0x0000, 0x0c40,
+	0x080c, 0x567a, 0x3c00, 0x0006, 0x2011, 0x0209, 0x20e1, 0x4000,
+	0x2214, 0x000e, 0x20e0, 0x82ff, 0x0178, 0x62c0, 0x82ff, 0x1160,
+	0x782b, 0x0000, 0x7824, 0xa065, 0x090c, 0x1410, 0x2009, 0x0013,
+	0x080c, 0x6d3f, 0x00ce, 0x0005, 0x3900, 0xa082, 0x8eca, 0x1210,
+	0x080c, 0x6c01, 0x00c6, 0x7824, 0xa065, 0x090c, 0x1410, 0x7804,
+	0xa086, 0x0004, 0x0904, 0x5853, 0x7828, 0xa092, 0x2710, 0x1230,
+	0x8000, 0x782a, 0x00ce, 0x080c, 0x66ea, 0x0c20, 0x6104, 0xa186,
+	0x0003, 0x1188, 0x00e6, 0x2071, 0x8b00, 0x70d4, 0x00ee, 0xd08c,
+	0x0150, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0x8b00, 0x080c,
+	0x403d, 0x00ee, 0x00ce, 0x080c, 0x8a4b, 0x2009, 0x0014, 0x080c,
+	0x6d3f, 0x00ce, 0x0838, 0x2001, 0x8dc6, 0x2003, 0x0000, 0x62c0,
+	0x82ff, 0x1160, 0x782b, 0x0000, 0x7824, 0xa065, 0x090c, 0x1410,
+	0x2009, 0x0013, 0x080c, 0x6d92, 0x00ce, 0x0005, 0x00c6, 0x00d6,
+	0x3900, 0xa082, 0x8eca, 0x1210, 0x080c, 0x6c01, 0x7824, 0xa005,
+	0x090c, 0x1410, 0x781c, 0xa06d, 0x090c, 0x1410, 0x6800, 0xc0dc,
+	0x6802, 0x7924, 0x2160, 0x080c, 0x6d18, 0x693c, 0x81ff, 0x090c,
+	0x1410, 0x8109, 0x693e, 0x6854, 0xa015, 0x0110, 0x7a1e, 0x0010,
+	0x7918, 0x791e, 0x7807, 0x0000, 0x7827, 0x0000, 0x00de, 0x00ce,
+	0x080c, 0x5d10, 0x0888, 0x6104, 0xa186, 0x0002, 0x0128, 0xa186,
+	0x0004, 0x0110, 0x0804, 0x57ec, 0x7808, 0xac06, 0x0904, 0x57ec,
+	0x080c, 0x5c37, 0x080c, 0x58e2, 0x00ce, 0x080c, 0x5d10, 0x0804,
+	0x57da, 0x00c6, 0x6027, 0x0002, 0x62c8, 0x60c4, 0xa205, 0x1170,
+	0x793c, 0xa1e5, 0x0000, 0x0120, 0x2009, 0x0049, 0x080c, 0x6d3f,
+	0x2011, 0x8dc9, 0x2013, 0x0000, 0x00ce, 0x0005, 0x3908, 0xa192,
+	0x8eca, 0x1210, 0x080c, 0x6c01, 0x793c, 0x81ff, 0x0d88, 0x793c,
+	0xa188, 0x0007, 0x210c, 0xa18e, 0x0006, 0x1138, 0x6014, 0xa084,
+	0x0184, 0xa085, 0x0012, 0x6016, 0x0c38, 0x6014, 0xa084, 0x0184,
+	0xa085, 0x0016, 0x6016, 0x0c00, 0x0006, 0x0016, 0x00c6, 0x0126,
+	0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, 0x8daa, 0x6020,
+	0x8000, 0x6022, 0x6010, 0xa005, 0x0148, 0xa080, 0x0003, 0x2102,
+	0x6112, 0x012e, 0x00ce, 0x001e, 0x000e, 0x0005, 0x6116, 0x6112,
+	0x0cc0, 0x00d6, 0x2069, 0x8daa, 0x6000, 0xd0d4, 0x0168, 0x6820,
+	0x8000, 0x6822, 0xa086, 0x0001, 0x1110, 0x2c00, 0x681e, 0x6804,
+	0xa084, 0x0007, 0x0804, 0x5d16, 0xc0d5, 0x6002, 0x6818, 0xa005,
+	0x0158, 0x6056, 0x605b, 0x0000, 0x0006, 0x2c00, 0x681a, 0x00de,
+	0x685a, 0x2069, 0x8daa, 0x0c18, 0x6056, 0x605a, 0x2c00, 0x681a,
+	0x681e, 0x08e8, 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000,
+	0x600f, 0x0000, 0x2c08, 0x2061, 0x8daa, 0x6020, 0x8000, 0x6022,
+	0x6008, 0xa005, 0x0148, 0xa080, 0x0003, 0x2102, 0x610a, 0x012e,
+	0x00ce, 0x001e, 0x000e, 0x0005, 0x610e, 0x610a, 0x0cc0, 0x00c6,
+	0x600f, 0x0000, 0x2c08, 0x2061, 0x8daa, 0x6034, 0xa005, 0x0130,
+	0xa080, 0x0003, 0x2102, 0x6136, 0x00ce, 0x0005, 0x613a, 0x6136,
+	0x0cd8, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0016,
+	0x0006, 0x0126, 0x2071, 0x8daa, 0x7638, 0x2660, 0x2678, 0x2091,
+	0x8000, 0x8cff, 0x0904, 0x597a, 0x6018, 0xa080, 0x0028, 0x2004,
+	0xa206, 0x1904, 0x5975, 0x88ff, 0x0120, 0x6020, 0xa106, 0x1904,
+	0x5975, 0x703c, 0xac06, 0x1170, 0x0036, 0x2019, 0x0001, 0x080c,
+	0x68e5, 0x7033, 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047,
+	0x0000, 0x003e, 0x7038, 0xac36, 0x1110, 0x660c, 0x763a, 0x7034,
+	0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7036, 0x0010,
+	0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e,
+	0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0x7b8f, 0x0188, 0x6010,
+	0x2068, 0x601c, 0xa086, 0x0003, 0x11f8, 0x6837, 0x0103, 0x6b4a,
+	0x6847, 0x0000, 0x080c, 0x7dc8, 0x080c, 0x46a1, 0x080c, 0x7d30,
+	0x080c, 0x7d3c, 0x00ce, 0x0804, 0x5921, 0x2c78, 0x600c, 0x2060,
+	0x0804, 0x5921, 0x012e, 0x000e, 0x001e, 0x002e, 0x006e, 0x00ce,
+	0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, 0x19e8,
+	0x080c, 0x8942, 0x0c28, 0x0006, 0x0066, 0x00c6, 0x00d6, 0x00f6,
+	0x2031, 0x0000, 0x0126, 0x2091, 0x8000, 0x2079, 0x8daa, 0x7838,
+	0xa065, 0x0558, 0x600c, 0x0006, 0x600f, 0x0000, 0x783c, 0xac06,
+	0x1170, 0x0036, 0x2019, 0x0001, 0x080c, 0x68e5, 0x7833, 0x0000,
+	0x783f, 0x0000, 0x7843, 0x0000, 0x7847, 0x0000, 0x003e, 0x080c,
+	0x7b8f, 0x0178, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x11b0,
+	0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x46a1, 0x080c,
+	0x7d30, 0x080c, 0x7d3c, 0x000e, 0x0898, 0x7e3a, 0x7e36, 0x012e,
 	0x00fe, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x601c, 0xa086,
-	0x0006, 0x0150, 0x601c, 0xa086, 0x0009, 0x1d10, 0x6b4a, 0x080c,
-	0x4809, 0x080c, 0x74f2, 0x0c38, 0x080c, 0x9097, 0x0c10, 0x0016,
-	0x0026, 0x0086, 0x2041, 0x0000, 0x0099, 0x080c, 0x61d3, 0x008e,
-	0x002e, 0x001e, 0x0005, 0x00f6, 0x0126, 0x2079, 0x94e5, 0x2091,
-	0x8000, 0x080c, 0x625e, 0x080c, 0x62be, 0x012e, 0x00fe, 0x0005,
-	0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0016, 0x0006, 0x0126,
-	0x2091, 0x8000, 0x2071, 0x94e5, 0x7614, 0x2660, 0x2678, 0x8cff,
-	0x0904, 0x61c3, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904,
-	0x61be, 0x88ff, 0x0120, 0x6020, 0xa106, 0x1904, 0x61be, 0x7024,
-	0xac06, 0x1538, 0x2069, 0x0100, 0x68c0, 0xa005, 0x01f0, 0x080c,
-	0x57a1, 0x080c, 0x6f1e, 0x68c3, 0x0000, 0x080c, 0x7356, 0x7027,
-	0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120,
-	0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084,
-	0x0110, 0x6827, 0x0001, 0x003e, 0x0020, 0x6003, 0x0009, 0x630a,
-	0x04a8, 0x7014, 0xac36, 0x1110, 0x660c, 0x7616, 0x7010, 0xac36,
-	0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013,
-	0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008,
-	0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, 0x82ee, 0x0178,
-	0x601c, 0xa086, 0x0003, 0x1500, 0x6837, 0x0103, 0x6b4a, 0x6847,
-	0x0000, 0x080c, 0x8527, 0x080c, 0x4809, 0x080c, 0x848f, 0x080c,
-	0x849b, 0x080c, 0x7238, 0x00ce, 0x0804, 0x614f, 0x2c78, 0x600c,
-	0x2060, 0x0804, 0x614f, 0x012e, 0x000e, 0x001e, 0x006e, 0x00ce,
-	0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, 0x19e0,
-	0x080c, 0x9097, 0x0c20, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000,
-	0xa280, 0x936e, 0x2004, 0xa065, 0x0904, 0x625a, 0x00f6, 0x00e6,
-	0x00d6, 0x0066, 0x2071, 0x94e5, 0x6654, 0x7018, 0xac06, 0x1108,
-	0x761a, 0x701c, 0xac06, 0x1130, 0x86ff, 0x1118, 0x7018, 0x701e,
-	0x0008, 0x761e, 0x6058, 0xa07d, 0x0108, 0x7e56, 0xa6ed, 0x0000,
-	0x0110, 0x2f00, 0x685a, 0x6057, 0x0000, 0x605b, 0x0000, 0x6000,
-	0xc0d4, 0xc0dc, 0x6002, 0x080c, 0x43ba, 0x0904, 0x6256, 0x7624,
-	0x86ff, 0x05e8, 0xa680, 0x0004, 0x2004, 0xad06, 0x15c0, 0x00d6,
-	0x2069, 0x0100, 0x68c0, 0xa005, 0x0548, 0x080c, 0x57a1, 0x080c,
-	0x6f1e, 0x68c3, 0x0000, 0x080c, 0x7356, 0x7027, 0x0000, 0x0036,
+	0x0006, 0x1d30, 0x080c, 0x8942, 0x0c60, 0x0016, 0x0026, 0x0086,
+	0x2041, 0x0000, 0x0099, 0x080c, 0x5a81, 0x008e, 0x002e, 0x001e,
+	0x0005, 0x00f6, 0x0126, 0x2079, 0x8daa, 0x2091, 0x8000, 0x080c,
+	0x5b0c, 0x080c, 0x5b6c, 0x012e, 0x00fe, 0x0005, 0x00f6, 0x00e6,
+	0x00d6, 0x00c6, 0x0066, 0x0016, 0x0006, 0x0126, 0x2091, 0x8000,
+	0x2071, 0x8daa, 0x7614, 0x2660, 0x2678, 0x8cff, 0x0904, 0x5a71,
+	0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904, 0x5a6c, 0x88ff,
+	0x0120, 0x6020, 0xa106, 0x1904, 0x5a6c, 0x7024, 0xac06, 0x1538,
+	0x2069, 0x0100, 0x68c0, 0xa005, 0x01f0, 0x080c, 0x567a, 0x080c,
+	0x66f7, 0x68c3, 0x0000, 0x080c, 0x6b23, 0x7027, 0x0000, 0x0036,
 	0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100,
 	0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827,
-	0x0001, 0x003e, 0x00de, 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001,
-	0x603e, 0x2660, 0x080c, 0x849b, 0x00ce, 0x0048, 0x00de, 0x00c6,
-	0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, 0x6203, 0x8dff,
-	0x0148, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x8527,
-	0x080c, 0x4809, 0x080c, 0x7238, 0x0804, 0x6203, 0x006e, 0x00de,
-	0x00ee, 0x00fe, 0x012e, 0x000e, 0x00ce, 0x0005, 0x0006, 0x0066,
-	0x00c6, 0x00d6, 0x2031, 0x0000, 0x7814, 0xa065, 0x0904, 0x62b0,
-	0x600c, 0x0006, 0x600f, 0x0000, 0x7824, 0xac06, 0x1540, 0x2069,
-	0x0100, 0x68c0, 0xa005, 0x01f0, 0x080c, 0x57a1, 0x080c, 0x6f1e,
-	0x68c3, 0x0000, 0x080c, 0x7356, 0x7827, 0x0000, 0x0036, 0x2069,
-	0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803,
-	0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001,
-	0x003e, 0x0028, 0x6003, 0x0009, 0x630a, 0x2c30, 0x00b0, 0x6010,
-	0x2068, 0x080c, 0x82ee, 0x0168, 0x601c, 0xa086, 0x0003, 0x11b8,
-	0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x4809, 0x080c,
-	0x848f, 0x080c, 0x849b, 0x080c, 0x7238, 0x000e, 0x0804, 0x6265,
-	0x7e16, 0x7e12, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x601c,
-	0xa086, 0x0006, 0x1d28, 0x080c, 0x9097, 0x0c58, 0x0006, 0x0066,
-	0x00c6, 0x00d6, 0x7818, 0xa065, 0x0904, 0x6324, 0x6054, 0x0006,
-	0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002,
-	0x080c, 0x43ba, 0x0904, 0x6321, 0x7e24, 0x86ff, 0x05e8, 0xa680,
-	0x0004, 0x2004, 0xad06, 0x15c0, 0x00d6, 0x2069, 0x0100, 0x68c0,
-	0xa005, 0x0548, 0x080c, 0x57a1, 0x080c, 0x6f1e, 0x68c3, 0x0000,
-	0x080c, 0x7356, 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04,
+	0x0001, 0x003e, 0x0020, 0x6003, 0x0009, 0x630a, 0x04a8, 0x7014,
+	0xac36, 0x1110, 0x660c, 0x7616, 0x7010, 0xac36, 0x1140, 0x2c00,
+	0xaf36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, 0x660c,
+	0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f,
+	0x0000, 0x6010, 0x2068, 0x080c, 0x7b8f, 0x0178, 0x601c, 0xa086,
+	0x0003, 0x1500, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c,
+	0x7dc8, 0x080c, 0x46a1, 0x080c, 0x7d30, 0x080c, 0x7d3c, 0x080c,
+	0x6a05, 0x00ce, 0x0804, 0x59fd, 0x2c78, 0x600c, 0x2060, 0x0804,
+	0x59fd, 0x012e, 0x000e, 0x001e, 0x006e, 0x00ce, 0x00de, 0x00ee,
+	0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, 0x19e0, 0x080c, 0x8942,
+	0x0c20, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0xa280, 0x8c34,
+	0x2004, 0xa065, 0x0904, 0x5b08, 0x00f6, 0x00e6, 0x00d6, 0x0066,
+	0x2071, 0x8daa, 0x6654, 0x7018, 0xac06, 0x1108, 0x761a, 0x701c,
+	0xac06, 0x1130, 0x86ff, 0x1118, 0x7018, 0x701e, 0x0008, 0x761e,
+	0x6058, 0xa07d, 0x0108, 0x7e56, 0xa6ed, 0x0000, 0x0110, 0x2f00,
+	0x685a, 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc,
+	0x6002, 0x080c, 0x4290, 0x0904, 0x5b04, 0x7624, 0x86ff, 0x05e8,
+	0xa680, 0x0004, 0x2004, 0xad06, 0x15c0, 0x00d6, 0x2069, 0x0100,
+	0x68c0, 0xa005, 0x0548, 0x080c, 0x567a, 0x080c, 0x66f7, 0x68c3,
+	0x0000, 0x080c, 0x6b23, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140,
+	0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000,
+	0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e,
+	0x00de, 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001, 0x603e, 0x2660,
+	0x080c, 0x7d3c, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003,
+	0x0009, 0x630a, 0x00ce, 0x0804, 0x5ab1, 0x8dff, 0x0148, 0x6837,
+	0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x7dc8, 0x080c, 0x46a1,
+	0x080c, 0x6a05, 0x0804, 0x5ab1, 0x006e, 0x00de, 0x00ee, 0x00fe,
+	0x012e, 0x000e, 0x00ce, 0x0005, 0x0006, 0x0066, 0x00c6, 0x00d6,
+	0x2031, 0x0000, 0x7814, 0xa065, 0x0904, 0x5b5e, 0x600c, 0x0006,
+	0x600f, 0x0000, 0x7824, 0xac06, 0x1540, 0x2069, 0x0100, 0x68c0,
+	0xa005, 0x01f0, 0x080c, 0x567a, 0x080c, 0x66f7, 0x68c3, 0x0000,
+	0x080c, 0x6b23, 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04,
 	0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069,
-	0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x00de,
+	0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0028,
+	0x6003, 0x0009, 0x630a, 0x2c30, 0x00b0, 0x6010, 0x2068, 0x080c,
+	0x7b8f, 0x0168, 0x601c, 0xa086, 0x0003, 0x11b8, 0x6837, 0x0103,
+	0x6b4a, 0x6847, 0x0000, 0x080c, 0x46a1, 0x080c, 0x7d30, 0x080c,
+	0x7d3c, 0x080c, 0x6a05, 0x000e, 0x0804, 0x5b13, 0x7e16, 0x7e12,
+	0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x601c, 0xa086, 0x0006,
+	0x1d28, 0x080c, 0x8942, 0x0c58, 0x0006, 0x0066, 0x00c6, 0x00d6,
+	0x7818, 0xa065, 0x0904, 0x5bd2, 0x6054, 0x0006, 0x6057, 0x0000,
+	0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x080c, 0x4290,
+	0x0904, 0x5bcf, 0x7e24, 0x86ff, 0x05e8, 0xa680, 0x0004, 0x2004,
+	0xad06, 0x15c0, 0x00d6, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0548,
+	0x080c, 0x567a, 0x080c, 0x66f7, 0x68c3, 0x0000, 0x080c, 0x6b23,
+	0x7827, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000,
+	0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824,
+	0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0x603c,
+	0xa005, 0x0110, 0x8001, 0x603e, 0x2660, 0x080c, 0x7d3c, 0x00ce,
+	0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce,
+	0x0804, 0x5b7e, 0x8dff, 0x0138, 0x6837, 0x0103, 0x6b4a, 0x6847,
+	0x0000, 0x080c, 0x46a1, 0x080c, 0x6a05, 0x0804, 0x5b7e, 0x000e,
+	0x0804, 0x5b71, 0x781e, 0x781a, 0x00de, 0x00ce, 0x006e, 0x000e,
+	0x0005, 0x00e6, 0x00d6, 0x0066, 0x6000, 0xd0dc, 0x0188, 0x604c,
+	0xa06d, 0x0170, 0x6848, 0xa606, 0x1158, 0x2071, 0x8daa, 0x7024,
+	0xa035, 0x0130, 0xa080, 0x0004, 0x2004, 0xad06, 0x1108, 0x0021,
+	0x006e, 0x00de, 0x00ee, 0x0005, 0x00f6, 0x2079, 0x0100, 0x78c0,
+	0xa005, 0x1138, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce,
+	0x04a0, 0x080c, 0x66f7, 0x78c3, 0x0000, 0x080c, 0x6b23, 0x7027,
+	0x0000, 0x0036, 0x2079, 0x0140, 0x7b04, 0xa384, 0x1000, 0x0120,
+	0x7803, 0x0100, 0x7803, 0x0000, 0x2079, 0x0100, 0x7824, 0xd084,
+	0x0110, 0x7827, 0x0001, 0x080c, 0x6b23, 0x003e, 0x080c, 0x4290,
 	0x00c6, 0x603c, 0xa005, 0x0110, 0x8001, 0x603e, 0x2660, 0x080c,
-	0x849b, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009,
-	0x630a, 0x00ce, 0x0804, 0x62d0, 0x8dff, 0x0138, 0x6837, 0x0103,
-	0x6b4a, 0x6847, 0x0000, 0x080c, 0x4809, 0x080c, 0x7238, 0x0804,
-	0x62d0, 0x000e, 0x0804, 0x62c3, 0x781e, 0x781a, 0x00de, 0x00ce,
-	0x006e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x0066, 0x6000, 0xd0dc,
-	0x0188, 0x604c, 0xa06d, 0x0170, 0x6848, 0xa606, 0x1158, 0x2071,
-	0x94e5, 0x7024, 0xa035, 0x0130, 0xa080, 0x0004, 0x2004, 0xad06,
-	0x1108, 0x0021, 0x006e, 0x00de, 0x00ee, 0x0005, 0x00f6, 0x2079,
-	0x0100, 0x78c0, 0xa005, 0x1138, 0x00c6, 0x2660, 0x6003, 0x0009,
-	0x630a, 0x00ce, 0x04a0, 0x080c, 0x6f1e, 0x78c3, 0x0000, 0x080c,
-	0x7356, 0x7027, 0x0000, 0x0036, 0x2079, 0x0140, 0x7b04, 0xa384,
-	0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, 0x2079, 0x0100,
-	0x7824, 0xd084, 0x0110, 0x7827, 0x0001, 0x080c, 0x7356, 0x003e,
-	0x080c, 0x43ba, 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001, 0x603e,
-	0x2660, 0x080c, 0x74f2, 0x00ce, 0x6837, 0x0103, 0x6b4a, 0x6847,
-	0x0000, 0x080c, 0x8527, 0x080c, 0x4809, 0x080c, 0x7238, 0x00fe,
-	0x0005, 0x00e6, 0x00c6, 0x2071, 0x94e5, 0x7004, 0xa084, 0x0007,
-	0x0002, 0x639b, 0x639e, 0x63b4, 0x63cd, 0x6406, 0x639b, 0x6399,
-	0x6399, 0x080c, 0x13fe, 0x00ce, 0x00ee, 0x0005, 0x7024, 0xa065,
-	0x0148, 0x7020, 0x8001, 0x7022, 0x600c, 0xa015, 0x0150, 0x7216,
-	0x600f, 0x0000, 0x7007, 0x0000, 0x7027, 0x0000, 0x00ce, 0x00ee,
-	0x0005, 0x7216, 0x7212, 0x0cb0, 0x6018, 0x2060, 0x080c, 0x43ba,
-	0x6000, 0xc0dc, 0x6002, 0x7020, 0x8001, 0x7022, 0x0120, 0x6054,
-	0xa015, 0x0140, 0x721e, 0x7007, 0x0000, 0x7027, 0x0000, 0x00ce,
-	0x00ee, 0x0005, 0x7218, 0x721e, 0x0cb0, 0x7024, 0xa065, 0x0598,
-	0x700c, 0xac06, 0x1160, 0x080c, 0x7238, 0x600c, 0xa015, 0x0120,
-	0x720e, 0x600f, 0x0000, 0x0428, 0x720e, 0x720a, 0x0410, 0x7014,
-	0xac06, 0x1160, 0x080c, 0x7238, 0x600c, 0xa015, 0x0120, 0x7216,
-	0x600f, 0x0000, 0x00b0, 0x7216, 0x7212, 0x0098, 0x6018, 0x2060,
-	0x080c, 0x43ba, 0x6000, 0xc0dc, 0x6002, 0x080c, 0x7238, 0x701c,
-	0xa065, 0x0138, 0x6054, 0xa015, 0x0110, 0x721e, 0x0010, 0x7218,
-	0x721e, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005, 0x7024, 0xa065,
-	0x0140, 0x080c, 0x7238, 0x600c, 0xa015, 0x0150, 0x720e, 0x600f,
-	0x0000, 0x080c, 0x7356, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005,
-	0x720e, 0x720a, 0x0cb0, 0x00d6, 0x2069, 0x94e5, 0x6830, 0xa084,
-	0x0003, 0x0002, 0x6428, 0x642a, 0x644a, 0x6426, 0x080c, 0x13fe,
-	0x00de, 0x0005, 0x00c6, 0x6840, 0xa086, 0x0001, 0x0198, 0x683c,
-	0xa065, 0x0130, 0x600c, 0xa015, 0x0150, 0x6a3a, 0x600f, 0x0000,
-	0x6833, 0x0000, 0x683f, 0x0000, 0x00ce, 0x00de, 0x0005, 0x683a,
-	0x6836, 0x0cb0, 0x6843, 0x0000, 0x6838, 0xa065, 0x0d88, 0x6003,
-	0x0003, 0x0c70, 0x00c6, 0x6843, 0x0000, 0x6847, 0x0000, 0x683c,
-	0xa065, 0x0168, 0x600c, 0xa015, 0x0130, 0x6a3a, 0x600f, 0x0000,
-	0x683f, 0x0000, 0x0020, 0x683f, 0x0000, 0x683a, 0x6836, 0x00ce,
-	0x00de, 0x0005, 0x00d6, 0x2001, 0x9295, 0x2004, 0xd084, 0x0110,
-	0x00de, 0x0005, 0x2069, 0x94e5, 0x6804, 0xa084, 0x0007, 0x0002,
-	0x647a, 0x650c, 0x650c, 0x650c, 0x650c, 0x650e, 0x6478, 0x6478,
-	0x080c, 0x13fe, 0x6820, 0xa005, 0x1110, 0x00de, 0x0005, 0x00c6,
-	0x680c, 0xa065, 0x0150, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000,
-	0x080c, 0x656d, 0x00ce, 0x00de, 0x0005, 0x6814, 0xa065, 0x0150,
-	0x6807, 0x0001, 0x6826, 0x682b, 0x0000, 0x080c, 0x656d, 0x00ce,
-	0x00de, 0x0005, 0x00e6, 0x0036, 0x6a1c, 0xa2f5, 0x0000, 0x0904,
-	0x6508, 0x704c, 0xa00d, 0x0118, 0x7088, 0xa005, 0x01a0, 0x7054,
-	0xa075, 0x0120, 0xa20e, 0x0904, 0x6508, 0x0028, 0x6818, 0xa20e,
-	0x0904, 0x6508, 0x2070, 0x704c, 0xa00d, 0x0d88, 0x7088, 0xa005,
-	0x1d70, 0x2e00, 0x681e, 0x733c, 0x7038, 0xa302, 0x1e40, 0x080c,
-	0x74c9, 0x0904, 0x6508, 0x8318, 0x733e, 0x6112, 0x2e10, 0x621a,
-	0xa180, 0x0015, 0x2004, 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999,
-	0x8003, 0x801b, 0x831b, 0xa318, 0x6316, 0x003e, 0x00f6, 0x2c78,
-	0x71a0, 0x2001, 0x9232, 0x2004, 0xd0ac, 0x1110, 0xd1bc, 0x0150,
-	0x7100, 0xd1f4, 0x0120, 0x7114, 0xa18c, 0x00ff, 0x0040, 0x2009,
-	0x0000, 0x0028, 0xa1e0, 0x2719, 0x2c0d, 0xa18c, 0x00ff, 0x2061,
-	0x0100, 0x619a, 0x080c, 0x6a46, 0x7300, 0xc3dd, 0x7302, 0x6807,
-	0x0002, 0x2f18, 0x6b26, 0x682b, 0x0000, 0x781f, 0x0003, 0x7803,
-	0x0001, 0x7807, 0x0040, 0x00fe, 0x00ee, 0x00ce, 0x00de, 0x0005,
-	0x003e, 0x00ee, 0x00ce, 0x0cd0, 0x00de, 0x0005, 0x00c6, 0x680c,
-	0xa065, 0x0138, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x080c,
-	0x656d, 0x00ce, 0x00de, 0x0005, 0x00f6, 0x00d6, 0x2069, 0x94e5,
-	0x6830, 0xa086, 0x0000, 0x1590, 0x6838, 0xa07d, 0x0578, 0x781c,
-	0xa086, 0x0009, 0x1140, 0x7808, 0xd0fc, 0x0128, 0x2001, 0x94e6,
-	0x2004, 0xa005, 0x1518, 0x2f00, 0x6833, 0x0001, 0x683e, 0x6847,
-	0x0000, 0x0126, 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c, 0x1d0f,
-	0x11c0, 0x012e, 0xe000, 0xe000, 0xe000, 0x6a3c, 0x2278, 0x781c,
-	0xa086, 0x0009, 0x1148, 0x7808, 0xd0fc, 0x0118, 0x080c, 0x6cf9,
-	0x0028, 0x080c, 0x6d75, 0x0010, 0x080c, 0x6dec, 0x00de, 0x00fe,
-	0x0005, 0x012e, 0xe000, 0x6843, 0x0000, 0x7803, 0x0002, 0x780c,
-	0xa015, 0x0140, 0x6a3a, 0x780f, 0x0000, 0x6833, 0x0000, 0x683f,
-	0x0000, 0x0c60, 0x683a, 0x6836, 0x0cc0, 0x601c, 0xa084, 0x000f,
-	0x000b, 0x0005, 0x657b, 0x6580, 0x68f8, 0x6a03, 0x6580, 0x68f8,
-	0x6a03, 0x657b, 0x6580, 0x080c, 0x6389, 0x080c, 0x6462, 0x0005,
-	0x0156, 0x0136, 0x0146, 0x00c6, 0x00f6, 0x6004, 0xa08a, 0x003e,
-	0x1a0c, 0x13fe, 0x6118, 0x2178, 0x79a0, 0x2011, 0x9232, 0x2214,
-	0xd2ac, 0x1110, 0xd1bc, 0x0150, 0x7900, 0xd1f4, 0x0120, 0x7914,
-	0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, 0xa1f8, 0x2719,
-	0x2f0d, 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0x0033,
-	0x00fe, 0x00ce, 0x014e, 0x013e, 0x015e, 0x0005, 0x65f5, 0x662d,
-	0x6647, 0x66fa, 0x6725, 0x672d, 0x674e, 0x675f, 0x6770, 0x6778,
-	0x6789, 0x6778, 0x67ce, 0x675f, 0x67ef, 0x67f7, 0x6770, 0x67f7,
-	0x6808, 0x65ec, 0x65ec, 0x65ec, 0x65ec, 0x65ec, 0x65ec, 0x65ec,
-	0x65ec, 0x65ec, 0x65ec, 0x65ec, 0x65ec, 0x6fda, 0x6fef, 0x7012,
-	0x7036, 0x674e, 0x65ec, 0x674e, 0x6778, 0x65ec, 0x6647, 0x66fa,
-	0x65ec, 0x744f, 0x6778, 0x65ec, 0x746f, 0x6778, 0x65ec, 0x6770,
-	0x65ee, 0x65ec, 0x65ec, 0x65ec, 0x65ec, 0x65ec, 0x65ec, 0x65ec,
-	0x65ec, 0x65ec, 0x65ec, 0x704b, 0x080c, 0x13fe, 0x2001, 0x9214,
-	0x2004, 0x609a, 0x080c, 0x6f0b, 0x0005, 0x20a1, 0x020b, 0x080c,
-	0x681d, 0x20a3, 0x5200, 0x20a3, 0x0000, 0x00d6, 0x2069, 0x9251,
+	0x6d18, 0x00ce, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c,
+	0x7dc8, 0x080c, 0x46a1, 0x080c, 0x6a05, 0x00fe, 0x0005, 0x00e6,
+	0x00c6, 0x2071, 0x8daa, 0x7004, 0xa084, 0x0007, 0x0002, 0x5c49,
+	0x5c4c, 0x5c62, 0x5c7b, 0x5cb4, 0x5c49, 0x5c47, 0x5c47, 0x080c,
+	0x1410, 0x00ce, 0x00ee, 0x0005, 0x7024, 0xa065, 0x0148, 0x7020,
+	0x8001, 0x7022, 0x600c, 0xa015, 0x0150, 0x7216, 0x600f, 0x0000,
+	0x7007, 0x0000, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005, 0x7216,
+	0x7212, 0x0cb0, 0x6018, 0x2060, 0x080c, 0x4290, 0x6000, 0xc0dc,
+	0x6002, 0x7020, 0x8001, 0x7022, 0x0120, 0x6054, 0xa015, 0x0140,
+	0x721e, 0x7007, 0x0000, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005,
+	0x7218, 0x721e, 0x0cb0, 0x7024, 0xa065, 0x0598, 0x700c, 0xac06,
+	0x1160, 0x080c, 0x6a05, 0x600c, 0xa015, 0x0120, 0x720e, 0x600f,
+	0x0000, 0x0428, 0x720e, 0x720a, 0x0410, 0x7014, 0xac06, 0x1160,
+	0x080c, 0x6a05, 0x600c, 0xa015, 0x0120, 0x7216, 0x600f, 0x0000,
+	0x00b0, 0x7216, 0x7212, 0x0098, 0x6018, 0x2060, 0x080c, 0x4290,
+	0x6000, 0xc0dc, 0x6002, 0x080c, 0x6a05, 0x701c, 0xa065, 0x0138,
+	0x6054, 0xa015, 0x0110, 0x721e, 0x0010, 0x7218, 0x721e, 0x7027,
+	0x0000, 0x00ce, 0x00ee, 0x0005, 0x7024, 0xa065, 0x0140, 0x080c,
+	0x6a05, 0x600c, 0xa015, 0x0150, 0x720e, 0x600f, 0x0000, 0x080c,
+	0x6b23, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005, 0x720e, 0x720a,
+	0x0cb0, 0x00d6, 0x2069, 0x8daa, 0x6830, 0xa084, 0x0003, 0x0002,
+	0x5cd6, 0x5cd8, 0x5cf8, 0x5cd4, 0x080c, 0x1410, 0x00de, 0x0005,
+	0x00c6, 0x6840, 0xa086, 0x0001, 0x0198, 0x683c, 0xa065, 0x0130,
+	0x600c, 0xa015, 0x0150, 0x6a3a, 0x600f, 0x0000, 0x6833, 0x0000,
+	0x683f, 0x0000, 0x00ce, 0x00de, 0x0005, 0x683a, 0x6836, 0x0cb0,
+	0x6843, 0x0000, 0x6838, 0xa065, 0x0d88, 0x6003, 0x0003, 0x0c70,
+	0x00c6, 0x6843, 0x0000, 0x6847, 0x0000, 0x683c, 0xa065, 0x0168,
+	0x600c, 0xa015, 0x0130, 0x6a3a, 0x600f, 0x0000, 0x683f, 0x0000,
+	0x0020, 0x683f, 0x0000, 0x683a, 0x6836, 0x00ce, 0x00de, 0x0005,
+	0x00d6, 0x2069, 0x8daa, 0x6804, 0xa084, 0x0007, 0x0002, 0x5d21,
+	0x5db3, 0x5db3, 0x5db3, 0x5db3, 0x5db5, 0x5d1f, 0x5d1f, 0x080c,
+	0x1410, 0x6820, 0xa005, 0x1110, 0x00de, 0x0005, 0x00c6, 0x680c,
+	0xa065, 0x0150, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x080c,
+	0x5df4, 0x00ce, 0x00de, 0x0005, 0x6814, 0xa065, 0x0150, 0x6807,
+	0x0001, 0x6826, 0x682b, 0x0000, 0x080c, 0x5df4, 0x00ce, 0x00de,
+	0x0005, 0x00e6, 0x0036, 0x6a1c, 0xa2f5, 0x0000, 0x0904, 0x5daf,
+	0x704c, 0xa00d, 0x0118, 0x7088, 0xa005, 0x01a0, 0x7054, 0xa075,
+	0x0120, 0xa20e, 0x0904, 0x5daf, 0x0028, 0x6818, 0xa20e, 0x0904,
+	0x5daf, 0x2070, 0x704c, 0xa00d, 0x0d88, 0x7088, 0xa005, 0x1d70,
+	0x2e00, 0x681e, 0x733c, 0x7038, 0xa302, 0x1e40, 0x080c, 0x6cef,
+	0x0904, 0x5daf, 0x8318, 0x733e, 0x6112, 0x2e10, 0x621a, 0xa180,
+	0x0015, 0x2004, 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003,
+	0x801b, 0x831b, 0xa318, 0x6316, 0x003e, 0x00f6, 0x2c78, 0x71a0,
+	0x2001, 0x8b32, 0x2004, 0xd0ac, 0x1110, 0xd1bc, 0x0150, 0x7100,
+	0xd1f4, 0x0120, 0x7114, 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000,
+	0x0028, 0xa1e0, 0x263d, 0x2c0d, 0xa18c, 0x00ff, 0x2061, 0x0100,
+	0x619a, 0x080c, 0x62f1, 0x7300, 0xc3dd, 0x7302, 0x6807, 0x0002,
+	0x2f18, 0x6b26, 0x682b, 0x0000, 0x781f, 0x0003, 0x7803, 0x0001,
+	0x7807, 0x0040, 0x00fe, 0x00ee, 0x00ce, 0x00de, 0x0005, 0x003e,
+	0x00ee, 0x00ce, 0x0cd0, 0x00de, 0x0005, 0x00c6, 0x680c, 0xa065,
+	0x0130, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x04a9, 0x00ce,
+	0x00de, 0x0005, 0x00f6, 0x00d6, 0x2069, 0x8daa, 0x6830, 0xa086,
+	0x0000, 0x1198, 0x6838, 0xa07d, 0x0180, 0x6833, 0x0001, 0x683e,
+	0x6847, 0x0000, 0x0126, 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c,
+	0x1c40, 0x1130, 0x012e, 0x080c, 0x65ca, 0x00de, 0x00fe, 0x0005,
+	0x012e, 0xe000, 0x6843, 0x0000, 0x7803, 0x0002, 0x780c, 0xa015,
+	0x0140, 0x6a3a, 0x780f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000,
+	0x0c60, 0x683a, 0x6836, 0x0cc0, 0x601c, 0xa084, 0x000f, 0x000b,
+	0x0005, 0x5e02, 0x5e07, 0x618e, 0x62ae, 0x5e07, 0x618e, 0x62ae,
+	0x5e02, 0x5e07, 0x080c, 0x5c37, 0x080c, 0x5d10, 0x0005, 0x0156,
+	0x0136, 0x0146, 0x00c6, 0x00f6, 0x6004, 0xa08a, 0x0040, 0x1a0c,
+	0x1410, 0x6118, 0x2178, 0x79a0, 0x2011, 0x8b32, 0x2214, 0xd2ac,
+	0x1110, 0xd1bc, 0x0150, 0x7900, 0xd1f4, 0x0120, 0x7914, 0xa18c,
+	0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, 0xa1f8, 0x263d, 0x2f0d,
+	0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0x0033, 0x00fe,
+	0x00ce, 0x014e, 0x013e, 0x015e, 0x0005, 0x5e7d, 0x5eb5, 0x5ecf,
+	0x5f82, 0x5fad, 0x5fb5, 0x5fd6, 0x5fe7, 0x5ff8, 0x6000, 0x6011,
+	0x6000, 0x6056, 0x5fe7, 0x6077, 0x607f, 0x5ff8, 0x607f, 0x6090,
+	0x5e74, 0x5e74, 0x5e74, 0x5e74, 0x5e74, 0x5e74, 0x5e74, 0x5e74,
+	0x5e74, 0x5e74, 0x5e74, 0x5e74, 0x67ad, 0x67c2, 0x67e5, 0x6809,
+	0x5fd6, 0x5e74, 0x5fd6, 0x6000, 0x5e74, 0x5ecf, 0x5f82, 0x5e74,
+	0x6c1e, 0x6000, 0x5e74, 0x6c3e, 0x6000, 0x5e74, 0x5ff8, 0x5e76,
+	0x5e74, 0x5e74, 0x5e74, 0x5e74, 0x5e74, 0x5e74, 0x5e74, 0x5e74,
+	0x5e74, 0x5e74, 0x681e, 0x6c63, 0x080c, 0x1410, 0x2001, 0x8b14,
+	0x2004, 0x609a, 0x080c, 0x66e4, 0x0005, 0x20a1, 0x020b, 0x080c,
+	0x60a5, 0x20a3, 0x5200, 0x20a3, 0x0000, 0x00d6, 0x2069, 0x8b51,
 	0x6804, 0xd084, 0x0150, 0x6828, 0x20a3, 0x0000, 0x0016, 0x080c,
-	0x241f, 0x21a2, 0x001e, 0x00de, 0x0028, 0x00de, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, 0x9205, 0x53a6, 0x20a9,
-	0x0004, 0x2099, 0x9201, 0x53a6, 0x20a3, 0x0000, 0x2001, 0x9214,
+	0x22fd, 0x21a2, 0x001e, 0x00de, 0x0028, 0x00de, 0x20a3, 0x0000,
+	0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, 0x8b05, 0x53a6, 0x20a9,
+	0x0004, 0x2099, 0x8b01, 0x53a6, 0x20a3, 0x0000, 0x2001, 0x8b14,
 	0x2004, 0xa084, 0x00ff, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x60c3, 0x001c, 0x080c, 0x6f0b, 0x0005, 0x20a1, 0x020b, 0x080c,
-	0x681d, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x2001, 0x921b, 0x2004,
-	0x20a2, 0x2001, 0x921c, 0x2004, 0x20a2, 0x20a9, 0x0004, 0x2099,
-	0x9205, 0x53a6, 0x60c3, 0x0010, 0x080c, 0x6f0b, 0x0005, 0x20a1,
-	0x020b, 0x080c, 0x681d, 0x7818, 0xa080, 0x0028, 0x2004, 0xa086,
+	0x60c3, 0x001c, 0x080c, 0x66e4, 0x0005, 0x20a1, 0x020b, 0x080c,
+	0x60a5, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x2001, 0x8b1b, 0x2004,
+	0x20a2, 0x2001, 0x8b1c, 0x2004, 0x20a2, 0x20a9, 0x0004, 0x2099,
+	0x8b05, 0x53a6, 0x60c3, 0x0010, 0x080c, 0x66e4, 0x0005, 0x20a1,
+	0x020b, 0x080c, 0x60a5, 0x7818, 0xa080, 0x0028, 0x2004, 0xa086,
 	0x007e, 0x1130, 0x20a3, 0x0400, 0x620c, 0xc2b4, 0x620e, 0x0010,
 	0x20a3, 0x0300, 0x20a3, 0x0000, 0x7818, 0xa080, 0x0028, 0x2004,
-	0xa086, 0x007e, 0x1904, 0x66bc, 0x2001, 0x9232, 0x2004, 0xd0a4,
-	0x01c8, 0x2099, 0x94c7, 0x33a6, 0x9398, 0x20a3, 0x0000, 0x9398,
+	0xa086, 0x007e, 0x1904, 0x5f44, 0x2001, 0x8b32, 0x2004, 0xd0a4,
+	0x01c8, 0x2099, 0x8d8c, 0x33a6, 0x9398, 0x20a3, 0x0000, 0x9398,
 	0x3304, 0xa084, 0x2000, 0x20a2, 0x9398, 0x33a6, 0x9398, 0x20a3,
 	0x0000, 0x9398, 0x2001, 0x2710, 0x20a2, 0x9398, 0x33a6, 0x9398,
-	0x33a6, 0x00d0, 0x2099, 0x94c7, 0x33a6, 0x9398, 0x33a6, 0x9398,
-	0x3304, 0x080c, 0x4dc5, 0x1118, 0xa084, 0x37ff, 0x0010, 0xa084,
+	0x33a6, 0x00d0, 0x2099, 0x8d8c, 0x33a6, 0x9398, 0x33a6, 0x9398,
+	0x3304, 0x080c, 0x4c42, 0x1118, 0xa084, 0x37ff, 0x0010, 0xa084,
 	0x3fff, 0x20a2, 0x9398, 0x33a6, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, 0x9205,
-	0x53a6, 0x20a9, 0x0004, 0x2099, 0x9201, 0x53a6, 0x20a9, 0x0008,
-	0x20a3, 0x0000, 0x1f04, 0x66a8, 0x20a9, 0x0008, 0x20a3, 0x0000,
-	0x1f04, 0x66ae, 0x2099, 0x94cf, 0x33a6, 0x20a9, 0x0007, 0x20a3,
-	0x0000, 0x1f04, 0x66b7, 0x0468, 0x2001, 0x9232, 0x2004, 0xd0a4,
-	0x0140, 0x2001, 0x94c8, 0x2004, 0x60e3, 0x0000, 0x080c, 0x2460,
-	0x60e2, 0x2099, 0x94c7, 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0004,
-	0x2099, 0x9205, 0x53a6, 0x20a9, 0x0004, 0x2099, 0x9201, 0x53a6,
-	0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x66da, 0x20a9, 0x0008,
-	0x20a3, 0x0000, 0x1f04, 0x66e0, 0x2099, 0x94cf, 0x20a9, 0x0008,
-	0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x66eb, 0x20a9,
-	0x000a, 0x20a3, 0x0000, 0x1f04, 0x66f1, 0x60c3, 0x0074, 0x080c,
-	0x6f0b, 0x0005, 0x20a1, 0x020b, 0x080c, 0x681d, 0x20a3, 0x2010,
+	0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, 0x8b05,
+	0x53a6, 0x20a9, 0x0004, 0x2099, 0x8b01, 0x53a6, 0x20a9, 0x0008,
+	0x20a3, 0x0000, 0x1f04, 0x5f30, 0x20a9, 0x0008, 0x20a3, 0x0000,
+	0x1f04, 0x5f36, 0x2099, 0x8d94, 0x33a6, 0x20a9, 0x0007, 0x20a3,
+	0x0000, 0x1f04, 0x5f3f, 0x0468, 0x2001, 0x8b32, 0x2004, 0xd0a4,
+	0x0140, 0x2001, 0x8d8d, 0x2004, 0x60e3, 0x0000, 0x080c, 0x233e,
+	0x60e2, 0x2099, 0x8d8c, 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0004,
+	0x2099, 0x8b05, 0x53a6, 0x20a9, 0x0004, 0x2099, 0x8b01, 0x53a6,
+	0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x5f62, 0x20a9, 0x0008,
+	0x20a3, 0x0000, 0x1f04, 0x5f68, 0x2099, 0x8d94, 0x20a9, 0x0008,
+	0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x5f73, 0x20a9,
+	0x000a, 0x20a3, 0x0000, 0x1f04, 0x5f79, 0x60c3, 0x0074, 0x080c,
+	0x66e4, 0x0005, 0x20a1, 0x020b, 0x080c, 0x60a5, 0x20a3, 0x2010,
 	0x20a3, 0x0014, 0x20a3, 0x0800, 0x20a3, 0x2000, 0xa006, 0x20a2,
-	0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x00f6, 0x2079, 0x9251, 0x7904,
+	0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x00f6, 0x2079, 0x8b51, 0x7904,
 	0x00fe, 0xd1ac, 0x1110, 0xa085, 0x0020, 0xd1a4, 0x0110, 0xa085,
 	0x0010, 0xa085, 0x0002, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x60c3, 0x0014, 0x080c, 0x6f0b, 0x0005, 0x20a1, 0x020b, 0x080c,
-	0x681d, 0x20a3, 0x5000, 0x0804, 0x665a, 0x20a1, 0x020b, 0x080c,
-	0x681d, 0x20a3, 0x2110, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3,
+	0x60c3, 0x0014, 0x080c, 0x66e4, 0x0005, 0x20a1, 0x020b, 0x080c,
+	0x60a5, 0x20a3, 0x5000, 0x0804, 0x5ee2, 0x20a1, 0x020b, 0x080c,
+	0x60a5, 0x20a3, 0x2110, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3,
 	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
 	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x60c3, 0x0014, 0x080c, 0x6f0b, 0x0005, 0x20a1, 0x020b,
-	0x080c, 0x68a0, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x60c3, 0x0004, 0x080c, 0x6f0b, 0x0005, 0x20a1,
-	0x020b, 0x080c, 0x68a0, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3,
-	0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x080c, 0x6f0b, 0x0005,
-	0x20a1, 0x020b, 0x080c, 0x68a0, 0x20a3, 0x0200, 0x0804, 0x665a,
-	0x20a1, 0x020b, 0x080c, 0x68a0, 0x20a3, 0x0100, 0x20a3, 0x0000,
-	0x20a3, 0x0003, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x6f0b,
-	0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x68a0, 0x20a3, 0x0210,
+	0x0000, 0x60c3, 0x0014, 0x080c, 0x66e4, 0x0005, 0x20a1, 0x020b,
+	0x080c, 0x612f, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a3, 0x0000,
+	0x20a3, 0x0000, 0x60c3, 0x0004, 0x080c, 0x66e4, 0x0005, 0x20a1,
+	0x020b, 0x080c, 0x612f, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3,
+	0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x080c, 0x66e4, 0x0005,
+	0x20a1, 0x020b, 0x080c, 0x612f, 0x20a3, 0x0200, 0x0804, 0x5ee2,
+	0x20a1, 0x020b, 0x080c, 0x612f, 0x20a3, 0x0100, 0x20a3, 0x0000,
+	0x20a3, 0x0003, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x66e4,
+	0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x612f, 0x20a3, 0x0210,
 	0x20a3, 0x0014, 0x20a3, 0x0800, 0x7818, 0x2068, 0x6894, 0xa086,
 	0x0014, 0x1178, 0x6998, 0xa184, 0xc000, 0x1140, 0xd1ec, 0x0118,
 	0x20a3, 0x2100, 0x0040, 0x20a3, 0x0100, 0x0028, 0x20a3, 0x0400,
 	0x0010, 0x20a3, 0x0700, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2,
-	0x20a2, 0x00f6, 0x2079, 0x9251, 0x7904, 0x00fe, 0xd1ac, 0x1110,
-	0xa085, 0x0020, 0xd1a4, 0x0110, 0xa085, 0x0010, 0x2009, 0x9273,
+	0x20a2, 0x00f6, 0x2079, 0x8b51, 0x7904, 0x00fe, 0xd1ac, 0x1110,
+	0xa085, 0x0020, 0xd1a4, 0x0110, 0xa085, 0x0010, 0x2009, 0x8b73,
 	0x210c, 0xd184, 0x1110, 0xa085, 0x0002, 0x20a2, 0x20a2, 0x20a2,
-	0x60c3, 0x0014, 0x080c, 0x6f0b, 0x00de, 0x0005, 0x20a1, 0x020b,
-	0x080c, 0x68a0, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0000,
+	0x60c3, 0x0014, 0x080c, 0x66e4, 0x00de, 0x0005, 0x20a1, 0x020b,
+	0x080c, 0x612f, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0000,
 	0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000,
 	0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x6f0b, 0x0005, 0x20a1,
-	0x020b, 0x080c, 0x68a0, 0x20a3, 0x0200, 0x0804, 0x65fb, 0x20a1,
-	0x020b, 0x080c, 0x68a0, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3,
-	0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x080c, 0x6f0b, 0x0005,
-	0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a1, 0x020b, 0x080c, 0x68a0,
+	0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x66e4, 0x0005, 0x20a1,
+	0x020b, 0x080c, 0x612f, 0x20a3, 0x0200, 0x0804, 0x5e83, 0x20a1,
+	0x020b, 0x080c, 0x612f, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3,
+	0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x080c, 0x66e4, 0x0005,
+	0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a1, 0x020b, 0x080c, 0x612f,
 	0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x000b, 0x20a3, 0x0000,
-	0x60c3, 0x0008, 0x080c, 0x6f0b, 0x0005, 0x0026, 0x20e1, 0x9080,
+	0x60c3, 0x0008, 0x080c, 0x66e4, 0x0005, 0x0026, 0x20e1, 0x9080,
 	0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e,
 	0x1198, 0x20a3, 0x22ff, 0x20a3, 0xfffe, 0x20a3, 0x0000, 0x2011,
-	0x9214, 0x2214, 0x2001, 0x94d7, 0x2004, 0xa005, 0x0118, 0x2011,
-	0x921c, 0x2214, 0x22a2, 0x0498, 0xa286, 0x007f, 0x1130, 0x00d6,
-	0x20a3, 0x22ff, 0x20a3, 0xfffd, 0x00c8, 0x2001, 0x9232, 0x2004,
+	0x8b14, 0x2214, 0x2001, 0x8d9c, 0x2004, 0xa005, 0x0118, 0x2011,
+	0x8b1c, 0x2214, 0x22a2, 0x04d0, 0xa286, 0x007f, 0x1130, 0x00d6,
+	0x20a3, 0x22ff, 0x20a3, 0xfffd, 0x00c8, 0x2001, 0x8b32, 0x2004,
 	0xd0ac, 0x1110, 0xd2bc, 0x01c8, 0xa286, 0x0080, 0x00d6, 0x1128,
-	0x20a3, 0x22ff, 0x20a3, 0xfffc, 0x0048, 0xa2e8, 0x936e, 0x2d6c,
-	0x6810, 0xa085, 0x2200, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x921b,
-	0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0050, 0x20a3, 0x2200, 0x6298,
-	0x22a2, 0x20a3, 0x0000, 0x2011, 0x9214, 0x2214, 0x22a2, 0x20a3,
-	0x0129, 0x20a3, 0x0000, 0x080c, 0x6efa, 0x22a2, 0x20a3, 0x0000,
-	0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e,
-	0x0005, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a3, 0x02ff,
-	0x2011, 0xfffc, 0x22a2, 0x00d6, 0x2069, 0x921b, 0x2da6, 0x8d68,
-	0x2da6, 0x00de, 0x20a3, 0x2029, 0x20a3, 0x0000, 0x08e0, 0x20a3,
-	0x0100, 0x20a3, 0x0000, 0x20a3, 0xfc02, 0x20a3, 0x0000, 0x0005,
-	0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
-	0x2004, 0x2011, 0x9232, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e,
-	0x02e0, 0x00d6, 0xa0e8, 0x936e, 0x2d6c, 0x6810, 0xa085, 0x2300,
-	0x20a2, 0x6814, 0x20a2, 0x6810, 0xa005, 0x1140, 0x6814, 0xa005,
-	0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x0028, 0x2069, 0x921b,
-	0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0050, 0x20a3, 0x2300, 0x6298,
-	0x22a2, 0x20a3, 0x0000, 0x2011, 0x9214, 0x2214, 0x22a2, 0x20a3,
-	0x0198, 0x20a3, 0x0000, 0x080c, 0x6efa, 0x22a2, 0x20a3, 0x0000,
-	0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e,
-	0x0005, 0x080c, 0x6efa, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2,
-	0x7810, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005,
-	0x00c6, 0x00f6, 0x6004, 0xa08a, 0x0085, 0x0a0c, 0x13fe, 0xa08a,
-	0x008c, 0x1a0c, 0x13fe, 0x6118, 0x2178, 0x79a0, 0x2011, 0x9232,
-	0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0150, 0x7900, 0xd1f4, 0x0120,
-	0x7914, 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, 0xa1f8,
-	0x2719, 0x2f0d, 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a,
-	0xa082, 0x0085, 0x001b, 0x00fe, 0x00ce, 0x0005, 0x692f, 0x6939,
-	0x6954, 0x692d, 0x692d, 0x692d, 0x692f, 0x080c, 0x13fe, 0x0146,
-	0x20a1, 0x020b, 0x04a1, 0x60c3, 0x0000, 0x080c, 0x6f0b, 0x014e,
-	0x0005, 0x0146, 0x20a1, 0x020b, 0x080c, 0x6999, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x7808, 0x20a2, 0x7810, 0x20a2, 0x20a3, 0x0000,
-	0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c,
-	0x080c, 0x6f0b, 0x014e, 0x0005, 0x0146, 0x20a1, 0x020b, 0x080c,
-	0x69d1, 0x20a3, 0x0003, 0x20a3, 0x0300, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x60c3, 0x0004, 0x080c, 0x6f0b, 0x014e, 0x0005, 0x0026,
+	0x20a3, 0x22ff, 0x20a3, 0xfffc, 0x0048, 0xa2e8, 0x8c34, 0x2d6c,
+	0x6810, 0xa085, 0x2200, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x8b1b,
+	0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa2e8, 0x8c34,
+	0x2d6c, 0x6810, 0xa085, 0x2200, 0x20a2, 0x6814, 0x20a2, 0x00de,
+	0x20a3, 0x0000, 0x2011, 0x8b14, 0x2214, 0x22a2, 0x20a3, 0x0129,
+	0x20a3, 0x0000, 0x080c, 0x66d3, 0x22a2, 0x20a3, 0x0000, 0x2fa2,
+	0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005,
+	0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a3, 0x02ff, 0x2011,
+	0xfffc, 0x22a2, 0x00d6, 0x2069, 0x8b1b, 0x2da6, 0x8d68, 0x2da6,
+	0x00de, 0x20a3, 0x2029, 0x20a3, 0x0000, 0x08e0, 0x20a3, 0x0100,
+	0x20a3, 0x0000, 0x20a3, 0xfc02, 0x20a3, 0x0000, 0x0005, 0x0026,
 	0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004,
-	0x2011, 0x9232, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288,
-	0x00d6, 0xa0e8, 0x936e, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2,
-	0x6814, 0x20a2, 0x2069, 0x921b, 0x2da6, 0x8d68, 0x2da6, 0x00de,
-	0x0050, 0x20a3, 0x8100, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x2011,
-	0x9214, 0x2214, 0x22a2, 0x20a3, 0x0009, 0x20a3, 0x0000, 0x0804,
-	0x6873, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080,
-	0x0028, 0x2004, 0x2011, 0x9232, 0x2214, 0xd2ac, 0x1118, 0xa092,
-	0x007e, 0x0288, 0x00d6, 0xa0e8, 0x936e, 0x2d6c, 0x6810, 0xa085,
-	0x8400, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x921b, 0x2da6, 0x8d68,
-	0x2da6, 0x00de, 0x0050, 0x20a3, 0x8400, 0x6298, 0x22a2, 0x20a3,
-	0x0000, 0x2011, 0x9214, 0x2214, 0x22a2, 0x080c, 0x4dc5, 0x1118,
-	0x20a3, 0x0099, 0x0010, 0x20a3, 0x00d1, 0x20a3, 0x0000, 0x0804,
-	0x68e9, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080,
-	0x0028, 0x2004, 0x2011, 0x9232, 0x2214, 0xd2ac, 0x1118, 0xa092,
-	0x007e, 0x0288, 0x00d6, 0xa0e8, 0x936e, 0x2d6c, 0x6810, 0xa085,
-	0x8500, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x921b, 0x2da6, 0x8d68,
-	0x2da6, 0x00de, 0x0050, 0x20a3, 0x8500, 0x6298, 0x22a2, 0x20a3,
-	0x0000, 0x2011, 0x9214, 0x2214, 0x22a2, 0x20a3, 0x0099, 0x20a3,
-	0x0000, 0x0804, 0x68e9, 0x00c6, 0x00f6, 0x2c78, 0x7804, 0xa08a,
-	0x0040, 0x0a0c, 0x13fe, 0xa08a, 0x0053, 0x1a0c, 0x13fe, 0x7918,
-	0x2160, 0x61a0, 0x2011, 0x9232, 0x2214, 0xd2ac, 0x1110, 0xd1bc,
-	0x0150, 0x6100, 0xd1f4, 0x0120, 0x6114, 0xa18c, 0x00ff, 0x0040,
-	0x2009, 0x0000, 0x0028, 0xa1e0, 0x2719, 0x2c0d, 0xa18c, 0x00ff,
-	0x2061, 0x0100, 0x619a, 0xa082, 0x0040, 0x001b, 0x00fe, 0x00ce,
-	0x0005, 0x6a46, 0x6b3a, 0x6ade, 0x6c75, 0x6a44, 0x6a44, 0x6a44,
-	0x6a44, 0x6a44, 0x6a44, 0x6a44, 0x71f1, 0x7201, 0x7211, 0x7221,
-	0x6a44, 0x6a44, 0x6a44, 0x71e0, 0x080c, 0x13fe, 0x00d6, 0x0156,
-	0x0146, 0x20a1, 0x020b, 0x080c, 0x6a9c, 0x7910, 0x2168, 0x6948,
-	0x7922, 0x21a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x694c, 0xa184,
-	0x000f, 0x1118, 0x2001, 0x0005, 0x0040, 0xd184, 0x0118, 0x2001,
-	0x0004, 0x0018, 0xa084, 0x0006, 0x8004, 0x20a2, 0xd1ac, 0x0118,
-	0x20a3, 0x0002, 0x0048, 0xd1b4, 0x0118, 0x20a3, 0x0001, 0x0020,
-	0x20a3, 0x0000, 0x2230, 0x0010, 0x6a80, 0x6e7c, 0x20a9, 0x0008,
-	0x0136, 0xad88, 0x0017, 0x2198, 0x20a1, 0x021b, 0x53a6, 0x013e,
-	0x20a1, 0x020b, 0x22a2, 0x26a2, 0x60c3, 0x0020, 0x20e1, 0x9080,
-	0x6014, 0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x2001, 0x9501,
-	0x2003, 0x07d0, 0x2001, 0x9500, 0x2003, 0x0009, 0x080c, 0x165a,
-	0x014e, 0x015e, 0x00de, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000,
-	0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202,
-	0x8217, 0x7818, 0xa080, 0x0028, 0x2004, 0x2019, 0x9232, 0x231c,
-	0xd3ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0x936e, 0x2d6c,
-	0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x921b,
-	0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0050, 0x20a3, 0x0600, 0x6198,
-	0x21a2, 0x20a3, 0x0000, 0x2009, 0x9214, 0x210c, 0x21a2, 0x20a3,
-	0x0829, 0x20a3, 0x0000, 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3,
-	0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x0005, 0x00d6, 0x0156,
-	0x0136, 0x0146, 0x20a1, 0x020b, 0x00c1, 0x7810, 0x2068, 0x6860,
-	0x20a2, 0x685c, 0x20a2, 0x6880, 0x20a2, 0x687c, 0x20a2, 0xa006,
-	0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x000c, 0x080c, 0x6f0b,
-	0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x0026, 0x20e1, 0x9080,
-	0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0x9232,
-	0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0x936e,
-	0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, 0x6814, 0x20a2, 0x2069,
-	0x921b, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0050, 0x20a3, 0x0500,
-	0x6298, 0x22a2, 0x20a3, 0x0000, 0x2011, 0x9214, 0x2214, 0x22a2,
-	0x20a3, 0x0889, 0x20a3, 0x0000, 0x080c, 0x6efa, 0x22a2, 0x20a3,
-	0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x002e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x20a1, 0x020b,
-	0x080c, 0x6c38, 0x7810, 0x2068, 0xa016, 0x22a2, 0x22a2, 0x22a2,
-	0x22a2, 0x22a2, 0x7810, 0xa084, 0xf000, 0x1130, 0x7810, 0xa084,
-	0x0700, 0x8007, 0x0043, 0x0010, 0xa006, 0x002b, 0x014e, 0x013e,
-	0x015e, 0x00de, 0x0005, 0x6b65, 0x6bde, 0x6be1, 0x6c04, 0x6c11,
-	0x6c23, 0x6c26, 0x6b63, 0x080c, 0x13fe, 0x0016, 0x0036, 0x694c,
-	0xa18c, 0x0003, 0xa186, 0x0000, 0x1150, 0x6b78, 0x23a2, 0x6868,
-	0x20a2, 0x6864, 0x20a2, 0x003e, 0x001e, 0x0804, 0x6c08, 0xa186,
-	0x0001, 0x1904, 0x6bd9, 0x6b78, 0x23a2, 0x6868, 0x20a2, 0x6864,
-	0x20a2, 0x22a2, 0x6874, 0x20a2, 0x22a2, 0x687c, 0x20a2, 0x2009,
-	0x0018, 0xa384, 0x0300, 0x0904, 0x6bd8, 0xd3c4, 0x0110, 0x687c,
-	0xa108, 0xd3cc, 0x0110, 0x6874, 0xa108, 0x0156, 0x20a9, 0x000d,
-	0xad80, 0x0020, 0x201c, 0x831f, 0x23a2, 0x8000, 0x1f04, 0x6b9a,
-	0x015e, 0x22a2, 0x22a2, 0x22a2, 0xa184, 0x0003, 0x0588, 0x20a1,
-	0x020b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x0006, 0x7818, 0xa080,
-	0x0028, 0x2004, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0x936e, 0x2d6c,
-	0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x921b,
-	0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0050, 0x20a3, 0x0700, 0x6298,
-	0x22a2, 0x20a3, 0x0000, 0x2011, 0x9214, 0x2214, 0x22a2, 0x000e,
-	0x20a3, 0x0898, 0x20a2, 0x080c, 0x6efa, 0x22a2, 0x20a3, 0x0000,
-	0x61c2, 0x003e, 0x001e, 0x080c, 0x6f0b, 0x0005, 0x20a3, 0x0008,
+	0x2011, 0x8b32, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x02e0,
+	0x00d6, 0xa0e8, 0x8c34, 0x2d6c, 0x6810, 0xa085, 0x2300, 0x20a2,
+	0x6814, 0x20a2, 0x6810, 0xa005, 0x1140, 0x6814, 0xa005, 0x1128,
+	0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x0028, 0x2069, 0x8b1b, 0x2da6,
+	0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0x8c34, 0x2d6c,
+	0x6810, 0xa085, 0x2300, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3,
+	0x0000, 0x2011, 0x8b14, 0x2214, 0x22a2, 0x20a3, 0x0198, 0x20a3,
+	0x0000, 0x080c, 0x66d3, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2,
+	0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x080c,
+	0x66d3, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x7810, 0x20a2,
+	0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x00c6, 0x00f6,
+	0x6004, 0xa08a, 0x0085, 0x0a0c, 0x1410, 0xa08a, 0x008c, 0x1a0c,
+	0x1410, 0x6118, 0x2178, 0x79a0, 0x2011, 0x8b32, 0x2214, 0xd2ac,
+	0x1110, 0xd1bc, 0x0150, 0x7900, 0xd1f4, 0x0120, 0x7914, 0xa18c,
+	0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, 0xa1f8, 0x263d, 0x2f0d,
+	0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0xa082, 0x0085,
+	0x001b, 0x00fe, 0x00ce, 0x0005, 0x61c5, 0x61cf, 0x61ea, 0x61c3,
+	0x61c3, 0x61c3, 0x61c5, 0x080c, 0x1410, 0x0146, 0x20a1, 0x020b,
+	0x04a1, 0x60c3, 0x0000, 0x080c, 0x66e4, 0x014e, 0x0005, 0x0146,
+	0x20a1, 0x020b, 0x080c, 0x6236, 0x20a3, 0x0000, 0x20a3, 0x0000,
+	0x7808, 0x20a2, 0x7810, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0xffff,
+	0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c, 0x080c, 0x66e4,
+	0x014e, 0x0005, 0x0146, 0x20a1, 0x020b, 0x080c, 0x6275, 0x20a3,
+	0x0003, 0x20a3, 0x0300, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
+	0x0004, 0x080c, 0x66e4, 0x014e, 0x0005, 0x0026, 0x20e1, 0x9080,
+	0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0x8b32,
+	0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288, 0x00d6, 0xa0e8,
+	0x8c34, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2,
+	0x2069, 0x8b1b, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6,
+	0xa0e8, 0x8c34, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814,
+	0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0x8b14, 0x2214, 0x22a2,
+	0x20a3, 0x0009, 0x20a3, 0x0000, 0x0804, 0x6102, 0x0026, 0x20e1,
+	0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011,
+	0x8b32, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288, 0x00d6,
+	0xa0e8, 0x8c34, 0x2d6c, 0x6810, 0xa085, 0x8400, 0x20a2, 0x6814,
+	0x20a2, 0x2069, 0x8b1b, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088,
+	0x00d6, 0xa0e8, 0x8c34, 0x2d6c, 0x6810, 0xa085, 0x8400, 0x20a2,
+	0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0x8b14, 0x2214,
+	0x22a2, 0x080c, 0x4c42, 0x1118, 0x20a3, 0x0099, 0x0010, 0x20a3,
+	0x00d1, 0x20a3, 0x0000, 0x0804, 0x617f, 0x0026, 0x20e1, 0x9080,
+	0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0x8b32,
+	0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288, 0x00d6, 0xa0e8,
+	0x8c34, 0x2d6c, 0x6810, 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2,
+	0x2069, 0x8b1b, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6,
+	0xa0e8, 0x8c34, 0x2d6c, 0x6810, 0xa085, 0x8500, 0x20a2, 0x6814,
+	0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0x8b14, 0x2214, 0x22a2,
+	0x20a3, 0x0099, 0x20a3, 0x0000, 0x0804, 0x617f, 0x00c6, 0x00f6,
+	0x2c78, 0x7804, 0xa08a, 0x0040, 0x0a0c, 0x1410, 0xa08a, 0x0053,
+	0x1a0c, 0x1410, 0x7918, 0x2160, 0x61a0, 0x2011, 0x8b32, 0x2214,
+	0xd2ac, 0x1110, 0xd1bc, 0x0150, 0x6100, 0xd1f4, 0x0120, 0x6114,
+	0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, 0xa1e0, 0x263d,
+	0x2c0d, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0xa082, 0x0040,
+	0x001b, 0x00fe, 0x00ce, 0x0005, 0x62f1, 0x63f3, 0x6390, 0x653f,
+	0x62ef, 0x62ef, 0x62ef, 0x62ef, 0x62ef, 0x62ef, 0x62ef, 0x69be,
+	0x69ce, 0x69de, 0x69ee, 0x62ef, 0x62ef, 0x62ef, 0x69ad, 0x080c,
+	0x1410, 0x00d6, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x6347,
+	0x7910, 0x2168, 0x6948, 0x7922, 0x21a2, 0xa016, 0x22a2, 0x22a2,
+	0x22a2, 0x694c, 0xa184, 0x000f, 0x1118, 0x2001, 0x0005, 0x0040,
+	0xd184, 0x0118, 0x2001, 0x0004, 0x0018, 0xa084, 0x0006, 0x8004,
+	0x20a2, 0xd1ac, 0x0118, 0x20a3, 0x0002, 0x0048, 0xd1b4, 0x0118,
+	0x20a3, 0x0001, 0x0020, 0x20a3, 0x0000, 0x2230, 0x0010, 0x6a80,
+	0x6e7c, 0x20a9, 0x0008, 0x0136, 0xad88, 0x0017, 0x2198, 0x20a1,
+	0x021b, 0x53a6, 0x013e, 0x20a1, 0x020b, 0x22a2, 0x26a2, 0x60c3,
+	0x0020, 0x20e1, 0x9080, 0x6014, 0xa084, 0x0004, 0xa085, 0x0009,
+	0x6016, 0x2001, 0x8dc6, 0x2003, 0x07d0, 0x2001, 0x8dc5, 0x2003,
+	0x0009, 0x080c, 0x166c, 0x014e, 0x015e, 0x00de, 0x0005, 0x20e1,
+	0x9080, 0x20e1, 0x4000, 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210,
+	0xa294, 0x00ff, 0x2202, 0x8217, 0x7818, 0xa080, 0x0028, 0x2004,
+	0x2019, 0x8b32, 0x231c, 0xd3ac, 0x1110, 0xd0bc, 0x0188, 0x00d6,
+	0xa0e8, 0x8c34, 0x2d6c, 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814,
+	0x20a2, 0x2069, 0x8b1b, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088,
+	0x00d6, 0xa0e8, 0x8c34, 0x2d6c, 0x6810, 0xa085, 0x0600, 0x20a2,
+	0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2009, 0x8b14, 0x210c,
+	0x21a2, 0x20a3, 0x0829, 0x20a3, 0x0000, 0x22a2, 0x20a3, 0x0000,
+	0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x0005,
+	0x00d6, 0x0156, 0x0136, 0x0146, 0x20a1, 0x020b, 0x00c1, 0x7810,
+	0x2068, 0x6860, 0x20a2, 0x685c, 0x20a2, 0x6880, 0x20a2, 0x687c,
+	0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x000c,
+	0x080c, 0x66e4, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x0026,
+	0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004,
+	0x2011, 0x8b32, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6,
+	0xa0e8, 0x8c34, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, 0x6814,
+	0x20a2, 0x2069, 0x8b1b, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088,
+	0x00d6, 0xa0e8, 0x8c34, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2,
+	0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0x8b14, 0x2214,
+	0x22a2, 0x20a3, 0x0889, 0x20a3, 0x0000, 0x080c, 0x66d3, 0x22a2,
+	0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3,
+	0x0000, 0x002e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x20a1,
+	0x020b, 0x080c, 0x64fb, 0x7810, 0x2068, 0xa016, 0x22a2, 0x22a2,
+	0x22a2, 0x22a2, 0x22a2, 0x7810, 0xa084, 0xf000, 0x1130, 0x7810,
+	0xa084, 0x0700, 0x8007, 0x0043, 0x0010, 0xa006, 0x002b, 0x014e,
+	0x013e, 0x015e, 0x00de, 0x0005, 0x641e, 0x649e, 0x64a1, 0x64c4,
+	0x64d1, 0x64e6, 0x64e9, 0x641c, 0x080c, 0x1410, 0x0016, 0x0036,
+	0x694c, 0xa18c, 0x0003, 0xa186, 0x0000, 0x1150, 0x6b78, 0x23a2,
+	0x6868, 0x20a2, 0x6864, 0x20a2, 0x003e, 0x001e, 0x0804, 0x64c8,
+	0xa186, 0x0001, 0x1904, 0x6499, 0x6b78, 0x23a2, 0x6868, 0x20a2,
+	0x6864, 0x20a2, 0x22a2, 0x6874, 0x20a2, 0x22a2, 0x687c, 0x20a2,
+	0x2009, 0x0018, 0xa384, 0x0300, 0x0904, 0x6498, 0xd3c4, 0x0110,
+	0x687c, 0xa108, 0xd3cc, 0x0110, 0x6874, 0xa108, 0x0156, 0x20a9,
+	0x000d, 0xad80, 0x0020, 0x201c, 0x831f, 0x23a2, 0x8000, 0x1f04,
+	0x6453, 0x015e, 0x22a2, 0x22a2, 0x22a2, 0xa184, 0x0003, 0x05c0,
+	0x20a1, 0x020b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x0006, 0x7818,
+	0xa080, 0x0028, 0x2004, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0x8c34,
+	0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x2069,
+	0x8b1b, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8,
+	0x8c34, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2,
+	0x00de, 0x20a3, 0x0000, 0x2011, 0x8b14, 0x2214, 0x22a2, 0x000e,
+	0x20a3, 0x0898, 0x20a2, 0x080c, 0x66d3, 0x22a2, 0x20a3, 0x0000,
+	0x61c2, 0x003e, 0x001e, 0x080c, 0x66e4, 0x0005, 0x20a3, 0x0008,
 	0x0428, 0x20a3, 0x0302, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0012,
 	0x22a2, 0x20a3, 0x0008, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3,
 	0x7000, 0x20a3, 0x0500, 0x22a2, 0x20a3, 0x000a, 0x22a2, 0x22a2,
 	0x20a3, 0x2500, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3,
-	0x0032, 0x080c, 0x6f0b, 0x0005, 0x20a3, 0x0028, 0x22a2, 0x22a2,
-	0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0018, 0x080c, 0x6f0b,
+	0x0032, 0x080c, 0x66e4, 0x0005, 0x20a3, 0x0028, 0x22a2, 0x22a2,
+	0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0018, 0x080c, 0x66e4,
 	0x0005, 0x20a3, 0x0100, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2,
-	0x20a3, 0x0008, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0020,
-	0x080c, 0x6f0b, 0x0005, 0x20a3, 0x0008, 0x0c00, 0x0036, 0x7b10,
-	0xa384, 0xff00, 0x7812, 0xa384, 0x00ff, 0x8001, 0x1118, 0x22a2,
-	0x003e, 0x08a0, 0x20a3, 0x0800, 0x22a2, 0x20a2, 0x003e, 0x0880,
-	0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
-	0x2004, 0x2011, 0x9232, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188,
-	0x00d6, 0xa0e8, 0x936e, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2,
-	0x6814, 0x20a2, 0x2069, 0x921b, 0x2da6, 0x8d68, 0x2da6, 0x00de,
-	0x0050, 0x20a3, 0x0700, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x2011,
-	0x9214, 0x2214, 0x22a2, 0x20a3, 0x0898, 0x20a3, 0x0000, 0x080c,
-	0x6efa, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x00d6, 0x0156, 0x0136,
-	0x0146, 0x0016, 0x0036, 0x7810, 0xa084, 0x0700, 0x8007, 0x003b,
-	0x003e, 0x001e, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x6c8f,
-	0x6c8f, 0x6c91, 0x6c8f, 0x6c8f, 0x6c8f, 0x6cb3, 0x6c8f, 0x080c,
-	0x13fe, 0x7910, 0xa18c, 0xf8ff, 0xa18d, 0x0600, 0x7912, 0x20a1,
-	0x020b, 0x2009, 0x0003, 0x00f9, 0x00d6, 0x2069, 0x9251, 0x6804,
-	0xd0bc, 0x0130, 0x682c, 0xa084, 0x00ff, 0x8007, 0x20a2, 0x0010,
-	0x20a3, 0x3f00, 0x00de, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0001,
-	0x080c, 0x6f0b, 0x0005, 0x20a1, 0x020b, 0x2009, 0x0003, 0x0019,
-	0x20a3, 0x7f00, 0x0c80, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000,
-	0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0x9232, 0x2214, 0xd2ac,
-	0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0x936e, 0x2d6c, 0x6810,
-	0xa085, 0x0100, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x921b, 0x2da6,
-	0x8d68, 0x2da6, 0x00de, 0x0050, 0x20a3, 0x0100, 0x6298, 0x22a2,
-	0x20a3, 0x0000, 0x2011, 0x9214, 0x2214, 0x22a2, 0x20a3, 0x0888,
-	0xa18d, 0x0008, 0x21a2, 0x080c, 0x6efa, 0x22a2, 0x20a3, 0x0000,
-	0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e,
-	0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0036,
-	0x2061, 0x0100, 0x2071, 0x9200, 0x2009, 0x9214, 0x210c, 0x7818,
-	0x2068, 0x2031, 0x9232, 0x2634, 0xa6b4, 0x0028, 0x0110, 0x736c,
-	0x7470, 0x2500, 0x2031, 0x9232, 0x2634, 0xa6b4, 0x0028, 0x0140,
-	0x2001, 0x04ff, 0x6062, 0x6067, 0xffff, 0x636a, 0x646e, 0x0050,
-	0x2001, 0x00ff, 0xa085, 0x0400, 0x6062, 0x6067, 0xffff, 0x606b,
-	0x0000, 0x616e, 0x68b8, 0x6072, 0x6077, 0x0008, 0x688c, 0x8000,
-	0xa084, 0x00ff, 0x688e, 0x8007, 0xa085, 0x0020, 0x607a, 0x68b4,
-	0x607f, 0x0000, 0x2d00, 0x6082, 0x6087, 0xffff, 0x7810, 0x2070,
-	0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008, 0x60ca,
-	0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000,
-	0x2001, 0x9232, 0x2004, 0xd09c, 0x0128, 0x609f, 0x0000, 0x2001,
-	0x0012, 0x0048, 0x6028, 0xc0bd, 0x602a, 0x609f, 0x00ff, 0x6027,
-	0xffff, 0x2001, 0x0032, 0x6016, 0x2009, 0x07d0, 0x080c, 0x57a6,
-	0x2001, 0x9295, 0x200c, 0xc185, 0x2102, 0x003e, 0x004e, 0x005e,
-	0x006e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x00e6, 0x00d6, 0x00c6,
-	0x0066, 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0x9200,
-	0x2009, 0x9214, 0x210c, 0x7818, 0x2068, 0x68a0, 0x2028, 0x2031,
-	0x9232, 0x2634, 0xd6ac, 0x1140, 0xd0bc, 0x1130, 0xa080, 0x2719,
-	0x2015, 0xa294, 0x00ff, 0x0020, 0x6910, 0x6a14, 0x736c, 0x7470,
-	0x2001, 0x9232, 0x2004, 0xd0ac, 0x1110, 0xd5bc, 0x0138, 0xa185,
-	0x0400, 0x6062, 0x6266, 0x636a, 0x646e, 0x0030, 0x6063, 0x0400,
-	0x6266, 0x606b, 0x0000, 0x616e, 0x68b8, 0x6072, 0x6077, 0x0008,
-	0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, 0xa085, 0x0020,
-	0x607a, 0x68b4, 0x607f, 0x0000, 0x2d00, 0x6082, 0x6087, 0xffff,
-	0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6,
-	0x7008, 0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5,
-	0x60d7, 0x0000, 0xa582, 0x0080, 0x0210, 0x2011, 0x0000, 0x629e,
-	0x00f6, 0x2079, 0x0140, 0x7803, 0x0000, 0x00fe, 0x6017, 0x0012,
-	0x2009, 0x07d0, 0x080c, 0x57a6, 0x003e, 0x004e, 0x005e, 0x006e,
-	0x00ce, 0x00de, 0x00ee, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0056,
-	0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0x9200, 0x7150, 0x7818,
-	0x2068, 0x68a0, 0x2028, 0x76c8, 0xd6ac, 0x1140, 0xd0bc, 0x1130,
-	0xa080, 0x2719, 0x2015, 0xa294, 0x00ff, 0x0020, 0x6910, 0x6a14,
-	0x736c, 0x7470, 0x781c, 0xa086, 0x0006, 0x0904, 0x6e65, 0x70c8,
-	0xd0ac, 0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266,
-	0x636a, 0x646e, 0x0030, 0x6063, 0x0100, 0x6266, 0x606b, 0x0000,
-	0x616e, 0x6073, 0x0809, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084,
-	0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082,
-	0x7808, 0x6086, 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e,
-	0x700c, 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036,
-	0x60af, 0x95d5, 0x60d7, 0x0000, 0xa582, 0x0080, 0x0248, 0x6a00,
-	0xd2f4, 0x0120, 0x6a14, 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000,
-	0x629e, 0x6017, 0x0016, 0x2009, 0x07d0, 0x60c4, 0xa084, 0xfff0,
-	0xa005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x57a6, 0x003e, 0x004e,
-	0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7810, 0x2070, 0x704c,
-	0xa084, 0x0003, 0xa086, 0x0002, 0x0904, 0x6eb4, 0x2001, 0x9232,
-	0x2004, 0xd0ac, 0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062,
-	0x6266, 0x636a, 0x646e, 0x0030, 0x6063, 0x0100, 0x6266, 0x606b,
-	0x0000, 0x616e, 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, 0x8000,
-	0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00,
-	0x6086, 0x7808, 0x6082, 0x7060, 0x608a, 0x705c, 0x608e, 0x7080,
-	0x60c6, 0x707c, 0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af,
-	0x95d5, 0x60d7, 0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4,
-	0x0120, 0x6a14, 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e,
-	0x6017, 0x0012, 0x0804, 0x6e53, 0x2001, 0x9232, 0x2004, 0xd0ac,
-	0x1110, 0xd5bc, 0x0138, 0xa185, 0x0700, 0x6062, 0x6266, 0x636a,
-	0x646e, 0x0030, 0x6063, 0x0700, 0x6266, 0x606b, 0x0000, 0x616e,
-	0x6073, 0x0898, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff,
-	0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808,
-	0x6082, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008,
-	0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7,
-	0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14,
-	0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x6017, 0x0016,
-	0x0804, 0x6e53, 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294,
-	0x00ff, 0x2202, 0x8217, 0x0005, 0x00d6, 0x2069, 0x94e5, 0x6843,
-	0x0001, 0x00de, 0x0005, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7,
-	0x9575, 0x0019, 0x080c, 0x5798, 0x0005, 0x0006, 0x6014, 0xa084,
-	0x0004, 0xa085, 0x0009, 0x6016, 0x000e, 0x0005, 0x0006, 0x00c6,
-	0x2061, 0x0100, 0x6014, 0xa084, 0x0004, 0xa085, 0x0008, 0x6016,
-	0x00ce, 0x000e, 0x0005, 0x00c6, 0x00d6, 0x0016, 0x0026, 0x080c,
-	0x57a1, 0x2061, 0x0100, 0x2069, 0x0140, 0x6904, 0xa194, 0x4000,
-	0x0538, 0x0c21, 0x6803, 0x1000, 0x6803, 0x0000, 0x00c6, 0x2061,
-	0x94e5, 0x6128, 0xa192, 0x0002, 0x1250, 0x8108, 0x612a, 0x6124,
-	0x00ce, 0x81ff, 0x0180, 0x080c, 0x5798, 0x0839, 0x0060, 0x6124,
-	0xa1e5, 0x0000, 0x0130, 0x080c, 0x91a0, 0x2009, 0x0014, 0x080c,
-	0x7518, 0x00ce, 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce, 0x0005,
-	0x080c, 0x4dc5, 0x1118, 0x080c, 0x6f1e, 0x08c0, 0x080c, 0x4105,
-	0x0c90, 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x0026, 0x080c, 0x57ae,
-	0x2071, 0x94e5, 0x713c, 0x81ff, 0x0578, 0x2061, 0x0100, 0x2069,
-	0x0140, 0x6904, 0xa194, 0x4000, 0x0568, 0x6803, 0x1000, 0x6803,
-	0x0000, 0x0036, 0x2019, 0x0001, 0x080c, 0x7110, 0x003e, 0x713c,
-	0x2160, 0x080c, 0x91a0, 0x2009, 0x004a, 0x621c, 0xa296, 0x0009,
-	0x1110, 0x2009, 0x0104, 0x080c, 0x7518, 0x080c, 0x4dc5, 0x1160,
-	0x0006, 0x2001, 0x94d8, 0x2003, 0x0002, 0x2001, 0x9200, 0x2003,
-	0x0001, 0x080c, 0x4d10, 0x000e, 0x002e, 0x001e, 0x00ee, 0x00de,
-	0x00ce, 0x0005, 0x08b0, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056,
-	0x0046, 0x0006, 0x0126, 0x2091, 0x8000, 0x6018, 0x2068, 0x6ca0,
-	0x2071, 0x94e5, 0x7018, 0x2068, 0x8dff, 0x0198, 0x68a0, 0xa406,
-	0x0118, 0x6854, 0x2068, 0x0cc0, 0x6010, 0x2060, 0x643c, 0x6540,
-	0x6e48, 0x2d60, 0x080c, 0x457f, 0x0120, 0x080c, 0x7238, 0xa085,
-	0x0001, 0x012e, 0x000e, 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de,
-	0x00ee, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x681d,
-	0x20a3, 0x0f00, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2,
-	0x60c3, 0x0008, 0x080c, 0x6f0b, 0x014e, 0x015e, 0x0005, 0x0156,
-	0x0146, 0x20a1, 0x020b, 0x080c, 0x68a0, 0x20a3, 0x0200, 0x20a3,
-	0x0000, 0x20a9, 0x0006, 0x2011, 0x9240, 0x2019, 0x9241, 0x23a6,
-	0x22a6, 0xa398, 0x0002, 0xa290, 0x0002, 0x1f04, 0x6fff, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x080c, 0x6f0b, 0x014e,
-	0x015e, 0x0005, 0x0156, 0x0146, 0x0016, 0x0026, 0x20a1, 0x020b,
-	0x080c, 0x6881, 0x080c, 0x6897, 0x7810, 0x0006, 0xa080, 0x0015,
-	0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6, 0xa080, 0x0004,
+	0x20a3, 0x0008, 0x22a2, 0x7824, 0xa084, 0x00ff, 0x20a2, 0x22a2,
+	0x22a2, 0x60c3, 0x0020, 0x080c, 0x66e4, 0x0005, 0x20a3, 0x0008,
+	0x08e8, 0x0036, 0x7b10, 0xa384, 0xff00, 0x7812, 0xa384, 0x00ff,
+	0x8001, 0x1118, 0x22a2, 0x003e, 0x0888, 0x20a3, 0x0800, 0x22a2,
+	0x20a2, 0x003e, 0x0868, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000,
+	0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0x8b32, 0x2214, 0xd2ac,
+	0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0x8c34, 0x2d6c, 0x6810,
+	0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x8b1b, 0x2da6,
+	0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0x8c34, 0x2d6c,
+	0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3,
+	0x0000, 0x2011, 0x8b14, 0x2214, 0x22a2, 0x20a3, 0x0898, 0x20a3,
+	0x0000, 0x080c, 0x66d3, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2,
+	0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x00d6,
+	0x0156, 0x0136, 0x0146, 0x0016, 0x0036, 0x7810, 0xa084, 0x0700,
+	0x8007, 0x003b, 0x003e, 0x001e, 0x014e, 0x013e, 0x015e, 0x00de,
+	0x0005, 0x6559, 0x6559, 0x655b, 0x6559, 0x6559, 0x6559, 0x657d,
+	0x6559, 0x080c, 0x1410, 0x7910, 0xa18c, 0xf8ff, 0xa18d, 0x0600,
+	0x7912, 0x20a1, 0x020b, 0x2009, 0x0003, 0x00f9, 0x00d6, 0x2069,
+	0x8b51, 0x6804, 0xd0bc, 0x0130, 0x682c, 0xa084, 0x00ff, 0x8007,
+	0x20a2, 0x0010, 0x20a3, 0x3f00, 0x00de, 0x22a2, 0x22a2, 0x22a2,
+	0x60c3, 0x0001, 0x080c, 0x66e4, 0x0005, 0x20a1, 0x020b, 0x2009,
+	0x0003, 0x0019, 0x20a3, 0x7f00, 0x0c80, 0x0026, 0x20e1, 0x9080,
+	0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0x8b32,
+	0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0x8c34,
+	0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2, 0x6814, 0x20a2, 0x2069,
+	0x8b1b, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8,
+	0x8c34, 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2, 0x6814, 0x20a2,
+	0x00de, 0x20a3, 0x0000, 0x2011, 0x8b14, 0x2214, 0x22a2, 0x20a3,
+	0x0888, 0xa18d, 0x0008, 0x21a2, 0x080c, 0x66d3, 0x22a2, 0x20a3,
+	0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000,
+	0x002e, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0056, 0x0046, 0x0036,
+	0x2061, 0x0100, 0x2071, 0x8b00, 0x7150, 0x7818, 0x2068, 0x68a0,
+	0x2028, 0x76c8, 0xd6ac, 0x1130, 0xd0bc, 0x1120, 0x6910, 0x6a14,
+	0x7450, 0x0020, 0x6910, 0x6a14, 0x736c, 0x7470, 0x781c, 0xa086,
+	0x0006, 0x0904, 0x6640, 0x70c8, 0xd0ac, 0x1110, 0xd5bc, 0x0138,
+	0xa185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, 0x0038, 0xa185,
+	0x0100, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x6073, 0x0809,
+	0x6077, 0x0008, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007,
+	0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, 0x6086, 0x7810,
+	0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008,
+	0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xa582,
+	0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0xa294, 0x00ff,
+	0x0010, 0x2011, 0x0000, 0x629e, 0x080c, 0x6cb4, 0x2009, 0x07d0,
+	0x60c4, 0xa084, 0xfff0, 0xa005, 0x0110, 0x2009, 0x1b58, 0x080c,
+	0x567f, 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005,
+	0x7810, 0x2070, 0x704c, 0xa084, 0x0003, 0xa086, 0x0002, 0x0904,
+	0x668e, 0x2001, 0x8b32, 0x2004, 0xd0ac, 0x1110, 0xd5bc, 0x0138,
+	0xa185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, 0x0038, 0xa185,
+	0x0100, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x6073, 0x0880,
+	0x6077, 0x0008, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007,
+	0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808, 0x6082, 0x7060,
+	0x608a, 0x705c, 0x608e, 0x7080, 0x60c6, 0x707c, 0x60ca, 0x686c,
+	0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xa582, 0x0080, 0x0248,
+	0x6a00, 0xd2f4, 0x0120, 0x6a14, 0xa294, 0x00ff, 0x0010, 0x2011,
+	0x0000, 0x629e, 0x080c, 0x6cb1, 0x0804, 0x662e, 0x2001, 0x8b32,
+	0x2004, 0xd0ac, 0x1110, 0xd5bc, 0x0138, 0xa185, 0x0700, 0x6062,
+	0x6266, 0x636a, 0x646e, 0x0038, 0xa185, 0x0700, 0x6062, 0x6266,
+	0x606b, 0x0000, 0x646e, 0x6073, 0x0898, 0x6077, 0x0000, 0x688c,
+	0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000,
+	0x2f00, 0x6086, 0x7808, 0x6082, 0x7014, 0x608a, 0x7010, 0x608e,
+	0x700c, 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5,
+	0x60d7, 0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120,
+	0x6a14, 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x080c,
+	0x6cb4, 0x0804, 0x662e, 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210,
+	0xa294, 0x00ff, 0x2202, 0x8217, 0x0005, 0x00d6, 0x2069, 0x8daa,
+	0x6843, 0x0001, 0x00de, 0x0005, 0x20e1, 0x9080, 0x60a3, 0x0056,
+	0x60a7, 0x9575, 0x0019, 0x080c, 0x5671, 0x0005, 0x0006, 0x6014,
+	0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x000e, 0x0005, 0x0006,
+	0x00c6, 0x2061, 0x0100, 0x6014, 0xa084, 0x0004, 0xa085, 0x0008,
+	0x6016, 0x00ce, 0x000e, 0x0005, 0x00c6, 0x00d6, 0x0016, 0x0026,
+	0x080c, 0x567a, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, 0x4c42,
+	0x1128, 0x0c29, 0x080c, 0x4cbf, 0x0150, 0x0438, 0x6904, 0xa194,
+	0x4000, 0x0540, 0x08e1, 0x6803, 0x1000, 0x6803, 0x0000, 0x00c6,
+	0x2061, 0x8daa, 0x6128, 0xa192, 0x0002, 0x1258, 0x8108, 0x612a,
+	0x6124, 0x00ce, 0x81ff, 0x0188, 0x080c, 0x5671, 0x080c, 0x66ee,
+	0x0060, 0x6124, 0xa1e5, 0x0000, 0x0130, 0x080c, 0x8a4b, 0x2009,
+	0x0014, 0x080c, 0x6d3f, 0x00ce, 0x0000, 0x002e, 0x001e, 0x00de,
+	0x00ce, 0x0005, 0x080c, 0x403d, 0x0cc0, 0x00c6, 0x00d6, 0x00e6,
+	0x0016, 0x0026, 0x080c, 0x5687, 0x2071, 0x8daa, 0x713c, 0x81ff,
+	0x0530, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, 0x4c42, 0x1148,
+	0x0036, 0x2019, 0x0001, 0x080c, 0x68e5, 0x003e, 0x080c, 0x4cbf,
+	0x00b0, 0x6904, 0xa194, 0x4000, 0x01c0, 0x6803, 0x1000, 0x6803,
+	0x0000, 0x0036, 0x2019, 0x0001, 0x080c, 0x68e5, 0x003e, 0x713c,
+	0x2160, 0x080c, 0x8a4b, 0x2009, 0x004a, 0x080c, 0x6d3f, 0x002e,
+	0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0c58, 0x00e6, 0x00d6,
+	0x00c6, 0x0066, 0x0056, 0x0046, 0x0006, 0x0126, 0x2091, 0x8000,
+	0x6018, 0x2068, 0x6ca0, 0x2071, 0x8daa, 0x7018, 0x2068, 0x8dff,
+	0x0198, 0x68a0, 0xa406, 0x0118, 0x6854, 0x2068, 0x0cc0, 0x6010,
+	0x2060, 0x643c, 0x6540, 0x6e48, 0x2d60, 0x080c, 0x4458, 0x0120,
+	0x080c, 0x6a05, 0xa085, 0x0001, 0x012e, 0x000e, 0x004e, 0x005e,
+	0x006e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x0156, 0x0146, 0x20a1,
+	0x020b, 0x080c, 0x60a5, 0x20a3, 0x0f00, 0x20a3, 0x0000, 0x20a3,
+	0x0000, 0x7808, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x66e4, 0x014e,
+	0x015e, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x612f,
+	0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a9, 0x0006, 0x2011, 0x8b40,
+	0x2019, 0x8b41, 0x23a6, 0x22a6, 0xa398, 0x0002, 0xa290, 0x0002,
+	0x1f04, 0x67d2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c,
+	0x080c, 0x66e4, 0x014e, 0x015e, 0x0005, 0x0156, 0x0146, 0x0016,
+	0x0026, 0x20a1, 0x020b, 0x080c, 0x6110, 0x080c, 0x6126, 0x7810,
+	0x0006, 0xa080, 0x0015, 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8,
+	0x53a6, 0xa080, 0x0004, 0x8003, 0x60c2, 0x000e, 0xa080, 0x0001,
+	0x2004, 0x7812, 0x080c, 0x66e4, 0x002e, 0x001e, 0x014e, 0x015e,
+	0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x60a5, 0x20a3,
+	0x6200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, 0x60c3,
+	0x0008, 0x080c, 0x66e4, 0x014e, 0x015e, 0x0005, 0x0156, 0x0146,
+	0x0016, 0x0026, 0x20a1, 0x020b, 0x080c, 0x60a5, 0x7810, 0x0006,
+	0xa080, 0x0017, 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6,
 	0x8003, 0x60c2, 0x000e, 0xa080, 0x0001, 0x2004, 0x7812, 0x080c,
-	0x6f0b, 0x002e, 0x001e, 0x014e, 0x015e, 0x0005, 0x0156, 0x0146,
-	0x20a1, 0x020b, 0x080c, 0x681d, 0x20a3, 0x6200, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x7808, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x6f0b,
-	0x014e, 0x015e, 0x0005, 0x0156, 0x0146, 0x0016, 0x0026, 0x20a1,
-	0x020b, 0x080c, 0x681d, 0x7810, 0x0006, 0xa080, 0x0017, 0x2098,
-	0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6, 0x8003, 0x60c2, 0x000e,
-	0xa080, 0x0001, 0x2004, 0x7812, 0x080c, 0x6f0b, 0x002e, 0x001e,
-	0x014e, 0x015e, 0x0005, 0x00e6, 0x00c6, 0x0006, 0x0126, 0x2091,
-	0x8000, 0x2071, 0x94e5, 0x700c, 0x2060, 0x8cff, 0x0168, 0x080c,
-	0x84c8, 0x1110, 0x080c, 0x7776, 0x600c, 0x0006, 0x080c, 0x74f2,
-	0x080c, 0x7238, 0x00ce, 0x0c88, 0x700f, 0x0000, 0x700b, 0x0000,
-	0x012e, 0x000e, 0x00ce, 0x00ee, 0x0005, 0x0126, 0x0156, 0x00f6,
-	0x00e6, 0x00d6, 0x00c6, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000,
-	0x2069, 0x0100, 0x2079, 0x0140, 0x2071, 0x94e5, 0x7024, 0x2060,
-	0x8cff, 0x05a0, 0x080c, 0x6f1e, 0x68c3, 0x0000, 0x080c, 0x57a1,
-	0x2009, 0x0013, 0x080c, 0x7518, 0x20a9, 0x01f4, 0x6824, 0xd094,
+	0x66e4, 0x002e, 0x001e, 0x014e, 0x015e, 0x0005, 0x00e6, 0x00c6,
+	0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x8daa, 0x700c, 0x2060,
+	0x8cff, 0x0178, 0x080c, 0x7d69, 0x1110, 0x080c, 0x6fb6, 0x600c,
+	0x0006, 0x080c, 0x7df6, 0x080c, 0x6d18, 0x080c, 0x6a05, 0x00ce,
+	0x0c78, 0x700f, 0x0000, 0x700b, 0x0000, 0x012e, 0x000e, 0x00ce,
+	0x00ee, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6,
+	0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079,
+	0x0140, 0x2071, 0x8daa, 0x7024, 0x2060, 0x8cff, 0x05a0, 0x080c,
+	0x66f7, 0x68c3, 0x0000, 0x080c, 0x567a, 0x2009, 0x0013, 0x080c,
+	0x6d3f, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0158, 0x6827, 0x0004,
+	0x7804, 0xa084, 0x4000, 0x01a0, 0x7803, 0x1000, 0x7803, 0x0000,
+	0x0078, 0xd084, 0x0118, 0x6827, 0x0001, 0x0010, 0x1f04, 0x6883,
+	0x7804, 0xa084, 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000,
+	0x6824, 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe,
+	0x015e, 0x012e, 0x0005, 0x2001, 0x8b00, 0x2004, 0xa096, 0x0001,
+	0x0550, 0xa096, 0x0004, 0x0538, 0x6817, 0x0008, 0x68c3, 0x0000,
+	0x2011, 0x3fe7, 0x080c, 0x560d, 0x20a9, 0x01f4, 0x6824, 0xd094,
 	0x0158, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, 0x7803,
 	0x1000, 0x7803, 0x0000, 0x0078, 0xd084, 0x0118, 0x6827, 0x0001,
-	0x0010, 0x1f04, 0x70ae, 0x7804, 0xa084, 0x1000, 0x0120, 0x7803,
-	0x0100, 0x7803, 0x0000, 0x6824, 0x000e, 0x001e, 0x002e, 0x00ce,
-	0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x2001, 0x9200,
-	0x2004, 0xa096, 0x0001, 0x0550, 0xa096, 0x0004, 0x0538, 0x6817,
-	0x0008, 0x68c3, 0x0000, 0x2011, 0x40af, 0x080c, 0x5731, 0x20a9,
-	0x01f4, 0x6824, 0xd094, 0x0158, 0x6827, 0x0004, 0x7804, 0xa084,
-	0x4000, 0x01a0, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0xd084,
-	0x0118, 0x6827, 0x0001, 0x0010, 0x1f04, 0x70e9, 0x7804, 0xa084,
-	0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, 0x000e, 0x001e,
-	0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005,
-	0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0026, 0x0016,
-	0x0006, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071,
-	0x94e5, 0x703c, 0x2060, 0x8cff, 0x0904, 0x7185, 0x6817, 0x0010,
-	0x68c7, 0x0000, 0x68cb, 0x0000, 0x080c, 0x57ae, 0x080c, 0x1ef8,
-	0x0046, 0x0056, 0x2009, 0x017f, 0x212c, 0x200b, 0x00a5, 0x2021,
-	0x0169, 0x2404, 0xa084, 0x000f, 0xa086, 0x0004, 0x11b0, 0x68c7,
-	0x0000, 0x68cb, 0x0008, 0x00e6, 0x00f6, 0x2079, 0x0020, 0x2071,
-	0x953b, 0x6814, 0xa084, 0x0004, 0xa085, 0x0012, 0x6816, 0x7803,
-	0x0008, 0x7003, 0x0000, 0x00fe, 0x00ee, 0x250a, 0x005e, 0x004e,
-	0xa39d, 0x0000, 0x1150, 0x2009, 0x0049, 0x601c, 0xa086, 0x0009,
-	0x1110, 0x2009, 0x0103, 0x080c, 0x7518, 0x20a9, 0x03e8, 0x6824,
-	0xd094, 0x0158, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0,
-	0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0xd094, 0x0118, 0x6827,
-	0x0002, 0x0010, 0x1f04, 0x7167, 0x7804, 0xa084, 0x1000, 0x0120,
-	0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x000e, 0x001e, 0x002e,
-	0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6,
-	0x0126, 0x2091, 0x8000, 0x2069, 0x94e5, 0x6a06, 0x012e, 0x00de,
-	0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, 0x94e5, 0x6a32,
-	0x012e, 0x00de, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0006,
-	0x0126, 0x2071, 0x94e5, 0x7614, 0x2660, 0x2678, 0x2091, 0x8000,
-	0x8cff, 0x0538, 0x601c, 0xa206, 0x1500, 0x7014, 0xac36, 0x1110,
-	0x660c, 0x7616, 0x7010, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118,
-	0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00,
-	0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c,
-	0x849b, 0x080c, 0x7238, 0x00ce, 0x08d8, 0x2c78, 0x600c, 0x2060,
-	0x08b8, 0x012e, 0x000e, 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005,
-	0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x6a9c, 0x7810, 0x20a2,
-	0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x1000, 0x0804,
-	0x7230, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x6a9c, 0x7810,
-	0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x4000,
-	0x0478, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x6a9c, 0x7810,
-	0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x2000,
-	0x00f8, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x6a9c, 0x7810,
-	0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400,
-	0x0078, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x6a9c, 0x7810,
-	0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200,
-	0x0089, 0x60c3, 0x0020, 0x080c, 0x6f0b, 0x014e, 0x015e, 0x0005,
-	0x00e6, 0x2071, 0x94e5, 0x7020, 0xa005, 0x0110, 0x8001, 0x7022,
-	0x00ee, 0x0005, 0x20a9, 0x0008, 0x20a2, 0x1f04, 0x7244, 0x20a2,
-	0x20a2, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066,
-	0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x94e5, 0x7614, 0x2660,
-	0x2678, 0x2039, 0x0001, 0x87ff, 0x0904, 0x72d2, 0x8cff, 0x0904,
-	0x72d2, 0x601c, 0xa086, 0x0006, 0x1904, 0x72cd, 0x88ff, 0x0138,
-	0x2800, 0xac06, 0x1904, 0x72cd, 0x2039, 0x0000, 0x0050, 0x6018,
-	0xa206, 0x1904, 0x72cd, 0x85ff, 0x0120, 0x6020, 0xa106, 0x1904,
-	0x72cd, 0x7024, 0xac06, 0x1538, 0x2069, 0x0100, 0x68c0, 0xa005,
-	0x01f0, 0x080c, 0x57a1, 0x6817, 0x0008, 0x68c3, 0x0000, 0x080c,
-	0x7356, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384,
-	0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100,
-	0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0020, 0x6003,
-	0x0009, 0x630a, 0x0450, 0x7014, 0xac36, 0x1110, 0x660c, 0x7616,
-	0x7010, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7012,
-	0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110,
-	0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c,
-	0x82ee, 0x0110, 0x080c, 0x9097, 0x080c, 0x849b, 0x080c, 0x7238,
-	0x88ff, 0x1190, 0x00ce, 0x0804, 0x725b, 0x2c78, 0x600c, 0x2060,
-	0x0804, 0x725b, 0xa006, 0x012e, 0x000e, 0x006e, 0x007e, 0x00ce,
-	0x00de, 0x00ee, 0x00fe, 0x0005, 0x6017, 0x0000, 0x00ce, 0xa8c5,
-	0x0001, 0x0c88, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026,
-	0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x94e5, 0x7638, 0x2660,
-	0x2678, 0x8cff, 0x0904, 0x7346, 0x601c, 0xa086, 0x0006, 0x1904,
-	0x7341, 0x88ff, 0x0128, 0x2800, 0xac06, 0x1904, 0x7341, 0x0040,
-	0x6018, 0xa206, 0x15f0, 0x85ff, 0x0118, 0x6020, 0xa106, 0x15c8,
-	0x703c, 0xac06, 0x1170, 0x0036, 0x2019, 0x0001, 0x080c, 0x7110,
-	0x7033, 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000,
-	0x003e, 0x7038, 0xac36, 0x1110, 0x660c, 0x763a, 0x7034, 0xac36,
-	0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037,
-	0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008,
-	0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, 0x82ee, 0x0110,
-	0x080c, 0x9097, 0x080c, 0x849b, 0x88ff, 0x1190, 0x00ce, 0x0804,
-	0x72f1, 0x2c78, 0x600c, 0x2060, 0x0804, 0x72f1, 0xa006, 0x012e,
-	0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005,
-	0x6017, 0x0000, 0x00ce, 0xa8c5, 0x0001, 0x0c88, 0x00e6, 0x2071,
-	0x94e5, 0x2001, 0x9200, 0x2004, 0xa086, 0x0002, 0x1118, 0x7007,
-	0x0005, 0x0010, 0x7007, 0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6,
-	0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071,
-	0x94e5, 0x2c10, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0518, 0x2200,
-	0xac06, 0x11e0, 0x7038, 0xac36, 0x1110, 0x660c, 0x763a, 0x7034,
-	0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7036, 0x0010,
-	0x7037, 0x0000, 0x660c, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008,
-	0x2678, 0x600f, 0x0000, 0xa085, 0x0001, 0x0020, 0x2c78, 0x600c,
-	0x2060, 0x08d8, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00ee,
-	0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0006,
-	0x0126, 0x2091, 0x8000, 0x2071, 0x94e5, 0x760c, 0x2660, 0x2678,
-	0x8cff, 0x0904, 0x7423, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206,
-	0x1904, 0x741e, 0x7024, 0xac06, 0x1500, 0x2069, 0x0100, 0x68c0,
-	0xa005, 0x01d8, 0x080c, 0x6f1e, 0x68c3, 0x0000, 0x080c, 0x7356,
-	0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000,
-	0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824,
-	0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x700c, 0xac36, 0x1110,
-	0x660c, 0x760e, 0x7008, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118,
-	0x2f00, 0x700a, 0x0010, 0x700b, 0x0000, 0x660c, 0x0066, 0x2c00,
-	0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c,
-	0x84b7, 0x1118, 0x080c, 0x2692, 0x00c0, 0x080c, 0x84c8, 0x1118,
-	0x080c, 0x7776, 0x0090, 0x6010, 0x2068, 0x080c, 0x82ee, 0x0168,
-	0x601c, 0xa086, 0x0003, 0x11f8, 0x6837, 0x0103, 0x6b4a, 0x6847,
-	0x0000, 0x080c, 0x4809, 0x080c, 0x848f, 0x6003, 0x0000, 0x080c,
-	0x849b, 0x080c, 0x7238, 0x00ce, 0x0804, 0x73b0, 0x2c78, 0x600c,
-	0x2060, 0x0804, 0x73b0, 0x012e, 0x000e, 0x006e, 0x00ce, 0x00de,
-	0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, 0x19e8, 0x080c,
-	0x9097, 0x0c18, 0x0036, 0x0156, 0x0136, 0x0146, 0x3908, 0xa006,
-	0xa190, 0x0020, 0x221c, 0xa39e, 0x251b, 0x1118, 0x8210, 0x8000,
-	0x0cc8, 0xa005, 0x0138, 0x20a9, 0x0020, 0x2198, 0xa110, 0x22a0,
-	0x22c8, 0x53a3, 0x014e, 0x013e, 0x015e, 0x003e, 0x0005, 0x00d6,
-	0x20a1, 0x020b, 0x080c, 0x68a0, 0x20a3, 0x0200, 0x20a3, 0x0014,
-	0x60c3, 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2099, 0x94df,
-	0x20a9, 0x0004, 0x53a6, 0x20a3, 0x0004, 0x20a3, 0x7878, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x080c, 0x6f0b, 0x00de, 0x0005, 0x20a1,
-	0x020b, 0x080c, 0x68a0, 0x20a3, 0x0210, 0x20a3, 0x0018, 0x20a3,
-	0x0800, 0x7810, 0xa084, 0xff00, 0x20a2, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7810,
-	0xa084, 0x00ff, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
-	0x0018, 0x080c, 0x6f0b, 0x0005, 0x2061, 0x9900, 0x2a70, 0x7064,
-	0x7046, 0x704b, 0x9900, 0x0005, 0x00e6, 0x0126, 0x2071, 0x9200,
-	0x2091, 0x8000, 0x7544, 0xa582, 0x0001, 0x0608, 0x7048, 0x2060,
+	0x0010, 0x1f04, 0x68be, 0x7804, 0xa084, 0x1000, 0x0120, 0x7803,
+	0x0100, 0x7803, 0x0000, 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de,
+	0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x0126, 0x0156, 0x00f6,
+	0x00e6, 0x00d6, 0x00c6, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000,
+	0x2069, 0x0100, 0x2079, 0x0140, 0x2071, 0x8daa, 0x703c, 0x2060,
+	0x8cff, 0x0904, 0x6952, 0x6817, 0x0010, 0x68c7, 0x0000, 0x68cb,
+	0x0000, 0x080c, 0x5687, 0x080c, 0x1e15, 0x0046, 0x2009, 0x017f,
+	0x200b, 0x00a5, 0x2021, 0x0169, 0x2404, 0xa084, 0x000f, 0xa086,
+	0x0004, 0x11b0, 0x68c7, 0x0000, 0x68cb, 0x0008, 0x00e6, 0x00f6,
+	0x2079, 0x0020, 0x2071, 0x8dff, 0x6814, 0xa084, 0x0184, 0xa085,
+	0x0012, 0x6816, 0x7803, 0x0008, 0x7003, 0x0000, 0x00fe, 0x00ee,
+	0x200b, 0x0000, 0x004e, 0xa39d, 0x0000, 0x1120, 0x2009, 0x0049,
+	0x080c, 0x6d3f, 0x20a9, 0x03e8, 0x6824, 0xd094, 0x0158, 0x6827,
+	0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, 0x7803, 0x1000, 0x7803,
+	0x0000, 0x0078, 0xd094, 0x0118, 0x6827, 0x0002, 0x0010, 0x1f04,
+	0x6934, 0x7804, 0xa084, 0x1000, 0x0120, 0x7803, 0x0100, 0x7803,
+	0x0000, 0x6824, 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee,
+	0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000,
+	0x2069, 0x8daa, 0x6a06, 0x012e, 0x00de, 0x0005, 0x00d6, 0x0126,
+	0x2091, 0x8000, 0x2069, 0x8daa, 0x6a32, 0x012e, 0x00de, 0x0005,
+	0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0006, 0x0126, 0x2071, 0x8daa,
+	0x7614, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0538, 0x601c,
+	0xa206, 0x1500, 0x7014, 0xac36, 0x1110, 0x660c, 0x7616, 0x7010,
+	0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7012, 0x0010,
+	0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e,
+	0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0x7d3c, 0x080c, 0x6a05,
+	0x00ce, 0x08d8, 0x2c78, 0x600c, 0x2060, 0x08b8, 0x012e, 0x000e,
+	0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0156, 0x0146, 0x20a1,
+	0x020b, 0x080c, 0x6347, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2,
+	0x20a2, 0x20a2, 0x20a3, 0x1000, 0x0804, 0x69fd, 0x0156, 0x0146,
+	0x20a1, 0x020b, 0x080c, 0x6347, 0x7810, 0x20a2, 0xa006, 0x20a2,
+	0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x4000, 0x0478, 0x0156, 0x0146,
+	0x20a1, 0x020b, 0x080c, 0x6347, 0x7810, 0x20a2, 0xa006, 0x20a2,
+	0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x2000, 0x00f8, 0x0156, 0x0146,
+	0x20a1, 0x020b, 0x080c, 0x6347, 0x7810, 0x20a2, 0xa006, 0x20a2,
+	0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400, 0x0078, 0x0156, 0x0146,
+	0x20a1, 0x020b, 0x080c, 0x6347, 0x7810, 0x20a2, 0xa006, 0x20a2,
+	0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200, 0x0089, 0x60c3, 0x0020,
+	0x080c, 0x66e4, 0x014e, 0x015e, 0x0005, 0x00e6, 0x2071, 0x8daa,
+	0x7020, 0xa005, 0x0110, 0x8001, 0x7022, 0x00ee, 0x0005, 0x20a9,
+	0x0008, 0x20a2, 0x1f04, 0x6a11, 0x20a2, 0x20a2, 0x0005, 0x00f6,
+	0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0006, 0x0126, 0x2091,
+	0x8000, 0x2071, 0x8daa, 0x7614, 0x2660, 0x2678, 0x2039, 0x0001,
+	0x87ff, 0x0904, 0x6a9f, 0x8cff, 0x0904, 0x6a9f, 0x601c, 0xa086,
+	0x0006, 0x1904, 0x6a9a, 0x88ff, 0x0138, 0x2800, 0xac06, 0x1904,
+	0x6a9a, 0x2039, 0x0000, 0x0050, 0x6018, 0xa206, 0x1904, 0x6a9a,
+	0x85ff, 0x0120, 0x6020, 0xa106, 0x1904, 0x6a9a, 0x7024, 0xac06,
+	0x1538, 0x2069, 0x0100, 0x68c0, 0xa005, 0x01f0, 0x080c, 0x567a,
+	0x6817, 0x0008, 0x68c3, 0x0000, 0x080c, 0x6b23, 0x7027, 0x0000,
+	0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803,
+	0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110,
+	0x6827, 0x0001, 0x003e, 0x0020, 0x6003, 0x0009, 0x630a, 0x0450,
+	0x7014, 0xac36, 0x1110, 0x660c, 0x7616, 0x7010, 0xac36, 0x1140,
+	0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000,
+	0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678,
+	0x600f, 0x0000, 0x6010, 0x2068, 0x080c, 0x7b8f, 0x0110, 0x080c,
+	0x8942, 0x080c, 0x7d3c, 0x080c, 0x6a05, 0x88ff, 0x1190, 0x00ce,
+	0x0804, 0x6a28, 0x2c78, 0x600c, 0x2060, 0x0804, 0x6a28, 0xa006,
+	0x012e, 0x000e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe,
+	0x0005, 0x6017, 0x0000, 0x00ce, 0xa8c5, 0x0001, 0x0c88, 0x00f6,
+	0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091,
+	0x8000, 0x2071, 0x8daa, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0904,
+	0x6b13, 0x601c, 0xa086, 0x0006, 0x1904, 0x6b0e, 0x88ff, 0x0128,
+	0x2800, 0xac06, 0x1904, 0x6b0e, 0x0040, 0x6018, 0xa206, 0x15f0,
+	0x85ff, 0x0118, 0x6020, 0xa106, 0x15c8, 0x703c, 0xac06, 0x1170,
+	0x0036, 0x2019, 0x0001, 0x080c, 0x68e5, 0x7033, 0x0000, 0x703f,
+	0x0000, 0x7043, 0x0000, 0x7047, 0x0000, 0x003e, 0x7038, 0xac36,
+	0x1110, 0x660c, 0x763a, 0x7034, 0xac36, 0x1140, 0x2c00, 0xaf36,
+	0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x0066,
+	0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000,
+	0x6010, 0x2068, 0x080c, 0x7b8f, 0x0110, 0x080c, 0x8942, 0x080c,
+	0x7d3c, 0x88ff, 0x1190, 0x00ce, 0x0804, 0x6abe, 0x2c78, 0x600c,
+	0x2060, 0x0804, 0x6abe, 0xa006, 0x012e, 0x000e, 0x002e, 0x006e,
+	0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x6017, 0x0000, 0x00ce,
+	0xa8c5, 0x0001, 0x0c88, 0x00e6, 0x2071, 0x8daa, 0x2001, 0x8b00,
+	0x2004, 0xa086, 0x0002, 0x1118, 0x7007, 0x0005, 0x0010, 0x7007,
+	0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0026,
+	0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x8daa, 0x2c10, 0x7638,
+	0x2660, 0x2678, 0x8cff, 0x0518, 0x2200, 0xac06, 0x11e0, 0x7038,
+	0xac36, 0x1110, 0x660c, 0x763a, 0x7034, 0xac36, 0x1140, 0x2c00,
+	0xaf36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c,
+	0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000,
+	0xa085, 0x0001, 0x0020, 0x2c78, 0x600c, 0x2060, 0x08d8, 0x012e,
+	0x000e, 0x002e, 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00f6,
+	0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0006, 0x0126, 0x2091, 0x8000,
+	0x2071, 0x8daa, 0x760c, 0x2660, 0x2678, 0x8cff, 0x0904, 0x6bf2,
+	0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904, 0x6bed, 0x7024,
+	0xac06, 0x1500, 0x2069, 0x0100, 0x68c0, 0xa005, 0x01d8, 0x080c,
+	0x66f7, 0x68c3, 0x0000, 0x080c, 0x6b23, 0x7027, 0x0000, 0x0036,
+	0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100,
+	0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827,
+	0x0001, 0x003e, 0x700c, 0xac36, 0x1110, 0x660c, 0x760e, 0x7008,
+	0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x700a, 0x0010,
+	0x700b, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e,
+	0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0x7d58, 0x1118, 0x080c,
+	0x2589, 0x00c0, 0x080c, 0x7d69, 0x1118, 0x080c, 0x6fb6, 0x0090,
+	0x6010, 0x2068, 0x080c, 0x7b8f, 0x0168, 0x601c, 0xa086, 0x0003,
+	0x1508, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x46a1,
+	0x080c, 0x7d30, 0x6003, 0x0000, 0x080c, 0x7df6, 0x080c, 0x7d3c,
+	0x080c, 0x6a05, 0x00ce, 0x0804, 0x6b7d, 0x2c78, 0x600c, 0x2060,
+	0x0804, 0x6b7d, 0x012e, 0x000e, 0x006e, 0x00ce, 0x00de, 0x00ee,
+	0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, 0x19d8, 0x080c, 0x8942,
+	0x0c08, 0x0036, 0x0156, 0x0136, 0x0146, 0x3908, 0xa006, 0xa190,
+	0x0020, 0x221c, 0xa39e, 0x23f9, 0x1118, 0x8210, 0x8000, 0x0cc8,
+	0xa005, 0x0138, 0x20a9, 0x0020, 0x2198, 0xa110, 0x22a0, 0x22c8,
+	0x53a3, 0x014e, 0x013e, 0x015e, 0x003e, 0x0005, 0x00d6, 0x20a1,
+	0x020b, 0x080c, 0x612f, 0x20a3, 0x0200, 0x20a3, 0x0014, 0x60c3,
+	0x0014, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2099, 0x8da4, 0x20a9,
+	0x0004, 0x53a6, 0x20a3, 0x0004, 0x20a3, 0x7878, 0x20a3, 0x0000,
+	0x20a3, 0x0000, 0x080c, 0x66e4, 0x00de, 0x0005, 0x20a1, 0x020b,
+	0x080c, 0x612f, 0x20a3, 0x0210, 0x20a3, 0x0018, 0x20a3, 0x0800,
+	0x7810, 0xa084, 0xff00, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000,
+	0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7810, 0xa084,
+	0x00ff, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0018,
+	0x080c, 0x66e4, 0x0005, 0x20a1, 0x020b, 0x0079, 0x7910, 0x21a2,
+	0x20a3, 0x0000, 0x60c3, 0x0000, 0x20e1, 0x9080, 0x60a7, 0x9575,
+	0x080c, 0x66ee, 0x080c, 0x5671, 0x0005, 0x0156, 0x0136, 0x0036,
+	0x00d6, 0x00e6, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7824, 0x2068,
+	0xadf0, 0x000f, 0x7210, 0xa296, 0x00c0, 0xa294, 0xfffd, 0x7212,
+	0x7214, 0xa294, 0x0300, 0x7216, 0x7100, 0xa194, 0x00ff, 0x7308,
+	0xa384, 0x00ff, 0xa08d, 0xc200, 0x7102, 0xa384, 0xff00, 0xa215,
+	0x720a, 0x7004, 0x720c, 0x700e, 0x7206, 0x20a9, 0x000a, 0x2e98,
+	0x53a6, 0x60a3, 0x0035, 0x6a38, 0xa294, 0x7000, 0xa286, 0x3000,
+	0x0110, 0x60a3, 0x0037, 0x00ee, 0x00de, 0x003e, 0x013e, 0x015e,
+	0x0005, 0x2009, 0x0092, 0x0010, 0x2009, 0x0096, 0x60ab, 0x0036,
+	0x6116, 0x0005, 0x2061, 0x9200, 0x2a70, 0x7064, 0x7046, 0x704b,
+	0x9200, 0x0005, 0x00e6, 0x0126, 0x2071, 0x8b00, 0x2091, 0x8000,
+	0x7544, 0xa582, 0x0001, 0x0608, 0x7048, 0x2060, 0x6000, 0xa086,
+	0x0000, 0x0148, 0xace0, 0x000c, 0x7058, 0xac02, 0x1208, 0x0cb0,
+	0x2061, 0x9200, 0x0c98, 0x6003, 0x0008, 0x8529, 0x7546, 0xaca8,
+	0x000c, 0x7058, 0xa502, 0x1230, 0x754a, 0xa085, 0x0001, 0x012e,
+	0x00ee, 0x0005, 0x704b, 0x9200, 0x0cc0, 0xa006, 0x0cc0, 0x00e6,
+	0x2071, 0x8b00, 0x7544, 0xa582, 0x0001, 0x0600, 0x7048, 0x2060,
 	0x6000, 0xa086, 0x0000, 0x0148, 0xace0, 0x000c, 0x7058, 0xac02,
-	0x1208, 0x0cb0, 0x2061, 0x9900, 0x0c98, 0x6003, 0x0008, 0x8529,
-	0x7546, 0xaca8, 0x000c, 0x7058, 0xa502, 0x1230, 0x754a, 0xa085,
-	0x0001, 0x012e, 0x00ee, 0x0005, 0x704b, 0x9900, 0x0cc0, 0xa006,
-	0x0cc0, 0x00e6, 0x2071, 0x9200, 0x7544, 0xa582, 0x0001, 0x0600,
-	0x7048, 0x2060, 0x6000, 0xa086, 0x0000, 0x0148, 0xace0, 0x000c,
-	0x7058, 0xac02, 0x1208, 0x0cb0, 0x2061, 0x9900, 0x0c98, 0x6003,
-	0x0008, 0x8529, 0x7546, 0xaca8, 0x000c, 0x7058, 0xa502, 0x1228,
-	0x754a, 0xa085, 0x0001, 0x00ee, 0x0005, 0x704b, 0x9900, 0x0cc8,
-	0xa006, 0x0cc8, 0xac82, 0x9900, 0x0a0c, 0x13fe, 0x2001, 0x9216,
-	0x2004, 0xac02, 0x1a0c, 0x13fe, 0xa006, 0x6006, 0x600a, 0x600e,
-	0x6012, 0x6016, 0x601a, 0x601f, 0x0000, 0x6003, 0x0000, 0x6022,
-	0x2061, 0x9200, 0x6044, 0x8000, 0x6046, 0xa086, 0x0001, 0x0108,
-	0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x6462, 0x012e, 0x0cc0,
-	0x601c, 0xa084, 0x000f, 0x0002, 0x7526, 0x752d, 0x7548, 0x7563,
-	0x8555, 0x8570, 0x858b, 0x7526, 0x752d, 0x5d3d, 0xa18e, 0x0047,
-	0x1118, 0xa016, 0x080c, 0x16c6, 0x0005, 0x0066, 0x6000, 0xa0b2,
-	0x0010, 0x1a0c, 0x13fe, 0x0013, 0x006e, 0x0005, 0x7546, 0x7654,
-	0x779c, 0x7546, 0x77eb, 0x7546, 0x7546, 0x7546, 0x75f6, 0x7b03,
-	0x7546, 0x7546, 0x7546, 0x7546, 0x7546, 0x7546, 0x080c, 0x13fe,
-	0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x13fe, 0x0013, 0x006e,
-	0x0005, 0x7561, 0x7fa1, 0x7561, 0x7561, 0x7561, 0x7561, 0x7561,
-	0x7561, 0x7f89, 0x8078, 0x7561, 0x7fce, 0x8023, 0x7fce, 0x8023,
-	0x7561, 0x080c, 0x13fe, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c,
-	0x13fe, 0x0013, 0x006e, 0x0005, 0x757c, 0x7b3f, 0x7bf0, 0x7cb4,
-	0x7df4, 0x757c, 0x757c, 0x757c, 0x7b1b, 0x7f40, 0x7f43, 0x757c,
-	0x757c, 0x757c, 0x757c, 0x7f66, 0x080c, 0x13fe, 0x20a9, 0x000e,
-	0x2e98, 0x6010, 0x20a0, 0x53a3, 0x20a9, 0x0006, 0x3310, 0x3420,
-	0x9398, 0x94a0, 0x3318, 0x3428, 0x222e, 0x2326, 0xa290, 0x0002,
-	0xa5a8, 0x0002, 0xa398, 0x0002, 0xa4a0, 0x0002, 0x1f04, 0x758c,
-	0x00e6, 0x080c, 0x82ee, 0x0130, 0x6010, 0x2070, 0x7007, 0x0000,
-	0x7037, 0x0103, 0x00ee, 0x080c, 0x74f2, 0x0005, 0x00d6, 0x0036,
-	0x7330, 0xa386, 0x0200, 0x1130, 0x6018, 0x2068, 0x6813, 0x00ff,
-	0x6817, 0xfffd, 0x6010, 0xa005, 0x0130, 0x2068, 0x6807, 0x0000,
-	0x6837, 0x0103, 0x6b32, 0x080c, 0x74f2, 0x003e, 0x00de, 0x0005,
-	0x0016, 0x20a9, 0x002a, 0xae80, 0x000c, 0x2098, 0x6010, 0xa080,
-	0x0002, 0x20a0, 0x53a3, 0x20a9, 0x002a, 0x6010, 0xa080, 0x0001,
-	0x2004, 0xa080, 0x0002, 0x20a0, 0x53a3, 0x00e6, 0x6010, 0x2004,
-	0x2070, 0x7037, 0x0103, 0x00ee, 0x080c, 0x74f2, 0x001e, 0x0005,
-	0x00d6, 0x20a9, 0x000e, 0x2e98, 0x6010, 0x20a0, 0x53a3, 0xa1b6,
-	0x0015, 0x1148, 0x6018, 0x2068, 0x7038, 0x680a, 0x703c, 0x680e,
-	0x6800, 0xc08d, 0x6802, 0x00de, 0x0804, 0x7598, 0x2100, 0xa1b2,
-	0x003e, 0x1a0c, 0x13fe, 0x0002, 0x763c, 0x7648, 0x763c, 0x763c,
-	0x763c, 0x763c, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a,
-	0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a,
-	0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a,
-	0x763a, 0x763a, 0x763a, 0x763c, 0x763a, 0x763c, 0x763c, 0x763a,
-	0x763a, 0x763a, 0x763a, 0x763a, 0x763c, 0x763a, 0x763a, 0x763a,
-	0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763c, 0x763a,
-	0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a,
-	0x763a, 0x763c, 0x080c, 0x13fe, 0x6003, 0x0001, 0x6106, 0x080c,
-	0x603e, 0x0126, 0x2091, 0x8000, 0x080c, 0x6462, 0x012e, 0x0005,
-	0x6003, 0x0001, 0x6106, 0x080c, 0x603e, 0x0126, 0x2091, 0x8000,
-	0x080c, 0x6462, 0x012e, 0x0005, 0x6004, 0xa0b2, 0x003e, 0x1a0c,
-	0x13fe, 0xa1b6, 0x0013, 0x0904, 0x76f0, 0xa1b6, 0x0027, 0x1904,
-	0x76b6, 0x080c, 0x6389, 0x6004, 0x080c, 0x84b7, 0x0178, 0x080c,
-	0x84c8, 0x0904, 0x76b0, 0xa08e, 0x0021, 0x0904, 0x76b3, 0xa08e,
-	0x0022, 0x05f0, 0xa08e, 0x003d, 0x05f0, 0x04a8, 0x080c, 0x2692,
-	0x2001, 0x0007, 0x080c, 0x43e3, 0x6018, 0xa080, 0x0028, 0x200c,
-	0x080c, 0x7776, 0xa186, 0x007e, 0x1148, 0x2001, 0x9232, 0x2014,
-	0xc285, 0x080c, 0x4dc5, 0x1108, 0xc2ad, 0x2202, 0x0016, 0x0026,
-	0x0036, 0x2110, 0x2019, 0x0028, 0x080c, 0x6127, 0x0086, 0x2041,
-	0x0000, 0x080c, 0x606d, 0x00c6, 0x6018, 0xa065, 0x0110, 0x080c,
-	0x460d, 0x00ce, 0x2c08, 0x080c, 0x8ee4, 0x008e, 0x003e, 0x002e,
-	0x001e, 0x080c, 0x441f, 0x080c, 0x74f2, 0x080c, 0x6462, 0x0005,
-	0x080c, 0x7776, 0x0cc0, 0x080c, 0x7790, 0x0ca8, 0xa186, 0x0014,
-	0x1db0, 0x080c, 0x6389, 0x080c, 0x266c, 0x080c, 0x84b7, 0x1188,
-	0x080c, 0x2692, 0x6018, 0xa080, 0x0028, 0x200c, 0x080c, 0x7776,
-	0xa186, 0x007e, 0x1128, 0x2001, 0x9232, 0x200c, 0xc185, 0x2102,
-	0x08d0, 0x080c, 0x84c8, 0x1118, 0x080c, 0x7776, 0x08a0, 0x6004,
-	0xa08e, 0x0032, 0x1158, 0x00e6, 0x00f6, 0x2071, 0x9296, 0x2079,
-	0x0000, 0x080c, 0x2924, 0x00fe, 0x00ee, 0x0828, 0x6004, 0xa08e,
-	0x0021, 0x0d50, 0xa08e, 0x0022, 0x090c, 0x7790, 0x0804, 0x76ab,
-	0x2008, 0x0002, 0x7732, 0x7733, 0x7736, 0x7739, 0x773c, 0x773f,
-	0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730,
-	0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730,
-	0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730,
-	0x7742, 0x7747, 0x7730, 0x7750, 0x7747, 0x7730, 0x7730, 0x7730,
-	0x7730, 0x7730, 0x7747, 0x7747, 0x7730, 0x7730, 0x7730, 0x7730,
-	0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730,
-	0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7747,
-	0x080c, 0x13fe, 0x00a0, 0x2001, 0x000b, 0x0418, 0x2001, 0x0003,
-	0x0400, 0x2001, 0x0005, 0x00e8, 0x2001, 0x0001, 0x00d0, 0x2001,
-	0x0009, 0x00b8, 0x080c, 0x13fe, 0x0098, 0x080c, 0x43e3, 0x080c,
-	0x6389, 0x6003, 0x0002, 0x6017, 0x0028, 0x080c, 0x6462, 0x0040,
-	0x080c, 0x6389, 0x6003, 0x0004, 0x6017, 0x0028, 0x080c, 0x6462,
-	0x0005, 0x080c, 0x43e3, 0x080c, 0x6389, 0x6003, 0x0002, 0x0036,
-	0x2019, 0x925c, 0x2304, 0xa084, 0xff00, 0x1118, 0x2019, 0x0028,
-	0x0040, 0x8007, 0xa09a, 0x0004, 0x0ec8, 0x8003, 0x801b, 0x831b,
-	0xa318, 0x6316, 0x003e, 0x080c, 0x6462, 0x0c10, 0x00e6, 0x080c,
-	0x82ee, 0x0188, 0x6010, 0x2070, 0x7007, 0x0000, 0x0016, 0x6004,
-	0xa08e, 0x0021, 0x0150, 0xa08e, 0x003d, 0x0138, 0x001e, 0x7037,
-	0x0103, 0x7033, 0x0100, 0x00ee, 0x0005, 0x001e, 0x0009, 0x0cd8,
-	0x00e6, 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103,
-	0x7023, 0x8001, 0x00ee, 0x0005, 0x00d6, 0x6618, 0x2668, 0x6804,
-	0xa084, 0x00ff, 0x00de, 0xa0b2, 0x000c, 0x1a0c, 0x13fe, 0x6604,
-	0xa6b6, 0x0028, 0x1118, 0x080c, 0x84f2, 0x0468, 0x6604, 0xa6b6,
-	0x0029, 0x1118, 0x080c, 0x8509, 0x0430, 0x6604, 0xa6b6, 0x001f,
-	0x1118, 0x080c, 0x757e, 0x00f8, 0x6604, 0xa6b6, 0x0000, 0x1118,
-	0x080c, 0x75e0, 0x00c0, 0x6604, 0xa6b6, 0x0022, 0x1118, 0x080c,
-	0x75a6, 0x0088, 0x6604, 0xa6b6, 0x003d, 0x1118, 0x080c, 0x75c0,
-	0x0050, 0xa1b6, 0x0015, 0x1110, 0x0053, 0x0028, 0xa1b6, 0x0016,
-	0x1118, 0x0804, 0x7983, 0x0005, 0x080c, 0x7526, 0x0ce0, 0x7805,
-	0x7808, 0x7805, 0x7844, 0x7805, 0x7923, 0x7805, 0x7805, 0x7805,
-	0x795b, 0x7805, 0x7971, 0xa1b6, 0x0048, 0x0140, 0x20e1, 0x0005,
-	0x3d18, 0x3e20, 0x2c10, 0x080c, 0x16c6, 0x0005, 0x00e6, 0xacf0,
-	0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, 0x00ee, 0x080c,
-	0x74f2, 0x0005, 0x080c, 0x74f2, 0x0005, 0xe000, 0xe000, 0x0005,
-	0x00e6, 0x2071, 0x9200, 0x7080, 0xa086, 0x0074, 0x11f0, 0x080c,
-	0x8ebb, 0x1170, 0x00d6, 0x6018, 0x2068, 0x00e9, 0x00de, 0x2001,
-	0x0006, 0x080c, 0x43e3, 0x080c, 0x2692, 0x080c, 0x74f2, 0x0088,
-	0x2001, 0x000a, 0x080c, 0x43e3, 0x080c, 0x2692, 0x6003, 0x0001,
-	0x6007, 0x0001, 0x080c, 0x603e, 0x0020, 0x2001, 0x0001, 0x080c,
-	0x7910, 0x00ee, 0x0005, 0x6800, 0xd084, 0x0168, 0x2001, 0x0000,
-	0x080c, 0x43d1, 0x2069, 0x9251, 0x6804, 0xd0a4, 0x0120, 0x2001,
-	0x0006, 0x080c, 0x43f1, 0x0005, 0x00d6, 0x2011, 0x9220, 0x2204,
-	0xa086, 0x0074, 0x1904, 0x790b, 0x080c, 0x7a64, 0x6018, 0x2068,
-	0xa080, 0x0028, 0x2014, 0xa286, 0x007e, 0x0198, 0xa286, 0x0080,
-	0x1904, 0x789c, 0x6813, 0x00ff, 0x6817, 0xfffc, 0x6010, 0xa005,
-	0x0588, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6833, 0x0200,
-	0x0448, 0x00d6, 0x00e6, 0x00f6, 0x6813, 0x00ff, 0x6817, 0xfffe,
-	0x2071, 0x9232, 0x2e04, 0xa085, 0x0003, 0x2072, 0x2071, 0x9780,
-	0x2079, 0x0100, 0x2e04, 0xa084, 0x00ff, 0x2069, 0x921b, 0x206a,
-	0x78e6, 0x8e70, 0x2e04, 0x2069, 0x921c, 0x206a, 0x78ea, 0x7832,
-	0x7836, 0xa084, 0x00ff, 0x2008, 0x080c, 0x2435, 0x00fe, 0x00ee,
-	0x00de, 0x00f8, 0x2001, 0x0006, 0x080c, 0x43e3, 0x080c, 0x2692,
-	0x080c, 0x74f2, 0x0804, 0x790e, 0x6010, 0xa005, 0x0130, 0x2068,
-	0x6838, 0xd0f4, 0x0110, 0x0804, 0x7862, 0x2001, 0x0004, 0x080c,
-	0x43e3, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x603e, 0x0804,
-	0x790e, 0x685c, 0xd0e4, 0x01c8, 0x080c, 0x8531, 0x080c, 0x4dc5,
-	0x0110, 0xd0dc, 0x19b8, 0x2011, 0x9232, 0x2204, 0xc0ad, 0x2012,
-	0x2001, 0x94c8, 0x2004, 0x00f6, 0x2079, 0x0100, 0x78e3, 0x0000,
-	0x080c, 0x2460, 0x78e2, 0x00fe, 0x0828, 0x080c, 0x854a, 0x2011,
-	0x9232, 0x2204, 0xc0a5, 0x2012, 0x0006, 0x080c, 0x8fa4, 0x000e,
-	0x1904, 0x7892, 0xc0b5, 0x2012, 0x2001, 0x0000, 0x080c, 0x43d1,
-	0x00c6, 0x2009, 0x00ef, 0x00f6, 0x2079, 0x0100, 0x79ea, 0x7932,
-	0x7936, 0x00fe, 0x080c, 0x2435, 0x2001, 0x9214, 0x2004, 0x2009,
-	0x0000, 0x080c, 0x240b, 0x2001, 0x9213, 0x2102, 0x8108, 0x080c,
-	0x4400, 0x2c00, 0x00ce, 0x1904, 0x7892, 0x601a, 0x2001, 0x0002,
-	0x080c, 0x43e3, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002,
-	0x080c, 0x603e, 0x0018, 0x2001, 0x0001, 0x0011, 0x00de, 0x0005,
-	0x0006, 0x2001, 0x9200, 0x2004, 0xa086, 0x0003, 0x000e, 0x0130,
-	0xa005, 0x0120, 0x2001, 0x0007, 0x080c, 0x43e3, 0x080c, 0x2692,
-	0x080c, 0x74f2, 0x0005, 0x00e6, 0x2071, 0x9200, 0x7080, 0xa086,
-	0x0014, 0x1548, 0x7000, 0xa086, 0x0003, 0x1128, 0x6010, 0xa005,
-	0x1110, 0x080c, 0x370a, 0x00d6, 0x6018, 0x2068, 0x080c, 0x44c7,
-	0x080c, 0x7833, 0x00de, 0x080c, 0x7a6e, 0x11a8, 0x2001, 0x0006,
-	0x080c, 0x43e3, 0x00e6, 0x6010, 0xa005, 0x0138, 0x2070, 0x7007,
-	0x0000, 0x7037, 0x0103, 0x7033, 0x0200, 0x00ee, 0x080c, 0x2692,
-	0x080c, 0x74f2, 0x0030, 0x080c, 0x7776, 0x2001, 0x0000, 0x080c,
-	0x7910, 0x00ee, 0x0005, 0x2011, 0x9220, 0x2204, 0xa086, 0x0014,
-	0x1158, 0x2001, 0x0002, 0x080c, 0x43e3, 0x6003, 0x0001, 0x6007,
-	0x0001, 0x080c, 0x603e, 0x0020, 0x2001, 0x0001, 0x080c, 0x7910,
-	0x0005, 0x2011, 0x9220, 0x2204, 0xa086, 0x0004, 0x1138, 0x2001,
-	0x0007, 0x080c, 0x43e3, 0x080c, 0x74f2, 0x0020, 0x2001, 0x0001,
-	0x080c, 0x7910, 0x0005, 0x000b, 0x0005, 0x7805, 0x7991, 0x7805,
-	0x79b5, 0x7805, 0x7a1a, 0x7805, 0x7802, 0x7805, 0x7a2f, 0x7805,
-	0x7a41, 0x00c6, 0x080c, 0x7a53, 0x1178, 0x2001, 0x0000, 0x080c,
-	0x43d1, 0x2001, 0x0002, 0x080c, 0x43e3, 0x6003, 0x0001, 0x6007,
-	0x0002, 0x080c, 0x603e, 0x0078, 0x2009, 0x978f, 0x2104, 0xa084,
-	0xff00, 0xa086, 0x1900, 0x1118, 0x080c, 0x74f2, 0x0020, 0x2001,
-	0x0001, 0x080c, 0x7910, 0x00ce, 0x0005, 0x080c, 0x7a61, 0x00d6,
-	0x2069, 0x94d7, 0x2d04, 0xa005, 0x0168, 0x6018, 0x2068, 0x68a0,
-	0xa086, 0x007e, 0x1138, 0x2069, 0x921c, 0x2d04, 0x8000, 0x206a,
-	0x00de, 0x0010, 0x00de, 0x0078, 0x2001, 0x0000, 0x080c, 0x43d1,
-	0x2001, 0x0002, 0x080c, 0x43e3, 0x6003, 0x0001, 0x6007, 0x0002,
-	0x080c, 0x603e, 0x0400, 0x080c, 0x7776, 0x2009, 0x978e, 0x2134,
-	0xa6b4, 0x00ff, 0xa686, 0x0005, 0x01b8, 0x2009, 0x978f, 0x2104,
-	0xa084, 0xff00, 0xa086, 0x1900, 0x1150, 0xa686, 0x0009, 0x0160,
-	0x2001, 0x0004, 0x080c, 0x43e3, 0x080c, 0x74f2, 0x0020, 0x2001,
-	0x0001, 0x080c, 0x7910, 0x0005, 0x00d6, 0x6010, 0x2068, 0x080c,
-	0x82ee, 0x0128, 0x6838, 0xd0fc, 0x0110, 0x00de, 0x0c80, 0x6018,
-	0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0140, 0x8001, 0x6842,
-	0x6017, 0x000a, 0x6007, 0x0016, 0x00de, 0x0c28, 0x080c, 0x266c,
-	0x00de, 0x08e8, 0x080c, 0x7a61, 0x1158, 0x2001, 0x0004, 0x080c,
-	0x43e3, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x603e, 0x0030,
-	0x080c, 0x7776, 0x2001, 0x0000, 0x080c, 0x7910, 0x0005, 0x0489,
-	0x1158, 0x2001, 0x0008, 0x080c, 0x43e3, 0x6003, 0x0001, 0x6007,
-	0x0005, 0x080c, 0x603e, 0x0020, 0x2001, 0x0001, 0x080c, 0x7910,
-	0x0005, 0x00f9, 0x1158, 0x2001, 0x000a, 0x080c, 0x43e3, 0x6003,
-	0x0001, 0x6007, 0x0001, 0x080c, 0x603e, 0x0020, 0x2001, 0x0001,
-	0x080c, 0x7910, 0x0005, 0x2009, 0x978e, 0x2104, 0xa086, 0x0003,
-	0x1138, 0x2009, 0x978f, 0x2104, 0xa084, 0xff00, 0xa086, 0x2a00,
+	0x1208, 0x0cb0, 0x2061, 0x9200, 0x0c98, 0x6003, 0x0008, 0x8529,
+	0x7546, 0xaca8, 0x000c, 0x7058, 0xa502, 0x1228, 0x754a, 0xa085,
+	0x0001, 0x00ee, 0x0005, 0x704b, 0x9200, 0x0cc8, 0xa006, 0x0cc8,
+	0xac82, 0x9200, 0x0a0c, 0x1410, 0x2001, 0x8b16, 0x2004, 0xac02,
+	0x1a0c, 0x1410, 0xa006, 0x6006, 0x600a, 0x600e, 0x6012, 0x6016,
+	0x601a, 0x601f, 0x0000, 0x6003, 0x0000, 0x6022, 0x6026, 0x2061,
+	0x8b00, 0x6044, 0x8000, 0x6046, 0xa086, 0x0001, 0x0108, 0x0005,
+	0x0126, 0x2091, 0x8000, 0x080c, 0x5d10, 0x012e, 0x0cc0, 0x601c,
+	0xa084, 0x000f, 0x0002, 0x6d4d, 0x6d5c, 0x6d77, 0x6d92, 0x7dfe,
+	0x7e19, 0x7e34, 0x6d4d, 0x6d5c, 0x6d4d, 0xa186, 0x0013, 0x1128,
+	0x080c, 0x5c37, 0x080c, 0x5d10, 0x0005, 0xa18e, 0x0047, 0x1118,
+	0xa016, 0x080c, 0x16d1, 0x0005, 0x0066, 0x6000, 0xa0b2, 0x0010,
+	0x1a0c, 0x1410, 0x0013, 0x006e, 0x0005, 0x6d75, 0x6e85, 0x6fdf,
+	0x6d75, 0x702e, 0x6d75, 0x6d75, 0x6d75, 0x6e25, 0x733b, 0x6d75,
+	0x6d75, 0x6d75, 0x6d75, 0x6d75, 0x6d75, 0x080c, 0x1410, 0x0066,
+	0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x1410, 0x0013, 0x006e, 0x0005,
+	0x6d90, 0x77f2, 0x6d90, 0x6d90, 0x6d90, 0x6d90, 0x6d90, 0x6d90,
+	0x77da, 0x78d0, 0x6d90, 0x781f, 0x7877, 0x781f, 0x7877, 0x6d90,
+	0x080c, 0x1410, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x1410,
+	0x0013, 0x006e, 0x0005, 0x6dab, 0x7377, 0x742b, 0x74ef, 0x762f,
+	0x6dab, 0x6dab, 0x6dab, 0x7353, 0x778f, 0x7792, 0x6dab, 0x6dab,
+	0x6dab, 0x6dab, 0x77b7, 0x080c, 0x1410, 0x20a9, 0x000e, 0x2e98,
+	0x6010, 0x20a0, 0x53a3, 0x20a9, 0x0006, 0x3310, 0x3420, 0x9398,
+	0x94a0, 0x3318, 0x3428, 0x222e, 0x2326, 0xa290, 0x0002, 0xa5a8,
+	0x0002, 0xa398, 0x0002, 0xa4a0, 0x0002, 0x1f04, 0x6dbb, 0x00e6,
+	0x080c, 0x7b8f, 0x0130, 0x6010, 0x2070, 0x7007, 0x0000, 0x7037,
+	0x0103, 0x00ee, 0x080c, 0x6d18, 0x0005, 0x00d6, 0x0036, 0x7330,
+	0xa386, 0x0200, 0x1130, 0x6018, 0x2068, 0x6813, 0x00ff, 0x6817,
+	0xfffd, 0x6010, 0xa005, 0x0130, 0x2068, 0x6807, 0x0000, 0x6837,
+	0x0103, 0x6b32, 0x080c, 0x6d18, 0x003e, 0x00de, 0x0005, 0x0016,
+	0x20a9, 0x002a, 0xae80, 0x000c, 0x2098, 0x6010, 0xa080, 0x0002,
+	0x20a0, 0x53a3, 0x20a9, 0x002a, 0x6010, 0xa080, 0x0001, 0x2004,
+	0xa080, 0x0002, 0x20a0, 0x53a3, 0x00e6, 0x6010, 0x2004, 0x2070,
+	0x7037, 0x0103, 0x00ee, 0x080c, 0x6d18, 0x001e, 0x0005, 0x00d6,
+	0x20a9, 0x000e, 0x2e98, 0x6010, 0x20a0, 0x53a3, 0xa1b6, 0x0015,
+	0x1148, 0x6018, 0x2068, 0x7038, 0x680a, 0x703c, 0x680e, 0x6800,
+	0xc08d, 0x6802, 0x00de, 0x0804, 0x6dc7, 0x2100, 0xa1b2, 0x0040,
+	0x1a0c, 0x1410, 0x0002, 0x6e6d, 0x6e79, 0x6e6d, 0x6e6d, 0x6e6d,
+	0x6e6d, 0x6e6b, 0x6e6b, 0x6e6b, 0x6e6b, 0x6e6b, 0x6e6b, 0x6e6b,
+	0x6e6b, 0x6e6b, 0x6e6b, 0x6e6b, 0x6e6b, 0x6e6b, 0x6e6b, 0x6e6b,
+	0x6e6b, 0x6e6b, 0x6e6b, 0x6e6b, 0x6e6b, 0x6e6b, 0x6e6b, 0x6e6b,
+	0x6e6b, 0x6e6b, 0x6e6d, 0x6e6b, 0x6e6d, 0x6e6d, 0x6e6b, 0x6e6b,
+	0x6e6b, 0x6e6b, 0x6e6b, 0x6e6d, 0x6e6b, 0x6e6b, 0x6e6b, 0x6e6b,
+	0x6e6b, 0x6e6b, 0x6e6b, 0x6e6b, 0x6e6b, 0x6e6d, 0x6e6b, 0x6e6b,
+	0x6e6b, 0x6e6b, 0x6e6b, 0x6e6b, 0x6e6b, 0x6e6b, 0x6e6b, 0x6e6b,
+	0x6e6d, 0x6e6b, 0x6e6b, 0x080c, 0x1410, 0x6003, 0x0001, 0x6106,
+	0x080c, 0x58e2, 0x0126, 0x2091, 0x8000, 0x080c, 0x5d10, 0x012e,
+	0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x58e2, 0x0126, 0x2091,
+	0x8000, 0x080c, 0x5d10, 0x012e, 0x0005, 0x6004, 0xa0b2, 0x0040,
+	0x1a0c, 0x1410, 0xa1b6, 0x0013, 0x0904, 0x6f25, 0xa1b6, 0x0027,
+	0x1904, 0x6eeb, 0x080c, 0x5c37, 0x6004, 0x080c, 0x7d58, 0x0188,
+	0x080c, 0x7d69, 0x0904, 0x6ee5, 0xa08e, 0x0021, 0x0904, 0x6ee8,
+	0xa08e, 0x0022, 0x0904, 0x6ee5, 0xa08e, 0x003d, 0x0904, 0x6ee8,
+	0x04a8, 0x080c, 0x2589, 0x2001, 0x0007, 0x080c, 0x42b9, 0x6018,
+	0xa080, 0x0028, 0x200c, 0x080c, 0x6fb6, 0xa186, 0x007e, 0x1148,
+	0x2001, 0x8b32, 0x2014, 0xc285, 0x080c, 0x4c42, 0x1108, 0xc2ad,
+	0x2202, 0x0016, 0x0026, 0x0036, 0x2110, 0x2019, 0x0028, 0x080c,
+	0x59d5, 0x0086, 0x2041, 0x0000, 0x080c, 0x5911, 0x00c6, 0x6018,
+	0xa065, 0x0110, 0x080c, 0x44e6, 0x00ce, 0x2c08, 0x080c, 0x878f,
+	0x008e, 0x003e, 0x002e, 0x001e, 0x080c, 0x42f5, 0x080c, 0x7df6,
+	0x080c, 0x6d18, 0x080c, 0x5d10, 0x0005, 0x080c, 0x6fb6, 0x0cb0,
+	0x080c, 0x6fd3, 0x0c98, 0xa186, 0x0014, 0x1db0, 0x080c, 0x5c37,
+	0x080c, 0x2563, 0x080c, 0x7d58, 0x1188, 0x080c, 0x2589, 0x6018,
+	0xa080, 0x0028, 0x200c, 0x080c, 0x6fb6, 0xa186, 0x007e, 0x1128,
+	0x2001, 0x8b32, 0x200c, 0xc185, 0x2102, 0x08c0, 0x080c, 0x7d69,
+	0x1118, 0x080c, 0x6fb6, 0x0890, 0x6004, 0xa08e, 0x0032, 0x1158,
+	0x00e6, 0x00f6, 0x2071, 0x8b81, 0x2079, 0x0000, 0x080c, 0x2848,
+	0x00fe, 0x00ee, 0x0818, 0x6004, 0xa08e, 0x0021, 0x0d50, 0xa08e,
+	0x0022, 0x090c, 0x6fd3, 0x0804, 0x6ede, 0x2008, 0x0002, 0x6f69,
+	0x6f6a, 0x6f6d, 0x6f70, 0x6f73, 0x6f76, 0x6f67, 0x6f67, 0x6f67,
+	0x6f67, 0x6f67, 0x6f67, 0x6f67, 0x6f67, 0x6f67, 0x6f67, 0x6f67,
+	0x6f67, 0x6f67, 0x6f67, 0x6f67, 0x6f67, 0x6f67, 0x6f67, 0x6f67,
+	0x6f67, 0x6f67, 0x6f67, 0x6f67, 0x6f67, 0x6f79, 0x6f7e, 0x6f67,
+	0x6f87, 0x6f7e, 0x6f67, 0x6f67, 0x6f67, 0x6f67, 0x6f67, 0x6f7e,
+	0x6f7e, 0x6f67, 0x6f67, 0x6f67, 0x6f67, 0x6f67, 0x6f67, 0x6f67,
+	0x6f67, 0x6f67, 0x6f67, 0x6f67, 0x6f67, 0x6f67, 0x6f67, 0x6f67,
+	0x6f67, 0x6f67, 0x6f67, 0x6f67, 0x6f7e, 0x6fad, 0x6f67, 0x080c,
+	0x1410, 0x00a0, 0x2001, 0x000b, 0x0418, 0x2001, 0x0003, 0x0400,
+	0x2001, 0x0005, 0x00e8, 0x2001, 0x0001, 0x00d0, 0x2001, 0x0009,
+	0x00b8, 0x080c, 0x1410, 0x0098, 0x080c, 0x42b9, 0x080c, 0x5c37,
+	0x6003, 0x0002, 0x6017, 0x0028, 0x080c, 0x5d10, 0x0040, 0x080c,
+	0x5c37, 0x6003, 0x0004, 0x6017, 0x0028, 0x080c, 0x5d10, 0x0005,
+	0x080c, 0x42b9, 0x080c, 0x5c37, 0x6003, 0x0002, 0x0036, 0x2019,
+	0x8b5c, 0x2304, 0xa084, 0xff00, 0x1118, 0x2019, 0x0028, 0x0040,
+	0x8007, 0xa09a, 0x0004, 0x0ec8, 0x8003, 0x801b, 0x831b, 0xa318,
+	0x6316, 0x003e, 0x080c, 0x5d10, 0x0c10, 0x080c, 0x5c37, 0x080c,
+	0x7df6, 0x080c, 0x6d18, 0x080c, 0x5d10, 0x08c8, 0x00e6, 0x080c,
+	0x7b8f, 0x01a0, 0x6010, 0x2070, 0x7038, 0xd0fc, 0x0178, 0x7007,
+	0x0000, 0x0016, 0x6004, 0xa08e, 0x0021, 0x0150, 0xa08e, 0x003d,
+	0x0138, 0x001e, 0x7037, 0x0103, 0x7033, 0x0100, 0x00ee, 0x0005,
+	0x001e, 0x0009, 0x0cd8, 0x00e6, 0xacf0, 0x0004, 0x2e74, 0x7000,
+	0x2070, 0x7037, 0x0103, 0x7023, 0x8001, 0x00ee, 0x0005, 0x00d6,
+	0x6618, 0x2668, 0x6804, 0xa084, 0x00ff, 0x00de, 0xa0b2, 0x000c,
+	0x1a0c, 0x1410, 0x6604, 0xa6b6, 0x0028, 0x1118, 0x080c, 0x7d93,
+	0x0468, 0x6604, 0xa6b6, 0x0029, 0x1118, 0x080c, 0x7daa, 0x0430,
+	0x6604, 0xa6b6, 0x001f, 0x1118, 0x080c, 0x6dad, 0x00f8, 0x6604,
+	0xa6b6, 0x0000, 0x1118, 0x080c, 0x6e0f, 0x00c0, 0x6604, 0xa6b6,
+	0x0022, 0x1118, 0x080c, 0x6dd5, 0x0088, 0x6604, 0xa6b6, 0x003d,
+	0x1118, 0x080c, 0x6def, 0x0050, 0xa1b6, 0x0015, 0x1110, 0x0053,
+	0x0028, 0xa1b6, 0x0016, 0x1118, 0x0804, 0x71c6, 0x0005, 0x080c,
+	0x6d55, 0x0ce0, 0x7045, 0x7048, 0x7045, 0x7082, 0x7045, 0x716c,
+	0x7045, 0x7045, 0x7045, 0x71a2, 0x7045, 0x71b6, 0xa1b6, 0x0048,
+	0x0140, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x16d1,
+	0x0005, 0x00e6, 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037,
+	0x0103, 0x00ee, 0x080c, 0x6d18, 0x0005, 0xe000, 0xe000, 0x0005,
+	0x00e6, 0x2071, 0x8b00, 0x7080, 0xa086, 0x0074, 0x11f0, 0x080c,
+	0x8766, 0x1170, 0x00d6, 0x6018, 0x2068, 0x00d9, 0x00de, 0x2001,
+	0x0006, 0x080c, 0x42b9, 0x080c, 0x2589, 0x080c, 0x6d18, 0x0078,
+	0x2001, 0x000a, 0x080c, 0x42b9, 0x080c, 0x2589, 0x6003, 0x0001,
+	0x6007, 0x0001, 0x080c, 0x58e2, 0x0010, 0x080c, 0x715d, 0x00ee,
+	0x0005, 0x6800, 0xd084, 0x0168, 0x2001, 0x0000, 0x080c, 0x42a7,
+	0x2069, 0x8b51, 0x6804, 0xd0a4, 0x0120, 0x2001, 0x0006, 0x080c,
+	0x42c7, 0x0005, 0x00d6, 0x2011, 0x8b20, 0x2204, 0xa086, 0x0074,
+	0x1904, 0x715a, 0x080c, 0x72a4, 0x6018, 0x2068, 0xa080, 0x0028,
+	0x2014, 0xa286, 0x007e, 0x0198, 0xa286, 0x0080, 0x1904, 0x70da,
+	0x6813, 0x00ff, 0x6817, 0xfffc, 0x6010, 0xa005, 0x0588, 0x2068,
+	0x6807, 0x0000, 0x6837, 0x0103, 0x6833, 0x0200, 0x0448, 0x00d6,
+	0x00e6, 0x00f6, 0x6813, 0x00ff, 0x6817, 0xfffe, 0x2071, 0x8b32,
+	0x2e04, 0xa085, 0x0003, 0x2072, 0x2071, 0x9080, 0x2079, 0x0100,
+	0x2e04, 0xa084, 0x00ff, 0x2069, 0x8b1b, 0x206a, 0x78e6, 0x8e70,
+	0x2e04, 0x2069, 0x8b1c, 0x206a, 0x78ea, 0x7832, 0x7836, 0xa084,
+	0x00ff, 0x2008, 0x080c, 0x2313, 0x00fe, 0x00ee, 0x00de, 0x0470,
+	0x2001, 0x0006, 0x080c, 0x42b9, 0x080c, 0x2589, 0x080c, 0x6d18,
+	0x0804, 0x715b, 0x00e6, 0x2071, 0x8b32, 0x2e04, 0xd09c, 0x0188,
+	0x2071, 0x9080, 0x7108, 0x720c, 0xa18c, 0x00ff, 0x1118, 0xa284,
+	0xff00, 0x0138, 0x6018, 0x2070, 0x70a0, 0xd0bc, 0x1110, 0x7112,
+	0x7216, 0x00ee, 0x2001, 0x0004, 0x080c, 0x42b9, 0x6003, 0x0001,
+	0x6007, 0x0003, 0x080c, 0x58e2, 0x0804, 0x715b, 0x685c, 0xd0e4,
+	0x01d0, 0x080c, 0x7dd2, 0x080c, 0x4c42, 0x0110, 0xd0dc, 0x1940,
+	0x2011, 0x8b32, 0x2204, 0xc0ad, 0x2012, 0x2001, 0x8d8d, 0x2004,
+	0x00f6, 0x2079, 0x0100, 0x78e3, 0x0000, 0x080c, 0x233e, 0x78e2,
+	0x00fe, 0x0804, 0x70d0, 0x080c, 0x7deb, 0x2011, 0x8b32, 0x2204,
+	0xc0a5, 0x2012, 0x0006, 0x080c, 0x884f, 0x000e, 0x1904, 0x70d0,
+	0xc0b5, 0x2012, 0x2001, 0x0000, 0x080c, 0x42a7, 0x00c6, 0x2009,
+	0x00ef, 0x00f6, 0x2079, 0x0100, 0x79ea, 0x7932, 0x7936, 0x00fe,
+	0x080c, 0x2313, 0x00f6, 0x2079, 0x8b00, 0x7972, 0x2100, 0x2009,
+	0x0000, 0x080c, 0x22e9, 0x794e, 0x00fe, 0x8108, 0x080c, 0x42d6,
+	0x2c00, 0x00ce, 0x1904, 0x70d0, 0x601a, 0x2001, 0x0002, 0x080c,
+	0x42b9, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c,
+	0x58e2, 0x0008, 0x0011, 0x00de, 0x0005, 0x2001, 0x8b00, 0x2004,
+	0xa086, 0x0003, 0x0120, 0x2001, 0x0007, 0x080c, 0x42b9, 0x080c,
+	0x2589, 0x080c, 0x6d18, 0x0005, 0x00e6, 0x2071, 0x8b00, 0x7080,
+	0xa086, 0x0014, 0x1548, 0x7000, 0xa086, 0x0003, 0x1128, 0x6010,
+	0xa005, 0x1110, 0x080c, 0x3689, 0x00d6, 0x6018, 0x2068, 0x080c,
+	0x43a0, 0x080c, 0x7071, 0x00de, 0x080c, 0x72ae, 0x11a8, 0x2001,
+	0x0006, 0x080c, 0x42b9, 0x00e6, 0x6010, 0xa005, 0x0138, 0x2070,
+	0x7007, 0x0000, 0x7037, 0x0103, 0x7033, 0x0200, 0x00ee, 0x080c,
+	0x2589, 0x080c, 0x6d18, 0x0020, 0x080c, 0x6fb6, 0x080c, 0x715d,
+	0x00ee, 0x0005, 0x2011, 0x8b20, 0x2204, 0xa086, 0x0014, 0x1158,
+	0x2001, 0x0002, 0x080c, 0x42b9, 0x6003, 0x0001, 0x6007, 0x0001,
+	0x080c, 0x58e2, 0x0010, 0x080c, 0x715d, 0x0005, 0x2011, 0x8b20,
+	0x2204, 0xa086, 0x0004, 0x1138, 0x2001, 0x0007, 0x080c, 0x42b9,
+	0x080c, 0x6d18, 0x0010, 0x080c, 0x715d, 0x0005, 0x000b, 0x0005,
+	0x7045, 0x71d4, 0x7045, 0x71f6, 0x7045, 0x7260, 0x7045, 0x7045,
+	0x7045, 0x7273, 0x7045, 0x7283, 0x00c6, 0x080c, 0x7293, 0x1178,
+	0x2001, 0x0000, 0x080c, 0x42a7, 0x2001, 0x0002, 0x080c, 0x42b9,
+	0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x58e2, 0x0068, 0x2009,
+	0x908f, 0x2104, 0xa084, 0xff00, 0xa086, 0x1900, 0x1118, 0x080c,
+	0x6d18, 0x0010, 0x080c, 0x715d, 0x00ce, 0x0005, 0x080c, 0x72a1,
+	0x00d6, 0x2069, 0x8d9c, 0x2d04, 0xa005, 0x0168, 0x6018, 0x2068,
+	0x68a0, 0xa086, 0x007e, 0x1138, 0x2069, 0x8b1c, 0x2d04, 0x8000,
+	0x206a, 0x00de, 0x0010, 0x00de, 0x0078, 0x2001, 0x0000, 0x080c,
+	0x42a7, 0x2001, 0x0002, 0x080c, 0x42b9, 0x6003, 0x0001, 0x6007,
+	0x0002, 0x080c, 0x58e2, 0x0428, 0x080c, 0x6fb6, 0x2009, 0x908e,
+	0x2134, 0xa6b4, 0x00ff, 0xa686, 0x0005, 0x01e0, 0xa686, 0x000b,
+	0x01b0, 0x2009, 0x908f, 0x2104, 0xa084, 0xff00, 0x1118, 0xa686,
+	0x0009, 0x0180, 0xa086, 0x1900, 0x1150, 0xa686, 0x0009, 0x0150,
+	0x2001, 0x0004, 0x080c, 0x42b9, 0x080c, 0x6d18, 0x0010, 0x080c,
+	0x715d, 0x0005, 0x00d6, 0x6010, 0x2068, 0x080c, 0x7b8f, 0x0128,
+	0x6838, 0xd0fc, 0x0110, 0x00de, 0x0c90, 0x6018, 0x2068, 0x6840,
+	0xa084, 0x00ff, 0xa005, 0x0140, 0x8001, 0x6842, 0x6017, 0x000a,
+	0x6007, 0x0016, 0x00de, 0x0c28, 0x080c, 0x2563, 0x00de, 0x08f8,
+	0x080c, 0x72a1, 0x1158, 0x2001, 0x0004, 0x080c, 0x42b9, 0x6003,
+	0x0001, 0x6007, 0x0003, 0x080c, 0x58e2, 0x0020, 0x080c, 0x6fb6,
+	0x080c, 0x715d, 0x0005, 0x0469, 0x1158, 0x2001, 0x0008, 0x080c,
+	0x42b9, 0x6003, 0x0001, 0x6007, 0x0005, 0x080c, 0x58e2, 0x0010,
+	0x080c, 0x715d, 0x0005, 0x00e9, 0x1158, 0x2001, 0x000a, 0x080c,
+	0x42b9, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x58e2, 0x0010,
+	0x080c, 0x715d, 0x0005, 0x2009, 0x908e, 0x2104, 0xa086, 0x0003,
+	0x1138, 0x2009, 0x908f, 0x2104, 0xa084, 0xff00, 0xa086, 0x2a00,
 	0x0005, 0xa085, 0x0001, 0x0005, 0x00c6, 0x0016, 0xac88, 0x0006,
-	0x2164, 0x080c, 0x4443, 0x001e, 0x00ce, 0x0005, 0x00e6, 0x2071,
-	0x978c, 0x7004, 0xa086, 0x0014, 0x11a8, 0x7008, 0xa086, 0x0800,
+	0x2164, 0x080c, 0x4319, 0x001e, 0x00ce, 0x0005, 0x00e6, 0x2071,
+	0x908c, 0x7004, 0xa086, 0x0014, 0x11a8, 0x7008, 0xa086, 0x0800,
 	0x1188, 0x700c, 0xd0ec, 0x0160, 0xa084, 0x0f00, 0xa086, 0x0100,
 	0x1138, 0x7024, 0xd0a4, 0x1110, 0xd0ac, 0x0110, 0xa006, 0x0010,
 	0xa085, 0x0001, 0x00ee, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0076,
 	0x0056, 0x0046, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2029,
-	0x94ee, 0x252c, 0x2021, 0x94f4, 0x2424, 0x2061, 0x9900, 0x2071,
-	0x9200, 0x7244, 0x7064, 0xa202, 0x1688, 0x080c, 0x90ee, 0x0540,
+	0x8db3, 0x252c, 0x2021, 0x8db9, 0x2424, 0x2061, 0x9200, 0x2071,
+	0x8b00, 0x7244, 0x7064, 0xa202, 0x1688, 0x080c, 0x8999, 0x0540,
 	0x671c, 0xa786, 0x0001, 0x0520, 0xa786, 0x0007, 0x0508, 0x2500,
 	0xac06, 0x01f0, 0x2400, 0xac06, 0x01d8, 0x00c6, 0x6000, 0xa086,
-	0x0004, 0x1110, 0x080c, 0x1788, 0x6010, 0x2068, 0x080c, 0x82ee,
+	0x0004, 0x1110, 0x080c, 0x179e, 0x6010, 0x2068, 0x080c, 0x7b8f,
 	0x0160, 0xa786, 0x0003, 0x11e0, 0x6837, 0x0103, 0x6b4a, 0x6847,
-	0x0000, 0x080c, 0x4809, 0x080c, 0x848f, 0x080c, 0x849b, 0x00ce,
+	0x0000, 0x080c, 0x46a1, 0x080c, 0x7d30, 0x080c, 0x7d3c, 0x00ce,
 	0xace0, 0x000c, 0x7058, 0xac02, 0x1208, 0x0858, 0x012e, 0x000e,
 	0x002e, 0x004e, 0x005e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x0005,
-	0xa786, 0x0006, 0x1118, 0x080c, 0x9097, 0x0c38, 0xa786, 0x0009,
-	0x19d8, 0x2009, 0x0106, 0x080c, 0x7518, 0x0c08, 0x220c, 0x2304,
-	0xa106, 0x1130, 0x8210, 0x8318, 0x1f04, 0x7aee, 0xa006, 0x0005,
+	0xa786, 0x0006, 0x1d08, 0x080c, 0x8942, 0x0c38, 0x220c, 0x2304,
+	0xa106, 0x1130, 0x8210, 0x8318, 0x1f04, 0x7326, 0xa006, 0x0005,
 	0x2304, 0xa102, 0x0218, 0x2001, 0x0001, 0x0010, 0x2001, 0x0000,
-	0xa18d, 0x0001, 0x0005, 0x6004, 0xa08a, 0x003e, 0x1a0c, 0x13fe,
-	0x080c, 0x84b7, 0x0120, 0x080c, 0x84c8, 0x0150, 0x0010, 0x080c,
-	0x2692, 0x080c, 0x6389, 0x080c, 0x74f2, 0x080c, 0x6462, 0x0005,
-	0x080c, 0x7776, 0x0cb0, 0xa182, 0x0040, 0x0002, 0x7b31, 0x7b31,
-	0x7b31, 0x7b31, 0x7b31, 0x7b31, 0x7b31, 0x7b31, 0x7b31, 0x7b31,
-	0x7b31, 0x7b33, 0x7b33, 0x7b33, 0x7b33, 0x7b31, 0x7b31, 0x7b31,
-	0x7b33, 0x080c, 0x13fe, 0x6003, 0x0001, 0x6106, 0x080c, 0x5ff8,
-	0x0126, 0x2091, 0x8000, 0x080c, 0x6462, 0x012e, 0x0005, 0xa186,
-	0x0013, 0x1128, 0x6004, 0xa082, 0x0040, 0x0804, 0x7bc5, 0xa186,
-	0x0027, 0x11d0, 0x080c, 0x6389, 0x080c, 0x266c, 0x00d6, 0x6110,
-	0x2168, 0x080c, 0x82ee, 0x0150, 0x6837, 0x0103, 0x684b, 0x0029,
-	0x6847, 0x0000, 0x080c, 0x4809, 0x080c, 0x848f, 0x00de, 0x080c,
-	0x74f2, 0x080c, 0x6462, 0x0005, 0xa186, 0x0014, 0x1120, 0x6004,
+	0xa18d, 0x0001, 0x0005, 0x6004, 0xa08a, 0x0040, 0x1a0c, 0x1410,
+	0x080c, 0x7d58, 0x0120, 0x080c, 0x7d69, 0x0150, 0x0010, 0x080c,
+	0x2589, 0x080c, 0x5c37, 0x080c, 0x6d18, 0x080c, 0x5d10, 0x0005,
+	0x080c, 0x6fb6, 0x0cb0, 0xa182, 0x0040, 0x0002, 0x7369, 0x7369,
+	0x7369, 0x7369, 0x7369, 0x7369, 0x7369, 0x7369, 0x7369, 0x7369,
+	0x7369, 0x736b, 0x736b, 0x736b, 0x736b, 0x7369, 0x7369, 0x7369,
+	0x736b, 0x080c, 0x1410, 0x6003, 0x0001, 0x6106, 0x080c, 0x589c,
+	0x0126, 0x2091, 0x8000, 0x080c, 0x5d10, 0x012e, 0x0005, 0xa186,
+	0x0013, 0x1128, 0x6004, 0xa082, 0x0040, 0x0804, 0x7400, 0xa186,
+	0x0027, 0x11d0, 0x080c, 0x5c37, 0x080c, 0x2563, 0x00d6, 0x6110,
+	0x2168, 0x080c, 0x7b8f, 0x0150, 0x6837, 0x0103, 0x684b, 0x0029,
+	0x6847, 0x0000, 0x080c, 0x46a1, 0x080c, 0x7d30, 0x00de, 0x080c,
+	0x6d18, 0x080c, 0x5d10, 0x0005, 0xa186, 0x0014, 0x1120, 0x6004,
 	0xa082, 0x0040, 0x0428, 0xa186, 0x0046, 0x0138, 0xa186, 0x0045,
-	0x0120, 0xa186, 0x0047, 0x190c, 0x13fe, 0x2001, 0x0109, 0x2004,
+	0x0120, 0xa186, 0x0047, 0x190c, 0x1410, 0x2001, 0x0109, 0x2004,
 	0xd084, 0x0198, 0x0126, 0x2091, 0x2400, 0x0006, 0x0016, 0x0026,
-	0x080c, 0x5ee3, 0x002e, 0x001e, 0x000e, 0x012e, 0xe000, 0x6000,
-	0xa086, 0x0002, 0x1110, 0x0804, 0x7bf0, 0x080c, 0x7526, 0x0005,
-	0x0002, 0x7ba6, 0x7ba4, 0x7ba4, 0x7ba4, 0x7ba4, 0x7ba4, 0x7ba4,
-	0x7ba4, 0x7ba4, 0x7ba4, 0x7ba4, 0x7bbe, 0x7bbe, 0x7bbe, 0x7bbe,
-	0x7ba4, 0x7ba4, 0x7ba4, 0x7bbe, 0x080c, 0x13fe, 0x080c, 0x6389,
-	0x00d6, 0x6110, 0x2168, 0x080c, 0x82ee, 0x0150, 0x6837, 0x0103,
-	0x684b, 0x0006, 0x6847, 0x0000, 0x080c, 0x4809, 0x080c, 0x848f,
-	0x00de, 0x080c, 0x74f2, 0x080c, 0x6462, 0x0005, 0x080c, 0x6389,
-	0x080c, 0x74f2, 0x080c, 0x6462, 0x0005, 0x0002, 0x7bdb, 0x7bd9,
-	0x7bd9, 0x7bd9, 0x7bd9, 0x7bd9, 0x7bd9, 0x7bd9, 0x7bd9, 0x7bd9,
-	0x7bd9, 0x7be9, 0x7be9, 0x7be9, 0x7be9, 0x7bd9, 0x7bd9, 0x7bd9,
-	0x7be9, 0x080c, 0x13fe, 0x080c, 0x6389, 0x6003, 0x0002, 0x080c,
-	0x6462, 0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a,
-	0x0005, 0x080c, 0x6389, 0x6003, 0x000f, 0x080c, 0x6462, 0x0005,
-	0xa182, 0x0040, 0x0002, 0x7c06, 0x7c06, 0x7c06, 0x7c06, 0x7c06,
-	0x7c08, 0x7c8a, 0x7ca9, 0x7c06, 0x7c06, 0x7c06, 0x7c06, 0x7c06,
-	0x7c06, 0x7c06, 0x7c06, 0x7c06, 0x7c06, 0x7c06, 0x080c, 0x13fe,
-	0x00e6, 0x00d6, 0x2071, 0x978c, 0x6110, 0x2168, 0x7614, 0xa6b4,
-	0x0fff, 0x86ff, 0x0904, 0x7c70, 0xa68c, 0x0c00, 0x0120, 0x7318,
-	0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0190,
-	0xa186, 0x0028, 0x1128, 0x080c, 0x84a6, 0x684b, 0x001c, 0x0060,
-	0xd6dc, 0x0118, 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b,
-	0x0007, 0x0010, 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, 0xa01e,
-	0xd6c4, 0x01b0, 0xa686, 0x0100, 0x1138, 0x2001, 0x9799, 0x2004,
-	0xa005, 0x1110, 0xc6c4, 0x0868, 0x7328, 0x732c, 0x6b56, 0x0036,
-	0x2308, 0x2019, 0x9798, 0xad90, 0x0019, 0x080c, 0x80e6, 0x003e,
-	0xd6cc, 0x0560, 0x7124, 0x695a, 0xa192, 0x0021, 0x1250, 0x2071,
-	0x9798, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0x80e6,
-	0x00e8, 0x6838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c78,
-	0x00f6, 0x2d78, 0x080c, 0x808b, 0x00fe, 0x080c, 0x80d6, 0x0080,
-	0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, 0x684c, 0xd0ac, 0x0130,
-	0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x7de6, 0x080c, 0x4809,
-	0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x00de, 0x00ee, 0x080c,
-	0x74f2, 0x0005, 0x00f6, 0x6003, 0x0003, 0x2079, 0x978c, 0x7c04,
-	0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x784c, 0xd0ac, 0x0120,
-	0x6003, 0x0002, 0x00fe, 0x0005, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e,
-	0x00fe, 0x2c10, 0x080c, 0x1c88, 0x080c, 0x605b, 0x080c, 0x651c,
-	0x0005, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20,
-	0x2c10, 0x080c, 0x16c6, 0x0005, 0xa182, 0x0040, 0x0002, 0x7cca,
-	0x7cca, 0x7cca, 0x7cca, 0x7cca, 0x7ccc, 0x7d54, 0x7cca, 0x7cca,
-	0x7d6a, 0x7dc1, 0x7cca, 0x7cca, 0x7cca, 0x7cca, 0x7dcc, 0x7cca,
-	0x7cca, 0x7cca, 0x080c, 0x13fe, 0x0076, 0x00f6, 0x00e6, 0x00d6,
-	0x2071, 0x978c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x7e46,
-	0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e,
-	0x86ff, 0x0904, 0x7d4f, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0120,
-	0x7018, 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, 0x0904, 0x7d4f,
-	0x080c, 0x147c, 0x090c, 0x13fe, 0x2d00, 0x784a, 0x7f4c, 0xc7cd,
-	0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, 0x783c, 0x683e, 0x7840,
-	0x6842, 0x6e46, 0xa68c, 0x0c00, 0x0120, 0x7318, 0x6b62, 0x731c,
-	0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0180, 0xa186, 0x0028,
-	0x1118, 0x684b, 0x001c, 0x0060, 0xd6dc, 0x0118, 0x684b, 0x0015,
-	0x0038, 0xd6d4, 0x0118, 0x684b, 0x0007, 0x0010, 0x684b, 0x0000,
-	0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, 0xa01e, 0xd6c4, 0x0160,
-	0x7328, 0x732c, 0x6b56, 0x0036, 0x2308, 0x2019, 0x9798, 0xad90,
-	0x0019, 0x080c, 0x80e6, 0x003e, 0xd6cc, 0x01c8, 0x7124, 0x695a,
-	0xa192, 0x0021, 0x1250, 0x2071, 0x9798, 0x831c, 0x2300, 0xae18,
-	0xad90, 0x001d, 0x080c, 0x80e6, 0x0050, 0x7838, 0xd0fc, 0x0120,
-	0x2009, 0x0020, 0x695a, 0x0c78, 0x2d78, 0x080c, 0x808b, 0x00de,
-	0x00ee, 0x00fe, 0x007e, 0x0005, 0x00f6, 0x6003, 0x0003, 0x2079,
-	0x978c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x7c12,
-	0x7b16, 0x7e0a, 0x7d0e, 0x00fe, 0x2c10, 0x080c, 0x1c88, 0x080c,
-	0x6f04, 0x0005, 0x00d6, 0x6003, 0x0002, 0x080c, 0x641b, 0x080c,
-	0x651c, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0904, 0x7dbf, 0xd1cc,
-	0x0540, 0x6948, 0x6838, 0xd0fc, 0x01e8, 0x0016, 0x684c, 0x0006,
-	0x6850, 0x0006, 0xad90, 0x000d, 0xa198, 0x000d, 0x2009, 0x0023,
-	0x0156, 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, 0x1f04, 0x7d8a,
-	0x015e, 0x000e, 0x6852, 0x000e, 0x684e, 0x001e, 0x2168, 0x080c,
-	0x14a3, 0x0418, 0x0016, 0x080c, 0x14a3, 0x00de, 0x080c, 0x80d6,
-	0x00e0, 0x6837, 0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002,
-	0x0180, 0xa086, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, 0xd1dc,
-	0x0118, 0x684b, 0x0015, 0x0038, 0xd1d4, 0x0118, 0x684b, 0x0007,
-	0x0010, 0x684b, 0x0000, 0x080c, 0x4809, 0x080c, 0x74f2, 0x00de,
-	0x0005, 0x2019, 0x0001, 0x080c, 0x7110, 0x6003, 0x0002, 0x080c,
-	0x641b, 0x080c, 0x651c, 0x0005, 0x080c, 0x641b, 0x080c, 0x266c,
-	0x00d6, 0x6110, 0x2168, 0x080c, 0x82ee, 0x0150, 0x6837, 0x0103,
-	0x684b, 0x0029, 0x6847, 0x0000, 0x080c, 0x4809, 0x080c, 0x848f,
-	0x00de, 0x080c, 0x74f2, 0x080c, 0x651c, 0x0005, 0x684b, 0x0015,
-	0xd1fc, 0x0138, 0x684b, 0x0007, 0x8002, 0x8000, 0x810a, 0xa189,
-	0x0000, 0x6962, 0x685e, 0x0005, 0xa182, 0x0040, 0x0002, 0x7e0a,
-	0x7e0a, 0x7e0a, 0x7e0a, 0x7e0a, 0x7e0c, 0x7e0a, 0x7eac, 0x7eb4,
-	0x7e0a, 0x7e0a, 0x7e0a, 0x7e0a, 0x7e0a, 0x7e0a, 0x7e0a, 0x7e0a,
-	0x7e0a, 0x7e0a, 0x080c, 0x13fe, 0x0076, 0x00f6, 0x00e6, 0x00d6,
-	0x2071, 0x978c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x7e46,
-	0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e,
-	0x86ff, 0x0904, 0x7e9d, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0120,
-	0x7018, 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, 0x0904, 0x7e9b,
-	0xa686, 0x0100, 0x1140, 0x2001, 0x9799, 0x2004, 0xa005, 0x1118,
-	0xc6c4, 0x7e46, 0x0c28, 0x080c, 0x147c, 0x090c, 0x13fe, 0x2d00,
-	0x784a, 0x7f4c, 0xa7bd, 0x0200, 0x7f4e, 0x6837, 0x0103, 0x7838,
-	0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00,
-	0x0120, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186,
-	0x0002, 0x0180, 0xa186, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060,
-	0xd6dc, 0x0118, 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b,
-	0x0007, 0x0010, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854,
-	0x6856, 0xa01e, 0xd6c4, 0x0160, 0x7328, 0x732c, 0x6b56, 0x0036,
-	0x2308, 0x2019, 0x9798, 0xad90, 0x0019, 0x080c, 0x80e6, 0x003e,
-	0xd6cc, 0x01c8, 0x7124, 0x695a, 0xa192, 0x0021, 0x1250, 0x2071,
-	0x9798, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0x80e6,
-	0x0050, 0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c78,
-	0x2d78, 0x080c, 0x808b, 0xd6dc, 0x1110, 0xa006, 0x0030, 0x2001,
-	0x0001, 0x2071, 0x978c, 0x7218, 0x731c, 0x080c, 0x1700, 0x00de,
-	0x00ee, 0x00fe, 0x007e, 0x0005, 0x20e1, 0x0005, 0x3d18, 0x3e20,
-	0x2c10, 0x080c, 0x16c6, 0x0005, 0x00d6, 0x6003, 0x0002, 0x6110,
-	0x2168, 0x694c, 0xd1e4, 0x0904, 0x7f3e, 0xd1cc, 0x0904, 0x7f17,
-	0x6948, 0x6838, 0xd0fc, 0x0590, 0x0016, 0x684c, 0x0006, 0x6850,
-	0x0006, 0x684c, 0xd0ac, 0x0180, 0x6810, 0x6914, 0xa115, 0x0160,
-	0x080c, 0x7de6, 0x00f6, 0x6948, 0x2178, 0x6848, 0x784a, 0x6860,
-	0x7862, 0x685c, 0x785e, 0x00fe, 0x6948, 0xad90, 0x000d, 0xa198,
+	0x080c, 0x578e, 0x002e, 0x001e, 0x000e, 0x012e, 0xe000, 0x6000,
+	0xa086, 0x0002, 0x1110, 0x0804, 0x742b, 0x080c, 0x6d55, 0x0005,
+	0x0002, 0x73de, 0x73dc, 0x73dc, 0x73dc, 0x73dc, 0x73dc, 0x73dc,
+	0x73dc, 0x73dc, 0x73dc, 0x73dc, 0x73f9, 0x73f9, 0x73f9, 0x73f9,
+	0x73dc, 0x73dc, 0x73dc, 0x73f9, 0x080c, 0x1410, 0x080c, 0x5c37,
+	0x00d6, 0x6110, 0x2168, 0x080c, 0x7b8f, 0x0168, 0x6837, 0x0103,
+	0x684b, 0x0006, 0x6847, 0x0000, 0x6850, 0xc0ec, 0x6852, 0x080c,
+	0x46a1, 0x080c, 0x7d30, 0x00de, 0x080c, 0x6d18, 0x080c, 0x5d10,
+	0x0005, 0x080c, 0x5c37, 0x080c, 0x6d18, 0x080c, 0x5d10, 0x0005,
+	0x0002, 0x7416, 0x7414, 0x7414, 0x7414, 0x7414, 0x7414, 0x7414,
+	0x7414, 0x7414, 0x7414, 0x7414, 0x7424, 0x7424, 0x7424, 0x7424,
+	0x7414, 0x7414, 0x7414, 0x7424, 0x080c, 0x1410, 0x080c, 0x5c37,
+	0x6003, 0x0002, 0x080c, 0x5d10, 0x6010, 0xa088, 0x0013, 0x2104,
+	0xa085, 0x0400, 0x200a, 0x0005, 0x080c, 0x5c37, 0x6003, 0x000f,
+	0x080c, 0x5d10, 0x0005, 0xa182, 0x0040, 0x0002, 0x7441, 0x7441,
+	0x7441, 0x7441, 0x7441, 0x7443, 0x74c5, 0x74e4, 0x7441, 0x7441,
+	0x7441, 0x7441, 0x7441, 0x7441, 0x7441, 0x7441, 0x7441, 0x7441,
+	0x7441, 0x080c, 0x1410, 0x00e6, 0x00d6, 0x2071, 0x908c, 0x6110,
+	0x2168, 0x7614, 0xa6b4, 0x0fff, 0x86ff, 0x0904, 0x74ab, 0xa68c,
+	0x0c00, 0x0120, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff,
+	0xa186, 0x0002, 0x0190, 0xa186, 0x0028, 0x1128, 0x080c, 0x7d47,
+	0x684b, 0x001c, 0x0060, 0xd6dc, 0x0118, 0x684b, 0x0015, 0x0038,
+	0xd6d4, 0x0118, 0x684b, 0x0007, 0x0010, 0x684b, 0x0000, 0x6837,
+	0x0103, 0x6e46, 0xa01e, 0xd6c4, 0x01b0, 0xa686, 0x0100, 0x1138,
+	0x2001, 0x9099, 0x2004, 0xa005, 0x1110, 0xc6c4, 0x0868, 0x7328,
+	0x732c, 0x6b56, 0x0036, 0x2308, 0x2019, 0x9098, 0xad90, 0x0019,
+	0x080c, 0x794f, 0x003e, 0xd6cc, 0x0560, 0x7124, 0x695a, 0xa192,
+	0x0021, 0x1250, 0x2071, 0x9098, 0x831c, 0x2300, 0xae18, 0xad90,
+	0x001d, 0x080c, 0x794f, 0x00e8, 0x6838, 0xd0fc, 0x0120, 0x2009,
+	0x0020, 0x695a, 0x0c78, 0x00f6, 0x2d78, 0x080c, 0x78f4, 0x00fe,
+	0x080c, 0x793f, 0x0080, 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46,
+	0x684c, 0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, 0x0110, 0x080c,
+	0x7621, 0x080c, 0x46a1, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e,
+	0x00de, 0x00ee, 0x080c, 0x6d18, 0x0005, 0x00f6, 0x6003, 0x0003,
+	0x2079, 0x908c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078,
+	0x784c, 0xd0ac, 0x0120, 0x6003, 0x0002, 0x00fe, 0x0005, 0x7c12,
+	0x7b16, 0x7e0a, 0x7d0e, 0x00fe, 0x2c10, 0x080c, 0x1bc8, 0x080c,
+	0x58ff, 0x080c, 0x5dc2, 0x0005, 0x6003, 0x0004, 0x6110, 0x20e1,
+	0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x16d1, 0x0005, 0xa182,
+	0x0040, 0x0002, 0x7505, 0x7505, 0x7505, 0x7505, 0x7505, 0x7507,
+	0x758f, 0x7505, 0x7505, 0x75a5, 0x75fc, 0x7505, 0x7505, 0x7505,
+	0x7505, 0x7607, 0x7505, 0x7505, 0x7505, 0x080c, 0x1410, 0x0076,
+	0x00f6, 0x00e6, 0x00d6, 0x2071, 0x908c, 0x6110, 0x2178, 0x7614,
+	0xa6b4, 0x0fff, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268,
+	0x6a3c, 0x8211, 0x6a3e, 0x86ff, 0x0904, 0x758a, 0xa694, 0xff00,
+	0xa284, 0x0c00, 0x0120, 0x7018, 0x7862, 0x701c, 0x785e, 0xa284,
+	0x0300, 0x0904, 0x758a, 0x080c, 0x1488, 0x090c, 0x1410, 0x2d00,
+	0x784a, 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a,
+	0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, 0x0120,
+	0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002,
+	0x0180, 0xa186, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, 0xd6dc,
+	0x0118, 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b, 0x0007,
+	0x0010, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856,
+	0xa01e, 0xd6c4, 0x0160, 0x7328, 0x732c, 0x6b56, 0x0036, 0x2308,
+	0x2019, 0x9098, 0xad90, 0x0019, 0x080c, 0x794f, 0x003e, 0xd6cc,
+	0x01c8, 0x7124, 0x695a, 0xa192, 0x0021, 0x1250, 0x2071, 0x9098,
+	0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0x794f, 0x0050,
+	0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c78, 0x2d78,
+	0x080c, 0x78f4, 0x00de, 0x00ee, 0x00fe, 0x007e, 0x0005, 0x00f6,
+	0x6003, 0x0003, 0x2079, 0x908c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08,
+	0x6010, 0x2078, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x00fe, 0x2c10,
+	0x080c, 0x1bc8, 0x080c, 0x66dd, 0x0005, 0x00d6, 0x6003, 0x0002,
+	0x080c, 0x5cc9, 0x080c, 0x5dc2, 0x6110, 0x2168, 0x694c, 0xd1e4,
+	0x0904, 0x75fa, 0xd1cc, 0x0540, 0x6948, 0x6838, 0xd0fc, 0x01e8,
+	0x0016, 0x684c, 0x0006, 0x6850, 0x0006, 0xad90, 0x000d, 0xa198,
 	0x000d, 0x2009, 0x0023, 0x0156, 0x21a8, 0x2304, 0x2012, 0x8318,
-	0x8210, 0x1f04, 0x7ee5, 0x015e, 0x000e, 0x6852, 0x000e, 0x684e,
-	0x001e, 0x2168, 0x080c, 0x14a3, 0x0804, 0x7f3c, 0x0016, 0x684c,
-	0xd0ac, 0x0190, 0x6810, 0x6914, 0xa115, 0x0170, 0x080c, 0x7de6,
-	0x00f6, 0x6948, 0x2178, 0x6848, 0x784a, 0x6860, 0x7862, 0x685c,
-	0x785e, 0x684c, 0x784e, 0x00fe, 0x6948, 0xa188, 0x0013, 0x684c,
-	0x200a, 0x080c, 0x14a3, 0x00de, 0x080c, 0x80d6, 0x0428, 0x6837,
-	0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0180, 0xa086,
-	0x0028, 0x1118, 0x684b, 0x001c, 0x00a8, 0xd1dc, 0x0118, 0x684b,
-	0x0015, 0x0080, 0xd1d4, 0x0118, 0x684b, 0x0007, 0x0058, 0x684b,
-	0x0000, 0x684c, 0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, 0x0110,
-	0x080c, 0x7de6, 0x080c, 0x4809, 0x080c, 0x74f2, 0x00de, 0x0005,
-	0x080c, 0x6389, 0x0010, 0x080c, 0x641b, 0x080c, 0x82ee, 0x0198,
-	0x00d6, 0x6110, 0x2168, 0x6837, 0x0103, 0x2009, 0x920c, 0x210c,
-	0xd18c, 0x1188, 0xd184, 0x1160, 0x6108, 0x694a, 0x6847, 0x0000,
-	0x080c, 0x4809, 0x00de, 0x080c, 0x74f2, 0x080c, 0x6462, 0x0005,
-	0x684b, 0x0004, 0x0c98, 0x684b, 0x0004, 0x0c80, 0xa182, 0x0040,
-	0x0002, 0x7f7c, 0x7f7c, 0x7f7c, 0x7f7c, 0x7f7c, 0x7f7e, 0x7f7c,
-	0x7f81, 0x7f7c, 0x7f7c, 0x7f7c, 0x7f7c, 0x7f7c, 0x7f7c, 0x7f7c,
-	0x7f7c, 0x7f7c, 0x7f7c, 0x7f7c, 0x080c, 0x13fe, 0x080c, 0x74f2,
-	0x0005, 0x0006, 0x0026, 0xa016, 0x080c, 0x16c6, 0x002e, 0x000e,
-	0x0005, 0xa182, 0x0085, 0x0002, 0x7f95, 0x7f93, 0x7f93, 0x7f93,
-	0x7f93, 0x7f93, 0x7f93, 0x080c, 0x13fe, 0x6003, 0x000b, 0x6106,
-	0x080c, 0x5ff8, 0x0126, 0x2091, 0x8000, 0x080c, 0x6462, 0x012e,
-	0x0005, 0xa186, 0x0013, 0x1160, 0x6004, 0xa08a, 0x0085, 0x0a0c,
-	0x13fe, 0xa08a, 0x008c, 0x1a0c, 0x13fe, 0xa082, 0x0085, 0x0072,
-	0xa186, 0x0027, 0x0120, 0xa186, 0x0014, 0x190c, 0x13fe, 0x080c,
-	0x6389, 0x080c, 0x849b, 0x080c, 0x6462, 0x0005, 0x7fc5, 0x7fc7,
-	0x7fc7, 0x7fc5, 0x7fc5, 0x7fc5, 0x7fc5, 0x080c, 0x13fe, 0x080c,
-	0x6389, 0x080c, 0x849b, 0x080c, 0x6462, 0x0005, 0xa186, 0x0013,
-	0x1128, 0x6004, 0xa082, 0x0085, 0x2008, 0x0492, 0xa186, 0x0027,
-	0x11e8, 0x080c, 0x6389, 0x080c, 0x266c, 0x00d6, 0x6010, 0x2068,
-	0x080c, 0x82ee, 0x0150, 0x6837, 0x0103, 0x6847, 0x0000, 0x684b,
-	0x0029, 0x080c, 0x4809, 0x080c, 0x848f, 0x00de, 0x080c, 0x74f2,
-	0x080c, 0x6462, 0x0005, 0x080c, 0x7526, 0x0ce0, 0xa186, 0x0014,
-	0x1dd0, 0x080c, 0x6389, 0x00d6, 0x6010, 0x2068, 0x080c, 0x82ee,
-	0x0d60, 0x6837, 0x0103, 0x6847, 0x0000, 0x684b, 0x0006, 0x0c08,
-	0x8011, 0x800f, 0x800f, 0x800f, 0x800f, 0x800f, 0x801a, 0x080c,
-	0x13fe, 0x080c, 0x6389, 0x6017, 0x0014, 0x6003, 0x000c, 0x080c,
-	0x6462, 0x0005, 0x080c, 0x6389, 0x6017, 0x0014, 0x6003, 0x000e,
-	0x080c, 0x6462, 0x0005, 0xa182, 0x008c, 0x1220, 0xa182, 0x0085,
-	0x0208, 0x001a, 0x080c, 0x7526, 0x0005, 0x8034, 0x8034, 0x8034,
-	0x8034, 0x8036, 0x8057, 0x8034, 0x080c, 0x13fe, 0x00d6, 0x080c,
-	0x848f, 0x080c, 0x82ee, 0x01b8, 0x6010, 0x2068, 0x6837, 0x0103,
-	0x6850, 0xd0b4, 0x0118, 0x684b, 0x0006, 0x0048, 0xd0bc, 0x0118,
-	0x684b, 0x0002, 0x0020, 0x684b, 0x0005, 0x080c, 0x852d, 0x6847,
-	0x0000, 0x080c, 0x4809, 0x080c, 0x74f2, 0x00de, 0x0005, 0x00d6,
-	0x6010, 0x2068, 0x080c, 0x82ee, 0x01b8, 0x6837, 0x0103, 0x6850,
-	0xd0b4, 0x0118, 0x684b, 0x0006, 0x0048, 0xd0bc, 0x0118, 0x684b,
-	0x0002, 0x0020, 0x684b, 0x0005, 0x080c, 0x852d, 0x6847, 0x0000,
-	0x080c, 0x4809, 0x080c, 0x848f, 0x00de, 0x080c, 0x74f2, 0x0005,
-	0xa186, 0x0013, 0x0148, 0xa186, 0x0014, 0x0130, 0xa186, 0x0027,
-	0x0118, 0x080c, 0x7526, 0x0030, 0x080c, 0x6389, 0x080c, 0x849b,
-	0x080c, 0x6462, 0x0005, 0x0056, 0x0066, 0x00d6, 0x00f6, 0x2029,
-	0x0001, 0xa182, 0x0101, 0x1208, 0x0010, 0x2009, 0x0100, 0x2130,
-	0x2069, 0x9798, 0x831c, 0x2300, 0xad18, 0x2009, 0x0020, 0xaf90,
-	0x001d, 0x080c, 0x80e6, 0xa6b2, 0x0020, 0x7804, 0xa06d, 0x0110,
-	0x080c, 0x14a3, 0x080c, 0x147c, 0x0500, 0x8528, 0x6837, 0x0110,
-	0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a, 0x003d, 0x1228, 0x2608,
-	0xad90, 0x000f, 0x0459, 0x0088, 0xa6b2, 0x003c, 0x2009, 0x003c,
-	0x2d78, 0xad90, 0x000f, 0x0411, 0x0c28, 0x00fe, 0x852f, 0xa5ad,
-	0x0003, 0x7d36, 0xa5ac, 0x0000, 0x0028, 0x00fe, 0x852f, 0xa5ad,
-	0x0003, 0x7d36, 0x00de, 0x006e, 0x005e, 0x0005, 0x00f6, 0x8dff,
-	0x0158, 0x6804, 0xa07d, 0x0130, 0x6807, 0x0000, 0x080c, 0x4809,
-	0x2f68, 0x0cb8, 0x080c, 0x4809, 0x00fe, 0x0005, 0x0156, 0xa184,
-	0x0001, 0x0108, 0x8108, 0x810c, 0x21a8, 0x2304, 0x8007, 0x2012,
-	0x8318, 0x8210, 0x1f04, 0x80ed, 0x015e, 0x0005, 0x0126, 0x2091,
-	0x8000, 0x601c, 0xa084, 0x000f, 0x0013, 0x012e, 0x0005, 0x8117,
-	0x8109, 0x8112, 0x812e, 0x8109, 0x8112, 0x810b, 0x8112, 0x8109,
-	0x5e80, 0x080c, 0x13fe, 0x0036, 0x2019, 0x0010, 0x080c, 0x8d4e,
-	0x003e, 0x0005, 0xa006, 0x0005, 0xa085, 0x0001, 0x0005, 0x00d6,
-	0x6010, 0x2068, 0x080c, 0x82ee, 0x0178, 0xa00e, 0x2001, 0x0005,
-	0x080c, 0x492c, 0x080c, 0x852d, 0x080c, 0x4809, 0x080c, 0x74f2,
-	0xa085, 0x0001, 0x00de, 0x0005, 0xa006, 0x0ce0, 0x6000, 0xa08a,
-	0x0010, 0x1a0c, 0x13fe, 0x000b, 0x0005, 0x8145, 0x8160, 0x8147,
-	0x816f, 0x815d, 0x8145, 0x8112, 0x8117, 0x8117, 0x8112, 0x8112,
-	0x8112, 0x8112, 0x8112, 0x8112, 0x8112, 0x080c, 0x13fe, 0x00d6,
-	0x6010, 0x2068, 0x080c, 0x82ee, 0x0110, 0x080c, 0x852d, 0x00de,
-	0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x5ff8,
-	0x080c, 0x6462, 0xa085, 0x0001, 0x0005, 0x080c, 0x1788, 0x0c38,
-	0x00e6, 0x2071, 0x94e5, 0x7024, 0xac06, 0x1110, 0x080c, 0x708d,
-	0x080c, 0x6fab, 0x00ee, 0x19d8, 0x080c, 0x8112, 0x0005, 0x0036,
-	0x00e6, 0x2071, 0x94e5, 0x703c, 0xac06, 0x1138, 0x2019, 0x0000,
-	0x080c, 0x7110, 0x00ee, 0x003e, 0x0850, 0x080c, 0x7366, 0x00ee,
-	0x003e, 0x1928, 0x080c, 0x8112, 0x0005, 0x00c6, 0x601c, 0xa084,
-	0x000f, 0x0013, 0x00ce, 0x0005, 0x819a, 0x81f7, 0x829a, 0x819e,
-	0x819a, 0x819a, 0x8d44, 0x74f2, 0x81f7, 0x080c, 0x84c8, 0x1110,
-	0x080c, 0x7776, 0x0005, 0x6017, 0x0001, 0x0005, 0x6000, 0xa08a,
-	0x0010, 0x1a0c, 0x13fe, 0x000b, 0x0005, 0x81b5, 0x81b7, 0x81d5,
-	0x81e7, 0x81f4, 0x81b5, 0x819a, 0x819a, 0x819a, 0x81e7, 0x81e7,
-	0x81b5, 0x81b5, 0x81b5, 0x81b5, 0x81f1, 0x080c, 0x13fe, 0x00e6,
-	0x6010, 0x2070, 0x7050, 0xc0b5, 0x7052, 0x2071, 0x94e5, 0x7024,
-	0xac06, 0x0180, 0x080c, 0x6fab, 0x6007, 0x0085, 0x6003, 0x000b,
-	0x601f, 0x0002, 0x6017, 0x0014, 0x080c, 0x5ff8, 0x080c, 0x6462,
-	0x00ee, 0x0005, 0x6017, 0x0001, 0x0cd8, 0x00d6, 0x6010, 0x2068,
-	0x6850, 0xc0b5, 0x6852, 0x00de, 0x6007, 0x0085, 0x6003, 0x000b,
-	0x601f, 0x0002, 0x080c, 0x5ff8, 0x080c, 0x6462, 0x0005, 0x00d6,
-	0x6017, 0x0001, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, 0x00de,
-	0x0005, 0x080c, 0x74f2, 0x0005, 0x080c, 0x1788, 0x08f0, 0x6000,
-	0xa08a, 0x0010, 0x1a0c, 0x13fe, 0x000b, 0x0005, 0x820e, 0x819b,
-	0x8210, 0x820e, 0x8210, 0x820e, 0x820e, 0x820e, 0x8195, 0x8195,
-	0x820e, 0x820e, 0x820e, 0x820e, 0x820e, 0x820e, 0x080c, 0x13fe,
-	0x00d6, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x00de, 0xa08a,
-	0x000c, 0x1a0c, 0x13fe, 0x000b, 0x0005, 0x8229, 0x824a, 0x8229,
-	0x824a, 0x8229, 0x824a, 0x822b, 0x8232, 0x8229, 0x824a, 0x8229,
-	0x8243, 0x080c, 0x13fe, 0x6004, 0xa08e, 0x0004, 0x01b0, 0xa08e,
-	0x0002, 0x0198, 0x6004, 0x080c, 0x84c8, 0x0904, 0x8292, 0xa08e,
-	0x0021, 0x0904, 0x8296, 0xa08e, 0x0022, 0x0904, 0x8292, 0xa08e,
-	0x003d, 0x0904, 0x8296, 0x080c, 0x266c, 0x080c, 0x7776, 0x080c,
-	0x74f2, 0x0005, 0x00c6, 0x00d6, 0x6104, 0xa186, 0x0016, 0x0598,
-	0xa186, 0x0002, 0x11f8, 0x6018, 0x2068, 0x2001, 0x9232, 0x2004,
-	0xd0ac, 0x11c0, 0x68a0, 0xd0bc, 0x11a8, 0x6840, 0xa084, 0x00ff,
-	0xa005, 0x0180, 0x8001, 0x6842, 0x6013, 0x0000, 0x601f, 0x0007,
-	0x6017, 0x0398, 0x080c, 0x749c, 0x0128, 0x2d00, 0x601a, 0x601f,
-	0x0001, 0x0088, 0x00de, 0x00ce, 0x080c, 0x7776, 0x080c, 0x266c,
-	0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x2692, 0x012e, 0x00ee,
-	0x080c, 0x74f2, 0x0005, 0x2001, 0x0002, 0x080c, 0x43e3, 0x6003,
-	0x0001, 0x6007, 0x0002, 0x080c, 0x603e, 0x080c, 0x6462, 0x00de,
-	0x00ce, 0x0c80, 0x080c, 0x7776, 0x0804, 0x8247, 0x080c, 0x7790,
-	0x0804, 0x8247, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x13fe, 0x000b,
-	0x0005, 0x82b1, 0x82b1, 0x82b1, 0x82b1, 0x82b1, 0x82b1, 0x82b1,
-	0x82b1, 0x82b1, 0x819a, 0x82b1, 0x819b, 0x82b3, 0x819b, 0x82bc,
-	0x82b1, 0x080c, 0x13fe, 0x6007, 0x008b, 0x6003, 0x000d, 0x080c,
-	0x5ff8, 0x080c, 0x6462, 0x0005, 0x080c, 0x848f, 0x0479, 0x01d8,
-	0x080c, 0x266c, 0x00d6, 0x0451, 0x0150, 0x6010, 0x2068, 0x6837,
-	0x0103, 0x684b, 0x0006, 0x6847, 0x0000, 0x080c, 0x4809, 0x00de,
-	0x601f, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x603e,
-	0x080c, 0x6462, 0x0010, 0x080c, 0x74f2, 0x0005, 0xa284, 0x0003,
-	0x1158, 0xa282, 0x9900, 0x0240, 0x2001, 0x9216, 0x2004, 0xa202,
-	0x1218, 0xa085, 0x0001, 0x0005, 0xa006, 0x0ce8, 0x0026, 0x6210,
-	0x82ff, 0x002e, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0006, 0x0126,
-	0x2091, 0x8000, 0x2061, 0x9900, 0x2071, 0x9200, 0x7344, 0x7064,
-	0xa302, 0x1290, 0x601c, 0xa206, 0x1148, 0x080c, 0x84c8, 0x1110,
-	0x080c, 0x7776, 0x00c6, 0x080c, 0x74f2, 0x00ce, 0xace0, 0x000c,
-	0x7058, 0xac02, 0x1208, 0x0c50, 0x012e, 0x000e, 0x003e, 0x00ce,
-	0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0016, 0xa188, 0x936e, 0x210c,
-	0x81ff, 0x0170, 0x2061, 0x9900, 0x2071, 0x9200, 0x0016, 0x080c,
-	0x749c, 0x001e, 0x0138, 0x611a, 0x080c, 0x266c, 0x080c, 0x74f2,
-	0xa006, 0x0010, 0xa085, 0x0001, 0x001e, 0x00ce, 0x00ee, 0x0005,
-	0x00c6, 0x0056, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x749c,
-	0x005e, 0x0170, 0x6612, 0x651a, 0x601f, 0x0003, 0x2009, 0x004b,
-	0x080c, 0x7518, 0xa085, 0x0001, 0x012e, 0x005e, 0x00ce, 0x0005,
-	0xa006, 0x0cd0, 0x00c6, 0x0056, 0x0126, 0x2091, 0x8000, 0x62a0,
-	0x00c6, 0x080c, 0x749c, 0x005e, 0x01f8, 0x6013, 0x0000, 0x651a,
-	0x601f, 0x0003, 0x00c6, 0x2560, 0x080c, 0x460d, 0x00ce, 0x080c,
-	0x6127, 0x0086, 0x2041, 0x0000, 0x080c, 0x606d, 0x2c08, 0x080c,
-	0x8ee4, 0x008e, 0x2009, 0x004c, 0x080c, 0x7518, 0xa085, 0x0001,
-	0x012e, 0x005e, 0x00ce, 0x0005, 0xa006, 0x0cd0, 0x00c6, 0x0056,
-	0x0126, 0x2091, 0x8000, 0x62a0, 0x00c6, 0x080c, 0x749c, 0x005e,
-	0x0500, 0x6612, 0x651a, 0x601f, 0x0003, 0x2019, 0x0005, 0x00c6,
-	0x2560, 0x080c, 0x460d, 0x00ce, 0x080c, 0x6127, 0x0086, 0x2041,
-	0x0000, 0x080c, 0x606d, 0x2c08, 0x080c, 0x8ee4, 0x008e, 0x2009,
-	0x004d, 0x080c, 0x7518, 0xa085, 0x0001, 0x012e, 0x005e, 0x00ce,
+	0x8210, 0x1f04, 0x75c5, 0x015e, 0x000e, 0x6852, 0x000e, 0x684e,
+	0x001e, 0x2168, 0x080c, 0x14af, 0x0418, 0x0016, 0x080c, 0x14af,
+	0x00de, 0x080c, 0x793f, 0x00e0, 0x6837, 0x0103, 0x6944, 0xa184,
+	0x00ff, 0xa0b6, 0x0002, 0x0180, 0xa086, 0x0028, 0x1118, 0x684b,
+	0x001c, 0x0060, 0xd1dc, 0x0118, 0x684b, 0x0015, 0x0038, 0xd1d4,
+	0x0118, 0x684b, 0x0007, 0x0010, 0x684b, 0x0000, 0x080c, 0x46a1,
+	0x080c, 0x6d18, 0x00de, 0x0005, 0x2019, 0x0001, 0x080c, 0x68e5,
+	0x6003, 0x0002, 0x080c, 0x5cc9, 0x080c, 0x5dc2, 0x0005, 0x080c,
+	0x5cc9, 0x080c, 0x2563, 0x00d6, 0x6110, 0x2168, 0x080c, 0x7b8f,
+	0x0150, 0x6837, 0x0103, 0x684b, 0x0029, 0x6847, 0x0000, 0x080c,
+	0x46a1, 0x080c, 0x7d30, 0x00de, 0x080c, 0x6d18, 0x080c, 0x5dc2,
+	0x0005, 0x684b, 0x0015, 0xd1fc, 0x0138, 0x684b, 0x0007, 0x8002,
+	0x8000, 0x810a, 0xa189, 0x0000, 0x6962, 0x685e, 0x0005, 0xa182,
+	0x0040, 0x0002, 0x7645, 0x7645, 0x7645, 0x7645, 0x7645, 0x7647,
+	0x7645, 0x76e7, 0x76ef, 0x7645, 0x7645, 0x7645, 0x7645, 0x7645,
+	0x7645, 0x7645, 0x7645, 0x7645, 0x7645, 0x080c, 0x1410, 0x0076,
+	0x00f6, 0x00e6, 0x00d6, 0x2071, 0x908c, 0x6110, 0x2178, 0x7614,
+	0xa6b4, 0x0fff, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268,
+	0x6a3c, 0x8211, 0x6a3e, 0x86ff, 0x0904, 0x76d8, 0xa694, 0xff00,
+	0xa284, 0x0c00, 0x0120, 0x7018, 0x7862, 0x701c, 0x785e, 0xa284,
+	0x0300, 0x0904, 0x76d6, 0xa686, 0x0100, 0x1140, 0x2001, 0x9099,
+	0x2004, 0xa005, 0x1118, 0xc6c4, 0x7e46, 0x0c28, 0x080c, 0x1488,
+	0x090c, 0x1410, 0x2d00, 0x784a, 0x7f4c, 0xa7bd, 0x0200, 0x7f4e,
+	0x6837, 0x0103, 0x7838, 0x683a, 0x783c, 0x683e, 0x7840, 0x6842,
+	0x6e46, 0xa68c, 0x0c00, 0x0120, 0x7318, 0x6b62, 0x731c, 0x6b5e,
+	0xa68c, 0x00ff, 0xa186, 0x0002, 0x0180, 0xa186, 0x0028, 0x1118,
+	0x684b, 0x001c, 0x0060, 0xd6dc, 0x0118, 0x684b, 0x0015, 0x0038,
+	0xd6d4, 0x0118, 0x684b, 0x0007, 0x0010, 0x684b, 0x0000, 0x6f4e,
+	0x7850, 0x6852, 0x7854, 0x6856, 0xa01e, 0xd6c4, 0x0160, 0x7328,
+	0x732c, 0x6b56, 0x0036, 0x2308, 0x2019, 0x9098, 0xad90, 0x0019,
+	0x080c, 0x794f, 0x003e, 0xd6cc, 0x01c8, 0x7124, 0x695a, 0xa192,
+	0x0021, 0x1250, 0x2071, 0x9098, 0x831c, 0x2300, 0xae18, 0xad90,
+	0x001d, 0x080c, 0x794f, 0x0050, 0x7838, 0xd0fc, 0x0120, 0x2009,
+	0x0020, 0x695a, 0x0c78, 0x2d78, 0x080c, 0x78f4, 0xd6dc, 0x1110,
+	0xa006, 0x0030, 0x2001, 0x0001, 0x2071, 0x908c, 0x7218, 0x731c,
+	0x080c, 0x1716, 0x00de, 0x00ee, 0x00fe, 0x007e, 0x0005, 0x20e1,
+	0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x16d1, 0x0005, 0x00d6,
+	0x6003, 0x0002, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0904, 0x778d,
+	0xd1cc, 0x0904, 0x7766, 0x6948, 0x6838, 0xd0fc, 0x0590, 0x0016,
+	0x684c, 0x0006, 0x6850, 0x0006, 0x684c, 0xd0ac, 0x0180, 0x6810,
+	0x6914, 0xa115, 0x0160, 0x080c, 0x7621, 0x00f6, 0x6948, 0x2178,
+	0x6848, 0x784a, 0x6860, 0x7862, 0x685c, 0x785e, 0x00fe, 0x6948,
+	0xad90, 0x000d, 0xa198, 0x000d, 0x2009, 0x0023, 0x0156, 0x21a8,
+	0x2304, 0x2012, 0x8318, 0x8210, 0x1f04, 0x7720, 0x015e, 0x000e,
+	0x6852, 0x000e, 0x684e, 0x001e, 0x2168, 0x080c, 0x14af, 0x0804,
+	0x778b, 0x0016, 0x00f6, 0x2178, 0x7944, 0xa184, 0x00ff, 0xa0b6,
+	0x0002, 0x01b0, 0xa086, 0x0028, 0x1128, 0x684b, 0x001c, 0x784b,
+	0x001c, 0x00b8, 0xd1dc, 0x0128, 0x684b, 0x0015, 0x784b, 0x0015,
+	0x0080, 0xd1d4, 0x0128, 0x684b, 0x0007, 0x784b, 0x0007, 0x0048,
+	0x684c, 0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, 0x0110, 0x080c,
+	0x7621, 0x6860, 0x7862, 0x685c, 0x785e, 0x684c, 0x784e, 0x00fe,
+	0x080c, 0x14af, 0x00de, 0x080c, 0x793f, 0x0428, 0x6837, 0x0103,
+	0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0180, 0xa086, 0x0028,
+	0x1118, 0x684b, 0x001c, 0x00a8, 0xd1dc, 0x0118, 0x684b, 0x0015,
+	0x0080, 0xd1d4, 0x0118, 0x684b, 0x0007, 0x0058, 0x684b, 0x0000,
+	0x684c, 0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, 0x0110, 0x080c,
+	0x7621, 0x080c, 0x46a1, 0x080c, 0x6d18, 0x00de, 0x0005, 0x080c,
+	0x5c37, 0x0010, 0x080c, 0x5cc9, 0x080c, 0x7b8f, 0x0198, 0x00d6,
+	0x6110, 0x2168, 0x6837, 0x0103, 0x2009, 0x8b0c, 0x210c, 0xd18c,
+	0x1198, 0xd184, 0x1170, 0x6108, 0x694a, 0x6847, 0x0000, 0x080c,
+	0x46a1, 0x00de, 0x080c, 0x6d18, 0x080c, 0x5d10, 0x080c, 0x5dc2,
+	0x0005, 0x684b, 0x0004, 0x0c88, 0x684b, 0x0004, 0x0c70, 0xa182,
+	0x0040, 0x0002, 0x77cd, 0x77cd, 0x77cd, 0x77cd, 0x77cd, 0x77cf,
+	0x77cd, 0x77d2, 0x77cd, 0x77cd, 0x77cd, 0x77cd, 0x77cd, 0x77cd,
+	0x77cd, 0x77cd, 0x77cd, 0x77cd, 0x77cd, 0x080c, 0x1410, 0x080c,
+	0x6d18, 0x0005, 0x0006, 0x0026, 0xa016, 0x080c, 0x16d1, 0x002e,
+	0x000e, 0x0005, 0xa182, 0x0085, 0x0002, 0x77e6, 0x77e4, 0x77e4,
+	0x77e4, 0x77e4, 0x77e4, 0x77e4, 0x080c, 0x1410, 0x6003, 0x000b,
+	0x6106, 0x080c, 0x589c, 0x0126, 0x2091, 0x8000, 0x080c, 0x5d10,
+	0x012e, 0x0005, 0xa186, 0x0013, 0x1160, 0x6004, 0xa08a, 0x0085,
+	0x0a0c, 0x1410, 0xa08a, 0x008c, 0x1a0c, 0x1410, 0xa082, 0x0085,
+	0x0072, 0xa186, 0x0027, 0x0120, 0xa186, 0x0014, 0x190c, 0x1410,
+	0x080c, 0x5c37, 0x080c, 0x7d3c, 0x080c, 0x5d10, 0x0005, 0x7816,
+	0x7818, 0x7818, 0x7816, 0x7816, 0x7816, 0x7816, 0x080c, 0x1410,
+	0x080c, 0x5c37, 0x080c, 0x7d3c, 0x080c, 0x5d10, 0x0005, 0xa186,
+	0x0013, 0x1128, 0x6004, 0xa082, 0x0085, 0x2008, 0x04aa, 0xa186,
+	0x0027, 0x11e8, 0x080c, 0x5c37, 0x080c, 0x2563, 0x00d6, 0x6010,
+	0x2068, 0x080c, 0x7b8f, 0x0150, 0x6837, 0x0103, 0x6847, 0x0000,
+	0x684b, 0x0029, 0x080c, 0x46a1, 0x080c, 0x7d30, 0x00de, 0x080c,
+	0x6d18, 0x080c, 0x5d10, 0x0005, 0x080c, 0x6d55, 0x0ce0, 0xa186,
+	0x0014, 0x1dd0, 0x080c, 0x5c37, 0x00d6, 0x6010, 0x2068, 0x080c,
+	0x7b8f, 0x0d60, 0x6837, 0x0103, 0x6847, 0x0000, 0x684b, 0x0006,
+	0x6850, 0xc0ec, 0x6852, 0x08f0, 0x7865, 0x7863, 0x7863, 0x7863,
+	0x7863, 0x7863, 0x786e, 0x080c, 0x1410, 0x080c, 0x5c37, 0x6017,
+	0x0014, 0x6003, 0x000c, 0x080c, 0x5d10, 0x0005, 0x080c, 0x5c37,
+	0x6017, 0x0014, 0x6003, 0x000e, 0x080c, 0x5d10, 0x0005, 0xa182,
+	0x008c, 0x1220, 0xa182, 0x0085, 0x0208, 0x001a, 0x080c, 0x6d55,
+	0x0005, 0x7888, 0x7888, 0x7888, 0x7888, 0x788a, 0x78ad, 0x7888,
+	0x080c, 0x1410, 0x00d6, 0x080c, 0x7d30, 0x080c, 0x7b8f, 0x01c8,
+	0x6010, 0x2068, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0128, 0x684b,
+	0x0006, 0xc0ec, 0x6852, 0x0048, 0xd0bc, 0x0118, 0x684b, 0x0002,
+	0x0020, 0x684b, 0x0005, 0x080c, 0x7dce, 0x6847, 0x0000, 0x080c,
+	0x46a1, 0x080c, 0x6d18, 0x00de, 0x0005, 0x00d6, 0x6010, 0x2068,
+	0x080c, 0x7b8f, 0x01c8, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0128,
+	0xc0ec, 0x6852, 0x684b, 0x0006, 0x0048, 0xd0bc, 0x0118, 0x684b,
+	0x0002, 0x0020, 0x684b, 0x0005, 0x080c, 0x7dce, 0x6847, 0x0000,
+	0x080c, 0x46a1, 0x080c, 0x7d30, 0x00de, 0x080c, 0x6d18, 0x0005,
+	0x0016, 0x00d6, 0x6010, 0x2068, 0x080c, 0x7b8f, 0x0140, 0x6837,
+	0x0103, 0x684b, 0x0028, 0x6847, 0x0000, 0x080c, 0x46a1, 0x00de,
+	0x001e, 0xa186, 0x0013, 0x0148, 0xa186, 0x0014, 0x0130, 0xa186,
+	0x0027, 0x0118, 0x080c, 0x6d55, 0x0030, 0x080c, 0x5c37, 0x080c,
+	0x7d3c, 0x080c, 0x5d10, 0x0005, 0x0056, 0x0066, 0x00d6, 0x00f6,
+	0x2029, 0x0001, 0xa182, 0x0101, 0x1208, 0x0010, 0x2009, 0x0100,
+	0x2130, 0x2069, 0x9098, 0x831c, 0x2300, 0xad18, 0x2009, 0x0020,
+	0xaf90, 0x001d, 0x080c, 0x794f, 0xa6b2, 0x0020, 0x7804, 0xa06d,
+	0x0110, 0x080c, 0x14af, 0x080c, 0x1488, 0x0500, 0x8528, 0x6837,
+	0x0110, 0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a, 0x003d, 0x1228,
+	0x2608, 0xad90, 0x000f, 0x0459, 0x0088, 0xa6b2, 0x003c, 0x2009,
+	0x003c, 0x2d78, 0xad90, 0x000f, 0x0411, 0x0c28, 0x00fe, 0x852f,
+	0xa5ad, 0x0003, 0x7d36, 0xa5ac, 0x0000, 0x0028, 0x00fe, 0x852f,
+	0xa5ad, 0x0003, 0x7d36, 0x00de, 0x006e, 0x005e, 0x0005, 0x00f6,
+	0x8dff, 0x0158, 0x6804, 0xa07d, 0x0130, 0x6807, 0x0000, 0x080c,
+	0x46a1, 0x2f68, 0x0cb8, 0x080c, 0x46a1, 0x00fe, 0x0005, 0x0156,
+	0xa184, 0x0001, 0x0108, 0x8108, 0x810c, 0x21a8, 0x2304, 0x8007,
+	0x2012, 0x8318, 0x8210, 0x1f04, 0x7956, 0x015e, 0x0005, 0x0126,
+	0x2091, 0x8000, 0x601c, 0xa084, 0x000f, 0x0013, 0x012e, 0x0005,
+	0x797e, 0x7970, 0x7979, 0x7995, 0x7970, 0x7979, 0x7972, 0x7979,
+	0x080c, 0x1410, 0x0036, 0x2019, 0x0010, 0x080c, 0x85f9, 0x003e,
+	0x0005, 0xa006, 0x0005, 0xa085, 0x0001, 0x0005, 0x00d6, 0x6010,
+	0x2068, 0x080c, 0x7b8f, 0x0178, 0xa00e, 0x2001, 0x0005, 0x080c,
+	0x4773, 0x080c, 0x7dce, 0x080c, 0x46a1, 0x080c, 0x6d18, 0xa085,
+	0x0001, 0x00de, 0x0005, 0xa006, 0x0ce0, 0x6000, 0xa08a, 0x0010,
+	0x1a0c, 0x1410, 0x000b, 0x0005, 0x79ac, 0x79c7, 0x79ae, 0x79d6,
+	0x79c4, 0x79ac, 0x7979, 0x797e, 0x797e, 0x7979, 0x7979, 0x7979,
+	0x7979, 0x7979, 0x7979, 0x7979, 0x080c, 0x1410, 0x00d6, 0x6010,
+	0x2068, 0x080c, 0x7b8f, 0x0110, 0x080c, 0x7dce, 0x00de, 0x6007,
+	0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x589c, 0x080c,
+	0x5d10, 0xa085, 0x0001, 0x0005, 0x080c, 0x179e, 0x0c38, 0x00e6,
+	0x2071, 0x8daa, 0x7024, 0xac06, 0x1110, 0x080c, 0x6862, 0x080c,
+	0x677e, 0x00ee, 0x19d8, 0x080c, 0x7979, 0x0005, 0x0036, 0x00e6,
+	0x2071, 0x8daa, 0x703c, 0xac06, 0x1138, 0x2019, 0x0000, 0x080c,
+	0x68e5, 0x00ee, 0x003e, 0x0850, 0x080c, 0x6b33, 0x00ee, 0x003e,
+	0x1928, 0x080c, 0x7979, 0x0005, 0x00c6, 0x601c, 0xa084, 0x000f,
+	0x0013, 0x00ce, 0x0005, 0x7a01, 0x7a62, 0x7b28, 0x7a05, 0x7a01,
+	0x7a01, 0x85ef, 0x6d18, 0x7a62, 0x080c, 0x7d69, 0x1110, 0x080c,
+	0x6fb6, 0x0005, 0x6017, 0x0001, 0x0005, 0x6010, 0xa080, 0x0019,
+	0x2c02, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1410, 0x000b, 0x0005,
+	0x7a20, 0x7a22, 0x7a40, 0x7a52, 0x7a5f, 0x7a20, 0x7a01, 0x7a01,
+	0x7a01, 0x7a52, 0x7a52, 0x7a20, 0x7a20, 0x7a20, 0x7a20, 0x7a5c,
+	0x080c, 0x1410, 0x00e6, 0x6010, 0x2070, 0x7050, 0xc0b5, 0x7052,
+	0x2071, 0x8daa, 0x7024, 0xac06, 0x0180, 0x080c, 0x677e, 0x6007,
+	0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x6017, 0x0014, 0x080c,
+	0x589c, 0x080c, 0x5d10, 0x00ee, 0x0005, 0x6017, 0x0001, 0x0cd8,
+	0x00d6, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, 0x00de, 0x6007,
+	0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x589c, 0x080c,
+	0x5d10, 0x0005, 0x00d6, 0x6017, 0x0001, 0x6010, 0x2068, 0x6850,
+	0xc0b5, 0x6852, 0x00de, 0x0005, 0x080c, 0x6d18, 0x0005, 0x080c,
+	0x179e, 0x08f0, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1410, 0x000b,
+	0x0005, 0x7a79, 0x7a02, 0x7a7b, 0x7a79, 0x7a7b, 0x7a79, 0x7a79,
+	0x7a79, 0x79fc, 0x79fc, 0x7a79, 0x7a79, 0x7a79, 0x7a79, 0x7a79,
+	0x7a79, 0x080c, 0x1410, 0x00d6, 0x6018, 0x2068, 0x6804, 0xa084,
+	0x00ff, 0x00de, 0xa08a, 0x000c, 0x1a0c, 0x1410, 0x000b, 0x0005,
+	0x7a94, 0x7ac2, 0x7a94, 0x7ac2, 0x7a94, 0x7ac2, 0x7a96, 0x7a9d,
+	0x7a94, 0x7ac2, 0x7a94, 0x7aae, 0x080c, 0x1410, 0x6004, 0xa08e,
+	0x0004, 0x0518, 0xa08e, 0x0002, 0x0500, 0x6004, 0x080c, 0x7d69,
+	0x0904, 0x7b0b, 0xa08e, 0x0021, 0x0904, 0x7b0f, 0xa08e, 0x0022,
+	0x0904, 0x7b0b, 0xa08e, 0x003d, 0x0904, 0x7b0f, 0xa08e, 0x0001,
+	0x1150, 0x00d6, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x00de,
+	0xa086, 0x0006, 0x0110, 0x080c, 0x2563, 0x080c, 0x6fb6, 0x080c,
+	0x7d3c, 0x0005, 0x00c6, 0x00d6, 0x6104, 0xa186, 0x0016, 0x05a0,
+	0xa186, 0x0002, 0x1500, 0x6018, 0x2068, 0x2001, 0x8b32, 0x2004,
+	0xd0ac, 0x1904, 0x7b13, 0x68a0, 0xd0bc, 0x15e8, 0x6840, 0xa084,
+	0x00ff, 0xa005, 0x0180, 0x8001, 0x6842, 0x6013, 0x0000, 0x601f,
+	0x0007, 0x6017, 0x0398, 0x080c, 0x6cc2, 0x0128, 0x2d00, 0x601a,
+	0x601f, 0x0001, 0x0088, 0x00de, 0x00ce, 0x080c, 0x6fb6, 0x080c,
+	0x2563, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x2589, 0x012e,
+	0x00ee, 0x080c, 0x7d3c, 0x0005, 0x2001, 0x0002, 0x080c, 0x42b9,
+	0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x58e2, 0x080c, 0x5d10,
+	0x00de, 0x00ce, 0x0c80, 0x080c, 0x6fb6, 0x0804, 0x7abf, 0x080c,
+	0x6fd3, 0x0804, 0x7abf, 0x00de, 0x00ce, 0x080c, 0x6fb6, 0x080c,
+	0x2563, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x2589, 0x6013,
+	0x0000, 0x601f, 0x0007, 0x6017, 0x0398, 0x012e, 0x00ee, 0x0005,
+	0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1410, 0x000b, 0x0005, 0x7b3f,
+	0x7b3f, 0x7b3f, 0x7b3f, 0x7b3f, 0x7b3f, 0x7b3f, 0x7b3f, 0x7b3f,
+	0x7a01, 0x7b3f, 0x7a02, 0x7b41, 0x7a02, 0x7b4a, 0x7b3f, 0x080c,
+	0x1410, 0x6007, 0x008b, 0x6003, 0x000d, 0x080c, 0x589c, 0x080c,
+	0x5d10, 0x0005, 0x080c, 0x7d30, 0x080c, 0x7b8f, 0x0568, 0x080c,
+	0x2563, 0x00d6, 0x04e1, 0x0168, 0x6010, 0x2068, 0x6837, 0x0103,
+	0x684b, 0x0006, 0x6847, 0x0000, 0x6850, 0xc0ed, 0x6852, 0x080c,
+	0x46a1, 0x2c68, 0x080c, 0x6cc2, 0x0140, 0x6818, 0x601a, 0x00c6,
+	0x2d60, 0x080c, 0x7d3c, 0x00ce, 0x0008, 0x2d60, 0x00de, 0x6013,
+	0x0000, 0x601f, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c,
+	0x58e2, 0x080c, 0x5d10, 0x0010, 0x080c, 0x7d3c, 0x0005, 0xa284,
+	0x0003, 0x1158, 0xa282, 0x9200, 0x0240, 0x2001, 0x8b16, 0x2004,
+	0xa202, 0x1218, 0xa085, 0x0001, 0x0005, 0xa006, 0x0ce8, 0x0026,
+	0x6210, 0x82ff, 0x002e, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0006,
+	0x0126, 0x2091, 0x8000, 0x2061, 0x9200, 0x2071, 0x8b00, 0x7344,
+	0x7064, 0xa302, 0x1290, 0x601c, 0xa206, 0x1148, 0x080c, 0x7d69,
+	0x1110, 0x080c, 0x6fb6, 0x00c6, 0x080c, 0x6d18, 0x00ce, 0xace0,
+	0x000c, 0x7058, 0xac02, 0x1208, 0x0c50, 0x012e, 0x000e, 0x003e,
+	0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0016, 0xa188, 0x8c34,
+	0x210c, 0x81ff, 0x0170, 0x2061, 0x9200, 0x2071, 0x8b00, 0x0016,
+	0x080c, 0x6cc2, 0x001e, 0x0138, 0x611a, 0x080c, 0x2563, 0x080c,
+	0x6d18, 0xa006, 0x0010, 0xa085, 0x0001, 0x001e, 0x00ce, 0x00ee,
+	0x0005, 0x00c6, 0x0056, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c,
+	0x6cc2, 0x005e, 0x0170, 0x6612, 0x651a, 0x601f, 0x0003, 0x2009,
+	0x004b, 0x080c, 0x6d3f, 0xa085, 0x0001, 0x012e, 0x005e, 0x00ce,
 	0x0005, 0xa006, 0x0cd0, 0x00c6, 0x0056, 0x0126, 0x2091, 0x8000,
-	0x62a0, 0x00c6, 0x080c, 0x749c, 0x005e, 0x0500, 0x6612, 0x651a,
-	0x601f, 0x0003, 0x2019, 0x0005, 0x00c6, 0x2560, 0x080c, 0x460d,
-	0x00ce, 0x080c, 0x6127, 0x0086, 0x2041, 0x0000, 0x080c, 0x606d,
-	0x2c08, 0x080c, 0x8ee4, 0x008e, 0x2009, 0x004e, 0x080c, 0x7518,
-	0xa085, 0x0001, 0x012e, 0x005e, 0x00ce, 0x0005, 0xa006, 0x0cd0,
-	0x00c6, 0x0096, 0x0086, 0x0056, 0x0126, 0x2091, 0x8000, 0x62a0,
-	0x00c6, 0x080c, 0x749c, 0x005e, 0x0904, 0x8426, 0x6612, 0x651a,
-	0x601f, 0x0003, 0x00c6, 0x2560, 0x080c, 0x45af, 0x0118, 0x2001,
-	0x83ec, 0x0028, 0x080c, 0x4581, 0x0160, 0x2001, 0x83f2, 0x0006,
-	0xa00e, 0x2001, 0x0004, 0x080c, 0x492c, 0x080c, 0x4809, 0x000e,
-	0x0807, 0x2019, 0x0004, 0x080c, 0x632b, 0x0036, 0x003e, 0x00ce,
-	0x2041, 0x0001, 0x2608, 0x080c, 0x6140, 0x080c, 0x606d, 0x2c08,
-	0x2648, 0x080c, 0x8ee4, 0x6018, 0xa080, 0x000f, 0x200c, 0x81ff,
-	0x090c, 0x61d3, 0x2009, 0x0052, 0x080c, 0x7518, 0xa085, 0x0001,
-	0x012e, 0x005e, 0x008e, 0x009e, 0x00ce, 0x0005, 0xa006, 0x0cc0,
-	0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x749c, 0x001e,
-	0x0178, 0x660a, 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009,
-	0x001f, 0x080c, 0x7518, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005,
-	0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c,
-	0x749c, 0x001e, 0x0178, 0x660a, 0x611a, 0x601f, 0x0008, 0x2d00,
-	0x6012, 0x2009, 0x0021, 0x080c, 0x7518, 0xa085, 0x0001, 0x012e,
-	0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000,
-	0x00c6, 0x080c, 0x749c, 0x001e, 0x0178, 0x660a, 0x611a, 0x601f,
-	0x0001, 0x2d00, 0x6012, 0x2009, 0x003d, 0x080c, 0x7518, 0xa085,
-	0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126,
-	0x2091, 0x8000, 0x00c6, 0x080c, 0x749c, 0x001e, 0x0170, 0x611a,
-	0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0000, 0x080c, 0x7518,
-	0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x0026,
-	0x00d6, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e,
-	0x00de, 0x002e, 0x0005, 0x0006, 0x6013, 0x0000, 0x601f, 0x0007,
-	0x2001, 0x94dd, 0x2004, 0x6016, 0x000e, 0x0005, 0x0066, 0x00c6,
-	0x00d6, 0x2031, 0x9252, 0x2634, 0xd6e4, 0x0128, 0x6618, 0x2660,
-	0x6e48, 0x080c, 0x453a, 0x00de, 0x00ce, 0x006e, 0x0005, 0x0006,
-	0x0016, 0x6004, 0xa08e, 0x0002, 0x0140, 0xa08e, 0x0003, 0x0128,
-	0xa08e, 0x0004, 0x0110, 0xa085, 0x0001, 0x001e, 0x000e, 0x0005,
-	0x0006, 0x00d6, 0x6010, 0xa06d, 0x0128, 0x6838, 0xd0fc, 0x0110,
-	0xa006, 0x0010, 0xa085, 0x0001, 0x00de, 0x000e, 0x0005, 0x00c6,
-	0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x749c, 0x001e, 0x0180,
-	0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x080c, 0x266c, 0x2009,
-	0x0028, 0x080c, 0x7518, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005,
-	0xa006, 0x0cd8, 0xa186, 0x0015, 0x1178, 0x2011, 0x9220, 0x2204,
-	0xa086, 0x0074, 0x1148, 0x080c, 0x7a64, 0x6003, 0x0001, 0x6007,
-	0x0029, 0x080c, 0x603e, 0x0020, 0x080c, 0x7776, 0x080c, 0x74f2,
-	0x0005, 0xa186, 0x0015, 0x11b0, 0x2011, 0x9220, 0x2204, 0xa086,
-	0x0014, 0x1180, 0x00d6, 0x6018, 0x2068, 0x080c, 0x44c7, 0x00de,
-	0x080c, 0x7a6e, 0x1138, 0x2001, 0x0006, 0x080c, 0x43e3, 0x080c,
-	0x7598, 0x0020, 0x080c, 0x7776, 0x080c, 0x74f2, 0x0005, 0x6848,
-	0xa086, 0x0005, 0x1108, 0x0009, 0x0005, 0x6850, 0xc0ad, 0x6852,
-	0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x2001, 0x94d9, 0x200c,
-	0x8000, 0x2014, 0x2001, 0x0064, 0x080c, 0x5eaf, 0x2001, 0x94dd,
-	0x82ff, 0x1110, 0x2011, 0x0002, 0x2202, 0x003e, 0x002e, 0x001e,
-	0x000e, 0x0005, 0x0006, 0x2001, 0x94dd, 0x2003, 0x0028, 0x2001,
-	0x94de, 0x2003, 0x07d0, 0x000e, 0x0005, 0x0066, 0x6000, 0xa0b2,
-	0x0010, 0x1a0c, 0x13fe, 0x0013, 0x006e, 0x0005, 0x856e, 0x881c,
-	0x8907, 0x856e, 0x856e, 0x856e, 0x856e, 0x856e, 0x85a6, 0x8973,
-	0x856e, 0x856e, 0x856e, 0x856e, 0x856e, 0x856e, 0x080c, 0x13fe,
-	0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x13fe, 0x0013, 0x006e,
-	0x0005, 0x8589, 0x8ce9, 0x8589, 0x8589, 0x8589, 0x8589, 0x8589,
-	0x8589, 0x8cad, 0x8d31, 0x8589, 0x9105, 0x9135, 0x9105, 0x9135,
-	0x8589, 0x080c, 0x13fe, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c,
-	0x13fe, 0x0013, 0x006e, 0x0005, 0x85a4, 0x8ab9, 0x8b64, 0x8b88,
-	0x8bd3, 0x85a4, 0x85a4, 0x8c44, 0x897f, 0x8c87, 0x8c9a, 0x85a4,
-	0x85a4, 0x85a4, 0x85a4, 0x85a4, 0x080c, 0x13fe, 0xa1b2, 0x003e,
-	0x1a0c, 0x13fe, 0x2100, 0x0002, 0x85df, 0x86f0, 0x85df, 0x85df,
-	0x85df, 0x86f7, 0x85df, 0x85df, 0x85df, 0x85df, 0x85df, 0x85df,
-	0x85df, 0x85df, 0x85df, 0x85df, 0x85df, 0x85df, 0x85df, 0x85df,
-	0x85df, 0x85df, 0x85df, 0x85e1, 0x860b, 0x8616, 0x865a, 0x8674,
-	0x86aa, 0x86dd, 0x85df, 0x85df, 0x86fa, 0x85df, 0x85df, 0x8709,
-	0x8710, 0x85df, 0x85df, 0x85df, 0x85df, 0x85df, 0x87ab, 0x85df,
-	0x85df, 0x87b5, 0x85df, 0x85df, 0x875d, 0x85df, 0x85df, 0x080c,
-	0x13fe, 0x080c, 0x470e, 0x6618, 0x00c6, 0x2660, 0x080c, 0x4443,
-	0x00ce, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006,
-	0x0278, 0x080c, 0x8e28, 0x1904, 0x8654, 0x080c, 0x8dd3, 0x1120,
-	0x6007, 0x0008, 0x0804, 0x86eb, 0x6007, 0x0009, 0x0804, 0x86eb,
-	0x080c, 0x8fa4, 0x0128, 0x080c, 0x8e28, 0x0d78, 0x0804, 0x8654,
-	0x6013, 0x1900, 0x0c88, 0x6106, 0x080c, 0x8d83, 0x6007, 0x0006,
-	0x0804, 0x86eb, 0x6007, 0x0007, 0x0804, 0x86eb, 0x080c, 0x9150,
-	0x1904, 0x87c6, 0x00d6, 0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00,
-	0x8637, 0xa686, 0x0006, 0x01a0, 0xa686, 0x0004, 0x0188, 0x080c,
-	0x4dc5, 0x1160, 0x6e04, 0xa6b4, 0x00ff, 0xa686, 0x0006, 0x0140,
-	0xa686, 0x0004, 0x0128, 0xa686, 0x0005, 0x0110, 0x00de, 0x00e0,
-	0x080c, 0x8e86, 0x11a0, 0xa686, 0x0006, 0x1150, 0x0026, 0x6218,
-	0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, 0x26b1, 0x002e,
-	0x080c, 0x44c7, 0x6007, 0x000a, 0x00de, 0x0804, 0x86eb, 0x6007,
-	0x000b, 0x00de, 0x0804, 0x86eb, 0x080c, 0x266c, 0x6007, 0x0001,
-	0x0804, 0x86eb, 0x080c, 0x9150, 0x1904, 0x87c6, 0x6618, 0x00d6,
-	0x2668, 0x6e04, 0x00de, 0xa686, 0x0707, 0x0d70, 0x0026, 0x6218,
-	0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, 0x26b1, 0x002e,
-	0x6007, 0x000c, 0x0804, 0x86eb, 0x080c, 0x470e, 0x6618, 0xa6b0,
-	0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x02b0, 0xa6b4,
-	0xff00, 0x8637, 0xa686, 0x0004, 0x0118, 0xa686, 0x0006, 0x1960,
-	0x080c, 0x8e93, 0x1120, 0x6007, 0x000e, 0x0804, 0x86eb, 0x080c,
-	0x266c, 0x6007, 0x000f, 0x0804, 0x86eb, 0x080c, 0x8fa4, 0x0160,
-	0xa6b4, 0xff00, 0x8637, 0xa682, 0x0004, 0x0a04, 0x8654, 0xa682,
-	0x0007, 0x0e30, 0x0804, 0x8654, 0x6013, 0x1900, 0x6007, 0x0009,
-	0x0804, 0x86eb, 0x080c, 0x470e, 0x6618, 0xa6b0, 0x0001, 0x2634,
-	0xa684, 0x00ff, 0xa082, 0x0006, 0x02c0, 0xa6b4, 0xff00, 0x8637,
-	0xa686, 0x0004, 0x0120, 0xa686, 0x0006, 0x1904, 0x8654, 0x080c,
-	0x8ebb, 0x1130, 0x080c, 0x8dd3, 0x1118, 0x6007, 0x0010, 0x0418,
-	0x080c, 0x266c, 0x6007, 0x0011, 0x00f0, 0x080c, 0x8fa4, 0x0140,
-	0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0d48, 0x0804, 0x8654,
-	0x6013, 0x1900, 0x6007, 0x0009, 0x0070, 0x7030, 0xa086, 0x6000,
-	0x0140, 0x080c, 0x9150, 0x1904, 0x87c6, 0x080c, 0x87c9, 0x1904,
-	0x8654, 0x6007, 0x0012, 0x6003, 0x0001, 0x080c, 0x603e, 0x0005,
-	0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x603e, 0x0cc0, 0x6007,
-	0x0005, 0x0cc0, 0x080c, 0x9150, 0x1904, 0x87c6, 0x080c, 0x87c9,
-	0x1904, 0x8654, 0x6007, 0x0020, 0x6003, 0x0001, 0x080c, 0x603e,
-	0x0005, 0x6007, 0x0023, 0x6003, 0x0001, 0x080c, 0x603e, 0x0005,
-	0x080c, 0x9150, 0x1904, 0x87c6, 0x080c, 0x87c9, 0x1904, 0x8654,
-	0x0016, 0x0026, 0x2011, 0x9791, 0x2214, 0xa286, 0xffff, 0x0190,
-	0x2c08, 0x080c, 0x82de, 0x01d8, 0x2260, 0x2011, 0x9790, 0x2214,
-	0x6008, 0xa206, 0x11a0, 0x6018, 0xa190, 0x0006, 0x2214, 0xa206,
-	0x01e0, 0x0068, 0x2011, 0x9790, 0x2214, 0x2c08, 0x080c, 0x90ab,
-	0x11a0, 0x2011, 0x9791, 0x2214, 0xa286, 0xffff, 0x01a0, 0x2160,
-	0x6007, 0x0026, 0x6013, 0x1700, 0x2011, 0x9789, 0x2214, 0xa296,
-	0xffff, 0x1160, 0x6007, 0x0025, 0x0048, 0x601c, 0xa086, 0x0007,
-	0x1d70, 0x080c, 0x74f2, 0x2160, 0x6007, 0x0025, 0x6003, 0x0001,
-	0x080c, 0x603e, 0x002e, 0x001e, 0x0005, 0x2001, 0x0001, 0x080c,
-	0x43d1, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019,
-	0x9205, 0x2011, 0x9796, 0x080c, 0x7aee, 0x003e, 0x002e, 0x001e,
-	0x015e, 0x0120, 0x6007, 0x0031, 0x0804, 0x86eb, 0x080c, 0x7910,
-	0x080c, 0x4dc5, 0x1578, 0x0006, 0x0026, 0x0036, 0x2011, 0x9223,
-	0x2204, 0x8000, 0x2012, 0xa084, 0x0007, 0x0190, 0x2001, 0x94d7,
-	0x2003, 0xaaaa, 0x2001, 0x94d8, 0x2003, 0x0001, 0x2001, 0x9200,
-	0x2003, 0x0001, 0x080c, 0x4d10, 0x003e, 0x002e, 0x000e, 0x0005,
-	0x2001, 0x0001, 0x080c, 0x23ba, 0x080c, 0x4dd7, 0x1110, 0x080c,
-	0x4d9a, 0x2011, 0x8036, 0x2019, 0x0005, 0x080c, 0x3698, 0x003e,
-	0x002e, 0x000e, 0x0005, 0x6106, 0x0479, 0x6007, 0x002b, 0x0804,
-	0x86eb, 0x6007, 0x002c, 0x0804, 0x86eb, 0x080c, 0x9150, 0x1170,
-	0x0081, 0x1904, 0x8654, 0x6106, 0x0419, 0x1120, 0x6007, 0x002e,
-	0x0804, 0x86eb, 0x6007, 0x002f, 0x0804, 0x86eb, 0x080c, 0x74f2,
-	0x0005, 0x00d6, 0x0066, 0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00,
-	0x8637, 0xa686, 0x0006, 0x0128, 0xa686, 0x0004, 0x0110, 0xa085,
-	0x0001, 0x006e, 0x00de, 0x0005, 0x00d6, 0x0439, 0x00de, 0x0005,
-	0x00d6, 0x0481, 0x11e0, 0x680c, 0xa08c, 0xff00, 0x6824, 0xa084,
-	0x00ff, 0xa115, 0x6212, 0xd1e4, 0x0118, 0x2009, 0x0001, 0x0060,
-	0xd1ec, 0x0168, 0x6920, 0xa18c, 0x00ff, 0x6824, 0x080c, 0x240b,
-	0x1130, 0x2110, 0x2009, 0x0000, 0x080c, 0x26b1, 0x0018, 0xa085,
-	0x0001, 0x0008, 0xa006, 0x00de, 0x0005, 0x2069, 0x978d, 0x6800,
-	0xa082, 0x0010, 0x1228, 0x6013, 0x0000, 0xa085, 0x0001, 0x0008,
-	0xa006, 0x0005, 0x6013, 0x0000, 0x2069, 0x978c, 0x6808, 0xa084,
-	0xff00, 0xa086, 0x0800, 0x0005, 0x6004, 0xa0b2, 0x003e, 0x1a0c,
-	0x13fe, 0xa1b6, 0x0013, 0x1110, 0x2008, 0x0092, 0xa1b6, 0x0027,
-	0x0120, 0xa1b6, 0x0014, 0x190c, 0x13fe, 0x2001, 0x0007, 0x080c,
-	0x43f1, 0x080c, 0x6389, 0x080c, 0x849b, 0x080c, 0x6462, 0x0005,
-	0x8875, 0x8877, 0x8875, 0x8875, 0x8875, 0x8877, 0x8885, 0x88e7,
-	0x88b2, 0x88e7, 0x88c3, 0x88e7, 0x8885, 0x88e7, 0x88df, 0x88e7,
-	0x88df, 0x88e7, 0x88e7, 0x8875, 0x8875, 0x8875, 0x8875, 0x8875,
-	0x8875, 0x8875, 0x8875, 0x8875, 0x8875, 0x8875, 0x8875, 0x8875,
-	0x88e7, 0x8875, 0x8875, 0x88e7, 0x8875, 0x88e7, 0x88e7, 0x8875,
-	0x8875, 0x8875, 0x8875, 0x88e7, 0x88e7, 0x8875, 0x88e7, 0x88e7,
-	0x8875, 0x887f, 0x8875, 0x8875, 0x8875, 0x8875, 0x8875, 0x8875,
-	0x8875, 0x8875, 0x8875, 0x8875, 0x8875, 0x080c, 0x13fe, 0x080c,
-	0x6389, 0x6003, 0x0002, 0x080c, 0x6462, 0x0804, 0x88ed, 0x2001,
-	0x0000, 0x080c, 0x43d1, 0x0804, 0x88e7, 0x00f6, 0x2079, 0x9251,
-	0x7804, 0x00fe, 0xd0ac, 0x1904, 0x88e7, 0x2001, 0x0000, 0x080c,
-	0x43d1, 0x6018, 0xa080, 0x0004, 0x2004, 0xa086, 0x00ff, 0x0904,
-	0x88e7, 0x2001, 0x0002, 0x080c, 0x43e3, 0x080c, 0x6389, 0x601f,
-	0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x603e, 0x080c,
-	0x6462, 0x00c6, 0x6118, 0x2160, 0x2009, 0x0001, 0x080c, 0x573d,
-	0x00ce, 0x04d8, 0x6618, 0x00d6, 0x2668, 0x6e04, 0x00de, 0xa6b4,
-	0xff00, 0x8637, 0xa686, 0x0006, 0x0550, 0xa686, 0x0004, 0x0538,
-	0x2001, 0x0004, 0x0410, 0x2001, 0x9200, 0x2004, 0xa086, 0x0003,
-	0x1110, 0x080c, 0x370a, 0x2001, 0x0006, 0x0401, 0x6618, 0x00d6,
+	0x62a0, 0x00c6, 0x080c, 0x6cc2, 0x005e, 0x01f8, 0x6013, 0x0000,
+	0x651a, 0x601f, 0x0003, 0x00c6, 0x2560, 0x080c, 0x44e6, 0x00ce,
+	0x080c, 0x59d5, 0x0086, 0x2041, 0x0000, 0x080c, 0x5911, 0x2c08,
+	0x080c, 0x878f, 0x008e, 0x2009, 0x004c, 0x080c, 0x6d3f, 0xa085,
+	0x0001, 0x012e, 0x005e, 0x00ce, 0x0005, 0xa006, 0x0cd0, 0x00c6,
+	0x0056, 0x0126, 0x2091, 0x8000, 0x62a0, 0x00c6, 0x080c, 0x6cc2,
+	0x005e, 0x0500, 0x6612, 0x651a, 0x601f, 0x0003, 0x2019, 0x0005,
+	0x00c6, 0x2560, 0x080c, 0x44e6, 0x00ce, 0x080c, 0x59d5, 0x0086,
+	0x2041, 0x0000, 0x080c, 0x5911, 0x2c08, 0x080c, 0x878f, 0x008e,
+	0x2009, 0x004d, 0x080c, 0x6d3f, 0xa085, 0x0001, 0x012e, 0x005e,
+	0x00ce, 0x0005, 0xa006, 0x0cd0, 0x00c6, 0x0056, 0x0126, 0x2091,
+	0x8000, 0x62a0, 0x00c6, 0x080c, 0x6cc2, 0x005e, 0x0500, 0x6612,
+	0x651a, 0x601f, 0x0003, 0x2019, 0x0005, 0x00c6, 0x2560, 0x080c,
+	0x44e6, 0x00ce, 0x080c, 0x59d5, 0x0086, 0x2041, 0x0000, 0x080c,
+	0x5911, 0x2c08, 0x080c, 0x878f, 0x008e, 0x2009, 0x004e, 0x080c,
+	0x6d3f, 0xa085, 0x0001, 0x012e, 0x005e, 0x00ce, 0x0005, 0xa006,
+	0x0cd0, 0x00c6, 0x0096, 0x0086, 0x0056, 0x0126, 0x2091, 0x8000,
+	0x62a0, 0x00c6, 0x080c, 0x6cc2, 0x005e, 0x0904, 0x7cc7, 0x6612,
+	0x651a, 0x601f, 0x0003, 0x00c6, 0x2560, 0x080c, 0x4488, 0x0118,
+	0x2001, 0x7c8d, 0x0028, 0x080c, 0x445a, 0x0160, 0x2001, 0x7c93,
+	0x0006, 0xa00e, 0x2001, 0x0004, 0x080c, 0x4773, 0x080c, 0x46a1,
+	0x000e, 0x0807, 0x2019, 0x0004, 0x080c, 0x5bd9, 0x0036, 0x003e,
+	0x00ce, 0x2041, 0x0001, 0x2608, 0x080c, 0x59ee, 0x080c, 0x5911,
+	0x2c08, 0x2648, 0x080c, 0x878f, 0x6018, 0xa080, 0x000f, 0x200c,
+	0x81ff, 0x090c, 0x5a81, 0x2009, 0x0052, 0x080c, 0x6d3f, 0xa085,
+	0x0001, 0x012e, 0x005e, 0x008e, 0x009e, 0x00ce, 0x0005, 0xa006,
+	0x0cc0, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x6cc2,
+	0x001e, 0x0178, 0x660a, 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012,
+	0x2009, 0x001f, 0x080c, 0x6d3f, 0xa085, 0x0001, 0x012e, 0x00ce,
+	0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6,
+	0x080c, 0x6cc2, 0x001e, 0x0178, 0x660a, 0x611a, 0x601f, 0x0008,
+	0x2d00, 0x6012, 0x2009, 0x0021, 0x080c, 0x6d3f, 0xa085, 0x0001,
+	0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091,
+	0x8000, 0x00c6, 0x080c, 0x6cc2, 0x001e, 0x0178, 0x660a, 0x611a,
+	0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x003d, 0x080c, 0x6d3f,
+	0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6,
+	0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x6cc2, 0x001e, 0x0170,
+	0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0000, 0x080c,
+	0x6d3f, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8,
+	0x0026, 0x00d6, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211,
+	0x6a3e, 0x00de, 0x002e, 0x0005, 0x0006, 0x6013, 0x0000, 0x601f,
+	0x0007, 0x2001, 0x8da2, 0x2004, 0x6016, 0x000e, 0x0005, 0x0066,
+	0x00c6, 0x00d6, 0x2031, 0x8b52, 0x2634, 0xd6e4, 0x0128, 0x6618,
+	0x2660, 0x6e48, 0x080c, 0x4413, 0x00de, 0x00ce, 0x006e, 0x0005,
+	0x0006, 0x0016, 0x6004, 0xa08e, 0x0002, 0x0140, 0xa08e, 0x0003,
+	0x0128, 0xa08e, 0x0004, 0x0110, 0xa085, 0x0001, 0x001e, 0x000e,
+	0x0005, 0x0006, 0x00d6, 0x6010, 0xa06d, 0x0128, 0x6838, 0xd0fc,
+	0x0110, 0xa006, 0x0010, 0xa085, 0x0001, 0x00de, 0x000e, 0x0005,
+	0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x6cc2, 0x001e,
+	0x0180, 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x080c, 0x2563,
+	0x2009, 0x0028, 0x080c, 0x6d3f, 0xa085, 0x0001, 0x012e, 0x00ce,
+	0x0005, 0xa006, 0x0cd8, 0xa186, 0x0015, 0x1178, 0x2011, 0x8b20,
+	0x2204, 0xa086, 0x0074, 0x1148, 0x080c, 0x72a4, 0x6003, 0x0001,
+	0x6007, 0x0029, 0x080c, 0x58e2, 0x0020, 0x080c, 0x6fb6, 0x080c,
+	0x6d18, 0x0005, 0xa186, 0x0015, 0x11b0, 0x2011, 0x8b20, 0x2204,
+	0xa086, 0x0014, 0x1180, 0x00d6, 0x6018, 0x2068, 0x080c, 0x43a0,
+	0x00de, 0x080c, 0x72ae, 0x1138, 0x2001, 0x0006, 0x080c, 0x42b9,
+	0x080c, 0x6dc7, 0x0020, 0x080c, 0x6fb6, 0x080c, 0x6d18, 0x0005,
+	0x6848, 0xa086, 0x0005, 0x1108, 0x0009, 0x0005, 0x6850, 0xc0ad,
+	0x6852, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x2001, 0x8d9e,
+	0x200c, 0x8000, 0x2014, 0x2001, 0x0064, 0x080c, 0x575a, 0x2001,
+	0x8da2, 0x82ff, 0x1110, 0x2011, 0x0002, 0x2202, 0x003e, 0x002e,
+	0x001e, 0x000e, 0x0005, 0x0006, 0x2001, 0x8da2, 0x2003, 0x0028,
+	0x2001, 0x8da3, 0x2003, 0x07d0, 0x000e, 0x0005, 0x00d6, 0x6024,
+	0xa06d, 0x0110, 0x080c, 0x149f, 0x00de, 0x0005, 0x0066, 0x6000,
+	0xa0b2, 0x0010, 0x1a0c, 0x1410, 0x0013, 0x006e, 0x0005, 0x7e17,
+	0x80cf, 0x81c5, 0x7e17, 0x7e17, 0x7e17, 0x7e17, 0x7e17, 0x7e4f,
+	0x8231, 0x7e17, 0x7e17, 0x7e17, 0x7e17, 0x7e17, 0x7e17, 0x080c,
+	0x1410, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x1410, 0x0013,
+	0x006e, 0x0005, 0x7e32, 0x8594, 0x7e32, 0x7e32, 0x7e32, 0x7e32,
+	0x7e32, 0x7e32, 0x8558, 0x85dc, 0x7e32, 0x89b0, 0x89e0, 0x89b0,
+	0x89e0, 0x7e32, 0x080c, 0x1410, 0x0066, 0x6000, 0xa0b2, 0x0010,
+	0x1a0c, 0x1410, 0x0013, 0x006e, 0x0005, 0x7e4d, 0x8364, 0x840f,
+	0x8433, 0x847e, 0x7e4d, 0x7e4d, 0x84ef, 0x823d, 0x8532, 0x8545,
+	0x7e4d, 0x7e4d, 0x7e4d, 0x7e4d, 0x7e4d, 0x080c, 0x1410, 0xa1b2,
+	0x0040, 0x1a0c, 0x1410, 0x2100, 0x0002, 0x7e98, 0x7fa9, 0x7e98,
+	0x7e98, 0x7e98, 0x7fb0, 0x7e98, 0x7e98, 0x7e98, 0x7e98, 0x7e98,
+	0x7e98, 0x7e98, 0x7e98, 0x7e98, 0x7e98, 0x7e98, 0x7e98, 0x7e98,
+	0x7e98, 0x7e98, 0x7e98, 0x7e98, 0x7e9a, 0x7ec4, 0x7ecf, 0x7f13,
+	0x7f2d, 0x7f63, 0x7f96, 0x7e98, 0x7e98, 0x7fb3, 0x7e98, 0x7e98,
+	0x7fc2, 0x7fc9, 0x7e98, 0x7e98, 0x7e98, 0x7e98, 0x7e98, 0x805e,
+	0x7e98, 0x7e98, 0x8068, 0x7e98, 0x7e98, 0x8016, 0x7e98, 0x7e98,
+	0x7e98, 0x7e98, 0x7e98, 0x7e98, 0x7e98, 0x7e98, 0x7e98, 0x7e98,
+	0x7e98, 0x7e98, 0x7e98, 0x7e98, 0x7e98, 0x7e98, 0x7e98, 0x7e98,
+	0x080c, 0x1410, 0x080c, 0x45e7, 0x6618, 0x00c6, 0x2660, 0x080c,
+	0x4319, 0x00ce, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082,
+	0x0006, 0x0278, 0x080c, 0x86d3, 0x1904, 0x7f0d, 0x080c, 0x867e,
+	0x1120, 0x6007, 0x0008, 0x0804, 0x7fa4, 0x6007, 0x0009, 0x0804,
+	0x7fa4, 0x080c, 0x884f, 0x0128, 0x080c, 0x86d3, 0x0d78, 0x0804,
+	0x7f0d, 0x6013, 0x1900, 0x0c88, 0x6106, 0x080c, 0x862e, 0x6007,
+	0x0006, 0x0804, 0x7fa4, 0x6007, 0x0007, 0x0804, 0x7fa4, 0x080c,
+	0x89fb, 0x1904, 0x8079, 0x00d6, 0x6618, 0x2668, 0x6e04, 0xa6b4,
+	0xff00, 0x8637, 0xa686, 0x0006, 0x01a0, 0xa686, 0x0004, 0x0188,
+	0x080c, 0x4c42, 0x1160, 0x6e04, 0xa6b4, 0x00ff, 0xa686, 0x0006,
+	0x0140, 0xa686, 0x0004, 0x0128, 0xa686, 0x0005, 0x0110, 0x00de,
+	0x00e0, 0x080c, 0x8731, 0x11a0, 0xa686, 0x0006, 0x1150, 0x0026,
+	0x6218, 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, 0x25a8,
+	0x002e, 0x080c, 0x43a0, 0x6007, 0x000a, 0x00de, 0x0804, 0x7fa4,
+	0x6007, 0x000b, 0x00de, 0x0804, 0x7fa4, 0x080c, 0x2563, 0x6007,
+	0x0001, 0x0804, 0x7fa4, 0x080c, 0x89fb, 0x1904, 0x8079, 0x6618,
+	0x00d6, 0x2668, 0x6e04, 0x00de, 0xa686, 0x0707, 0x0d70, 0x0026,
+	0x6218, 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, 0x25a8,
+	0x002e, 0x6007, 0x000c, 0x0804, 0x7fa4, 0x080c, 0x45e7, 0x6618,
+	0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x02b0,
+	0xa6b4, 0xff00, 0x8637, 0xa686, 0x0004, 0x0118, 0xa686, 0x0006,
+	0x1960, 0x080c, 0x873e, 0x1120, 0x6007, 0x000e, 0x0804, 0x7fa4,
+	0x080c, 0x2563, 0x6007, 0x000f, 0x0804, 0x7fa4, 0x080c, 0x884f,
+	0x0160, 0xa6b4, 0xff00, 0x8637, 0xa682, 0x0004, 0x0a04, 0x7f0d,
+	0xa682, 0x0007, 0x0e30, 0x0804, 0x7f0d, 0x6013, 0x1900, 0x6007,
+	0x0009, 0x0804, 0x7fa4, 0x080c, 0x45e7, 0x6618, 0xa6b0, 0x0001,
+	0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x02c0, 0xa6b4, 0xff00,
+	0x8637, 0xa686, 0x0004, 0x0120, 0xa686, 0x0006, 0x1904, 0x7f0d,
+	0x080c, 0x8766, 0x1130, 0x080c, 0x867e, 0x1118, 0x6007, 0x0010,
+	0x0418, 0x080c, 0x2563, 0x6007, 0x0011, 0x00f0, 0x080c, 0x884f,
+	0x0140, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0d48, 0x0804,
+	0x7f0d, 0x6013, 0x1900, 0x6007, 0x0009, 0x0070, 0x7030, 0xa086,
+	0x6000, 0x0140, 0x080c, 0x89fb, 0x1904, 0x8079, 0x080c, 0x807c,
+	0x1904, 0x7f0d, 0x6007, 0x0012, 0x6003, 0x0001, 0x080c, 0x58e2,
+	0x0005, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x58e2, 0x0cc0,
+	0x6007, 0x0005, 0x0cc0, 0x080c, 0x89fb, 0x1904, 0x8079, 0x080c,
+	0x807c, 0x1904, 0x7f0d, 0x6007, 0x0020, 0x6003, 0x0001, 0x080c,
+	0x58e2, 0x0005, 0x6007, 0x0023, 0x6003, 0x0001, 0x080c, 0x58e2,
+	0x0005, 0x080c, 0x89fb, 0x1904, 0x8079, 0x080c, 0x807c, 0x1904,
+	0x7f0d, 0x0016, 0x0026, 0x2011, 0x9091, 0x2214, 0xa286, 0xffff,
+	0x0190, 0x2c08, 0x080c, 0x7b7f, 0x01d8, 0x2260, 0x2011, 0x9090,
+	0x2214, 0x6008, 0xa206, 0x11a0, 0x6018, 0xa190, 0x0006, 0x2214,
+	0xa206, 0x01e0, 0x0068, 0x2011, 0x9090, 0x2214, 0x2c08, 0x080c,
+	0x8956, 0x11a0, 0x2011, 0x9091, 0x2214, 0xa286, 0xffff, 0x01a0,
+	0x2160, 0x6007, 0x0026, 0x6013, 0x1700, 0x2011, 0x9089, 0x2214,
+	0xa296, 0xffff, 0x1160, 0x6007, 0x0025, 0x0048, 0x601c, 0xa086,
+	0x0007, 0x1d70, 0x080c, 0x6d18, 0x2160, 0x6007, 0x0025, 0x6003,
+	0x0001, 0x080c, 0x58e2, 0x002e, 0x001e, 0x0005, 0x2001, 0x0001,
+	0x080c, 0x42a7, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004,
+	0x2019, 0x8b05, 0x2011, 0x9096, 0x080c, 0x7326, 0x003e, 0x002e,
+	0x001e, 0x015e, 0x0120, 0x6007, 0x0031, 0x0804, 0x7fa4, 0x080c,
+	0x715d, 0x080c, 0x4c42, 0x1548, 0x0006, 0x0026, 0x0036, 0x2011,
+	0x8b23, 0x2204, 0x8000, 0x2012, 0xa084, 0x0007, 0x0190, 0x2001,
+	0x8d9c, 0x2003, 0xaaaa, 0x2001, 0x8d9d, 0x2003, 0x0001, 0x2001,
+	0x8b00, 0x2003, 0x0001, 0x080c, 0x4b8b, 0x003e, 0x002e, 0x000e,
+	0x0005, 0x2001, 0x0001, 0x080c, 0x2298, 0x080c, 0x4c54, 0x1110,
+	0x080c, 0x4c15, 0x003e, 0x002e, 0x000e, 0x0005, 0x6106, 0x0479,
+	0x6007, 0x002b, 0x0804, 0x7fa4, 0x6007, 0x002c, 0x0804, 0x7fa4,
+	0x080c, 0x89fb, 0x1170, 0x0081, 0x1904, 0x7f0d, 0x6106, 0x0419,
+	0x1120, 0x6007, 0x002e, 0x0804, 0x7fa4, 0x6007, 0x002f, 0x0804,
+	0x7fa4, 0x080c, 0x6d18, 0x0005, 0x00d6, 0x0066, 0x6618, 0x2668,
+	0x6e04, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0128, 0xa686,
+	0x0004, 0x0110, 0xa085, 0x0001, 0x006e, 0x00de, 0x0005, 0x00d6,
+	0x0439, 0x00de, 0x0005, 0x00d6, 0x0481, 0x11e0, 0x680c, 0xa08c,
+	0xff00, 0x6824, 0xa084, 0x00ff, 0xa115, 0x6212, 0xd1e4, 0x0118,
+	0x2009, 0x0001, 0x0060, 0xd1ec, 0x0168, 0x6920, 0xa18c, 0x00ff,
+	0x6824, 0x080c, 0x22e9, 0x1130, 0x2110, 0x2009, 0x0000, 0x080c,
+	0x25a8, 0x0018, 0xa085, 0x0001, 0x0008, 0xa006, 0x00de, 0x0005,
+	0x2069, 0x908d, 0x6800, 0xa082, 0x0010, 0x1228, 0x6013, 0x0000,
+	0xa085, 0x0001, 0x0008, 0xa006, 0x0005, 0x6013, 0x0000, 0x2069,
+	0x908c, 0x6808, 0xa084, 0xff00, 0xa086, 0x0800, 0x0005, 0x6004,
+	0xa0b2, 0x0040, 0x1a0c, 0x1410, 0xa1b6, 0x0013, 0x1110, 0x2008,
+	0x0092, 0xa1b6, 0x0027, 0x0120, 0xa1b6, 0x0014, 0x190c, 0x1410,
+	0x2001, 0x0007, 0x080c, 0x42c7, 0x080c, 0x5c37, 0x080c, 0x7d3c,
+	0x080c, 0x5d10, 0x0005, 0x812b, 0x812d, 0x812b, 0x812b, 0x812b,
+	0x812d, 0x813b, 0x81a3, 0x816e, 0x81a3, 0x817f, 0x81a3, 0x813b,
+	0x81a3, 0x819b, 0x81a3, 0x819b, 0x81a3, 0x81a3, 0x812b, 0x812b,
+	0x812b, 0x812b, 0x812b, 0x812b, 0x812b, 0x812b, 0x812b, 0x812b,
+	0x812b, 0x812b, 0x812b, 0x81a3, 0x812b, 0x812b, 0x81a3, 0x812b,
+	0x81a3, 0x81a3, 0x812b, 0x812b, 0x812b, 0x812b, 0x81a3, 0x81a3,
+	0x812b, 0x81a3, 0x81a3, 0x812b, 0x8135, 0x812b, 0x812b, 0x812b,
+	0x812b, 0x812b, 0x812b, 0x812b, 0x812b, 0x812b, 0x812b, 0x812b,
+	0x812b, 0x812b, 0x812b, 0x080c, 0x1410, 0x080c, 0x5c37, 0x6003,
+	0x0002, 0x080c, 0x5d10, 0x0804, 0x81a9, 0x2001, 0x0000, 0x080c,
+	0x42a7, 0x0804, 0x81a3, 0x00f6, 0x2079, 0x8b51, 0x7804, 0x00fe,
+	0xd0ac, 0x1904, 0x81a3, 0x2001, 0x0000, 0x080c, 0x42a7, 0x6018,
+	0xa080, 0x0004, 0x2004, 0xa086, 0x00ff, 0x1138, 0x00f6, 0x2079,
+	0x8b00, 0x7894, 0x8000, 0x7896, 0x00fe, 0x2001, 0x0002, 0x080c,
+	0x42b9, 0x080c, 0x5c37, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007,
+	0x0002, 0x080c, 0x58e2, 0x080c, 0x5d10, 0x00c6, 0x6118, 0x2160,
+	0x2009, 0x0001, 0x080c, 0x5619, 0x00ce, 0x04d8, 0x6618, 0x00d6,
 	0x2668, 0x6e04, 0x00de, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006,
-	0x0170, 0x2001, 0x0006, 0x0048, 0x2001, 0x0004, 0x0030, 0x2001,
-	0x0006, 0x0061, 0x0020, 0x0018, 0x0010, 0x080c, 0x43f1, 0x080c,
-	0x6389, 0x080c, 0x74f2, 0x080c, 0x6462, 0x0005, 0x0016, 0x00d6,
-	0x6118, 0x2168, 0x6900, 0xd184, 0x0178, 0x6104, 0xa18e, 0x000a,
-	0x1128, 0x699c, 0xd1a4, 0x1110, 0x2001, 0x0007, 0x2001, 0x0000,
-	0x080c, 0x43d1, 0x080c, 0x2692, 0x00de, 0x001e, 0x0005, 0x00d6,
-	0x6618, 0x2668, 0x6804, 0xa084, 0xff00, 0x8007, 0x00de, 0xa0b2,
-	0x000c, 0x1a0c, 0x13fe, 0xa1b6, 0x0015, 0x1110, 0x003b, 0x0028,
-	0xa1b6, 0x0016, 0x190c, 0x13fe, 0x04eb, 0x0005, 0x7805, 0x7805,
-	0x7805, 0x7805, 0x7805, 0x7805, 0x7805, 0x892a, 0x7805, 0x7805,
-	0x7805, 0x7805, 0x00f6, 0x2079, 0x9251, 0x7804, 0x00fe, 0xd0ac,
-	0x1198, 0x2001, 0x0000, 0x080c, 0x43d1, 0x2001, 0x0002, 0x080c,
-	0x43e3, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c,
-	0x603e, 0x080c, 0x6462, 0x00a8, 0x2011, 0x9783, 0x2204, 0x8211,
-	0x220c, 0x080c, 0x240b, 0x1168, 0x00c6, 0x080c, 0x4434, 0x0120,
-	0x00ce, 0x080c, 0x74f2, 0x0028, 0x080c, 0x41e0, 0x00ce, 0x080c,
-	0x74f2, 0x0005, 0x7805, 0x7805, 0x7805, 0x7805, 0x7805, 0x7805,
-	0x7805, 0x8966, 0x7805, 0x7805, 0x7805, 0x7805, 0x080c, 0x7a61,
-	0x1138, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x603e, 0x0010,
-	0x080c, 0x74f2, 0x0005, 0x6004, 0xa08a, 0x003e, 0x1a0c, 0x13fe,
-	0x080c, 0x6389, 0x080c, 0x849b, 0x080c, 0x6462, 0x0005, 0xa182,
-	0x0040, 0x0002, 0x8995, 0x8995, 0x8995, 0x8995, 0x8997, 0x8995,
-	0x8995, 0x8995, 0x8995, 0x8995, 0x8995, 0x8995, 0x8995, 0x8995,
-	0x8995, 0x8995, 0x8995, 0x8995, 0x8995, 0x080c, 0x13fe, 0x00d6,
-	0x00e6, 0x00f6, 0x0156, 0x0046, 0x0026, 0x6106, 0x2071, 0x9780,
-	0x7444, 0xa4a4, 0xf600, 0x0904, 0x8a0d, 0xa486, 0x2000, 0x01f0,
-	0xa486, 0x0400, 0x01d8, 0xa486, 0x1000, 0x0178, 0xa486, 0x4000,
-	0x01d8, 0xa486, 0x0200, 0x0120, 0x080c, 0x74f2, 0x0804, 0x8a67,
-	0x6118, 0x2104, 0xc0fd, 0x200a, 0x0078, 0x2069, 0x9566, 0x6a00,
-	0xd284, 0x0904, 0x8a79, 0xc2cd, 0x6a02, 0x0030, 0x2009, 0x0001,
-	0x2011, 0x0200, 0x080c, 0x585b, 0x080c, 0x147c, 0x090c, 0x13fe,
+	0x0550, 0xa686, 0x0004, 0x0538, 0x2001, 0x0004, 0x0410, 0x2001,
+	0x8b00, 0x2004, 0xa086, 0x0003, 0x1110, 0x080c, 0x3689, 0x2001,
+	0x0006, 0x0401, 0x6618, 0x00d6, 0x2668, 0x6e04, 0x00de, 0xa6b4,
+	0xff00, 0x8637, 0xa686, 0x0006, 0x0170, 0x2001, 0x0006, 0x0048,
+	0x2001, 0x0004, 0x0030, 0x2001, 0x0006, 0x0061, 0x0020, 0x0018,
+	0x0010, 0x080c, 0x42c7, 0x080c, 0x5c37, 0x080c, 0x6d18, 0x080c,
+	0x5d10, 0x0005, 0x0016, 0x00d6, 0x6118, 0x2168, 0x6900, 0xd184,
+	0x0188, 0x6104, 0xa18e, 0x000a, 0x1128, 0x699c, 0xd1a4, 0x1110,
+	0x2001, 0x0007, 0x080c, 0x42b9, 0x2001, 0x0000, 0x080c, 0x42a7,
+	0x080c, 0x2589, 0x00de, 0x001e, 0x0005, 0x00d6, 0x6618, 0x2668,
+	0x6804, 0xa084, 0xff00, 0x8007, 0x00de, 0xa0b2, 0x000c, 0x1a0c,
+	0x1410, 0xa1b6, 0x0015, 0x1110, 0x003b, 0x0028, 0xa1b6, 0x0016,
+	0x190c, 0x1410, 0x04eb, 0x0005, 0x7045, 0x7045, 0x7045, 0x7045,
+	0x7045, 0x7045, 0x7045, 0x81e8, 0x7045, 0x7045, 0x7045, 0x7045,
+	0x00f6, 0x2079, 0x8b51, 0x7804, 0x00fe, 0xd0ac, 0x1198, 0x2001,
+	0x0000, 0x080c, 0x42a7, 0x2001, 0x0002, 0x080c, 0x42b9, 0x601f,
+	0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x58e2, 0x080c,
+	0x5d10, 0x00a8, 0x2011, 0x9083, 0x2204, 0x8211, 0x220c, 0x080c,
+	0x22e9, 0x1168, 0x00c6, 0x080c, 0x430a, 0x0120, 0x00ce, 0x080c,
+	0x6d18, 0x0028, 0x080c, 0x4118, 0x00ce, 0x080c, 0x6d18, 0x0005,
+	0x7045, 0x7045, 0x7045, 0x7045, 0x7045, 0x7045, 0x7045, 0x8224,
+	0x7045, 0x7045, 0x7045, 0x7045, 0x080c, 0x72a1, 0x1138, 0x6003,
+	0x0001, 0x6007, 0x0001, 0x080c, 0x58e2, 0x0010, 0x080c, 0x6d18,
+	0x0005, 0x6004, 0xa08a, 0x0040, 0x1a0c, 0x1410, 0x080c, 0x5c37,
+	0x080c, 0x7d3c, 0x080c, 0x5d10, 0x0005, 0xa182, 0x0040, 0x0002,
+	0x8253, 0x8253, 0x8253, 0x8253, 0x8255, 0x8253, 0x8253, 0x8253,
+	0x8253, 0x8253, 0x8253, 0x8253, 0x8253, 0x8253, 0x8253, 0x8253,
+	0x8253, 0x8253, 0x8253, 0x080c, 0x1410, 0x00d6, 0x00e6, 0x00f6,
+	0x0156, 0x0046, 0x0026, 0x6106, 0x2071, 0x9080, 0x7444, 0xa4a4,
+	0xff00, 0x0904, 0x82bd, 0xa486, 0x2000, 0x0180, 0xa486, 0x0400,
+	0x0168, 0xa486, 0x1000, 0x0108, 0x0078, 0x2069, 0x8e2a, 0x6a00,
+	0xd284, 0x0904, 0x8324, 0xc2cd, 0x6a02, 0x0030, 0x2009, 0x0001,
+	0x2011, 0x0200, 0x080c, 0x5734, 0x080c, 0x1488, 0x090c, 0x1410,
 	0x6003, 0x0007, 0x2d00, 0x6837, 0x010d, 0x6803, 0x0000, 0x683b,
 	0x0000, 0x6c5a, 0x2c00, 0x685e, 0x6008, 0x68b2, 0x6018, 0x2078,
 	0x78a0, 0x8007, 0x7130, 0x694a, 0x0016, 0xa084, 0xff00, 0x6846,
-	0x684f, 0x0000, 0x6857, 0x0036, 0x080c, 0x4809, 0x001e, 0xa486,
-	0x2000, 0x1130, 0x2019, 0x0017, 0x080c, 0x9071, 0x0804, 0x8a67,
-	0xa486, 0x0400, 0x1130, 0x2019, 0x0002, 0x080c, 0x9033, 0x0804,
-	0x8a67, 0xa486, 0x0200, 0x1110, 0x080c, 0x9020, 0xa486, 0x1000,
-	0x1110, 0x080c, 0x905e, 0x0804, 0x8a67, 0x2069, 0x9566, 0x6a00,
-	0xd284, 0x0904, 0x8ab6, 0xa284, 0x0300, 0x1904, 0x8ab0, 0x6804,
-	0xa005, 0x0904, 0x8aa1, 0x2d78, 0x6003, 0x0007, 0x6018, 0x2004,
-	0xd0fc, 0x1904, 0x8ab0, 0x080c, 0x145f, 0x0904, 0x8a6e, 0x7800,
-	0xd08c, 0x1118, 0x7804, 0x8001, 0x7806, 0x6013, 0x0000, 0x6803,
-	0x0000, 0x6837, 0x0116, 0x683b, 0x0000, 0x6008, 0x68b2, 0x2c00,
-	0x684a, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0x6986, 0x6846,
-	0x6853, 0x003d, 0x7244, 0xa294, 0x0003, 0xa286, 0x0002, 0x1118,
-	0x684f, 0x0040, 0x0040, 0xa286, 0x0001, 0x1118, 0x684f, 0x0080,
-	0x0010, 0x684f, 0x0000, 0x20a9, 0x000a, 0x2001, 0x9790, 0xad90,
-	0x0015, 0x200c, 0x810f, 0x2112, 0x8000, 0x8210, 0x1f04, 0x8a59,
-	0x200c, 0x6982, 0x8000, 0x200c, 0x697e, 0x080c, 0x4809, 0x002e,
-	0x004e, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x6013, 0x0100,
-	0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x5ff8, 0x080c, 0x6462,
-	0x0c70, 0x2069, 0x9792, 0x2d04, 0xa084, 0xff00, 0xa086, 0x1200,
-	0x11a8, 0x2069, 0x9780, 0x686c, 0xa084, 0x00ff, 0x0016, 0x6110,
-	0xa18c, 0x0700, 0xa10d, 0x6112, 0x001e, 0x6003, 0x0001, 0x6007,
-	0x0043, 0x080c, 0x5ff8, 0x080c, 0x6462, 0x0888, 0x6013, 0x0200,
-	0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x5ff8, 0x080c, 0x6462,
-	0x0830, 0x6013, 0x0300, 0x0010, 0x6013, 0x0100, 0x6003, 0x0001,
-	0x6007, 0x0041, 0x080c, 0x5ff8, 0x080c, 0x6462, 0x0804, 0x8a67,
-	0x6013, 0x0500, 0x0c98, 0x6013, 0x0600, 0x0818, 0x6013, 0x0200,
-	0x0800, 0xa186, 0x0013, 0x1170, 0x6004, 0xa08a, 0x0040, 0x0a0c,
-	0x13fe, 0xa08a, 0x0053, 0x1a0c, 0x13fe, 0xa082, 0x0040, 0x2008,
-	0x0804, 0x8b24, 0xa186, 0x0047, 0x11b8, 0x2001, 0x0109, 0x2004,
-	0xd084, 0x01f0, 0x0126, 0x2091, 0x2400, 0x0006, 0x0016, 0x0026,
-	0x080c, 0x5ee3, 0x002e, 0x001e, 0x000e, 0x012e, 0x6000, 0xa086,
-	0x0002, 0x1170, 0x0804, 0x8b64, 0xa186, 0x0027, 0x0120, 0xa186,
-	0x0014, 0x190c, 0x13fe, 0x6004, 0xa082, 0x0040, 0x2008, 0x001a,
-	0x080c, 0x7526, 0x0005, 0x8b06, 0x8b08, 0x8b08, 0x8b06, 0x8b06,
-	0x8b06, 0x8b06, 0x8b06, 0x8b06, 0x8b06, 0x8b06, 0x8b06, 0x8b06,
-	0x8b06, 0x8b06, 0x8b06, 0x8b06, 0x8b06, 0x8b06, 0x080c, 0x13fe,
-	0x080c, 0x6389, 0x080c, 0x6462, 0x0036, 0x00d6, 0x6010, 0xa06d,
-	0x0180, 0xad84, 0xf000, 0x0168, 0x2019, 0x0004, 0x080c, 0x9097,
-	0x6013, 0x0000, 0x6014, 0xa005, 0x1110, 0x6017, 0x0014, 0x6003,
-	0x0007, 0x00de, 0x003e, 0x0005, 0x0002, 0x8b38, 0x8b55, 0x8b41,
-	0x8b5e, 0x8b38, 0x8b38, 0x8b38, 0x8b38, 0x8b38, 0x8b38, 0x8b38,
-	0x8b38, 0x8b38, 0x8b38, 0x8b38, 0x8b38, 0x8b38, 0x8b38, 0x8b38,
-	0x080c, 0x13fe, 0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400,
-	0x200a, 0x080c, 0x6389, 0x6010, 0xa080, 0x0013, 0x2004, 0xd0b4,
-	0x0138, 0x6003, 0x0007, 0x2009, 0x0043, 0x080c, 0x7518, 0x0010,
-	0x6003, 0x0002, 0x080c, 0x6462, 0x0005, 0x080c, 0x6389, 0x080c,
-	0x5836, 0x080c, 0x74f2, 0x080c, 0x6462, 0x0005, 0x080c, 0x6389,
-	0x2009, 0x0041, 0x0804, 0x8c44, 0xa182, 0x0040, 0x0002, 0x8b7a,
-	0x8b7c, 0x8b7a, 0x8b7a, 0x8b7a, 0x8b7a, 0x8b7a, 0x8b7d, 0x8b7a,
-	0x8b7a, 0x8b7a, 0x8b7a, 0x8b7a, 0x8b7a, 0x8b7a, 0x8b7a, 0x8b7a,
-	0x8b7a, 0x8b7a, 0x080c, 0x13fe, 0x0005, 0x6003, 0x0004, 0x6110,
-	0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x16c6, 0x0005,
-	0xa182, 0x0040, 0x0002, 0x8b9e, 0x8b9e, 0x8b9e, 0x8b9e, 0x8b9e,
-	0x8b9e, 0x8b9e, 0x8b9e, 0x8b9e, 0x8ba0, 0x8bc0, 0x8b9e, 0x8b9e,
-	0x8b9e, 0x8b9e, 0x8bc0, 0x8b9e, 0x8b9e, 0x8b9e, 0x080c, 0x13fe,
-	0x080c, 0x641b, 0x080c, 0x651c, 0x6010, 0x00d6, 0x2068, 0x684c,
-	0xd0fc, 0x0150, 0xa08c, 0x0003, 0xa18e, 0x0002, 0x0158, 0x2009,
-	0x0041, 0x00de, 0x0804, 0x8c44, 0x6003, 0x0007, 0x080c, 0x5836,
-	0x00de, 0x0005, 0x080c, 0x5836, 0x080c, 0x74f2, 0x00de, 0x0cc8,
-	0x0036, 0x080c, 0x641b, 0x080c, 0x651c, 0x6010, 0x00d6, 0x2068,
-	0x2019, 0x0004, 0x080c, 0x9097, 0x080c, 0x849b, 0x6017, 0x0028,
-	0x00de, 0x003e, 0x0005, 0xa186, 0x0013, 0x1150, 0x6004, 0xa086,
-	0x0042, 0x190c, 0x13fe, 0x080c, 0x6389, 0x080c, 0x6462, 0x0005,
-	0xa186, 0x0027, 0x0118, 0xa186, 0x0014, 0x1180, 0x6004, 0xa086,
-	0x0042, 0x190c, 0x13fe, 0x2001, 0x0007, 0x080c, 0x43f1, 0x080c,
-	0x6389, 0x080c, 0x849b, 0x080c, 0x6462, 0x0005, 0xa182, 0x0040,
-	0x0002, 0x8c0c, 0x8c0c, 0x8c0c, 0x8c0c, 0x8c0c, 0x8c0c, 0x8c0c,
-	0x8c0e, 0x8c1a, 0x8c0c, 0x8c0c, 0x8c0c, 0x8c0c, 0x8c0c, 0x8c0c,
-	0x8c0c, 0x8c0c, 0x8c0c, 0x8c0c, 0x080c, 0x13fe, 0x0036, 0x0046,
-	0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x16c6, 0x004e,
-	0x003e, 0x0005, 0x6010, 0x00d6, 0x2068, 0x6810, 0x6a14, 0xa20d,
-	0x1168, 0x684c, 0xd0fc, 0x0120, 0x2009, 0x0041, 0x00de, 0x00e0,
-	0x6003, 0x0007, 0x080c, 0x5836, 0x00de, 0x0005, 0x6003, 0x0007,
-	0x0021, 0x080c, 0x5838, 0x00de, 0x0005, 0xd2fc, 0x0140, 0x8002,
-	0x8000, 0x8212, 0xa291, 0x0000, 0x2009, 0x0009, 0x0010, 0x2009,
-	0x0015, 0x6a6a, 0x6866, 0x0005, 0xa182, 0x0040, 0x0002, 0x8c5a,
-	0x8c5c, 0x8c68, 0x8c74, 0x8c5a, 0x8c5a, 0x8c5a, 0x8c83, 0x8c5a,
-	0x8c5a, 0x8c5a, 0x8c5a, 0x8c5a, 0x8c5a, 0x8c5a, 0x8c5a, 0x8c5a,
-	0x8c5a, 0x8c5a, 0x080c, 0x13fe, 0x6003, 0x0001, 0x6106, 0x080c,
-	0x5ff8, 0x0126, 0x2091, 0x8000, 0x080c, 0x6462, 0x012e, 0x0005,
-	0x6003, 0x0001, 0x6106, 0x080c, 0x5ff8, 0x0126, 0x2091, 0x8000,
-	0x080c, 0x6462, 0x012e, 0x0005, 0x6003, 0x0003, 0x6106, 0x2c10,
-	0x080c, 0x1c88, 0x0126, 0x2091, 0x8000, 0x080c, 0x605b, 0x080c,
-	0x651c, 0x012e, 0x0005, 0xa016, 0x080c, 0x16c6, 0x0005, 0x080c,
-	0x6389, 0x6110, 0x81ff, 0x0148, 0x00d6, 0x2168, 0x0036, 0x2019,
-	0x0029, 0x080c, 0x9097, 0x003e, 0x00de, 0x080c, 0x849b, 0x080c,
-	0x6462, 0x0005, 0x080c, 0x641b, 0x6110, 0x81ff, 0x0148, 0x00d6,
-	0x2168, 0x0036, 0x2019, 0x0029, 0x080c, 0x9097, 0x003e, 0x00de,
-	0x080c, 0x849b, 0x080c, 0x651c, 0x0005, 0xa182, 0x0085, 0x0002,
-	0x8cb9, 0x8cb7, 0x8cb7, 0x8cc5, 0x8cb7, 0x8cb7, 0x8cb7, 0x080c,
-	0x13fe, 0x6003, 0x000b, 0x6106, 0x080c, 0x5ff8, 0x0126, 0x2091,
-	0x8000, 0x080c, 0x6462, 0x012e, 0x0005, 0x0026, 0x00e6, 0x080c,
-	0x9150, 0x0118, 0x080c, 0x74f2, 0x00c8, 0x2071, 0x9780, 0x7224,
-	0x6212, 0x7220, 0x080c, 0x8f71, 0x0118, 0x6007, 0x0086, 0x0040,
-	0x6007, 0x0087, 0x7224, 0xa296, 0xffff, 0x1110, 0x6007, 0x0086,
-	0x6003, 0x0001, 0x080c, 0x5ff8, 0x080c, 0x6462, 0x00ee, 0x002e,
-	0x0005, 0xa186, 0x0013, 0x1160, 0x6004, 0xa08a, 0x0085, 0x0a0c,
-	0x13fe, 0xa08a, 0x008c, 0x1a0c, 0x13fe, 0xa082, 0x0085, 0x00a2,
-	0xa186, 0x0027, 0x0130, 0xa186, 0x0014, 0x0118, 0x080c, 0x7526,
-	0x0050, 0x2001, 0x0007, 0x080c, 0x43f1, 0x080c, 0x6389, 0x080c,
-	0x849b, 0x080c, 0x6462, 0x0005, 0x8d13, 0x8d15, 0x8d15, 0x8d13,
-	0x8d13, 0x8d13, 0x8d13, 0x080c, 0x13fe, 0x080c, 0x6389, 0x080c,
-	0x74f2, 0x080c, 0x6462, 0x0005, 0xa182, 0x0085, 0x0a0c, 0x13fe,
-	0xa182, 0x008c, 0x1a0c, 0x13fe, 0xa182, 0x0085, 0x0002, 0x8d2e,
-	0x8d2e, 0x8d2e, 0x8d30, 0x8d2e, 0x8d2e, 0x8d2e, 0x080c, 0x13fe,
-	0x0005, 0xa186, 0x0013, 0x0148, 0xa186, 0x0014, 0x0130, 0xa186,
-	0x0027, 0x0118, 0x080c, 0x7526, 0x0030, 0x080c, 0x6389, 0x080c,
-	0x849b, 0x080c, 0x6462, 0x0005, 0x0036, 0x2019, 0x000b, 0x0031,
-	0x601f, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0x0126, 0x0036,
-	0x0086, 0x2091, 0x8000, 0x2c40, 0x080c, 0x724a, 0x1540, 0x080c,
-	0x72e2, 0x1528, 0x6000, 0xa086, 0x0000, 0x0508, 0x601c, 0xa086,
-	0x0007, 0x01e8, 0x00d6, 0x6000, 0xa086, 0x0004, 0x1140, 0x601f,
-	0x0007, 0x2001, 0x94dd, 0x2004, 0x6016, 0x080c, 0x1788, 0x6010,
-	0x2068, 0x080c, 0x82ee, 0x0110, 0x080c, 0x9097, 0x00de, 0x6013,
-	0x0000, 0x601f, 0x0007, 0x2001, 0x94dd, 0x2004, 0x6016, 0x008e,
-	0x003e, 0x012e, 0x0005, 0x00f6, 0x00c6, 0x0036, 0x0156, 0x2079,
-	0x9780, 0x7938, 0x783c, 0x080c, 0x240b, 0x1904, 0x8dce, 0x0016,
-	0x00c6, 0x080c, 0x4434, 0x15c0, 0x2011, 0x9790, 0xac98, 0x000a,
-	0x20a9, 0x0004, 0x080c, 0x7aee, 0x1578, 0x001e, 0x002e, 0x0026,
-	0x0016, 0x2019, 0x0029, 0x080c, 0x73a2, 0x080c, 0x6127, 0x0086,
-	0x2041, 0x0000, 0x080c, 0x606d, 0x008e, 0x001e, 0x0086, 0x2041,
-	0x0000, 0x080c, 0x8ee4, 0x008e, 0x080c, 0x460d, 0x0026, 0x6204,
-	0xa294, 0xff00, 0x8217, 0xa286, 0x0006, 0x0118, 0xa286, 0x0004,
-	0x1118, 0x62a0, 0x080c, 0x2704, 0x002e, 0x001e, 0x080c, 0x41e0,
-	0x6612, 0x6516, 0xa006, 0x0010, 0x00ce, 0x001e, 0x015e, 0x003e,
-	0x00ce, 0x00fe, 0x0005, 0x00c6, 0x00d6, 0x0016, 0x2009, 0x9220,
-	0x2104, 0xa086, 0x0074, 0x1904, 0x8e1e, 0x2069, 0x978e, 0x690c,
-	0xa182, 0x0100, 0x0678, 0x6908, 0xa184, 0x8000, 0x05a0, 0x2001,
-	0x94d7, 0x2004, 0xa005, 0x1118, 0xa184, 0x0800, 0x0560, 0x6910,
-	0xa18a, 0x0001, 0x0610, 0x6914, 0x2069, 0x97ae, 0x6904, 0x81ff,
-	0x1198, 0x690c, 0xa182, 0x0100, 0x02a8, 0x6908, 0x81ff, 0x1178,
-	0x6910, 0xa18a, 0x0001, 0x0288, 0x6918, 0xa18a, 0x0001, 0x0298,
-	0x00d0, 0x6013, 0x0100, 0x00a0, 0x6013, 0x0300, 0x0088, 0x6013,
-	0x0500, 0x0070, 0x6013, 0x0700, 0x0058, 0x6013, 0x0900, 0x0040,
-	0x6013, 0x0b00, 0x0028, 0x6013, 0x0f00, 0x0010, 0x6013, 0x2d00,
-	0xa085, 0x0001, 0x0008, 0xa006, 0x001e, 0x00de, 0x00ce, 0x0005,
-	0x00c6, 0x00d6, 0x0026, 0x0036, 0x0156, 0x6218, 0x2268, 0x6b04,
-	0xa394, 0x00ff, 0xa286, 0x0006, 0x0190, 0xa286, 0x0004, 0x0178,
-	0xa394, 0xff00, 0x8217, 0xa286, 0x0006, 0x0148, 0xa286, 0x0004,
-	0x0130, 0x00c6, 0x2d60, 0x080c, 0x4443, 0x00ce, 0x04c0, 0x2011,
-	0x9796, 0xad98, 0x000a, 0x20a9, 0x0004, 0x080c, 0x7aee, 0x1580,
-	0x2011, 0x979a, 0xad98, 0x0006, 0x20a9, 0x0004, 0x080c, 0x7aee,
-	0x1538, 0x0046, 0x0016, 0x6aa0, 0xa294, 0x00ff, 0x8227, 0xa006,
-	0x2009, 0x9252, 0x210c, 0xd1a4, 0x0138, 0x2009, 0x0029, 0x080c,
-	0x90d7, 0x6800, 0xc0e5, 0x6802, 0x2019, 0x0029, 0x080c, 0x6127,
-	0x0086, 0x2041, 0x0000, 0x080c, 0x606d, 0x2c08, 0x080c, 0x8ee4,
-	0x008e, 0x2001, 0x0007, 0x080c, 0x43f1, 0x001e, 0x004e, 0xa006,
-	0x015e, 0x003e, 0x002e, 0x00de, 0x00ce, 0x0005, 0x00d6, 0x2069,
-	0x978e, 0x6800, 0xa086, 0x0800, 0x0118, 0x6013, 0x0000, 0x0008,
-	0xa006, 0x00de, 0x0005, 0x00c6, 0x00f6, 0x0016, 0x0026, 0x0036,
-	0x0156, 0x2079, 0x978c, 0x7930, 0x7834, 0x080c, 0x240b, 0x11a0,
-	0x080c, 0x4434, 0x1188, 0x2011, 0x9790, 0xac98, 0x000a, 0x20a9,
-	0x0004, 0x080c, 0x7aee, 0x1140, 0x2011, 0x9794, 0xac98, 0x0006,
-	0x20a9, 0x0004, 0x080c, 0x7aee, 0x015e, 0x003e, 0x002e, 0x001e,
-	0x00fe, 0x00ce, 0x0005, 0x00c6, 0x0006, 0x0016, 0x0026, 0x0036,
-	0x0156, 0x2011, 0x9783, 0x2204, 0x8211, 0x220c, 0x080c, 0x240b,
-	0x11a0, 0x080c, 0x4434, 0x1188, 0x2011, 0x9796, 0xac98, 0x000a,
-	0x20a9, 0x0004, 0x080c, 0x7aee, 0x1140, 0x2011, 0x979a, 0xac98,
-	0x0006, 0x20a9, 0x0004, 0x080c, 0x7aee, 0x015e, 0x003e, 0x002e,
-	0x001e, 0x000e, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0076, 0x0066,
-	0x0056, 0x0046, 0x0026, 0x0126, 0x2091, 0x8000, 0x2029, 0x94ee,
-	0x252c, 0x2021, 0x94f4, 0x2424, 0x2061, 0x9900, 0x2071, 0x9200,
-	0x7644, 0x7064, 0x8001, 0xa602, 0x1a04, 0x8f44, 0x2100, 0xac06,
-	0x05d0, 0x080c, 0x90ee, 0x05b8, 0x671c, 0xa786, 0x0001, 0x0904,
-	0x8f56, 0xa786, 0x0007, 0x0578, 0x2500, 0xac06, 0x0560, 0x2400,
-	0xac06, 0x0548, 0x080c, 0x90fe, 0x1530, 0x88ff, 0x0118, 0x6020,
-	0xa906, 0x1508, 0x00d6, 0x6000, 0xa086, 0x0004, 0x1120, 0x0016,
-	0x080c, 0x1788, 0x001e, 0x6010, 0x2068, 0x080c, 0x82ee, 0x0180,
-	0xa786, 0x0003, 0x1510, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000,
-	0x0016, 0x080c, 0x8527, 0x080c, 0x4809, 0x001e, 0x080c, 0x848f,
-	0x00de, 0x080c, 0x849b, 0xace0, 0x000c, 0x2001, 0x9216, 0x2004,
-	0xac02, 0x1210, 0x0804, 0x8ef6, 0x012e, 0x002e, 0x004e, 0x005e,
-	0x006e, 0x007e, 0x00ce, 0x00ee, 0x0005, 0xa786, 0x0006, 0x19d8,
-	0xa386, 0x0005, 0x0d40, 0x080c, 0x9097, 0x0c10, 0x080c, 0x90fe,
-	0x1d10, 0xa180, 0x0001, 0x2004, 0xa086, 0x0018, 0x19e0, 0x6000,
-	0xa086, 0x0002, 0x19c0, 0x080c, 0x84b7, 0x0130, 0x080c, 0x84c8,
-	0x1990, 0x080c, 0x7776, 0x0010, 0x080c, 0x2692, 0x080c, 0x849b,
-	0x0850, 0x00c6, 0x00e6, 0x0016, 0x2c08, 0x2170, 0x080c, 0x90ab,
-	0x001e, 0x0120, 0x601c, 0xa084, 0x000f, 0x001b, 0x00ee, 0x00ce,
-	0x0005, 0x8f89, 0x8f89, 0x8f89, 0x8f89, 0x8f89, 0x8f89, 0x8f8b,
-	0x8f89, 0xa006, 0x0005, 0x0046, 0x0016, 0x7018, 0xa080, 0x0028,
-	0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00, 0x2009, 0x0020, 0x080c,
-	0x90d7, 0x001e, 0x004e, 0x0036, 0x2019, 0x0002, 0x080c, 0x8d4e,
-	0x003e, 0xa085, 0x0001, 0x0005, 0x2001, 0x0001, 0x080c, 0x43d1,
-	0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0x9205,
-	0x2011, 0x9796, 0x080c, 0x7aee, 0x003e, 0x002e, 0x001e, 0x015e,
-	0xa005, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0076, 0x0066, 0x0026,
-	0x0126, 0x2091, 0x8000, 0x2061, 0x9900, 0x2079, 0x0001, 0x8fff,
-	0x0904, 0x9014, 0x2071, 0x9200, 0x7644, 0x7064, 0x8001, 0xa602,
-	0x1a04, 0x9014, 0x88ff, 0x0128, 0x2800, 0xac06, 0x15a0, 0x2079,
-	0x0000, 0x080c, 0x90ee, 0x0578, 0x2400, 0xac06, 0x0560, 0x671c,
-	0xa786, 0x0006, 0x1540, 0xa786, 0x0007, 0x0528, 0x88ff, 0x1140,
-	0x6018, 0xa206, 0x1500, 0x85ff, 0x0118, 0x6020, 0xa106, 0x11d8,
-	0x00d6, 0x6000, 0xa086, 0x0004, 0x1140, 0x601f, 0x0007, 0x2001,
-	0x94dd, 0x2004, 0x6016, 0x080c, 0x1788, 0x6010, 0x2068, 0x080c,
-	0x82ee, 0x0120, 0x0046, 0x080c, 0x9097, 0x004e, 0x00de, 0x080c,
-	0x849b, 0x88ff, 0x1190, 0xace0, 0x000c, 0x2001, 0x9216, 0x2004,
-	0xac02, 0x1210, 0x0804, 0x8fc7, 0xa006, 0x012e, 0x002e, 0x006e,
-	0x007e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0xa8c5, 0x0001, 0x0ca8,
-	0x0086, 0x0056, 0x2041, 0x0000, 0x2029, 0x0001, 0x2c20, 0x2019,
-	0x0002, 0x6218, 0x080c, 0x724a, 0x080c, 0x72e2, 0x080c, 0x8fba,
-	0x005e, 0x008e, 0x0005, 0x0026, 0x0046, 0x0056, 0x0086, 0x00c6,
-	0x0156, 0x2c20, 0x2128, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016,
-	0x0036, 0x080c, 0x4434, 0x1170, 0x2c10, 0x2041, 0x0000, 0x2508,
-	0x0056, 0x2029, 0x0001, 0x080c, 0x724a, 0x080c, 0x72e2, 0x080c,
-	0x8fba, 0x005e, 0x003e, 0x001e, 0x8108, 0x1f04, 0x903f, 0x015e,
-	0x00ce, 0x008e, 0x005e, 0x004e, 0x002e, 0x0005, 0x0086, 0x0056,
-	0x6218, 0x2041, 0x0000, 0x2029, 0x0001, 0x2019, 0x0048, 0x080c,
-	0x724a, 0x080c, 0x72e2, 0x2c20, 0x080c, 0x8fba, 0x005e, 0x008e,
-	0x0005, 0x0026, 0x0046, 0x0056, 0x0086, 0x00c6, 0x0156, 0x2c20,
-	0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x0036, 0x080c, 0x4434,
-	0x1150, 0x2c10, 0x2041, 0x0000, 0x2828, 0x080c, 0x724a, 0x080c,
-	0x72e2, 0x080c, 0x8fba, 0x003e, 0x001e, 0x8108, 0x1f04, 0x907c,
-	0x015e, 0x00ce, 0x008e, 0x005e, 0x004e, 0x002e, 0x0005, 0x0016,
-	0x00f6, 0x8dff, 0x0168, 0x6800, 0xa07d, 0x0138, 0x6803, 0x0000,
-	0x6b52, 0x080c, 0x4809, 0x2f68, 0x0cb0, 0x6b52, 0x080c, 0x4809,
-	0x00fe, 0x001e, 0x0005, 0x00e6, 0x0046, 0x0036, 0x2061, 0x9900,
-	0x2071, 0x9200, 0x7444, 0x7064, 0x8001, 0xa402, 0x12d8, 0x2100,
-	0xac06, 0x0168, 0x6000, 0xa086, 0x0000, 0x0148, 0x6008, 0xa206,
-	0x1130, 0x6018, 0xa1a0, 0x0006, 0x2424, 0xa406, 0x0140, 0xace0,
-	0x000c, 0x2001, 0x9216, 0x2004, 0xac02, 0x1220, 0x0c08, 0xa085,
-	0x0001, 0x0008, 0xa006, 0x003e, 0x004e, 0x00ee, 0x0005, 0x00d6,
-	0x0006, 0x080c, 0x147c, 0x000e, 0x090c, 0x13fe, 0x6837, 0x010d,
-	0x685e, 0x6956, 0x6c46, 0x684f, 0x0000, 0xa006, 0x68b2, 0x6802,
-	0x683a, 0x685a, 0x080c, 0x4809, 0x00de, 0x0005, 0x6700, 0xa786,
-	0x0000, 0x0158, 0xa786, 0x0001, 0x0140, 0xa786, 0x000a, 0x0128,
-	0xa786, 0x0009, 0x0110, 0xa085, 0x0001, 0x0005, 0x00e6, 0x6018,
-	0x2070, 0x70a0, 0xa206, 0x00ee, 0x0005, 0xa186, 0x0013, 0x1128,
-	0x6004, 0xa082, 0x0085, 0x2008, 0x00c2, 0xa186, 0x0027, 0x1178,
-	0x080c, 0x6389, 0x0036, 0x00d6, 0x6010, 0x2068, 0x2019, 0x0004,
-	0x080c, 0x9097, 0x00de, 0x003e, 0x080c, 0x6462, 0x0005, 0xa186,
-	0x0014, 0x0d70, 0x080c, 0x7526, 0x0005, 0x912e, 0x912c, 0x912c,
-	0x912c, 0x912c, 0x912c, 0x912e, 0x080c, 0x13fe, 0x080c, 0x6389,
-	0x6003, 0x000c, 0x080c, 0x6462, 0x0005, 0xa182, 0x008c, 0x1220,
-	0xa182, 0x0085, 0x0208, 0x001a, 0x080c, 0x7526, 0x0005, 0x9146,
-	0x9146, 0x9146, 0x9146, 0x9148, 0x914d, 0x9146, 0x080c, 0x13fe,
-	0x00d6, 0x080c, 0x74f2, 0x00de, 0x0005, 0x080c, 0x74f2, 0x0005,
-	0x00e6, 0x6018, 0x2070, 0x7000, 0xd0ec, 0x00ee, 0x0005, 0x0126,
-	0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0x9240, 0xd5a4, 0x0118,
-	0x7034, 0x8000, 0x7036, 0xd5b4, 0x0118, 0x7030, 0x8000, 0x7032,
-	0xd5ac, 0x0118, 0x2071, 0x924a, 0x0451, 0x00ee, 0x000e, 0x012e,
-	0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0x9240,
-	0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0118, 0x7030,
-	0x8000, 0x7032, 0xd5ac, 0x0118, 0x2071, 0x924a, 0x0081, 0x00ee,
-	0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000,
-	0x2071, 0x9242, 0x0021, 0x00ee, 0x000e, 0x012e, 0x0005, 0x2e04,
-	0x8000, 0x2072, 0x1220, 0x8e70, 0x2e04, 0x8000, 0x2072, 0x0005,
-	0x00e6, 0x2071, 0x9240, 0x0c99, 0x00ee, 0x0005, 0x00e6, 0x2071,
-	0x9244, 0x0c69, 0x00ee, 0x0005, 0x0001, 0x0002, 0x0004, 0x0008,
-	0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800,
-	0x1000, 0x2000, 0x4000, 0x8000, 0x448c
+	0x684f, 0x0000, 0x6857, 0x0036, 0x080c, 0x46a1, 0x001e, 0xa486,
+	0x2000, 0x1130, 0x2019, 0x0017, 0x080c, 0x891c, 0x0804, 0x8312,
+	0xa486, 0x0400, 0x1130, 0x2019, 0x0002, 0x080c, 0x88de, 0x0804,
+	0x8312, 0xa486, 0x0200, 0x1110, 0x080c, 0x88cb, 0xa486, 0x1000,
+	0x1110, 0x080c, 0x8909, 0x0804, 0x8312, 0x2069, 0x8e2a, 0x6a00,
+	0xd284, 0x0904, 0x8361, 0xa284, 0x0300, 0x1904, 0x835b, 0x6804,
+	0xa005, 0x0904, 0x834c, 0x2d78, 0x6003, 0x0007, 0x080c, 0x146f,
+	0x0904, 0x8319, 0x7800, 0xd08c, 0x1118, 0x7804, 0x8001, 0x7806,
+	0x6013, 0x0000, 0x6803, 0x0000, 0x6837, 0x0116, 0x683b, 0x0000,
+	0x6008, 0x68b2, 0x2c00, 0x684a, 0x6018, 0x2078, 0x78a0, 0x8007,
+	0x7130, 0x6986, 0x6846, 0x6853, 0x003d, 0x7244, 0xa294, 0x0003,
+	0xa286, 0x0002, 0x1118, 0x684f, 0x0040, 0x0040, 0xa286, 0x0001,
+	0x1118, 0x684f, 0x0080, 0x0010, 0x684f, 0x0000, 0x20a9, 0x000a,
+	0x2001, 0x9090, 0xad90, 0x0015, 0x200c, 0x810f, 0x2112, 0x8000,
+	0x8210, 0x1f04, 0x8304, 0x200c, 0x6982, 0x8000, 0x200c, 0x697e,
+	0x080c, 0x46a1, 0x002e, 0x004e, 0x015e, 0x00fe, 0x00ee, 0x00de,
+	0x0005, 0x6013, 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c,
+	0x589c, 0x080c, 0x5d10, 0x0c70, 0x2069, 0x9092, 0x2d04, 0xa084,
+	0xff00, 0xa086, 0x1200, 0x11a8, 0x2069, 0x9080, 0x686c, 0xa084,
+	0x00ff, 0x0016, 0x6110, 0xa18c, 0x0700, 0xa10d, 0x6112, 0x001e,
+	0x6003, 0x0001, 0x6007, 0x0043, 0x080c, 0x589c, 0x080c, 0x5d10,
+	0x0888, 0x6013, 0x0200, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c,
+	0x589c, 0x080c, 0x5d10, 0x0830, 0x6013, 0x0300, 0x0010, 0x6013,
+	0x0100, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x589c, 0x080c,
+	0x5d10, 0x0804, 0x8312, 0x6013, 0x0500, 0x0c98, 0x6013, 0x0600,
+	0x0818, 0x6013, 0x0200, 0x0800, 0xa186, 0x0013, 0x1170, 0x6004,
+	0xa08a, 0x0040, 0x0a0c, 0x1410, 0xa08a, 0x0053, 0x1a0c, 0x1410,
+	0xa082, 0x0040, 0x2008, 0x0804, 0x83cf, 0xa186, 0x0047, 0x11b8,
+	0x2001, 0x0109, 0x2004, 0xd084, 0x01f0, 0x0126, 0x2091, 0x2400,
+	0x0006, 0x0016, 0x0026, 0x080c, 0x578e, 0x002e, 0x001e, 0x000e,
+	0x012e, 0x6000, 0xa086, 0x0002, 0x1170, 0x0804, 0x840f, 0xa186,
+	0x0027, 0x0120, 0xa186, 0x0014, 0x190c, 0x1410, 0x6004, 0xa082,
+	0x0040, 0x2008, 0x001a, 0x080c, 0x6d55, 0x0005, 0x83b1, 0x83b3,
+	0x83b3, 0x83b1, 0x83b1, 0x83b1, 0x83b1, 0x83b1, 0x83b1, 0x83b1,
+	0x83b1, 0x83b1, 0x83b1, 0x83b1, 0x83b1, 0x83b1, 0x83b1, 0x83b1,
+	0x83b1, 0x080c, 0x1410, 0x080c, 0x5c37, 0x080c, 0x5d10, 0x0036,
+	0x00d6, 0x6010, 0xa06d, 0x0180, 0xad84, 0xf000, 0x0168, 0x2019,
+	0x0004, 0x080c, 0x8942, 0x6013, 0x0000, 0x6014, 0xa005, 0x1110,
+	0x6017, 0x0014, 0x6003, 0x0007, 0x00de, 0x003e, 0x0005, 0x0002,
+	0x83e3, 0x8400, 0x83ec, 0x8409, 0x83e3, 0x83e3, 0x83e3, 0x83e3,
+	0x83e3, 0x83e3, 0x83e3, 0x83e3, 0x83e3, 0x83e3, 0x83e3, 0x83e3,
+	0x83e3, 0x83e3, 0x83e3, 0x080c, 0x1410, 0x6010, 0xa088, 0x0013,
+	0x2104, 0xa085, 0x0400, 0x200a, 0x080c, 0x5c37, 0x6010, 0xa080,
+	0x0013, 0x2004, 0xd0b4, 0x0138, 0x6003, 0x0007, 0x2009, 0x0043,
+	0x080c, 0x6d3f, 0x0010, 0x6003, 0x0002, 0x080c, 0x5d10, 0x0005,
+	0x080c, 0x5c37, 0x080c, 0x570f, 0x080c, 0x6d18, 0x080c, 0x5d10,
+	0x0005, 0x080c, 0x5c37, 0x2009, 0x0041, 0x0804, 0x84ef, 0xa182,
+	0x0040, 0x0002, 0x8425, 0x8427, 0x8425, 0x8425, 0x8425, 0x8425,
+	0x8425, 0x8428, 0x8425, 0x8425, 0x8425, 0x8425, 0x8425, 0x8425,
+	0x8425, 0x8425, 0x8425, 0x8425, 0x8425, 0x080c, 0x1410, 0x0005,
+	0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10,
+	0x080c, 0x16d1, 0x0005, 0xa182, 0x0040, 0x0002, 0x8449, 0x8449,
+	0x8449, 0x8449, 0x8449, 0x8449, 0x8449, 0x8449, 0x8449, 0x844b,
+	0x846b, 0x8449, 0x8449, 0x8449, 0x8449, 0x846b, 0x8449, 0x8449,
+	0x8449, 0x080c, 0x1410, 0x080c, 0x5cc9, 0x080c, 0x5dc2, 0x6010,
+	0x00d6, 0x2068, 0x684c, 0xd0fc, 0x0150, 0xa08c, 0x0003, 0xa18e,
+	0x0002, 0x0158, 0x2009, 0x0041, 0x00de, 0x0804, 0x84ef, 0x6003,
+	0x0007, 0x080c, 0x570f, 0x00de, 0x0005, 0x080c, 0x570f, 0x080c,
+	0x6d18, 0x00de, 0x0cc8, 0x0036, 0x080c, 0x5cc9, 0x080c, 0x5dc2,
+	0x6010, 0x00d6, 0x2068, 0x2019, 0x0004, 0x080c, 0x8942, 0x080c,
+	0x7d3c, 0x6017, 0x0028, 0x00de, 0x003e, 0x0005, 0xa186, 0x0013,
+	0x1150, 0x6004, 0xa086, 0x0042, 0x190c, 0x1410, 0x080c, 0x5c37,
+	0x080c, 0x5d10, 0x0005, 0xa186, 0x0027, 0x0118, 0xa186, 0x0014,
+	0x1180, 0x6004, 0xa086, 0x0042, 0x190c, 0x1410, 0x2001, 0x0007,
+	0x080c, 0x42c7, 0x080c, 0x5c37, 0x080c, 0x7d3c, 0x080c, 0x5d10,
+	0x0005, 0xa182, 0x0040, 0x0002, 0x84b7, 0x84b7, 0x84b7, 0x84b7,
+	0x84b7, 0x84b7, 0x84b7, 0x84b9, 0x84c5, 0x84b7, 0x84b7, 0x84b7,
+	0x84b7, 0x84b7, 0x84b7, 0x84b7, 0x84b7, 0x84b7, 0x84b7, 0x080c,
+	0x1410, 0x0036, 0x0046, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10,
+	0x080c, 0x16d1, 0x004e, 0x003e, 0x0005, 0x6010, 0x00d6, 0x2068,
+	0x6810, 0x6a14, 0xa20d, 0x1168, 0x684c, 0xd0fc, 0x0120, 0x2009,
+	0x0041, 0x00de, 0x00e0, 0x6003, 0x0007, 0x080c, 0x570f, 0x00de,
+	0x0005, 0x6003, 0x0007, 0x0021, 0x080c, 0x5711, 0x00de, 0x0005,
+	0xd2fc, 0x0140, 0x8002, 0x8000, 0x8212, 0xa291, 0x0000, 0x2009,
+	0x0009, 0x0010, 0x2009, 0x0015, 0x6a6a, 0x6866, 0x0005, 0xa182,
+	0x0040, 0x0002, 0x8505, 0x8507, 0x8513, 0x851f, 0x8505, 0x8505,
+	0x8505, 0x852e, 0x8505, 0x8505, 0x8505, 0x8505, 0x8505, 0x8505,
+	0x8505, 0x8505, 0x8505, 0x8505, 0x8505, 0x080c, 0x1410, 0x6003,
+	0x0001, 0x6106, 0x080c, 0x589c, 0x0126, 0x2091, 0x8000, 0x080c,
+	0x5d10, 0x012e, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x589c,
+	0x0126, 0x2091, 0x8000, 0x080c, 0x5d10, 0x012e, 0x0005, 0x6003,
+	0x0003, 0x6106, 0x2c10, 0x080c, 0x1bc8, 0x0126, 0x2091, 0x8000,
+	0x080c, 0x58ff, 0x080c, 0x5dc2, 0x012e, 0x0005, 0xa016, 0x080c,
+	0x16d1, 0x0005, 0x080c, 0x5c37, 0x6110, 0x81ff, 0x0148, 0x00d6,
+	0x2168, 0x0036, 0x2019, 0x0029, 0x080c, 0x8942, 0x003e, 0x00de,
+	0x080c, 0x7d3c, 0x080c, 0x5d10, 0x0005, 0x080c, 0x5cc9, 0x6110,
+	0x81ff, 0x0148, 0x00d6, 0x2168, 0x0036, 0x2019, 0x0029, 0x080c,
+	0x8942, 0x003e, 0x00de, 0x080c, 0x7d3c, 0x080c, 0x5dc2, 0x0005,
+	0xa182, 0x0085, 0x0002, 0x8564, 0x8562, 0x8562, 0x8570, 0x8562,
+	0x8562, 0x8562, 0x080c, 0x1410, 0x6003, 0x000b, 0x6106, 0x080c,
+	0x589c, 0x0126, 0x2091, 0x8000, 0x080c, 0x5d10, 0x012e, 0x0005,
+	0x0026, 0x00e6, 0x080c, 0x89fb, 0x0118, 0x080c, 0x6d18, 0x00c8,
+	0x2071, 0x9080, 0x7224, 0x6212, 0x7220, 0x080c, 0x881c, 0x0118,
+	0x6007, 0x0086, 0x0040, 0x6007, 0x0087, 0x7224, 0xa296, 0xffff,
+	0x1110, 0x6007, 0x0086, 0x6003, 0x0001, 0x080c, 0x589c, 0x080c,
+	0x5d10, 0x00ee, 0x002e, 0x0005, 0xa186, 0x0013, 0x1160, 0x6004,
+	0xa08a, 0x0085, 0x0a0c, 0x1410, 0xa08a, 0x008c, 0x1a0c, 0x1410,
+	0xa082, 0x0085, 0x00a2, 0xa186, 0x0027, 0x0130, 0xa186, 0x0014,
+	0x0118, 0x080c, 0x6d55, 0x0050, 0x2001, 0x0007, 0x080c, 0x42c7,
+	0x080c, 0x5c37, 0x080c, 0x7d3c, 0x080c, 0x5d10, 0x0005, 0x85be,
+	0x85c0, 0x85c0, 0x85be, 0x85be, 0x85be, 0x85be, 0x080c, 0x1410,
+	0x080c, 0x5c37, 0x080c, 0x6d18, 0x080c, 0x5d10, 0x0005, 0xa182,
+	0x0085, 0x0a0c, 0x1410, 0xa182, 0x008c, 0x1a0c, 0x1410, 0xa182,
+	0x0085, 0x0002, 0x85d9, 0x85d9, 0x85d9, 0x85db, 0x85d9, 0x85d9,
+	0x85d9, 0x080c, 0x1410, 0x0005, 0xa186, 0x0013, 0x0148, 0xa186,
+	0x0014, 0x0130, 0xa186, 0x0027, 0x0118, 0x080c, 0x6d55, 0x0030,
+	0x080c, 0x5c37, 0x080c, 0x7d3c, 0x080c, 0x5d10, 0x0005, 0x0036,
+	0x2019, 0x000b, 0x0031, 0x601f, 0x0006, 0x6003, 0x0007, 0x003e,
+	0x0005, 0x0126, 0x0036, 0x0086, 0x2091, 0x8000, 0x2c40, 0x080c,
+	0x6a17, 0x1540, 0x080c, 0x6aaf, 0x1528, 0x6000, 0xa086, 0x0000,
+	0x0508, 0x601c, 0xa086, 0x0007, 0x01e8, 0x00d6, 0x6000, 0xa086,
+	0x0004, 0x1140, 0x601f, 0x0007, 0x2001, 0x8da2, 0x2004, 0x6016,
+	0x080c, 0x179e, 0x6010, 0x2068, 0x080c, 0x7b8f, 0x0110, 0x080c,
+	0x8942, 0x00de, 0x6013, 0x0000, 0x601f, 0x0007, 0x2001, 0x8da2,
+	0x2004, 0x6016, 0x008e, 0x003e, 0x012e, 0x0005, 0x00f6, 0x00c6,
+	0x0036, 0x0156, 0x2079, 0x9080, 0x7938, 0x783c, 0x080c, 0x22e9,
+	0x1904, 0x8679, 0x0016, 0x00c6, 0x080c, 0x430a, 0x15c0, 0x2011,
+	0x9090, 0xac98, 0x000a, 0x20a9, 0x0004, 0x080c, 0x7326, 0x1578,
+	0x001e, 0x002e, 0x0026, 0x0016, 0x2019, 0x0029, 0x080c, 0x6b6f,
+	0x080c, 0x59d5, 0x0086, 0x2041, 0x0000, 0x080c, 0x5911, 0x008e,
+	0x001e, 0x0086, 0x2041, 0x0000, 0x080c, 0x878f, 0x008e, 0x080c,
+	0x44e6, 0x0026, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006,
+	0x0118, 0xa286, 0x0004, 0x1118, 0x62a0, 0x080c, 0x25fb, 0x002e,
+	0x001e, 0x080c, 0x4118, 0x6612, 0x6516, 0xa006, 0x0010, 0x00ce,
+	0x001e, 0x015e, 0x003e, 0x00ce, 0x00fe, 0x0005, 0x00c6, 0x00d6,
+	0x0016, 0x2009, 0x8b20, 0x2104, 0xa086, 0x0074, 0x1904, 0x86c9,
+	0x2069, 0x908e, 0x690c, 0xa182, 0x0100, 0x0678, 0x6908, 0xa184,
+	0x8000, 0x05a0, 0x2001, 0x8d9c, 0x2004, 0xa005, 0x1118, 0xa184,
+	0x0800, 0x0560, 0x6910, 0xa18a, 0x0001, 0x0610, 0x6914, 0x2069,
+	0x90ae, 0x6904, 0x81ff, 0x1198, 0x690c, 0xa182, 0x0100, 0x02a8,
+	0x6908, 0x81ff, 0x1178, 0x6910, 0xa18a, 0x0001, 0x0288, 0x6918,
+	0xa18a, 0x0001, 0x0298, 0x00d0, 0x6013, 0x0100, 0x00a0, 0x6013,
+	0x0300, 0x0088, 0x6013, 0x0500, 0x0070, 0x6013, 0x0700, 0x0058,
+	0x6013, 0x0900, 0x0040, 0x6013, 0x0b00, 0x0028, 0x6013, 0x0f00,
+	0x0010, 0x6013, 0x2d00, 0xa085, 0x0001, 0x0008, 0xa006, 0x001e,
+	0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x0026, 0x0036, 0x0156,
+	0x6218, 0x2268, 0x6b04, 0xa394, 0x00ff, 0xa286, 0x0006, 0x0190,
+	0xa286, 0x0004, 0x0178, 0xa394, 0xff00, 0x8217, 0xa286, 0x0006,
+	0x0148, 0xa286, 0x0004, 0x0130, 0x00c6, 0x2d60, 0x080c, 0x4319,
+	0x00ce, 0x04c0, 0x2011, 0x9096, 0xad98, 0x000a, 0x20a9, 0x0004,
+	0x080c, 0x7326, 0x1580, 0x2011, 0x909a, 0xad98, 0x0006, 0x20a9,
+	0x0004, 0x080c, 0x7326, 0x1538, 0x0046, 0x0016, 0x6aa0, 0xa294,
+	0x00ff, 0x8227, 0xa006, 0x2009, 0x8b52, 0x210c, 0xd1a4, 0x0138,
+	0x2009, 0x0029, 0x080c, 0x8982, 0x6800, 0xc0e5, 0x6802, 0x2019,
+	0x0029, 0x080c, 0x59d5, 0x0086, 0x2041, 0x0000, 0x080c, 0x5911,
+	0x2c08, 0x080c, 0x878f, 0x008e, 0x2001, 0x0007, 0x080c, 0x42c7,
+	0x001e, 0x004e, 0xa006, 0x015e, 0x003e, 0x002e, 0x00de, 0x00ce,
+	0x0005, 0x00d6, 0x2069, 0x908e, 0x6800, 0xa086, 0x0800, 0x0118,
+	0x6013, 0x0000, 0x0008, 0xa006, 0x00de, 0x0005, 0x00c6, 0x00f6,
+	0x0016, 0x0026, 0x0036, 0x0156, 0x2079, 0x908c, 0x7930, 0x7834,
+	0x080c, 0x22e9, 0x11a0, 0x080c, 0x430a, 0x1188, 0x2011, 0x9090,
+	0xac98, 0x000a, 0x20a9, 0x0004, 0x080c, 0x7326, 0x1140, 0x2011,
+	0x9094, 0xac98, 0x0006, 0x20a9, 0x0004, 0x080c, 0x7326, 0x015e,
+	0x003e, 0x002e, 0x001e, 0x00fe, 0x00ce, 0x0005, 0x00c6, 0x0006,
+	0x0016, 0x0026, 0x0036, 0x0156, 0x2011, 0x9083, 0x2204, 0x8211,
+	0x220c, 0x080c, 0x22e9, 0x11a0, 0x080c, 0x430a, 0x1188, 0x2011,
+	0x9096, 0xac98, 0x000a, 0x20a9, 0x0004, 0x080c, 0x7326, 0x1140,
+	0x2011, 0x909a, 0xac98, 0x0006, 0x20a9, 0x0004, 0x080c, 0x7326,
+	0x015e, 0x003e, 0x002e, 0x001e, 0x000e, 0x00ce, 0x0005, 0x00e6,
+	0x00c6, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0126, 0x2091,
+	0x8000, 0x2029, 0x8db3, 0x252c, 0x2021, 0x8db9, 0x2424, 0x2061,
+	0x9200, 0x2071, 0x8b00, 0x7644, 0x7064, 0x8001, 0xa602, 0x1a04,
+	0x87ef, 0x2100, 0xac06, 0x05d0, 0x080c, 0x8999, 0x05b8, 0x671c,
+	0xa786, 0x0001, 0x0904, 0x8801, 0xa786, 0x0007, 0x0578, 0x2500,
+	0xac06, 0x0560, 0x2400, 0xac06, 0x0548, 0x080c, 0x89a9, 0x1530,
+	0x88ff, 0x0118, 0x6020, 0xa906, 0x1508, 0x00d6, 0x6000, 0xa086,
+	0x0004, 0x1120, 0x0016, 0x080c, 0x179e, 0x001e, 0x6010, 0x2068,
+	0x080c, 0x7b8f, 0x0180, 0xa786, 0x0003, 0x1510, 0x6837, 0x0103,
+	0x6b4a, 0x6847, 0x0000, 0x0016, 0x080c, 0x7dc8, 0x080c, 0x46a1,
+	0x001e, 0x080c, 0x7d30, 0x00de, 0x080c, 0x7d3c, 0xace0, 0x000c,
+	0x2001, 0x8b16, 0x2004, 0xac02, 0x1210, 0x0804, 0x87a1, 0x012e,
+	0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x00ce, 0x00ee, 0x0005,
+	0xa786, 0x0006, 0x19d8, 0xa386, 0x0005, 0x0d40, 0x080c, 0x8942,
+	0x0c10, 0x080c, 0x89a9, 0x1d10, 0xa180, 0x0001, 0x2004, 0xa086,
+	0x0018, 0x19e0, 0x6000, 0xa086, 0x0002, 0x19c0, 0x080c, 0x7d58,
+	0x0130, 0x080c, 0x7d69, 0x1990, 0x080c, 0x6fb6, 0x0010, 0x080c,
+	0x2589, 0x080c, 0x7d3c, 0x0850, 0x00c6, 0x00e6, 0x0016, 0x2c08,
+	0x2170, 0x080c, 0x8956, 0x001e, 0x0120, 0x601c, 0xa084, 0x000f,
+	0x001b, 0x00ee, 0x00ce, 0x0005, 0x8834, 0x8834, 0x8834, 0x8834,
+	0x8834, 0x8834, 0x8836, 0x8834, 0xa006, 0x0005, 0x0046, 0x0016,
+	0x7018, 0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00,
+	0x2009, 0x0020, 0x080c, 0x8982, 0x001e, 0x004e, 0x0036, 0x2019,
+	0x0002, 0x080c, 0x85f9, 0x003e, 0xa085, 0x0001, 0x0005, 0x2001,
+	0x0001, 0x080c, 0x42a7, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9,
+	0x0004, 0x2019, 0x8b05, 0x2011, 0x9096, 0x080c, 0x7326, 0x003e,
+	0x002e, 0x001e, 0x015e, 0xa005, 0x0005, 0x00f6, 0x00e6, 0x00c6,
+	0x0076, 0x0066, 0x0026, 0x0126, 0x2091, 0x8000, 0x2061, 0x9200,
+	0x2079, 0x0001, 0x8fff, 0x0904, 0x88bf, 0x2071, 0x8b00, 0x7644,
+	0x7064, 0x8001, 0xa602, 0x1a04, 0x88bf, 0x88ff, 0x0128, 0x2800,
+	0xac06, 0x15a0, 0x2079, 0x0000, 0x080c, 0x8999, 0x0578, 0x2400,
+	0xac06, 0x0560, 0x671c, 0xa786, 0x0006, 0x1540, 0xa786, 0x0007,
+	0x0528, 0x88ff, 0x1140, 0x6018, 0xa206, 0x1500, 0x85ff, 0x0118,
+	0x6020, 0xa106, 0x11d8, 0x00d6, 0x6000, 0xa086, 0x0004, 0x1140,
+	0x601f, 0x0007, 0x2001, 0x8da2, 0x2004, 0x6016, 0x080c, 0x179e,
+	0x6010, 0x2068, 0x080c, 0x7b8f, 0x0120, 0x0046, 0x080c, 0x8942,
+	0x004e, 0x00de, 0x080c, 0x7d3c, 0x88ff, 0x1190, 0xace0, 0x000c,
+	0x2001, 0x8b16, 0x2004, 0xac02, 0x1210, 0x0804, 0x8872, 0xa006,
+	0x012e, 0x002e, 0x006e, 0x007e, 0x00ce, 0x00ee, 0x00fe, 0x0005,
+	0xa8c5, 0x0001, 0x0ca8, 0x0086, 0x0056, 0x2041, 0x0000, 0x2029,
+	0x0001, 0x2c20, 0x2019, 0x0002, 0x6218, 0x080c, 0x6a17, 0x080c,
+	0x6aaf, 0x080c, 0x8865, 0x005e, 0x008e, 0x0005, 0x0026, 0x0046,
+	0x0056, 0x0086, 0x00c6, 0x0156, 0x2c20, 0x2128, 0x20a9, 0x007f,
+	0x2009, 0x0000, 0x0016, 0x0036, 0x080c, 0x430a, 0x1170, 0x2c10,
+	0x2041, 0x0000, 0x2508, 0x0056, 0x2029, 0x0001, 0x080c, 0x6a17,
+	0x080c, 0x6aaf, 0x080c, 0x8865, 0x005e, 0x003e, 0x001e, 0x8108,
+	0x1f04, 0x88ea, 0x015e, 0x00ce, 0x008e, 0x005e, 0x004e, 0x002e,
+	0x0005, 0x0086, 0x0056, 0x6218, 0x2041, 0x0000, 0x2029, 0x0001,
+	0x2019, 0x0048, 0x080c, 0x6a17, 0x080c, 0x6aaf, 0x2c20, 0x080c,
+	0x8865, 0x005e, 0x008e, 0x0005, 0x0026, 0x0046, 0x0056, 0x0086,
+	0x00c6, 0x0156, 0x2c20, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016,
+	0x0036, 0x080c, 0x430a, 0x1150, 0x2c10, 0x2041, 0x0000, 0x2828,
+	0x080c, 0x6a17, 0x080c, 0x6aaf, 0x080c, 0x8865, 0x003e, 0x001e,
+	0x8108, 0x1f04, 0x8927, 0x015e, 0x00ce, 0x008e, 0x005e, 0x004e,
+	0x002e, 0x0005, 0x0016, 0x00f6, 0x8dff, 0x0168, 0x6800, 0xa07d,
+	0x0138, 0x6803, 0x0000, 0x6b52, 0x080c, 0x46a1, 0x2f68, 0x0cb0,
+	0x6b52, 0x080c, 0x46a1, 0x00fe, 0x001e, 0x0005, 0x00e6, 0x0046,
+	0x0036, 0x2061, 0x9200, 0x2071, 0x8b00, 0x7444, 0x7064, 0x8001,
+	0xa402, 0x12d8, 0x2100, 0xac06, 0x0168, 0x6000, 0xa086, 0x0000,
+	0x0148, 0x6008, 0xa206, 0x1130, 0x6018, 0xa1a0, 0x0006, 0x2424,
+	0xa406, 0x0140, 0xace0, 0x000c, 0x2001, 0x8b16, 0x2004, 0xac02,
+	0x1220, 0x0c08, 0xa085, 0x0001, 0x0008, 0xa006, 0x003e, 0x004e,
+	0x00ee, 0x0005, 0x00d6, 0x0006, 0x080c, 0x1488, 0x000e, 0x090c,
+	0x1410, 0x6837, 0x010d, 0x685e, 0x6956, 0x6c46, 0x684f, 0x0000,
+	0xa006, 0x68b2, 0x6802, 0x683a, 0x685a, 0x080c, 0x46a1, 0x00de,
+	0x0005, 0x6700, 0xa786, 0x0000, 0x0158, 0xa786, 0x0001, 0x0140,
+	0xa786, 0x000a, 0x0128, 0xa786, 0x0009, 0x0110, 0xa085, 0x0001,
+	0x0005, 0x00e6, 0x6018, 0x2070, 0x70a0, 0xa206, 0x00ee, 0x0005,
+	0xa186, 0x0013, 0x1128, 0x6004, 0xa082, 0x0085, 0x2008, 0x00c2,
+	0xa186, 0x0027, 0x1178, 0x080c, 0x5c37, 0x0036, 0x00d6, 0x6010,
+	0x2068, 0x2019, 0x0004, 0x080c, 0x8942, 0x00de, 0x003e, 0x080c,
+	0x5d10, 0x0005, 0xa186, 0x0014, 0x0d70, 0x080c, 0x6d55, 0x0005,
+	0x89d9, 0x89d7, 0x89d7, 0x89d7, 0x89d7, 0x89d7, 0x89d9, 0x080c,
+	0x1410, 0x080c, 0x5c37, 0x6003, 0x000c, 0x080c, 0x5d10, 0x0005,
+	0xa182, 0x008c, 0x1220, 0xa182, 0x0085, 0x0208, 0x001a, 0x080c,
+	0x6d55, 0x0005, 0x89f1, 0x89f1, 0x89f1, 0x89f1, 0x89f3, 0x89f8,
+	0x89f1, 0x080c, 0x1410, 0x00d6, 0x080c, 0x6d18, 0x00de, 0x0005,
+	0x080c, 0x6d18, 0x0005, 0x00e6, 0x6018, 0x2070, 0x7000, 0xd0ec,
+	0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071,
+	0x8b40, 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0118,
+	0x7030, 0x8000, 0x7032, 0xd5ac, 0x0118, 0x2071, 0x8b4a, 0x0451,
+	0x00ee, 0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091,
+	0x8000, 0x2071, 0x8b40, 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036,
+	0xd5b4, 0x0118, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0118, 0x2071,
+	0x8b4a, 0x0081, 0x00ee, 0x000e, 0x012e, 0x0005, 0x0126, 0x0006,
+	0x00e6, 0x2091, 0x8000, 0x2071, 0x8b42, 0x0021, 0x00ee, 0x000e,
+	0x012e, 0x0005, 0x2e04, 0x8000, 0x2072, 0x1220, 0x8e70, 0x2e04,
+	0x8000, 0x2072, 0x0005, 0x00e6, 0x2071, 0x8b40, 0x0c99, 0x00ee,
+	0x0005, 0x00e6, 0x2071, 0x8b44, 0x0c69, 0x00ee, 0x0005, 0x0001,
+	0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100,
+	0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0x2854
 };
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/scsi/scsi.c linux.15p9/drivers/scsi/scsi.c
--- linux.vanilla/drivers/scsi/scsi.c	Tue Jan  4 21:18:58 2000
+++ linux.15p9/drivers/scsi/scsi.c	Wed Feb 16 18:17:32 2000
@@ -277,6 +277,8 @@
 {"HP", "C2500A", "", BLIST_NOLUN},              /* scanjet iicx */
 {"YAMAHA","CDR100","1.00", BLIST_NOLUN},	/* Locks up if polled for lun != 0 */
 {"YAMAHA","CDR102","1.00", BLIST_NOLUN},	/* Locks up if polled for lun != 0 */
+{"YAMAHA","CRW8424S","1.0", BLIST_NOLUN},	/* Locks up if polled for lun != 0 */
+{"YAMAHA","CRW6416S","1.0c", BLIST_NOLUN},	/* Locks up if polled for lun != 0 */
 {"RELISYS", "Scorpio", "*", BLIST_NOLUN},	/* responds to all LUN */
 
 /*
@@ -290,6 +292,7 @@
 {"NRC","MBR-7","*", BLIST_FORCELUN | BLIST_SINGLELUN},
 {"NRC","MBR-7.4","*", BLIST_FORCELUN | BLIST_SINGLELUN},
 {"REGAL","CDC-4X","*", BLIST_MAX5LUN | BLIST_SINGLELUN},
+{"LASOUND","CDX7405","3.10", BLIST_MAX5LUN | BLIST_SINGLELUN},
 {"NAKAMICH","MJ-4.8S","*", BLIST_FORCELUN | BLIST_SINGLELUN},
 {"NAKAMICH","MJ-5.16S","*", BLIST_FORCELUN | BLIST_SINGLELUN},
 {"PIONEER","CD-ROM DRM-600","*", BLIST_FORCELUN | BLIST_SINGLELUN},
@@ -303,6 +306,7 @@
 {"iomega","jaz 1GB","J.86", BLIST_NOTQ | BLIST_NOLUN},
 {"CREATIVE","DVD-RAM RAM","*", BLIST_GHOST},
 {"MATSHITA","PD-2 LF-D100","*", BLIST_GHOST},
+{"AOpen","PD-2 DVD-520S","*", BLIST_GHOST},
 {"HITACHI","GF-1050","*", BLIST_GHOST},        /* Hitachi SCSI DVD-RAM */
 {"TOSHIBA","CDROM","*", BLIST_ISROM},
 {"TOSHIBA","DVD-RAM SD-W1101","*", BLIST_GHOST},
@@ -3452,6 +3456,8 @@
 }
 
 #ifdef MODULE
+
+MODULE_PARM(max_scsi_luns, "i");
 
 int init_module(void) 
 {
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/scsi/sd.c linux.15p9/drivers/scsi/sd.c
--- linux.vanilla/drivers/scsi/sd.c	Tue Jan  4 21:18:58 2000
+++ linux.15p9/drivers/scsi/sd.c	Mon Jan 24 19:40:33 2000
@@ -483,11 +483,16 @@
 	 * would be a ten byte read where only a six byte read was supported.
 	 * Also, on a system where READ CAPACITY failed, we have have read
 	 * past the end of the disk.
+	 *
+	 * Don't screw with the ten byte flag unless we are certain that
+	 * the drive does not understand the command /axboe
 	 */
 
 	if (SCpnt->sense_buffer[2] == ILLEGAL_REQUEST) {
 	    if (rscsi_disks[DEVICE_NR(SCpnt->request.rq_dev)].ten) {
-		rscsi_disks[DEVICE_NR(SCpnt->request.rq_dev)].ten = 0;
+		if (SCpnt->cmnd[0] == READ_10 || SCpnt->cmnd[0] == WRITE_10 ||
+		    SCpnt->sense_buffer[12] == 0x20)
+		    rscsi_disks[DEVICE_NR(SCpnt->request.rq_dev)].ten = 0;
 		requeue_sd_request(SCpnt);
 		result = 0;
 	    } else {
@@ -1016,7 +1021,7 @@
 	this_count = this_count << 1;
     }
 
-    if (((this_count > 0xff) ||  (block > 0x1fffff)) && rscsi_disks[dev].ten)
+    if (((this_count > 0xff) ||  (block > 0x1fffff)) || rscsi_disks[dev].ten)
     {
 	if (this_count > 0xffff)
 	    this_count = 0xffff;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/scsi/st.c linux.15p9/drivers/scsi/st.c
--- linux.vanilla/drivers/scsi/st.c	Sat Aug 14 02:26:50 1999
+++ linux.15p9/drivers/scsi/st.c	Wed Feb  9 16:01:00 2000
@@ -8,10 +8,10 @@
   order) Klaus Ehrenfried, Wolfgang Denk, Steve Hirsch, Andreas Koppenh"ofer,
   Michael Leodolter, Eyal Lebedinsky, J"org Weule, and Eric Youngdale.
 
-  Copyright 1992 - 1999 Kai Makisara
+  Copyright 1992 - 2000 Kai Makisara
 		 email Kai.Makisara@metla.fi
 
-  Last modified: Tue May 18 09:29:52 1999 by makisara@home
+  Last modified: Wed Feb  2 22:04:05 2000 by makisara@kai.makisara.local
   Some small formal changes - aeb, 950809
 */
 
@@ -595,8 +595,14 @@
 #endif
       return (-EBUSY);
     }
+    STp->in_use = 1;
     STp->rew_at_close = (MINOR(inode->i_rdev) & 0x80) == 0;
 
+    if (scsi_tapes[dev].device->host->hostt->module)
+	__MOD_INC_USE_COUNT(scsi_tapes[dev].device->host->hostt->module);
+    if(st_template.module)
+	__MOD_INC_USE_COUNT(st_template.module);
+
     if (mode != STp->current_mode) {
 #if DEBUG
       if (debugging)
@@ -618,6 +624,11 @@
       STp->buffer = new_tape_buffer(FALSE, need_dma_buffer);
       if (STp->buffer == NULL) {
 	printk(KERN_WARNING "st%d: Can't allocate tape buffer.\n", dev);
+	STp->in_use = 0;
+	if (scsi_tapes[dev].device->host->hostt->module)
+	    __MOD_DEC_USE_COUNT(scsi_tapes[dev].device->host->hostt->module);
+	if(st_template.module)
+	    __MOD_DEC_USE_COUNT(st_template.module);
 	return (-EBUSY);
       }
     }
@@ -651,17 +662,15 @@
     STp->nbr_waits = STp->nbr_finished = 0;
 #endif
 
-    if (scsi_tapes[dev].device->host->hostt->module)
-	__MOD_INC_USE_COUNT(scsi_tapes[dev].device->host->hostt->module);
-    if(st_template.module)
-	__MOD_INC_USE_COUNT(st_template.module);
-
     memset ((void *) &cmd[0], 0, 10);
     cmd[0] = TEST_UNIT_READY;
 
     SCpnt = st_do_scsi(NULL, STp, cmd, 0, STp->long_timeout, MAX_READY_RETRIES,
 		       TRUE);
     if (!SCpnt) {
+	(STp->buffer)->in_use = 0;
+	STp->buffer = NULL;
+	STp->in_use = 0;
 	if (scsi_tapes[dev].device->host->hostt->module)
 	    __MOD_DEC_USE_COUNT(scsi_tapes[dev].device->host->hostt->module);
 	if(st_template.module)
@@ -671,11 +680,16 @@
 
     if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
 	(SCpnt->sense_buffer[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */
-      memset ((void *) &cmd[0], 0, 10);
-      cmd[0] = TEST_UNIT_READY;
 
-      SCpnt = st_do_scsi(SCpnt, STp, cmd, 0, STp->long_timeout, MAX_READY_RETRIES,
-			 TRUE);
+      for (i=0; i < 10; i++) {
+	  memset ((void *) &cmd[0], 0, 10);
+	  cmd[0] = TEST_UNIT_READY;
+	  SCpnt = st_do_scsi(SCpnt, STp, cmd, 0, STp->long_timeout, MAX_READY_RETRIES,
+			     TRUE);
+	  if ((SCpnt->sense_buffer[0] & 0x70) != 0x70 ||
+	      (SCpnt->sense_buffer[2] & 0x0f) != UNIT_ATTENTION)
+	      break;
+      }
 
       (STp->device)->was_reset = 0;
       STp->partition = STp->new_partition = 0;
@@ -709,7 +723,6 @@
       STp->ps[0].drv_file = STp->ps[0].drv_block = (-1);
       STp->partition = STp->new_partition = 0;
       STp->door_locked = ST_UNLOCKED;
-      STp->in_use = 1;
       return 0;
     }
 
@@ -787,6 +800,7 @@
 	scsi_release_command(SCpnt);
 	(STp->buffer)->in_use = 0;
 	STp->buffer = NULL;
+	STp->in_use = 0;
 	if (scsi_tapes[dev].device->host->hostt->module)
 	    __MOD_DEC_USE_COUNT(scsi_tapes[dev].device->host->hostt->module);
 	if(st_template.module)
@@ -820,6 +834,7 @@
       if ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR) {
 	(STp->buffer)->in_use = 0;
 	STp->buffer = NULL;
+	STp->in_use = 0;
 	if (scsi_tapes[dev].device->host->hostt->module)
 	    __MOD_DEC_USE_COUNT(scsi_tapes[dev].device->host->hostt->module);
 	if(st_template.module)
@@ -837,13 +852,15 @@
 	printk(ST_DEB_MSG "st%d: Updating partition number in status.\n", dev);
 #endif
       if ((STp->partition = find_partition(inode)) < 0) {
+	i = STp->partition;
 	(STp->buffer)->in_use = 0;
 	STp->buffer = NULL;
+	STp->in_use = 0;
 	if (scsi_tapes[dev].device->host->hostt->module)
 	    __MOD_DEC_USE_COUNT(scsi_tapes[dev].device->host->hostt->module);
 	if(st_template.module)
 	    __MOD_DEC_USE_COUNT(st_template.module);
-	return STp->partition;
+	return i;
       }
       STp->new_partition = STp->partition;
       STp->nbr_partitions = 1;  /* This guess will be updated when necessary */
@@ -856,6 +873,7 @@
 	  (i = set_mode_densblk(inode, STp, STm)) < 0) {
 	(STp->buffer)->in_use = 0;
 	STp->buffer = NULL;
+	STp->in_use = 0;
 	if (scsi_tapes[dev].device->host->hostt->module)
 	    __MOD_DEC_USE_COUNT(scsi_tapes[dev].device->host->hostt->module);
 	if(st_template.module)
@@ -869,8 +887,6 @@
       }
     }
 
-    STp->in_use = 1;
-
     return 0;
 }
 
@@ -898,19 +914,25 @@
     STm = &(STp->modes[STp->current_mode]);
     STps = &(STp->ps[STp->partition]);
 
+    if ( STps->rw == ST_WRITING && !(STp->device)->was_reset) {
+      result = flush_write_buffer(STp);
+      if (result != 0 && result != (-ENOSPC))
+	  goto out;
+    }
+
     if (STp->can_partitions &&
-	(result = update_partition(inode)) < 0) {
+	(result2 = update_partition(inode)) < 0) {
 #if DEBUG
       if (debugging)
 	printk(ST_DEB_MSG "st%d: update_partition at close failed.\n", dev);
 #endif
+      if (result == 0)
+	  result = result2;
       goto out;
     }
 
     if ( STps->rw == ST_WRITING && !(STp->device)->was_reset) {
 
-      result = flush_write_buffer(STp);
-
 #if DEBUG
       if (debugging) {
 	printk(ST_DEB_MSG "st%d: File length %ld bytes.\n",
@@ -920,41 +942,38 @@
       }
 #endif
 
-      if (result == 0 || result == (-ENOSPC)) {
+      memset(cmd, 0, 10);
+      cmd[0] = WRITE_FILEMARKS;
+      cmd[4] = 1 + STp->two_fm;
 
-	memset(cmd, 0, 10);
-	cmd[0] = WRITE_FILEMARKS;
-	cmd[4] = 1 + STp->two_fm;
-
-	SCpnt = st_do_scsi(NULL, STp, cmd, 0, STp->timeout, MAX_WRITE_RETRIES,
-			   TRUE);
-	if (!SCpnt)
+      SCpnt = st_do_scsi(NULL, STp, cmd, 0, STp->timeout, MAX_WRITE_RETRIES,
+			 TRUE);
+      if (!SCpnt)
 	  goto out;
 
-	if ((STp->buffer)->last_result_fatal != 0 &&
-	    ((SCpnt->sense_buffer[0] & 0x70) != 0x70 ||
-	     (SCpnt->sense_buffer[2] & 0x4f) != 0x40 ||
-	     ((SCpnt->sense_buffer[0] & 0x80) != 0 &&
-	      (SCpnt->sense_buffer[3] | SCpnt->sense_buffer[4] |
-	       SCpnt->sense_buffer[5] |
-	       SCpnt->sense_buffer[6]) == 0))) {
-	    /* Filter out successful write at EOM */
-	    scsi_release_command(SCpnt);
-	    SCpnt = NULL;
-	    printk(KERN_ERR "st%d: Error on write filemark.\n", dev);
-	    if (result == 0)
-		result = (-EIO);
-	}
-	else {
+      if ((STp->buffer)->last_result_fatal != 0 &&
+	  ((SCpnt->sense_buffer[0] & 0x70) != 0x70 ||
+	   (SCpnt->sense_buffer[2] & 0x4f) != 0x40 ||
+	   ((SCpnt->sense_buffer[0] & 0x80) != 0 &&
+	    (SCpnt->sense_buffer[3] | SCpnt->sense_buffer[4] |
+	     SCpnt->sense_buffer[5] |
+	     SCpnt->sense_buffer[6]) == 0))) {
+	  /* Filter out successful write at EOM */
+	  scsi_release_command(SCpnt);
+	  SCpnt = NULL;
+	  printk(KERN_ERR "st%d: Error on write filemark.\n", dev);
+	  if (result == 0)
+	      result = (-EIO);
+      }
+      else {
 	  scsi_release_command(SCpnt);
 	  SCpnt = NULL;
 	  if (STps->drv_file >= 0)
 	      STps->drv_file++ ;
 	  STps->drv_block = 0;
 	  if (STp->two_fm)
-	    cross_eof(STp, FALSE);
+	      cross_eof(STp, FALSE);
 	  STps->eof = ST_FM;
-	}
       }
 
 #if DEBUG
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/sound/cmpci.c linux.15p9/drivers/sound/cmpci.c
--- linux.vanilla/drivers/sound/cmpci.c	Wed Oct 20 01:12:48 1999
+++ linux.15p9/drivers/sound/cmpci.c	Wed Feb 16 18:38:07 2000
@@ -21,7 +21,7 @@
  *      along with this program; if not, write to the Free Software
  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Special thanks to David C. Niemi
+ * Special thanks to David C. Niemi, Jan Pfeifer
  *
  *
  * Module command line parameters:
@@ -57,9 +57,45 @@
  *                     reported by Johan Maes <joma@telindus.be>
  *    22.03.99   0.12  return EAGAIN instead of EBUSY when O_NONBLOCK
  *                     read/write cannot be executed
+ *    20 09 99   0.13  merged the generic changes in sonicvibes since this
+ *		       diverged.
+ *    18.08.99   1.5   Only deallocate DMA buffer when unloading.
+ *    02.09.99   1.6   Enable SPDIF LOOP
+ *                     Change the mixer read back
+ *    21.09.99   2.33  Use RCS version aas driver version.
+ *                     Add support for modem, S/PDIF loop and 4 channels.
+ *                     (8738 only)
+ *                     Fix bug cause x11amp cannot play.
+ *    $Log: cmpci.c,v $
+ *    Revision 2.41  1999/10/27 02:00:05  cltien
+ *    Now the fragsize for modem is activated by parameter.
+ *
+ *    Revision 2.40  1999/10/26 23:38:26  cltien
+ *    Remove debugging message in cm_write which may cause module counter not 0.
+ *
+ *    Revision 2.39  1999/10/26 21:52:50  cltien
+ *    I forgor too adjust mic recording volume, as it should be moved to 5MUTEMONO.
+ *    Change the DYNAMIC macro to FIXEDDMA, which means static DMA buffer.
+ *
+ *    Revision 2.38  1999/10/08 21:59:03  cltien
+ *    Set FLINKON and reset FLINKOFF for modem.
+ *
+ *    Revision 2.37  1999/09/28 02:57:04  cltien
+ *    Add set_bus_master() to make sure bus master enabled.
+ *
+ *    Revision 2.36  1999/09/22 14:15:03  cltien
+ *    Use open_sem to avoid multiple access to open_mode.
+ *    Use wakeup in IntrClose to activate process in waiting queue.
+ *
+ *    Revision 2.35  1999/09/22 13:20:53  cltien
+ *    Use open_mode to check if DAC in used. Also more check in IntrWrite and IntrClose. Now the modem can access DAC safely.
+ *
+ *    Revision 2.34  1999/09/22 03:29:57  cltien
+ *    Use module count to decide which one to access the dac.
+ *
  *
  */
-
+ 
 /*****************************************************************************/
       
 #include <linux/config.h>
@@ -251,6 +287,7 @@
 		unsigned fragsize;
 		unsigned dmasize;
 		unsigned fragsamples;
+		unsigned dmasamples;
 		/* OSS stuff */
 		unsigned mapped:1;
 		unsigned ready:1;
@@ -275,6 +312,7 @@
 /* --------------------------------------------------------------------- */
 
 static struct cm_state *devs = NULL;
+static struct cm_state *devaudio = NULL;
 static unsigned long wavetable_mem = 0;
 
 /* --------------------------------------------------------------------- */
@@ -330,7 +368,7 @@
 	outl(addr, s->iobase + CODEC_CMI_CH0_FRAME1);
 	outw(count, s->iobase + CODEC_CMI_CH0_FRAME2);
 	outb(inb(s->iobase + CODEC_CMI_FUNCTRL0) & ~1, s->iobase + CODEC_CMI_FUNCTRL0);
-	outb(inb(s->iobase + CODEC_CMI_FUNCTRL0 + 2) | 1, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
+//	outb(inb(s->iobase + CODEC_CMI_FUNCTRL0 + 2) | 1, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
 }
 
 static void set_dmaadc(struct cm_state *s, unsigned int addr, unsigned int count)
@@ -339,13 +377,16 @@
 	outl(addr, s->iobase + CODEC_CMI_CH1_FRAME1);
 	outw(count, s->iobase + CODEC_CMI_CH1_FRAME2);
 	outb(inb(s->iobase + CODEC_CMI_FUNCTRL0) | 2, s->iobase + CODEC_CMI_FUNCTRL0);
-	outb(inb(s->iobase + CODEC_CMI_FUNCTRL0 + 2) | 2, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
+//	outb(inb(s->iobase + CODEC_CMI_FUNCTRL0 + 2) | 2, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
 }
 
 extern __inline__ unsigned get_dmadac(struct cm_state *s)
 {
 	unsigned int curr_addr;
 
+	if (!s->dma_dac.dmasize || !(s->enable & CM_CENABLE_PE))
+		return 0;
+
 	curr_addr = inl(s->iobase + CODEC_CMI_CH0_FRAME1);
 	curr_addr -= virt_to_bus(s->dma_dac.rawbuf);
 	curr_addr = s->dma_dac.dmasize - curr_addr;
@@ -357,6 +398,9 @@
 {
 	unsigned int curr_addr;
 
+	if (!s->dma_adc.dmasize || !(s->enable & CM_CENABLE_RE))
+		return 0;
+
 	curr_addr = inl(s->iobase + CODEC_CMI_CH1_FRAME1);
 	curr_addr -= virt_to_bus(s->dma_adc.rawbuf);
 	curr_addr = s->dma_adc.dmasize - curr_addr;
@@ -420,7 +464,7 @@
 	{ 22050,	(16000 + 22050) / 2,	(22050 + 32000) / 2,	2 },
 	{ 32000,	(22050 + 32000) / 2,	(32000 + 44100) / 2,	6 },
 	{ 44100,	(32000 + 44100) / 2,	(44100 + 48000) / 2,	3 },
-	{ 48000,	48000,			48000,			7 }
+	{ 48000,	(44100 + 48000) /2,	48000,			7 }
 };
 
 static void set_dac_rate(struct cm_state *s, unsigned rate)
@@ -484,10 +528,12 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&s->lock, flags);
+	/* disable channel */
+	outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
 	s->enable &= ~CM_CENABLE_RE;
 	/* disable interrupt */
 	outb(inb(s->iobase + CODEC_CMI_INT_HLDCLR + 2) & ~2, s->iobase + CODEC_CMI_INT_HLDCLR + 2);
-	/* disable channel and reset */
+	/* reset */
 	outb(s->enable | CM_CH1_RESET, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
 	udelay(10);
 	outb(s->enable & ~CM_CH1_RESET, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
@@ -499,10 +545,12 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&s->lock, flags);
+	/* disable channel */
 	s->enable &= ~CM_CENABLE_PE;
+	outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
 	/* disable interrupt */
 	outb(inb(s->iobase + CODEC_CMI_INT_HLDCLR + 2) & ~1, s->iobase + CODEC_CMI_INT_HLDCLR + 2);
-	/* disable channel and reset */
+	/* reset */
 	outb(s->enable | CM_CH0_RESET, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
 	udelay(10);
 	outb(s->enable & ~CM_CH0_RESET, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
@@ -515,10 +563,10 @@
 
 	spin_lock_irqsave(&s->lock, flags);
 	if ((s->dma_dac.mapped || s->dma_dac.count > 0) && s->dma_dac.ready) {
+		outb(inb(s->iobase + CODEC_CMI_INT_HLDCLR + 2) | 1, s->iobase + CODEC_CMI_INT_HLDCLR + 2);
 		s->enable |= CM_CENABLE_PE;
 		outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
 	}
-	outb(inb(s->iobase + CODEC_CMI_INT_HLDCLR + 2) | 1, s->iobase + CODEC_CMI_INT_HLDCLR + 2);
 	spin_unlock_irqrestore(&s->lock, flags);
 }	
 
@@ -529,10 +577,10 @@
 	spin_lock_irqsave(&s->lock, flags);
 	if ((s->dma_adc.mapped || s->dma_adc.count < (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize)) 
 	    && s->dma_adc.ready) {
+		outb(inb(s->iobase + CODEC_CMI_INT_HLDCLR + 2) | 2, s->iobase + CODEC_CMI_INT_HLDCLR + 2);
 		s->enable |= CM_CENABLE_RE;
 		outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
 	}
-	outb(inb(s->iobase + CODEC_CMI_INT_HLDCLR + 2) | 2, s->iobase + CODEC_CMI_INT_HLDCLR + 2);
 	spin_unlock_irqrestore(&s->lock, flags);
 }	
 
@@ -585,16 +633,17 @@
 	db->hwptr = db->swptr = db->total_bytes = db->count = db->error = db->endcleared = 0;
 	if (!db->rawbuf) {
 		db->ready = db->mapped = 0;
-		for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER && !db->rawbuf; order--)
-			db->rawbuf = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA, order);
+		for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--)
+			if ((db->rawbuf = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA, order)))
+				break;
 		if (!db->rawbuf)
 			return -ENOMEM;
 		db->buforder = order;
 		if ((virt_to_bus(db->rawbuf) ^ (virt_to_bus(db->rawbuf) + (PAGE_SIZE << db->buforder) - 1)) & ~0xffff)
-			printk(KERN_DEBUG "cm: DMA buffer crosses 64k boundary: busaddr 0x%lx  size %ld\n", 
+			printk(KERN_DEBUG "cmpci: DMA buffer crosses 64k boundary: busaddr 0x%lx  size %ld\n", 
 			       virt_to_bus(db->rawbuf), PAGE_SIZE << db->buforder);
 		if ((virt_to_bus(db->rawbuf) + (PAGE_SIZE << db->buforder) - 1) & ~0xffffff)
-			printk(KERN_DEBUG "cm: DMA buffer beyond 16MB: busaddr 0x%lx  size %ld\n", 
+			printk(KERN_DEBUG "cmpci: DMA buffer beyond 16MB: busaddr 0x%lx  size %ld\n", 
 			       virt_to_bus(db->rawbuf), PAGE_SIZE << db->buforder);
 		/* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */
 		mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
@@ -621,17 +670,21 @@
 	db->fragsize = 1 << db->fragshift;
 	if (db->ossmaxfrags >= 4 && db->ossmaxfrags < db->numfrag)
 		db->numfrag = db->ossmaxfrags;
-#if 1
-	/* to make fragsize >= 4096 */
-	while (db->fragsize < 4096 && db->numfrag >= 4)
-	{
-		db->fragsize *= 2;
-		db->fragshift++;
-		db->numfrag /= 2;
+ 	/* to make fragsize >= 4096 */
+#if 0 	
+ 	if(s->modem)
+ 	{
+	 	while (db->fragsize < 4096 && db->numfrag >= 4)
+		{
+			db->fragsize *= 2;
+ 			db->fragshift++;
+ 			db->numfrag /= 2;
+ 		}
 	}
-#endif
+#endif	
 	db->fragsamples = db->fragsize >> sample_shift[fmt];
 	db->dmasize = db->numfrag << db->fragshift;
+	db->dmasamples = db->dmasize >> sample_shift[fmt];
 	memset(db->rawbuf, (fmt & CM_CFMT_16BIT) ? 0 : 0x80, db->dmasize);
 	spin_lock_irqsave(&s->lock, flags);
 	if (rec) {
@@ -663,6 +716,7 @@
 		len -= x;
 	}
 	memset(buf + bptr, c, len);
+	outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
 }
 
 /* call with spinlock held! */
@@ -750,25 +804,26 @@
 	unsigned int intsrc, intstat;
 	
 	/* fastpath out, to ease interrupt sharing */
-	intsrc = inb(s->iobase + CODEC_CMI_INT_STATUS);
-	if (!(intsrc & (CM_INT_CH0 | CM_INT_CH1)))
+	intsrc = inl(s->iobase + CODEC_CMI_INT_STATUS);
+	if (!(intsrc & 0x80000000))
 		return;
 	spin_lock(&s->lock);
 	intstat = inb(s->iobase + CODEC_CMI_INT_HLDCLR + 2);
-	/* disable interrupt */
+	/* acknowledge interrupt */
 	if (intsrc & CM_INT_CH0)
+	{
 		outb(intstat & ~1, s->iobase + CODEC_CMI_INT_HLDCLR + 2);
+		udelay(10);
+		outb(intstat | 1, s->iobase + CODEC_CMI_INT_HLDCLR + 2);
+	}
 	if (intsrc & CM_INT_CH1)
+	{
 		outb(intstat & ~2, s->iobase + CODEC_CMI_INT_HLDCLR + 2);
+		udelay(10);
+		outb(intstat | 2, s->iobase + CODEC_CMI_INT_HLDCLR + 2);
+	}
 	cm_update_ptr(s);
-#ifdef SOUND_CONFIG_CMPCI_MIDI
 	cm_handle_midi(s);
-#endif
-	/* enable interrupt */
-	if (intsrc & CM_INT_CH0)
-		outb(intstat | 1, s->iobase + CODEC_CMI_INT_HLDCLR + 2);
-	if (intsrc & CM_INT_CH1)
-		outb(intstat | 2, s->iobase + CODEC_CMI_INT_HLDCLR + 2);
 	spin_unlock(&s->lock);
 }
 
@@ -786,7 +841,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static const char invalid_magic[] = KERN_CRIT "cm: invalid magic value\n";
+static const char invalid_magic[] = KERN_CRIT "cmpci: invalid magic value\n";
 
 #ifdef CONFIG_SOUND_CMPCI	/* support multiple chips */
 #define VALIDATE_STATE(s)
@@ -806,6 +861,7 @@
 #define MT_5MUTE      2
 #define MT_4MUTEMONO  3
 #define MT_6MUTE      4
+#define MT_5MUTEMONO  5
 
 static const struct {
 	unsigned left;
@@ -816,7 +872,7 @@
 } mixtable[SOUND_MIXER_NRDEVICES] = {
 	[SOUND_MIXER_CD]     = { DSP_MIX_CDVOLIDX_L,     DSP_MIX_CDVOLIDX_R,     MT_5MUTE,     0x04, 0x02 },
 	[SOUND_MIXER_LINE]   = { DSP_MIX_LINEVOLIDX_L,   DSP_MIX_LINEVOLIDX_R,   MT_5MUTE,     0x10, 0x08 },
-	[SOUND_MIXER_MIC]    = { DSP_MIX_MICVOLIDX,      CODEC_CMI_MIXER2,       MT_4MUTEMONO, 0x01, 0x01 },
+	[SOUND_MIXER_MIC]    = { DSP_MIX_MICVOLIDX,      DSP_MIX_MICVOLIDX,      MT_5MUTEMONO, 0x01, 0x01 },
 	[SOUND_MIXER_SYNTH]  = { DSP_MIX_FMVOLIDX_L,  	 DSP_MIX_FMVOLIDX_R,     MT_5MUTE,     0x40, 0x00 },
 	[SOUND_MIXER_VOLUME] = { DSP_MIX_MASTERVOLIDX_L, DSP_MIX_MASTERVOLIDX_R, MT_5MUTE,     0x00, 0x00 },
 	[SOUND_MIXER_PCM]    = { DSP_MIX_VOICEVOLIDX_L,  DSP_MIX_VOICEVOLIDX_R,  MT_5MUTE,     0x00, 0x00 }
@@ -849,10 +905,16 @@
 		r = l;
 		break;
 
+	case MT_5MUTEMONO:
+		r = l;
+		rl = 100 - 3 * ((l >> 3) & 31);
+		rr = rl;
+		break;
+				
 	case MT_5MUTE:
 	default:
-		rl = 100 - 3 * (l & 31);
-		rr = 100 - 3 * (r & 31);
+		rl = 100 - 3 * ((l >> 3) & 31);
+		rr = 100 - 3 * ((r >> 3) & 31);
 		break;
 				
 	case MT_6MUTE:
@@ -990,7 +1052,7 @@
 		}
 		spin_lock_irqsave(&s->lock, flags);
 		wrmixer(s, DSP_MIX_ADCMIXIDX_L, j);
-		wrmixer(s, DSP_MIX_ADCMIXIDX_R, (j & 1) | j>>1);
+		wrmixer(s, DSP_MIX_ADCMIXIDX_R, (j & 1) | (j>>1));
 		spin_unlock_irqrestore(&s->lock, flags);
 		return 0;
 
@@ -1039,6 +1101,14 @@
 			outb((inb(s->iobase + CODEC_CMI_MIXER2) & ~0x0e) | rr<<1, s->iobase + CODEC_CMI_MIXER2);
 			break;
 			
+		case MT_5MUTEMONO:
+			r = l;
+			rl = l < 4 ? 0 : (l - 5) / 3;
+			rr = rl >> 2;
+ 			wrmixer(s, mixtable[i].left, rl<<3);
+			outb((inb(s->iobase + CODEC_CMI_MIXER2) & ~0x0e) | rr<<1, s->iobase + CODEC_CMI_MIXER2);
+			break;
+				
 		case MT_5MUTE:
 			rl = l < 4 ? 0 : (l - 5) / 3;
 			rr = r < 4 ? 0 : (r - 5) / 3;
@@ -1122,8 +1192,6 @@
 	&cm_release_mixdev,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
 
@@ -1131,7 +1199,7 @@
 
 static int drain_dac(struct cm_state *s, int nonblock)
 {
-        struct wait_queue wait = { current, NULL };
+	struct wait_queue wait = { current, NULL} ;
 	unsigned long flags;
 	int count, tmo;
 
@@ -1155,7 +1223,7 @@
 		tmo = (count * HZ) / s->ratedac;
 		tmo >>= sample_shift[(s->fmt >> CM_CFMT_DACSHIFT) & CM_CFMT_MASK];
 		if (!schedule_timeout(tmo ? : 1) && tmo)
-			printk(KERN_DEBUG "cm: dma timed out??\n");
+			printk(KERN_DEBUG "cmpci: dma timed out??\n");
         }
         remove_wait_queue(&s->dma_dac.wait, &wait);
         current->state = TASK_RUNNING;
@@ -1202,7 +1270,18 @@
 			start_adc(s);
 			if (file->f_flags & O_NONBLOCK)
 				return ret ? ret : -EAGAIN;
-			interruptible_sleep_on(&s->dma_adc.wait);
+			if (!interruptible_sleep_on_timeout(&s->dma_adc.wait, HZ)) {
+				printk(KERN_DEBUG "cmpci: read: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
+				       s->dma_adc.dmasize, s->dma_adc.fragsize, s->dma_adc.count,
+				       s->dma_adc.hwptr, s->dma_adc.swptr);
+				stop_adc(s);
+				spin_lock_irqsave(&s->lock, flags);
+				set_dmaadc(s, virt_to_bus(s->dma_adc.rawbuf), s->dma_adc.dmasamples);
+				/* program sample counts */
+				outw(s->dma_adc.fragsamples-1, s->iobase + CODEC_CMI_CH1_FRAME2 + 2);
+				s->dma_adc.count = s->dma_adc.hwptr = s->dma_adc.swptr = 0;
+				spin_unlock_irqrestore(&s->lock, flags);
+			}
 			if (signal_pending(current))
 				return ret ? ret : -ERESTARTSYS;
 			continue;
@@ -1262,7 +1341,18 @@
 			start_dac(s);
 			if (file->f_flags & O_NONBLOCK)
 				return ret ? ret : -EAGAIN;
-			interruptible_sleep_on(&s->dma_dac.wait);
+			if (!interruptible_sleep_on_timeout(&s->dma_dac.wait, HZ)) {
+				printk(KERN_DEBUG "cmpci: write: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
+				       s->dma_dac.dmasize, s->dma_dac.fragsize, s->dma_dac.count,
+				       s->dma_dac.hwptr, s->dma_dac.swptr);
+				stop_dac(s);
+				spin_lock_irqsave(&s->lock, flags);
+				set_dmadac(s, virt_to_bus(s->dma_dac.rawbuf), s->dma_dac.dmasamples);
+				/* program sample counts */
+				outw(s->dma_dac.fragsamples-1, s->iobase + CODEC_CMI_CH0_FRAME2 + 2);
+				s->dma_dac.count = s->dma_dac.hwptr = s->dma_dac.swptr = 0;
+				spin_unlock_irqrestore(&s->lock, flags);
+			}
 			if (signal_pending(current))
 				return ret ? ret : -ERESTARTSYS;
 			continue;
@@ -1630,9 +1720,11 @@
         case SOUND_PCM_READ_BITS:
 		return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (CM_CFMT_16BIT << CM_CFMT_ADCSHIFT) : (CM_CFMT_16BIT << CM_CFMT_DACSHIFT))) ? 16 : 8, (int *)arg);
 
+        case SOUND_PCM_READ_FILTER:
+		return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg);
+
         case SOUND_PCM_WRITE_FILTER:
         case SNDCTL_DSP_SETSYNCRO:
-        case SOUND_PCM_READ_FILTER:
                 return -EINVAL;
 		
 	}
@@ -1721,17 +1813,15 @@
 	&cm_release,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
 
-#ifdef CONFIG_SOUND_CMPCI_MIDI
 /* --------------------------------------------------------------------- */
 
 static ssize_t cm_midi_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
 	struct cm_state *s = (struct cm_state *)file->private_data;
+	struct wait_queue wait = { current , NULL };
 	ssize_t ret;
 	unsigned long flags;
 	unsigned ptr;
@@ -1742,7 +1832,10 @@
 		return -ESPIPE;
 	if (!access_ok(VERIFY_WRITE, buffer, count))
 		return -EFAULT;
+	if (count == 0)
+		return 0;
 	ret = 0;
+	add_wait_queue(&s->midi.iwait, &wait);
 	while (count > 0) {
 		spin_lock_irqsave(&s->lock, flags);
 		ptr = s->midi.ird;
@@ -1753,15 +1846,27 @@
 		if (cnt > count)
 			cnt = count;
 		if (cnt <= 0) {
-			if (file->f_flags & O_NONBLOCK)
-				return ret ? ret : -EAGAIN;
-			interruptible_sleep_on(&s->midi.iwait);
-			if (signal_pending(current))
-				return ret ? ret : -ERESTARTSYS;
+			if (file->f_flags & O_NONBLOCK) 
+			{
+				if (!ret)
+					ret = -EAGAIN;
+				break;
+			}
+			current->state = TASK_INTERRUPTIBLE;
+			schedule();
+			if (signal_pending(current)) 
+			{
+				if (!ret)
+					ret = -ERESTARTSYS;
+				break;
+			}
 			continue;
 		}
-		if (copy_to_user(buffer, s->midi.ibuf + ptr, cnt))
-			return ret ? ret : -EFAULT;
+		if (copy_to_user(buffer, s->midi.ibuf + ptr, cnt)) {
+			if (!ret)
+				ret = -EFAULT;
+			break;
+		}
 		ptr = (ptr + cnt) % MIDIINBUF;
 		spin_lock_irqsave(&s->lock, flags);
 		s->midi.ird = ptr;
@@ -1770,13 +1875,17 @@
 		count -= cnt;
 		buffer += cnt;
 		ret += cnt;
+		break;
 	}
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&s->midi.iwait, &wait);
 	return ret;
 }
 
 static ssize_t cm_midi_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
 {
 	struct cm_state *s = (struct cm_state *)file->private_data;
+	struct wait_queue wait = { current, NULL };
 	ssize_t ret;
 	unsigned long flags;
 	unsigned ptr;
@@ -1787,7 +1896,10 @@
 		return -ESPIPE;
 	if (!access_ok(VERIFY_READ, buffer, count))
 		return -EFAULT;
+	if (count == 0)
+		return 0;
 	ret = 0;
+	add_wait_queue(&s->midi.owait, &wait);
 	while (count > 0) {
 		spin_lock_irqsave(&s->lock, flags);
 		ptr = s->midi.owr;
@@ -1800,15 +1912,25 @@
 		if (cnt > count)
 			cnt = count;
 		if (cnt <= 0) {
-			if (file->f_flags & O_NONBLOCK)
-				return ret ? ret : -EAGAIN;
-			interruptible_sleep_on(&s->midi.owait);
-			if (signal_pending(current))
-				return ret ? ret : -ERESTARTSYS;
+			if (file->f_flags & O_NONBLOCK) {
+				if (!ret)
+					ret = -EAGAIN;
+				break;
+			}
+ 			current->state = TASK_INTERRUPTIBLE;
+			schedule();
+			if (signal_pending(current)) {
+				if (!ret)
+					ret = -ERESTARTSYS;
+				break;
+			}
 			continue;
 		}
-		if (copy_from_user(s->midi.obuf + ptr, buffer, cnt))
-			return ret ? ret : -EFAULT;
+		if (copy_from_user(s->midi.obuf + ptr, buffer, cnt)) {
+			if (!ret)
+				ret = -EFAULT;
+			break;
+		}
 		ptr = (ptr + cnt) % MIDIOUTBUF;
 		spin_lock_irqsave(&s->lock, flags);
 		s->midi.owr = ptr;
@@ -1821,6 +1943,8 @@
 		cm_handle_midi(s);
 		spin_unlock_irqrestore(&s->lock, flags);
 	}
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&s->midi.owait, &wait);
 	return ret;
 }
 
@@ -1908,14 +2032,15 @@
 static int cm_midi_release(struct inode *inode, struct file *file)
 {
 	struct cm_state *s = (struct cm_state *)file->private_data;
-        struct wait_queue wait = { current, NULL };
+	struct wait_queue wait = { current, NULL};
+
 	unsigned long flags;
 	unsigned count, tmo;
 
 	VALIDATE_STATE(s);
 
 	if (file->f_mode & FMODE_WRITE) {
-		current->state = TASK_INTERRUPTIBLE;
+ current->state = TASK_INTERRUPTIBLE;
 		add_wait_queue(&s->midi.owait, &wait);
 		for (;;) {
 			spin_lock_irqsave(&s->lock, flags);
@@ -1932,7 +2057,7 @@
 			}
 			tmo = (count * HZ) / 3100;
 			if (!schedule_timeout(tmo ? : 1) && tmo)
-				printk(KERN_DEBUG "cm: midi timed out??\n");
+				printk(KERN_DEBUG "cmpci: midi timed out??\n");
 		}
 		remove_wait_queue(&s->midi.owait, &wait);
 		current->state = TASK_RUNNING;
@@ -1968,15 +2093,11 @@
 	&cm_midi_release,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
-#endif
 
 /* --------------------------------------------------------------------- */
 
-#ifdef CONFIG_SOUND_CMPCI_FM
 static int cm_dmfm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
 	static const unsigned char op_offset[18] = {
@@ -2144,11 +2265,8 @@
 	&cm_dmfm_release,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
-#endif /* CONFIG_SOUND_CMPCI_FM */
 
 /* --------------------------------------------------------------------- */
 
@@ -2176,15 +2294,39 @@
 };
 
 #ifdef MODULE
-__initfunc(int init_module(void))
+static int	spdif_loop = 0;
+static int	four_ch = 0;
+static int	rear_out = 0;
+MODULE_PARM(spdif_loop, "i");
+MODULE_PARM(four_ch, "i");
+MODULE_PARM(rear_out, "i");
+
+int  __init init_module(void)
+#else
+#ifdef CONFIG_SOUND_CMPCI_SPDIFLOOP
+static int	spdif_loop = 1;
+#else
+static int	spdif_loop = 0;
+#endif
+#ifdef CONFIG_SOUND_CMPCI_4CH
+static int	four_ch = 1;
+#else
+static int	four_ch = 0;
+#endif
+#ifdef CONFIG_SOUND_CMPCI_REAR
+static int	rear_out = 1;
 #else
-__initfunc(int init_cmpci(void))
+static int	read_out = 0;
+#endif
+
+int __init init_cmpci(void)
 #endif
 {
 	struct cm_state *s;
 	struct pci_dev *pcidev = NULL;
 	mm_segment_t fs;
 	int i, val, index = 0;
+	
 	struct {
 		unsigned short	deviceid;
 		char		*devicename;
@@ -2200,10 +2342,10 @@
 	if (!pci_present())   /* No PCI bus in this machine! */
 #endif
 		return -ENODEV;
-	printk(KERN_INFO "cm: version v1.1 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "cmpci: version v2.41-nomodem time " __TIME__ " " __DATE__ "\n");
 #if 0
 	if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT)))
-		printk(KERN_INFO "cm: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n");
+		printk(KERN_INFO "cmpci: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n");
 #endif
 	while (index < NR_DEVICE && pcidev == NULL && (
  	       (pcidev = pci_find_device(PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338A, pcidev)) ||
@@ -2212,7 +2354,7 @@
 		if (pcidev->irq == 0)
 			continue;
 		if (!(s = kmalloc(sizeof(struct cm_state), GFP_KERNEL))) {
-			printk(KERN_WARNING "cm: out of memory\n");
+			printk(KERN_WARNING "cmpci: out of memory\n");
 			continue;
 		}
 		/* search device name */
@@ -2233,65 +2375,60 @@
 		s->open_sem = MUTEX;
 		s->magic = CM_MAGIC;
 		s->iobase = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
-#ifdef CONFIG_SOUND_CMPCI_FM
 		s->iosynth = 0x388;
-#endif
-#ifdef CONFIG_SOUND_CMPCI_MIDI
 		s->iomidi = 0x330;
-#endif
 		if (s->iobase == 0)
 			continue;
 		s->irq = pcidev->irq;
 
 		if (check_region(s->iobase, CM_EXTENT_CODEC)) {
-			printk(KERN_ERR "cm: io ports %#x-%#x in use\n", s->iobase, s->iobase+CM_EXTENT_CODEC-1);
+			printk(KERN_ERR "cmpci: io ports %#x-%#x in use\n", s->iobase, s->iobase+CM_EXTENT_CODEC-1);
 			goto err_region5;
 		}
 		request_region(s->iobase, CM_EXTENT_CODEC, "cmpci");
-#ifdef CONFIG_SOUND_CMPCI_MIDI
 		if (check_region(s->iomidi, CM_EXTENT_MIDI)) {
-			printk(KERN_ERR "cm: io ports %#x-%#x in use\n", s->iomidi, s->iomidi+CM_EXTENT_MIDI-1);
-			goto err_region4;
+			printk(KERN_WARNING "cmpci: io ports %#x-%#x in use, midi disabled.\n", s->iomidi, s->iomidi+CM_EXTENT_MIDI-1);
+			s->iomidi = 0;
+		}
+		else
+		{
+			request_region(s->iomidi, CM_EXTENT_MIDI, "cmpci Midi");
+			/* set IO based at 0x330 */
+			outb(inb(s->iobase + CODEC_CMI_LEGACY_CTRL + 3) & ~0x60, s->iobase + CODEC_CMI_LEGACY_CTRL + 3);
 		}
-		request_region(s->iomidi, CM_EXTENT_MIDI, "cmpci Midi");
-		/* set IO based at 0x330 */
-		outb(inb(s->iobase + CODEC_CMI_LEGACY_CTRL + 3) & ~0x60, s->iobase + CODEC_CMI_LEGACY_CTRL + 3);
-#endif
-#ifdef CONFIG_SOUND_CMPCI_FM
 		if (check_region(s->iosynth, CM_EXTENT_SYNTH)) {
-			printk(KERN_ERR "cm: io ports %#x-%#x in use\n", s->iosynth, s->iosynth+CM_EXTENT_SYNTH-1);
-			goto err_region1;
+			printk(KERN_WARNING "cmpci: io ports %#x-%#x in use, synth disabled.\n", s->iosynth, s->iosynth+CM_EXTENT_SYNTH-1);
+			s->iosynth = 0;
+		}
+		else
+		{
+			request_region(s->iosynth, CM_EXTENT_SYNTH, "cmpci FM");
+			/* enable FM */
+			outb(inb(s->iobase + CODEC_CMI_MISC_CTRL + 2) | 8, s->iobase + CODEC_CMI_MISC_CTRL);
 		}
-		request_region(s->iosynth, CM_EXTENT_SYNTH, "cmpci FM");
-		/* enable FM */
-		outb(inb(s->iobase + CODEC_CMI_MISC_CTRL + 2) | 8, s->iobase + CODEC_CMI_MISC_CTRL);
-#endif
 		/* initialize codec registers */
 		outb(0, s->iobase + CODEC_CMI_INT_HLDCLR + 2);  /* disable ints */
-		outb(0, s->iobase + CODEC_CMI_FUNCTRL0 + 2); /* reset channels */
+		outb(0, s->iobase + CODEC_CMI_FUNCTRL0 + 2); /* disable channels */
 		/* reset mixer */
 		wrmixer(s, DSP_MIX_DATARESETIDX, 0);
 
 		/* request irq */
 		if (request_irq(s->irq, cm_interrupt, SA_SHIRQ, "cmpci", s)) {
-			printk(KERN_ERR "cm: irq %u in use\n", s->irq);
+			printk(KERN_ERR "cmpci: irq %u in use\n", s->irq);
 			goto err_irq;
 		}
-		printk(KERN_INFO "cm: found %s adapter at io %#06x irq %u\n",
+		printk(KERN_INFO "cmpci: found %s adapter at io %#06x irq %u\n",
 		       devicename, s->iobase, s->irq);
 		/* register devices */
 		if ((s->dev_audio = register_sound_dsp(&cm_audio_fops, -1)) < 0)
 			goto err_dev1;
 		if ((s->dev_mixer = register_sound_mixer(&cm_mixer_fops, -1)) < 0)
 			goto err_dev2;
-#ifdef CONFIG_SOUND_CMPCI_MIDI
-		if ((s->dev_midi = register_sound_midi(&cm_midi_fops, -1)) < 0)
+		if (s->iomidi && (s->dev_midi = register_sound_midi(&cm_midi_fops, -1)) < 0)
 			goto err_dev3;
-#endif
-#ifdef CONFIG_SOUND_CMPCI_FM
-		if ((s->dev_dmfm = register_sound_special(&cm_dmfm_fops, 15 /* ?? */)) < 0)
+		if (s->iosynth && (s->dev_dmfm = register_sound_special(&cm_dmfm_fops, 15 /* ?? */)) < 0)
 			goto err_dev4;
-#endif
+		pci_set_master(pcidev);
 		/* initialize the chips */
 		fs = get_fs();
 		set_fs(KERNEL_DS);
@@ -2305,6 +2442,38 @@
 			mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
 		}
 		set_fs(fs);
+		if (pcidev->device == PCI_DEVICE_ID_CMEDIA_CM8738)
+		{
+			/* enable SPDIF loop */
+			if (spdif_loop)
+			{
+				/* turn on spdif-in to spdif-out */
+				outb(inb(s->iobase + CODEC_CMI_FUNCTRL1) | 0x80, s->iobase + CODEC_CMI_FUNCTRL1);
+				printk(KERN_INFO "cmpci: Enable SPDIF loop\n");
+			}
+			else
+				outb(inb(s->iobase + CODEC_CMI_FUNCTRL1) & ~0x80, s->iobase + CODEC_CMI_FUNCTRL1);
+			/* enable 4 channels mode */
+			if (four_ch)
+			{
+				/* 4 channel mode (analog duplicate) */
+				outb(inb(s->iobase + CODEC_CMI_MISC_CTRL + 3) | 0x04, s->iobase + CODEC_CMI_MISC_CTRL + 3);
+				printk(KERN_INFO "cmpci: Enable 4 channels mode\n");
+				/* has separate rear-out jack ? */
+				if (rear_out)
+				{
+					/* has separate rear out jack */
+					outb(inb(s->iobase + CODEC_CMI_MIXER1) & ~0x20, s->iobase + CODEC_CMI_MIXER1);
+				}
+				else
+				{
+					outb(inb(s->iobase + CODEC_CMI_MIXER1) | 0x20, s->iobase + CODEC_CMI_MIXER1);
+					printk(KERN_INFO "cmpci: line-in routed as rear-out\n");
+				}
+			}
+			else
+				outb(inb(s->iobase + CODEC_CMI_MISC_CTRL + 3) & ~0x04, s->iobase + CODEC_CMI_MISC_CTRL + 3);
+		}
 		/* queue it for later freeing */
 		s->next = devs;
 		devs = s;
@@ -2318,16 +2487,14 @@
 	err_dev2:
 		unregister_sound_dsp(s->dev_audio);
 	err_dev1:
-		printk(KERN_ERR "cm: cannot register misc device\n");
+		printk(KERN_ERR "cmpci: cannot register misc device\n");
 		free_irq(s->irq, s);
 	err_irq:
-#ifdef CONFIG_SOUND_CMPCI_FM
-		release_region(s->iosynth, CM_EXTENT_SYNTH);
+		if(s->iosynth)
+			release_region(s->iosynth, CM_EXTENT_SYNTH);
 	err_region1:
-#endif
-#ifdef CONFIG_SOUND_CMPCI_MIDI
-		release_region(s->iomidi, CM_EXTENT_MIDI);
-#endif
+		if(s->iomidi)
+			release_region(s->iomidi, CM_EXTENT_MIDI);
 	err_region4:
 		release_region(s->iobase, CM_EXTENT_CODEC);
 	err_region5:
@@ -2345,11 +2512,6 @@
 
 #ifdef MODULE
 
-#if 0
-MODULE_PARM(wavetable, "1-" __MODULE_STRING(NR_DEVICE) "i");
-MODULE_PARM_DESC(wavetable, "if 1 the wavetable synth is enabled");
-#endif
-
 MODULE_AUTHOR("ChenLi Tien, cltien@home.com");
 MODULE_DESCRIPTION("CMPCI Audio Driver");
 
@@ -2361,32 +2523,30 @@
 		devs = devs->next;
 		outb(0, s->iobase + CODEC_CMI_INT_HLDCLR + 2);  /* disable ints */
 		synchronize_irq();
-		outb(0, s->iobase + CODEC_CMI_FUNCTRL0 + 2); /* reset channels */
+		outb(0, s->iobase + CODEC_CMI_FUNCTRL0 + 2); /* disable channels */
 		free_irq(s->irq, s);
 
 		/* reset mixer */
 		wrmixer(s, DSP_MIX_DATARESETIDX, 0);
 
 		release_region(s->iobase, CM_EXTENT_CODEC);
-#ifdef CONFIG_SOUND_CMPCI_MIDI
-		release_region(s->iomidi, CM_EXTENT_MIDI);
-#endif
-#ifdef CONFIG_SOUND_CMPCI_FM
-		release_region(s->iosynth, CM_EXTENT_SYNTH);
-#endif
+		if(s->iomidi)
+		{
+			release_region(s->iomidi, CM_EXTENT_MIDI);
+			unregister_sound_midi(s->dev_midi);
+		}
+		if(s->iosynth)
+		{
+			release_region(s->iosynth, CM_EXTENT_SYNTH);
+			unregister_sound_special(s->dev_dmfm);
+		}
 		unregister_sound_dsp(s->dev_audio);
 		unregister_sound_mixer(s->dev_mixer);
-#ifdef CONFIG_SOUND_CMPCI_MIDI
-		unregister_sound_midi(s->dev_midi);
-#endif
-#ifdef CONFIG_SOUND_CMPCI_FM
-		unregister_sound_special(s->dev_dmfm);
-#endif
 		kfree_s(s, sizeof(struct cm_state));
 	}
 	if (wavetable_mem)
 		free_pages(wavetable_mem, 20-PAGE_SHIFT);
-	printk(KERN_INFO "cm: unloading\n");
+	printk(KERN_INFO "cmpci: unloading\n");
 }
 
 #endif /* MODULE */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/sound/dmabuf.c linux.15p9/drivers/sound/dmabuf.c
--- linux.vanilla/drivers/sound/dmabuf.c	Wed Oct 20 01:12:48 1999
+++ linux.15p9/drivers/sound/dmabuf.c	Mon Feb  7 13:26:05 2000
@@ -70,6 +70,14 @@
 	if (dma_buffsize < 4096)
 		dma_buffsize = 4096;
 	dma_pagesize = (dmap->dma < 4) ? (64 * 1024) : (128 * 1024);
+	
+	/*
+	 *	Now check for the Cyrix problem.
+	 */
+	 
+	if(isa_dma_bridge_buggy==2)
+		dma_pagesize=32768;
+	 
 	dmap->raw_buf = NULL;
 	dmap->buffsize = dma_buffsize;
 	if (dmap->buffsize > dma_pagesize)
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/sound/es1370.c linux.15p9/drivers/sound/es1370.c
--- linux.vanilla/drivers/sound/es1370.c	Tue Jan  4 21:18:59 2000
+++ linux.15p9/drivers/sound/es1370.c	Wed Jan 12 01:26:27 2000
@@ -3,7 +3,7 @@
 /*
  *      es1370.c  --  Ensoniq ES1370/Asahi Kasei AK4531 audio driver.
  *
- *      Copyright (C) 1998-1999  Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *      Copyright (C) 1998-2000  Thomas Sailer (sailer@ife.ee.ethz.ch)
  *
  *      This program is free software; you can redistribute it and/or modify
  *      it under the terms of the GNU General Public License as published by
@@ -52,66 +52,68 @@
  *  there are several MIDI to PCM (WAV) packages, one of them is timidity.
  *
  *  Revision history
- *    26.03.98   0.1   Initial release
- *    31.03.98   0.2   Fix bug in GETOSPACE
- *    04.04.98   0.3   Make it work (again) under 2.0.33
- *                     Fix mixer write operation not returning the actual
- *                     settings
- *    05.04.98   0.4   First attempt at using the new PCI stuff
- *    29.04.98   0.5   Fix hang when ^C is pressed on amp
- *    07.05.98   0.6   Don't double lock around stop_*() in *_release()
- *    10.05.98   0.7   First stab at a simple midi interface (no bells&whistles)
- *    14.05.98   0.8   Don't allow excessive interrupt rates
- *    08.06.98   0.9   First release using Alan Cox' soundcore instead of
- *                     miscdevice
- *    05.07.98   0.10  Fixed the driver to correctly maintin OSS style volume
- *                     settings (not sure if this should be standard)
- *                     Fixed many references: f_flags should be f_mode
- *                     -- Gerald Britton <gbritton@mit.edu>
- *    03.08.98   0.11  Now mixer behaviour can basically be selected between
- *                     "OSS documented" and "OSS actual" behaviour
- *                     Fixed mixer table thanks to Hakan.Lennestal@lu.erisoft.se
- *                     On module startup, set DAC2 to 11kSPS instead of 5.5kSPS,
- *                     as it produces an annoying ssssh in the lower sampling rate
- *                     Do not include modversions.h
- *    22.08.98   0.12  Mixer registers actually have 5 instead of 4 bits
- *                     pointed out by Itai Nahshon
- *    31.08.98   0.13  Fix realplayer problems - dac.count issues
- *    08.10.98   0.14  Joystick support fixed
- *		       -- Oliver Neukum <c188@org.chemie.uni-muenchen.de>
- *    10.12.98   0.15  Fix drain_dac trying to wait on not yet initialized DMA
- *    16.12.98   0.16  Don't wake up app until there are fragsize bytes to read/write
- *    06.01.99   0.17  remove the silly SA_INTERRUPT flag.
- *                     hopefully killed the egcs section type conflict
- *    12.03.99   0.18  cinfo.blocks should be reset after GETxPTR ioctl.
- *                     reported by Johan Maes <joma@telindus.be>
- *    22.03.99   0.19  return EAGAIN instead of EBUSY when O_NONBLOCK
- *                     read/write cannot be executed
- *    07.04.99   0.20  implemented the following ioctl's: SOUND_PCM_READ_RATE, 
- *                     SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS; 
- *                     Alpha fixes reported by Peter Jones <pjones@redhat.com>
- *                     Note: joystick address handling might still be wrong on archs
- *                     other than i386
- *    10.05.99   0.21  Added support for an electret mic for SB PCI64
- *                     to the Linux kernel sound driver. This mod also straighten
- *                     out the question marks around the mic impedance setting
- *                     (micz). From Kim.Berts@fisub.mail.abb.com
- *    11.05.99   0.22  Implemented the IMIX call to mute recording monitor.
- *                     Guenter Geiger <geiger@epy.co.at>
- *    15.06.99   0.23  Fix bad allocation bug.
- *                     Thanks to Deti Fliegl <fliegl@in.tum.de>
- *    28.06.99   0.24  Add pci_set_master
- *    02.08.99   0.25  Added workaround for the "phantom write" bug first
- *                     documented by Dave Sharpless from Anchor Games
- *    03.08.99   0.26  adapt to Linus' new __setup/__initcall
- *                     added kernel command line option "es1370=joystick[,lineout[,micbias]]"
- *                     removed CONFIG_SOUND_ES1370_JOYPORT_BOOT kludge
- *    12.08.99   0.27  module_init/__setup fixes
- *    19.08.99   0.28  SOUND_MIXER_IMIX fixes, reported by Gianluca <gialluca@mail.tiscalinet.it>
- *    31.08.99   0.29  add spin_lock_init
- *                     __initlocaldata to fix gcc 2.7.x problems
- *    03.09.99   0.30  change read semantics for MIDI to match
- *                     OSS more closely; remove possible wakeup race
+ *    26.03.1998   0.1   Initial release
+ *    31.03.1998   0.2   Fix bug in GETOSPACE
+ *    04.04.1998   0.3   Make it work (again) under 2.0.33
+ *                       Fix mixer write operation not returning the actual
+ *                       settings
+ *    05.04.1998   0.4   First attempt at using the new PCI stuff
+ *    29.04.1998   0.5   Fix hang when ^C is pressed on amp
+ *    07.05.1998   0.6   Don't double lock around stop_*() in *_release()
+ *    10.05.1998   0.7   First stab at a simple midi interface (no bells&whistles)
+ *    14.05.1998   0.8   Don't allow excessive interrupt rates
+ *    08.06.1998   0.9   First release using Alan Cox' soundcore instead of
+ *                       miscdevice
+ *    05.07.1998   0.10  Fixed the driver to correctly maintin OSS style volume
+ *                       settings (not sure if this should be standard)
+ *                       Fixed many references: f_flags should be f_mode
+ *                       -- Gerald Britton <gbritton@mit.edu>
+ *    03.08.1998   0.11  Now mixer behaviour can basically be selected between
+ *                       "OSS documented" and "OSS actual" behaviour
+ *                       Fixed mixer table thanks to Hakan.Lennestal@lu.erisoft.se
+ *                       On module startup, set DAC2 to 11kSPS instead of 5.5kSPS,
+ *                       as it produces an annoying ssssh in the lower sampling rate
+ *                       Do not include modversions.h
+ *    22.08.1998   0.12  Mixer registers actually have 5 instead of 4 bits
+ *                       pointed out by Itai Nahshon
+ *    31.08.1998   0.13  Fix realplayer problems - dac.count issues
+ *    08.10.1998   0.14  Joystick support fixed
+ *		         -- Oliver Neukum <c188@org.chemie.uni-muenchen.de>
+ *    10.12.1998   0.15  Fix drain_dac trying to wait on not yet initialized DMA
+ *    16.12.1998   0.16  Don't wake up app until there are fragsize bytes to read/write
+ *    06.01.1999   0.17  remove the silly SA_INTERRUPT flag.
+ *                       hopefully killed the egcs section type conflict
+ *    12.03.1999   0.18  cinfo.blocks should be reset after GETxPTR ioctl.
+ *                       reported by Johan Maes <joma@telindus.be>
+ *    22.03.1999   0.19  return EAGAIN instead of EBUSY when O_NONBLOCK
+ *                       read/write cannot be executed
+ *    07.04.1999   0.20  implemented the following ioctl's: SOUND_PCM_READ_RATE, 
+ *                       SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS; 
+ *                       Alpha fixes reported by Peter Jones <pjones@redhat.com>
+ *                       Note: joystick address handling might still be wrong on archs
+ *                       other than i386
+ *    10.05.1999   0.21  Added support for an electret mic for SB PCI64
+ *                       to the Linux kernel sound driver. This mod also straighten
+ *                       out the question marks around the mic impedance setting
+ *                       (micz). From Kim.Berts@fisub.mail.abb.com
+ *    11.05.1999   0.22  Implemented the IMIX call to mute recording monitor.
+ *                       Guenter Geiger <geiger@epy.co.at>
+ *    15.06.1999   0.23  Fix bad allocation bug.
+ *                       Thanks to Deti Fliegl <fliegl@in.tum.de>
+ *    28.06.1999   0.24  Add pci_set_master
+ *    02.08.1999   0.25  Added workaround for the "phantom write" bug first
+ *                       documented by Dave Sharpless from Anchor Games
+ *    03.08.1999   0.26  adapt to Linus' new __setup/__initcall
+ *                       added kernel command line option "es1370=joystick[,lineout[,micbias]]"
+ *                       removed CONFIG_SOUND_ES1370_JOYPORT_BOOT kludge
+ *    12.08.1999   0.27  module_init/__setup fixes
+ *    19.08.1999   0.28  SOUND_MIXER_IMIX fixes, reported by Gianluca <gialluca@mail.tiscalinet.it>
+ *    31.08.1999   0.29  add spin_lock_init
+ *                       __initlocaldata to fix gcc 2.7.x problems
+ *                       replaced current->state = x with set_current_state(x)
+ *    03.09.1999   0.30  change read semantics for MIDI to match
+ *                       OSS more closely; remove possible wakeup race
+ *    28.10.1999   0.31  More waitqueue races fixed
  *
  * some important things missing in Ensoniq documentation:
  *
@@ -160,6 +162,26 @@
 
 /* --------------------------------------------------------------------- */
 
+#ifdef MODULE
+#define __exit
+#define module_exit(x) void cleanup_module(void) { x(); }
+#define module_init(x) int init_module(void) { return x(); }
+#else
+#define __exit __attribute__ ((unused, __section__ (".text.init")))
+#define module_exit(x) /* nothing */
+#define module_init(x) /* nothing */
+#endif
+
+#define DECLARE_WAIT_QUEUE_HEAD(w) struct wait_queue *w = NULL
+#define DECLARE_WAITQUEUE(w,c) struct wait_queue w = {(c), NULL}
+#define wait_queue_head_t struct wait_queue *
+#define init_waitqueue_head(w) *(w) = 0
+#define init_MUTEX(m) *(m) = MUTEX
+#define __set_current_state(x) do { current->state = (x); } while (0)
+#define set_current_state(x) __set_current_state(x)
+
+/* --------------------------------------------------------------------- */
+
 #ifndef PCI_VENDOR_ID_ENSONIQ
 #define PCI_VENDOR_ID_ENSONIQ        0x1274    
 #endif
@@ -332,7 +354,7 @@
 	spinlock_t lock;
 	struct semaphore open_sem;
 	mode_t open_mode;
-	struct wait_queue *open_wait;
+	wait_queue_head_t open_wait;
 
 	struct dmabuf {
 		void *rawbuf;
@@ -343,7 +365,7 @@
 		unsigned total_bytes;
 		int count;
 		unsigned error; /* over/underrun */
-		struct wait_queue *wait;
+		wait_queue_head_t wait;
 		/* redundant, but makes calculations easier */
 		unsigned fragsize;
 		unsigned dmasize;
@@ -361,8 +383,8 @@
 	struct {
 		unsigned ird, iwr, icnt;
 		unsigned ord, owr, ocnt;
-		struct wait_queue *iwait;
-		struct wait_queue *owait;
+		wait_queue_head_t iwait;
+		wait_queue_head_t owait;
 		unsigned char ibuf[MIDIINBUF];
 		unsigned char obuf[MIDIOUTBUF];
 	} midi;
@@ -1057,15 +1079,15 @@
 
 static int drain_dac1(struct es1370_state *s, int nonblock)
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
 	int count, tmo;
 	
 	if (s->dma_dac1.mapped || !s->dma_dac1.ready)
 		return 0;
-        current->state = TASK_INTERRUPTIBLE;
         add_wait_queue(&s->dma_dac1.wait, &wait);
         for (;;) {
+		__set_current_state(TASK_INTERRUPTIBLE);
                 spin_lock_irqsave(&s->lock, flags);
 		count = s->dma_dac1.count;
                 spin_unlock_irqrestore(&s->lock, flags);
@@ -1075,7 +1097,7 @@
                         break;
                 if (nonblock) {
                         remove_wait_queue(&s->dma_dac1.wait, &wait);
-                        current->state = TASK_RUNNING;
+                        set_current_state(TASK_RUNNING);
                         return -EBUSY;
                 }
 		tmo = 3 * HZ * (count + s->dma_dac1.fragsize) / 2
@@ -1085,7 +1107,7 @@
 			DBG(printk(KERN_DEBUG "es1370: dma timed out??\n");)
         }
         remove_wait_queue(&s->dma_dac1.wait, &wait);
-        current->state = TASK_RUNNING;
+        set_current_state(TASK_RUNNING);
         if (signal_pending(current))
                 return -ERESTARTSYS;
         return 0;
@@ -1093,15 +1115,15 @@
 
 static int drain_dac2(struct es1370_state *s, int nonblock)
 {
-        struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
 	int count, tmo;
 
 	if (s->dma_dac2.mapped || !s->dma_dac2.ready)
 		return 0;
-        current->state = TASK_INTERRUPTIBLE;
         add_wait_queue(&s->dma_dac2.wait, &wait);
         for (;;) {
+		__set_current_state(TASK_INTERRUPTIBLE);
                 spin_lock_irqsave(&s->lock, flags);
 		count = s->dma_dac2.count;
                 spin_unlock_irqrestore(&s->lock, flags);
@@ -1111,7 +1133,7 @@
                         break;
                 if (nonblock) {
                         remove_wait_queue(&s->dma_dac2.wait, &wait);
-                        current->state = TASK_RUNNING;
+                        set_current_state(TASK_RUNNING);
                         return -EBUSY;
                 }
 		tmo = 3 * HZ * (count + s->dma_dac2.fragsize) / 2
@@ -1121,7 +1143,7 @@
 			DBG(printk(KERN_DEBUG "es1370: dma timed out??\n");)
         }
         remove_wait_queue(&s->dma_dac2.wait, &wait);
-        current->state = TASK_RUNNING;
+        set_current_state(TASK_RUNNING);
         if (signal_pending(current))
                 return -ERESTARTSYS;
         return 0;
@@ -1132,6 +1154,7 @@
 static ssize_t es1370_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
 	struct es1370_state *s = (struct es1370_state *)file->private_data;
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t ret;
 	unsigned long flags;
 	unsigned swptr;
@@ -1147,26 +1170,38 @@
 	if (!access_ok(VERIFY_WRITE, buffer, count))
 		return -EFAULT;
 	ret = 0;
+        add_wait_queue(&s->dma_adc.wait, &wait);
 	while (count > 0) {
 		spin_lock_irqsave(&s->lock, flags);
 		swptr = s->dma_adc.swptr;
 		cnt = s->dma_adc.dmasize-swptr;
 		if (s->dma_adc.count < cnt)
 			cnt = s->dma_adc.count;
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
 		if (cnt <= 0) {
 			start_adc(s);
-			if (file->f_flags & O_NONBLOCK)
-				return ret ? ret : -EAGAIN;
-			interruptible_sleep_on(&s->dma_adc.wait);
-			if (signal_pending(current))
-				return ret ? ret : -ERESTARTSYS;
+			if (file->f_flags & O_NONBLOCK) {
+				if (!ret)
+					ret = -EAGAIN;
+				break;
+			}
+			schedule();
+			if (signal_pending(current)) {
+				if (!ret)
+					ret = -ERESTARTSYS;
+				break;
+			}
 			continue;
 		}
-		if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt))
-			return ret ? ret : -EFAULT;
+		if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) {
+			if (!ret)
+				ret = -EFAULT;
+			break;
+		}
 		swptr = (swptr + cnt) % s->dma_adc.dmasize;
 		spin_lock_irqsave(&s->lock, flags);
 		s->dma_adc.swptr = swptr;
@@ -1177,12 +1212,15 @@
 		ret += cnt;
 		start_adc(s);
 	}
+        remove_wait_queue(&s->dma_adc.wait, &wait);
+	set_current_state(TASK_RUNNING);
 	return ret;
 }
 
 static ssize_t es1370_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
 {
 	struct es1370_state *s = (struct es1370_state *)file->private_data;
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t ret;
 	unsigned long flags;
 	unsigned swptr;
@@ -1198,6 +1236,7 @@
 	if (!access_ok(VERIFY_READ, buffer, count))
 		return -EFAULT;
 	ret = 0;
+        add_wait_queue(&s->dma_dac2.wait, &wait);
 	while (count > 0) {
 		spin_lock_irqsave(&s->lock, flags);
 		if (s->dma_dac2.count < 0) {
@@ -1208,20 +1247,31 @@
 		cnt = s->dma_dac2.dmasize-swptr;
 		if (s->dma_dac2.count + cnt > s->dma_dac2.dmasize)
 			cnt = s->dma_dac2.dmasize - s->dma_dac2.count;
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
 		if (cnt <= 0) {
 			start_dac2(s);
-			if (file->f_flags & O_NONBLOCK)
-				return ret ? ret : -EAGAIN;
-			interruptible_sleep_on(&s->dma_dac2.wait);
-			if (signal_pending(current))
-				return ret ? ret : -ERESTARTSYS;
+			if (file->f_flags & O_NONBLOCK) {
+				if (!ret)
+					ret = -EAGAIN;
+				break;
+			}
+			schedule();
+			if (signal_pending(current)) {
+				if (!ret)
+					ret = -ERESTARTSYS;
+				break;
+			}
 			continue;
 		}
-		if (copy_from_user(s->dma_dac2.rawbuf + swptr, buffer, cnt))
-			return ret ? ret : -EFAULT;
+		if (copy_from_user(s->dma_dac2.rawbuf + swptr, buffer, cnt)) {
+			if (!ret)
+				ret = -EFAULT;
+			break;
+		}
 		swptr = (swptr + cnt) % s->dma_dac2.dmasize;
 		spin_lock_irqsave(&s->lock, flags);
 		s->dma_dac2.swptr = swptr;
@@ -1233,6 +1283,8 @@
 		ret += cnt;
 		start_dac2(s);
 	}
+        remove_wait_queue(&s->dma_dac2.wait, &wait);
+	set_current_state(TASK_RUNNING);
 	return ret;
 }
 
@@ -1607,6 +1659,7 @@
 static int es1370_open(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
+	DECLARE_WAITQUEUE(wait, current);
 	struct es1370_state *s = devs;
 	unsigned long flags;
 
@@ -1623,8 +1676,12 @@
 			up(&s->open_sem);
 			return -EBUSY;
 		}
+		add_wait_queue(&s->open_wait, &wait);
+		__set_current_state(TASK_INTERRUPTIBLE);
 		up(&s->open_sem);
-		interruptible_sleep_on(&s->open_wait);
+		schedule();
+		remove_wait_queue(&s->open_wait, &wait);
+		set_current_state(TASK_RUNNING);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 		down(&s->open_sem);
@@ -1675,8 +1732,8 @@
 		dealloc_dmabuf(&s->dma_adc);
 	}
 	s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
-	up(&s->open_sem);
 	wake_up(&s->open_wait);
+	up(&s->open_sem);
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
@@ -1704,6 +1761,7 @@
 static ssize_t es1370_write_dac(struct file *file, const char *buffer, size_t count, loff_t *ppos)
 {
 	struct es1370_state *s = (struct es1370_state *)file->private_data;
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t ret = 0;
 	unsigned long flags;
 	unsigned swptr;
@@ -1718,6 +1776,7 @@
 		return ret;
 	if (!access_ok(VERIFY_READ, buffer, count))
 		return -EFAULT;
+        add_wait_queue(&s->dma_dac1.wait, &wait);
 	while (count > 0) {
 		spin_lock_irqsave(&s->lock, flags);
 		if (s->dma_dac1.count < 0) {
@@ -1728,20 +1787,31 @@
 		cnt = s->dma_dac1.dmasize-swptr;
 		if (s->dma_dac1.count + cnt > s->dma_dac1.dmasize)
 			cnt = s->dma_dac1.dmasize - s->dma_dac1.count;
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
 		if (cnt <= 0) {
 			start_dac1(s);
-			if (file->f_flags & O_NONBLOCK)
-				return ret ? ret : -EAGAIN;
-			interruptible_sleep_on(&s->dma_dac1.wait);
-			if (signal_pending(current))
-				return ret ? ret : -ERESTARTSYS;
+			if (file->f_flags & O_NONBLOCK) {
+				if (!ret)
+					ret = -EAGAIN;
+				break;
+			}
+			schedule();
+			if (signal_pending(current)) {
+				if (!ret)
+					ret = -ERESTARTSYS;
+				break;
+			}
 			continue;
 		}
-		if (copy_from_user(s->dma_dac1.rawbuf + swptr, buffer, cnt))
-			return ret ? ret : -EFAULT;
+		if (copy_from_user(s->dma_dac1.rawbuf + swptr, buffer, cnt)) {
+			if (!ret)
+				ret = -EFAULT;
+			break;
+		}
 		swptr = (swptr + cnt) % s->dma_dac1.dmasize;
 		spin_lock_irqsave(&s->lock, flags);
 		s->dma_dac1.swptr = swptr;
@@ -1753,6 +1823,8 @@
 		ret += cnt;
 		start_dac1(s);
 	}
+        remove_wait_queue(&s->dma_dac1.wait, &wait);
+	set_current_state(TASK_RUNNING);
 	return ret;
 }
 
@@ -1990,6 +2062,7 @@
 static int es1370_open_dac(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
+	DECLARE_WAITQUEUE(wait, current);
 	struct es1370_state *s = devs;
 	unsigned long flags;
 
@@ -2013,8 +2086,12 @@
 			up(&s->open_sem);
 			return -EBUSY;
 		}
+		add_wait_queue(&s->open_wait, &wait);
+		__set_current_state(TASK_INTERRUPTIBLE);
 		up(&s->open_sem);
-		interruptible_sleep_on(&s->open_wait);
+		schedule();
+		remove_wait_queue(&s->open_wait, &wait);
+		set_current_state(TASK_RUNNING);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 		down(&s->open_sem);
@@ -2046,8 +2123,8 @@
 	stop_dac1(s);
 	dealloc_dmabuf(&s->dma_dac1);
 	s->open_mode &= ~FMODE_DAC;
-	up(&s->open_sem);
 	wake_up(&s->open_wait);
+	up(&s->open_sem);
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
@@ -2075,7 +2152,7 @@
 static ssize_t es1370_midi_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
 	struct es1370_state *s = (struct es1370_state *)file->private_data;
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t ret;
 	unsigned long flags;
 	unsigned ptr;
@@ -2096,6 +2173,8 @@
 		cnt = MIDIINBUF - ptr;
 		if (s->midi.icnt < cnt)
 			cnt = s->midi.icnt;
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
@@ -2105,7 +2184,6 @@
 					ret = -EAGAIN;
 				break;
 			}
-			current->state = TASK_INTERRUPTIBLE;
 			schedule();
 			if (signal_pending(current)) {
 				if (!ret)
@@ -2129,7 +2207,7 @@
 		ret += cnt;
 		break;
 	}
-	current->state = TASK_RUNNING;
+	__set_current_state(TASK_RUNNING);
         remove_wait_queue(&s->midi.iwait, &wait);
 	return ret;
 }
@@ -2137,7 +2215,7 @@
 static ssize_t es1370_midi_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
 {
 	struct es1370_state *s = (struct es1370_state *)file->private_data;
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t ret;
 	unsigned long flags;
 	unsigned ptr;
@@ -2158,8 +2236,10 @@
 		cnt = MIDIOUTBUF - ptr;
 		if (s->midi.ocnt + cnt > MIDIOUTBUF)
 			cnt = MIDIOUTBUF - s->midi.ocnt;
-		if (cnt <= 0)
+		if (cnt <= 0) {
+			__set_current_state(TASK_INTERRUPTIBLE);
 			es1370_handle_midi(s);
+		}
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
@@ -2169,7 +2249,6 @@
 					ret = -EAGAIN;
 				break;
 			}
-			current->state = TASK_INTERRUPTIBLE;
 			schedule();
 			if (signal_pending(current)) {
 				if (!ret)
@@ -2195,7 +2274,7 @@
 		es1370_handle_midi(s);
 		spin_unlock_irqrestore(&s->lock, flags);
 	}
-	current->state = TASK_RUNNING;
+	__set_current_state(TASK_RUNNING);
         remove_wait_queue(&s->midi.owait, &wait);
 	return ret;
 }
@@ -2227,6 +2306,7 @@
 static int es1370_midi_open(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
+	DECLARE_WAITQUEUE(wait, current);
 	struct es1370_state *s = devs;
 	unsigned long flags;
 
@@ -2243,8 +2323,12 @@
 			up(&s->open_sem);
 			return -EBUSY;
 		}
+		add_wait_queue(&s->open_wait, &wait);
+		__set_current_state(TASK_INTERRUPTIBLE);
 		up(&s->open_sem);
-		interruptible_sleep_on(&s->open_wait);
+		schedule();
+		remove_wait_queue(&s->open_wait, &wait);
+		set_current_state(TASK_RUNNING);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 		down(&s->open_sem);
@@ -2276,16 +2360,16 @@
 static int es1370_midi_release(struct inode *inode, struct file *file)
 {
 	struct es1370_state *s = (struct es1370_state *)file->private_data;
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
 	unsigned count, tmo;
 
 	VALIDATE_STATE(s);
 
 	if (file->f_mode & FMODE_WRITE) {
-		current->state = TASK_INTERRUPTIBLE;
 		add_wait_queue(&s->midi.owait, &wait);
 		for (;;) {
+			__set_current_state(TASK_INTERRUPTIBLE);
 			spin_lock_irqsave(&s->lock, flags);
 			count = s->midi.ocnt;
 			spin_unlock_irqrestore(&s->lock, flags);
@@ -2295,7 +2379,7 @@
 				break;
 			if (file->f_flags & O_NONBLOCK) {
 				remove_wait_queue(&s->midi.owait, &wait);
-				current->state = TASK_RUNNING;
+				set_current_state(TASK_RUNNING);
 				return -EBUSY;
 			}
 			tmo = (count * HZ) / 3100;
@@ -2303,7 +2387,7 @@
 				DBG(printk(KERN_DEBUG "es1370: midi timed out??\n");)
 		}
 		remove_wait_queue(&s->midi.owait, &wait);
-		current->state = TASK_RUNNING;
+		set_current_state(TASK_RUNNING);
 	}
 	down(&s->open_sem);
 	s->open_mode &= (~(file->f_mode << FMODE_MIDI_SHIFT)) & (FMODE_MIDI_READ|FMODE_MIDI_WRITE);
@@ -2313,8 +2397,8 @@
 		outl(s->ctrl, s->io+ES1370_REG_CONTROL);
 	}
 	spin_unlock_irqrestore(&s->lock, flags);
-	up(&s->open_sem);
 	wake_up(&s->open_wait);
+	up(&s->open_sem);
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
@@ -2380,7 +2464,7 @@
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "es1370: version v0.30 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "es1370: version v0.31 time " __TIME__ " " __DATE__ "\n");
 	while (index < NR_DEVICE && 
 	       (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, pcidev))) {
 		if (pcidev->base_address[0] == 0 || 
@@ -2393,13 +2477,13 @@
 			continue;
 		}
 		memset(s, 0, sizeof(struct es1370_state));
-		init_waitqueue(&s->dma_adc.wait);
-		init_waitqueue(&s->dma_dac1.wait);
-		init_waitqueue(&s->dma_dac2.wait);
-		init_waitqueue(&s->open_wait);
-		init_waitqueue(&s->midi.iwait);
-		init_waitqueue(&s->midi.owait);
-		s->open_sem = MUTEX;
+		init_waitqueue_head(&s->dma_adc.wait);
+		init_waitqueue_head(&s->dma_dac1.wait);
+		init_waitqueue_head(&s->dma_dac2.wait);
+		init_waitqueue_head(&s->open_wait);
+		init_waitqueue_head(&s->midi.iwait);
+		init_waitqueue_head(&s->midi.owait);
+		init_MUTEX(&s->open_sem);
 		spin_lock_init(&s->lock);
 		s->magic = ES1370_MAGIC;
 		s->io = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/sound/es1371.c linux.15p9/drivers/sound/es1371.c
--- linux.vanilla/drivers/sound/es1371.c	Tue Jan  4 21:18:59 2000
+++ linux.15p9/drivers/sound/es1371.c	Wed Jan 12 01:26:27 2000
@@ -3,7 +3,7 @@
 /*
  *      es1371.c  --  Creative Ensoniq ES1371.
  *
- *      Copyright (C) 1998-1999  Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *      Copyright (C) 1998-2000  Thomas Sailer (sailer@ife.ee.ethz.ch)
  *
  *      This program is free software; you can redistribute it and/or modify
  *      it under the terms of the GNU General Public License as published by
@@ -38,57 +38,64 @@
  *  there are several MIDI to PCM (WAV) packages, one of them is timidity.
  *
  *  Revision history
- *    04.06.98   0.1   Initial release
- *                     Mixer stuff should be overhauled; especially optional AC97 mixer bits
- *                     should be detected. This results in strange behaviour of some mixer
- *                     settings, like master volume and mic.
- *    08.06.98   0.2   First release using Alan Cox' soundcore instead of miscdevice
- *    03.08.98   0.3   Do not include modversions.h
- *                     Now mixer behaviour can basically be selected between
- *                     "OSS documented" and "OSS actual" behaviour
- *    31.08.98   0.4   Fix realplayer problems - dac.count issues
- *    27.10.98   0.5   Fix joystick support
- *                     -- Oliver Neukum (c188@org.chemie.uni-muenchen.de)
- *    10.12.98   0.6   Fix drain_dac trying to wait on not yet initialized DMA
- *    23.12.98   0.7   Fix a few f_file & FMODE_ bugs
- *                     Don't wake up app until there are fragsize bytes to read/write
- *    06.01.99   0.8   remove the silly SA_INTERRUPT flag.
- *                     hopefully killed the egcs section type conflict
- *    12.03.99   0.9   cinfo.blocks should be reset after GETxPTR ioctl.
- *                     reported by Johan Maes <joma@telindus.be>
- *    22.03.99   0.10  return EAGAIN instead of EBUSY when O_NONBLOCK
- *                     read/write cannot be executed
- *    07.04.99   0.11  implemented the following ioctl's: SOUND_PCM_READ_RATE, 
- *                     SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS; 
- *                     Alpha fixes reported by Peter Jones <pjones@redhat.com>
- *                     Another Alpha fix (wait_src_ready in init routine)
- *                     reported by "Ivan N. Kokshaysky" <ink@jurassic.park.msu.ru>
- *                     Note: joystick address handling might still be wrong on archs
- *                     other than i386
- *    15.06.99   0.12  Fix bad allocation bug.
- *                     Thanks to Deti Fliegl <fliegl@in.tum.de>
- *    28.06.99   0.13  Add pci_set_master
- *    03.08.99   0.14  adapt to Linus' new __setup/__initcall
- *                     added kernel command line option "es1371=joystickaddr"
- *                     removed CONFIG_SOUND_ES1371_JOYPORT_BOOT kludge
- *    10.08.99   0.15  (Re)added S/PDIF module option for cards revision >= 4.
- *                     Initial version by Dave Platt <dplatt@snulbug.mtview.ca.us>.
- *                     module_init/__setup fixes
- *    08.16.99   0.16  Joe Cotellese <joec@ensoniq.com>
- *                     Added detection for ES1371 revision ID so that we can
- *                     detect the ES1373 and later parts.
- *                     added AC97 #defines for readability
- *                     added a /proc file system for dumping hardware state
- *                     updated SRC and CODEC w/r functions to accomodate bugs
- *                     in some versions of the ES137x chips.
- *    31.08.99   0.17  add spin_lock_init
- *                     __initlocaldata to fix gcc 2.7.x problems
- *                     replaced current->state = x with set_current_state(x)
- *    03.09.99   0.18  change read semantics for MIDI to match
- *                     OSS more closely; remove possible wakeup race
- *    21.10.99   0.19  Round sampling rates, requested by
- *                     Kasamatsu Kenichi <t29w0267@ip.media.kyoto-u.ac.jp>
- *
+ *    04.06.1998   0.1   Initial release
+ *                       Mixer stuff should be overhauled; especially optional AC97 mixer bits
+ *                       should be detected. This results in strange behaviour of some mixer
+ *                       settings, like master volume and mic.
+ *    08.06.1998   0.2   First release using Alan Cox' soundcore instead of miscdevice
+ *    03.08.1998   0.3   Do not include modversions.h
+ *                       Now mixer behaviour can basically be selected between
+ *                       "OSS documented" and "OSS actual" behaviour
+ *    31.08.1998   0.4   Fix realplayer problems - dac.count issues
+ *    27.10.1998   0.5   Fix joystick support
+ *                       -- Oliver Neukum (c188@org.chemie.uni-muenchen.de)
+ *    10.12.1998   0.6   Fix drain_dac trying to wait on not yet initialized DMA
+ *    23.12.1998   0.7   Fix a few f_file & FMODE_ bugs
+ *                       Don't wake up app until there are fragsize bytes to read/write
+ *    06.01.1999   0.8   remove the silly SA_INTERRUPT flag.
+ *                       hopefully killed the egcs section type conflict
+ *    12.03.1999   0.9   cinfo.blocks should be reset after GETxPTR ioctl.
+ *                       reported by Johan Maes <joma@telindus.be>
+ *    22.03.1999   0.10  return EAGAIN instead of EBUSY when O_NONBLOCK
+ *                       read/write cannot be executed
+ *    07.04.1999   0.11  implemented the following ioctl's: SOUND_PCM_READ_RATE, 
+ *                       SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS; 
+ *                       Alpha fixes reported by Peter Jones <pjones@redhat.com>
+ *                       Another Alpha fix (wait_src_ready in init routine)
+ *                       reported by "Ivan N. Kokshaysky" <ink@jurassic.park.msu.ru>
+ *                       Note: joystick address handling might still be wrong on archs
+ *                       other than i386
+ *    15.06.1999   0.12  Fix bad allocation bug.
+ *                       Thanks to Deti Fliegl <fliegl@in.tum.de>
+ *    28.06.1999   0.13  Add pci_set_master
+ *    03.08.1999   0.14  adapt to Linus' new __setup/__initcall
+ *                       added kernel command line option "es1371=joystickaddr"
+ *                       removed CONFIG_SOUND_ES1371_JOYPORT_BOOT kludge
+ *    10.08.1999   0.15  (Re)added S/PDIF module option for cards revision >= 4.
+ *                       Initial version by Dave Platt <dplatt@snulbug.mtview.ca.us>.
+ *                       module_init/__setup fixes
+ *    08.16.1999   0.16  Joe Cotellese <joec@ensoniq.com>
+ *                       Added detection for ES1371 revision ID so that we can
+ *                       detect the ES1373 and later parts.
+ *                       added AC97 #defines for readability
+ *                       added a /proc file system for dumping hardware state
+ *                       updated SRC and CODEC w/r functions to accomodate bugs
+ *                       in some versions of the ES137x chips.
+ *    31.08.1999   0.17  add spin_lock_init
+ *                       __initlocaldata to fix gcc 2.7.x problems
+ *                       replaced current->state = x with set_current_state(x)
+ *    03.09.1999   0.18  change read semantics for MIDI to match
+ *                       OSS more closely; remove possible wakeup race
+ *    21.10.1999   0.19  Round sampling rates, requested by
+ *                       Kasamatsu Kenichi <t29w0267@ip.media.kyoto-u.ac.jp>
+ *    27.10.1999   0.20  Added SigmaTel 3D enhancement string
+ *                       Codec ID printing changes
+ *    28.10.1999   0.21  More waitqueue races fixed
+ *                       Joe Cotellese <joec@ensoniq.com>
+ *                       Changed PCI detection routine so we can more easily
+ *                       detect ES137x chip and derivatives.
+ *    05.01.2000   0.22  Should now work with rev7 boards; patch by
+ *                       Eric Lemar, elemar@cs.washington.edu
  */
 
 /*****************************************************************************/
@@ -118,16 +125,51 @@
 
 #undef OSS_DOCUMENTED_MIXER_SEMANTICS
 #undef ES1371_DEBUG
+#define DBG(x) {}
+/*#define DBG(x) {x}*/
+
+/* --------------------------------------------------------------------- */
+
+#ifdef MODULE
+#define __exit
+#define module_exit(x) void cleanup_module(void) { x(); }
+#define module_init(x) int init_module(void) { return x(); }
+#else
+#define __exit __attribute__ ((unused, __section__ (".text.init")))
+#define module_exit(x) /* nothing */
+#define module_init(x) /* nothing */
+#endif
+
+#define DECLARE_WAIT_QUEUE_HEAD(w) struct wait_queue *w = NULL
+#define DECLARE_WAITQUEUE(w,c) struct wait_queue w = {(c), NULL}
+#define wait_queue_head_t struct wait_queue *
+#define init_waitqueue_head(w) *(w) = 0
+#define init_MUTEX(m) *(m) = MUTEX
+#define __set_current_state(x) do { current->state = (x); } while (0)
+#define set_current_state(x) __set_current_state(x)
 
 /* --------------------------------------------------------------------- */
 
 #ifndef PCI_VENDOR_ID_ENSONIQ
 #define PCI_VENDOR_ID_ENSONIQ        0x1274    
 #endif
+
+#ifndef PCI_VENDOR_ID_ECTIVA
+#define PCI_VENDOR_ID_ECTIVA         0x1102
+#endif
+
 #ifndef PCI_DEVICE_ID_ENSONIQ_ES1371
 #define PCI_DEVICE_ID_ENSONIQ_ES1371 0x1371
 #endif
 
+#ifndef PCI_DEVICE_ID_ENSONIQ_CT5880
+#define PCI_DEVICE_ID_ENSONIQ_CT5880 0x5880
+#endif
+
+#ifndef PCI_DEVICE_ID_ECTIVA_EV1938
+#define PCI_DEVICE_ID_ECTIVA_EV1938 0x8938
+#endif
+
 /* ES1371 chip ID */
 /* This is a little confusing because all ES1371 compatible chips have the
    same DEVICE_ID, the only thing differentiating them is the REV_ID field.
@@ -137,8 +179,9 @@
 #define ES1371REV_ES1373_A  0x04
 #define ES1371REV_ES1373_B  0x06
 #define ES1371REV_CT5880_A  0x07
+#define CT5880REV_CT5880_C  0x02
 #define ES1371REV_ES1371_B  0x09
-
+#define EV1938REV_EV1938_A  0x00
 
 #define ES1371_MAGIC  ((PCI_VENDOR_ID_ENSONIQ<<16)|PCI_DEVICE_ID_ENSONIQ_ES1371)
 
@@ -146,7 +189,7 @@
 #define JOY_EXTENT                8
 
 #define ES1371_REG_CONTROL        0x00
-#define ES1371_REG_STATUS         0x04
+#define ES1371_REG_STATUS         0x04 /* on the 5880 it is control/status */
 #define ES1371_REG_UART_DATA      0x08
 #define ES1371_REG_UART_STATUS    0x09
 #define ES1371_REG_UART_CONTROL   0x09
@@ -214,6 +257,7 @@
 
 
 #define STAT_INTR       0x80000000  /* wired or of all interrupt bits */
+#define CSTAT_5880_AC97_RST 0x20000000 /* CT5880 Reset bit */
 #define STAT_EN_SPDIF   0x00040000  /* enable S/PDIF circuitry */
 #define STAT_TS_SPDIF   0x00020000  /* test S/PDIF circuitry */
 #define STAT_TESTMODE   0x00010000  /* test ASIC */
@@ -372,7 +416,13 @@
 	"NVidea 3D Stereo Enhancement",
 	"Philips Incredible Sound",
 	"Texas Instruments 3D Stereo Enhancement",
-	"VLSI Technology 3D Stereo Enhancement"
+	"VLSI Technology 3D Stereo Enhancement",
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	"SigmaTel SS3D"
 };
 
 /* --------------------------------------------------------------------- */
@@ -393,8 +443,12 @@
 	/* hardware resources */
 	unsigned long io; /* long for SPARC */
 	unsigned int irq;
+
+	/* PCI ID's */
+	u16 vendor;
+	u16 device;
         u8 rev; /* the chip revision */
-        
+
 #ifdef ES1371_DEBUG
         /* debug /proc entry */
 	struct proc_dir_entry *ps;
@@ -416,7 +470,7 @@
 	spinlock_t lock;
 	struct semaphore open_sem;
 	mode_t open_mode;
-	struct wait_queue *open_wait;
+	wait_queue_head_t open_wait;
 
 	struct dmabuf {
 		void *rawbuf;
@@ -427,7 +481,7 @@
 		unsigned total_bytes;
 		int count;
 		unsigned error; /* over/underrun */
-		struct wait_queue *wait;
+		wait_queue_head_t wait;
 		/* redundant, but makes calculations easier */
 		unsigned fragsize;
 		unsigned dmasize;
@@ -445,8 +499,8 @@
 	struct {
 		unsigned ird, iwr, icnt;
 		unsigned ord, owr, ocnt;
-		struct wait_queue *iwait;
-		struct wait_queue *owait;
+		wait_queue_head_t iwait;
+		wait_queue_head_t owait;
 		unsigned char ibuf[MIDIINBUF];
 		unsigned char obuf[MIDIOUTBUF];
 	} midi;
@@ -1228,7 +1282,7 @@
 		
 	case SOUND_MIXER_SPEAKER:
 		j = rdcodec(s, AC97_PCBEEP_VOL);
-		if (j & AC97_MUTE
+		if (j & AC97_MUTE)
 			return put_user(0, (int *)arg);
 		return put_user(0x6464 - ((j >> 1) & 0xf) * 0x606, (int *)arg);
 		
@@ -1607,15 +1661,15 @@
 
 static int drain_dac1(struct es1371_state *s, int nonblock)
 {
-        struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
 	int count, tmo;
 	
 	if (s->dma_dac1.mapped || !s->dma_dac1.ready)
 		return 0;
-        current->state = TASK_INTERRUPTIBLE;
         add_wait_queue(&s->dma_dac1.wait, &wait);
         for (;;) {
+		__set_current_state(TASK_INTERRUPTIBLE);
                 spin_lock_irqsave(&s->lock, flags);
 		count = s->dma_dac1.count;
                 spin_unlock_irqrestore(&s->lock, flags);
@@ -1625,16 +1679,16 @@
                         break;
                 if (nonblock) {
                         remove_wait_queue(&s->dma_dac1.wait, &wait);
-                        current->state = TASK_RUNNING;
+                        set_current_state(TASK_RUNNING);
                         return -EBUSY;
                 }
 		tmo = 3 * HZ * (count + s->dma_dac1.fragsize) / 2 / s->dac1rate;
 		tmo >>= sample_shift[(s->sctrl & SCTRL_P1FMT) >> SCTRL_SH_P1FMT];
 		if (!schedule_timeout(tmo + 1))
-			printk(KERN_DEBUG "es1371: dac1 dma timed out??\n");
+			DBG(printk(KERN_DEBUG "es1371: dac1 dma timed out??\n");)
         }
         remove_wait_queue(&s->dma_dac1.wait, &wait);
-        current->state = TASK_RUNNING;
+        set_current_state(TASK_RUNNING);
         if (signal_pending(current))
                 return -ERESTARTSYS;
         return 0;
@@ -1642,15 +1696,15 @@
 
 static int drain_dac2(struct es1371_state *s, int nonblock)
 {
-        struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
 	int count, tmo;
 
 	if (s->dma_dac2.mapped || !s->dma_dac2.ready)
 		return 0;
-        current->state = TASK_INTERRUPTIBLE;
         add_wait_queue(&s->dma_dac2.wait, &wait);
         for (;;) {
+		__set_current_state(TASK_UNINTERRUPTIBLE);
                 spin_lock_irqsave(&s->lock, flags);
 		count = s->dma_dac2.count;
                 spin_unlock_irqrestore(&s->lock, flags);
@@ -1660,16 +1714,16 @@
                         break;
                 if (nonblock) {
                         remove_wait_queue(&s->dma_dac2.wait, &wait);
-                        current->state = TASK_RUNNING;
+                        set_current_state(TASK_RUNNING);
                         return -EBUSY;
                 }
 		tmo = 3 * HZ * (count + s->dma_dac2.fragsize) / 2 / s->dac2rate;
 		tmo >>= sample_shift[(s->sctrl & SCTRL_P2FMT) >> SCTRL_SH_P2FMT];
 		if (!schedule_timeout(tmo + 1))
-			printk(KERN_DEBUG "es1371: dac2 dma timed out??\n");
+			DBG(printk(KERN_DEBUG "es1371: dac2 dma timed out??\n");)
         }
         remove_wait_queue(&s->dma_dac2.wait, &wait);
-        current->state = TASK_RUNNING;
+        set_current_state(TASK_RUNNING);
         if (signal_pending(current))
                 return -ERESTARTSYS;
         return 0;
@@ -1680,6 +1734,7 @@
 static ssize_t es1371_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
 	struct es1371_state *s = (struct es1371_state *)file->private_data;
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t ret;
 	unsigned long flags;
 	unsigned swptr;
@@ -1695,26 +1750,38 @@
 	if (!access_ok(VERIFY_WRITE, buffer, count))
 		return -EFAULT;
 	ret = 0;
+	add_wait_queue(&s->dma_adc.wait, &wait);
 	while (count > 0) {
 		spin_lock_irqsave(&s->lock, flags);
 		swptr = s->dma_adc.swptr;
 		cnt = s->dma_adc.dmasize-swptr;
 		if (s->dma_adc.count < cnt)
 			cnt = s->dma_adc.count;
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
 		if (cnt <= 0) {
 			start_adc(s);
-			if (file->f_flags & O_NONBLOCK)
-				return ret ? ret : -EAGAIN;
-			interruptible_sleep_on(&s->dma_adc.wait);
-			if (signal_pending(current))
-				return ret ? ret : -ERESTARTSYS;
+			if (file->f_flags & O_NONBLOCK) {
+				if (!ret)
+					ret = -EAGAIN;
+				break;
+			}
+			schedule();
+			if (signal_pending(current)) {
+				if (!ret)
+					ret = -ERESTARTSYS;
+				break;
+			}
 			continue;
 		}
-		if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt))
-			return ret ? ret : -EFAULT;
+		if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) {
+			if (!ret)
+				ret = -EFAULT;
+			break;
+		}
 		swptr = (swptr + cnt) % s->dma_adc.dmasize;
 		spin_lock_irqsave(&s->lock, flags);
 		s->dma_adc.swptr = swptr;
@@ -1725,12 +1792,15 @@
 		ret += cnt;
 		start_adc(s);
 	}
+	remove_wait_queue(&s->dma_adc.wait, &wait);
+	set_current_state(TASK_RUNNING);
 	return ret;
 }
 
 static ssize_t es1371_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
 {
 	struct es1371_state *s = (struct es1371_state *)file->private_data;
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t ret;
 	unsigned long flags;
 	unsigned swptr;
@@ -1746,6 +1816,7 @@
 	if (!access_ok(VERIFY_READ, buffer, count))
 		return -EFAULT;
 	ret = 0;
+	add_wait_queue(&s->dma_dac2.wait, &wait);
 	while (count > 0) {
 		spin_lock_irqsave(&s->lock, flags);
 		if (s->dma_dac2.count < 0) {
@@ -1756,20 +1827,31 @@
 		cnt = s->dma_dac2.dmasize-swptr;
 		if (s->dma_dac2.count + cnt > s->dma_dac2.dmasize)
 			cnt = s->dma_dac2.dmasize - s->dma_dac2.count;
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
 		if (cnt <= 0) {
 			start_dac2(s);
-			if (file->f_flags & O_NONBLOCK)
-				return ret ? ret : -EAGAIN;
-			interruptible_sleep_on(&s->dma_dac2.wait);
-			if (signal_pending(current))
-				return ret ? ret : -ERESTARTSYS;
+			if (file->f_flags & O_NONBLOCK) {
+				if (!ret)
+					ret = -EAGAIN;
+				break;
+			}
+			schedule();
+			if (signal_pending(current)) {
+				if (!ret)
+					ret = -ERESTARTSYS;
+				break;
+			}
 			continue;
 		}
-		if (copy_from_user(s->dma_dac2.rawbuf + swptr, buffer, cnt))
-			return ret ? ret : -EFAULT;
+		if (copy_from_user(s->dma_dac2.rawbuf + swptr, buffer, cnt)) {
+			if (!ret)
+				ret = -EFAULT;
+			break;
+		}
 		swptr = (swptr + cnt) % s->dma_dac2.dmasize;
 		spin_lock_irqsave(&s->lock, flags);
 		s->dma_dac2.swptr = swptr;
@@ -1781,6 +1863,8 @@
 		ret += cnt;
 		start_dac2(s);
 	}
+	remove_wait_queue(&s->dma_dac2.wait, &wait);
+	set_current_state(TASK_RUNNING);
 	return ret;
 }
 
@@ -2150,6 +2234,7 @@
 static int es1371_open(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
+	DECLARE_WAITQUEUE(wait, current);
 	struct es1371_state *s = devs;
 	unsigned long flags;
 
@@ -2166,8 +2251,12 @@
 			up(&s->open_sem);
 			return -EBUSY;
 		}
+		add_wait_queue(&s->open_wait, &wait);
+		__set_current_state(TASK_INTERRUPTIBLE);
 		up(&s->open_sem);
-		interruptible_sleep_on(&s->open_wait);
+		schedule();
+		remove_wait_queue(&s->open_wait, &wait);
+		set_current_state(TASK_RUNNING);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 		down(&s->open_sem);
@@ -2249,6 +2338,7 @@
 static ssize_t es1371_write_dac(struct file *file, const char *buffer, size_t count, loff_t *ppos)
 {
 	struct es1371_state *s = (struct es1371_state *)file->private_data;
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t ret = 0;
 	unsigned long flags;
 	unsigned swptr;
@@ -2263,6 +2353,7 @@
 		return ret;
 	if (!access_ok(VERIFY_READ, buffer, count))
 		return -EFAULT;
+	add_wait_queue(&s->dma_dac1.wait, &wait);
 	while (count > 0) {
 		spin_lock_irqsave(&s->lock, flags);
 		if (s->dma_dac1.count < 0) {
@@ -2273,20 +2364,31 @@
 		cnt = s->dma_dac1.dmasize-swptr;
 		if (s->dma_dac1.count + cnt > s->dma_dac1.dmasize)
 			cnt = s->dma_dac1.dmasize - s->dma_dac1.count;
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
 		if (cnt <= 0) {
 			start_dac1(s);
-			if (file->f_flags & O_NONBLOCK)
-				return ret ? ret : -EAGAIN;
-			interruptible_sleep_on(&s->dma_dac1.wait);
-			if (signal_pending(current))
-				return ret ? ret : -ERESTARTSYS;
+			if (file->f_flags & O_NONBLOCK) {
+				if (!ret)
+					ret = -EAGAIN;
+				break;
+			}
+			schedule();
+			if (signal_pending(current)) {
+				if (!ret)
+					ret = -ERESTARTSYS;
+				break;
+			}
 			continue;
 		}
-		if (copy_from_user(s->dma_dac1.rawbuf + swptr, buffer, cnt))
-			return ret ? ret : -EFAULT;
+		if (copy_from_user(s->dma_dac1.rawbuf + swptr, buffer, cnt)) {
+			if (!ret)
+				ret = -EFAULT;
+			break;
+		}
 		swptr = (swptr + cnt) % s->dma_dac1.dmasize;
 		spin_lock_irqsave(&s->lock, flags);
 		s->dma_dac1.swptr = swptr;
@@ -2298,6 +2400,8 @@
 		ret += cnt;
 		start_dac1(s);
 	}
+	remove_wait_queue(&s->dma_dac1.wait, &wait);
+	set_current_state(TASK_RUNNING);
 	return ret;
 }
 
@@ -2526,6 +2630,7 @@
 static int es1371_open_dac(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
+	DECLARE_WAITQUEUE(wait, current);
 	struct es1371_state *s = devs;
 	unsigned long flags;
 
@@ -2549,8 +2654,12 @@
 			up(&s->open_sem);
 			return -EBUSY;
 		}
+		add_wait_queue(&s->open_wait, &wait);
+		__set_current_state(TASK_INTERRUPTIBLE);
 		up(&s->open_sem);
-		interruptible_sleep_on(&s->open_wait);
+		schedule();
+		remove_wait_queue(&s->open_wait, &wait);
+		set_current_state(TASK_RUNNING);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 		down(&s->open_sem);
@@ -2610,7 +2719,7 @@
 static ssize_t es1371_midi_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
 	struct es1371_state *s = (struct es1371_state *)file->private_data;
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t ret;
 	unsigned long flags;
 	unsigned ptr;
@@ -2631,6 +2740,8 @@
 		cnt = MIDIINBUF - ptr;
 		if (s->midi.icnt < cnt)
 			cnt = s->midi.icnt;
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
@@ -2640,7 +2751,6 @@
 					ret = -EAGAIN;
 				break;
 			}
-			current->state = TASK_INTERRUPTIBLE;
 			schedule();
 			if (signal_pending(current)) {
 				if (!ret)
@@ -2664,7 +2774,7 @@
 		ret += cnt;
 		break;
 	}
-	current->state = TASK_RUNNING;
+	__set_current_state(TASK_RUNNING);
 	remove_wait_queue(&s->midi.iwait, &wait);
 	return ret;
 }
@@ -2672,7 +2782,7 @@
 static ssize_t es1371_midi_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
 {
 	struct es1371_state *s = (struct es1371_state *)file->private_data;
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t ret;
 	unsigned long flags;
 	unsigned ptr;
@@ -2693,8 +2803,10 @@
 		cnt = MIDIOUTBUF - ptr;
 		if (s->midi.ocnt + cnt > MIDIOUTBUF)
 			cnt = MIDIOUTBUF - s->midi.ocnt;
-		if (cnt <= 0)
+		if (cnt <= 0) {
+			__set_current_state(TASK_INTERRUPTIBLE);
 			es1371_handle_midi(s);
+		}
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
@@ -2704,7 +2816,6 @@
 					ret = -EAGAIN;
 				break;
 			}
-			current->state = TASK_INTERRUPTIBLE;
 			schedule();
 			if (signal_pending(current)) {
 				if (!ret)
@@ -2730,7 +2841,7 @@
 		es1371_handle_midi(s);
 		spin_unlock_irqrestore(&s->lock, flags);
 	}
-	current->state = TASK_RUNNING;
+	__set_current_state(TASK_RUNNING);
 	remove_wait_queue(&s->midi.owait, &wait);
 	return ret;
 }
@@ -2762,6 +2873,7 @@
 static int es1371_midi_open(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
+	DECLARE_WAITQUEUE(wait, current);
 	struct es1371_state *s = devs;
 	unsigned long flags;
 
@@ -2778,8 +2890,12 @@
 			up(&s->open_sem);
 			return -EBUSY;
 		}
+		add_wait_queue(&s->open_wait, &wait);
+		__set_current_state(TASK_INTERRUPTIBLE);
 		up(&s->open_sem);
-		interruptible_sleep_on(&s->open_wait);
+		schedule();
+		remove_wait_queue(&s->open_wait, &wait);
+		set_current_state(TASK_RUNNING);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 		down(&s->open_sem);
@@ -2811,15 +2927,15 @@
 static int es1371_midi_release(struct inode *inode, struct file *file)
 {
 	struct es1371_state *s = (struct es1371_state *)file->private_data;
-        struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
 	unsigned count, tmo;
 
 	VALIDATE_STATE(s);
 	if (file->f_mode & FMODE_WRITE) {
-		current->state = TASK_INTERRUPTIBLE;
 		add_wait_queue(&s->midi.owait, &wait);
 		for (;;) {
+			__set_current_state(TASK_INTERRUPTIBLE);
 			spin_lock_irqsave(&s->lock, flags);
 			count = s->midi.ocnt;
 			spin_unlock_irqrestore(&s->lock, flags);
@@ -2829,7 +2945,7 @@
 				break;
 			if (file->f_flags & O_NONBLOCK) {
 				remove_wait_queue(&s->midi.owait, &wait);
-				current->state = TASK_RUNNING;
+				set_current_state(TASK_RUNNING);
 				return -EBUSY;
 			}
 			tmo = (count * HZ) / 3100;
@@ -2837,7 +2953,7 @@
 				printk(KERN_DEBUG "es1371: midi timed out??\n");
 		}
 		remove_wait_queue(&s->midi.owait, &wait);
-		current->state = TASK_RUNNING;
+		set_current_state(TASK_RUNNING);
 	}
 	down(&s->open_sem);
 	s->open_mode &= (~(file->f_mode << FMODE_MIDI_SHIFT)) & (FMODE_MIDI_READ|FMODE_MIDI_WRITE);
@@ -2882,7 +2998,7 @@
 static int proc_es1371_dump (char *buf, char **start, off_t fpos, int length, int *eof, void *data)
 {
         int len = 0;
-
+        
         struct es1371_state *s = devs;
         int cnt;
 
@@ -2944,166 +3060,214 @@
 	{ SOUND_MIXER_WRITE_IGAIN, 0x4040 }
 };
 
+__initfunc(static int probe_chip(struct pci_dev *pcidev, int index))
+{
+	struct es1371_state *s;
+	mm_segment_t fs;
+	int i, val, val2;
+	unsigned char id[4];
+	unsigned long tmo;
+	signed long tmo2;
+	unsigned int cssr;
+
+	if (pcidev->base_address[0] == 0 || 
+	    (pcidev->base_address[0] & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO)
+		return -1;
+	if (pcidev->irq == 0) 
+		return -1;
+	if (!(s = kmalloc(sizeof(struct es1371_state), GFP_KERNEL))) {
+		printk(KERN_WARNING "es1371: out of memory\n");
+		return -1;
+	}
+	memset(s, 0, sizeof(struct es1371_state));
+	init_waitqueue_head(&s->dma_adc.wait);
+	init_waitqueue_head(&s->dma_dac1.wait);
+	init_waitqueue_head(&s->dma_dac2.wait);
+	init_waitqueue_head(&s->open_wait);
+	init_waitqueue_head(&s->midi.iwait);
+	init_waitqueue_head(&s->midi.owait);
+	init_MUTEX(&s->open_sem);
+	spin_lock_init(&s->lock);
+	s->magic = ES1371_MAGIC;
+	s->io = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
+	s->irq = pcidev->irq;
+	s->vendor = pcidev->vendor;
+	s->device = pcidev->device;
+	pci_read_config_byte(pcidev, PCI_REVISION_ID, &s->rev);
+	printk(KERN_INFO "es1371: found chip, vendor id 0x%04x device id 0x%04x revision 0x%02x\n",
+	       s->vendor, s->device, s->rev);
+	if (check_region(s->io, ES1371_EXTENT)) {
+		printk(KERN_ERR "es1371: io ports %#lx-%#lx in use\n", s->io, s->io+ES1371_EXTENT-1);
+		goto err_region;
+	}
+	request_region(s->io, ES1371_EXTENT, "es1371");
+	if (request_irq(s->irq, es1371_interrupt, SA_SHIRQ, "es1371", s)) {
+		printk(KERN_ERR "es1371: irq %u in use\n", s->irq);
+		goto err_irq;
+	}
+	printk(KERN_INFO "es1371: found es1371 rev %d at io %#lx irq %u\n"
+	       KERN_INFO "es1371: features: joystick 0x%x\n", s->rev, s->io, s->irq, joystick[index]);
+	/* register devices */
+	if ((s->dev_audio = register_sound_dsp(&es1371_audio_fops, -1)) < 0)
+		goto err_dev1;
+	if ((s->dev_mixer = register_sound_mixer(&es1371_mixer_fops, -1)) < 0)
+		goto err_dev2;
+	if ((s->dev_dac = register_sound_dsp(&es1371_dac_fops, -1)) < 0)
+		goto err_dev3;
+	if ((s->dev_midi = register_sound_midi(&es1371_midi_fops, -1)) < 0)
+		goto err_dev4;
+#ifdef ES1371_DEBUG
+	/* intialize the debug proc device */
+	s->ps = create_proc_read_entry("es1371",0,NULL,proc_es1371_dump,NULL);
+#endif /* ES1371_DEBUG */
+	
+	/* initialize codec registers */
+	s->ctrl = 0;
+	if ((joystick[index] & ~0x18) == 0x200) {
+		if (check_region(joystick[index], JOY_EXTENT))
+			printk(KERN_ERR "es1371: joystick address 0x%x already in use\n", joystick[index]);
+		else {
+			s->ctrl |= CTRL_JYSTK_EN | (((joystick[index] >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
+		}
+	}
+	s->sctrl = 0;
+	cssr = 0;
+	/* check to see if s/pdif mode is being requested */
+	if (spdif[index]) {
+		if (s->rev >= 4) {
+			printk(KERN_INFO "es1371: enabling S/PDIF output\n");
+			cssr |= STAT_EN_SPDIF;
+			s->ctrl |= CTRL_SPDIFEN_B;
+		} else {
+			printk(KERN_ERR "es1371: revision %d does not support S/PDIF\n", s->rev);
+		}
+	}
+	/* initialize the chips */
+	outl(s->ctrl, s->io+ES1371_REG_CONTROL);
+	outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
+	outl(0, s->io+ES1371_REG_LEGACY);
+	pci_set_master(pcidev);  /* enable bus mastering */
+	/* if we are a 5880 turn on the AC97 */
+	if (s->vendor == PCI_VENDOR_ID_ENSONIQ &&
+	    ((s->device == PCI_DEVICE_ID_ENSONIQ_CT5880 && s->rev == CT5880REV_CT5880_C) || 
+	     (s->device == PCI_DEVICE_ID_ENSONIQ_ES1371 && s->rev == ES1371REV_CT5880_A))) { 
+		cssr |= CSTAT_5880_AC97_RST;
+		outl(cssr, s->io+ES1371_REG_STATUS);
+		/* need to delay around 20ms(bleech) to give
+		   some CODECs enough time to wakeup */
+		tmo = jiffies + (HZ / 50) + 1;
+		for (;;) {
+			tmo2 = tmo - jiffies;
+			if (tmo2 <= 0)
+				break;
+			schedule_timeout(tmo2);
+		}
+	}
+	/* AC97 warm reset to start the bitclk */
+	outl(s->ctrl | CTRL_SYNCRES, s->io+ES1371_REG_CONTROL);
+	udelay(2);
+	outl(s->ctrl, s->io+ES1371_REG_CONTROL);
+	/* init the sample rate converter */
+	src_init(s);
+	/* codec init */
+	wrcodec(s, AC97_RESET, 0); /* reset codec */
+	s->mix.codec_id = rdcodec(s, AC97_RESET);  /* get codec ID */
+	val = rdcodec(s, AC97_VENDOR_ID1);
+	val2 = rdcodec(s, AC97_VENDOR_ID2);
+	id[0] = val >> 8;
+	id[1] = val;
+	id[2] = val2 >> 8;
+	id[3] = 0;
+	if (id[0] <= ' ' || id[0] > 0x7f)
+		id[0] = ' ';
+	if (id[1] <= ' ' || id[1] > 0x7f)
+		id[1] = ' ';
+	if (id[2] <= ' ' || id[2] > 0x7f)
+		id[2] = ' ';
+	printk(KERN_INFO "es1371: codec vendor %s (0x%04x%02x) revision %d (0x%02x)\n", 
+	       id, val & 0xffff, (val2 >> 8) & 0xff, val2 & 0xff, val2 & 0xff);
+	printk(KERN_INFO "es1371: codec features");
+	if (s->mix.codec_id & CODEC_ID_DEDICATEDMIC)
+		printk(" dedicated MIC PCM in");
+	if (s->mix.codec_id & CODEC_ID_MODEMCODEC)
+		printk(" Modem Line Codec");
+	if (s->mix.codec_id & CODEC_ID_BASSTREBLE)
+		printk(" Bass & Treble");
+	if (s->mix.codec_id & CODEC_ID_SIMULATEDSTEREO)
+		printk(" Simulated Stereo");
+	if (s->mix.codec_id & CODEC_ID_HEADPHONEOUT)
+		printk(" Headphone out");
+	if (s->mix.codec_id & CODEC_ID_LOUDNESS)
+		printk(" Loudness");
+	if (s->mix.codec_id & CODEC_ID_18BITDAC)
+		printk(" 18bit DAC");
+	if (s->mix.codec_id & CODEC_ID_20BITDAC)
+		printk(" 20bit DAC");
+	if (s->mix.codec_id & CODEC_ID_18BITADC)
+		printk(" 18bit ADC");
+	if (s->mix.codec_id & CODEC_ID_20BITADC)
+		printk(" 20bit ADC");
+	printk("%s\n", (s->mix.codec_id & 0x3ff) ? "" : " none");
+	val = (s->mix.codec_id >> CODEC_ID_SESHIFT) & CODEC_ID_SEMASK;
+	printk(KERN_INFO "es1371: stereo enhancement: %s\n", 
+	       (val <= 26 && stereo_enhancement[val]) ? stereo_enhancement[val] : "unknown");
+
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+	val = SOUND_MASK_LINE;
+	mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);
+	for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) {
+		val = initvol[i].vol;
+		mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
+	}
+	set_fs(fs);
+	/* turn on S/PDIF output driver if requested */
+	outl(cssr, s->io+ES1371_REG_STATUS);
+	/* queue it for later freeing */
+	s->next = devs;
+	devs = s;
+       	return 0;
+
+ err_dev4:
+	unregister_sound_dsp(s->dev_dac);
+ err_dev3:
+	unregister_sound_mixer(s->dev_mixer);
+ err_dev2:
+	unregister_sound_dsp(s->dev_audio);
+ err_dev1:
+	printk(KERN_ERR "es1371: cannot register misc device\n");
+	free_irq(s->irq, s);
+ err_irq:
+	release_region(s->io, ES1371_EXTENT);
+ err_region:
+	kfree_s(s, sizeof(struct es1371_state));
+	return -1;
+}
+
 #ifdef MODULE
 __initfunc(int init_module(void))
 #else
 __initfunc(int init_es1371(void))
 #endif
 {
-	struct es1371_state *s;
-	struct pci_dev *pcidev = NULL;
-	mm_segment_t fs;
-	int i, val, val2, index = 0;
-	unsigned cssr;
+	struct pci_dev *pcidev;
+	int index = 0;
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "es1371: version v0.19 time " __TIME__ " " __DATE__ "\n");
-	while (index < NR_DEVICE && 
-	       (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1371, pcidev))) {
-		if (pcidev->base_address[0] == 0 || 
-		    (pcidev->base_address[0] & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO)
-			continue;
-		if (pcidev->irq == 0) 
-			continue;
-		if (!(s = kmalloc(sizeof(struct es1371_state), GFP_KERNEL))) {
-			printk(KERN_WARNING "es1371: out of memory\n");
+	printk(KERN_INFO "es1371: version v0.22 time " __TIME__ " " __DATE__ "\n");
+	for (pcidev = pci_devices; pcidev && index < NR_DEVICE; pcidev = pcidev->next) {
+		if (pcidev->vendor == PCI_VENDOR_ID_ENSONIQ) {
+			if (pcidev->device != PCI_DEVICE_ID_ENSONIQ_ES1371 &&
+			    pcidev->device != PCI_DEVICE_ID_ENSONIQ_CT5880)
+				continue;
+		} else if (pcidev->vendor == PCI_VENDOR_ID_ECTIVA) {
+			if (pcidev->device != PCI_DEVICE_ID_ECTIVA_EV1938)
+				continue;
+		} else
 			continue;
-		}
-		memset(s, 0, sizeof(struct es1371_state));
-		init_waitqueue(&s->dma_adc.wait);
-		init_waitqueue(&s->dma_dac1.wait);
-		init_waitqueue(&s->dma_dac2.wait);
-		init_waitqueue(&s->open_wait);
-		init_waitqueue(&s->midi.iwait);
-		init_waitqueue(&s->midi.owait);
-		s->open_sem = MUTEX;
-		spin_lock_init(&s->lock);
-		s->magic = ES1371_MAGIC;
-		s->io = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
-		s->irq = pcidev->irq;
-		pci_read_config_byte(pcidev, PCI_REVISION_ID, &s->rev);
-		if (check_region(s->io, ES1371_EXTENT)) {
-			printk(KERN_ERR "es1371: io ports %#lx-%#lx in use\n", s->io, s->io+ES1371_EXTENT-1);
-			goto err_region;
-		}
-		request_region(s->io, ES1371_EXTENT, "es1371");
-		if (request_irq(s->irq, es1371_interrupt, SA_SHIRQ, "es1371", s)) {
-			printk(KERN_ERR "es1371: irq %u in use\n", s->irq);
-			goto err_irq;
-		}
-		printk(KERN_INFO "es1371: found adapter at io %#lx irq %u\n"
-		       KERN_INFO "es1371: features: joystick 0x%x\n", s->io, s->irq, joystick[index]);
-		/* register devices */
-		if ((s->dev_audio = register_sound_dsp(&es1371_audio_fops, -1)) < 0)
-			goto err_dev1;
-		if ((s->dev_mixer = register_sound_mixer(&es1371_mixer_fops, -1)) < 0)
-			goto err_dev2;
-		if ((s->dev_dac = register_sound_dsp(&es1371_dac_fops, -1)) < 0)
-			goto err_dev3;
-		if ((s->dev_midi = register_sound_midi(&es1371_midi_fops, -1)) < 0)
-			goto err_dev4;
-#ifdef ES1371_DEBUG
-                /* intialize the debug proc device */
-                s->ps = create_proc_entry("es1371", S_IFREG | S_IRUGO, NULL);
-                if (s->ps)
-                        s->ps->read_proc = proc_es1371_dump;
-#endif /* ES1371_DEBUG */
-
-		/* initialize codec registers */
-		s->ctrl = 0;
-		if ((joystick[index] & ~0x18) == 0x200) {
-			if (check_region(joystick[index], JOY_EXTENT))
-				printk(KERN_ERR "es1371: joystick address 0x%x already in use\n", joystick[index]);
-			else {
-				s->ctrl |= CTRL_JYSTK_EN | (((joystick[index] >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
-			}
-		}
-		s->sctrl = 0;
-		cssr = 0;
-		/* check to see if s/pdif mode is being requested */
-		if (spdif[index]) {
-			if (s->rev >= 4) {
-				printk(KERN_INFO "es1371: enabling S/PDIF output\n");
-				cssr |= STAT_EN_SPDIF;
-				s->ctrl |= CTRL_SPDIFEN_B;
-			} else {
-				printk(KERN_ERR "es1371: revision %d does not support S/PDIF\n", s->rev);
-			}
-		}
-		/* initialize the chips */
-		outl(s->ctrl, s->io+ES1371_REG_CONTROL);
-		outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
-		outl(0, s->io+ES1371_REG_LEGACY);
-		pci_set_master(pcidev);  /* enable bus mastering */
-		/* AC97 warm reset to start the bitclk */
-		outl(s->ctrl | CTRL_SYNCRES, s->io+ES1371_REG_CONTROL);
-		udelay(2);
-		outl(s->ctrl, s->io+ES1371_REG_CONTROL);
-		/* init the sample rate converter */
-                src_init(s);
-		/* codec init */
-		wrcodec(s, AC97_RESET, 0); /* reset codec */
-		s->mix.codec_id = rdcodec(s, AC97_RESET);  /* get codec ID */
-		val = rdcodec(s, AC97_VENDOR_ID1);
-		val2 = rdcodec(s, AC97_VENDOR_ID2);
-		printk(KERN_INFO "es1371: codec vendor %c%c%c revision %d\n", 
-		       (val >> 8) & 0xff, val & 0xff, (val2 >> 8) & 0xff, val2 & 0xff);
-		printk(KERN_INFO "es1371: codec features");
-		if (s->mix.codec_id & CODEC_ID_DEDICATEDMIC)
-			printk(" dedicated MIC PCM in");
-		if (s->mix.codec_id & CODEC_ID_MODEMCODEC)
-			printk(" Modem Line Codec");
-		if (s->mix.codec_id & CODEC_ID_BASSTREBLE)
-			printk(" Bass & Treble");
-		if (s->mix.codec_id & CODEC_ID_SIMULATEDSTEREO)
-			printk(" Simulated Stereo");
-		if (s->mix.codec_id & CODEC_ID_HEADPHONEOUT)
-			printk(" Headphone out");
-		if (s->mix.codec_id & CODEC_ID_LOUDNESS)
-			printk(" Loudness");
-		if (s->mix.codec_id & CODEC_ID_18BITDAC)
-			printk(" 18bit DAC");
-		if (s->mix.codec_id & CODEC_ID_20BITDAC)
-			printk(" 20bit DAC");
-		if (s->mix.codec_id & CODEC_ID_18BITADC)
-			printk(" 18bit ADC");
-		if (s->mix.codec_id & CODEC_ID_20BITADC)
-			printk(" 20bit ADC");
-		printk("%s\n", (s->mix.codec_id & 0x3ff) ? "" : " none");
-		val = (s->mix.codec_id >> CODEC_ID_SESHIFT) & CODEC_ID_SEMASK;
-		printk(KERN_INFO "es1371: stereo enhancement: %s\n", (val <= 20) ? stereo_enhancement[val] : "unknown");
-
-		fs = get_fs();
-		set_fs(KERNEL_DS);
-		val = SOUND_MASK_LINE;
-		mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);
-		for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) {
-			val = initvol[i].vol;
-			mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
-		}
-		set_fs(fs);
-		/* turn on S/PDIF output driver if requested */
-		outl(cssr, s->io+ES1371_REG_STATUS);
-		/* queue it for later freeing */
-		s->next = devs;
-		devs = s;
-		index++;
-		continue;
-
-	err_dev4:
-		unregister_sound_dsp(s->dev_dac);
-	err_dev3:
-		unregister_sound_mixer(s->dev_mixer);
-	err_dev2:
-		unregister_sound_dsp(s->dev_audio);
-	err_dev1:
-		printk(KERN_ERR "es1371: cannot register misc device\n");
-		free_irq(s->irq, s);
-	err_irq:
-		release_region(s->io, ES1371_EXTENT);
-	err_region:
-		kfree_s(s, sizeof(struct es1371_state));
+		if (!probe_chip(pcidev, index))
+			index++;
 	}
 	if (!devs)
 		return -ENODEV;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/sound/esssolo1.c linux.15p9/drivers/sound/esssolo1.c
--- linux.vanilla/drivers/sound/esssolo1.c	Tue Jan  4 21:18:59 2000
+++ linux.15p9/drivers/sound/esssolo1.c	Wed Feb 16 18:37:46 2000
@@ -3,7 +3,7 @@
 /*
  *      esssolo1.c  --  ESS Technology Solo1 (ES1946) audio driver.
  *
- *      Copyright (C) 1998-1999  Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *      Copyright (C) 1998-2000  Thomas Sailer (sailer@ife.ee.ethz.ch)
  *
  *      This program is free software; you can redistribute it and/or modify
  *      it under the terms of the GNU General Public License as published by
@@ -28,38 +28,41 @@
  *  /dev/midi   simple MIDI UART interface, no ioctl
  *
  *  Revision history
- *    10.11.98   0.1   Initial release (without any hardware)
- *    22.03.99   0.2   cinfo.blocks should be reset after GETxPTR ioctl.
- *                     reported by Johan Maes <joma@telindus.be>
- *                     return EAGAIN instead of EBUSY when O_NONBLOCK
- *                     read/write cannot be executed
- *    07.04.99   0.3   implemented the following ioctl's: SOUND_PCM_READ_RATE, 
- *                     SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS; 
- *                     Alpha fixes reported by Peter Jones <pjones@redhat.com>
- *    15.06.99   0.4   Fix bad allocation bug.
- *                     Thanks to Deti Fliegl <fliegl@in.tum.de>
- *    28.06.99   0.5   Add pci_set_master
- *    12.08.99   0.6   Fix MIDI UART crashing the driver
- *                     Changed mixer semantics from OSS documented
- *                     behaviour to OSS "code behaviour".
- *                     Recording might actually work now.
- *                     The real DDMA controller address register is at PCI config
- *                     0x60, while the register at 0x18 is used as a placeholder
- *                     register for BIOS address allocation. This register
- *                     is supposed to be copied into 0x60, according
- *                     to the Solo1 datasheet. When I do that, I can access
- *                     the DDMA registers except the mask bit, which
- *                     is stuck at 1. When I copy the contents of 0x18 +0x10
- *                     to the DDMA base register, everything seems to work.
- *                     The fun part is that the Windows Solo1 driver doesn't
- *                     seem to do these tricks.
- *                     Bugs remaining: plops and clicks when starting/stopping playback
- *    31.08.99   0.7   add spin_lock_init
- *                     replaced current->state = x with set_current_state(x)
- *    03.09.99   0.8   change read semantics for MIDI to match
- *                     OSS more closely; remove possible wakeup race
- *    07.10.99   0.9   Fix initialization; complain if sequencer writes time out
- *                     Revised resource grabbing for the FM synthesizer
+ *    10.11.1998   0.1   Initial release (without any hardware)
+ *    22.03.1999   0.2   cinfo.blocks should be reset after GETxPTR ioctl.
+ *                       reported by Johan Maes <joma@telindus.be>
+ *                       return EAGAIN instead of EBUSY when O_NONBLOCK
+ *                       read/write cannot be executed
+ *    07.04.1999   0.3   implemented the following ioctl's: SOUND_PCM_READ_RATE, 
+ *                       SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS; 
+ *                       Alpha fixes reported by Peter Jones <pjones@redhat.com>
+ *    15.06.1999   0.4   Fix bad allocation bug.
+ *                       Thanks to Deti Fliegl <fliegl@in.tum.de>
+ *    28.06.1999   0.5   Add pci_set_master
+ *    12.08.1999   0.6   Fix MIDI UART crashing the driver
+ *                       Changed mixer semantics from OSS documented
+ *                       behaviour to OSS "code behaviour".
+ *                       Recording might actually work now.
+ *                       The real DDMA controller address register is at PCI config
+ *                       0x60, while the register at 0x18 is used as a placeholder
+ *                       register for BIOS address allocation. This register
+ *                       is supposed to be copied into 0x60, according
+ *                       to the Solo1 datasheet. When I do that, I can access
+ *                       the DDMA registers except the mask bit, which
+ *                       is stuck at 1. When I copy the contents of 0x18 +0x10
+ *                       to the DDMA base register, everything seems to work.
+ *                       The fun part is that the Windows Solo1 driver doesn't
+ *                       seem to do these tricks.
+ *                       Bugs remaining: plops and clicks when starting/stopping playback
+ *    31.08.1999   0.7   add spin_lock_init
+ *                       replaced current->state = x with set_current_state(x)
+ *    03.09.1999   0.8   change read semantics for MIDI to match
+ *                       OSS more closely; remove possible wakeup race
+ *    07.10.1999   0.9   Fix initialization; complain if sequencer writes time out
+ *                       Revised resource grabbing for the FM synthesizer
+ *    28.10.1999   0.10  More waitqueue races fixed
+ *    09.12.1999   0.11  Work around stupid Alpha port issue (virt_to_bus(kmalloc(GFP_DMA)) > 16M)
+ *                       Disabling recording on Alpha
  *
  */
 
@@ -442,6 +445,14 @@
 				break;
 		if (!db->rawbuf)
 			return -ENOMEM;
+		/* work around a problem of the alpha port */
+		if ((gfp_mask & GFP_DMA) && (virt_to_bus(db->rawbuf) & (~0xffffffUL))) {
+			printk(KERN_ERR "solo1: requested DMA buffer below 16M but got 0x%lx, Alpha bug?\n", 
+			       (unsigned long)virt_to_bus(db->rawbuf));
+			kfree(db->rawbuf);
+			db->rawbuf = NULL;
+			return -ENOMEM;
+		}
 		db->buforder = order;
 		/* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */
 		mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
@@ -963,9 +974,9 @@
 	
 	if (s->dma_dac.mapped)
 		return 0;
-        __set_current_state(TASK_INTERRUPTIBLE);
         add_wait_queue(&s->dma_dac.wait, &wait);
         for (;;) {
+		set_current_state(TASK_INTERRUPTIBLE);
                 spin_lock_irqsave(&s->lock, flags);
 		count = s->dma_dac.count;
                 spin_unlock_irqrestore(&s->lock, flags);
@@ -998,6 +1009,7 @@
 static ssize_t solo1_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
 	struct solo1_state *s = (struct solo1_state *)file->private_data;
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t ret;
 	unsigned long flags;
 	unsigned swptr;
@@ -1013,12 +1025,15 @@
 	if (!access_ok(VERIFY_WRITE, buffer, count))
 		return -EFAULT;
 	ret = 0;
+	add_wait_queue(&s->dma_adc.wait, &wait);
 	while (count > 0) {
 		spin_lock_irqsave(&s->lock, flags);
 		swptr = s->dma_adc.swptr;
 		cnt = s->dma_adc.dmasize-swptr;
 		if (s->dma_adc.count < cnt)
 			cnt = s->dma_adc.count;
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
@@ -1039,9 +1054,12 @@
 #endif
 			if (inb(s->ddmabase+15) & 1)
 				printk(KERN_ERR "solo1: cannot start recording, DDMA mask bit stuck at 1\n");
-			if (file->f_flags & O_NONBLOCK)
-				return ret ? ret : -EAGAIN;
-			interruptible_sleep_on(&s->dma_adc.wait);
+			if (file->f_flags & O_NONBLOCK) {
+				if (!ret)
+					ret = -EAGAIN;
+				break;
+			}
+			schedule();
 #ifdef DEBUGREC
 			printk(KERN_DEBUG "solo1_read: regs: A1: 0x%02x  A2: 0x%02x  A4: 0x%02x  A5: 0x%02x  A8: 0x%02x\n"
 			       KERN_DEBUG "solo1_read: regs: B1: 0x%02x  B2: 0x%02x  B7: 0x%02x  B8: 0x%02x  B9: 0x%02x\n"
@@ -1051,12 +1069,18 @@
 			       read_ctrl(s, 0xb1), read_ctrl(s, 0xb2), read_ctrl(s, 0xb7), read_ctrl(s, 0xb8), read_ctrl(s, 0xb9), 
 			       inl(s->ddmabase), inw(s->ddmabase+4), inb(s->ddmabase+8), inb(s->ddmabase+15), inb(s->sbbase+0xc), cnt);
 #endif
-			if (signal_pending(current))
-				return ret ? ret : -ERESTARTSYS;
+			if (signal_pending(current)) {
+				if (!ret)
+					ret = -ERESTARTSYS;
+				break;
+			}
 			continue;
 		}
-		if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt))
-			return ret ? ret : -EFAULT;
+		if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) {
+			if (!ret)
+				ret = -EFAULT;
+			break;
+		}
 		swptr = (swptr + cnt) % s->dma_adc.dmasize;
 		spin_lock_irqsave(&s->lock, flags);
 		s->dma_adc.swptr = swptr;
@@ -1071,12 +1095,15 @@
 		       read_ctrl(s, 0xb8), inb(s->ddmabase+8), inw(s->ddmabase+4), inb(s->sbbase+0xc));
 #endif
 	}
+	remove_wait_queue(&s->dma_adc.wait, &wait);
+	set_current_state(TASK_RUNNING);
 	return ret;
 }
 
 static ssize_t solo1_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
 {
 	struct solo1_state *s = (struct solo1_state *)file->private_data;
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t ret;
 	unsigned long flags;
 	unsigned swptr;
@@ -1100,6 +1127,7 @@
 	       read_mixer(s, 0x78), read_mixer(s, 0x7a), inw(s->iobase+4), inb(s->iobase+6), inb(s->sbbase+0xc));
 #endif
 	ret = 0;
+	add_wait_queue(&s->dma_dac.wait, &wait);	
 	while (count > 0) {
 		spin_lock_irqsave(&s->lock, flags);
 		if (s->dma_dac.count < 0) {
@@ -1110,20 +1138,31 @@
 		cnt = s->dma_dac.dmasize-swptr;
 		if (s->dma_dac.count + cnt > s->dma_dac.dmasize)
 			cnt = s->dma_dac.dmasize - s->dma_dac.count;
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
 		if (cnt <= 0) {
 			start_dac(s);
-			if (file->f_flags & O_NONBLOCK)
-				return ret ? ret : -EAGAIN;
-			interruptible_sleep_on(&s->dma_dac.wait);
-			if (signal_pending(current))
-				return ret ? ret : -ERESTARTSYS;
+			if (file->f_flags & O_NONBLOCK) {
+				if (!ret)
+					ret = -EAGAIN;
+				break;
+			}
+			schedule();
+			if (signal_pending(current)) {
+				if (!ret)
+					ret = -ERESTARTSYS;
+				break;
+			}
 			continue;
 		}
-		if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt))
-			return ret ? ret : -EFAULT;
+		if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt)) {
+			if (!ret)
+				ret = -EFAULT;
+			break;
+		}
 		swptr = (swptr + cnt) % s->dma_dac.dmasize;
 		spin_lock_irqsave(&s->lock, flags);
 		s->dma_dac.swptr = swptr;
@@ -1135,6 +1174,8 @@
 		ret += cnt;
 		start_dac(s);
 	}
+	remove_wait_queue(&s->dma_dac.wait, &wait);
+	set_current_state(TASK_RUNNING);
 	return ret;
 }
 
@@ -1209,7 +1250,7 @@
 	unsigned long flags;
         audio_buf_info abinfo;
         count_info cinfo;
-	int val, mapped, ret;
+	int val, mapped, ret, count;
         int div1, div2;
         unsigned rate1, rate2;
 
@@ -1289,7 +1330,7 @@
 			stop_dac(s);
 			s->dma_adc.ready = s->dma_dac.ready = 0;
 			/* program channels */
-			s->channels = val ? 2 : 1;
+			s->channels = (val >= 2) ? 2 : 1;
 			prog_codec(s);
 		}
 		return put_user(s->channels, (int *)arg);
@@ -1353,7 +1394,10 @@
 		spin_lock_irqsave(&s->lock, flags);
 		solo1_update_ptr(s);
 		abinfo.fragsize = s->dma_dac.fragsize;
-                abinfo.bytes = s->dma_dac.dmasize - s->dma_dac.count;
+		count = s->dma_dac.count;
+		if (count < 0)
+			count = 0;
+                abinfo.bytes = s->dma_dac.dmasize - count;
                 abinfo.fragstotal = s->dma_dac.numfrag;
                 abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift;      
 		spin_unlock_irqrestore(&s->lock, flags);
@@ -1382,9 +1426,11 @@
 			return -EINVAL;
 		spin_lock_irqsave(&s->lock, flags);
 		solo1_update_ptr(s);
-                val = s->dma_dac.count;
+                count = s->dma_dac.count;
 		spin_unlock_irqrestore(&s->lock, flags);
-		return put_user(val, (int *)arg);
+		if (count < 0)
+			count = 0;
+		return put_user(count, (int *)arg);
 
         case SNDCTL_DSP_GETIPTR:
 		if (!(file->f_mode & FMODE_READ))
@@ -1392,7 +1438,10 @@
 		spin_lock_irqsave(&s->lock, flags);
 		solo1_update_ptr(s);
                 cinfo.bytes = s->dma_adc.total_bytes;
-                cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift;
+		count = s->dma_dac.count;
+		if (count < 0)
+			count = 0;
+		cinfo.blocks = count >> s->dma_dac.fragshift;
                 cinfo.ptr = s->dma_adc.hwptr;
 		if (s->dma_adc.mapped)
 			s->dma_adc.count &= s->dma_adc.fragsize-1;
@@ -1410,6 +1459,12 @@
 		if (s->dma_dac.mapped)
 			s->dma_dac.count &= s->dma_dac.fragsize-1;
 		spin_unlock_irqrestore(&s->lock, flags);
+#if 0
+		printk(KERN_DEBUG "esssolo1: GETOPTR: bytes %u blocks %u ptr %u, buforder %u numfrag %u fragshift %u\n"
+		       KERN_DEBUG "esssolo1: swptr %u count %u fragsize %u dmasize %u fragsamples %u\n",
+		       cinfo.bytes, cinfo.blocks, cinfo.ptr, s->dma_dac.buforder, s->dma_dac.numfrag, s->dma_dac.fragshift,
+		       s->dma_dac.swptr, s->dma_dac.count, s->dma_dac.fragsize, s->dma_dac.dmasize, s->dma_dac.fragsamples);
+#endif
                 return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
 
         case SNDCTL_DSP_GETBLKSIZE:
@@ -1497,8 +1552,8 @@
 		dealloc_dmabuf(&s->dma_adc);
 	}
 	s->open_mode &= ~(FMODE_READ | FMODE_WRITE);
-	up(&s->open_sem);
 	wake_up(&s->open_wait);
+	up(&s->open_sem);
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
@@ -1506,6 +1561,7 @@
 static int solo1_open(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
+	DECLARE_WAITQUEUE(wait, current);
 	struct solo1_state *s = devs;
 
 	while (s && ((s->dev_audio ^ minor) & ~0xf))
@@ -1521,8 +1577,12 @@
 			up(&s->open_sem);
 			return -EBUSY;
 		}
+		add_wait_queue(&s->open_wait, &wait);
+		__set_current_state(TASK_INTERRUPTIBLE);
 		up(&s->open_sem);
-		interruptible_sleep_on(&s->open_wait);
+		schedule();
+		remove_wait_queue(&s->open_wait, &wait);
+		set_current_state(TASK_RUNNING);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 		down(&s->open_sem);
@@ -1537,10 +1597,6 @@
 	s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
 	up(&s->open_sem);
 	MOD_INC_USE_COUNT;
-	if (prog_dmabuf_dac(s) || prog_dmabuf_adc(s)) {
-		solo1_release(inode, file);
-		return -ENOMEM;
-	}
 	prog_codec(s);
 	return 0;
 }
@@ -1654,6 +1710,8 @@
 		cnt = MIDIINBUF - ptr;
 		if (s->midi.icnt < cnt)
 			cnt = s->midi.icnt;
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
@@ -1663,7 +1721,6 @@
 					ret = -EAGAIN;
 				break;
 			}
-			__set_current_state(TASK_INTERRUPTIBLE);
 			schedule();
 			if (signal_pending(current)) {
 				if (!ret)
@@ -1716,8 +1773,10 @@
 		cnt = MIDIOUTBUF - ptr;
 		if (s->midi.ocnt + cnt > MIDIOUTBUF)
 			cnt = MIDIOUTBUF - s->midi.ocnt;
-		if (cnt <= 0)
+		if (cnt <= 0) {
+			__set_current_state(TASK_INTERRUPTIBLE);
 			solo1_handle_midi(s);
+		}
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
@@ -1727,7 +1786,6 @@
 					ret = -EAGAIN;
 				break;
 			}
-			__set_current_state(TASK_INTERRUPTIBLE);
 			schedule();
 			if (signal_pending(current)) {
 				if (!ret)
@@ -1785,6 +1843,7 @@
 static int solo1_midi_open(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
+	DECLARE_WAITQUEUE(wait, current);
 	struct solo1_state *s = devs;
 	unsigned long flags;
 
@@ -1801,8 +1860,12 @@
 			up(&s->open_sem);
 			return -EBUSY;
 		}
+		add_wait_queue(&s->open_wait, &wait);
+		__set_current_state(TASK_INTERRUPTIBLE);
 		up(&s->open_sem);
-		interruptible_sleep_on(&s->open_wait);
+		schedule();
+		remove_wait_queue(&s->open_wait, &wait);
+		set_current_state(TASK_RUNNING);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 		down(&s->open_sem);
@@ -1846,9 +1909,9 @@
 	VALIDATE_STATE(s);
 
 	if (file->f_mode & FMODE_WRITE) {
-		current->state = TASK_INTERRUPTIBLE;
 		add_wait_queue(&s->midi.owait, &wait);
 		for (;;) {
+			__set_current_state(TASK_INTERRUPTIBLE);
 			spin_lock_irqsave(&s->lock, flags);
 			count = s->midi.ocnt;
 			spin_unlock_irqrestore(&s->lock, flags);
@@ -1858,7 +1921,7 @@
 				break;
 			if (file->f_flags & O_NONBLOCK) {
 				remove_wait_queue(&s->midi.owait, &wait);
-				current->state = TASK_RUNNING;
+				set_current_state(TASK_RUNNING);
 				return -EBUSY;
 			}
 			tmo = (count * HZ) / 3100;
@@ -1866,7 +1929,7 @@
 				printk(KERN_DEBUG "solo1: midi timed out??\n");
 		}
 		remove_wait_queue(&s->midi.owait, &wait);
-		current->state = TASK_RUNNING;
+		set_current_state(TASK_RUNNING);
 	}
 	down(&s->open_sem);
 	s->open_mode &= (~(file->f_mode << FMODE_MIDI_SHIFT)) & (FMODE_MIDI_READ|FMODE_MIDI_WRITE);
@@ -1876,8 +1939,8 @@
 		del_timer(&s->midi.timer);		
 	}
 	spin_unlock_irqrestore(&s->lock, flags);
-	up(&s->open_sem);
 	wake_up(&s->open_wait);
+	up(&s->open_sem);
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
@@ -2002,6 +2065,7 @@
 static int solo1_dmfm_open(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
+	DECLARE_WAITQUEUE(wait, current);
 	struct solo1_state *s = devs;
 
 	while (s && s->dev_dmfm != minor)
@@ -2017,8 +2081,12 @@
 			up(&s->open_sem);
 			return -EBUSY;
 		}
+		add_wait_queue(&s->open_wait, &wait);
+		__set_current_state(TASK_INTERRUPTIBLE);
 		up(&s->open_sem);
-		interruptible_sleep_on(&s->open_wait);
+		schedule();
+		remove_wait_queue(&s->open_wait, &wait);
+		set_current_state(TASK_RUNNING);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 		down(&s->open_sem);
@@ -2057,8 +2125,8 @@
 		outb(0, s->sbbase+3);
 	}
 	release_region(s->sbbase, FMSYNTH_EXTENT);
-	up(&s->open_sem);
 	wake_up(&s->open_wait);
+	up(&s->open_sem);
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
@@ -2113,7 +2181,7 @@
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "solo1: version v0.9 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "solo1: version v0.11 time " __TIME__ " " __DATE__ "\n");
 	while (index < NR_DEVICE && 
 	       (pcidev = pci_find_device(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_SOLO1, pcidev))) {
 		if (pcidev->base_address[0] == 0 ||
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/sound/maestro.c linux.15p9/drivers/sound/maestro.c
--- linux.vanilla/drivers/sound/maestro.c	Tue Jan  4 21:18:59 2000
+++ linux.15p9/drivers/sound/maestro.c	Wed Feb 16 18:24:15 2000
@@ -105,8 +105,24 @@
  *	being used now is quite dirty and assumes we're on a uni-processor
  *	machine.  Much of it will need to be cleaned up for SMP ACPI or 
  *	similar.
+ *
+ *	We also pay attention to PCI power management now.  The driver
+ *	will power down units of the chip that it knows aren't needed.
+ *	The WaveProcessor and company are only powered on when people
+ *	have /dev/dsp*s open.  On removal the driver will
+ *	power down the maestro entirely.  There could still be
+ *	trouble with BIOSen that magically change power states 
+ *	themselves, but we'll see.  
  *	
  * History
+ *  v0.14 - Jan 28 2000 - Zach Brown <zab@redhat.com>
+ *	add PCI power management through ACPI regs.
+ *	we now shut down on machine reboot/halt
+ *	leave scary PCI config items alone (isa stuff, mostly)
+ *	enable 1921s, it seems only mine was broke.
+ *	fix swapped left/right pcm dac.  har har.
+ *	up bob freq, increase buffers, fix pointers at underflow
+ *	silly compilation problems
  *  v0.13 - Nov 18 1999 - Zach Brown <zab@redhat.com>
  *	fix nec Versas?  man would that be cool.
  *  v0.12 - Nov 12 1999 - Zach Brown <zab@redhat.com>
@@ -162,7 +178,22 @@
  *	bob freq code, region sanity, jitter sync fix; all from Eric 
  *
  * TODO
- *	some people get indir reg timeouts?
+ * 	add ref to http://www.booyaka.com/~g00z/alcam/alcam_audio.html
+ *	ac97 power management?
+ *	request_region in _config??
+ *	v0.10 recovers from underrun more quickly than v0.1[34]?
+ *	use new resources and enable_Device in 2.3
+ *	current->state = task_int in for(;;)
+ *	mention 1948 as maestro agogo
+ *	check smp
+ * 	look at spdif, game port
+ *	static linking in 2.3?
+ *	some folks get unexplained constant whine on modprobe, 
+ *		apparently irrespective of mixer settings..
+ *	power apm events (and power down when inactive)
+ *		this should stop indir timeouts on boot
+ *		and randomly falling off to static after while
+ *	make sure real 5.0 works, flash 4 something also
  *	fix bob frequency
  *	endianness
  *	do smart things with ac97 2.0 bits.
@@ -179,27 +210,13 @@
 #include <linux/version.h>
 #include <linux/module.h>
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
-
- #ifdef MODULE
-  #ifdef MODVERSIONS
-   #include <linux/modversions.h>
-  #endif
- #endif
- #define DECLARE_WAITQUEUE(QUEUE,INIT) struct wait_queue QUEUE = {INIT, NULL}
- #define wait_queue_head_t struct wait_queue *
- #define SILLY_PCI_BASE_ADDRESS(PCIDEV) (PCIDEV->base_address[0] & PCI_BASE_ADDRESS_IO_MASK)
- #define SILLY_INIT_SEM(SEM) SEM=MUTEX;
- #define init_waitqueue_head init_waitqueue
- #define SILLY_MAKE_INIT(FUNC) __initfunc(FUNC)
-
-#else
-
- #define SILLY_PCI_BASE_ADDRESS(PCIDEV) (PCIDEV->resource[0].start)
- #define SILLY_INIT_SEM(SEM) init_MUTEX(&SEM)
- #define SILLY_MAKE_INIT(FUNC) __init FUNC
-
-#endif
+#define DECLARE_WAITQUEUE(QUEUE,INIT) struct wait_queue QUEUE = {INIT, NULL}
+#define wait_queue_head_t struct wait_queue *
+#define SILLY_PCI_BASE_ADDRESS(PCIDEV) (PCIDEV->base_address[0] & PCI_BASE_ADDRESS_IO_MASK)
+#define SILLY_INIT_SEM(SEM) SEM=MUTEX;
+#define init_waitqueue_head init_waitqueue
+#define SILLY_MAKE_INIT(FUNC) __initfunc(FUNC)
+#define SILLY_OFFSET(VMA) ((VMA)->vm_offset)
 
 #include <linux/string.h>
 #include <linux/ctype.h>
@@ -214,6 +231,7 @@
 #include <asm/dma.h>
 #include <linux/init.h>
 #include <linux/poll.h>
+#include <linux/reboot.h>
 #include <asm/uaccess.h>
 #include <asm/hardirq.h>
 #include <asm/spinlock.h>
@@ -237,14 +255,18 @@
 
 #ifdef M_DEBUG
 static int debug=0;
-static int dsps_order=0;
 #define M_printk(args...) {if (debug) printk(args);}
 #else
 #define M_printk(x)
 #endif
 
+/* we try to setup 2^(dsps_order) /dev/dsp devices */
+static int dsps_order=0;
+/* wether or not we mess around with power management */
+static int use_pm=2; /* set to 1 for force */
+
 /* --------------------------------------------------------------------- */
-#define DRIVER_VERSION "0.13"
+#define DRIVER_VERSION "0.14"
 
 #ifndef PCI_VENDOR_ESS
 #define PCI_VENDOR_ESS			0x125D
@@ -288,6 +310,46 @@
 #define NR_APUS		64
 #define NR_APU_REGS	16
 
+/* acpi states */
+enum {
+	ACPI_D0=0,
+	ACPI_D1,
+	ACPI_D2,
+	ACPI_D3
+};
+
+/* bits in the acpi masks */
+#define ACPI_12MHZ	( 1 << 15)
+#define ACPI_24MHZ	( 1 << 14)
+#define ACPI_978	( 1 << 13)
+#define ACPI_SPDIF	( 1 << 12)
+#define ACPI_GLUE	( 1 << 11)
+#define ACPI__10	( 1 << 10) /* reserved */
+#define ACPI_PCIINT	( 1 << 9)
+#define ACPI_HV		( 1 << 8) /* hardware volume */
+#define ACPI_GPIO	( 1 << 7)
+#define ACPI_ASSP	( 1 << 6)
+#define ACPI_SB		( 1 << 5) /* sb emul */
+#define ACPI_FM		( 1 << 4) /* fm emul */
+#define ACPI_RB		( 1 << 3) /* ringbus / aclink */
+#define ACPI_MIDI	( 1 << 2) 
+#define ACPI_GP		( 1 << 1) /* game port */
+#define ACPI_WP		( 1 << 0) /* wave processor */
+
+#define ACPI_ALL	(0xffff)
+#define ACPI_SLEEP	(~(ACPI_SPDIF|ACPI_ASSP|ACPI_SB|ACPI_FM| \
+			ACPI_MIDI|ACPI_GP|ACPI_WP))
+#define ACPI_NONE	(ACPI__10)
+
+/* these masks indicate which units we care about at
+	which states */
+u16 acpi_state_mask[] = {
+	[ACPI_D0] = ACPI_ALL,
+	[ACPI_D1] = ACPI_SLEEP,
+	[ACPI_D2] = ACPI_SLEEP,
+	[ACPI_D3] = ACPI_NONE
+};
+
 static const unsigned sample_size[] = { 1, 2, 2, 4 };
 static const unsigned sample_shift[] = { 0, 1, 1, 2 };
 
@@ -309,6 +371,10 @@
 	[TYPE_MAESTRO2E] = (50000000L / 1024L)
 };
 
+static int maestro_notifier(struct notifier_block *nb, unsigned long event, void *buf);
+
+struct notifier_block maestro_nb = {maestro_notifier, NULL, 0};
+
 /* --------------------------------------------------------------------- */
 
 struct ess_state {
@@ -389,6 +455,8 @@
 		unsigned int mixer_state[SOUND_MIXER_NRDEVICES];
 	} mix;
 	
+	int power_regs;
+		
 	struct ess_state channels[MAX_DSPS];
 	u16 maestro_map[NR_IDRS];	/* Register map */
 #ifdef CONFIG_APM
@@ -405,7 +473,7 @@
 	int dmaorder;
 
 	/* hardware resources */
-	struct pci_dev pcidev; /* uck.. */
+	struct pci_dev *pcidev;
 	u32 iobase;
 	u32 irq;
 
@@ -777,6 +845,10 @@
 		maestro_ac97_set(iobase,0x2c,0x0000);
 		maestro_ac97_set(iobase,0x2c,0xffff);
 		break;
+#if 0	/* i thought the problems I was seeing were with
+	the 1921, but apparently they were with the pci board
+	it was on, so this code is commented out.
+	 lets see if this holds true. */
 	case 0x83847609:	/* ESS 1921 */
 		/* writing to 0xe (mic) or 0x1a (recmask) seems
 			to hang this codec */
@@ -792,6 +864,7 @@
 		udelay(20);
 #endif
 		break;
+#endif
 	default: break;
 	}
 
@@ -1314,11 +1387,12 @@
 			
 /* XXX think about endianess when writing these registers */
 		M_printk("maestro: ess_play_setup: APU[%d] pa = 0x%x\n", ess->apu[channel], pa);
-		/* Load the buffer into the wave engine */
+		/* start of sample */
 		apu_set_register(ess, channel, 4, ((pa>>16)&0xFF)<<8);
 		apu_set_register(ess, channel, 5, pa&0xFFFF);
+		/* sample end */
 		apu_set_register(ess, channel, 6, (pa+size)&0xFFFF);
-		/* setting loop == sample len */
+		/* setting loop len == sample len */
 		apu_set_register(ess, channel, 7, size);
 		
 		/* clear effects/env.. */
@@ -1338,7 +1412,7 @@
 
 		if(mode&ESS_FMT_STEREO) {
 			/* set panning: left or right */
-			apu_set_register(ess, channel, 10, 0x8F00 | (channel ? 0x10 : 0));
+			apu_set_register(ess, channel, 10, 0x8F00 | (channel ? 0 : 0x10));
 			ess->apu_mode[channel] += 0x10;
 		} else
 			apu_set_register(ess, channel, 10, 0x8F08);
@@ -1549,7 +1623,7 @@
 	int divide;
 	
 	/* XXX make freq selector much smarter, see calc_bob_rate */
-	int freq = 150;		/* requested frequency - calculate what we want here. */
+	int freq = 200; 
 	
 	/* compute ideal interrupt frequency for buffer size & play rate */
 	/* first, find best prescaler value to match freq */
@@ -1657,6 +1731,7 @@
 
 	db->hwptr = db->swptr = db->total_bytes = db->count = db->error = db->endcleared = 0;
 
+	/* this algorithm is a little nuts.. where did /1000 come from? */
 	bytepersec = rate << sample_shift[fmt];
 	bufs = PAGE_SIZE << db->buforder;
 	if (db->ossfragshift) {
@@ -1685,13 +1760,11 @@
 	memset(db->rawbuf, (fmt & ESS_FMT_16BIT) ? 0 : 0x80, db->dmasize);
 
 	spin_lock_irqsave(&s->lock, flags);
-	if (rec) {
-		ess_rec_setup(s, fmt, s->rateadc, 
-			db->rawbuf, db->numfrag << db->fragshift);
-	} else {
-		ess_play_setup(s, fmt, s->ratedac, 
-			db->rawbuf, db->numfrag << db->fragshift);
-	}
+	if (rec) 
+		ess_rec_setup(s, fmt, s->rateadc, db->rawbuf, db->dmasize);
+	else 
+		ess_play_setup(s, fmt, s->ratedac, db->rawbuf, db->dmasize);
+
 	spin_unlock_irqrestore(&s->lock, flags);
 	db->ready = 1;
 
@@ -1761,7 +1834,7 @@
 		hwptr = get_dmaa(s) % s->dma_dac.dmasize; 
 		/* the apu only reports the length it has seen, not the
 			length of the memory that has been used (the WP
-			knows that */
+			knows that) */
 		if ( ((s->fmt >> ESS_DAC_SHIFT) & ESS_FMT_MASK) == (ESS_FMT_STEREO|ESS_FMT_16BIT))
 			hwptr<<=1;
 
@@ -1778,14 +1851,15 @@
 			s->dma_dac.count -= diff;
 /*			M_printk("maestro: ess_update_ptr: diff: %d, count: %d\n", diff, s->dma_dac.count); */
 			if (s->dma_dac.count <= 0) {
+				M_printk("underflow! diff: %d count: %d hw: %d sw: %d\n", diff, s->dma_dac.count, 
+					hwptr, s->dma_dac.swptr);
 				/* FILL ME 
 				wrindir(s, SV_CIENABLE, s->enable); */
 				/* XXX how on earth can calling this with the lock held work.. */
 				stop_dac(s);
 				/* brute force everyone back in sync, sigh */
 				s->dma_dac.count = 0; 
-				s->dma_dac.swptr = 0; 
-				s->dma_dac.hwptr = 0; 
+				s->dma_dac.swptr = hwptr; 
 				s->dma_dac.error++;
 			} else if (s->dma_dac.count <= (signed)s->dma_dac.fragsize && !s->dma_dac.endcleared) {
 				clear_advance(s);
@@ -1793,6 +1867,8 @@
 			}
 			if (s->dma_dac.count + (signed)s->dma_dac.fragsize <= (signed)s->dma_dac.dmasize) {
 				wake_up(&s->dma_dac.wait);
+/*				printk("waking up DAC count: %d sw: %d hw: %d\n",s->dma_dac.count, s->dma_dac.swptr, 
+					hwptr);*/
 			}
 		}
 	}
@@ -2302,6 +2378,7 @@
 			if (!ret) ret = -EFAULT;
 			goto return_free;
 		}
+/*		printk("wrote %d bytes at sw: %d cnt: %d while hw: %d\n",cnt, swptr, s->dma_dac.count, s->dma_dac.hwptr);*/
 
 		swptr = (swptr + cnt) % s->dma_dac.dmasize;
 
@@ -2372,7 +2449,7 @@
 	} else  
 #endif
 		return -EINVAL;
-	if (vma->vm_offset != 0)
+	if (SILLY_OFFSET(vma) != 0)
 		return -EINVAL;
 	size = vma->vm_end - vma->vm_start;
 	if (size > (PAGE_SIZE << db->buforder))
@@ -2638,6 +2715,7 @@
 
         case SNDCTL_DSP_SETFRAGMENT:
                 get_user_ret(val, (int *)arg, -EFAULT);
+		M_printk("maestro: SETFRAGMENT: %0x\n",val);
 		if (file->f_mode & FMODE_READ) {
 			s->dma_adc.ossfragshift = val & 0xffff;
 			s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff;
@@ -2703,6 +2781,34 @@
 	wave_set_register(s, 0x01FF , packed_phys);
 }
 
+/* this guy makes sure we're in the right power
+	state for what we want to be doing */
+void maestro_power(struct ess_card *card, int tostate)
+{
+	u16 active_mask = acpi_state_mask[tostate];
+	u8 state;
+
+	if(!use_pm) return;
+
+	pci_read_config_byte(card->pcidev, card->power_regs+0x4, &state);
+	state&=3;
+
+	/* make sure we're in the right state */
+	if(state != tostate) {
+		M_printk(KERN_WARNING "maestro: dev %02x:%02x.%x switching from D%d to D%d\n",
+			card->pcidev->bus->number, 
+			PCI_SLOT(card->pcidev->devfn),
+			PCI_FUNC(card->pcidev->devfn),
+			state,tostate);
+		pci_write_config_byte(card->pcidev, card->power_regs+0x4, tostate);
+	}
+
+	/* and make sure the units we care about are on 
+		XXX we might want to do this before state flipping? */
+	pci_write_config_word(card->pcidev, 0x54, ~ active_mask);
+	pci_write_config_word(card->pcidev, 0x56, ~ active_mask);
+}
+
 /* we allocate a large power of two for all our memory.
 	this is cut up into (not to scale :):
 	|silly fifo word	| 512byte mixbuf per adc	| dac/adc * channels |
@@ -2715,7 +2821,7 @@
 	unsigned long mapend,map;
 
 	/* alloc as big a chunk as we can */
-	for (order = (dsps_order + (15-PAGE_SHIFT) + 1); order >= (dsps_order + 2 + 1); order--)
+	for (order = (dsps_order + (16-PAGE_SHIFT) + 1); order >= (dsps_order + 2 + 1); order--)
 		if((rawbuf = (void *)__get_free_pages(GFP_KERNEL|GFP_DMA, order)))
 			break;
 
@@ -2734,12 +2840,6 @@
 	s->card->dmapages = rawbuf;
 	s->card->dmaorder = order;
 
-	/* play bufs are in the same first region as record bufs */
-	set_base_registers(s,rawbuf);
-
-	M_printk("maestro: writing %lx (%lx) to the wp\n",virt_to_bus(rawbuf),
-		((virt_to_bus(rawbuf))&0xFFE00000)>>12);
-
 	for(i=0;i<NR_DSPS;i++) {
 		struct ess_state *ess = &s->card->channels[i];
 
@@ -2758,7 +2858,7 @@
 			happily scribble away.. */ 
 		ess->mixbuf = rawbuf + (512 * (i+1));
 
-		M_printk("maestro: setup apu %d: %p %p %p\n",i,ess->dma_dac.rawbuf,
+		M_printk("maestro: setup apu %d: dac: %p adc: %p mix: %p\n",i,ess->dma_dac.rawbuf,
 			ess->dma_adc.rawbuf, ess->mixbuf);
 
 	}
@@ -2844,6 +2944,20 @@
 		return -ENOMEM;
 	}
 
+	/* we're covered by the open_sem */
+	if( ! s->card->dsps_open )  {
+		maestro_power(s->card,ACPI_D0);
+		start_bob(s);
+	}
+	s->card->dsps_open++;
+	M_printk("maestro: open, %d bobs now\n",s->card->dsps_open);
+
+	/* ok, lets write WC base regs now that we've 
+		powered up the chip */
+	M_printk("maestro: writing 0x%lx (bus 0x%lx) to the wp\n",virt_to_bus(s->card->dmapages),
+		((virt_to_bus(s->card->dmapages))&0xFFE00000)>>12);
+	set_base_registers(s,s->card->dmapages);
+
 	if (file->f_mode & FMODE_READ) {
 /*
 		fmtm &= ~((ESS_FMT_STEREO | ESS_FMT_16BIT) << ESS_ADC_SHIFT);
@@ -2867,13 +2981,6 @@
 	set_fmt(s, fmtm, fmts);
 	s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
 
-	/* we're covered by the open_sem */
-	if( ! s->card->dsps_open )  {
-		start_bob(s);
-	}
-	s->card->dsps_open++;
-	M_printk("maestro: open, %d bobs now\n",s->card->dsps_open);
-
 	up(&s->open_sem);
 	MOD_INC_USE_COUNT;
 	return 0;
@@ -2899,8 +3006,10 @@
 	/* we're covered by the open_sem */
 	M_printk("maestro: %d dsps now alive\n",s->card->dsps_open-1);
 	if( --s->card->dsps_open <= 0) {
+		s->card->dsps_open = 0;
 		stop_bob(s);
 		free_buffers(s);
+		maestro_power(s->card,ACPI_D2);
 	}
 	up(&s->open_sem);
 	wake_up(&s->open_wait);
@@ -2908,64 +3017,31 @@
 	return 0;
 }
 
-static struct file_operations ess_audio_fops = {
-	&ess_llseek,
-	&ess_read,
-	&ess_write,
-	NULL,  /* readdir */
-	&ess_poll,
-	&ess_ioctl,
-	&ess_mmap,
-	&ess_open,
-	NULL,	/* flush */
-	&ess_release,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
-	NULL,  /* lock */
-};
-
 static int
 maestro_config(struct ess_card *card) 
 {
-	struct pci_dev *pcidev = &card->pcidev;
+	struct pci_dev *pcidev = card->pcidev;
 	struct ess_state *ess = &card->channels[0];
 	int apu,iobase  = card->iobase;
 	u16 w;
 	u32 n;
 
-	/*
-	 *	Disable ACPI
-	 */
-	 
-	pci_write_config_dword(pcidev, 0x54, 0x00000000);
-	pci_write_config_dword(pcidev, 0x56, 0x00000000);
+	/* We used to muck around with pci config space that
+	we had no business messing with.  We don't know enough
+	about the machine to know which DMA mode is appropriate, 
+	etc.  We were guessing wrong on some machines and making
+	them unhappy.  We now trust in the BIOS to do things right,
+	which almost certainly means a new host of problems will
+	arise with broken BIOS implementations.  screw 'em. 
+	We're already intolerant of machines that don't assign
+	IRQs. */
 	
-	/*
-	 *	Use TDMA for now. TDMA works on all boards, so while its
-	 *	not the most efficient its the simplest.
-	 */ 
+	/* do config work at full power */
+	maestro_power(card,ACPI_D0);
 	 
 	pci_read_config_word(pcidev, 0x50, &w);
 
-	/* Clear DMA bits */
-	w&=~(1<<10|1<<9|1<<8);
-
-	/* TDMA on */
-	w|= (1<<8);
-
-	/*
-	 *	Some of these are undocumented bits
-	 */
-	 
-	w&=~(1<<13)|(1<<14);		/* PIC Snoop mode bits */
-	w&=~(1<<11);			/* Safeguard off */
-	w|= (1<<7);			/* Posted write */
-	w|= (1<<6);			/* ISA timing on */
-	/* XXX huh?  claims to be reserved.. */
-	w&=~(1<<5);			/* Don't swap left/right */
-	w&=~(1<<1);			/* Subtractive decode off */
+	w&=~(1<<5);			/* Don't swap left/right (undoc)*/
 	
 	pci_write_config_word(pcidev, 0x50, w);
 	
@@ -2978,19 +3054,9 @@
 	w&=~(1<<6);		/* Debounce off */
 	w&=~(1<<5);		/* GPIO 4:5 */
 	w|= (1<<4);             /* Disconnect from the CHI.  Enabling this made a dell 7500 work. */
-	w&=~(1<<3);		/* IDMA off (undocumented) */
 	w&=~(1<<2);		/* MIDI fix off (undoc) */
 	w&=~(1<<1);		/* reserved, always write 0 */
-	w&=~(1<<0);		/* IRQ to ISA off (undoc) */
 	pci_write_config_word(pcidev, 0x52, w);
-
-	/*
-	 *	DDMA off
-	 */
-
-	pci_read_config_word(pcidev, 0x60, &w);
-	w&=~(1<<0);
-	pci_write_config_word(pcidev, 0x60, w);
 	
 	/*
 	 *	Legacy mode
@@ -3003,8 +3069,6 @@
 	 
 	pci_write_config_word(pcidev, 0x40, w);
 
-	/* stake our claim on the iospace */
-	request_region(iobase, 256, card_names[card->card_type]);
 	
 	sound_reset(iobase);
 
@@ -3172,6 +3236,57 @@
 	
 }
 
+/* this guy tries to find the pci power management
+ * register bank.  this should really be in core
+ * code somewhere.  1 on success. */
+int
+parse_power(struct ess_card *card, struct pci_dev *pcidev)
+{
+	u32 n;
+	u16 w;
+	u8 next;
+	int max = 64;  /* an a 8bit guy pointing to 32bit guys
+				can only express so much. */
+
+	card->power_regs = 0;
+
+	/* check to see if we have a capabilities list in
+		the config register */
+	pci_read_config_word(pcidev, PCI_STATUS, &w);
+	if(! w & PCI_STATUS_CAP_LIST) return 0;
+
+	/* walk the list, starting at the head. */
+	pci_read_config_byte(pcidev,PCI_CAPABILITY_LIST,&next);
+
+	while(next && max--) {
+		pci_read_config_dword(pcidev, next & ~3, &n);
+		if((n & 0xff) == PCI_CAP_ID_PM) {
+			card->power_regs = next;
+			break;
+		}
+		next = ((n>>8) & 0xff);
+	}
+
+	return card->power_regs ? 1 : 0;
+}
+
+static struct file_operations ess_audio_fops = {
+	&ess_llseek,
+	&ess_read,
+	&ess_write,
+	NULL,  /* readdir */
+	&ess_poll,
+	&ess_ioctl,
+	&ess_mmap,
+	&ess_open,
+	NULL,	/* flush */
+	&ess_release,
+	NULL,  /* fsync */
+	NULL,  /* fasync */
+	NULL,  /* check_media_change */
+	NULL,  /* revalidate */
+	NULL,  /* lock */
+};
 
 static int 
 maestro_install(struct pci_dev *pcidev, int card_type)
@@ -3194,6 +3309,8 @@
 		printk(KERN_WARNING "maestro: can't allocate 256 bytes I/O at 0x%4.4x\n", iobase);
 		return 0;
 	}
+	/* stake our claim on the iospace */
+	request_region(iobase, 256, card_names[card_type]);
 
 	/* this was tripping up some machines */
 	if(pcidev->irq == 0) 
@@ -3212,13 +3329,16 @@
 	}
 	
 	memset(card, 0, sizeof(*card));
-	memcpy(&card->pcidev,pcidev,sizeof(card->pcidev));
+	card->pcidev = pcidev;
 
 #ifdef CONFIG_APM
 	if (apm_register_callback(maestro_apm_callback)) {
 		printk(KERN_WARNING "maestro: apm suspend might not work.\n");
 	}
 #endif
+	if (register_reboot_notifier(&maestro_nb)) {
+		printk(KERN_WARNING "maestro: reboot notifier registration failed; may not reboot properly.\n");
+	}
 
 	card->iobase = iobase;
 	card->card_type = card_type;
@@ -3277,6 +3397,25 @@
 	pci_read_config_dword(pcidev, PCI_SUBSYSTEM_VENDOR_ID, &n);
 	printk(KERN_INFO "maestro:  subvendor id: 0x%08x\n",n); 
 
+	/* turn off power management if it isn't explicitly
+		asked for by the user, we aren't on a 2E, or
+		we aren't on our very small whitelist :) */
+#define SUBSYSTEM_VENDOR(x) (x&0xffff)
+	if(	(use_pm != 1) && 
+		((card_type != TYPE_MAESTRO2E)	|| (SUBSYSTEM_VENDOR(n) != 0x1028)))
+			use_pm = 0;
+
+	if(!use_pm) 
+		printk(KERN_INFO "maestro: not attempting power management.\n");
+	else {
+		if(!parse_power(card,pcidev)) 
+			printk(KERN_INFO "maestro: no PCI power managment interface found.\n");
+		else {
+			pci_read_config_dword(pcidev, card->power_regs, &n);
+			printk(KERN_INFO "maestro: PCI power managment capability: 0x%x\n",n>>16);
+		}	
+	}
+
 	maestro_config(card);
 
 	if(maestro_ac97_get(iobase, 0x00)==0x0080) {
@@ -3307,6 +3446,8 @@
 		kfree(card);
 		return 0;
 	}
+	/* now go to sleep 'till something interesting happens */
+	maestro_power(card,ACPI_D2);
 
 	printk(KERN_INFO "maestro: %d channels configured.\n", num);
 	return 1; 
@@ -3373,44 +3514,66 @@
 	return 0;
 }
 
-/* --------------------------------------------------------------------- */
-
-#ifdef MODULE
-MODULE_AUTHOR("Zach Brown <zab@redhat.com>, Alan Cox <alan@redhat.com>");
-MODULE_DESCRIPTION("ESS Maestro Driver");
-#ifdef M_DEBUG
-MODULE_PARM(debug,"i");
-#endif
-MODULE_PARM(dsps_order,"i");
-
-void cleanup_module(void)
+void nuke_maestros(void)
 {
-	struct ess_card *s;
+	struct ess_card *card;
 
+	/* we do these unconditionally, which is probably wrong */
 #ifdef CONFIG_APM
 	apm_unregister_callback(maestro_apm_callback);
 #endif
-	while ((s = devs)) {
+	unregister_reboot_notifier(&maestro_nb);
+
+	while ((card = devs)) {
 		int i;
 		devs = devs->next;
 	
 		/* XXX maybe should force stop bob, but should be all 
 			stopped by _release by now */
-		free_irq(s->irq, s);
-		unregister_sound_mixer(s->dev_mixer);
+		free_irq(card->irq, card);
+		unregister_sound_mixer(card->dev_mixer);
 		for(i=0;i<NR_DSPS;i++)
 		{
-			struct ess_state *ess = &s->channels[i];
+			struct ess_state *ess = &card->channels[i];
 			if(ess->dev_audio != -1)
 				unregister_sound_dsp(ess->dev_audio);
 		}
-		release_region(s->iobase, 256);
-		kfree(s);
+		/* Goodbye, Mr. Bond. */
+		maestro_power(card,ACPI_D3);
+		release_region(card->iobase, 256);
+		kfree(card);
 	}
+	devs = NULL;
+}
+
+static int maestro_notifier(struct notifier_block *nb, unsigned long event, void *buf)
+{
+	/* this notifier is called when the kernel is really shut down. */
+	M_printk("maestro: shutting down\n");
+	nuke_maestros();
+	return NOTIFY_OK;
+}
+
+/* --------------------------------------------------------------------- */
+
+#ifdef MODULE
+MODULE_AUTHOR("Zach Brown <zab@redhat.com>, Alan Cox <alan@redhat.com>");
+MODULE_DESCRIPTION("ESS Maestro Driver");
+#ifdef M_DEBUG
+MODULE_PARM(debug,"i");
+#endif
+MODULE_PARM(dsps_order,"i");
+MODULE_PARM(use_pm,"i");
+
+void cleanup_module(void) {
 	M_printk("maestro: unloading\n");
+	nuke_maestros();
 }
 
 #endif /* MODULE */
+
+/* --------------------------------------------------------------------- */
+
 #ifdef CONFIG_APM
 
 void
@@ -3442,6 +3605,10 @@
 
 		M_printk("maestro: apm in dev %p\n",card);
 
+		/* we have to read from the apu regs, need
+			to power it up */
+		maestro_power(card,ACPI_D0);
+
 		for(i=0;i<NR_DSPS;i++) {
 			struct ess_state *s = &card->channels[i];
 
@@ -3464,8 +3631,9 @@
 
 	restore_flags(flags);
 
-	/* we'll let the bios do the rest of the power down.. */
-
+	/* we trust in the bios to power down on suspend.
+	XXX I'm also not sure that in_suspend will protect
+	against all reg accesses from here on out. */
 	return 0;
 }
 static int 
@@ -3474,7 +3642,7 @@
 	struct ess_card *card;
 	unsigned long flags;
 
-	save_flags(flags);
+	save_flags(flags); /* paranoia */
 	cli();
 	in_suspend=0;
 	M_printk("maestro: resuming\n");
@@ -3485,6 +3653,7 @@
 
 		M_printk("maestro: apm in dev %p\n",card);
 
+		/* restore all our config */
 		maestro_config(card);
 		/* need to restore the base pointers.. */ 
 		if(card->dmapages) 
@@ -3515,6 +3684,16 @@
 
 		M_printk("maestro: apm in dev %p\n",card);
 
+		if( card->dsps_open <= 0) {
+			/* this card's idle */
+			maestro_power(card,ACPI_D2);
+			continue;
+		}
+
+		/* ok, we're actually playing things on
+			this card */
+		maestro_power(card,ACPI_D0);
+		start_bob(&card->channels[0]);
 		for(i=0;i<NR_DSPS;i++) {
 			struct ess_state *s = &card->channels[i];
 
@@ -3523,12 +3702,13 @@
 			start_dac(s);	
 			start_adc(s);	
 		}
-		if( card->dsps_open > 0)
-			start_bob(&card->channels[0]);
 	}
 
 	restore_flags(flags);
 
+	/* all right, we think things are ready, 
+		wake up people who were using the device
+		when we suspended */
 	wake_up(&suspend_queue);
 
 	return 0;
@@ -3536,8 +3716,9 @@
 
 int 
 maestro_apm_callback(apm_event_t ae) {
+	struct ess_card *card;
 
-	M_printk("maestro: apm event received: 0x%x\n",ae);
+	M_printk("maestro: APM event received: 0x%x\n",ae);
 
 	switch(ae) {
 	case APM_SYS_SUSPEND: 
@@ -3548,6 +3729,15 @@
 	case APM_CRITICAL_RESUME: 
 	case APM_STANDBY_RESUME: 
 		maestro_resume();break;
+	case APM_POWER_STATUS_CHANGE:
+		for(card = devs ; card ; card = card->next) {
+			maestro_power(card, (card->dsps_open>0) ? ACPI_D0 : ACPI_D2);
+			/* XXX we're probably screwed here.  If the bios
+			drops the regs out from under us we'll have to actively
+			rebuild them.  This would look alot like the things
+			we do at _resume. */
+		}
+		break;
 	default: break;
 	}
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/sound/sonicvibes.c linux.15p9/drivers/sound/sonicvibes.c
--- linux.vanilla/drivers/sound/sonicvibes.c	Tue Jan  4 21:18:59 2000
+++ linux.15p9/drivers/sound/sonicvibes.c	Wed Jan 12 01:26:28 2000
@@ -3,7 +3,7 @@
 /*
  *      sonicvibes.c  --  S3 Sonic Vibes audio driver.
  *
- *      Copyright (C) 1998-1999  Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *      Copyright (C) 1998-2000  Thomas Sailer (sailer@ife.ee.ethz.ch)
  *
  *      This program is free software; you can redistribute it and/or modify
  *      it under the terms of the GNU General Public License as published by
@@ -35,50 +35,53 @@
  *  out first how to drive them...
  *
  *  Revision history
- *    06.05.98   0.1   Initial release
- *    10.05.98   0.2   Fixed many bugs, esp. ADC rate calculation
- *                     First stab at a simple midi interface (no bells&whistles)
- *    13.05.98   0.3   Fix stupid cut&paste error: set_adc_rate was called instead of
- *                     set_dac_rate in the FMODE_WRITE case in sv_open
- *                     Fix hwptr out of bounds (now mpg123 works)
- *    14.05.98   0.4   Don't allow excessive interrupt rates
- *    08.06.98   0.5   First release using Alan Cox' soundcore instead of miscdevice
- *    03.08.98   0.6   Do not include modversions.h
- *                     Now mixer behaviour can basically be selected between
- *                     "OSS documented" and "OSS actual" behaviour
- *    31.08.98   0.7   Fix realplayer problems - dac.count issues
- *    10.12.98   0.8   Fix drain_dac trying to wait on not yet initialized DMA
- *    16.12.98   0.9   Fix a few f_file & FMODE_ bugs
- *    06.01.99   0.10  remove the silly SA_INTERRUPT flag.
- *                     hopefully killed the egcs section type conflict
- *    12.03.99   0.11  cinfo.blocks should be reset after GETxPTR ioctl.
- *                     reported by Johan Maes <joma@telindus.be>
- *    22.03.99   0.12  return EAGAIN instead of EBUSY when O_NONBLOCK
- *                     read/write cannot be executed
- *    05.04.99   0.13  added code to sv_read and sv_write which should detect
- *                     lockups of the sound chip and revive it. This is basically
- *                     an ugly hack, but at least applications using this driver
- *                     won't hang forever. I don't know why these lockups happen,
- *                     it might well be the motherboard chipset (an early 486 PCI
- *                     board with ALI chipset), since every busmastering 100MB
- *                     ethernet card I've tried (Realtek 8139 and Macronix tulip clone)
- *                     exhibit similar behaviour (they work for a couple of packets
- *                     and then lock up and can be revived by ifconfig down/up).
- *    07.04.99   0.14  implemented the following ioctl's: SOUND_PCM_READ_RATE, 
- *                     SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS; 
- *                     Alpha fixes reported by Peter Jones <pjones@redhat.com>
- *                     Note: dmaio hack might still be wrong on archs other than i386
- *    15.06.99   0.15  Fix bad allocation bug.
- *                     Thanks to Deti Fliegl <fliegl@in.tum.de>
- *    28.06.99   0.16  Add pci_set_master
- *    03.08.99   0.17  adapt to Linus' new __setup/__initcall
- *                     added kernel command line options "sonicvibes=reverb" and "sonicvibesdmaio=dmaioaddr"
- *    12.08.99   0.18  module_init/__setup fixes
- *    24.08.99   0.19  get rid of the dmaio kludge, replace with allocate_resource
- *    31.08.99   0.20  add spin_lock_init
- *                     __initlocaldata to fix gcc 2.7.x problems
- *    03.09.99   0.21  change read semantics for MIDI to match
- *                     OSS more closely; remove possible wakeup race
+ *    06.05.1998   0.1   Initial release
+ *    10.05.1998   0.2   Fixed many bugs, esp. ADC rate calculation
+ *                       First stab at a simple midi interface (no bells&whistles)
+ *    13.05.1998   0.3   Fix stupid cut&paste error: set_adc_rate was called instead of
+ *                       set_dac_rate in the FMODE_WRITE case in sv_open
+ *                       Fix hwptr out of bounds (now mpg123 works)
+ *    14.05.1998   0.4   Don't allow excessive interrupt rates
+ *    08.06.1998   0.5   First release using Alan Cox' soundcore instead of miscdevice
+ *    03.08.1998   0.6   Do not include modversions.h
+ *                       Now mixer behaviour can basically be selected between
+ *                       "OSS documented" and "OSS actual" behaviour
+ *    31.08.1998   0.7   Fix realplayer problems - dac.count issues
+ *    10.12.1998   0.8   Fix drain_dac trying to wait on not yet initialized DMA
+ *    16.12.1998   0.9   Fix a few f_file & FMODE_ bugs
+ *    06.01.1999   0.10  remove the silly SA_INTERRUPT flag.
+ *                       hopefully killed the egcs section type conflict
+ *    12.03.1999   0.11  cinfo.blocks should be reset after GETxPTR ioctl.
+ *                       reported by Johan Maes <joma@telindus.be>
+ *    22.03.1999   0.12  return EAGAIN instead of EBUSY when O_NONBLOCK
+ *                       read/write cannot be executed
+ *    05.04.1999   0.13  added code to sv_read and sv_write which should detect
+ *                       lockups of the sound chip and revive it. This is basically
+ *                       an ugly hack, but at least applications using this driver
+ *                       won't hang forever. I don't know why these lockups happen,
+ *                       it might well be the motherboard chipset (an early 486 PCI
+ *                       board with ALI chipset), since every busmastering 100MB
+ *                       ethernet card I've tried (Realtek 8139 and Macronix tulip clone)
+ *                       exhibit similar behaviour (they work for a couple of packets
+ *                       and then lock up and can be revived by ifconfig down/up).
+ *    07.04.1999   0.14  implemented the following ioctl's: SOUND_PCM_READ_RATE, 
+ *                       SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS; 
+ *                       Alpha fixes reported by Peter Jones <pjones@redhat.com>
+ *                       Note: dmaio hack might still be wrong on archs other than i386
+ *    15.06.1999   0.15  Fix bad allocation bug.
+ *                       Thanks to Deti Fliegl <fliegl@in.tum.de>
+ *    28.06.1999   0.16  Add pci_set_master
+ *    03.08.1999   0.17  adapt to Linus' new __setup/__initcall
+ *                       added kernel command line options "sonicvibes=reverb" and "sonicvibesdmaio=dmaioaddr"
+ *    12.08.1999   0.18  module_init/__setup fixes
+ *    24.08.1999   0.19  get rid of the dmaio kludge, replace with allocate_resource
+ *    31.08.1999   0.20  add spin_lock_init
+ *                       __initlocaldata to fix gcc 2.7.x problems
+ *                       use new resource allocation to allocate DDMA IO space
+ *                       replaced current->state = x with set_current_state(x)
+ *    03.09.1999   0.21  change read semantics for MIDI to match
+ *                       OSS more closely; remove possible wakeup race
+ *    28.10.1999   0.22  More waitqueue races fixed
  *
  */
 
@@ -110,6 +113,26 @@
 
 /* --------------------------------------------------------------------- */
 
+#ifdef MODULE
+#define __exit
+#define module_exit(x) void cleanup_module(void) { x(); }
+#define module_init(x) int init_module(void) { return x(); }
+#else
+#define __exit __attribute__ ((unused, __section__ (".text.init")))
+#define module_exit(x) /* nothing */
+#define module_init(x) /* nothing */
+#endif
+
+#define DECLARE_WAIT_QUEUE_HEAD(w) struct wait_queue *w = NULL
+#define DECLARE_WAITQUEUE(w,c) struct wait_queue w = {(c), NULL}
+#define wait_queue_head_t struct wait_queue *
+#define init_waitqueue_head(w) *(w) = 0
+#define init_MUTEX(m) *(m) = MUTEX
+#define __set_current_state(x) do { current->state = (x); } while (0)
+#define set_current_state(x) __set_current_state(x)
+
+/* --------------------------------------------------------------------- */
+
 #ifndef PCI_VENDOR_ID_S3
 #define PCI_VENDOR_ID_S3             0x5333
 #endif
@@ -297,7 +320,7 @@
 	spinlock_t lock;
 	struct semaphore open_sem;
 	mode_t open_mode;
-	struct wait_queue *open_wait;
+	wait_queue_head_t open_wait;
 
 	struct dmabuf {
 		void *rawbuf;
@@ -308,7 +331,7 @@
 		unsigned total_bytes;
 		int count;
 		unsigned error; /* over/underrun */
-		struct wait_queue *wait;
+		wait_queue_head_t wait;
 		/* redundant, but makes calculations easier */
 		unsigned fragsize;
 		unsigned dmasize;
@@ -326,8 +349,8 @@
 	struct {
 		unsigned ird, iwr, icnt;
 		unsigned ord, owr, ocnt;
-		struct wait_queue *iwait;
-		struct wait_queue *owait;
+		wait_queue_head_t iwait;
+		wait_queue_head_t owait;
 		struct timer_list timer;
 		unsigned char ibuf[MIDIINBUF];
 		unsigned char obuf[MIDIOUTBUF];
@@ -512,8 +535,9 @@
 static unsigned setpll(struct sv_state *s, unsigned char reg, unsigned rate)
 {
 	unsigned long flags;
-	unsigned char r, m=0, n=0;
+	unsigned char r, m, n;
 	unsigned xm, xn, xr, xd, metric = ~0U;
+	/* the warnings about m and n used uninitialized are bogus and may safely be ignored */
 
 	if (rate < 625000/ADCMULT)
 		rate = 625000/ADCMULT;
@@ -1252,15 +1276,15 @@
 
 static int drain_dac(struct sv_state *s, int nonblock)
 {
-        struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
 	int count, tmo;
 
 	if (s->dma_dac.mapped || !s->dma_dac.ready)
 		return 0;
-        current->state = TASK_INTERRUPTIBLE;
         add_wait_queue(&s->dma_dac.wait, &wait);
         for (;;) {
+		__set_current_state(TASK_INTERRUPTIBLE);
                 spin_lock_irqsave(&s->lock, flags);
 		count = s->dma_dac.count;
                 spin_unlock_irqrestore(&s->lock, flags);
@@ -1270,7 +1294,7 @@
                         break;
                 if (nonblock) {
                         remove_wait_queue(&s->dma_dac.wait, &wait);
-                        current->state = TASK_RUNNING;
+                        set_current_state(TASK_RUNNING);
                         return -EBUSY;
                 }
 		tmo = 3 * HZ * (count + s->dma_dac.fragsize) / 2 / s->ratedac;
@@ -1279,7 +1303,7 @@
 			printk(KERN_DEBUG "sv: dma timed out??\n");
         }
         remove_wait_queue(&s->dma_dac.wait, &wait);
-        current->state = TASK_RUNNING;
+        set_current_state(TASK_RUNNING);
         if (signal_pending(current))
                 return -ERESTARTSYS;
         return 0;
@@ -1290,6 +1314,7 @@
 static ssize_t sv_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
 	struct sv_state *s = (struct sv_state *)file->private_data;
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t ret;
 	unsigned long flags;
 	unsigned swptr;
@@ -1306,24 +1331,30 @@
 		return -EFAULT;
 	ret = 0;
 #if 0
-   spin_lock_irqsave(&s->lock, flags);
-   sv_update_ptr(s);
-   spin_unlock_irqrestore(&s->lock, flags);
+	spin_lock_irqsave(&s->lock, flags);
+	sv_update_ptr(s);
+	spin_unlock_irqrestore(&s->lock, flags);
 #endif
+        add_wait_queue(&s->dma_adc.wait, &wait);
 	while (count > 0) {
 		spin_lock_irqsave(&s->lock, flags);
 		swptr = s->dma_adc.swptr;
 		cnt = s->dma_adc.dmasize-swptr;
 		if (s->dma_adc.count < cnt)
 			cnt = s->dma_adc.count;
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
 		if (cnt <= 0) {
 			start_adc(s);
-			if (file->f_flags & O_NONBLOCK)
-				return ret ? ret : -EAGAIN;
-			if (!interruptible_sleep_on_timeout(&s->dma_adc.wait, HZ)) {
+			if (file->f_flags & O_NONBLOCK) {
+				if (!ret)
+					ret = -EAGAIN;
+				break;
+			}
+			if (!schedule_timeout(HZ)) {
 				printk(KERN_DEBUG "sv: read: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
 				       s->dma_adc.dmasize, s->dma_adc.fragsize, s->dma_adc.count, 
 				       s->dma_adc.hwptr, s->dma_adc.swptr);
@@ -1336,12 +1367,18 @@
 				s->dma_adc.count = s->dma_adc.hwptr = s->dma_adc.swptr = 0;
 				spin_unlock_irqrestore(&s->lock, flags);
 			}
-			if (signal_pending(current))
-				return ret ? ret : -ERESTARTSYS;
+			if (signal_pending(current)) {
+				if (!ret)
+					ret = -ERESTARTSYS;
+				break;
+			}
 			continue;
 		}
-		if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt))
-			return ret ? ret : -EFAULT;
+		if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) {
+			if (!ret)
+				ret = -EFAULT;
+			break;
+		}
 		swptr = (swptr + cnt) % s->dma_adc.dmasize;
 		spin_lock_irqsave(&s->lock, flags);
 		s->dma_adc.swptr = swptr;
@@ -1352,12 +1389,15 @@
 		ret += cnt;
 		start_adc(s);
 	}
+        remove_wait_queue(&s->dma_adc.wait, &wait);
+	set_current_state(TASK_RUNNING);
 	return ret;
 }
 
 static ssize_t sv_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
 {
 	struct sv_state *s = (struct sv_state *)file->private_data;
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t ret;
 	unsigned long flags;
 	unsigned swptr;
@@ -1374,10 +1414,11 @@
 		return -EFAULT;
 	ret = 0;
 #if 0
-   spin_lock_irqsave(&s->lock, flags);
-   sv_update_ptr(s);
-   spin_unlock_irqrestore(&s->lock, flags);
+	spin_lock_irqsave(&s->lock, flags);
+	sv_update_ptr(s);
+	spin_unlock_irqrestore(&s->lock, flags);
 #endif
+        add_wait_queue(&s->dma_dac.wait, &wait);
 	while (count > 0) {
 		spin_lock_irqsave(&s->lock, flags);
 		if (s->dma_dac.count < 0) {
@@ -1388,14 +1429,19 @@
 		cnt = s->dma_dac.dmasize-swptr;
 		if (s->dma_dac.count + cnt > s->dma_dac.dmasize)
 			cnt = s->dma_dac.dmasize - s->dma_dac.count;
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
 		if (cnt <= 0) {
 			start_dac(s);
-			if (file->f_flags & O_NONBLOCK)
-				return ret ? ret : -EAGAIN;
-			if (!interruptible_sleep_on_timeout(&s->dma_dac.wait, HZ)) {
+			if (file->f_flags & O_NONBLOCK) {
+				if (!ret)
+					ret = -EAGAIN;
+				break;
+			}
+			if (!schedule_timeout(HZ)) {
 				printk(KERN_DEBUG "sv: write: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
 				       s->dma_dac.dmasize, s->dma_dac.fragsize, s->dma_dac.count, 
 				       s->dma_dac.hwptr, s->dma_dac.swptr);
@@ -1408,12 +1454,18 @@
 				s->dma_dac.count = s->dma_dac.hwptr = s->dma_dac.swptr = 0;
 				spin_unlock_irqrestore(&s->lock, flags);
 			}
-			if (signal_pending(current))
-				return ret ? ret : -ERESTARTSYS;
+			if (signal_pending(current)) {
+				if (!ret)
+					ret = -ERESTARTSYS;
+				break;
+			}
 			continue;
 		}
-		if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt))
-			return ret ? ret : -EFAULT;
+		if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt)) {
+			if (!ret)
+				ret = -EFAULT;
+			break;
+		}
 		swptr = (swptr + cnt) % s->dma_dac.dmasize;
 		spin_lock_irqsave(&s->lock, flags);
 		s->dma_dac.swptr = swptr;
@@ -1425,6 +1477,8 @@
 		ret += cnt;
 		start_dac(s);
 	}
+        remove_wait_queue(&s->dma_dac.wait, &wait);
+	set_current_state(TASK_RUNNING);
 	return ret;
 }
 
@@ -1789,6 +1843,7 @@
 static int sv_open(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
+	DECLARE_WAITQUEUE(wait, current);
 	struct sv_state *s = devs;
 	unsigned char fmtm = ~0, fmts = 0;
 
@@ -1805,8 +1860,12 @@
 			up(&s->open_sem);
 			return -EBUSY;
 		}
+		add_wait_queue(&s->open_wait, &wait);
+		__set_current_state(TASK_INTERRUPTIBLE);
 		up(&s->open_sem);
-		interruptible_sleep_on(&s->open_wait);
+		schedule();
+		remove_wait_queue(&s->open_wait, &wait);
+		set_current_state(TASK_RUNNING);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 		down(&s->open_sem);
@@ -1849,8 +1908,8 @@
 		dealloc_dmabuf(&s->dma_adc);
 	}
 	s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
-	up(&s->open_sem);
 	wake_up(&s->open_wait);
+	up(&s->open_sem);
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
@@ -1878,7 +1937,7 @@
 static ssize_t sv_midi_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
 	struct sv_state *s = (struct sv_state *)file->private_data;
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t ret;
 	unsigned long flags;
 	unsigned ptr;
@@ -1899,6 +1958,8 @@
 		cnt = MIDIINBUF - ptr;
 		if (s->midi.icnt < cnt)
 			cnt = s->midi.icnt;
+		if (cnt <= 0)
+                      __set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
@@ -1908,7 +1969,6 @@
                                       ret = -EAGAIN;
                               break;
                       }
-                      current->state = TASK_INTERRUPTIBLE;
                       schedule();
                       if (signal_pending(current)) {
                               if (!ret)
@@ -1932,7 +1992,7 @@
 		ret += cnt;
 		break;
 	}
-	current->state = TASK_RUNNING;
+	__set_current_state(TASK_RUNNING);
 	remove_wait_queue(&s->midi.iwait, &wait);
 	return ret;
 }
@@ -1940,7 +2000,7 @@
 static ssize_t sv_midi_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
 {
 	struct sv_state *s = (struct sv_state *)file->private_data;
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t ret;
 	unsigned long flags;
 	unsigned ptr;
@@ -1961,8 +2021,10 @@
 		cnt = MIDIOUTBUF - ptr;
 		if (s->midi.ocnt + cnt > MIDIOUTBUF)
 			cnt = MIDIOUTBUF - s->midi.ocnt;
-		if (cnt <= 0)
+		if (cnt <= 0) {
+			__set_current_state(TASK_INTERRUPTIBLE);
 			sv_handle_midi(s);
+		}
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (cnt > count)
 			cnt = count;
@@ -1972,7 +2034,6 @@
 					ret = -EAGAIN;
 				break;
 			}
-			current->state = TASK_INTERRUPTIBLE;
 			schedule();
 			if (signal_pending(current)) {
 				if (!ret)
@@ -1998,7 +2059,7 @@
 		sv_handle_midi(s);
 		spin_unlock_irqrestore(&s->lock, flags);
 	}
-	current->state = TASK_RUNNING;
+	__set_current_state(TASK_RUNNING);
 	remove_wait_queue(&s->midi.owait, &wait);
 	return ret;
 }
@@ -2030,6 +2091,7 @@
 static int sv_midi_open(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
+	DECLARE_WAITQUEUE(wait, current);
 	struct sv_state *s = devs;
 	unsigned long flags;
 
@@ -2046,8 +2108,12 @@
 			up(&s->open_sem);
 			return -EBUSY;
 		}
+		add_wait_queue(&s->open_wait, &wait);
+		__set_current_state(TASK_INTERRUPTIBLE);
 		up(&s->open_sem);
-		interruptible_sleep_on(&s->open_wait);
+		schedule();
+		remove_wait_queue(&s->open_wait, &wait);
+		set_current_state(TASK_RUNNING);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 		down(&s->open_sem);
@@ -2087,16 +2153,16 @@
 static int sv_midi_release(struct inode *inode, struct file *file)
 {
 	struct sv_state *s = (struct sv_state *)file->private_data;
-        struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
 	unsigned count, tmo;
 
 	VALIDATE_STATE(s);
 
 	if (file->f_mode & FMODE_WRITE) {
-		current->state = TASK_INTERRUPTIBLE;
 		add_wait_queue(&s->midi.owait, &wait);
 		for (;;) {
+			__set_current_state(TASK_INTERRUPTIBLE);
 			spin_lock_irqsave(&s->lock, flags);
 			count = s->midi.ocnt;
 			spin_unlock_irqrestore(&s->lock, flags);
@@ -2106,7 +2172,7 @@
 				break;
 			if (file->f_flags & O_NONBLOCK) {
 				remove_wait_queue(&s->midi.owait, &wait);
-				current->state = TASK_RUNNING;
+				set_current_state(TASK_RUNNING);
 				return -EBUSY;
 			}
 			tmo = (count * HZ) / 3100;
@@ -2114,7 +2180,7 @@
 				printk(KERN_DEBUG "sv: midi timed out??\n");
 		}
 		remove_wait_queue(&s->midi.owait, &wait);
-		current->state = TASK_RUNNING;
+		set_current_state(TASK_RUNNING);
 	}
 	down(&s->open_sem);
 	s->open_mode &= (~(file->f_mode << FMODE_MIDI_SHIFT)) & (FMODE_MIDI_READ|FMODE_MIDI_WRITE);
@@ -2124,8 +2190,8 @@
 		del_timer(&s->midi.timer);		
 	}
 	spin_unlock_irqrestore(&s->lock, flags);
-	up(&s->open_sem);
 	wake_up(&s->open_wait);
+	up(&s->open_sem);
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
@@ -2250,6 +2316,7 @@
 static int sv_dmfm_open(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
+	DECLARE_WAITQUEUE(wait, current);
 	struct sv_state *s = devs;
 
 	while (s && s->dev_dmfm != minor)
@@ -2265,8 +2332,12 @@
 			up(&s->open_sem);
 			return -EBUSY;
 		}
+		add_wait_queue(&s->open_wait, &wait);
+		__set_current_state(TASK_INTERRUPTIBLE);
 		up(&s->open_sem);
-		interruptible_sleep_on(&s->open_wait);
+		schedule();
+		remove_wait_queue(&s->open_wait, &wait);
+		set_current_state(TASK_RUNNING);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 		down(&s->open_sem);
@@ -2298,8 +2369,8 @@
 		outb(regb, s->iosynth+2);
 		outb(0, s->iosynth+3);
 	}
-	up(&s->open_sem);
 	wake_up(&s->open_wait);
+	up(&s->open_sem);
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
@@ -2365,7 +2436,7 @@
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "sv: version v0.21 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "sv: version v0.22 time " __TIME__ " " __DATE__ "\n");
 #if 0
 	if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT)))
 		printk(KERN_INFO "sv: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n");
@@ -2388,12 +2459,12 @@
 			continue;
 		}
 		memset(s, 0, sizeof(struct sv_state));
-		init_waitqueue(&s->dma_adc.wait);
-		init_waitqueue(&s->dma_dac.wait);
-		init_waitqueue(&s->open_wait);
-		init_waitqueue(&s->midi.iwait);
-		init_waitqueue(&s->midi.owait);
-		s->open_sem = MUTEX;
+		init_waitqueue_head(&s->dma_adc.wait);
+		init_waitqueue_head(&s->dma_dac.wait);
+		init_waitqueue_head(&s->open_wait);
+		init_waitqueue_head(&s->midi.iwait);
+		init_waitqueue_head(&s->midi.owait);
+		init_MUTEX(&s->open_sem);
 		spin_lock_init(&s->lock);
 		s->magic = SV_MAGIC;
 		s->iosb = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/telephony/ixj.c linux.15p9/drivers/telephony/ixj.c
--- linux.vanilla/drivers/telephony/ixj.c	Tue Jan  4 21:18:59 2000
+++ linux.15p9/drivers/telephony/ixj.c	Wed Jan 12 01:17:32 2000
@@ -1974,7 +1974,7 @@
 
 		ixj_WriteDSPCommand(0x0700, board);
 	}
-	if (ixj[board].play_mode != -1 && ixj[board].rec_mode != -1);
+	if (ixj[board].play_mode != -1 && ixj[board].rec_mode != -1)
 	{
 		ixj_WriteDSPCommand(0xB002, board);	// AEC Stop
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/video/atyfb.c linux.15p9/drivers/video/atyfb.c
--- linux.vanilla/drivers/video/atyfb.c	Tue Jan  4 21:18:59 2000
+++ linux.15p9/drivers/video/atyfb.c	Fri Jan 14 15:56:16 2000
@@ -1,4 +1,4 @@
-/*  $Id: atyfb.c,v 1.106.2.6 1999/10/14 08:44:47 davem Exp $
+/*  $Id: atyfb.c,v 1.106.2.7 1999/11/19 00:12:29 davem Exp $
  *  linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
  *
  *	Copyright (C) 1997-1998  Geert Uytterhoeven
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/video/iga.h linux.15p9/drivers/video/iga.h
--- linux.vanilla/drivers/video/iga.h	Thu Oct 15 23:24:18 1998
+++ linux.15p9/drivers/video/iga.h	Fri Jan 21 17:50:18 2000
@@ -1,4 +1,4 @@
-/* $Id: iga.h,v 1.1 1998/10/07 11:36:07 jj Exp $
+/* $Id: iga.h,v 1.1.2.1 2000/01/21 01:05:53 davem Exp $
  * iga1682.h: Sparc/PCI iga1682 driver constants etc.
  *
  * Copyleft 1998 V. Roganov and G. Raiko
@@ -12,6 +12,8 @@
     unsigned int total_vram;
 };
 
+#define IGA_ATTR_CTL			0x3C0
+#define   IGA_IDX_VGA_OVERSCAN		0x11
 #define DAC_W_INDEX                     0x03C8
 #define DAC_DATA                        0x03C9
 #define IGA_EXT_CNTRL                   0x3CE
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/video/igafb.c linux.15p9/drivers/video/igafb.c
--- linux.vanilla/drivers/video/igafb.c	Sun Mar  7 18:39:03 1999
+++ linux.15p9/drivers/video/igafb.c	Fri Jan 21 17:50:18 2000
@@ -659,11 +659,11 @@
 	info->frame_buffer_phys = addr & PCI_BASE_ADDRESS_MEM_MASK;
 
 #ifdef __sparc__
-	
-	info->io_base_phys = info->frame_buffer_phys;
-	
-	/* Obtain virtual address and correct physical by PCIC shift */
-	info->io_base = pcic_alloc_io(&info->io_base_phys);
+
+	info->io_base_phys = 0x30000000;
+
+	info->io_base = sparc_alloc_io(info->io_base_phys,
+	    NULL, 0x1000, "iga", 0, 0);
 	if (!info->io_base) {
 		return;
 	}
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/fs/Config.in linux.15p9/fs/Config.in
--- linux.vanilla/fs/Config.in	Sat Aug 14 02:27:35 1999
+++ linux.15p9/fs/Config.in	Tue Jan 18 00:59:09 2000
@@ -42,9 +42,9 @@
   bool '/dev/pts filesystem for Unix98 PTYs' CONFIG_DEVPTS_FS
 fi
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-  tristate 'QNX filesystem support (EXPERIMENTAL)' CONFIG_QNX4FS_FS
+  tristate 'QNX4 filesystem support (read only) (EXPERIMENTAL)' CONFIG_QNX4FS_FS
   if [ "$CONFIG_QNX4FS_FS" != "n" ]; then
-    bool '   QNXFS read-write support (FOR TESTING ONLY)' CONFIG_QNX4FS_RW
+    bool '   QNX4FS write support (DANGEROUS)' CONFIG_QNX4FS_RW
   fi    
 fi
 tristate 'ROM filesystem support' CONFIG_ROMFS_FS
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/fs/binfmt_elf.c linux.15p9/fs/binfmt_elf.c
--- linux.vanilla/fs/binfmt_elf.c	Sat Aug 14 02:26:50 1999
+++ linux.15p9/fs/binfmt_elf.c	Tue Jan 18 00:54:47 2000
@@ -243,9 +243,10 @@
 
 	/* Now read in all of the header information */
 
-	size = sizeof(struct elf_phdr) * interp_elf_ex->e_phnum;
-	if (size > ELF_EXEC_PAGESIZE)
+	if (interp_elf_ex->e_phnum < 1 || interp_elf_ex->e_phnum >
+	    ELF_EXEC_PAGESIZE / sizeof(struct elf_phdr))
 		goto out;
+	size = sizeof(struct elf_phdr) * interp_elf_ex->e_phnum;
 	elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL);
 	if (!elf_phdata)
 		goto out;
@@ -333,6 +334,11 @@
 			MAP_FIXED|MAP_PRIVATE, 0);
 
 	*interp_load_addr = load_addr;
+	/*
+	 * AUDIT: is everything deallocated properly if this happens
+	 * to be ~0UL? We'd better switch to out-of-band error reporting.
+	 * Also for a.out.
+	 */
 	error = ((unsigned long) interp_elf_ex->e_entry) + load_addr;
 
 out_close:
@@ -447,10 +453,13 @@
 
 	/* Now read in all of the header information */
 
+	if (elf_ex.e_phentsize != sizeof(struct elf_phdr) ||
+	    elf_ex.e_phnum < 1 ||
+	    elf_ex.e_phnum > 65536 / sizeof(struct elf_phdr))
+		goto out;
+
 	retval = -ENOMEM;
 	size = elf_ex.e_phentsize * elf_ex.e_phnum;
-	if (size > 65536)
-		goto out;
 	elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL);
 	if (!elf_phdata)
 		goto out;
@@ -476,8 +485,10 @@
 
 	for (i = 0; i < elf_ex.e_phnum; i++) {
 		if (elf_ppnt->p_type == PT_INTERP) {
-			retval = -EINVAL;
-		  	if (elf_interpreter)
+			retval = -ENOEXEC;
+		  	if (elf_interpreter ||
+			    elf_ppnt->p_filesz < 2 ||
+			    elf_ppnt->p_filesz > PAGE_SIZE)
 				goto out_free_interp;
 
 			/* This is the program interpreter used for
@@ -496,6 +507,7 @@
 					   elf_ppnt->p_filesz, 1);
 			if (retval < 0)
 				goto out_free_interp;
+			elf_interpreter[elf_ppnt->p_filesz - 1] = 0;
 			/* If the program interpreter is one of these two,
 			 * then assume an iBCS2 image. Otherwise assume
 			 * a native linux image.
@@ -685,14 +697,17 @@
 						    &interp_load_addr);
 
 		dput(interpreter_dentry);
-		kfree(elf_interpreter);
 
 		if (elf_entry == ~0UL) {
-			printk(KERN_ERR "Unable to load interpreter\n");
+			printk(KERN_ERR "Unable to load interpreter %.128s\n",
+				elf_interpreter);
+			kfree(elf_interpreter);
 			kfree(elf_phdata);
 			send_sig(SIGSEGV, current, 0);
 			return 0;
 		}
+
+		kfree(elf_interpreter);
 	}
 
 	kfree(elf_phdata);
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/fs/block_dev.c linux.15p9/fs/block_dev.c
--- linux.vanilla/fs/block_dev.c	Tue Jan  4 21:19:00 2000
+++ linux.15p9/fs/block_dev.c	Wed Jan 12 01:06:21 2000
@@ -92,6 +92,7 @@
 		      blocks = read_ahead[MAJOR(dev)] / (blocksize >> 9) / 2;
 		      if (block + blocks > size) blocks = size - block;
 		      if (blocks > NBUF) blocks=NBUF;
+		      if (!blocks) blocks = 1;
 		      for(i=1; i<blocks; i++)
 		      {
 		        bhlist[i] = getblk (dev, block+i, blocksize);
@@ -105,8 +106,10 @@
 		    ll_rw_block(READ, blocks, bhlist);
 		    for(i=1; i<blocks; i++) brelse(bhlist[i]);
 		    wait_on_buffer(bh);
-		    if (!buffer_uptodate(bh))
+		    if (!buffer_uptodate(bh)) {
+			  brelse(bh);
 			  return written ? written : -EIO;
+		    }
 		  };
 		};
 #endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/fs/fat/misc.c linux.15p9/fs/fat/misc.c
--- linux.vanilla/fs/fat/misc.c	Sat Aug 14 02:27:37 1999
+++ linux.15p9/fs/fat/misc.c	Wed Jan 12 01:22:48 2000
@@ -222,9 +222,10 @@
 	sector = MSDOS_SB(sb)->data_start+(nr-2)*cluster_size;
 	last_sector = sector + cluster_size;
 	if (MSDOS_SB(sb)->cvf_format &&
-	    MSDOS_SB(sb)->cvf_format->zero_out_cluster)
+	    MSDOS_SB(sb)->cvf_format->zero_out_cluster) {
 		MSDOS_SB(sb)->cvf_format->zero_out_cluster(inode,nr);
-	else
+		res=fat_bread(sb,fat_smap(inode,inode->i_blocks));
+	}else
 	for ( ; sector < last_sector; sector++) {
 		#ifdef DEBUG
 			printk("zeroing sector %d\n",sector);
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/fs/ncpfs/dir.c linux.15p9/fs/ncpfs/dir.c
--- linux.vanilla/fs/ncpfs/dir.c	Sat Aug 14 02:27:37 1999
+++ linux.15p9/fs/ncpfs/dir.c	Wed Feb 16 18:22:56 2000
@@ -868,7 +868,9 @@
 int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode,
 		int attributes)
 {
+ 	struct ncp_server *server = NCP_SERVER(dir);
 	int error, result;
+	int opmode;
 	struct ncpfs_inode_info finfo;
 	__u8 _name[dentry->d_name.len + 1];
 	
@@ -886,18 +888,25 @@
 	io2vol(NCP_SERVER(dir), _name, !ncp_preserve_case(dir));
 
 	error = -EACCES;
-	result = ncp_open_create_file_or_subdir(NCP_SERVER(dir), dir, _name,
+	result = ncp_open_create_file_or_subdir(server, dir, _name,
 			   OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
 			   attributes, AR_READ | AR_WRITE, &finfo.nw_info);
-	if (!result) {
-		finfo.nw_info.access = O_RDWR;
-		error = ncp_instantiate(dir, dentry, &finfo);
-	} else {
-		if (result == 0x87) error = -ENAMETOOLONG;
-		DPRINTK(KERN_DEBUG "ncp_create: %s/%s failed\n",
-			dentry->d_parent->d_name.name, dentry->d_name.name);
-	}
-
+	opmode = O_RDWR;
+	if (result) {
+		result = ncp_open_create_file_or_subdir(server, dir, _name,
+				OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
+				attributes, AR_WRITE, &finfo.nw_info);
+		if (result) {
+			if (result == 0x87)
+				error = -ENAMETOOLONG;
+			DPRINTK("ncp_create: %s/%s failed\n",
+				dentry->d_parent->d_name.name, dentry->d_name.name);
+			goto out;
+		}
+		opmode = O_WRONLY;
+ 	}
+	finfo.nw_info.access = opmode;
+	error = ncp_instantiate(dir, dentry, &finfo);
 out:
 	return error;
 }
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/fs/ncpfs/file.c linux.15p9/fs/ncpfs/file.c
--- linux.vanilla/fs/ncpfs/file.c	Sat Aug 14 02:26:51 1999
+++ linux.15p9/fs/ncpfs/file.c	Wed Feb 16 18:22:56 2000
@@ -36,9 +36,8 @@
  */
 int ncp_make_open(struct inode *inode, int right)
 {
-	int error, result;
+	int error;
 	int access;
-	struct nw_file_info finfo;
 
 	error = -EINVAL;
 	if (!inode) {
@@ -53,6 +52,9 @@
 	error = -EACCES;
 	lock_super(inode->i_sb);
 	if (!NCP_FINFO(inode)->opened) {
+		int result;
+		struct nw_file_info finfo;
+		
 		finfo.i.dirEntNum = NCP_FINFO(inode)->dirEntNum;
 		finfo.i.volNumber = NCP_FINFO(inode)->volNumber;
 		/* tries max. rights */
@@ -62,10 +64,20 @@
 					0, AR_READ | AR_WRITE, &finfo);
 		if (!result)
 			goto update;
-		finfo.access = O_RDONLY;
-		result = ncp_open_create_file_or_subdir(NCP_SERVER(inode),
+		switch (right) {
+			case O_RDONLY:
+				finfo.access = O_RDONLY;
+				result = ncp_open_create_file_or_subdir(NCP_SERVER(inode),
+ 					NULL, NULL, OC_MODE_OPEN,
+ 					0, AR_READ, &finfo);
+				break;
+			case O_WRONLY:
+				finfo.access = O_WRONLY;
+				result = ncp_open_create_file_or_subdir(NCP_SERVER(inode),
 					NULL, NULL, OC_MODE_OPEN,
-					0, AR_READ, &finfo);
+					0, AR_WRITE, &finfo);
+				break;
+		}		
 		if (result) {
 #ifdef NCPFS_PARANOIA
 printk(KERN_DEBUG "ncp_make_open: failed, result=%d\n", result);
@@ -134,7 +146,7 @@
 
 	error = ncp_make_open(inode, O_RDONLY);
 	if (error) {
-		printk(KERN_ERR "ncp_file_read: open failed, error=%d\n", error);
+		DPRINTK(KERN_ERR "ncp_file_read: open failed, error=%d\n", error);
 		goto out;
 	}
 
@@ -212,9 +224,9 @@
 	errno = 0;
 	if (!count)
 		goto out;
-	errno = ncp_make_open(inode, O_RDWR);
+	errno = ncp_make_open(inode, O_WRONLY);
 	if (errno) {
-		printk(KERN_ERR "ncp_file_write: open failed, error=%d\n", errno);
+		DPRINTK(KERN_ERR "ncp_file_write: open failed, error=%d\n", errno);
 		return errno;
 	}
 	pos = *ppos;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/fs/ncpfs/inode.c linux.15p9/fs/ncpfs/inode.c
--- linux.vanilla/fs/ncpfs/inode.c	Tue Jan  4 21:19:00 2000
+++ linux.15p9/fs/ncpfs/inode.c	Wed Feb 16 18:22:56 2000
@@ -691,7 +691,7 @@
 		DPRINTK(KERN_DEBUG "ncpfs: trying to change size to %ld\n",
 			attr->ia_size);
 
-		if ((result = ncp_make_open(inode, O_RDWR)) < 0) {
+		if ((result = ncp_make_open(inode, O_WRONLY)) < 0) {
 			return -EACCES;
 		}
 		ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/fs/ncpfs/ioctl.c linux.15p9/fs/ncpfs/ioctl.c
--- linux.vanilla/fs/ncpfs/ioctl.c	Sat Aug 14 02:26:51 1999
+++ linux.15p9/fs/ncpfs/ioctl.c	Wed Feb 16 18:22:56 2000
@@ -307,6 +307,7 @@
 				default:
 						return -EINVAL;
 			}
+			/* locking needs both read and write access */
 			if ((result = ncp_make_open(inode, O_RDWR)) != 0)
 			{
 				return result;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/fs/nfs/inode.c linux.15p9/fs/nfs/inode.c
--- linux.vanilla/fs/nfs/inode.c	Tue Jan  4 21:19:00 2000
+++ linux.15p9/fs/nfs/inode.c	Wed Jan 12 01:23:39 2000
@@ -212,7 +212,12 @@
 	if (!data)
 		goto out_miss_args;
 
-	if (data->version != NFS_MOUNT_VERSION) {
+	/* No NFS V3. */
+	if (data->flags & NFS_MOUNT_VER3)
+		goto out_fail;
+
+	/* Don't complain if "mount" is newer. */
+	if (data->version < NFS_MOUNT_VERSION) {
 		printk("nfs warning: mount version %s than kernel\n",
 			data->version < NFS_MOUNT_VERSION ? "older" : "newer");
 		if (data->version < 2)
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/fs/nfsd/nfsctl.c linux.15p9/fs/nfsd/nfsctl.c
--- linux.vanilla/fs/nfsd/nfsctl.c	Tue Jan  4 21:19:00 2000
+++ linux.15p9/fs/nfsd/nfsctl.c	Wed Jan 12 01:23:39 2000
@@ -345,7 +345,7 @@
 int
 init_module(void)
 {
-	printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n");
+	printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de)\n");
 	do_nfsservctl = handle_sys_nfsservctl;
 	return 0;
 }
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/fs/nfsd/nfsfh.c linux.15p9/fs/nfsd/nfsfh.c
--- linux.vanilla/fs/nfsd/nfsfh.c	Tue Jan  4 21:19:00 2000
+++ linux.15p9/fs/nfsd/nfsfh.c	Thu Jan 13 22:40:20 2000
@@ -455,13 +455,27 @@
 			break;
 		}
 
-		result = ERR_PTR(-ENOENT);
-		dir = iget_in_use(sb, dirino);
-		if (!dir)
-			goto out_root;
-		dentry = d_alloc_root(dir, NULL);
-		if (!dentry)
-			goto out_iput;
+		/*
+		 *  Fix for /// bad export bug: if dirino is the root,
+		 *  get the real root dentry rather than creating a temporary
+		 *  "root" dentry.  XXX We could extend this to use
+		 *  any existing dentry for the located 'dir', but all
+		 *  of this code is going to be completely rewritten soon,
+		 *  so I won't bother. 
+		 */
+
+		if (dirino == root_ino) {
+			dentry = dget(root);
+		}
+		else {
+			result = ERR_PTR(-ENOENT);
+			dir = iget_in_use(sb, dirino);
+			if (!dir)
+				goto out_root;
+			dentry = d_alloc_root(dir, NULL);
+			if (!dentry)
+				goto out_iput;
+		}
 
 		/*
 		 * Get the name for this inode and the next parent inode.
@@ -847,12 +861,12 @@
 	dirent.ino = ino;
 	error = get_parent_ino(parent, &dirent);
 	if (error) {
-#ifdef NFSD_PARANOIA
+#ifdef NFSD_PARANOIA_EXTREME
 printk("lookup_by_inode: ino %ld not found in %s\n", ino, parent->d_name.name);
 #endif
 		goto no_entry;
 	}
-#ifdef NFSD_PARANOIA
+#ifdef NFSD_PARANOIA_EXTREME
 printk("lookup_by_inode: found %s\n", dirent.name);
 #endif
 
@@ -860,13 +874,13 @@
 	if (!IS_ERR(dentry)) {
 		if (dentry->d_inode && dentry->d_inode->i_ino == ino)
 			goto out;
-#ifdef NFSD_PARANOIA
+#ifdef NFSD_PARANOIA_EXTREME
 printk("lookup_by_inode: %s/%s inode mismatch??\n",
 parent->d_name.name, dentry->d_name.name);
 #endif
 		dput(dentry);
 	} else {
-#ifdef NFSD_PARANOIA
+#ifdef NFSD_PARANOIA_EXTREME
 printk("lookup_by_inode: %s lookup failed, error=%ld\n",
 dirent.name, PTR_ERR(dentry));
 #endif
@@ -1077,7 +1091,7 @@
 	/*
 	 * Stage 5: Search the whole volume, Yea Right.
 	 */
-#ifdef NFSD_PARANOIA
+#ifdef NFSD_PARANOIA_EXTREME
 printk("find_fh_dentry: %s/%u dir/%u not found!\n",
        kdevname(u32_to_kdev_t(fh->fh_dev)), fh->fh_ino, fh->fh_dirino);
 #endif
@@ -1330,7 +1344,7 @@
 	fhp->fh_handle.fh_ino = ino_t_to_u32(inode->i_ino);
 	fhp->fh_handle.fh_generation = inode->i_generation;
 	fhp->fh_handle.fh_dcookie = (struct dentry *)0xfeebbaca;
- out:
+out:
 	return;
 
 out_bad:
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/fs/nfsd/nfsproc.c linux.15p9/fs/nfsd/nfsproc.c
--- linux.vanilla/fs/nfsd/nfsproc.c	Tue Jan  4 21:19:00 2000
+++ linux.15p9/fs/nfsd/nfsproc.c	Wed Jan 12 01:23:39 2000
@@ -237,6 +237,9 @@
 	if (nfserr)
 		goto done;
 	inode = newfhp->fh_dentry->d_inode;
+	if (inode && newfhp->fh_handle.fh_ino == 0)
+		 /* inode might have been instantiated while we slept */
+		 fh_update(newfhp);
 
 	/* Unfudge the mode bits */
 	if (attr->ia_valid & ATTR_MODE) { 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/fs/proc/array.c linux.15p9/fs/proc/array.c
--- linux.vanilla/fs/proc/array.c	Tue Jan  4 21:19:00 2000
+++ linux.15p9/fs/proc/array.c	Thu Feb 17 13:38:52 2000
@@ -248,9 +248,10 @@
 	unsigned long ticks;
 
 	ticks = jiffies * smp_num_cpus;
+#ifndef CONFIG_ARCH_S390
 	for (i = 0 ; i < NR_IRQS ; i++)
 		sum += kstat_irqs(i);
-
+#endif
 #ifdef __SMP__
 	len = sprintf(buffer,
 		"cpu  %u %u %u %lu\n",
@@ -274,8 +275,12 @@
 		"disk_rblk %u %u %u %u\n"
 		"disk_wblk %u %u %u %u\n"
 		"page %u %u\n"
+#ifdef CONFIG_ARCH_S390
+                "swap %u %u\n",
+#else
 		"swap %u %u\n"
 		"intr %u",
+#endif
 #else
 	len = sprintf(buffer,
 		"cpu  %u %u %u %lu\n"
@@ -285,8 +290,12 @@
 		"disk_rblk %u %u %u %u\n"
 		"disk_wblk %u %u %u %u\n"
 		"page %u %u\n"
+#ifdef CONFIG_ARCH_S390           
+                "swap %u %u\n",   
+#else                             
 		"swap %u %u\n"
 		"intr %u",
+#endif                            
 		kstat.cpu_user,
 		kstat.cpu_nice,
 		kstat.cpu_system,
@@ -305,10 +314,14 @@
 		kstat.pgpgin,
 		kstat.pgpgout,
 		kstat.pswpin,
+#ifdef CONFIG_ARCH_S390
+		kstat.pswpout);
+#else
 		kstat.pswpout,
 		sum);
 	for (i = 0 ; i < NR_IRQS ; i++)
 		len += sprintf(buffer + len, " %u", kstat_irqs(i));
+#endif
 	len += sprintf(buffer + len,
 		"\nctxt %u\n"
 		"btime %lu\n"
@@ -850,7 +863,6 @@
 	buffer += sprintf(buffer, "SigBlk:\t");
 	buffer = render_sigset_t(&p->blocked, buffer);
 	*buffer++ = '\n';
-
 	collect_sigign_sigcatch(p, &ign, &catch);
 	buffer += sprintf(buffer, "SigIgn:\t");
 	buffer = render_sigset_t(&ign, buffer);
@@ -877,7 +889,7 @@
 {
 	char * orig = buffer;
 	struct task_struct *tsk;
-#ifdef  CONFIG_ARCH_S390
+#if  __s390__
 	int line,len;
 #endif
 
@@ -891,7 +903,7 @@
 	buffer = task_mem(tsk, buffer);
 	buffer = task_sig(tsk, buffer);
 	buffer = task_cap(tsk, buffer);
-#ifdef CONFIG_ARCH_S390
+#if __s390__
 	for(line=0;(len=sprintf_regs(line,buffer,tsk,NULL,NULL))!=0;line++)
 		buffer+=len;
 #endif
@@ -1302,7 +1314,9 @@
 extern int get_partition_list(char *);
 extern int get_filesystem_list(char *);
 extern int get_filesystem_info( char * );
+#ifndef CONFIG_ARCH_S390
 extern int get_irq_list(char *);
+#endif
 extern int get_dma_list(char *);
 extern int get_cpuinfo(char *);
 extern int get_pci_list(char *);
@@ -1366,10 +1380,10 @@
 
 		case PROC_PARTITIONS:
 			return get_partition_list(page);
-
+#ifndef CONFIG_ARCH_S390
 		case PROC_INTERRUPTS:
 			return get_irq_list(page);
-
+#endif
 		case PROC_FILESYSTEMS:
 			return get_filesystem_list(page);
 #ifndef CONFIG_ARCH_S390
@@ -1450,7 +1464,7 @@
 		case PROC_PID_CPU:
 			return 0;	
 	}
-	if(capable(CAP_DAC_OVERRIDE) || (current->fsuid == euid && ok))
+	if ((current->fsuid == euid && ok) || capable(CAP_DAC_OVERRIDE))
 		return 0;
 	return 1;
 }
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/fs/qnx4/BUGS linux.15p9/fs/qnx4/BUGS
--- linux.vanilla/fs/qnx4/BUGS	Mon Aug 31 21:01:35 1998
+++ linux.15p9/fs/qnx4/BUGS	Tue Jan 18 00:59:09 2000
@@ -1,4 +1,13 @@
-Last update: 03-07-1998
+Last update: 1999-12-23
+
+- Fragmented files and directories were incorrectly handled.
+  Fixed 1999-12-23, Anders.
+
+- readdir sometimes returned the same dir entry more than once.
+  Fixed 1999-12-13, Anders.
+
+- File names with a length of exactly 16 chars were handled incorrectly.
+  Fixed 1999-12-11, Anders.
 
 - Files in a subdir can't be accessed, I think that the inode information
   is not correctly copied at some point. Solved 06-06-1998, Richard.
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/fs/qnx4/README linux.15p9/fs/qnx4/README
--- linux.vanilla/fs/qnx4/README	Mon Aug 31 21:01:35 1998
+++ linux.15p9/fs/qnx4/README	Tue Jan 18 00:59:09 2000
@@ -1,9 +1,9 @@
 
   This is a snapshot of the QNX4 filesystem for Linux.
-  Please send diffs and remarks to <qnxfs@rtc-one.net> .
+  Please send diffs and remarks to <al@alarsen.net> .
   
 Credits :
 
 Richard "Scuba" A. Frowijn     <scuba@wxs.nl>
 Frank "Jedi/Sector One" Denis  <j@4u.net>
-
+Anders Larsen                  <al@alarsen.net> (Maintainer)
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/fs/qnx4/TODO linux.15p9/fs/qnx4/TODO
--- linux.vanilla/fs/qnx4/TODO	Mon Aug 31 21:01:35 1998
+++ linux.15p9/fs/qnx4/TODO	Tue Jan 18 00:59:09 2000
@@ -1,5 +1,8 @@
 Name       : QNX4 TODO list
-Last update: 29-06-1998
+Last update: 1999-12-23
+
+    - Writing is still unsupported (it may compile, but it certainly won't
+      bring you any joy).
 
     - qnx4_checkroot (inode.c), currently there's a look for the '/' in
       the root direntry, if so then the current mounted device is a qnx4
@@ -11,10 +14,6 @@
       
     - Bitmap functions. To find out the free space, largest free block, etc.
       Partly done (RO), Richard, 05/06/1998. Optimized 20-06-1998, Frank.
-    
-    - Symbolic links. symlinks.c have to be rewritten.
-    
-    - Extended files.
     
     - Complete write, unlink and truncate functions : the bitmap should be
 updated.
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/fs/qnx4/bitmap.c linux.15p9/fs/qnx4/bitmap.c
--- linux.vanilla/fs/qnx4/bitmap.c	Tue Sep  1 18:43:13 1998
+++ linux.15p9/fs/qnx4/bitmap.c	Wed Jan 19 11:58:42 2000
@@ -1,7 +1,7 @@
 /* 
  * QNX4 file system, Linux implementation.
  * 
- * Version : 0.1
+ * Version : 0.2.1
  * 
  * Using parts of the xiafs filesystem.
  * 
@@ -81,12 +81,14 @@
 	return total_free;
 }
 
-unsigned long qnx4_count_free_inodes(struct super_block *sb)
+int qnx4_bmap(struct inode *inode, int block)
 {
-	return qnx4_count_free_blocks(sb) * QNX4_INODES_PER_BLOCK;	/* FIXME */
+   return qnx4_block_map( inode, block );
 }
 
-int qnx4_is_free(struct super_block *sb, int block)
+#ifdef CONFIG_QNX4FS_RW
+
+int qnx4_is_free(struct super_block *sb, long block)
 {
 	int start = sb->u.qnx4_sb.BitMap->di_first_xtnt.xtnt_blk - 1;
 	int size = sb->u.qnx4_sb.BitMap->di_size;
@@ -115,18 +117,7 @@
 	return ret;
 }
 
-int qnx4_bmap(struct inode *inode, int block)
-{
-   QNX4DEBUG(("qnx4: bmap on block [%d]\n", block));
-   if (block < 0) {
-      return 0;
-   }
-   return !qnx4_is_free(inode->i_sb, block);
-}
-
-#ifdef CONFIG_QNX4FS_RW
-
-int qnx4_set_bitmap(struct super_block *sb, int block, int busy)
+int qnx4_set_bitmap(struct super_block *sb, long block, int busy)
 {
 	int start = sb->u.qnx4_sb.BitMap->di_first_xtnt.xtnt_blk - 1;
 	int size = sb->u.qnx4_sb.BitMap->di_size;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/fs/qnx4/dir.c linux.15p9/fs/qnx4/dir.c
--- linux.vanilla/fs/qnx4/dir.c	Wed Oct 20 01:12:49 1999
+++ linux.15p9/fs/qnx4/dir.c	Mon Jan 24 19:44:50 2000
@@ -1,7 +1,7 @@
 /* 
  * QNX4 file system, Linux implementation.
  * 
- * Version : 0.1
+ * Version : 0.2.1
  * 
  * Using parts of the xiafs filesystem.
  * 
@@ -20,55 +20,57 @@
 
 #include <asm/segment.h>
 
-static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir);
-
 static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
 	struct inode *inode = filp->f_dentry->d_inode;
 	unsigned int offset;
 	struct buffer_head *bh;
 	struct qnx4_inode_entry *de;
-	long blknum;
-	int i;
+	struct qnx4_link_info *le;
+	unsigned long blknum;
+	int ix, ino;
 	int size;
 
-	blknum = inode->u.qnx4_i.i_first_xtnt.xtnt_blk - 1 +
-	    ((filp->f_pos >> 6) >> 3);
-
 	QNX4DEBUG(("qnx4_readdir:i_size = %ld\n", (long) inode->i_size));
 	QNX4DEBUG(("filp->f_pos         = %ld\n", (long) filp->f_pos));
-	QNX4DEBUG(("BlkNum              = %ld\n", (long) blknum));
 
 	while (filp->f_pos < inode->i_size) {
+		blknum = qnx4_block_map( inode, filp->f_pos >> QNX4_BLOCK_SIZE_SHIFT );
 		bh = bread(inode->i_dev, blknum, QNX4_BLOCK_SIZE);
-		if(bh==NULL)
-		{
+		if(bh==NULL) {
 			printk(KERN_ERR "qnx4_readdir: bread failed (%ld)\n", blknum);
 			break;
 		}
-		i = (filp->f_pos - (((filp->f_pos >> 6) >> 3) << 9)) & 0x3f;
-		while (i < QNX4_INODES_PER_BLOCK) {
-			offset = i * QNX4_DIR_ENTRY_SIZE;
+		ix = ( (filp->f_pos >> QNX4_DIR_ENTRY_SIZE_SHIFT) - (filp->f_pos >> QNX4_BLOCK_SIZE_SHIFT) * QNX4_INODES_PER_BLOCK) & QNX4_INODES_PER_BLOCK_MASK;
+		while (ix < QNX4_INODES_PER_BLOCK) {
+			offset = ix * QNX4_DIR_ENTRY_SIZE;
 			de = (struct qnx4_inode_entry *) (bh->b_data + offset);
 			size = strlen(de->di_fname);
 			if (size) {
-
-				QNX4DEBUG(("qnx4_readdir:%s\n", de->di_fname));
-
-				if ((de->di_mode) || (de->di_status == QNX4_FILE_LINK)) {
-					if (de->di_status) {
-						if (filldir(dirent, de->di_fname, size, filp->f_pos, de->di_first_xtnt.xtnt_blk) < 0) {
-							brelse(bh);
-							return 0;
-						}
+				if ( !(de->di_status & QNX4_FILE_LINK) && size > QNX4_SHORT_NAME_MAX )
+					size = QNX4_SHORT_NAME_MAX;
+				else if ( size > QNX4_NAME_MAX )
+					size = QNX4_NAME_MAX;
+				if ( ( de->di_status & (QNX4_FILE_USED|QNX4_FILE_LINK) ) != 0 ) {
+					QNX4DEBUG(("qnx4_readdir:%.*s\n", size, de->di_fname));
+					if ( ( de->di_status & QNX4_FILE_LINK ) == 0 )
+						ino = blknum * QNX4_INODES_PER_BLOCK + ix - 1;
+					else {
+						le  = (struct qnx4_link_info*)de;
+						ino = ( le->dl_inode_blk - 1 ) *
+							QNX4_INODES_PER_BLOCK +
+							le->dl_inode_ndx;
+					}
+					if (filldir(dirent, de->di_fname, size, filp->f_pos, ino) < 0) {
+						brelse(bh);
+						return 0;
 					}
 				}
 			}
-			i++;
+			ix++;
 			filp->f_pos += QNX4_DIR_ENTRY_SIZE;
 		}
 		brelse(bh);
-		blknum++;
 	}
 	UPDATE_ATIME(inode);
 
@@ -77,52 +79,19 @@
 
 static struct file_operations qnx4_dir_operations =
 {
-	NULL,			/* lseek - default */
-	NULL,			/* read */
-	NULL,			/* write - bad */
-	qnx4_readdir,		/* readdir */
-	NULL,			/* poll - default */
-	NULL,			/* ioctl - default */
-	NULL,			/* mmap */
-	NULL,			/* no special open code */
-        NULL,                   /* no special flush code */
-	NULL,			/* no special release code */
-	file_fsync,		/* default fsync */
-	NULL,			/* default fasync */
-	NULL,			/* default check_media_change */
-	NULL,			/* default revalidate */
+	readdir:		qnx4_readdir,
+	fsync:			file_fsync,
 };
 
 struct inode_operations qnx4_dir_inode_operations =
 {
-	&qnx4_dir_operations,
-#ifdef CONFIG_QNX4FS_RW
-	qnx4_create,
-#else
-	NULL,			/* create */
-#endif
-	qnx4_lookup,
-	NULL,			/* link */
+	default_file_ops:	&qnx4_dir_operations,
 #ifdef CONFIG_QNX4FS_RW
-	qnx4_unlink,		/* unlink */
-#else
-	NULL,
+	create:			qnx4_create,
 #endif
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
+	lookup:			qnx4_lookup,
 #ifdef CONFIG_QNX4FS_RW
-	qnx4_rmdir,		/* rmdir */
-#else
-	NULL,
+	unlink:			qnx4_unlink,
+	rmdir:			qnx4_rmdir,
 #endif
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* bmap */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL			/* smap */
 };
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/fs/qnx4/file.c linux.15p9/fs/qnx4/file.c
--- linux.vanilla/fs/qnx4/file.c	Fri Mar 26 21:57:41 1999
+++ linux.15p9/fs/qnx4/file.c	Tue Jan 18 00:59:09 2000
@@ -1,7 +1,7 @@
 /* 
  * QNX4 file system, Linux implementation.
  * 
- * Version : 0.1
+ * Version : 0.2.1
  * 
  * Using parts of the xiafs filesystem.
  * 
@@ -34,9 +34,8 @@
 #define MAX(a,b) (((a)>(b))?(a):(b))
 
 
-static int qnx4_readpage(struct file *file, struct page *page);
-
 #ifdef CONFIG_QNX4FS_RW
+
 static ssize_t qnx4_file_write(struct file *filp, const char *buf,
 			       size_t count, loff_t * ppos)
 {
@@ -145,115 +144,27 @@
 #endif
 
 /*
- * We have moostly NULL's here: the current defaults are ok for
+ * We have mostly NULL's here: the current defaults are ok for
  * the qnx4 filesystem.
  */
 static struct file_operations qnx4_file_operations =
 {
-	NULL,			/* lseek - default */
-	generic_file_read,	/* read */
+	read:		generic_file_read,
 #ifdef CONFIG_QNX4FS_RW
-	qnx4_file_write,	/* write */
-#else
-	NULL,
+	write:		qnx4_file_write,
 #endif
-	NULL,			/* readdir - bad */
-	NULL,			/* poll - default */
-	NULL,			/* ioctl - default */
-	generic_file_mmap,	/* mmap */
-	NULL,			/* no special open is needed */
-        NULL,                   /* no special flush code */
-	NULL,			/* release */
+	mmap:		generic_file_mmap,
 #ifdef CONFIG_QNX4FS_RW   
-	qnx4_sync_file,	        /* fsync */
-#else
-        NULL,
+	fsync:		qnx4_sync_file,
 #endif
-	NULL,			/* fasync */
-	NULL,			/* check_media_change */
-	NULL,			/* revalidate */
-	NULL			/* lock */
 };
 
 struct inode_operations qnx4_file_inode_operations =
 {
-	&qnx4_file_operations,	/* default file operations */
-	NULL,			/* create? It's not a directory */
-	NULL,			/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	qnx4_readpage,		/* readpage */
-	NULL,			/* writepage */
-	qnx4_bmap,	        /* bmap */
+	default_file_ops:	&qnx4_file_operations,
+	readpage:		generic_readpage,
+	bmap:			qnx4_bmap,
 #ifdef CONFIG_QNX4FS_RW
-	qnx4_truncate,		/* truncate */
-#else
-	NULL,
+	truncate:		qnx4_truncate,
 #endif
-	NULL,			/* permission */
-	NULL			/* smap */
 };
-
-static int qnx4_readpage(struct file *file, struct page *page)
-{
-	struct dentry *dentry = file->f_dentry;
-	struct inode *inode = dentry->d_inode;
-	struct qnx4_inode_info *qnx4_ino = &inode->u.qnx4_i;
-	unsigned long buf;
-	unsigned long offset, avail, readlen;
-	unsigned long start;
-	unsigned long count;
-	struct buffer_head *bh;
-	int res = -EIO;
-
-	QNX4DEBUG(("qnx4: readpage offset=[%ld]\n", (long) page->offset));
-
-	if (qnx4_ino->i_xblk != 0) {
-		printk("qnx4: sorry, this file is extended, don't know how to handle it (yet) !\n");
-		return -EIO;
-	}
-	atomic_inc(&page->count);
-	set_bit(PG_locked, &page->flags);
-	buf = page_address(page);
-	clear_bit(PG_uptodate, &page->flags);
-	clear_bit(PG_error, &page->flags);
-	offset = page->offset;
-
-	if (offset < inode->i_size) {
-		res = 0;
-		avail = inode->i_size - offset;
-		readlen = MIN(avail, PAGE_SIZE);
-		start = qnx4_ino->i_first_xtnt.xtnt_blk + (offset >> 9) - 1;
-		count = PAGE_SIZE / QNX4_BLOCK_SIZE;
-		do {
-			QNX4DEBUG(("qnx4: reading page starting at [%ld]\n", (long) start));
-			if ((bh = bread(inode->i_dev, start, QNX4_BLOCK_SIZE)) == NULL) {
-				printk("qnx4: data corrupted or I/O error.\n");
-				res = -EIO;
-			} else {
-				memcpy((void *) buf, bh->b_data, QNX4_BLOCK_SIZE);
-			}
-			buf += QNX4_BLOCK_SIZE;
-			start++;
-			count--;
-		} while (count != 0);
-	}
-	if (res != 0) {
-		set_bit(PG_error, &page->flags);
-		memset((void *) buf, 0, PAGE_SIZE);
-	} else {
-		set_bit(PG_uptodate, &page->flags);
-	}
-	clear_bit(PG_locked, &page->flags);
-	wake_up(&page->wait);
-/*  free_page(buf); */
-
-	return res;
-}
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/fs/qnx4/inode.c linux.15p9/fs/qnx4/inode.c
--- linux.vanilla/fs/qnx4/inode.c	Wed Oct 20 01:12:49 1999
+++ linux.15p9/fs/qnx4/inode.c	Tue Jan 18 00:59:09 2000
@@ -1,7 +1,7 @@
 /* 
  * QNX4 file system, Linux implementation.
  * 
- * Version : 0.1
+ * Version : 0.2.1
  * 
  * Using parts of the xiafs filesystem.
  * 
@@ -127,30 +127,18 @@
 
 static struct super_operations qnx4_sops =
 {
-	qnx4_read_inode,
+	read_inode:		qnx4_read_inode,
 #ifdef CONFIG_QNX4FS_RW
-	qnx4_write_inode,
-#else
-	NULL,
+	write_inode:		qnx4_write_inode,
+	put_inode:		qnx4_put_inode,
+	delete_inode:		qnx4_delete_inode,
 #endif
+	put_super:		qnx4_put_super,
 #ifdef CONFIG_QNX4FS_RW
-	qnx4_put_inode,
-	qnx4_delete_inode,
-	NULL,			/* notify_change */
-#else
-	NULL,			/* put_inode */
-	NULL,			/* delete_inode */
-	NULL,			/* notify_change */
+	write_super:		qnx4_write_super,
 #endif
-	qnx4_put_super,
-#ifdef CONFIG_QNX4FS_RW
-	qnx4_write_super,
-#else
-	NULL,
-#endif
-	qnx4_statfs,
-	qnx4_remount,
-	NULL			/* clear_inode */
+	statfs:			qnx4_statfs,
+	remount_fs:		qnx4_remount,
 };
 
 static int qnx4_remount(struct super_block *sb, int *flags, char *data)
@@ -167,23 +155,16 @@
 	return 0;
 }
 
-struct buffer_head *inode_getblk(struct inode *inode, int nr,
+struct buffer_head *qnx4_getblk(struct inode *inode, int nr,
 				 int create)
 {
-	int tmp;
-	int tst;
 	struct buffer_head *result = NULL;
 
-	tst = nr;
-      repeat:
-	tmp = tst;
-	if (tmp) {
-		result = getblk(inode->i_dev, tmp, QNX4_BLOCK_SIZE);
-		if (tmp == tst) {
-			return result;
-		}
-		brelse(result);
-		goto repeat;
+	if ( nr >= 0 )
+		nr = qnx4_block_map( inode, nr );
+	if (nr) {
+		result = getblk(inode->i_dev, nr, QNX4_BLOCK_SIZE);
+		return result;
 	}
 	if (!create) {
 		return NULL;
@@ -210,7 +191,7 @@
 {
 	struct buffer_head *bh;
 
-	bh = inode_getblk(inode, block, create);
+	bh = qnx4_getblk(inode, block, create);
 	if (!bh || buffer_uptodate(bh)) {
 		return bh;
 	}
@@ -224,19 +205,72 @@
 	return NULL;
 }
 
+unsigned long qnx4_block_map( struct inode *inode, long iblock )
+{
+	int ix;
+	long offset, i_xblk;
+	unsigned long block = 0;
+	struct buffer_head *bh = 0;
+	struct qnx4_xblk *xblk = 0;
+	struct qnx4_inode_info *qnx4_inode = &inode->u.qnx4_i;
+	qnx4_nxtnt_t nxtnt = qnx4_inode->i_num_xtnts;
+
+	if ( iblock < qnx4_inode->i_first_xtnt.xtnt_size ) {
+		// iblock is in the first extent. This is easy.
+		block = qnx4_inode->i_first_xtnt.xtnt_blk + iblock - 1;
+	} else {
+		// iblock is beyond first extent. We have to follow the extent chain.
+		i_xblk = qnx4_inode->i_xblk;
+		offset = iblock - qnx4_inode->i_first_xtnt.xtnt_size;
+		ix = 0;
+		while ( --nxtnt > 0 ) {
+			if ( ix == 0 ) {
+				// read next xtnt block.
+				bh = bread( inode->i_dev, i_xblk - 1, QNX4_BLOCK_SIZE );
+				if ( !bh ) {
+					QNX4DEBUG(("qnx4: I/O error reading xtnt block [%ld])\n", i_xblk - 1));
+					return -EIO;
+				}
+				xblk = (struct qnx4_xblk*)bh->b_data;
+				if ( memcmp( xblk->xblk_signature, "IamXblk", 7 ) ) {
+					QNX4DEBUG(("qnx4: block at %ld is not a valid xtnt\n", qnx4_inode->i_xblk));
+					return -EIO;
+				}
+			}
+			if ( offset < xblk->xblk_xtnts[ix].xtnt_size ) {
+				// got it!
+				block = xblk->xblk_xtnts[ix].xtnt_blk + offset - 1;
+				break;
+			}
+			offset -= xblk->xblk_xtnts[ix].xtnt_size;
+			if ( ++ix >= xblk->xblk_num_xtnts ) {
+				i_xblk = xblk->xblk_next_xblk;
+				ix = 0;
+				brelse( bh );
+				bh = 0;
+			}
+		}
+		if ( bh )
+			brelse( bh );
+	}
+
+	QNX4DEBUG(("qnx4: mapping block %ld of inode %ld = %ld\n",iblock,inode->i_ino,block));
+	return block;
+}
+
 static int qnx4_statfs(struct super_block *sb,
 		       struct statfs *buf, int bufsize)
 {
 	struct statfs tmp;
 
 	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 = 0x00;	/* change this !!! */
-	tmp.f_ffree = qnx4_count_free_inodes(sb);
+	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;
@@ -247,7 +281,7 @@
  * it really _is_ a qnx4 filesystem, and to check the size
  * of the directory entry.
  */
-static const char *qnx4_checkroot(struct super_block *s)
+static const char *qnx4_checkroot(struct super_block *sb)
 {
 	struct buffer_head *bh;
 	struct qnx4_inode_entry *rootdir;
@@ -255,14 +289,14 @@
 	int i, j;
 	int found = 0;
 
-	if (*(s->u.qnx4_sb.sb->RootDir.di_fname) != '/') {
+	if (*(sb->u.qnx4_sb.sb->RootDir.di_fname) != '/') {
 		return "no qnx4 filesystem (no root dir).";
 	} else {
 		QNX4DEBUG(("QNX4 filesystem found on dev %s.\n", kdevname(s->s_dev)));
-		rd = s->u.qnx4_sb.sb->RootDir.di_first_xtnt.xtnt_blk - 1;
-		rl = s->u.qnx4_sb.sb->RootDir.di_first_xtnt.xtnt_size;
+		rd = sb->u.qnx4_sb.sb->RootDir.di_first_xtnt.xtnt_blk - 1;
+		rl = sb->u.qnx4_sb.sb->RootDir.di_first_xtnt.xtnt_size;
 		for (j = 0; j < rl; j++) {
-			bh = bread(s->s_dev, rd + j, QNX4_BLOCK_SIZE);	/* root dir, first block */
+			bh = bread(sb->s_dev, rd + j, QNX4_BLOCK_SIZE);	/* root dir, first block */
 			if (bh == NULL) {
 				return "unable to read root entry.";
 			}
@@ -272,13 +306,12 @@
 					QNX4DEBUG(("Rootdir entry found : [%s]\n", rootdir->di_fname));
 					if (!strncmp(rootdir->di_fname, QNX4_BMNAME, sizeof QNX4_BMNAME)) {
 						found = 1;
-						s->u.qnx4_sb.BitMap = rootdir;	/* keep bitmap inode known */
+						sb->u.qnx4_sb.BitMap = kmalloc( sizeof( struct qnx4_inode_entry ), GFP_KERNEL );
+						memcpy( sb->u.qnx4_sb.BitMap, rootdir, sizeof( struct qnx4_inode_entry ) );	/* keep bitmap inode known */
 						break;
 					}
 				}
 			}
-			/* WAIT! s->u.qnx4_sb.BitMap points into bh->b_data
-			   and now we release bh?? */
 			brelse(bh);
 			if (found != 0) {
 				break;
@@ -376,6 +409,7 @@
 
 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;
 }
@@ -455,7 +489,7 @@
 
 __initfunc(int init_qnx4_fs(void))
 {
-	printk("QNX4 filesystem v0.2 registered.\n");
+	printk("QNX4 filesystem v0.2.1 registered.\n");
 	return register_filesystem(&qnx4_fs_type);
 }
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/fs/qnx4/namei.c linux.15p9/fs/qnx4/namei.c
--- linux.vanilla/fs/qnx4/namei.c	Sat Aug 14 02:26:18 1999
+++ linux.15p9/fs/qnx4/namei.c	Tue Jan 18 00:59:09 2000
@@ -1,7 +1,7 @@
 /* 
  * QNX4 file system, Linux implementation.
  * 
- * Version : 0.1
+ * Version : 0.2.1
  * 
  * Using parts of the xiafs filesystem.
  * 
@@ -33,7 +33,7 @@
 		      struct buffer_head *bh, unsigned long *offset)
 {
 	struct qnx4_inode_entry *de;
-	int namelen;
+	int namelen, thislen;
 
 	if (bh == NULL) {
 		printk("qnx4: matching unassigned buffer !\n");
@@ -41,23 +41,24 @@
 	}
 	de = (struct qnx4_inode_entry *) (bh->b_data + *offset);
 	*offset += QNX4_DIR_ENTRY_SIZE;
-	if ((de->di_status & 0x08) == 0x08) {
+	if ((de->di_status & QNX4_FILE_LINK) != 0) {
 		namelen = QNX4_NAME_MAX;
 	} else {
-		namelen = _SHORT_NAME_MAX;
+		namelen = QNX4_SHORT_NAME_MAX;
 	}
 	/* "" means "." ---> so paths like "/usr/lib//libc.a" work */
 	if (!len && (de->di_fname[0] == '.') && (de->di_fname[1] == '\0')) {
 		return 1;
 	}
-	if (len != strlen(de->di_fname)) {
+	thislen = strlen( de->di_fname );
+	if ( thislen > namelen )
+		thislen = namelen;
+	if (len != thislen) {
 		return 0;
 	}
 	if (strncmp(name, de->di_fname, len) == 0) {
-		if ((de->di_mode) || (de->di_status == QNX4_FILE_LINK)) {
-			if (de->di_status) {
-				return 1;
-			}
+		if ((de->di_status & (QNX4_FILE_USED|QNX4_FILE_LINK)) != 0) {
+			return 1;
 		}
 	}
 	return 0;
@@ -75,19 +76,19 @@
 		return NULL;
 	}
 	bh = NULL;
-	blkofs = dir->u.qnx4_i.i_first_xtnt.xtnt_blk - 1;
-	offset = block = 0;
-	while (block * QNX4_BLOCK_SIZE + offset < dir->i_size) {
+	block = blkofs = offset = 0;
+	while (blkofs * QNX4_BLOCK_SIZE + offset < dir->i_size) {
 		if (!bh) {
-			bh = qnx4_bread(dir, block + blkofs, 0);
+			bh = qnx4_bread(dir, blkofs, 0);
 			if (!bh) {
-				block++;
+				blkofs++;
 				continue;
 			}
 		}
 		*res_dir = (struct qnx4_inode_entry *) (bh->b_data + offset);
 		if (qnx4_match(len, name, bh, &offset)) {
-			*ino = (block + blkofs) * QNX4_INODES_PER_BLOCK +
+			block = qnx4_block_map( dir, blkofs );
+			*ino = block * QNX4_INODES_PER_BLOCK +
 			    (offset / QNX4_DIR_ENTRY_SIZE) - 1;
 			return bh;
 		}
@@ -97,7 +98,7 @@
 		brelse(bh);
 		bh = NULL;
 		offset = 0;
-		block++;
+		blkofs++;
 	}
 	brelse(bh);
 	*res_dir = NULL;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/fs/qnx4/symlinks.c linux.15p9/fs/qnx4/symlinks.c
--- linux.vanilla/fs/qnx4/symlinks.c	Sat Aug 14 02:27:37 1999
+++ linux.15p9/fs/qnx4/symlinks.c	Tue Jan 18 00:59:09 2000
@@ -1,7 +1,7 @@
 /* 
  * QNX4 file system, Linux implementation.
  * 
- * Version : 0.1
+ * Version : 0.2.1
  * 
  * Using parts of the xiafs filesystem.
  * 
@@ -11,8 +11,6 @@
  * 21-06-1998 by Frank Denis : ugly changes to make it compile on Linux 2.1.99+
  */
 
-/* THIS FILE HAS TO BE REWRITTEN */
-
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/fs.h>
@@ -30,49 +28,27 @@
  */
 struct inode_operations qnx4_symlink_inode_operations =
 {
-	NULL,			/* no file-operations */
-	NULL,			/* create */
-	NULL,			/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	qnx4_readlink,		/* readlink */
-	qnx4_follow_link,	/* follow_link */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* bmap */
-	NULL,			/* truncate */
-	NULL			/* permission */
+	readlink:	qnx4_readlink,
+	follow_link:	qnx4_follow_link,
 };
 
 static struct dentry *qnx4_follow_link(struct dentry *dentry,
 				       struct dentry *base, unsigned int follow)
 {
-#if 0
 	struct inode *inode = dentry->d_inode;
 	struct buffer_head *bh;
 
-	if (!inode) {
+	if ( !inode ) {
 		return ERR_PTR(-ENOENT);
 	}
-	if (current->link_count > 5) {
-		return ERR_PTR(-ELOOP);
-	}
-	if (!(bh = qnx4_bread(inode, 0, 0))) {
+	if ( !( bh = qnx4_bread( inode, 0, 0 ) ) ) {
+		dput( base );
 		return ERR_PTR(-EIO);
 	}
-	current->link_count++;
-	current->link_count--;
-	brelse(bh);
-	return 0;
-#else
-	printk("qnx4: qnx4_follow_link needs to be fixed.\n");
-	return ERR_PTR(-EIO);
-#endif
+	UPDATE_ATIME( inode );
+	base = lookup_dentry( bh->b_data, base, follow );
+	brelse( bh );
+	return base;
 }
 
 static int qnx4_readlink(struct dentry *dentry, char *buffer, int buflen)
@@ -81,36 +57,27 @@
 	struct buffer_head *bh;
 	int i;
 	char c;
-	struct qnx4_inode_info *qnx4_ino;
 
 	QNX4DEBUG(("qnx4: qnx4_readlink() called\n"));
 
 	if (buffer == NULL || inode == NULL || !S_ISLNK(inode->i_mode)) {
 		return -EINVAL;
 	}
-	qnx4_ino = &inode->u.qnx4_i;
 	if (buflen > 1023) {
 		buflen = 1023;
 	}
-	bh = bread(inode->i_dev, qnx4_ino->i_first_xtnt.xtnt_blk,
-		   QNX4_BLOCK_SIZE);
+	bh = qnx4_bread( inode, 0, 0 );
 	if (bh == NULL) {
 		QNX4DEBUG(("qnx4: NULL symlink bh\n"));
 		return 0;
 	}
 	QNX4DEBUG(("qnx4: qnx4_bread sym called -> [%s]\n",
 		   bh->b_data));
-	if (bh->b_data[0] != 0) {
-		i = 0;
-		while (i < buflen && (c = bh->b_data[i])) {
-			i++;
-			put_user(c, buffer++);
-		}
-		brelse(bh);
-		return i;
-	} else {
-		brelse(bh);
-		memcpy(buffer, "fixme", 5);
-		return 5;
+	i = 0;
+	while (i < buflen && (c = bh->b_data[i])) {
+		i++;
+		put_user(c, buffer++);
 	}
+	brelse(bh);
+	return i;
 }
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/fs/select.c linux.15p9/fs/select.c
--- linux.vanilla/fs/select.c	Sat Aug 28 20:00:58 1999
+++ linux.15p9/fs/select.c	Wed Feb  9 15:50:56 2000
@@ -39,6 +39,39 @@
  * Linus noticed.  -- jrs
  */
 
+static poll_table* alloc_wait(int nfds)
+{
+	poll_table* out;
+	poll_table* walk;
+
+	out = (poll_table *) __get_free_page(GFP_KERNEL);
+	if(out==NULL)
+		return NULL;
+	out->nr = 0;
+	out->entry = (struct poll_table_entry *)(out + 1);
+	out->next = NULL;
+	nfds -=__MAX_POLL_TABLE_ENTRIES;
+	walk = out;
+	while(nfds > 0) {
+		poll_table *tmp = (poll_table *) __get_free_page(GFP_KERNEL);
+		if (!tmp) {
+			while(out != NULL) {
+				tmp = out->next;
+				free_page((unsigned long)out);
+				out = tmp;
+			}
+			return NULL;
+		}
+		tmp->nr = 0;
+		tmp->entry = (struct poll_table_entry *)(tmp + 1);
+		tmp->next = NULL;
+		walk->next = tmp;
+		walk = tmp;
+		nfds -=__MAX_POLL_TABLE_ENTRIES;
+	}
+	return out;
+}
+
 static void free_wait(poll_table * p)
 {
 	struct poll_table_entry * entry;
@@ -63,7 +96,6 @@
 	for (;;) {
 		if (p->nr < __MAX_POLL_TABLE_ENTRIES) {
 			struct poll_table_entry * entry;
-ok_table:
 		 	entry = p->entry + p->nr;
 		 	entry->filp = filp;
 		 	filp->f_count++;
@@ -74,17 +106,6 @@
 			p->nr++;
 			return;
 		}
-		if (p->next == NULL) {
-			poll_table *tmp = (poll_table *) __get_free_page(GFP_KERNEL);
-			if (!tmp)
-				return;
-			tmp->nr = 0;
-			tmp->entry = (struct poll_table_entry *)(tmp + 1);
-			tmp->next = NULL;
-			p->next = tmp;
-			p = tmp;
-			goto ok_table;
-		}
 		p = p->next;
 	}
 }
@@ -154,23 +175,21 @@
 	long __timeout = *timeout;
 
 	wait = wait_table = NULL;
-	if (__timeout) {
-		wait_table = (poll_table *) __get_free_page(GFP_KERNEL);
-		if (!wait_table)
-			return -ENOMEM;
-
-		wait_table->nr = 0;
-		wait_table->entry = (struct poll_table_entry *)(wait_table + 1);
-		wait_table->next = NULL;
-		wait = wait_table;
-	}
-
 	lock_kernel();
 
 	retval = max_select_fd(n, fds);
 	if (retval < 0)
 		goto out;
 	n = retval;
+	if (__timeout) {
+		retval = -ENOMEM;
+		wait_table = alloc_wait(n);
+		if (!wait_table)
+			goto out;
+
+		wait = wait_table;
+	}
+
 	retval = 0;
 	for (;;) {
 		current->state = TASK_INTERRUPTIBLE;
@@ -406,12 +425,10 @@
 
 	err = -ENOMEM;
 	if (timeout) {
-		wait_table = (poll_table *) __get_free_page(GFP_KERNEL);
+		wait_table = alloc_wait(nfds);
 		if (!wait_table)
 			goto out;
-		wait_table->nr = 0;
-		wait_table->entry = (struct poll_table_entry *)(wait_table + 1);
-		wait_table->next = NULL;
+
 		wait = wait_table;
 	}
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/asm-ppc/gemini_serial.h linux.15p9/include/asm-ppc/gemini_serial.h
--- linux.vanilla/include/asm-ppc/gemini_serial.h	Tue Jan  4 21:19:00 2000
+++ linux.15p9/include/asm-ppc/gemini_serial.h	Mon Feb  7 12:11:32 2000
@@ -7,10 +7,10 @@
 #define BASE_BAUD  (24576000 / 16)
 
 #ifdef CONFIG_SERIAL_DETECT_IRQ
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#define STD_COM_FLAGS (/*ASYNC_BOOT_AUTOCONF|*/ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
 #define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_AUTO_IRQ)
 #else
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
+#define STD_COM_FLAGS (/*ASYNC_BOOT_AUTOCONF|*/ASYNC_SKIP_TEST)
 #define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF)
 #endif
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/asm-s390/atomic.h linux.15p9/include/asm-s390/atomic.h
--- linux.vanilla/include/asm-s390/atomic.h	Tue Jan  4 21:19:00 2000
+++ linux.15p9/include/asm-s390/atomic.h	Thu Feb 17 13:38:52 2000
@@ -28,7 +28,7 @@
 static __inline__ int atomic_read(atomic_t *v)
 {
         int retval;
-        __asm__ __volatile("bcr      15,0\n\t"
+        __asm__ __volatile__("bcr      15,0\n\t"
                            "l        %0,%1"
                            : "=d" (retval) : "m" (*v) );
         return retval;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/asm-s390/irq.h linux.15p9/include/asm-s390/irq.h
--- linux.vanilla/include/asm-s390/irq.h	Tue Jan  4 21:19:00 2000
+++ linux.15p9/include/asm-s390/irq.h	Thu Feb 17 13:38:52 2000
@@ -1,24 +1,735 @@
+#ifndef __irq_h
+#define __irq_h
+
+#include <asm/hardirq.h>
+
+/*
+ * How many IRQ's for S390 ?!?
+ */
+#define __MAX_SUBCHANNELS 65536
+#define NR_IRQS           __MAX_SUBCHANNELS
+
+#define INVALID_STORAGE_AREA ((void *)(-1 - 0x3FFF ))
+
+extern int disable_irq(unsigned int);
+extern int enable_irq(unsigned int);
+
+/*
+ * Interrupt controller descriptor. This is all we need
+ * to describe about the low-level hardware.
+ */
+struct hw_interrupt_type {
+        const char   *typename;
+        int         (*handle)(unsigned int irq,
+                              int cpu,
+                              struct pt_regs * regs);
+        int         (*enable) (unsigned int irq);
+        int         (*disable)(unsigned int irq);
+};
+
+/*
+ * Status: reason for being disabled: somebody has
+ * done a "disable_irq()" or we must not re-enter the
+ * already executing irq..
+ */
+#define IRQ_INPROGRESS  1
+#define IRQ_DISABLED    2
+#define IRQ_PENDING     4
+
+/*
+ * path management control word
+ */
+typedef struct {
+      unsigned long  intparm;      /* interruption parameter */
+      unsigned int   res0 : 2;     /* reserved zeros */
+      unsigned int   isc  : 3;     /* interruption sublass */
+      unsigned int   res5 : 3;     /* reserved zeros */
+      unsigned int   ena  : 1;     /* enabled */
+      unsigned int   lm   : 2;     /* limit mode */
+      unsigned int   mme  : 2;     /* measurement-mode enable */
+      unsigned int   mp   : 1;     /* multipath mode */
+      unsigned int   tf   : 1;     /* timing facility */
+      unsigned int   dnv  : 1;     /* device number valid */
+      unsigned int   dev  : 16;    /* device number */
+      unsigned char  lpm;          /* logical path mask */
+      unsigned char  pnom;         /* path not operational mask */
+      unsigned char  lpum;         /* last path used mask */
+      unsigned char  pim;          /* path installed mask */
+      unsigned short mbi;          /* measurement-block index */
+      unsigned char  pom;          /* path operational mask */
+      unsigned char  pam;          /* path available mask */
+      unsigned char  chpid[8];     /* CHPID 0-7 (if available) */
+      unsigned int   unused1 : 8;  /* reserved zeros */
+      unsigned int   st      : 3;  /* subchannel type */
+      unsigned int   unused2 : 20; /* reserved zeros */
+      unsigned int   csense  : 1;  /* concurrent sense; can be enabled ...*/
+                                   /*  ... per MSCH, however, if facility */
+                                   /*  ... is not installed, this results */
+                                   /*  ... in an operand exception.       */
+   } pmcw_t;
+
+/*
+ * subchannel status word
+ */
+typedef struct {
+      unsigned int   key  : 4; /* subchannel key */
+      unsigned int   sctl : 1; /* suspend control */
+      unsigned int   eswf : 1; /* ESW format */
+      unsigned int   cc   : 2; /* deferred condition code */
+      unsigned int   fmt  : 1; /* format */
+      unsigned int   pfch : 1; /* prefetch */
+      unsigned int   isic : 1; /* initial-status interruption control */
+      unsigned int   alcc : 1; /* address-limit checking control */
+      unsigned int   ssi  : 1; /* supress-suspended interruption */
+      unsigned int   zcc  : 1; /* zero condition code */
+      unsigned int   ectl : 1; /* extended control */
+      unsigned int   pno  : 1;     /* path not operational */
+      unsigned int   res  : 1;     /* reserved */
+      unsigned int   fctl : 3;     /* function control */
+      unsigned int   actl : 7;     /* activity control */
+      unsigned int   stctl : 5;    /* status control */
+      unsigned long  cpa;          /* channel program address */
+      unsigned int   dstat : 8;    /* device status */
+      unsigned int   cstat : 8;    /* subchannel status */
+      unsigned int   count : 16;   /* residual count */
+   } scsw_t;
+
+#define SCSW_FCTL_CLEAR_FUNC     0x1
+#define SCSW_FCTL_HALT_FUNC      0x2
+#define SCSW_FCTL_START_FUNC     0x4
+
+#define SCSW_ACTL_SUSPENDED      0x1
+#define SCSW_ACTL_DEVACT         0x2
+#define SCSW_ACTL_SCHACT         0x4
+#define SCSW_ACTL_CLEAR_PEND     0x8
+#define SCSW_ACTL_HALT_PEND      0x10
+#define SCSW_ACTL_START_PEND     0x20
+#define SCSW_ACTL_RESUME_PEND    0x40
+
+#define SCSW_STCTL_STATUS_PEND   0x1
+#define SCSW_STCTL_SEC_STATUS    0x2
+#define SCSW_STCTL_PRIM_STATUS   0x4
+#define SCSW_STCTL_INTER_STATUS  0x8
+#define SCSW_STCTL_ALERT_STATUS  0x10
+
+#define DEV_STAT_ATTENTION       0x80
+#define DEV_STAT_STAT_MOD        0x40
+#define DEV_STAT_CU_END          0x20
+#define DEV_STAT_BUSY            0x10
+#define DEV_STAT_CHN_END         0x08
+#define DEV_STAT_DEV_END         0x04
+#define DEV_STAT_UNIT_CHECK      0x02
+#define DEV_STAT_UNIT_EXCEP      0x01
+
+#define SCHN_STAT_PCI            0x80
+#define SCHN_STAT_INCORR_LEN     0x40
+#define SCHN_STAT_PROG_CHECK     0x20
+#define SCHN_STAT_PROT_CHECK     0x10
+#define SCHN_STAT_CHN_DATA_CHK   0x08
+#define SCHN_STAT_CHN_CTRL_CHK   0x04
+#define SCHN_STAT_INTF_CTRL_CHK  0x02
+#define SCHN_STAT_CHAIN_CHECK    0x01
+
+/*
+ * subchannel information block
+ */
+typedef struct {
+      pmcw_t pmcw;             /* path management control word */
+      scsw_t scsw;             /* subchannel status word */
+      char mda[12];            /* model dependent area */
+   } schib_t;
+
+typedef struct {
+      char            cmd_code;/* command code */
+      char            flags;   /* flags, like IDA adressing, etc. */
+      unsigned short  count;   /* byte count */
+      void           *cda;     /* data address */
+   } ccw1_t __attribute__ ((aligned(8)));
+
+#define CCW_FLAG_DC             0x80
+#define CCW_FLAG_CC             0x40
+#define CCW_FLAG_SLI            0x20
+#define CCW_FLAG_SKIP           0x10
+#define CCW_FLAG_PCI            0x08
+#define CCW_FLAG_IDA            0x04
+#define CCW_FLAG_SUSPEND        0x02
+
+#define CCW_CMD_BASIC_SENSE     0x04
+#define CCW_CMD_TIC             0x08
+#define CCW_CMD_SENSE_ID        0xE4
+#define CCW_CMD_NOOP            0x03
+#define CCW_CMD_RDC             0x64
+#define CCW_CMD_READ_IPL        0x02
+
+#define SENSE_MAX_COUNT         0x20
+
+/*
+ * architectured values for first sense byte
+ */
+#define SNS0_CMD_REJECT         0x80
+#define SNS_CMD_REJECT          SNS0_CMD_REJECT
+#define SNS0_INTERVENTION_REQ   0x40
+#define SNS0_BUS_OUT_CHECK      0x20
+#define SNS0_EQUIPMENT_CHECK    0x10
+#define SNS0_DATA_CHECK         0x08
+#define SNS0_OVERRUN            0x04
+
+/*
+ * operation request block
+ */
+typedef struct {
+      unsigned long  intparm;  /* interruption parameter */
+      unsigned int   key  : 4; /* flags, like key, suspend control, etc. */
+      unsigned int   spnd : 1; /* suspend control */
+      unsigned int   res1 : 3; /* reserved */
+      unsigned int   fmt  : 1; /* format control */
+      unsigned int   pfch : 1; /* prefetch control */
+      unsigned int   isic : 1; /* initial-status-interruption control */
+      unsigned int   alcc : 1; /* address-limit-checking control */
+      unsigned int   ssic : 1; /* suppress-suspended-interr. control */
+      unsigned int   res2 : 3; /* reserved */
+      unsigned int   lpm  : 8; /* logical path mask */
+      unsigned int   ils  : 1; /* incorrect length */
+      unsigned int   zero : 7; /* reserved zeros */
+      ccw1_t        *cpa;      /* channel program address */
+   }  __attribute__ ((packed,aligned(4))) orb_t;
+
+typedef struct {
+      unsigned int res0  : 4;  /* reserved */
+      unsigned int pvrf  : 1;  /* path-verification-required flag */
+      unsigned int cpt   : 1;  /* channel-path timeout */
+      unsigned int fsavf : 1;  /* Failing storage address validity flag */
+      unsigned int cons  : 1;  /* concurrent-sense */
+      unsigned int res8  : 2;  /* reserved */
+      unsigned int scnt  : 6;  /* sense count if cons == 1 */
+      unsigned int res16 : 16; /* reserved */
+   } erw_t;
+
+/*
+ * subchannel logout area
+ */
+typedef struct {
+      unsigned int res0  : 1;  /* reserved */
+      unsigned int esf   : 7;  /* extended status flags */
+      unsigned int lpum  : 8;  /* last path used mask */
+      unsigned int res16 : 1;  /* reserved */
+      unsigned int fvf   : 5;  /* field-validity flags */
+      unsigned int sacc  : 2;  /* storage access code */
+      unsigned int termc : 2;  /* termination code */
+      unsigned int devsc : 1;  /* device-status check */
+      unsigned int serr  : 1;  /* secondary error */
+      unsigned int ioerr : 1;  /* i/o-error alert */
+      unsigned int seqc  : 3;  /* sequence code */
+   } sublog_t ;
+
+/*
+ * Format 0 Extended Status Word (ESW)
+ */
+typedef struct {
+      sublog_t      sublog;    /* subchannel logout */
+      erw_t         erw;       /* extended report word */
+      void         *faddr;     /* failing address */
+      unsigned int  zeros[2];  /* 2 fullwords of zeros */
+   } esw0_t;
+
+/*
+ * Format 1 Extended Status Word (ESW)
+ */
+typedef struct {
+      unsigned char  zero0;    /* reserved zeros */
+      unsigned char  lpum;     /* last path used mask */
+      unsigned short zero16;   /* reserved zeros */
+      erw_t          erw;      /* extended report word */
+      unsigned int   zeros[3]; /* 2 fullwords of zeros */
+   } esw1_t;
+
+/*
+ * Format 2 Extended Status Word (ESW)
+ */
+typedef struct {
+      unsigned char  zero0;    /* reserved zeros */
+      unsigned char  lpum;     /* last path used mask */
+      unsigned short dcti;     /* device-connect-time interval */
+      erw_t          erw;      /* extended report word */
+      unsigned int   zeros[3]; /* 2 fullwords of zeros */
+   } esw2_t;
+
+/*
+ * Format 3 Extended Status Word (ESW)
+ */
+typedef struct {
+      unsigned char  zero0;    /* reserved zeros */
+      unsigned char  lpum;     /* last path used mask */
+      unsigned short res;      /* reserved */
+      erw_t          erw;      /* extended report word */
+      unsigned int   zeros[3]; /* 2 fullwords of zeros */
+   } esw3_t;
+
+typedef union {
+      esw0_t esw0;
+      esw1_t esw1;
+      esw2_t esw2;
+      esw3_t esw3;
+   } esw_t;
+
+/*
+ * interruption response block
+ */
+typedef struct {
+      scsw_t scsw;             /* subchannel status word */
+      esw_t  esw;              /* extended status word */
+      char   ecw[32];          /* extended control word */
+   } irb_t __attribute__ ((aligned(4)));
+
+/*
+ * TPI info structure
+ */
+typedef struct {
+      unsigned int res : 16;   /* reserved 0x00000001 */
+      unsigned int irq : 16;   /* aka. subchannel number */
+      unsigned int intparm;    /* interruption parameter */
+   } tpi_info_t;
+
+
+/*
+ * This is the "IRQ descriptor", which contains various information
+ * about the irq, including what kind of hardware handling it has,
+ * whether it is disabled etc etc.
+ *
+ * Pad this out to 32 bytes for cache and indexing reasons.
+ */
+typedef struct {
+      unsigned int              status;    /* IRQ status - IRQ_INPROGRESS, IRQ_DISABLED */
+      struct hw_interrupt_type *handler;   /* handle/enable/disable functions */
+      struct irqaction         *action;    /* IRQ action list */
+      unsigned int              unused[3];
+      spinlock_t                irq_lock;
+   } irq_desc_t;
+
+//
+// command information word  (CIW) layout
+//
+typedef struct _ciw {
+   unsigned int et       :  2; // entry type
+   unsigned int reserved :  2; // reserved
+   unsigned int ct       :  4; // command type
+   unsigned int cmd      :  8; // command
+   unsigned int count    : 16; // count
+   } ciw_t;
+
+#define CIW_TYPE_RCD    0x0    // read configuration data
+#define CIW_TYPE_SII    0x1    // set interface identifier
+#define CIW_TYPE_RNI    0x2    // read node identifier
+
+//
+// sense-id response buffer layout
+//
+typedef struct {
+  /* common part */
+      unsigned char  reserved;     /* always 0x'FF' */
+      unsigned short cu_type;      /* control unit type */
+      unsigned char  cu_model;     /* control unit model */
+      unsigned short dev_type;     /* device type */
+      unsigned char  dev_model;    /* device model */
+      unsigned char  unused;       /* padding byte */
+  /* extended part */
+      ciw_t    ciw[62];            /* variable # of CIWs */
+   }  __attribute__ ((packed,aligned(4))) senseid_t;
+
+/*
+ * sense data
+ */
+typedef struct {
+      unsigned char res[32];   /* reserved   */
+      unsigned char data[32];  /* sense data */
+   } sense_t;
+
 /*
- *  include/asm-s390/irq.h
+ * device status area, to be provided by the device driver
+ *  when calling request_irq() as parameter "dev_id", later
+ *  tied to the "action" control block.
  *
- *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Note : No data area must be added after union ii or the
+ *         effective devstat size calculation will fail !
+ */
+typedef struct {
+     unsigned int  devno;    /* device number, aka. "cuu" from irb */
+     unsigned int  intparm;  /* interrupt parameter */
+     unsigned char cstat;    /* channel status - accumulated */
+     unsigned char dstat;    /* device status - accumulated */
+     unsigned char lpum;     /* last path used mask from irb */
+     unsigned char unused;   /* not used - reserved */
+     unsigned int  flag;     /* flag : see below */
+     unsigned long cpa;      /* CCW address from irb at primary status */
+     unsigned int  rescnt;   /* res. count from irb at primary status */
+     unsigned int  scnt;     /* sense count, if DEVSTAT_FLAG_SENSE_AVAIL */
+     union {
+        irb_t   irb;         /* interruption response block */
+        sense_t sense;       /* sense information */
+        } ii;                /* interrupt information */
+  } devstat_t;
+
+#define DEVSTAT_FLAG_SENSE_AVAIL   0x00000001
+#define DEVSTAT_NOT_OPER           0x00000002
+#define DEVSTAT_START_FUNCTION     0x00000004
+#define DEVSTAT_HALT_FUNCTION      0x00000008
+#define DEVSTAT_STATUS_PENDING     0x00000010
+#define DEVSTAT_DEVICE_OWNED       0x00000080
+#define DEVSTAT_FINAL_STATUS       0x80000000
+
+/*
+ * Flags used as input parameters for do_IO()
+ */
+#define DOIO_EARLY_NOTIFICATION 0x01    /* allow for I/O completion ... */
+                                        /* ... notification after ... */
+                                        /* ... primary interrupt status */
+#define DOIO_RETURN_CHAN_END       DOIO_EARLY_NOTIFICATION
+#define DOIO_VALID_LPM          0x02    /* LPM input parameter is valid */
+#define DOIO_WAIT_FOR_INTERRUPT 0x04    /* wait synchronously for interrupt */
+#define DOIO_REPORT_ALL         0x08    /* report all interrupt conditions */
+#define DOIO_ALLOW_SUSPEND      0x10    /* allow for channel prog. suspend */
+#define DOIO_DENY_PREFETCH      0x20    /* don't allow for CCW prefetch */
+#define DOIO_SUPPRESS_INTER     0x40    /* suppress intermediate inter. */
+                                        /* ... for suspended CCWs */
+
+/*
+ * do_IO()
  *
- *  Derived from "include/asm-i386/irq.h"
- *    Copyright (C) 1992, 1993 Linus Torvalds, (C) 1997 Ingo Molnar
+ * Start a S/390 channel program. When the interrupt arrives
+ *  handle_IRQ_event() is called, which eventually calls the
+ *  IRQ handler, either immediately, delayed (dev-end missing,
+ *  or sense required) or never (no IRQ handler registered -
+ *  should never occur, as the IRQ (subchannel ID) should be
+ *  disabled if no handler is present. Depending on the action
+ *  taken, do_IO() returns :  0      - Success
+ *                           -EIO    - Status pending
+ *                                        see : action->dev_id->cstat
+ *                                              action->dev_id->dstat
+ *                           -EBUSY  - Device busy
+ *                           -ENODEV - Device not operational
  */
+int do_IO( int            irq,          /* IRQ aka. subchannel number */
+           ccw1_t        *cpa,          /* logical channel program address */
+           unsigned long  initparm,     /* interruption parameter */
+           unsigned char  lpm,          /* logical path mask */
+           unsigned long  flag);        /* flags : see above */
+
+int start_IO( int            irq,       /* IRQ aka. subchannel number */
+              ccw1_t        *cpa,       /* logical channel program address */
+              unsigned long  intparm,   /* interruption parameter */
+              unsigned char  lpm,       /* logical path mask */
+              unsigned long  flag);     /* flags : see above */
+
+int resume_IO( int irq);                /* IRQ aka. subchannel number */
+
+int halt_IO( int           irq,      /* IRQ aka. subchannel number */
+             unsigned long intparm,  /* dummy intparm */
+             unsigned int  flag);    /* possible DOIO_WAIT_FOR_INTERRUPT */
+
+
+int process_IRQ( struct pt_regs regs,
+                 unsigned int   irq,
+                 unsigned int   intparm);
+
+
+int enable_cpu_sync_isc ( int irq );
+int disable_cpu_sync_isc( int irq );
+
+typedef struct {
+     int          irq;                  /* irq, aka. subchannel */
+     unsigned int devno;                /* device number */
+     unsigned int status;               /* device status */
+     senseid_t    sid_data;             /* senseID data */
+     } dev_info_t;
+
+int get_dev_info( int irq, dev_info_t *);   /* to be eliminated - don't use */
+
+int get_dev_info_by_irq  ( int irq, dev_info_t *pdi);
+int get_dev_info_by_devno( unsigned int devno, dev_info_t *pdi);
+
+int          get_irq_by_devno( unsigned int devno );
+unsigned int get_devno_by_irq( int irq );
+
+int get_irq_first( void );
+int get_irq_next ( int irq );
 
-#ifndef _ASM_IRQ_H
-#define _ASM_IRQ_H
+int read_dev_chars( int irq, void **buffer, int length );
+int read_conf_data( int irq, void **buffer, int *length );
 
-#define TIMER_IRQ 0x1005
+extern int handle_IRQ_event(unsigned int, int cpu, struct pt_regs *);
+
+extern int set_cons_dev(int irq);
+extern int reset_cons_dev(int irq);
+extern int wait_cons_dev(int irq);
 
 /*
- * How many IRQ's for S390 ?!?
+ * Some S390 specific IO instructions as inline
  */
-#define NR_IRQS 1024
 
-extern int disable_irq(unsigned int);
-extern int enable_irq(unsigned int);
+extern __inline__ int stsch(int irq, volatile schib_t *addr)
+{
+        int ccode;
+
+        __asm__ __volatile__(
+                "LR 1,%1\n\t"
+                "STSCH 0(%2)\n\t"
+                "IPM %0\n\t"
+                "SRL %0,28\n\t"
+                : "=d" (ccode) : "r" (irq | 0x10000L), "a" (addr)
+                : "cc", "1" );
+        return ccode;
+}
+
+extern __inline__ int msch(int irq, volatile schib_t *addr)
+{
+        int ccode;
+
+        __asm__ __volatile__(
+                "LR 1,%1\n\t"
+                "MSCH 0(%2)\n\t"
+                "IPM %0\n\t"
+                "SRL %0,28\n\t"
+                : "=d" (ccode) : "r" (irq | 0x10000L), "a" (addr)
+                : "cc", "1" );
+        return ccode;
+}
+
+extern __inline__ int msch_err(int irq, volatile schib_t *addr)
+{
+        int ccode;
+
+        __asm__ __volatile__(
+                "    lr   1,%1\n"
+                "    msch 0(%2)\n"
+                "0:  ipm  %0\n"
+                "    srl  %0,28\n"
+                "1:\n"
+                ".section .fixup,\"ax\"\n"
+                "2:  l    %0,%3\n"
+                "    bras 1,3f\n"
+                "    .long 1b\n"
+                "3:  l    1,0(1)\n"
+                "    br   1\n"
+                ".previous\n"
+                ".section __ex_table,\"a\"\n"
+                "   .align 4\n"
+                "   .long 0b,2b\n"
+                ".previous"
+                : "=d" (ccode)
+                : "r" (irq | 0x10000L), "a" (addr), "i" (__LC_PGM_ILC)
+                : "cc", "1" );
+        return ccode;
+}
+
+extern __inline__ int tsch(int irq, volatile irb_t *addr)
+{
+        int ccode;
+
+        __asm__ __volatile__(
+                "LR 1,%1\n\t"
+                "TSCH 0(%2)\n\t"
+                "IPM %0\n\t"
+                "SRL %0,28\n\t"
+                : "=d" (ccode) : "r" (irq | 0x10000L), "a" (addr)
+                : "cc", "1" );
+        return ccode;
+}
+
+extern __inline__ int tpi( volatile tpi_info_t *addr)
+{
+        int ccode;
+
+        __asm__ __volatile__(
+                "TPI 0(%1)\n\t"
+                "IPM %0\n\t"
+                "SRL %0,28\n\t"
+                : "=d" (ccode) : "a" (addr)
+                : "cc", "1" );
+        return ccode;
+}
+
+extern __inline__ int ssch(int irq, volatile orb_t *addr)
+{
+        int ccode;
+
+        __asm__ __volatile__(
+                "LR 1,%1\n\t"
+                "SSCH 0(%2)\n\t"
+                "IPM %0\n\t"
+                "SRL %0,28\n\t"
+                : "=d" (ccode) : "r" (irq | 0x10000L), "a" (addr)
+                : "cc", "1" );
+        return ccode;
+}
+
+extern __inline__ int rsch(int irq)
+{
+        int ccode;
+
+        __asm__ __volatile__(
+                "LR 1,%1\n\t"
+                "RSCH\n\t"
+                "IPM %0\n\t"
+                "SRL %0,28\n\t"
+                : "=d" (ccode) : "r" (irq | 0x10000L)
+                : "cc", "1" );
+        return ccode;
+}
+
+extern __inline__ int csch(int irq)
+{
+        int ccode;
+
+        __asm__ __volatile__(
+                "LR 1,%1\n\t"
+                "CSCH\n\t"
+                "IPM %0\n\t"
+                "SRL %0,28\n\t"
+                : "=d" (ccode) : "r" (irq | 0x10000L)
+                : "cc", "1" );
+        return ccode;
+}
+
+extern __inline__ int hsch(int irq)
+{
+        int ccode;
+
+        __asm__ __volatile__(
+                "LR 1,%1\n\t"
+                "HSCH\n\t"
+                "IPM %0\n\t"
+                "SRL %0,28\n\t"
+                : "=d" (ccode) : "r" (irq | 0x10000L)
+                : "cc", "1" );
+        return ccode;
+}
+
+extern __inline__ int iac( void)
+{
+        int ccode;
+
+        __asm__ __volatile__(
+                "IAC 1\n\t"
+                "IPM %0\n\t"
+                "SRL %0,28\n\t"
+                : "=d" (ccode) : : "cc", "1" );
+        return ccode;
+}
+
+typedef struct {
+     unsigned int vrdcdvno : 16;   /* device number (input) */
+     unsigned int vrdclen  : 16;   /* data block length (input) */
+     unsigned int vrdcvcla : 8;    /* virtual device class (output) */
+     unsigned int vrdcvtyp : 8;    /* virtual device type (output) */
+     unsigned int vrdcvsta : 8;    /* virtual device status (output) */
+     unsigned int vrdcvfla : 8;    /* virtual device flags (output) */
+     unsigned int vrdcrccl : 8;    /* real device class (output) */
+     unsigned int vrdccrty : 8;    /* real device type (output) */
+     unsigned int vrdccrmd : 8;    /* real device model (output) */
+     unsigned int vrdccrft : 8;    /* real device feature (output) */
+     } __attribute__ ((packed,aligned(4))) diag210_t;
+
+void VM_virtual_device_info( unsigned int  devno, /* device number */
+                             senseid_t    *ps );  /* ptr to senseID data */
+
+extern __inline__ int diag210( diag210_t * addr)
+{
+        int ccode;
+
+        __asm__ __volatile__(
+                "LR 1,%1\n\t"
+                ".long 0x83110210\n\t"
+                "IPM %0\n\t"
+                "SRL %0,28\n\t"
+                : "=d" (ccode) : "a" (addr)
+                : "cc", "1" );
+        return ccode;
+}
+
+/*
+ * Various low-level irq details needed by irq.c, process.c,
+ * time.c, io_apic.c and smp.c
+ *
+ * Interrupt entry/exit code at both C and assembly level
+ */
+
+void mask_irq(unsigned int irq);
+void unmask_irq(unsigned int irq);
+
+#define MAX_IRQ_SOURCES 128
+
+extern spinlock_t irq_controller_lock;
+
+#ifdef __SMP__
+
+#include <asm/atomic.h>
+
+static inline void irq_enter(int cpu, unsigned int irq)
+{
+        hardirq_enter(cpu);
+        while (test_bit(0,&global_irq_lock)) {
+                eieio();
+        }
+}
+
+static inline void irq_exit(int cpu, unsigned int irq)
+{
+        hardirq_exit(cpu);
+        release_irqlock(cpu);
+}
+
+
+#else
+
+#define irq_enter(cpu, irq)     (++local_irq_count[cpu])
+#define irq_exit(cpu, irq)      (--local_irq_count[cpu])
+
+#endif
+
+#define __STR(x) #x
+#define STR(x) __STR(x)
+
+#ifdef __SMP__
+
+/*
+ *      SMP has a few special interrupts for IPI messages
+ */
+
+#endif /* __SMP__ */
+
+/*
+ * x86 profiling function, SMP safe. We might want to do this in
+ * assembly totally?
+ */
+extern unsigned long _stext;
+static inline void s390_do_profile (unsigned long addr)
+{
+        if (prof_buffer && current->pid) {
+                addr &= 0x7fffffff;
+                addr -= (unsigned long) &_stext;
+                addr >>= prof_shift;
+                /*
+                 * Don't ignore out-of-bounds EIP values silently,
+                 * put them into the last histogram slot, so if
+                 * present, they will show up as a sharp peak.
+                 */
+                if (addr > prof_len-1)
+                        addr = prof_len-1;
+                atomic_inc((atomic_t *)&prof_buffer[addr]);
+        }
+}
+
+#include <asm/s390io.h>
+
+#define s390irq_spin_lock(irq) \
+        spin_lock(&(ioinfo[irq]->irq_desc.irq_lock))
+
+#define s390irq_spin_unlock(irq) \
+        spin_unlock(&(ioinfo[irq]->irq_desc.irq_lock))
+
+#define s390irq_spin_lock_irqsave(irq,flags) \
+        spin_lock_irqsave(&(ioinfo[irq]->irq_desc.irq_lock), flags)
+#define s390irq_spin_unlock_irqrestore(irq,flags) \
+        spin_unlock_irqrestore(&(ioinfo[irq]->irq_desc.irq_lock), flags)
+#endif
 
-#endif /* _ASM_IRQ_H */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/asm-s390/lowcore.h linux.15p9/include/asm-s390/lowcore.h
--- linux.vanilla/include/asm-s390/lowcore.h	Tue Jan  4 21:19:00 2000
+++ linux.15p9/include/asm-s390/lowcore.h	Thu Feb 17 13:38:52 2000
@@ -2,7 +2,7 @@
  *  include/asm-s390/lowcore.h
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Hartmut Penner (hp@de.ibm.com),
  *               Martin Schwidefsky (schwidefsky@de.ibm.com),
  *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
@@ -28,6 +28,7 @@
 #define __LC_PGM_ILC                    0x08C
 #define __LC_PGM_INT_CODE               0x08E
 #define __LC_TRANS_EXC_ADDR             0x090
+#define __LC_SUBCHANNEL_ID              0x0B8
 #define __LC_SUBCHANNEL_NR              0x0BA
 #define __LC_IO_INT_PARM                0x0BC
 #define __LC_MCCK_CODE                  0x0E8
@@ -54,7 +55,7 @@
 #define _IO_PSW_MASK         0x04080000
 #define _USER_PSW_MASK       0x070DC000/* DAT, IO, EXT, Home-space         */
 #define _PSW_IO_WAIT         0x020A0000/* IO, Wait */
-#define _WAIT_PSW_MASK       0x070EC000/* DAT, IO, EXT, Wait, Home-space   */
+#define _WAIT_PSW_MASK       0x070E0000/* DAT, IO, EXT, Wait, Home-space   */
 #define _DW_PSW_MASK         0x000A0000/* disabled wait PSW mask           */
 #define _PRIMARY_MASK        0x0000    /* MASK for SACF                    */
 #define _SECONDARY_MASK      0x0100    /* MASK for SACF                    */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/asm-s390/pgtable.h linux.15p9/include/asm-s390/pgtable.h
--- linux.vanilla/include/asm-s390/pgtable.h	Tue Jan  4 21:19:00 2000
+++ linux.15p9/include/asm-s390/pgtable.h	Thu Feb 17 13:38:52 2000
@@ -2,7 +2,7 @@
  *  include/asm-s390/pgtable.h
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Hartmut Penner
  *
  *  Derived from "include/asm-i386/pgtable.h"
@@ -284,7 +284,7 @@
  * The Kernel segment-tables includes the User segment-table
  */
 
-#define _SEGMENT_TABLE  (_USER_SEG_TABLE_LEN)
+#define _SEGMENT_TABLE  (_USER_SEG_TABLE_LEN|0x80000000)
 #define _KERNSEG_TABLE  (_KERNEL_SEG_TABLE_LEN)
 /*
  * No mapping available
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/asm-s390/s390-regs-common.h linux.15p9/include/asm-s390/s390-regs-common.h
--- linux.vanilla/include/asm-s390/s390-regs-common.h	Tue Jan  4 21:19:00 2000
+++ linux.15p9/include/asm-s390/s390-regs-common.h	Thu Feb 17 13:38:52 2000
@@ -2,7 +2,7 @@
  *  include/asm-s390/s390-regs-common.h
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
  *
  *  this file is designed to keep as much compatibility between
@@ -84,8 +84,11 @@
 
 
 /* Sequence of bytes for breakpoint illegal instruction.  */
-#define BREAKPOINT {0x0,0x1}
-#define BREAKPOINT_U16 ((__u16)0x0001)
+#define S390_BREAKPOINT {0x0,0x1}
+#define S390_BREAKPOINT_U16 ((__u16)0x0001)
+#define S390_SYSCALL_OPCODE ((__u16)0x0a00)
+#define S390_SYSCALL_SIZE   2
+#define ADDR_BITS_REMOVE(addr) ((addr)&0x7fffffff)
 #endif
 #endif
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/asm-s390/s390io.h linux.15p9/include/asm-s390/s390io.h
--- linux.vanilla/include/asm-s390/s390io.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/include/asm-s390/s390io.h	Thu Feb 17 13:38:52 2000
@@ -0,0 +1,81 @@
+/*
+ *  arch/s390/kernel/s390io.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Ingo Adlung (adlung@de.ibm.com)
+ */
+
+#ifndef __s390io_h
+#define __s390io_h
+
+/*
+ * Private data structure used by do_IO()
+ *
+ * Note : If bit flags are added, the "unused" value must be
+ *        decremented accordingly !
+ */
+typedef struct _ioinfo {
+     unsigned int  irq;           /* aka. subchannel number */
+     spinlock_t    irq_lock;      /* irq lock */
+     union {
+        unsigned int info;
+        struct {
+           unsigned int  busy      : 1;  /* device currently in use */
+           unsigned int  oper      : 1;  /* device is operational */
+           unsigned int  fast      : 1;  /* post with "channel end", ...    */
+                                         /* ... don't wait for "device end" */
+                                         /* ... from do_IO() parameters     */
+           unsigned int  ready     : 1;  /* interrupt handler registered */
+           unsigned int  haltio    : 1;  /* halt_IO in process */
+           unsigned int  doio      : 1;  /* do_IO in process */
+           unsigned int  doio_q    : 1;  /* do_IO queued - only possible ... */
+                                         /* ... if 'fast' is set too */
+           unsigned int  w4final   : 1;  /* wait for final status, internally */
+                                         /* ... used with 'fast' setting only */
+           unsigned int  repall    : 1;  /* report every interrupt status */
+           unsigned int  unready   : 1;  /* deregister irq handler in process */
+           unsigned int  d_disable : 1;  /* delayed disabling required */
+           unsigned int  w4sense   : 1;  /* SENSE status pending */
+           unsigned int  syncio    : 1;  /* synchronous I/O requested */
+           unsigned int  consns    : 1;  /* concurrent sense is available */
+           unsigned int  delsense  : 1;  /* delayed SENSE required */
+           unsigned int  s_pend    : 1;  /* status pending condition */
+           unsigned int  unused    : 16; /* unused */
+              } __attribute__ ((packed)) flags;
+        } ui;
+     unsigned long u_intparm;     /* user interruption parameter */
+     senseid_t     senseid;       /* SenseID info */
+     irq_desc_t    irq_desc;      /* irq descriptor */
+     unsigned int  lpm;           /* logical path mask to be used ... */
+                                  /* ... from do_IO() parms. Only ... */
+                                  /* ... valid if vlpm is set too.    */
+     schib_t       schib;         /* subchannel information block */
+     orb_t         orb;           /* operation request block */
+     devstat_t     devstat;       /* device status */
+     ccw1_t       *qcpa;          /* queued channel program */
+     ccw1_t        senseccw;      /* ccw for sense command */
+     unsigned int  stctl;         /* accumulated status control from irb */
+     unsigned int  qintparm;      /* queued interruption parameter  */
+     unsigned long qflag;         /* queued flags */
+     unsigned char qlpm;          /* queued logical path mask */
+
+     struct _ioinfo *prev;
+     struct _ioinfo *next;
+
+   } __attribute__ ((aligned(8))) ioinfo_t;
+
+#define IOINFO_FLAGS_BUSY    0x80000000
+#define IOINFO_FLAGS_OPER    0x40000000
+#define IOINFO_FLAGS_FAST    0x20000000
+#define IOINFO_FLAGS_READY   0x10000000
+#define IOINFO_FLAGS_HALTIO  0x08000000
+#define IOINFO_FLAGS_DOIO    0x04000000
+#define IOINFO_FLAGS_DOIO_Q  0x02000000
+#define IOINFO_FLAGS_W4FINAL 0x01000000
+#define IOINFO_FLAGS_REPALL  0x00800000
+
+extern ioinfo_t *ioinfo[];
+
+#endif  /* __s390io_h */
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/asm-s390/setup.h linux.15p9/include/asm-s390/setup.h
--- linux.vanilla/include/asm-s390/setup.h	Tue Jan  4 21:19:00 2000
+++ linux.15p9/include/asm-s390/setup.h	Thu Feb 17 13:38:52 2000
@@ -2,7 +2,7 @@
  *  include/asm-s390/setup.h
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  */
 
 #ifndef _ASM_S390_SETUP_H
@@ -40,6 +40,7 @@
  */
 #define MACHINE_IS_VM    (MACHINE_FLAGS & 1)
 #define MACHINE_HAS_IEEE (MACHINE_FLAGS & 2)
+#define MACHINE_IS_P390  (MACHINE_FLAGS & 4)
 
 #define RAMDISK_ORIGIN            0x800000
 #define RAMDISK_BLKSIZE           0x1000
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/asm-s390/sigcontext.h linux.15p9/include/asm-s390/sigcontext.h
--- linux.vanilla/include/asm-s390/sigcontext.h	Tue Jan  4 21:19:00 2000
+++ linux.15p9/include/asm-s390/sigcontext.h	Thu Feb 17 13:38:52 2000
@@ -2,14 +2,12 @@
  *  include/asm-s390/sigcontext.h
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  */
 
 #ifndef _ASM_S390_SIGCONTEXT_H
 #define _ASM_S390_SIGCONTEXT_H
-
-#include <asm/ptrace.h>
-
+#include <asm/s390-regs-common.h>
 
 /*
   Has to be at least _NSIG_WORDS from asm/signal.h
@@ -20,11 +18,19 @@
 #define __SIGNAL_FRAMESIZE      STACK_FRAME_OVERHEAD
 #define _SIGCONTEXT_NSIG_WORDS  (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
 #define SIGMASK_COPY_SIZE       (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS)
-struct sigcontext_struct {
-	int		signal;
-	unsigned long	handler;
-	user_regs_struct *regs;
+
+typedef struct
+{
+	s390_regs_common regs;
+	s390_fp_regs     fpregs;
+} sigregs;
+
+struct sigcontext
+{
 	unsigned long	oldmask[_SIGCONTEXT_NSIG_WORDS];
+	sigregs         *sregs;
 };
 
+
 #endif
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/asm-s390/uaccess.h linux.15p9/include/asm-s390/uaccess.h
--- linux.vanilla/include/asm-s390/uaccess.h	Tue Jan  4 21:19:00 2000
+++ linux.15p9/include/asm-s390/uaccess.h	Thu Feb 17 13:38:52 2000
@@ -2,7 +2,7 @@
  *  include/asm-s390/uaccess.h
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Hartmut Penner (hp@de.ibm.com),
  *               Martin Schwidefsky (schwidefsky@de.ibm.com)
  *
@@ -321,6 +321,20 @@
         __gu_err;                                               \
 })
 
+/*
+ * The "xxx_ret" versions return constant specified in third argument, if
+ * something bad happens. These macros can be optimized for the
+ * case of just returning from the function xxx_ret is used.
+ */
+
+#define put_user_ret(x,ptr,ret) ({ if (put_user(x,ptr)) return ret; })
+
+#define get_user_ret(x,ptr,ret) ({ if (get_user(x,ptr)) return ret; })
+
+#define __put_user_ret(x,ptr,ret) ({ if (__put_user(x,ptr)) return ret; })
+
+#define __get_user_ret(x,ptr,ret) ({ if (__get_user(x,ptr)) return ret; })
+
 extern int __get_user_bad(void);
 
 /*
@@ -427,30 +441,28 @@
                                 "   sacf  512\n"
                                 "0: ic    3,0(%0,4)\n"
                                 "1: stc   3,0(%0,2)\n"
-                                "   ahi   %0,1\n"
-                                "   cr    %0,%3\n"
-                                "   je    2f\n"
                                 "   ltr   3,3\n"
-                                "   jne   0b\n"
+                                "   jz    2f\n"
+                                "   ahi   %0,1\n"
+                                "   clr   %0,%3\n"
+                                "   jl    0b\n"
                                 "2: sacf  0(1)\n"
-				"3:\n"
 				".section .fixup,\"ax\"\n"
-				"4: sacf  0(1)\n"
-                                "   lhi   %0,%h4\n"
-				"   bras  3,5f\n"
-				"   .long 3b\n"
-				"5: l     3,0(3)\n"
+                                "3: lhi   %0,%h4\n"
+				"   basr  3,0\n"
+                                "   l     3,4f-.(3)\n"
 				"   br    3\n"
+				"4: .long 2b\n"
 				".previous\n"
 				".section __ex_table,\"a\"\n"
 				"   .align 4\n"
-				"   .long  0b,4b\n"
-				"   .long  1b,4b\n"
+				"   .long  0b,3b\n"
+                                "   .long  1b,3b\n"
 				".previous"
                                 : "=&a" (len)
                                 : "a"  (dst), "d" (src), "d" (count),
                                   "K" (-EFAULT)
-                                : "1", "2" ,"3", "4" );
+                                : "1", "2", "3", "4", "memory" );
         return len;
 }
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/asm-s390/ucontext.h linux.15p9/include/asm-s390/ucontext.h
--- linux.vanilla/include/asm-s390/ucontext.h	Tue Jan  4 21:19:00 2000
+++ linux.15p9/include/asm-s390/ucontext.h	Thu Feb 17 13:38:52 2000
@@ -16,4 +16,6 @@
 	sigset_t	  uc_sigmask;	/* mask last for extensibility */
 };
 
+
+
 #endif /* !_ASM_S390_UCONTEXT_H */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/asm-sparc/ethtool.h linux.15p9/include/asm-sparc/ethtool.h
--- linux.vanilla/include/asm-sparc/ethtool.h	Thu Mar 11 00:53:37 1999
+++ linux.15p9/include/asm-sparc/ethtool.h	Mon Feb  7 12:29:22 2000
@@ -1,7 +1,7 @@
-/* $Id: ethtool.h,v 1.1 1998/12/19 15:09:38 davem Exp $
+/* $Id: ethtool.h,v 1.1.2.1 2000/01/31 05:02:42 davem Exp $
  * ethtool.h: Defines for SparcLinux ethtool.
  *
- * Copyright (C) 1998 David S. Miller (davem@dm.cobaltmicro.com)
+ * Copyright (C) 1998 David S. Miller (davem@redhat.com)
  */
 
 #ifndef _SPARC_ETHTOOL_H
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/asm-sparc/pcic.h linux.15p9/include/asm-sparc/pcic.h
--- linux.vanilla/include/asm-sparc/pcic.h	Sun Oct  4 18:22:44 1998
+++ linux.15p9/include/asm-sparc/pcic.h	Fri Jan 21 17:50:18 2000
@@ -1,5 +1,5 @@
-/* $Id: pcic.h,v 1.1 1998/09/22 05:54:39 jj Exp $
- * pcic.h: JavaEngine 1 specific PCI definitions.
+/* $Id: pcic.h,v 1.1.2.1 2000/01/21 01:05:56 davem Exp $
+ * pcic.h: MicroSPARC-IIep specific PCI definitions.
  *
  * Copyright (C) 1998 V. Roganov and G. Raiko
  */
@@ -7,6 +7,8 @@
 #ifndef __SPARC_PCIC_H
 #define __SPARC_PCIC_H
 
+#ifndef __ASSEMBLY__
+
 #include <linux/types.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
@@ -21,13 +23,17 @@
         unsigned long           pcic_config_space_addr;
         unsigned long           pcic_config_space_data;
         struct linux_pbm_info   pbm;
+	struct pcic_ca2irq	*pcic_imap;
+	int			pcic_imdim;
 };
 
 extern unsigned long pcic_alloc_io(unsigned long* addr);
 extern void pcic_probe(void);
 extern void sun4m_pci_init_IRQ(void);
 
-/* Size of PCI Space */
+#endif
+
+/* Size of PCI I/O space which we relocate. */
 #define PCI_SPACE_SIZE                  0x1000000       /* 16 MB */
 
 /* PCIC Register Set. */
@@ -50,10 +56,18 @@
 #define PCI_SOFTWARE_INT_CLEAR          0x6a    /* 16 bits */
 #define PCI_SOFTWARE_INT_SET            0x6e    /* 16 bits */
 #define PCI_SYS_INT_PENDING             0x70    /* 32 bits */
+#define  PCI_SYS_INT_PENDING_PIO		0x40000000
+#define  PCI_SYS_INT_PENDING_DMA		0x20000000
+#define  PCI_SYS_INT_PENDING_PCI		0x10000000
+#define  PCI_SYS_INT_PENDING_APSR		0x08000000
 #define PCI_SYS_INT_TARGET_MASK         0x74    /* 32 bits */
 #define PCI_SYS_INT_TARGET_MASK_CLEAR   0x78    /* 32 bits */
 #define PCI_SYS_INT_TARGET_MASK_SET     0x7c    /* 32 bits */
 #define PCI_SYS_INT_PENDING_CLEAR       0x83    /* 8  bits */
+#define  PCI_SYS_INT_PENDING_CLEAR_ALL		0x80
+#define  PCI_SYS_INT_PENDING_CLEAR_PIO		0x40
+#define  PCI_SYS_INT_PENDING_CLEAR_DMA		0x20
+#define  PCI_SYS_INT_PENDING_CLEAR_PCI		0x10
 #define PCI_IOTLB_CONTROL               0x84    /* 8  bits */
 #define PCI_INT_SELECT_LO               0x88    /* 16 bits */
 #define PCI_ARBITRATION_SELECT          0x8a    /* 16 bits */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/asm-sparc64/ethtool.h linux.15p9/include/asm-sparc64/ethtool.h
--- linux.vanilla/include/asm-sparc64/ethtool.h	Thu Mar 11 00:53:38 1999
+++ linux.15p9/include/asm-sparc64/ethtool.h	Mon Feb  7 12:29:22 2000
@@ -1,7 +1,7 @@
-/* $Id: ethtool.h,v 1.1 1998/12/19 15:09:40 davem Exp $
+/* $Id: ethtool.h,v 1.1.2.1 2000/01/31 05:02:43 davem Exp $
  * ethtool.h: Defines for SparcLinux ethtool.
  *
- * Copyright (C) 1998 David S. Miller (davem@dm.cobaltmicro.com)
+ * Copyright (C) 1998 David S. Miller (davem@redhat.com)
  */
 
 #ifndef _SPARC64_ETHTOOL_H
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/asm-sparc64/floppy.h linux.15p9/include/asm-sparc64/floppy.h
--- linux.vanilla/include/asm-sparc64/floppy.h	Sat Aug 28 20:00:58 1999
+++ linux.15p9/include/asm-sparc64/floppy.h	Fri Jan 14 15:56:16 2000
@@ -1,4 +1,4 @@
-/* $Id: floppy.h,v 1.18.2.2 1999/08/09 21:07:41 ecd Exp $
+/* $Id: floppy.h,v 1.18.2.3 2000/01/09 18:29:32 ecd Exp $
  * asm-sparc64/floppy.h: Sparc specific parts of the Floppy driver.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -574,7 +574,6 @@
 		struct linux_ebus_device *edev = 0;
 		unsigned long config = 0;
 		unsigned long auxio_reg;
-		unsigned char cfg;
 
 		for_each_ebus(ebus) {
 			for_each_ebusdev(edev, ebus) {
@@ -678,9 +677,7 @@
 			return sun_floppy_types[0];
 
 		/* Enable PC-AT mode. */
-		cfg = ns87303_readb(config, ASC);
-		cfg |= 0xc0;
-		ns87303_writeb(config, ASC, cfg);
+		ns87303_modify(config, ASC, 0, 0xc0);
 
 #ifdef PCI_FDC_SWAP_DRIVES
 		/*
@@ -691,15 +688,9 @@
 			 * Set the drive exchange bit in FCR on NS87303,
 			 * make shure other bits are sane before doing so.
 			 */
-			cfg = ns87303_readb(config, FER);
-			cfg &= ~(FER_EDM);
-			ns87303_writeb(config, FER, cfg);
-			cfg = ns87303_readb(config, ASC);
-			cfg &= ~(ASC_DRV2_SEL);
-			ns87303_writeb(config, ASC, cfg);
-			cfg = ns87303_readb(config, FCR);
-			cfg |= FCR_LDE;
-			ns87303_writeb(config, FCR, cfg);
+			ns87303_modify(config, FER, FER_EDM, 0);
+			ns87303_modify(config, ASC, ASC_DRV2_SEL, 0);
+			ns87303_modify(config, FCR, 0, FCR_LDE);
 
 			cfg = sun_floppy_types[0];
 			sun_floppy_types[0] = sun_floppy_types[1];
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/asm-sparc64/io.h linux.15p9/include/asm-sparc64/io.h
--- linux.vanilla/include/asm-sparc64/io.h	Sun Oct  4 18:22:44 1998
+++ linux.15p9/include/asm-sparc64/io.h	Fri Jan 14 15:56:16 2000
@@ -1,4 +1,4 @@
-/* $Id: io.h,v 1.19 1998/08/23 05:41:46 ecd Exp $ */
+/* $Id: io.h,v 1.19.2.1 2000/01/14 03:55:36 davem Exp $ */
 #ifndef __SPARC64_IO_H
 #define __SPARC64_IO_H
 
@@ -120,12 +120,66 @@
 extern void insl(unsigned long addr, void *dst, unsigned long count);
 
 /* Memory functions, same as I/O accesses on Ultra. */
-#define readb(addr)		inb((unsigned long)(addr))
-#define readw(addr)		inw((unsigned long)(addr))
-#define readl(addr)		inl((unsigned long)(addr))
-#define writeb(b, addr)		outb((b), (unsigned long)(addr))
-#define writew(w, addr)		outw((w), (unsigned long)(addr))
-#define writel(l, addr)		outl((l), (unsigned long)(addr))
+extern __inline__ unsigned int _readb(unsigned long addr)
+{
+	unsigned int ret;
+
+	__asm__ __volatile__("lduba [%1] %2, %0"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PL));
+
+	return ret;
+}
+
+extern __inline__ unsigned int _readw(unsigned long addr)
+{
+	unsigned int ret;
+
+	__asm__ __volatile__("lduha [%1] %2, %0"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PL));
+
+	return ret;
+}
+
+extern __inline__ unsigned int _readl(unsigned long addr)
+{
+	unsigned int ret;
+
+	__asm__ __volatile__("lduwa [%1] %2, %0"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PL));
+
+	return ret;
+}
+
+extern __inline__ void _writeb(unsigned char b, unsigned long addr)
+{
+	__asm__ __volatile__("stba %0, [%1] %2"
+			     : /* no outputs */
+			     : "r" (b), "r" (addr), "i" (ASI_PL));
+}
+
+extern __inline__ void _writew(unsigned short w, unsigned long addr)
+{
+	__asm__ __volatile__("stha %0, [%1] %2"
+			     : /* no outputs */
+			     : "r" (w), "r" (addr), "i" (ASI_PL));
+}
+
+extern __inline__ void _writel(unsigned int l, unsigned long addr)
+{
+	__asm__ __volatile__("stwa %0, [%1] %2"
+			     : /* no outputs */
+			     : "r" (l), "r" (addr), "i" (ASI_PL));
+}
+
+#define readb(addr)		_readb((unsigned long)(addr))
+#define readw(addr)		_readw((unsigned long)(addr))
+#define readl(addr)		_readl((unsigned long)(addr))
+#define writeb(b, addr)		_writeb((b), (unsigned long)(addr))
+#define writew(w, addr)		_writew((w), (unsigned long)(addr))
+#define writel(l, addr)		_writel((l), (unsigned long)(addr))
 
 /*
  * Memcpy to/from I/O space is just a regular memory operation on
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/asm-sparc64/ns87303.h linux.15p9/include/asm-sparc64/ns87303.h
--- linux.vanilla/include/asm-sparc64/ns87303.h	Sun Oct  4 18:22:44 1998
+++ linux.15p9/include/asm-sparc64/ns87303.h	Fri Jan 14 15:56:16 2000
@@ -1,4 +1,4 @@
-/* $Id: ns87303.h,v 1.2 1998/09/13 15:38:50 ecd Exp $
+/* $Id: ns87303.h,v 1.2.2.1 2000/01/09 18:29:33 ecd Exp $
  * ns87303.h: Configuration Register Description for the
  *            National Semiconductor PC87303 (SuperIO).
  *
@@ -45,7 +45,7 @@
 #define FCR_LDE		0x10	/* Logical Drive Exchange                    */
 #define FCR_ZWS_ENA	0x20	/* Enable short host read/write in ECP/EPP   */
 
-/* Printer Controll Register (PCR) bits */
+/* Printer Control Register (PCR) bits */
 #define PCR_EPP_ENABLE	0x01
 #define PCR_EPP_IEEE	0x02	/* Enable EPP Version 1.9 (IEEE 1284)        */
 #define PCR_ECP_ENABLE	0x04
@@ -61,27 +61,51 @@
 #define ASC_LPT_IRQ7	0x01	/* Allways use IRQ7 for LPT                  */
 #define ASC_DRV2_SEL	0x02	/* Logical Drive Exchange controlled by TDR  */
 
+#define FER_RESERVED	0x00
+#define FAR_RESERVED	0x00
+#define PTR_RESERVED	0x73
+#define FCR_RESERVED	0xc4
+#define PCR_RESERVED	0x10
+#define KRR_RESERVED	0x00
+#define PMC_RESERVED	0x98
+#define TUP_RESERVED	0xfb
+#define SIP_RESERVED	0x00
+#define ASC_RESERVED	0x18
+#define CS0CF0_RESERVED	0x00
+#define CS0CF1_RESERVED	0x08
+#define CS1CF0_RESERVED	0x00
+#define CS1CF1_RESERVED	0x08
+
 #ifdef __KERNEL__
 
 #include <asm/system.h>
 #include <asm/io.h>
 
-static __inline__ void ns87303_writeb(unsigned long port, int index,
-				     unsigned char value)
+static __inline__ int ns87303_modify(unsigned long port, unsigned int index,
+				     unsigned char clr, unsigned char set)
 {
+	static unsigned char reserved[] = {
+		FER_RESERVED, FAR_RESERVED, PTR_RESERVED, FCR_RESERVED,
+		PCR_RESERVED, KRR_RESERVED, PMC_RESERVED, TUP_RESERVED,
+		SIP_RESERVED, ASC_RESERVED, CS0CF0_RESERVED, CS0CF1_RESERVED,
+		CS1CF0_RESERVED, CS1CF1_RESERVED
+	};
 	unsigned long flags;
+	unsigned char value;
+
+	if (index > 0x0d)
+		return -EINVAL;
 
 	save_flags(flags); cli();
 	outb(index, port);
+	value = inb(port + 1);
+	value &= ~(reserved[index] | clr);
+	value |= set;
 	outb(value, port + 1);
 	outb(value, port + 1);
 	restore_flags(flags);
-}
 
-static __inline__ unsigned char ns87303_readb(unsigned long port, int index)
-{
-	outb(index, port);
-	return inb(port + 1);
+	return 0;
 }
 
 #endif /* __KERNEL__ */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/linux/apm_bios.h linux.15p9/include/linux/apm_bios.h
--- linux.vanilla/include/linux/apm_bios.h	Tue Jan  4 21:19:02 2000
+++ linux.15p9/include/linux/apm_bios.h	Wed Feb 16 18:35:25 2000
@@ -3,7 +3,7 @@
 
 /*
  * Include file for the interface to an APM BIOS
- * Copyright 1994-1999 Stephen Rothwell (sfr@linuxcare.com)
+ * Copyright 1994-2000 Stephen Rothwell (sfr@linuxcare.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
@@ -46,46 +46,61 @@
 #define APM_BIOS_DISENGAGED     0x0010
 
 /*
- * Maximum number of events stored
+ * The APM function codes
  */
-#define APM_MAX_EVENTS		20
-
-/*
- * The per-file APM data
- */
-struct apm_bios_struct {
-	int		magic;
-	struct apm_bios_struct *	next;
-	int		suser;
-	int		suspends_pending;
-	int		standbys_pending;
-	int		suspends_read;
-	int		standbys_read;
-	int		event_head;
-	int		event_tail;
-	apm_event_t	events[APM_MAX_EVENTS];
-};
-
-/*
- * The magic number in apm_bios_struct
- */
-#define APM_BIOS_MAGIC		0x4101
+#define	APM_FUNC_INST_CHECK	0x5300
+#define	APM_FUNC_REAL_CONN	0x5301
+#define	APM_FUNC_16BIT_CONN	0x5302
+#define	APM_FUNC_32BIT_CONN	0x5303
+#define	APM_FUNC_DISCONN	0x5304
+#define	APM_FUNC_IDLE		0x5305
+#define	APM_FUNC_BUSY		0x5306
+#define	APM_FUNC_SET_STATE	0x5307
+#define	APM_FUNC_ENABLE_PM	0x5308
+#define	APM_FUNC_RESTORE_BIOS	0x5309
+#define	APM_FUNC_GET_STATUS	0x530a
+#define	APM_FUNC_GET_EVENT	0x530b
+#define	APM_FUNC_GET_STATE	0x530c
+#define	APM_FUNC_ENABLE_DEV_PM	0x530d
+#define	APM_FUNC_VERSION	0x530e
+#define	APM_FUNC_ENGAGE_PM	0x530f
+#define	APM_FUNC_GET_CAP	0x5310
+#define	APM_FUNC_RESUME_TIMER	0x5311
+#define	APM_FUNC_RESUME_ON_RING	0x5312
+#define	APM_FUNC_TIMER		0x5313
+
+/*
+ * Function code for APM_FUNC_RESUME_TIMER
+ */
+#define	APM_FUNC_DISABLE_TIMER	0
+#define	APM_FUNC_GET_TIMER	1
+#define	APM_FUNC_SET_TIMER	2
+
+/*
+ * Function code for APM_FUNC_RESUME_ON_RING
+ */
+#define	APM_FUNC_DISABLE_RING	0
+#define	APM_FUNC_ENABLE_RING	1
+#define	APM_FUNC_GET_RING	2
+
+/*
+ * Function code for APM_FUNC_TIMER_STATUS
+ */
+#define	APM_FUNC_TIMER_DISABLE	0
+#define	APM_FUNC_TIMER_ENABLE	1
+#define	APM_FUNC_TIMER_GET	2
 
 /*
  * in init/main.c
  */
 extern struct apm_bios_info	apm_bios_info;
 
-extern void		apm_bios_init(void);
+extern void		apm_init(void);
 extern void		apm_setup(char *, int *);
 
 extern int		apm_register_callback(int (*callback)(apm_event_t));
 extern void		apm_unregister_callback(int (*callback)(apm_event_t));
 
-extern void		apm_power_off(void);
-extern int		apm_display_blank(void);
-extern int		apm_display_unblank(void);
-
 #endif	/* __KERNEL__ */
 
 /*
@@ -97,6 +112,14 @@
 #define APM_STATE_OFF		0x0003
 #define APM_STATE_BUSY		0x0004
 #define APM_STATE_REJECT	0x0005
+#define APM_STATE_OEM_SYS	0x0020
+#define APM_STATE_OEM_DEV	0x0040
+
+#define APM_STATE_DISABLE	0x0000
+#define APM_STATE_ENABLE	0x0001
+
+#define APM_STATE_DISENGAGE	0x0000
+#define APM_STATE_ENGAGE	0x0001
 
 /*
  * Events (results of Get PM Event)
@@ -112,7 +135,7 @@
 #define APM_USER_STANDBY	0x0009
 #define APM_USER_SUSPEND	0x000a
 #define APM_STANDBY_RESUME	0x000b
-#define APM_CAPABILITY_CHANGE   0x000c
+#define APM_CAPABILITY_CHANGE	0x000c
 
 /*
  * Error codes
@@ -128,14 +151,58 @@
 #define APM_BAD_DEVICE		0x09
 #define APM_BAD_PARAM		0x0a
 #define APM_NOT_ENGAGED		0x0b
-#define APM_BAD_FUNCTION        0x0c
+#define APM_BAD_FUNCTION	0x0c
 #define APM_RESUME_DISABLED	0x0d
 #define APM_NO_ERROR		0x53
 #define APM_BAD_STATE		0x60
 #define APM_NO_EVENTS		0x80
 #define APM_NOT_PRESENT		0x86
 
-/* ioctl operations */
+/*
+ * APM Device IDs
+ */
+#define APM_DEVICE_BIOS		0x0000
+#define APM_DEVICE_ALL		0x0001
+#define APM_DEVICE_DISPLAY	0x0100
+#define APM_DEVICE_STORAGE	0x0200
+#define APM_DEVICE_PARALLEL	0x0300
+#define APM_DEVICE_SERIAL	0x0400
+#define APM_DEVICE_NETWORK	0x0500
+#define APM_DEVICE_PCMCIA	0x0600
+#define APM_DEVICE_BATTERY	0x8000
+#define APM_DEVICE_OEM		0xe000
+#define APM_DEVICE_OLD_ALL	0xffff
+#define APM_DEVICE_CLASS	0x00ff
+#define APM_DEVICE_MASK		0xff00
+
+#ifdef __KERNEL__
+/*
+ * This is the "All Devices" ID communicated to the BIOS
+ */
+#define APM_DEVICE_BALL		((apm_bios_info.version > 0x0100) ? \
+				 APM_DEVICE_ALL : APM_DEVICE_OLD_ALL)
+#endif
+
+/*
+ * Battery status
+ */
+#define APM_MAX_BATTERIES	2
+
+/*
+ * APM defined capability bit flags
+ */
+#define APM_CAP_GLOBAL_STANDBY		0x0001
+#define APM_CAP_GLOBAL_SUSPEND		0x0002
+#define APM_CAP_RESUME_STANDBY_TIMER	0x0004 /* Timer resume from standby */
+#define APM_CAP_RESUME_SUSPEND_TIMER	0x0008 /* Timer resume from suspend */
+#define APM_CAP_RESUME_STANDBY_RING	0x0010 /* Resume on Ring fr standby */
+#define APM_CAP_RESUME_SUSPEND_RING	0x0020 /* Resume on Ring fr suspend */
+#define APM_CAP_RESUME_STANDBY_PCMCIA	0x0040 /* Resume on PCMCIA Ring	*/
+#define APM_CAP_RESUME_SUSPEND_PCMCIA	0x0080 /* Resume on PCMCIA Ring	*/
+
+/*
+ * ioctl operations
+ */
 #include <linux/ioctl.h>
 
 #define APM_IOC_STANDBY		_IO('A', 1)
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/linux/cd1400.h linux.15p9/include/linux/cd1400.h
--- linux.vanilla/include/linux/cd1400.h	Wed Feb  4 22:52:16 1998
+++ linux.15p9/include/linux/cd1400.h	Mon Feb  7 12:07:56 2000
@@ -4,7 +4,7 @@
  *	cd1400.h  -- cd1400 UART hardware info.
  *
  *	Copyright (C) 1996-1998  Stallion Technologies (support@stallion.oz.au).
- *	Copyright (C) 1994-1996  Greg Ungerer (gerg@stallion.oz.au).
+ *	Copyright (C) 1994-1996  Greg Ungerer.
  *
  *	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
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/linux/cdk.h linux.15p9/include/linux/cdk.h
--- linux.vanilla/include/linux/cdk.h	Wed Feb  4 22:52:16 1998
+++ linux.15p9/include/linux/cdk.h	Mon Feb  7 12:07:56 2000
@@ -4,7 +4,7 @@
  *	cdk.h  -- CDK interface definitions.
  *
  *	Copyright (C) 1996-1998  Stallion Technologies (support@stallion.oz.au).
- *	Copyright (C) 1994-1996  Greg Ungerer (gerg@stallion.oz.au).
+ *	Copyright (C) 1994-1996  Greg Ungerer.
  *
  *	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
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/linux/compatmac.h linux.15p9/include/linux/compatmac.h
--- linux.vanilla/include/linux/compatmac.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/include/linux/compatmac.h	Wed Feb 16 20:44:53 2000
@@ -0,0 +1,163 @@
+  /* 
+   * This header tries to allow you to write 2.3-compatible drivers, 
+   * but (using this header) still allows you to run them on 2.2 and 
+   * 2.0 kernels. 
+   *
+   * Sometimes, a #define replaces a "construct" that older kernels
+   * had. For example, 
+   *
+   *       DECLARE_MUTEX(name);
+   *
+   * replaces the older 
+   *
+   *       struct semaphore name = MUTEX;
+   *
+   * This file then declares the DECLARE_MUTEX macro to compile into the 
+   * older version. 
+   * 
+   * In some cases, a macro or function changes the number of arguments.
+   * In that case, there is nothing we can do except define an access 
+   * macro that provides the same functionality on both versions of Linux. 
+   * 
+   * This is the case for example with the "get_user" macro 2.0 kernels use:
+   *
+   *          a = get_user (b);
+   *  
+   * while newer kernels use 
+   * 
+   *          get_user (a,b);
+   *
+   * This is unfortunate. We therefore define "Get_user (a,b)" which looks
+   * almost the same as the 2.2+ construct, and translates into the 
+   * appropriate sequence for earlier constructs. 
+   * 
+   * Supported by this file are the 2.0 kernels, 2.2 kernels, and the 
+   * most recent 2.3 kernel. 2.3 support will be dropped as soon when 2.4
+   * comes out. 2.0 support may someday be dropped. But then again, maybe 
+   * not. 
+   *
+   * I'll try to maintain this, provided that Linus agrees with the setup. 
+   * Feel free to mail updates or suggestions. 
+   *
+   * -- R.E.Wolff@BitWizard.nl
+   *
+   */
+
+#ifndef COMPATMAC_H
+#define COMPATMAC_H
+
+#include <linux/version.h>
+
+#if LINUX_VERSION_CODE < 0x020100    /* Less than 2.1.0 */
+#define TWO_ZERO
+#else
+#if LINUX_VERSION_CODE < 0x020200   /* less than 2.2.x */
+#warning "Please use a 2.2.x kernel. "
+#else
+#if LINUX_VERSION_CODE < 0x020300   /* less than 2.3.x */
+#define TWO_TWO
+#else
+#define TWO_THREE
+#endif
+#endif
+#endif
+
+#ifdef TWO_ZERO
+
+/* Here is the section that makes the 2.2 compatible driver source 
+   work for 2.0 too! We mostly try to adopt the "new thingies" from 2.2, 
+   and provide for compatibility stuff here if possible. */
+
+/* Some 200 days (on intel) */
+#define MAX_SCHEDULE_TIMEOUT     ((long)(~0UL>>1))
+
+#include <linux/bios32.h>
+
+#define Get_user(a,b)                a = get_user(b)
+#define Put_user(a,b)                0,put_user(a,b)
+#define copy_to_user(a,b,c)          memcpy_tofs(a,b,c)
+
+static inline int copy_from_user(void *to,const void *from, int c) 
+{
+  memcpy_fromfs(to, from, c);
+  return 0;
+}
+
+#define pci_present                  pcibios_present
+#define pci_read_config_word         pcibios_read_config_word
+#define pci_read_config_dword        pcibios_read_config_dword
+
+static inline unsigned char get_irq (unsigned char bus, unsigned char fn)
+{
+	unsigned char t; 
+	pcibios_read_config_byte (bus, fn, PCI_INTERRUPT_LINE, &t);
+	return t;
+}
+
+static inline void *ioremap(unsigned long base, long length)
+{
+	if (base < 0x100000) return (void *)base;
+	return vremap (base, length);
+}
+
+#define my_iounmap(x, b)             (((long)x<0x100000)?0:vfree ((void*)x))
+
+#define capable(x)                   suser()
+
+#define queue_task                   queue_task_irq_off
+#define tty_flip_buffer_push(tty)    queue_task(&tty->flip.tqueue, &tq_timer)
+#define signal_pending(current)      (current->signal & ~current->blocked)
+#define schedule_timeout(to)         do {current->timeout = jiffies + (to);schedule ();} while (0)
+#define time_after(t1,t2)            (((long)t1-t2) > 0)
+
+
+#define test_and_set_bit(nr, addr)   set_bit(nr, addr)
+#define test_and_clear_bit(nr, addr) clear_bit(nr, addr)
+
+/* Not yet implemented on 2.0 */
+#define ASYNC_SPD_SHI  -1
+#define ASYNC_SPD_WARP -1
+
+
+/* Ugly hack: the driver_name doesn't exist in 2.0.x . So we define it
+   to the "name" field that does exist. As long as the assignments are
+   done in the right order, there is nothing to worry about. */
+#define driver_name           name 
+
+/* Should be in a header somewhere. They are in tty.h on 2.2 */
+#define TTY_HW_COOK_OUT       14 /* Flag to tell ntty what we can handle */
+#define TTY_HW_COOK_IN        15 /* in hardware - output and input       */
+
+/* The return type of a "close" routine. */
+#define INT                   void
+#define NO_ERROR              /* Nothing */
+
+#else
+
+/* The 2.2.x compatibility section. */
+#include <asm/uaccess.h>
+
+
+#define Get_user(a,b)         get_user(a,b)
+#define Put_user(a,b)         put_user(a,b)
+#define get_irq(pdev)         pdev->irq
+
+#define INT                   int
+#define NO_ERROR              0
+
+#define my_iounmap(x,b)       (iounmap((char *)(b)))
+
+#endif
+
+#ifndef TWO_THREE
+/* These are new in 2.3. The source now uses 2.3 syntax, and here is 
+   the compatibility define... */
+#define wait_queue_head_t     struct wait_queue *
+#define DECLARE_MUTEX(name)   struct semaphore name = MUTEX
+#define DECLARE_WAITQUEUE(wait, current) \
+                              struct wait_queue wait = { current, NULL }
+
+#endif
+
+
+#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/linux/comstats.h linux.15p9/include/linux/comstats.h
--- linux.vanilla/include/linux/comstats.h	Wed Feb  4 22:52:16 1998
+++ linux.15p9/include/linux/comstats.h	Mon Feb  7 12:07:56 2000
@@ -4,7 +4,7 @@
  *	comstats.h  -- Serial Port Stats.
  *
  *	Copyright (C) 1996-1998  Stallion Technologies (support@stallion.oz.au).
- *	Copyright (C) 1994-1996  Greg Ungerer (gerg@stallion.oz.au).
+ *	Copyright (C) 1994-1996  Greg Ungerer.
  *
  *	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
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/linux/cpia.h linux.15p9/include/linux/cpia.h
--- linux.vanilla/include/linux/cpia.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/include/linux/cpia.h	Mon Feb  7 12:30:39 2000
@@ -0,0 +1,220 @@
+#ifndef cpia_h
+#define cpia_h
+
+/*
+ * CPiA Parallel Port Video4Linux driver
+ *
+ * Supports CPiA based parallel port Video Camera's.
+ *
+ * (C) Copyright 1999 Bas Huisman,
+ *                    Peter Pregler,
+ *                    Scott J. Bertin,
+ *                    VLSI Vision Ltd.
+ *
+ * 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.
+ */
+
+#define CPIA_MAJ_VER	0
+#define CPIA_MIN_VER    5
+#define CPIA_PATCH_VER	0
+
+#define CPIA_PP_MAJ_VER       0
+#define CPIA_PP_MIN_VER       5
+#define CPIA_PP_PATCH_VER     0
+
+#define CPIA_MAX_FRAME_SIZE_UNALIGNED	(352 * 288 * 4)   /* CIF at RGB32 */
+#define CPIA_MAX_FRAME_SIZE	((CPIA_MAX_FRAME_SIZE_UNALIGNED + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)) /* align above to PAGE_SIZE */
+
+#ifdef __KERNEL__
+
+#include <asm/uaccess.h>
+
+struct cpia_camera_ops
+{
+	/* open sets privdata to point to structure for this camera.
+         * Returns negative value on error, otherwise 0.
+	 */
+	int (*open)(int camnr, void **privdata);
+	
+	/* Registers callback function cb to be called with cbdata
+	 * when an image is ready.  If cb is NULL, only single image grabs
+	 * should be used.  cb should immediately call streamRead to read
+	 * the data or data may be lost. Returns negative value on error,
+	 * otherwise 0.
+	 */
+	int (*registerCallback)(void *privdata, void (*cb)(void *cbdata),
+	                        void *cbdata);
+	
+	/* transferCmd sends commands to the camera.  command MUST point to
+	 * an  8 byte buffer in kernel space. data can be NULL if no extra
+	 * data is needed.  The size of the data is given by the last 2
+	 * bytes of comand.  data must also point to memory in kernel space.
+	 * Returns negative value on error, otherwise 0.
+	 */
+	int (*transferCmd)(void *privdata, u8 *command, u8 *data);
+
+	/* streamStart initiates stream capture mode.
+	 * Returns negative value on error, otherwise 0.
+	 */
+	int (*streamStart)(void *privdata);
+	
+	/* streamStop terminates stream capture mode.
+	 * Returns negative value on error, otherwise 0.
+	 */
+	int (*streamStop)(void *privdata);
+        
+	/* streamRead reads a frame from the camera.  buffer points to a
+         * buffer large enough to hold a complete frame in kernel space.
+         * noblock indicates if this should be a non blocking read.
+	 * Returns the number of bytes read, or negative value on error.
+         */
+	int (*streamRead)(void *privdata, u8 *buffer, int noblock);
+	
+	/* close disables the device until open() is called again.
+	 * Returns negative value on error, otherwise 0.
+	 */
+	int (*close)(void *privdata);
+};
+
+/* cpia_register_camera is called by low level driver for each camera.
+ * A unique camera number is returned, or a negative value on error */
+int cpia_register_camera(struct cpia_camera_ops *ops);
+
+/* cpia_unregister_camera is called by low level driver when a camera
+ * is removed.  This must not fail. */
+void cpia_unregister_camera(int camnr);
+
+#define CPIA_MAXCAMS		4
+
+/* raw CIF + 64 byte header + (2 bytes line_length + EOL) per line + 4*EOI +
+ * one byte 16bit DMA alignment
+ */
+#define CPIA_MAX_IMAGE_SIZE ((352*288*2)+64+(288*3)+5)
+
+/* constant value's */
+#define MAGIC_0		0x19
+#define MAGIC_1		0x68
+#define DATA_IN		0xC0
+#define DATA_OUT	0x40
+#define VIDEOSIZE_QCIF	0	/* 176x144 */
+#define VIDEOSIZE_CIF	1	/* 352x288 */
+#define VIDEOSIZE_SIF	2	/* 320x240 */
+#define VIDEOSIZE_QSIF	3	/* 160x120 */
+#define VIDEOSIZE_48_48		4 /* where no one has gone before, iconsize! */
+#define VIDEOSIZE_64_48		5
+#define VIDEOSIZE_128_96	6
+#define VIDEOSIZE_160_120	VIDEOSIZE_QSIF
+#define VIDEOSIZE_176_144	VIDEOSIZE_QCIF
+#define VIDEOSIZE_192_144	7
+#define VIDEOSIZE_224_168	8
+#define VIDEOSIZE_256_192	9
+#define VIDEOSIZE_288_216	10
+#define VIDEOSIZE_320_240	VIDEOSIZE_SIF
+#define VIDEOSIZE_352_288	VIDEOSIZE_CIF
+#define SUBSAMPLE_420	0
+#define SUBSAMPLE_422	1
+#define YUVORDER_YUYV	0
+#define YUVORDER_UYVY	1
+#define NOT_COMPRESSED	0
+#define COMPRESSED	1
+#define NO_DECIMATION	0
+#define DECIMATION_ENAB	1
+#define EOI		0xff	/* End Of Image */
+#define EOL		0xfd	/* End Of Line */
+
+/* Image grab modes */
+#define CPIA_GRAB_SINGLE	0
+#define CPIA_GRAB_CONTINUOUS	1
+
+/* Compression parameters */
+#define CPIA_COMPRESSION_NONE	0
+#define CPIA_COMPRESSION_AUTO	1
+#define CPIA_COMPRESSION_MANUAL	2
+#define CPIA_COMPRESSION_TARGET_QUALITY         0
+#define CPIA_COMPRESSION_TARGET_FRAMERATE       1
+
+/* Return offsets for GetCameraState */
+#define SYSTEMSTATE	0
+#define GRABSTATE	1
+#define STREAMSTATE	2
+#define FATALERROR	3
+#define CMDERROR	4
+#define DEBUGFLAGS	5
+#define VPSTATUS	6
+#define ERRORCODE	7
+
+/* SystemState */
+#define UNINITIALISED_STATE	0
+#define PASS_THROUGH_STATE	1
+#define LO_POWER_STATE		2
+#define HI_POWER_STATE		3
+#define WARM_BOOT_STATE		4
+
+/* GrabState */
+#define GRAB_IDLE		0
+#define GRAB_ACTIVE		1
+#define GRAB_DONE		2
+
+/* StreamState */
+#define STREAM_NOT_READY	0
+#define STREAM_READY		1
+#define STREAM_OPEN		2
+#define STREAM_PAUSED		3
+#define STREAM_FINISHED		4
+
+/* Fatal Error, CmdError, and DebugFlags */
+#define CPIA_FLAG	  1
+#define SYSTEM_FLAG	  2
+#define INT_CTRL_FLAG	  4
+#define PROCESS_FLAG	  8
+#define COM_FLAG	 16
+#define VP_CTRL_FLAG	 32
+#define CAPTURE_FLAG	 64
+#define DEBUG_FLAG	128
+
+/* VPStatus */
+#define VP_STATE_OK			0x00
+
+#define VP_STATE_FAILED_VIDEOINIT	0x01
+#define VP_STATE_FAILED_AECACBINIT	0x02
+#define VP_STATE_AEC_MAX		0x04
+#define VP_STATE_ACB_BMAX		0x08
+
+#define VP_STATE_ACB_RMIN		0x10
+#define VP_STATE_ACB_GMIN		0x20
+#define VP_STATE_ACB_RMAX		0x40
+#define VP_STATE_ACB_GMAX		0x80
+
+/* ErrorCode */
+#define ERROR_FLICKER_BELOW_MIN_EXP     0x01 /*flicker exposure got below minimum exposure */
+
+#define ALOG(lineno,fmt,args...) printk(fmt,lineno,##args)
+#define LOG(fmt,args...) ALOG((__LINE__),KERN_INFO __FILE__":"__FUNCTION__"(%d):"fmt,##args)
+
+#ifdef _CPIA_DEBUG_
+#define ADBG(lineno,fmt,args...) printk(fmt, jiffies, lineno, ##args)
+#define DBG(fmt,args...) ADBG((__LINE__),KERN_DEBUG __FILE__"(%ld):"__FUNCTION__"(%d):"fmt,##args)
+#else
+#define DBG(fmn,args...) {}
+#endif
+
+#define DEB_BYTE(p)\
+  DBG("%1d %1d %1d %1d %1d %1d %1d %1d \n",\
+      (p)&0x80?1:0, (p)&0x40?1:0, (p)&0x20?1:0, (p)&0x10?1:0,\
+        (p)&0x08?1:0, (p)&0x04?1:0, (p)&0x02?1:0, (p)&0x01?1:0);
+
+#endif /* __KERNEL__ */
+
+#endif /* cpia_h */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/linux/cyclades.h linux.15p9/include/linux/cyclades.h
--- linux.vanilla/include/linux/cyclades.h	Wed Oct 20 01:12:50 1999
+++ linux.15p9/include/linux/cyclades.h	Fri Jan 21 18:26:25 2000
@@ -1,4 +1,4 @@
-/* $Revision: 2.6 $$Date: 1998/08/10 16:57:01 $
+/* $Revision: 3.0 $$Date: 1998/11/02 14:20:59 $
  * linux/include/linux/cyclades.h
  *
  * This file was initially written by
@@ -7,6 +7,9 @@
  *
  * This file contains the general definitions for the cyclades.c driver
  *$Log: cyclades.h,v $
+ *Revision 3.0  1998/11/02 14:20:59  ivan
+ *added nports field on cyclades_card structure;
+ *
  *Revision 2.5  1998/08/03 16:57:01  ivan
  *added cyclades_idle_stats structure;
  * 
@@ -502,6 +505,7 @@
     int irq;
     int num_chips;	/* 0 if card absent, -1 if Z/PCI, else Y */
     int first_line;	/* minor number of first channel on card */
+    int nports;		/* Number of ports in the card */
     int bus_index;	/* address shift - 0 for ISA, 1 for PCI */
     int	intr_enabled;	/* FW Interrupt flag - 0 disabled, 1 enabled */
 #ifdef __KERNEL__
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/linux/generic_serial.h linux.15p9/include/linux/generic_serial.h
--- linux.vanilla/include/linux/generic_serial.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/include/linux/generic_serial.h	Tue Jan 18 00:52:11 2000
@@ -0,0 +1,105 @@
+/*
+ *  generic_serial.h
+ *
+ *  Copyright (C) 1998 R.E.Wolff@BitWizard.nl
+ *
+ *  written for the SX serial driver.
+ *     Contains the code that should be shared over all the serial drivers.
+ *
+ *  Version 0.1 -- December, 1998.
+ */
+
+#ifndef GENERIC_SERIAL_H
+#define GENERIC_SERIAL_H
+
+
+
+
+struct real_driver {
+  void                    (*disable_tx_interrupts) (void *);
+  void                    (*enable_tx_interrupts) (void *);
+  void                    (*disable_rx_interrupts) (void *);
+  void                    (*enable_rx_interrupts) (void *);
+  int                     (*get_CD) (void *);
+  void                    (*shutdown_port) (void*);
+  int                     (*set_real_termios) (void*);
+  int                     (*chars_in_buffer) (void*);
+  void                    (*close) (void*);
+  void                    (*hungup) (void*);
+  void                    (*getserial) (void*, struct serial_struct *sp);
+};
+
+
+
+struct gs_port {
+  int                     magic;
+  unsigned char           *xmit_buf; 
+  int                     xmit_head;
+  int                     xmit_tail;
+  int                     xmit_cnt;
+  /*  struct semaphore        port_write_sem; */
+  int                     flags;
+  struct termios          normal_termios;
+  struct termios          callout_termios;
+  wait_queue_head_t       open_wait;
+  wait_queue_head_t       close_wait;
+  long                    session;
+  long                    pgrp;
+  int                     count;
+  int                     blocked_open;
+  struct tty_struct       *tty;
+  int                     event;
+  unsigned short          closing_wait;
+  int                     close_delay;
+  struct real_driver      *rd;
+  int                     wakeup_chars;
+  int                     baud_base;
+  int                     baud;
+  int                     custom_divisor;
+};
+
+
+/* Flags */
+/* Warning: serial.h defines some ASYNC_ flags, they say they are "only"
+   used in serial.c, but they are also used in all other serial drivers. 
+   Make sure they don't clash with these here... */
+#define GS_TX_INTEN      0x00800000
+#define GS_RX_INTEN      0x00400000
+#define GS_ACTIVE        0x00200000
+
+
+
+#define GS_TYPE_NORMAL   1
+#define GS_TYPE_CALLOUT  2
+
+
+#define GS_DEBUG_FLUSH   0x00000001
+#define GS_DEBUG_BTR     0x00000002
+#define GS_DEBUG_TERMIOS 0x00000004
+#define GS_DEBUG_STUFF   0x00000008
+#define GS_DEBUG_CLOSE   0x00000010
+#define GS_DEBUG_FLOW    0x00000020
+
+
+void gs_put_char(struct tty_struct *tty, unsigned char ch);
+int  gs_write(struct tty_struct *tty, int from_user, 
+             const unsigned char *buf, int count);
+int  gs_write_room(struct tty_struct *tty);
+int  gs_chars_in_buffer(struct tty_struct *tty);
+void gs_flush_buffer(struct tty_struct *tty);
+void gs_flush_chars(struct tty_struct *tty);
+void gs_stop(struct tty_struct *tty);
+void gs_start(struct tty_struct *tty);
+void gs_hangup(struct tty_struct *tty);
+void gs_do_softint(void *private_);
+int  block_til_ready(void *port, struct file *filp);
+void gs_close(struct tty_struct *tty, struct file *filp);
+void gs_set_termios (struct tty_struct * tty, 
+                     struct termios * old_termios);
+int  gs_init_port(struct gs_port *port);
+int  gs_setserial(struct gs_port *port, struct serial_struct *sp);
+void gs_getserial(struct gs_port *port, struct serial_struct *sp);
+
+extern int gs_debug;
+
+#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/linux/hdreg.h linux.15p9/include/linux/hdreg.h
--- linux.vanilla/include/linux/hdreg.h	Sun Mar 28 19:03:27 1999
+++ linux.15p9/include/linux/hdreg.h	Mon Feb  7 12:21:10 2000
@@ -49,6 +49,7 @@
 #define WIN_SEEK		0x70
 #define WIN_DIAGNOSE		0x90
 #define WIN_SPECIFY		0x91	/* set drive geometry translation */
+#define WIN_IDLEIMMEDIATE	0xE1	/* force drive to become "ready" */
 #define WIN_SETIDLE1		0xE3
 #define WIN_SETIDLE2		0x97
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/linux/if_bonding.h linux.15p9/include/linux/if_bonding.h
--- linux.vanilla/include/linux/if_bonding.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/include/linux/if_bonding.h	Wed Jan 26 23:15:27 2000
@@ -0,0 +1,59 @@
+/*
+ * Bond several ethernet interfaces into a Cisco, running 'Etherchannel'.
+ *
+ * 
+ * Portions are (c) Copyright 1995 Simon "Guru Aleph-Null" Janes
+ * NCM: Network and Communications Management, Inc.
+ *
+ * BUT, I'm the one who modified it for ethernet, so:
+ * (c) Copyright 1999, Thomas Davis, tadavis@lbl.gov
+ *
+ *	This software may be used and distributed according to the terms
+ *	of the GNU Public License, incorporated herein by reference.
+ * 
+ */
+
+#ifndef _LINUX_IF_BONDING_H
+#define _LINUX_IF_BONDING_H
+
+#include <linux/timer.h>
+
+#define BOND_ENSLAVE     (SIOCDEVPRIVATE)
+#define BOND_RELEASE     (SIOCDEVPRIVATE + 1)
+#define BOND_SETHWADDR   (SIOCDEVPRIVATE + 2)
+
+typedef struct slave {
+	struct device *dev;
+	struct slave *next;
+	struct slave *prev;
+} slave_t;
+
+typedef struct slave_queue {
+	slave_t *head;
+	slave_t *tail;
+	slave_t *current_slave;
+	int num_slaves;
+	struct device *master_dev;
+	char lock;
+} slave_queue_t;
+
+typedef struct bonding {
+	slave_queue_t *queue;
+	int min_slaves;
+	int max_slaves;
+	struct net_device_stats *stats;
+	struct timer_list timer;
+	char timer_on;
+} bonding_t;  
+
+#endif /* _LINUX_BOND_H */
+
+/*
+ * Local variables:
+ *  version-control: t
+ *  kept-new-versions: 5
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/linux/irda.h linux.15p9/include/linux/irda.h
--- linux.vanilla/include/linux/irda.h	Sat Aug 14 02:26:01 1999
+++ linux.15p9/include/linux/irda.h	Tue Jan 18 01:08:18 2000
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Mar  8 14:06:12 1999
- * Modified at:   Mon Mar 22 14:14:54 1999
+ * Modified at:   Sat Dec 25 16:06:42 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -19,7 +19,7 @@
  *     Neither Dag Brattli nor University of Tromsř admit liability nor
  *     provide warranty for any of this software. This material is 
  *     provided "AS-IS" and at no charge.
- *     
+ *
  ********************************************************************/
 
 #ifndef KERNEL_IRDA_H
@@ -44,17 +44,36 @@
 #define HINT_OBEX        0x20
 
 /* IrLMP character code values */
-#define CS_ASCII       0x00
-#define	CS_ISO_8859_1  0x01
-#define	CS_ISO_8859_2  0x02
-#define	CS_ISO_8859_3  0x03
-#define	CS_ISO_8859_4  0x04
-#define	CS_ISO_8859_5  0x05
-#define	CS_ISO_8859_6  0x06
-#define	CS_ISO_8859_7  0x07
-#define	CS_ISO_8859_8  0x08
-#define	CS_ISO_8859_9  0x09
-#define CS_UNICODE     0xff
+#define CS_ASCII         0x00
+#define	CS_ISO_8859_1    0x01
+#define	CS_ISO_8859_2    0x02
+#define	CS_ISO_8859_3    0x03
+#define	CS_ISO_8859_4    0x04
+#define	CS_ISO_8859_5    0x05
+#define	CS_ISO_8859_6    0x06
+#define	CS_ISO_8859_7    0x07
+#define	CS_ISO_8859_8    0x08
+#define	CS_ISO_8859_9    0x09
+#define CS_UNICODE       0xff
+
+/* These are the currently known dongles */
+typedef enum {
+	IRDA_TEKRAM_DONGLE       = 0,
+	IRDA_ESI_DONGLE          = 1,
+	IRDA_ACTISYS_DONGLE      = 2,
+	IRDA_ACTISYS_PLUS_DONGLE = 3,
+	IRDA_GIRBIL_DONGLE       = 4,
+	IRDA_LITELINK_DONGLE     = 5,
+	IRDA_AIRPORT_DONGLE      = 6,
+	IRDA_OLD_BELKIN_DONGLE   = 7,
+} IRDA_DONGLE;
+
+/* Protocol types to be used for SOCK_DGRAM */
+enum {
+	IRDAPROTO_UNITDATA = 0,
+	IRDAPROTO_ULTRA    = 1,
+	IRDAPROTO_MAX
+};
 
 #define SOL_IRLMP      266 /* Same as SOL_IRDA for now */
 #define SOL_IRTTP      266 /* Same as SOL_IRDA for now */
@@ -62,37 +81,39 @@
 #define IRLMP_ENUMDEVICES        1
 #define IRLMP_IAS_SET            2
 #define IRLMP_IAS_QUERY          3
-#define IRLMP_DISCOVERY_MASK_SET 4
-
-#define IRTTP_QOS_SET            5
-#define IRTTP_QOS_GET            6
-#define IRTTP_MAX_SDU_SIZE       7
-
-#define IAS_MAX_STRING           256
-#define IAS_MAX_OCTET_STRING     1024
-#define IAS_MAX_CLASSNAME        64
-#define IAS_MAX_ATTRIBNAME       256
+#define IRLMP_HINTS_SET          4
+#define IRLMP_QOS_SET            5
+#define IRLMP_QOS_GET            6
+#define IRLMP_MAX_SDU_SIZE       7
+#define IRLMP_IAS_GET            8
+
+#define IRTTP_MAX_SDU_SIZE IRLMP_MAX_SDU_SIZE /* Compatibility */
+
+#define IAS_MAX_STRING         256
+#define IAS_MAX_OCTET_STRING  1024
+#define IAS_MAX_CLASSNAME       64
+#define IAS_MAX_ATTRIBNAME     256
 
-#define LSAP_ANY                 0xff
+#define LSAP_ANY              0xff
 
 struct sockaddr_irda {
-	sa_family_t   sir_family;   /* AF_IRDA */
-	unsigned char sir_lsap_sel; /* LSAP/TSAP selector */
-	unsigned int  sir_addr;     /* Device address */
-	char          sir_name[25]; /* Usually <service>:IrDA:TinyTP */
+	sa_family_t sir_family;   /* AF_IRDA */
+	__u8        sir_lsap_sel; /* LSAP selector */
+	__u32       sir_addr;     /* Device address */
+	char        sir_name[25]; /* Usually <service>:IrDA:TinyTP */
 };
 
 struct irda_device_info {
-	unsigned int  saddr;       /* Address of remote device */
-	unsigned int  daddr;       /* Link where it was discovered */
-	char          info[22];     /* Description */
-	unsigned char charset;      /* Charset used for description */
-	unsigned char hints[2];     /* Hint bits */
+	__u32       saddr;    /* Address of local interface */
+	__u32       daddr;    /* Address of remote device */
+	char        info[22]; /* Description */
+	__u8        charset;  /* Charset used for description */
+	__u8        hints[2]; /* Hint bits */
 };
 
 struct irda_device_list {
-       unsigned int len;
-       struct irda_device_info dev[0];
+       __u32 len;
+       struct irda_device_info dev[1];
 };
 
 struct irda_ias_set {
@@ -103,15 +124,71 @@
 		unsigned int irda_attrib_int;
 		struct {
 			unsigned short len;
-			u_char OctetSeq[IAS_MAX_OCTET_STRING];
+			__u8 octet_seq[IAS_MAX_OCTET_STRING];
 		} irda_attrib_octet_seq;
 		struct {
-			unsigned char len;
-			unsigned char charset;
-			unsigned char string[IAS_MAX_STRING];
+			__u8 len;
+			__u8 charset;
+			__u8 string[IAS_MAX_STRING];
 		} irda_attrib_string;
 	} attribute;
 };
+
+/* Some private IOCTL's (max 16) */
+#define SIOCSDONGLE    (SIOCDEVPRIVATE + 0)
+#define SIOCGDONGLE    (SIOCDEVPRIVATE + 1)
+#define SIOCSBANDWIDTH (SIOCDEVPRIVATE + 2)
+#define SIOCSMEDIABUSY (SIOCDEVPRIVATE + 3)
+#define SIOCGMEDIABUSY (SIOCDEVPRIVATE + 4)
+#define SIOCGRECEIVING (SIOCDEVPRIVATE + 5)
+#define SIOCSMODE      (SIOCDEVPRIVATE + 6)
+#define SIOCGMODE      (SIOCDEVPRIVATE + 7)
+#define SIOCSDTRRTS    (SIOCDEVPRIVATE + 8)
+#define SIOCGQOS       (SIOCDEVPRIVATE + 9)
+
+/* No reason to include <linux/if.h> just because of this one ;-) */
+#define IRNAMSIZ 16 
+
+/* IrDA quality of service information (must not exceed 16 bytes) */
+struct if_irda_qos {
+	unsigned long  baudrate;
+	unsigned short data_size;
+	unsigned short window_size;
+	unsigned short min_turn_time;
+	unsigned short max_turn_time;
+	unsigned char  add_bofs;
+	unsigned char  link_disc;
+};
+
+/* For setting RTS and DTR lines of a dongle */
+struct if_irda_line {
+	__u8 dtr;
+	__u8 rts;
+};
+
+/* IrDA interface configuration (data part must not exceed 16 bytes) */
+struct if_irda_req {
+	union {
+		char ifrn_name[IRNAMSIZ];  /* if name, e.g. "irda0" */
+	} ifr_ifrn;
+	
+	/* Data part */
+	union {
+		struct if_irda_line ifru_line;
+		struct if_irda_qos  ifru_qos;
+		unsigned short      ifru_flags;
+		unsigned int        ifru_receiving;
+		unsigned int        ifru_mode;
+		unsigned int        ifru_dongle;
+	} ifr_ifru;
+};
+
+#define ifr_baudrate  ifr_ifru.ifru_qos.baudrate
+#define ifr_receiving ifr_ifru.ifru_receiving 
+#define ifr_dongle    ifr_ifru.ifru_dongle
+#define ifr_mode      ifr_ifru.ifru_mode
+#define ifr_dtr       ifr_ifru.ifru_line.dtr
+#define ifr_rts       ifr_ifru.ifru_line.rts
 
 #endif /* KERNEL_IRDA_H */
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/linux/isdn.h linux.15p9/include/linux/isdn.h
--- linux.vanilla/include/linux/isdn.h	Tue Jan  4 21:19:02 2000
+++ linux.15p9/include/linux/isdn.h	Thu Jan 27 00:03:53 2000
@@ -1,4 +1,4 @@
-/* $Id: isdn.h,v 1.81 1999/10/27 21:21:18 detabc Exp $
+/* $Id: isdn.h,v 1.88 2000/01/20 19:59:43 keil Exp $
  *
  * Main header for the Linux ISDN subsystem (linklevel).
  *
@@ -21,6 +21,43 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: isdn.h,v $
+ * Revision 1.88  2000/01/20 19:59:43  keil
+ * Add FAX Class 1 support
+ *
+ * Revision 1.87  2000/01/09 20:43:15  detabc
+ * exand logical bind-group's for both call's (in and out).
+ * add first part of kernel-config-help for abc-extension.
+ *
+ * Revision 1.86  1999/12/05 16:06:09  detabc
+ * add resethandling for rawip-compression.
+ * at now all B2-Protocols are usable with rawip-compression
+ *
+ * Revision 1.85  1999/11/30 11:29:06  detabc
+ * add a on the fly frame-counter and limit
+ *
+ * Revision 1.84  1999/11/28 14:49:08  detabc
+ * In case of rawip-compress adjust dev[x]->ibytes/obytes to reflect the
+ * uncompressed size.
+ *
+ * Revision 1.83  1999/11/26 15:54:59  detabc
+ * added compression (isdn_bsdcompress) for rawip interfaces with x75i B2-protocol.
+ *
+ * Revision 1.82  1999/11/20 22:14:14  detabc
+ * added channel dial-skip in case of external use
+ * (isdn phone or another isdn device) on the same NTBA.
+ * usefull with two or more card's connected the different NTBA's.
+ * global switchable in kernel-config and also per netinterface.
+ *
+ * add auto disable of netinterface's in case of:
+ * 	to many connection's in short time.
+ * 	config mistakes (wrong encapsulation, B2-protokoll or so on) on local
+ * 	or remote side.
+ * 	wrong password's or something else to a ISP (syncppp).
+ *
+ * possible encapsulations for this future are:
+ * ISDN_NET_ENCAP_SYNCPPP, ISDN_NET_ENCAP_UIHDLC, ISDN_NET_ENCAP_RAWIP,
+ * and ISDN_NET_ENCAP_CISCOHDLCK.
+ *
  * Revision 1.81  1999/10/27 21:21:18  detabc
  * Added support for building logically-bind-group's per interface.
  * usefull for outgoing call's with more then one isdn-card.
@@ -333,6 +370,10 @@
 #undef CONFIG_ISDN_WITH_ABC_IPV4_DYNADDR
 #undef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER
 #undef CONFIG_ISDN_WITH_ABC_ICALL_BIND
+#undef CONFIG_ISDN_WITH_ABC_CH_EXTINUSE
+#undef CONFIG_ISDN_WITH_ABC_CONN_ERROR
+#undef CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS
+#undef CONFIG_ISDN_WITH_ABC_FRAME_LIMIT
 
 
 /* New ioctl-codes */
@@ -359,6 +400,7 @@
 #define IIOCGETCPS  _IO('I',21)
 #define IIOCGETDVR  _IO('I',22)
 #define IIOCNETLCR  _IO('I',23) /* dwabc ioctl for LCR from isdnlog */
+#define IIOCNETDWRSET  _IO('I',24) /* dwabc ioctl to reset abc-values to default on a net-interface */
 
 #define IIOCNETALN  _IO('I',32)
 #define IIOCNETDLN  _IO('I',33)
@@ -923,6 +965,7 @@
 	isdn_v110_stream  *v110[ISDN_MAX_CHANNELS];  /* V.110 private data         */
 	struct semaphore  sem;                       /* serialize list access*/
 	isdn_module       *modules;
+	unsigned long     global_features;
 } isdn_dev;
 
 extern isdn_dev *dev;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/linux/isdnif.h linux.15p9/include/linux/isdnif.h
--- linux.vanilla/include/linux/isdnif.h	Tue Jan  4 21:19:02 2000
+++ linux.15p9/include/linux/isdnif.h	Thu Jan 27 00:03:53 2000
@@ -1,4 +1,4 @@
-/* $Id: isdnif.h,v 1.32 1999/10/11 22:03:00 keil Exp $
+/* $Id: isdnif.h,v 1.33 2000/01/20 19:59:43 keil Exp $
  *
  * Linux ISDN subsystem
  *
@@ -22,6 +22,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: isdnif.h,v $
+ * Revision 1.33  2000/01/20 19:59:43  keil
+ * Add FAX Class 1 support
+ *
  * Revision 1.32  1999/10/11 22:03:00  keil
  * COMPAT_NEED_UACCESS (no include in isdn_compat.h)
  *
@@ -175,10 +178,11 @@
 /*
  * Values for Layer-3-protocol-selection
  */
-#define ISDN_PROTO_L3_TRANS  0   /* Transparent                 */
-#define ISDN_PROTO_L3_TRANSDSP 1   /* Transparent with DSP    */
-#define ISDN_PROTO_L3_FAX    2   /* Fax Group 2/3             */
-#define ISDN_PROTO_L3_MAX    7   /* Max. 8 Protocols            */
+#define ISDN_PROTO_L3_TRANS	0	/* Transparent */
+#define ISDN_PROTO_L3_TRANSDSP	1	/* Transparent with DSP */
+#define ISDN_PROTO_L3_FCLASS2	2	/* Fax Group 2/3 CLASS 2 */
+#define ISDN_PROTO_L3_FCLASS1	3	/* Fax Group 2/3 CLASS 1 */
+#define ISDN_PROTO_L3_MAX	7	/* Max. 8 Protocols */
 
 #ifdef __KERNEL__
 
@@ -362,7 +366,8 @@
 /* Layer 3 */
 #define ISDN_FEATURE_L3_TRANS   (0x10000 << ISDN_PROTO_L3_TRANS)
 #define ISDN_FEATURE_L3_TRANSDSP (0x10000 << ISDN_PROTO_L3_TRANSDSP)
-#define ISDN_FEATURE_L3_FAX	(0x10000 << ISDN_PROTO_L3_FAX)
+#define ISDN_FEATURE_L3_FCLASS2	(0x10000 << ISDN_PROTO_L3_FCLASS2)
+#define ISDN_FEATURE_L3_FCLASS1	(0x10000 << ISDN_PROTO_L3_FCLASS1)
 
 #define ISDN_FEATURE_L3_MASK    (0x0FF0000) /* Max. 8 Protocols */
 #define ISDN_FEATURE_L3_SHIFT   (16)
@@ -463,6 +468,33 @@
 
 #endif /* TTY_FAX */
 
+#define ISDN_FAX_CLASS1_FAE	0
+#define ISDN_FAX_CLASS1_FTS	1
+#define ISDN_FAX_CLASS1_FRS	2
+#define ISDN_FAX_CLASS1_FTM	3
+#define ISDN_FAX_CLASS1_FRM	4
+#define ISDN_FAX_CLASS1_FTH	5
+#define ISDN_FAX_CLASS1_FRH	6
+#define ISDN_FAX_CLASS1_CTRL	7
+
+#define ISDN_FAX_CLASS1_OK	0
+#define ISDN_FAX_CLASS1_CONNECT	1
+#define ISDN_FAX_CLASS1_NOCARR	2
+#define ISDN_FAX_CLASS1_ERROR	3
+#define ISDN_FAX_CLASS1_FCERROR	4
+#define ISDN_FAX_CLASS1_QUERY	5
+
+typedef struct {
+	__u8	cmd;
+	__u8	subcmd;
+	__u8	para[50];
+} aux_s;
+
+#define AT_COMMAND	0
+#define AT_EQ_VALUE	1
+#define AT_QUERY	2
+#define AT_EQ_QUERY	3
+
 /* CAPI structs */
 
 /* this is compatible to the old union size */
@@ -494,13 +526,14 @@
 	int   command;		/* Command or Status (see above) */
 	ulong arg;		/* Additional Data               */
 	union {
-		ulong errcode;	/* Type of error with STAT_L1ERR         */
-		int length;	/* Amount of bytes sent with STAT_BSENT  */
-		u_char num[50];/* Additional Data			*/
+		ulong errcode;	/* Type of error with STAT_L1ERR	*/
+		int length;	/* Amount of bytes sent with STAT_BSENT	*/
+		u_char num[50];	/* Additional Data			*/
 		setup_parm setup;/* For SETUP msg			*/
 		capi_msg cmsg;	/* For CAPI like messages		*/
-		char display[85];/* display message data          */ 
-		dss1_cmd_stat dss1_io; /* DSS1 IO-parameter/result */
+		char display[85];/* display message data		*/ 
+		dss1_cmd_stat dss1_io; /* DSS1 IO-parameter/result	*/
+		aux_s aux;	/* for modem commands/indications	*/
 #ifdef CONFIG_ISDN_TTY_FAX
 		T30_s	*fax;	/* Pointer to ttys fax struct		*/
 #endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/linux/istallion.h linux.15p9/include/linux/istallion.h
--- linux.vanilla/include/linux/istallion.h	Wed Feb  4 22:52:16 1998
+++ linux.15p9/include/linux/istallion.h	Mon Feb  7 12:07:56 2000
@@ -4,7 +4,7 @@
  *	istallion.h  -- stallion intelligent multiport serial driver.
  *
  *	Copyright (C) 1996-1998  Stallion Technologies (support@stallion.oz.au).
- *	Copyright (C) 1994-1996  Greg Ungerer (gerg@stallion.oz.au).
+ *	Copyright (C) 1994-1996  Greg Ungerer.
  *
  *	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
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/linux/kernel_stat.h linux.15p9/include/linux/kernel_stat.h
--- linux.vanilla/include/linux/kernel_stat.h	Sun Mar 28 19:03:27 1999
+++ linux.15p9/include/linux/kernel_stat.h	Thu Feb 17 13:38:52 2000
@@ -25,7 +25,9 @@
 	unsigned int dk_drive_wblk[DK_NDRIVE];
 	unsigned int pgpgin, pgpgout;
 	unsigned int pswpin, pswpout;
+#ifndef CONFIG_ARCH_S390
 	unsigned int irqs[NR_CPUS][NR_IRQS];
+#endif
 	unsigned int ipackets, opackets;
 	unsigned int ierrors, oerrors;
 	unsigned int collisions;
@@ -34,6 +36,7 @@
 
 extern struct kernel_stat kstat;
 
+#ifndef CONFIG_ARCH_S390
 /*
  * Number of interrupts per specific IRQ source, since bootup
  */
@@ -46,5 +49,6 @@
 
 	return sum;
 }
+#endif
 
 #endif /* _LINUX_KERNEL_STAT_H */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/linux/module.h linux.15p9/include/linux/module.h
--- linux.vanilla/include/linux/module.h	Sun Mar 28 19:03:25 1999
+++ linux.15p9/include/linux/module.h	Wed Feb 16 20:17:14 2000
@@ -101,6 +101,7 @@
 #define MOD_VISITED  		8
 #define MOD_USED_ONCE		16
 #define MOD_JUST_FREED		32
+#define MOD_INITIALIZING	64
 
 /* Values for query_module's which.  */
 
@@ -109,6 +110,9 @@
 #define QM_REFS		3
 #define QM_SYMBOLS	4
 #define QM_INFO		5
+
+/* Can the module be queried? */
+#define MOD_CAN_QUERY(mod) (((mod)->flags & (MOD_RUNNING | MOD_INITIALIZING)) && !((mod)->flags & MOD_DELETED))
 
 /* When struct module is extended, we must test whether the new member
    is present in the header received from insmod before we can use it.  
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/linux/pci.h linux.15p9/include/linux/pci.h
--- linux.vanilla/include/linux/pci.h	Tue Jan  4 21:19:03 2000
+++ linux.15p9/include/linux/pci.h	Wed Feb 16 18:32:54 2000
@@ -286,6 +286,7 @@
 #define PCI_DEVICE_ID_COMPAQ_TOKENRING	0x0508
 #define PCI_DEVICE_ID_COMPAQ_1280	0x3033
 #define PCI_DEVICE_ID_COMPAQ_TRIFLEX	0x4000
+#define PCI_DEVICE_ID_COMPAQ_6010	0x6010
 #define PCI_DEVICE_ID_COMPAQ_SMART2P	0xae10
 #define PCI_DEVICE_ID_COMPAQ_NETEL100	0xae32
 #define PCI_DEVICE_ID_COMPAQ_NETEL10	0xae34
@@ -856,6 +857,10 @@
 #define PCI_DEVICE_ID_RENDITION_VERITE	0x0001
 #define PCI_DEVICE_ID_RENDITION_VERITE2100 0x2000
 
+#define PCI_VENDOR_ID_RCC		0x1166
+#define PCI_DEVICE_ID_RCC_HE		0x0008
+#define PCI_DEVICE_ID_RCC_LE		0x0009
+
 #define PCI_VENDOR_ID_TOSHIBA		0x1179
 #define PCI_DEVICE_ID_TOSHIBA_601	0x0601
 #define PCI_DEVICE_ID_TOSHIBA_TOPIC95	0x060a
@@ -889,6 +894,7 @@
 
 #define PCI_VENDOR_ID_ATT		0x11c1
 #define PCI_DEVICE_ID_ATT_L56XMF	0x0440
+#define PCI_DEVICE_ID_ATT_L56DVP	0x0480
 
 #define PCI_VENDOR_ID_SPECIALIX		0x11cb
 #define PCI_DEVICE_ID_SPECIALIX_IO8	0x2000
@@ -1082,6 +1088,7 @@
 #define PCI_DEVICE_ID_INTEL_82430	0x0486
 #define PCI_DEVICE_ID_INTEL_82434	0x04a3
 #define PCI_DEVICE_ID_INTEL_I960	0x0960
+#define PCI_DEVICE_ID_INTEL_82559ER	0x1209
 #define PCI_DEVICE_ID_INTEL_82092AA_0	0x1221
 #define PCI_DEVICE_ID_INTEL_82092AA_1	0x1222
 #define PCI_DEVICE_ID_INTEL_7116	0x1223
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/linux/proc_fs.h linux.15p9/include/linux/proc_fs.h
--- linux.vanilla/include/linux/proc_fs.h	Tue Jan  4 21:19:03 2000
+++ linux.15p9/include/linux/proc_fs.h	Mon Feb  7 13:48:41 2000
@@ -210,6 +210,7 @@
  	PROC_SCSI_IPH5526_FC,
 	PROC_SCSI_FCAL,
 	PROC_SCSI_I2O,
+	PROC_SCSI_3W_XXXX,
 	PROC_SCSI_USB_SCSI,
 	PROC_SCSI_SCSI_DEBUG,	
 	PROC_SCSI_NOT_PRESENT,
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/linux/qnx4_fs.h linux.15p9/include/linux/qnx4_fs.h
--- linux.vanilla/include/linux/qnx4_fs.h	Sat Aug 14 02:26:01 1999
+++ linux.15p9/include/linux/qnx4_fs.h	Mon Jan 24 19:45:59 2000
@@ -2,8 +2,8 @@
  *  Name                         : qnx4_fs.h
  *  Author                       : Richard Frowijn
  *  Function                     : qnx4 global filesystem definitions
- *  Version                      : 1.0
- *  Last modified                : 23-03-1998
+ *  Version                      : 1.0.2
+ *  Last modified                : 2000-01-15
  *
  *  History                      : 23-03-1998 created
  */
@@ -14,7 +14,7 @@
 
 #define QNX4_ROOT_INO 1
 
-#define _MAX_XTNTS_PER_XBLK	60
+#define QNX4_MAX_XTNTS_PER_XBLK	60
 /* for di_status */
 #define QNX4_FILE_USED          0x01
 #define QNX4_FILE_MODIFIED      0x02
@@ -29,53 +29,55 @@
 #define QNX4_VALID_FS		0x0001	/* Clean fs. */
 #define QNX4_ERROR_FS		0x0002	/* fs has errors. */
 #define QNX4_BLOCK_SIZE         0x200	/* blocksize of 512 bytes */
-#define QNX4_DIR_ENTRY_SIZE     0x040	/* dir entry size */
+#define QNX4_BLOCK_SIZE_SHIFT	9
+#define QNX4_DIR_ENTRY_SIZE     0x040	/* dir entry size of 64 bytes */
+#define QNX4_DIR_ENTRY_SIZE_SHIFT 6
 #define QNX4_XBLK_ENTRY_SIZE    0x200	/* xblk entry size */
 #define QNX4_INODES_PER_BLOCK   0x08	/* 512 / 64 */
-
+#define QNX4_INODES_PER_BLOCK_MASK 0x07
 /* for filenames */
-#define _SHORT_NAME_MAX        16
-#define QNX4_NAME_MAX          48
+#define QNX4_SHORT_NAME_MAX	16
+#define QNX4_NAME_MAX		48
 
 /*
  * This is the original qnx4 inode layout on disk.
  */
 struct qnx4_inode_entry {
-	char di_fname[16];
-	off_t di_size;
-	_xtnt_t di_first_xtnt;
-	long di_xblk;
-	time_t di_ftime;
-	time_t di_mtime;
-	time_t di_atime;
-	time_t di_ctime;
-	_nxtnt_t di_num_xtnts;
-	mode_t di_mode;
-	muid_t di_uid;
-	mgid_t di_gid;
-	nlink_t di_nlink;
-	char di_zero[4];
-	_ftype_t di_type;
-	unsigned char di_status;
+	char		di_fname[QNX4_SHORT_NAME_MAX];
+	qnx4_off_t	di_size;
+	qnx4_xtnt_t	di_first_xtnt;
+	__u32		di_xblk;
+	__s32		di_ftime;
+	__s32		di_mtime;
+	__s32		di_atime;
+	__s32		di_ctime;
+	qnx4_nxtnt_t	di_num_xtnts;
+	qnx4_mode_t	di_mode;
+	qnx4_muid_t	di_uid;
+	qnx4_mgid_t	di_gid;
+	qnx4_nlink_t	di_nlink;
+	__u8		di_zero[4];
+	qnx4_ftype_t	di_type;
+	__u8		di_status;
 };
 
 struct qnx4_link_info {
-	char dl_fname[QNX4_NAME_MAX];
-	long dl_inode_blk;
-	unsigned char dl_inode_ndx;
-	unsigned char dl_spare[10];
-	unsigned char dl_status;
+	char		dl_fname[QNX4_NAME_MAX];
+	__u32		dl_inode_blk;
+	__u8		dl_inode_ndx;
+	__u8		dl_spare[10];
+	__u8		dl_status;
 };
 
 struct qnx4_xblk {
-	long xblk_next_xblk;
-	long xblk_prev_xblk;
-	unsigned char xblk_num_xtnts;
-	char xblk_spare[3];
-	long xblk_num_blocks;
-	_xtnt_t xblk_xnts[_MAX_XTNTS_PER_XBLK];
-	char xblk_signature[8];
-	_xtnt_t xblk_first_xtnt;
+	__u32		xblk_next_xblk;
+	__u32		xblk_prev_xblk;
+	__u8		xblk_num_xtnts;
+	__u8		xblk_spare[3];
+	__s32		xblk_num_blocks;
+	qnx4_xtnt_t	xblk_xtnts[QNX4_MAX_XTNTS_PER_XBLK];
+	char		xblk_signature[8];
+	qnx4_xtnt_t	xblk_first_xtnt;
 };
 
 struct qnx4_super_block {
@@ -96,8 +98,8 @@
 #endif
 
 extern struct dentry *qnx4_lookup(struct inode *dir, struct dentry *dentry);
-extern unsigned long qnx4_count_free_inodes(struct super_block *sb);
 extern unsigned long qnx4_count_free_blocks(struct super_block *sb);
+extern unsigned long qnx4_block_map(struct inode *inode, long iblock);
 
 extern struct buffer_head *qnx4_getblk(struct inode *, int, int);
 extern struct buffer_head *qnx4_bread(struct inode *, int, int);
@@ -107,8 +109,8 @@
 extern struct inode_operations qnx4_file_inode_operations;
 extern struct inode_operations qnx4_dir_inode_operations;
 extern struct inode_operations qnx4_symlink_inode_operations;
-extern int qnx4_is_free(struct super_block *sb, int block);
-extern int qnx4_set_bitmap(struct super_block *sb, int block, int busy);
+extern int qnx4_is_free(struct super_block *sb, long block);
+extern int qnx4_set_bitmap(struct super_block *sb, long block, int busy);
 extern int qnx4_create(struct inode *inode, struct dentry *dentry, int mode);
 extern void qnx4_truncate(struct inode *inode);
 extern void qnx4_free_inode(struct inode *inode);
@@ -116,7 +118,7 @@
 extern int qnx4_rmdir(struct inode *dir, struct dentry *dentry);
 extern int qnx4_sync_file(struct file *file, struct dentry *dentry);
 extern int qnx4_sync_inode(struct inode *inode);
-extern int qnx4_bmap(struct inode *inode, int block);
+extern int qnx4_bmap(struct inode *inode, int iblock);
 
 #endif				/* __KERNEL__ */
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/linux/qnx4_fs_i.h linux.15p9/include/linux/qnx4_fs_i.h
--- linux.vanilla/include/linux/qnx4_fs_i.h	Mon Aug 31 21:01:35 1998
+++ linux.15p9/include/linux/qnx4_fs_i.h	Tue Jan 18 00:59:09 2000
@@ -2,11 +2,11 @@
  *  Name                         : qnx4_fs_i.h
  *  Author                       : Richard Frowijn
  *  Function                     : qnx4 inode definitions
- *  Version                      : 1.0
- *  Last modified                : 25-05-1998
- * 
+ *  Version                      : 1.0.2
+ *  Last modified                : 2000-01-06
+ *
  *  History                      : 23-03-1998 created
- * 
+ *
  */
 #ifndef _QNX4_FS_I
 #define _QNX4_FS_I
@@ -14,25 +14,25 @@
 #include <linux/qnxtypes.h>
 
 /*
- * qnx4 fs inode entry 
+ * qnx4 fs inode entry
  */
 struct qnx4_inode_info {
-	char i_reserved[16];	/* 16 */
-	off_t i_size;		/*  4 */
-	_xtnt_t i_first_xtnt;	/*  8 */
-	long i_xblk;		/*  4 */
-	time_t i_ftime;		/*  4 */
-	time_t i_mtime;		/*  4 */
-	time_t i_atime;		/*  4 */
-	time_t i_ctime;		/*  4 */
-	_nxtnt_t i_num_xtnts;	/*  2 */
-	mode_t i_mode;		/*  2 */
-	muid_t i_uid;		/*  2 */
-	mgid_t i_gid;		/*  2 */
-	nlink_t i_nlink;	/*  2 */
-	char i_zero[4];		/*  4 */
-	_ftype_t i_type;	/*  1 */
-	unsigned char i_status;	/*  1 */
+	char		i_reserved[16];	/* 16 */
+	qnx4_off_t	i_size;		/*  4 */
+	qnx4_xtnt_t	i_first_xtnt;	/*  8 */
+	__u32		i_xblk;		/*  4 */
+	__s32		i_ftime;	/*  4 */
+	__s32		i_mtime;	/*  4 */
+	__s32		i_atime;	/*  4 */
+	__s32		i_ctime;	/*  4 */
+	qnx4_nxtnt_t	i_num_xtnts;	/*  2 */
+	qnx4_mode_t	i_mode;		/*  2 */
+	qnx4_muid_t	i_uid;		/*  2 */
+	qnx4_mgid_t	i_gid;		/*  2 */
+	qnx4_nlink_t	i_nlink;	/*  2 */
+	__u8		i_zero[4];	/*  4 */
+	qnx4_ftype_t	i_type;		/*  1 */
+	__u8		i_status;	/*  1 */
 };
 
 #endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/linux/qnx4_fs_sb.h linux.15p9/include/linux/qnx4_fs_sb.h
--- linux.vanilla/include/linux/qnx4_fs_sb.h	Mon Aug 31 21:01:35 1998
+++ linux.15p9/include/linux/qnx4_fs_sb.h	Wed Jan 26 23:44:15 2000
@@ -2,8 +2,8 @@
  *  Name                         : qnx4_fs_sb.h
  *  Author                       : Richard Frowijn
  *  Function                     : qnx4 superblock definitions
- *  Version                      : 1.0
- *  Last modified                : 20-05-1998
+ *  Version                      : 1.0.2
+ *  Last modified                : 2000-01-06
  * 
  *  History                      : 23-03-1998 created
  * 
@@ -11,17 +11,17 @@
 #ifndef _QNX4_FS_SB
 #define _QNX4_FS_SB
 
-#include <linux/qnxtypes.h>
+#include <linux/qnx4_fs.h>
 
 /*
  * qnx4 super-block data in memory
  */
 
 struct qnx4_sb_info {
-	struct buffer_head *sb_buf;	/* superblock buffer */
-	struct qnx4_super_block *sb;	/* our superblock */
-	unsigned int Version;	/* may be useful */
-	struct qnx4_inode_entry *BitMap;	/* useful */
+	struct buffer_head	*sb_buf;	/* superblock buffer */
+	struct qnx4_super_block	*sb;		/* our superblock */
+	unsigned int		Version;	/* may be useful */
+	struct qnx4_inode_entry	*BitMap;	/* useful */
 };
 
 #endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/linux/qnxtypes.h linux.15p9/include/linux/qnxtypes.h
--- linux.vanilla/include/linux/qnxtypes.h	Mon Aug 31 21:01:35 1998
+++ linux.15p9/include/linux/qnxtypes.h	Tue Jan 18 00:59:09 2000
@@ -2,27 +2,28 @@
  *  Name                         : qnxtypes.h
  *  Author                       : Richard Frowijn
  *  Function                     : standard qnx types
- *  Version                      : 1.0
- *  Last modified                : 22-03-1998
- * 
+ *  Version                      : 1.0.2
+ *  Last modified                : 2000-01-06
+ *
  *  History                      : 22-03-1998 created
- * 
+ *
  */
 
 #ifndef _QNX4TYPES_H
 #define _QNX4TYPES_H
 
-typedef unsigned short _nxtnt_t;
-typedef unsigned char _ftype_t;
+typedef __u16 qnx4_nxtnt_t;
+typedef __u8  qnx4_ftype_t;
 
 typedef struct {
-	long xtnt_blk;
-	long xtnt_size;
-} _xtnt_t;
+	__u32 xtnt_blk;
+	__u32 xtnt_size;
+} qnx4_xtnt_t;
 
-typedef unsigned short muid_t;
-typedef unsigned short mgid_t;
-typedef unsigned long qnx_off_t;
-typedef unsigned short qnx_nlink_t;
+typedef __u16 qnx4_mode_t;
+typedef __u16 qnx4_muid_t;
+typedef __u16 qnx4_mgid_t;
+typedef __u32 qnx4_off_t;
+typedef __u16 qnx4_nlink_t;
 
 #endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/linux/stallion.h linux.15p9/include/linux/stallion.h
--- linux.vanilla/include/linux/stallion.h	Wed Feb  4 22:52:16 1998
+++ linux.15p9/include/linux/stallion.h	Mon Feb  7 12:07:56 2000
@@ -4,7 +4,7 @@
  *	stallion.h  -- stallion multiport serial driver.
  *
  *	Copyright (C) 1996-1998  Stallion Technologies (support@stallion.oz.au).
- *	Copyright (C) 1994-1996  Greg Ungerer (gerg@stallion.oz.au).
+ *	Copyright (C) 1994-1996  Greg Ungerer.
  *
  *	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
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/math-emu/op-1.h linux.15p9/include/math-emu/op-1.h
--- linux.vanilla/include/math-emu/op-1.h	Tue Jan  4 21:19:03 2000
+++ linux.15p9/include/math-emu/op-1.h	Fri Jan 14 15:56:16 2000
@@ -199,25 +199,25 @@
 
 #define _FP_DIV_MEAT_1_udiv_norm(fs, R, X, Y)				\
   do {									\
-    _FP_W_TYPE _nh, _nl, _q, _r;					\
+    _FP_W_TYPE _nh, _nl, _q, _r, _y;					\
 									\
     /* Normalize Y -- i.e. make the most significant bit set.  */	\
-    Y##_f <<= _FP_WFRACXBITS_##fs - 1;					\
+    _y = Y##_f << _FP_WFRACXBITS_##fs;					\
 									\
     /* Shift X op correspondingly high, that is, up one full word.  */	\
-    if (X##_f <= Y##_f)							\
+    if (X##_f < Y##_f)							\
       {									\
+	R##_e--;							\
 	_nl = 0;							\
 	_nh = X##_f;							\
       }									\
     else								\
       {									\
-	R##_e++;							\
-	_nl = X##_f << (_FP_W_TYPE_SIZE-1);				\
+	_nl = X##_f << (_FP_W_TYPE_SIZE - 1);				\
 	_nh = X##_f >> 1;						\
       }									\
     									\
-    udiv_qrnnd(_q, _r, _nh, _nl, Y##_f);				\
+    udiv_qrnnd(_q, _r, _nh, _nl, _y);					\
     R##_f = _q | (_r != 0);						\
   } while (0)
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/discovery.h linux.15p9/include/net/irda/discovery.h
--- linux.vanilla/include/net/irda/discovery.h	Sat Aug 14 02:26:01 1999
+++ linux.15p9/include/net/irda/discovery.h	Mon Feb  7 13:23:13 2000
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Apr  6 16:53:53 1999
- * Modified at:   Thu Apr 22 11:04:56 1999
+ * Modified at:   Tue Oct  5 10:05:10 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -39,28 +39,30 @@
 #define DISCOVERY_EXPIRE_TIMEOUT 6*HZ
 #define DISCOVERY_DEFAULT_SLOTS  0
 
+#define NICKNAME_MAX_LEN 21
+
 /*
  * The DISCOVERY structure is used for both discovery requests and responses
  */
 typedef struct {
-	QUEUE queue;             /* Must be first! */
+	queue_t q;               /* Must be first! */
 
 	__u32      saddr;        /* Which link the device was discovered */
 	__u32      daddr;        /* Remote device address */
 	LAP_REASON condition;    /* More info about the discovery */
 
 	__u16_host_order hints;  /* Discovery hint bits */
-	__u8       charset;
-	char       info[32];     /* Usually the name of the device */
-	__u8       info_len;     /* Length of device info field */
+	__u8       charset;      /* Encoding of nickname */
+	char       nickname[22]; /* The name of the device (21 bytes + \0) */
+	int        name_len;     /* Lenght of nickname */
 
 	int        gen_addr_bit; /* Need to generate a new device address? */
 	int        nslots;       /* Number of slots to use when discovering */
-	int        timestamp;    /* Time discovered */
+	unsigned long timestamp; /* Time discovered */
 } discovery_t;
 
 void irlmp_add_discovery(hashbin_t *cachelog, discovery_t *discovery);
 void irlmp_add_discovery_log(hashbin_t *cachelog, hashbin_t *log);
-void irlmp_expire_discoveries(hashbin_t *log, int saddr, int force);
+void irlmp_expire_discoveries(hashbin_t *log, __u32 saddr, int force);
 
 #endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/dongle.h linux.15p9/include/net/irda/dongle.h
--- linux.vanilla/include/net/irda/dongle.h	Wed Oct 20 01:12:51 1999
+++ linux.15p9/include/net/irda/dongle.h	Thu Jan  1 01:00:00 1970
@@ -1,52 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      dongle.h
- * Version:       
- * Description:   
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Wed Oct 21 22:47:12 1998
- * Modified at:   Sun May 16 13:40:03 1999
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
- *      
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
- *     the License, or (at your option) any later version.
- *  
- *     Neither Dag Brattli nor University of Tromsř admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
- *     
- ********************************************************************/
-
-#ifndef DONGLE_H
-#define DONGLE_H
-
-#include <net/irda/qos.h>
-
-/* These are the currently known dongles */
-typedef enum {
-	TEKRAM_DONGLE,
-	ESI_DONGLE,
-	ACTISYS_DONGLE,
-	ACTISYS_PLUS_DONGLE,
-	GIRBIL_DONGLE,
-	LITELINK_DONGLE,
-	AIRPORT_DONGLE,
-} IRDA_DONGLE;
-
-struct irda_device;
-
-struct dongle {
-	IRDA_DONGLE type;
-	void (*open)(struct irda_device *, int type);
-	void (*close)(struct irda_device *);
-	void (*reset)( struct irda_device *);
-	void (*change_speed)( struct irda_device *, int baudrate);
-	void (*qos_init)( struct irda_device *, struct qos_info *);
-};
-
-#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/ircomm_common.h linux.15p9/include/net/irda/ircomm_common.h
--- linux.vanilla/include/net/irda/ircomm_common.h	Sat Aug 14 02:26:51 1999
+++ linux.15p9/include/net/irda/ircomm_common.h	Thu Jan  1 01:00:00 1970
@@ -1,270 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      ircomm_common.h
- * Version:       
- * Description:   An implementation of IrCOMM service interface and state machine 
- * Status:        Experimental.
- * Author:        Takahide Higuchi <thiguchi@pluto.dti.ne.jp>
- *
- *     Copyright (c) 1998-1999, Takahide Higuchi, <thiguchi@pluto.dti.ne.jp>,
- *     All Rights Reserved.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     I, Takahide Higuchi, provide no warranty for any of this software.
- *     This material is provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#ifndef IRCOMM_H
-#define IRCOMM_H
-
-/* #define DEBUG(n, args...) printk( KERN_DEBUG args) */ /* enable all debug message */
-
-#include <linux/types.h>
-#include <net/irda/irmod.h> 
-
-typedef enum {
-        COMM_IDLE,
-
-	COMM_DISCOVERY_WAIT,
-	COMM_QUERYPARAM_WAIT,
-	COMM_QUERYLSAP_WAIT,
-
-	COMM_WAITI,
-	COMM_WAITR,
-	COMM_CONN,
-} IRCOMM_STATE;
-
-/* IrCOMM Events */
-typedef enum {
-	IRCOMM_CONNECT_REQUEST,
-	TTP_CONNECT_INDICATION,
-	LMP_CONNECT_INDICATION,
-
-	TTP_CONNECT_CONFIRM,
-	TTP_DISCONNECT_INDICATION,
-	LMP_CONNECT_CONFIRM,
-	LMP_DISCONNECT_INDICATION,
-
-	IRCOMM_CONNECT_RESPONSE,
-	IRCOMM_DISCONNECT_REQUEST,
-
-	TTP_DATA_INDICATION,
-	IRCOMM_DATA_REQUEST,
-	LMP_DATA_INDICATION,
-	IRCOMM_CONTROL_REQUEST,
-	
-	DISCOVERY_INDICATION,
-	GOT_PARAMETERS,
-	GOT_LSAPSEL,
-	QUERYIAS_ERROR,
-
-} IRCOMM_EVENT;
-
-typedef enum {
-	TX_READY,
-	TX_BUSY,
-
-	IAS_PARAM,
-	CONTROL_CHANNEL,
-} IRCOMM_CMD;
-
-
-
-#define IRCOMM_MAGIC            0x434f4d4d
-#define COMM_INIT_CTRL_PARAM    3          /* length of initial control parameters */
-#define COMM_HEADER_SIZE        1          /* length of clen field */
-#define COMM_MAX_HEADER_SIZE    (TTP_MAX_HEADER+COMM_HEADER_SIZE)
-#define COMM_DEFAULT_SDU_SIZE   (64 - COMM_HEADER_SIZE)
-#define IRCOMM_MAX_CONNECTION   1          /* Don't change for now */
-
-
-
-
-#define UNKNOWN         0x00            /* not defined yet. */
-/* we use 9wire if servicetype=DEFAULT, but is it good? */
-#define DEFAULT         0x0a            /* private number */
-#define THREE_WIRE_RAW	0x01		/* bit 0 */
-#define THREE_WIRE	0x02		/* bit 1 */
-#define NINE_WIRE	0x04		/* bit 2 */
-#define CENTRONICS	0x08		/* bit 3 */
-
-#define SERIAL		0x01		/* bit 0 */
-#define PARALLEL	0x02		/* bit 1 */
-
-
-#define SERVICETYPE 0x00
-#define PORT_TYPE 0x01
-#define PORT_NAME 0x02
-#define FIXED_PORT_NAME 0x82
-
-#define DATA_RATE 0x10
-#define DATA_FORMAT 0x11
-#define FLOW_CONTROL 0x12
-#define XON_XOFF_CHAR 0x13
-#define ENQ_ACK_CHAR 0x14
-#define LINESTATUS 0x15
-#define BREAK_SIGNAL 0x16
-
-#define DTELINE_STATE 0x20
-#define DCELINE_STATE 0x21
-#define POLL_FOR_LINE_SETTINGS 0x22
-
-#define STATUS_QUERY 0x30
-#define SET_BUSY_TIMEOUT 0x31
-#define IEEE1284_MODE_SUPPORT 0x32
-#define IEEE1284_DEVICEID 0x33
-#define IEEE1284_MODE 0x34
-#define IEEE1284_ECP_EPP_DATA_TRANSFER 0x35
-
-/*  parameters of FLOW_CONTROL  */
-
-#define USE_RTS 0x08  /* use RTS on output */
-#define USE_CTS 0x04  /* use CTS on input */
-#define USE_DTR 0x20  /* use DTR on output */
-
-/*  parameters of DTELINE_STATE  */
-
-#define DELTA_DTR 0x01
-#define DELTA_RTS 0x02
-#define MCR_DTR 0x04
-#define MCR_RTS 0x08
-
-/*  parameters of DCELINE_STATE  */
-
-#define DELTA_CTS 0x01
-#define DELTA_DSR 0x02
-#define DELTA_RI  0x04 
-#define DELTA_DCD 0x08
-#define MSR_CTS   0x10
-#define MSR_DSR   0x20
-#define MSR_RI    0x40 
-#define MSR_DCD   0x80
-
-/*  parameters of DATA_FORMAT */
-
-#define IRCOMM_WLEN5   0x00       /* word length is 5bit */
-#define IRCOMM_WLEN6   0x01       /* word length is 6bit */
-#define IRCOMM_WLEN7   0x02       /* word length is 7bit */
-#define IRCOMM_WLEN8   0x03       /* word length is 8bit */
-
-#define IRCOMM_STOP2   0x04       /* 2 stop bits mode */
-#define IRCOMM_PARENB  0x08       /* parity enable */
-#define IRCOMM_PARODD  0x00       /*  odd parity */
-#define IRCOMM_PAREVEN 0x10       /*  even parity */
-#define IRCOMM_PARMARK 0x20
-#define IRCOMM_PARSPC  0x30
-
-/*  parameters of LINE_STATUS */
-
-#define LSR_OE     0x02    /* Overrun error indicator */
-#define LSR_PE     0x04    /* Parity error indicator */
-#define LSR_FE     0x08    /* Frame error indicator */
-#define LSR_BI     0x01    /* Break interrupt indicator */
-
-
-struct ircomm_cb {
-	int magic;
-	int state;          /* Current state of IrCOMM layer: 
-			     *  DISCOVERY,COMM_IDLE, COMM_WAITR,
-			     *  COMM_WAITI, COMM_CONN
-			     */
-	int in_use;
-	int null_modem_mode;     /* switch for null modem emulation */
-	int ttp_stop;
-
-	__u32 tx_max_sdu_size;          
-	__u32 rx_max_sdu_size;
-	__u8 max_header_size;
-
- 	__u32 daddr;        /* Device address of the peer device */ 
-	__u32 saddr;
-	__u32 skey;
-	__u32 ckey;
-	int                 queryias_lock;
-	int                 ias_type;
-	int disconnect_priority; /* P_NORMAL or P_HIGH. see irttp.h */
-	struct notify_t notify;     /* container of callbacks */
-	void (*d_handler)(struct ircomm_cb *self);
-
-	int control_ch_pending;
-	struct sk_buff *ctrl_skb;   /* queue of control channel */
-
-	__u8 dlsap;          /* IrLMP dlsap */
-	__u8 lsap;           /* sap of local device */ 
-	struct tsap_cb *tsap;          /* IrTTP/LMP handle */
-	struct qos_info *qos;         /* Quality of Service */
-	int reason;          /* I don't know about reason: 
-				see Irlmp.c or somewhere :p)*/ 
-	int peer_cap;        /* capability of peer device */
-
-	struct wait_queue   *discovery_wait;
-	struct wait_queue   *ias_wait;
-
-	/* statistics */
-	int                 tx_packets;
-	int                 rx_packets;
-	int                 tx_controls;
-	int                 pending_control_tuples;
-	int                 ignored_control_tuples;
-
-	__u8 pi ;            /* instruction of control channel*/ 
-
-	__u8 port_type;
-	__u8 peer_port_type;
-
-	__u8 servicetype;    
-	__u8 peer_servicetype;    
-	__u8 data_format;   
-	__u8 peer_data_format;   
-	__u8 flow_ctrl;
-	__u8 peer_flow_ctrl;
-	__u8 line_status;
-	__u8 peer_line_status;
-	__u8 break_signal;
-	__u8 peer_break_signal;
-	__u8 dte;
-	__u8 peer_dte;
-	__u8 dce;
-	__u8 peer_dce;
-	__u8 xon_char;
-	__u8 xoff_char;
-	__u8 peer_xon_char;
-	__u8 peer_xoff_char;
-	__u8 enq_char;
-	__u8 ack_char;
-	__u8 peer_enq_char;
-	__u8 peer_ack_char;
-	__u8 busy_timeout;
-	__u8 peer_busy_timeout;
-	__u8 ecp_epp_mode;
-	__u8 peer_ecp_epp_mode;
-	__u8 channel_or_addr;
-	__u8 peer_channel_or_addr;
-	
-	__u32 data_rate;
-	__u32 peer_data_rate;
-	char port_name[33];
-	int port_name_critical;
-};
-
-void ircomm_connect_request(struct ircomm_cb *self, __u8 servicetype);
-void ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata,
-			     __u32 maxsdusize);
-void ircomm_disconnect_request(struct ircomm_cb *self,
-			       struct sk_buff *userdata, int priority);
-int ircomm_data_request(struct ircomm_cb *self,
-			struct sk_buff *userdata);
-void ircomm_control_request(struct ircomm_cb *self, __u8 instruction);
-
-void ircomm_parse_tuples(struct ircomm_cb *self, struct sk_buff *skb, int type);
-
-struct ircomm_cb *ircomm_open_instance(struct notify_t notify);
-int ircomm_close_instance(struct ircomm_cb *self);
-
-
-#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/ircomm_core.h linux.15p9/include/net/irda/ircomm_core.h
--- linux.vanilla/include/net/irda/ircomm_core.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/include/net/irda/ircomm_core.h	Mon Feb  7 13:55:26 2000
@@ -0,0 +1,107 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_core.h
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Wed Jun  9 08:58:43 1999
+ * Modified at:   Mon Dec 13 11:52:29 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#ifndef IRCOMM_CORE_H
+#define IRCOMM_CORE_H
+
+#include <net/irda/irda.h>
+#include <net/irda/ircomm_event.h>
+
+#define IRCOMM_MAGIC 0x98347298
+#define IRCOMM_HEADER_SIZE 1
+
+struct ircomm_cb;   /* Forward decl. */
+
+/*
+ * A small call-table, so we don't have to check the service-type whenever
+ * we want to do something
+ */
+typedef struct {
+	int (*data_request)(struct ircomm_cb *, struct sk_buff *, int clen);
+	int (*connect_request)(struct ircomm_cb *, struct sk_buff *, 
+			       struct ircomm_info *);
+	int (*connect_response)(struct ircomm_cb *, struct sk_buff *);
+	int (*disconnect_request)(struct ircomm_cb *, struct sk_buff *, 
+				  struct ircomm_info *);	
+} call_t;
+
+struct ircomm_cb {
+	queue_t queue;
+	magic_t magic;
+
+	notify_t notify;
+	call_t   issue;
+
+	int state;
+	int line;            /* Which TTY line we are using */
+
+	struct tsap_cb *tsap;
+	struct lsap_cb *lsap;
+	
+	__u8 dlsap_sel;      /* Destination LSAP/TSAP selector */
+	__u8 slsap_sel;      /* Source LSAP/TSAP selector */
+
+	__u32 saddr;         /* Source device address (link we are using) */
+	__u32 daddr;         /* Destination device address */
+
+	int max_header_size; /* Header space we must reserve for each frame */
+	int max_data_size;   /* The amount of data we can fill in each frame */
+
+	LOCAL_FLOW flow_status; /* Used by ircomm_lmp */
+	int pkt_count;          /* Number of frames we have sent to IrLAP */
+
+	__u8 service_type;
+};
+
+extern hashbin_t *ircomm;
+
+struct ircomm_cb *ircomm_open(notify_t *notify, __u8 service_type, int line);
+int ircomm_close(struct ircomm_cb *self);
+
+int ircomm_data_request(struct ircomm_cb *self, struct sk_buff *skb);
+void ircomm_data_indication(struct ircomm_cb *self, struct sk_buff *skb);
+void ircomm_process_data(struct ircomm_cb *self, struct sk_buff *skb);
+int ircomm_control_request(struct ircomm_cb *self, struct sk_buff *skb);
+int ircomm_connect_request(struct ircomm_cb *self, __u8 dlsap_sel, 
+			   __u32 saddr, __u32 daddr, struct sk_buff *skb,
+			   __u8 service_type);
+void ircomm_connect_indication(struct ircomm_cb *self, struct sk_buff *skb,
+			       struct ircomm_info *info);
+void ircomm_connect_confirm(struct ircomm_cb *self, struct sk_buff *skb,
+			    struct ircomm_info *info);
+int ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata);
+int ircomm_disconnect_request(struct ircomm_cb *self, struct sk_buff *userdata);
+void ircomm_disconnect_indication(struct ircomm_cb *self, struct sk_buff *skb,
+				  struct ircomm_info *info);
+void ircomm_flow_request(struct ircomm_cb *self, LOCAL_FLOW flow);
+
+#define ircomm_is_connected(self) (self->state == IRCOMM_CONN)
+
+#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/ircomm_event.h linux.15p9/include/net/irda/ircomm_event.h
--- linux.vanilla/include/net/irda/ircomm_event.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/include/net/irda/ircomm_event.h	Tue Jan 18 01:08:18 2000
@@ -0,0 +1,84 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_event.h
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Jun  6 23:51:13 1999
+ * Modified at:   Thu Jun 10 08:36:25 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#ifndef IRCOMM_EVENT_H
+#define IRCOMM_EVENT_H
+
+typedef enum {
+        IRCOMM_IDLE,
+        IRCOMM_WAITI,
+        IRCOMM_WAITR,
+        IRCOMM_CONN,
+} IRCOMM_STATE;
+
+/* IrCOMM Events */
+typedef enum {
+        IRCOMM_CONNECT_REQUEST,
+        IRCOMM_CONNECT_RESPONSE,
+        IRCOMM_TTP_CONNECT_INDICATION,
+	IRCOMM_LMP_CONNECT_INDICATION,
+        IRCOMM_TTP_CONNECT_CONFIRM,
+	IRCOMM_LMP_CONNECT_CONFIRM,
+
+        IRCOMM_LMP_DISCONNECT_INDICATION,
+	IRCOMM_TTP_DISCONNECT_INDICATION,
+        IRCOMM_DISCONNECT_REQUEST,
+
+        IRCOMM_TTP_DATA_INDICATION,
+	IRCOMM_LMP_DATA_INDICATION,
+        IRCOMM_DATA_REQUEST,
+        IRCOMM_CONTROL_REQUEST,
+        IRCOMM_CONTROL_INDICATION,
+} IRCOMM_EVENT;
+
+/*
+ * Used for passing information through the state-machine
+ */
+struct ircomm_info {
+        __u32     saddr;               /* Source device address */
+        __u32     daddr;               /* Destination device address */
+        __u8      dlsap_sel;
+        LM_REASON reason;              /* Reason for disconnect */
+	__u32     max_data_size;
+	__u32     max_header_size;
+
+	struct qos_info *qos;
+};
+
+extern char *ircomm_state[];
+extern char *ircomm_event[];
+
+struct ircomm_cb;   /* Forward decl. */
+
+int ircomm_do_event(struct ircomm_cb *self, IRCOMM_EVENT event,
+		    struct sk_buff *skb, struct ircomm_info *info);
+void ircomm_next_state(struct ircomm_cb *self, IRCOMM_STATE state);
+
+#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/ircomm_lmp.h linux.15p9/include/net/irda/ircomm_lmp.h
--- linux.vanilla/include/net/irda/ircomm_lmp.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/include/net/irda/ircomm_lmp.h	Mon Feb  7 13:55:27 2000
@@ -0,0 +1,65 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_lmp.h
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Wed Jun  9 10:06:07 1999
+ * Modified at:   Fri Aug 13 07:32:32 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#ifndef IRCOMM_LMP_H
+#define IRCOMM_LMP_H
+
+#include <net/irda/ircomm_core.h>
+#include <net/irda/ircomm_event.h>
+
+int ircomm_open_lsap(struct ircomm_cb *self);
+int  ircomm_lmp_connect_request(struct ircomm_cb *self, 
+				struct sk_buff *userdata, 
+				struct ircomm_info *info);
+int  ircomm_lmp_connect_response(struct ircomm_cb *self, struct sk_buff *skb);
+int  ircomm_lmp_disconnect_request(struct ircomm_cb *self, 
+				   struct sk_buff *userdata, 
+				   struct ircomm_info *info);
+int  ircomm_lmp_data_request(struct ircomm_cb *self, struct sk_buff *skb, 
+			     int clen);
+int  ircomm_lmp_control_request(struct ircomm_cb *self, 
+			       struct sk_buff *userdata);
+int  ircomm_lmp_data_indication(void *instance, void *sap,
+				struct sk_buff *skb);
+void ircomm_lmp_connect_confirm(void *instance, void *sap,
+				struct qos_info *qos, 
+				__u32 max_sdu_size, 
+				__u8 max_header_size,
+				struct sk_buff *skb);
+void ircomm_lmp_connect_indication(void *instance, void *sap,
+				   struct qos_info *qos,
+				   __u32 max_sdu_size,
+				   __u8 max_header_size,
+				   struct sk_buff *skb);
+void ircomm_lmp_disconnect_indication(void *instance, void *sap, 
+				      LM_REASON reason,
+				      struct sk_buff *skb);
+
+#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/ircomm_param.h linux.15p9/include/net/irda/ircomm_param.h
--- linux.vanilla/include/net/irda/ircomm_param.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/include/net/irda/ircomm_param.h	Mon Feb  7 13:55:26 2000
@@ -0,0 +1,150 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_param.h
+ * Version:       1.0
+ * Description:   Parameter handling for the IrCOMM protocol
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Mon Jun  7 08:47:28 1999
+ * Modified at:   Wed Aug 25 13:46:33 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#ifndef IRCOMM_PARAMS_H
+#define IRCOMM_PARAMS_H
+
+#include <net/irda/parameters.h>
+
+/* Parameters common to all service types */
+#define IRCOMM_SERVICE_TYPE     0x00
+#define IRCOMM_PORT_TYPE        0x01 /* Only used in LM-IAS */
+#define IRCOMM_PORT_NAME        0x02 /* Only used in LM-IAS */
+
+/* Parameters for both 3 wire and 9 wire */
+#define IRCOMM_DATA_RATE        0x10
+#define IRCOMM_DATA_FORMAT      0x11
+#define IRCOMM_FLOW_CONTROL     0x12
+#define IRCOMM_XON_XOFF         0x13
+#define IRCOMM_ENQ_ACK          0x14
+#define IRCOMM_LINE_STATUS      0x15
+#define IRCOMM_BREAK            0x16
+
+/* Parameters for 9 wire */
+#define IRCOMM_DTE              0x20
+#define IRCOMM_DCE              0x21
+#define IRCOMM_POLL             0x22
+
+/* Service type (details) */
+#define IRCOMM_3_WIRE_RAW       0x01
+#define IRCOMM_3_WIRE           0x02
+#define IRCOMM_9_WIRE           0x04
+#define IRCOMM_CENTRONICS       0x08
+
+/* Port type (details) */
+#define IRCOMM_SERIAL           0x00
+#define IRCOMM_PARALLEL         0x01
+
+/* Data format (details) */
+#define IRCOMM_WSIZE_5          0x00
+#define IRCOMM_WSIZE_6          0x01
+#define IRCOMM_WSIZE_7          0x02
+#define IRCOMM_WSIZE_8          0x03
+
+#define IRCOMM_1_STOP_BIT       0x00
+#define IRCOMM_2_STOP_BIT       0x04 /* 1.5 if char len 5 */
+
+#define IRCOMM_PARITY_DISABLE   0x00
+#define IRCOMM_PARITY_ENABLE    0x08
+
+#define IRCOMM_PARITY_ODD       0x00
+#define IRCOMM_PARITY_EVEN      0x10
+#define IRCOMM_PARITY_MARK      0x20
+#define IRCOMM_PARITY_SPACE     0x30
+
+/* Flow control */
+#define IRCOMM_XON_XOFF_IN      0x01
+#define IRCOMM_XON_XOFF_OUT     0x02
+#define IRCOMM_RTS_CTS_IN       0x04
+#define IRCOMM_RTS_CTS_OUT      0x08
+#define IRCOMM_DSR_DTR_IN       0x10
+#define IRCOMM_DSR_DTR_OUT      0x20
+#define IRCOMM_ENQ_ACK_IN       0x40
+#define IRCOMM_ENQ_ACK_OUT      0x80
+
+/* Line status */
+#define IRCOMM_OVERRUN_ERROR    0x02
+#define IRCOMM_PARITY_ERROR     0x04
+#define IRCOMM_FRAMING_ERROR    0x08
+
+/* DTE (Data terminal equipment) line settings */
+#define IRCOMM_DELTA_DTR        0x01
+#define IRCOMM_DELTA_RTS        0x02
+#define IRCOMM_DTR              0x04
+#define IRCOMM_RTS              0x08
+
+/* DCE (Data communications equipment) line settings */
+#define IRCOMM_DELTA_CTS        0x01  /* Clear to send has changed */
+#define IRCOMM_DELTA_DSR        0x02  /* Data set ready has changed */
+#define IRCOMM_DELTA_RI         0x04  /* Ring indicator has changed */
+#define IRCOMM_DELTA_CD         0x08  /* Carrier detect has changed */
+#define IRCOMM_CTS              0x10  /* Clear to send is high */
+#define IRCOMM_DSR              0x20  /* Data set ready is high */
+#define IRCOMM_RI               0x40  /* Ring indicator is high */
+#define IRCOMM_CD               0x80  /* Carrier detect is high */
+#define IRCOMM_DCE_DELTA_ANY    0x0f
+
+/*
+ * Parameter state
+ */
+struct ircomm_params {
+	/* General control params */
+	__u8  service_type;
+	__u8  port_type;
+	char  port_name[32];
+
+	/* Control params for 3- and 9-wire service type */
+	__u32 data_rate;         /* Data rate in bps */
+	__u8  data_format;
+	__u8  flow_control;
+	char  xonxoff[2];
+	char  enqack[2];
+	__u8  line_status;
+	__u8  _break;
+
+	__u8  null_modem;
+
+	/* Control params for 9-wire service type */
+	__u8 dte;
+	__u8 dce;
+	__u8 poll;
+
+	/* Control params for Centronics service type */
+};
+
+struct ircomm_tty_cb; /* Forward decl. */
+
+int ircomm_param_flush(struct ircomm_tty_cb *self);
+int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush);
+
+extern pi_param_info_t ircomm_param_info;
+
+#endif /* IRCOMM_PARAMS_H */
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/ircomm_ttp.h linux.15p9/include/net/irda/ircomm_ttp.h
--- linux.vanilla/include/net/irda/ircomm_ttp.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/include/net/irda/ircomm_ttp.h	Mon Feb  7 13:55:27 2000
@@ -0,0 +1,70 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_ttp.h
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Wed Jun  9 10:06:07 1999
+ * Modified at:   Fri Aug 13 07:32:22 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#ifndef IRCOMM_TTP_H
+#define IRCOMM_TTP_H
+
+#include <net/irda/ircomm_core.h>
+#include <net/irda/ircomm_event.h>
+
+int  ircomm_open_tsap(struct ircomm_cb *self);
+int  ircomm_ttp_connect_request(struct ircomm_cb *self, 
+				struct sk_buff *userdata, 
+				struct ircomm_info *info);
+int  ircomm_ttp_connect_response(struct ircomm_cb *self, struct sk_buff *skb);
+int  ircomm_ttp_disconnect_request(struct ircomm_cb *self, 
+				   struct sk_buff *userdata, 
+				   struct ircomm_info *info);
+int  ircomm_ttp_data_request(struct ircomm_cb *self, struct sk_buff *skb, 
+			     int clen);
+int  ircomm_ttp_control_request(struct ircomm_cb *self, 
+			       struct sk_buff *userdata);
+int  ircomm_ttp_data_indication(void *instance, void *sap,
+				struct sk_buff *skb);
+void ircomm_ttp_connect_confirm(void *instance, void *sap,
+				struct qos_info *qos, 
+				__u32 max_sdu_size, 
+				__u8 max_header_size,
+				struct sk_buff *skb);
+void ircomm_ttp_connect_indication(void *instance, void *sap,
+				   struct qos_info *qos,
+				   __u32 max_sdu_size,
+				   __u8 max_header_size,
+				   struct sk_buff *skb);
+void ircomm_ttp_disconnect_indication(void *instance, void *sap, 
+				      LM_REASON reason,
+				      struct sk_buff *skb);
+void ircomm_ttp_flow_indication(void *instance, void *sap, LOCAL_FLOW cmd);
+
+#endif
+
+
+
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/ircomm_tty.h linux.15p9/include/net/irda/ircomm_tty.h
--- linux.vanilla/include/net/irda/ircomm_tty.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/include/net/irda/ircomm_tty.h	Mon Feb  7 13:55:26 2000
@@ -0,0 +1,121 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_tty.h
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Jun  6 23:24:22 1999
+ * Modified at:   Sun Dec 12 15:57:38 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#ifndef IRCOMM_TTY_H
+#define IRCOMM_TTY_H
+
+#include <linux/serial.h>
+#include <linux/termios.h>
+#include <linux/timer.h>
+
+#include <net/irda/irias_object.h>
+#include <net/irda/ircomm_core.h>
+#include <net/irda/ircomm_param.h>
+
+#define IRCOMM_TTY_PORTS 32
+#define IRCOMM_TTY_MAGIC 0x3432
+#define IRCOMM_TTY_MAJOR 161
+#define IRCOMM_TTY_MINOR 0
+
+/*
+ * IrCOMM TTY driver state
+ */
+struct ircomm_tty_cb {
+	queue_t queue;            /* Must be first */
+	magic_t magic;
+
+	int state;                /* Connect state */
+
+	struct tty_struct *tty;
+	struct ircomm_cb *ircomm; /* IrCOMM layer instance */
+
+	struct sk_buff *tx_skb;   /* Transmit buffer */
+	struct sk_buff *ctrl_skb; /* Control data buffer */
+
+	/* Parameters */
+	struct ircomm_params settings;
+
+	__u8 service_type;        /* The service that we support */
+	int client;               /* True if we are a client */
+	LOCAL_FLOW flow;          /* IrTTP flow status */
+
+	int line;
+	__u32 flags;
+
+	__u8 dlsap_sel;
+	__u8 slsap_sel;
+
+	__u32 saddr;
+	__u32 daddr;
+
+	__u32 max_data_size;   /* Max data we can transmit in one packet */
+	__u32 max_header_size; /* The amount of header space we must reserve */
+
+	struct iriap_cb *iriap; /* Instance used for querying remote IAS */
+	struct ias_object* obj;
+	int skey;
+	int ckey;
+
+	struct termios	  normal_termios;
+	struct termios	  callout_termios;
+
+	struct wait_queue *open_wait;
+	struct wait_queue *close_wait;
+	struct timer_list watchdog_timer;
+	struct tq_struct  tqueue;
+
+        unsigned short    close_delay;
+        unsigned short    closing_wait; /* time to wait before closing */
+
+	long session;           /* Session of opening process */
+	long pgrp;		/* pgrp of opening process */
+	int  open_count;
+	int  blocked_open;	/* # of blocked opens */
+};
+
+void ircomm_tty_start(struct tty_struct *tty);
+void ircomm_tty_stop(struct tty_struct *tty);
+void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self);
+
+extern void ircomm_tty_change_speed(struct ircomm_tty_cb *self);
+extern int ircomm_tty_ioctl(struct tty_struct *tty, struct file *file, 
+			    unsigned int cmd, unsigned long arg);
+extern void ircomm_tty_set_termios(struct tty_struct *tty, 
+				   struct termios *old_termios);
+extern hashbin_t *ircomm_tty;
+
+#endif
+
+
+
+
+
+
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/ircomm_tty_attach.h linux.15p9/include/net/irda/ircomm_tty_attach.h
--- linux.vanilla/include/net/irda/ircomm_tty_attach.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/include/net/irda/ircomm_tty_attach.h	Mon Feb  7 13:55:26 2000
@@ -0,0 +1,96 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_tty_attach.h
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Wed Jun  9 15:55:18 1999
+ * Modified at:   Fri Dec 10 21:04:55 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#ifndef IRCOMM_TTY_ATTACH_H
+#define IRCOMM_TTY_ATTACH_H
+
+#include <net/irda/ircomm_tty.h>
+
+typedef enum {
+        IRCOMM_TTY_IDLE,
+	IRCOMM_TTY_SEARCH,
+        IRCOMM_TTY_QUERY_PARAMETERS,
+	IRCOMM_TTY_QUERY_LSAP_SEL,
+	IRCOMM_TTY_SETUP,
+        IRCOMM_TTY_READY,
+} IRCOMM_TTY_STATE;
+
+/* IrCOMM TTY Events */
+typedef enum {
+	IRCOMM_TTY_ATTACH_CABLE,
+	IRCOMM_TTY_DETACH_CABLE,
+	IRCOMM_TTY_DATA_REQUEST,
+	IRCOMM_TTY_DATA_INDICATION,
+	IRCOMM_TTY_DISCOVERY_REQUEST,
+	IRCOMM_TTY_DISCOVERY_INDICATION,
+	IRCOMM_TTY_CONNECT_CONFIRM,
+	IRCOMM_TTY_CONNECT_INDICATION,
+	IRCOMM_TTY_DISCONNECT_REQUEST,
+	IRCOMM_TTY_DISCONNECT_INDICATION,
+	IRCOMM_TTY_WD_TIMER_EXPIRED,
+	IRCOMM_TTY_GOT_PARAMETERS,
+	IRCOMM_TTY_GOT_LSAPSEL,
+} IRCOMM_TTY_EVENT;
+
+/* Used for passing information through the state-machine */
+struct ircomm_tty_info {
+        __u32     saddr;               /* Source device address */
+        __u32     daddr;               /* Destination device address */
+        __u8      dlsap_sel;
+};
+
+extern char *ircomm_state[];
+extern char *ircomm_event[];
+extern char *ircomm_tty_state[];
+
+int ircomm_tty_do_event(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event,
+			struct sk_buff *skb, struct ircomm_tty_info *info);
+void ircomm_tty_next_state(struct ircomm_tty_cb *self, IRCOMM_TTY_STATE state);
+
+
+int  ircomm_tty_attach_cable(struct ircomm_tty_cb *self);
+void ircomm_tty_detach_cable(struct ircomm_tty_cb *self);
+void ircomm_tty_connect_confirm(void *instance, void *sap, 
+				struct qos_info *qos, 
+				__u32 max_sdu_size, 
+				__u8 max_header_size, 
+				struct sk_buff *skb);
+void ircomm_tty_disconnect_indication(void *instance, void *sap, 
+				      LM_REASON reason,
+				      struct sk_buff *skb);
+void ircomm_tty_connect_indication(void *instance, void *sap, 
+				   struct qos_info *qos, 
+				   __u32 max_sdu_size,
+				   __u8 max_header_size, 
+				   struct sk_buff *skb);
+int ircomm_tty_send_initial_parameters(struct ircomm_tty_cb *self);
+void ircomm_tty_link_established(struct ircomm_tty_cb *self);
+
+#endif /* IRCOMM_TTY_ATTACH_H */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/irda.h linux.15p9/include/net/irda/irda.h
--- linux.vanilla/include/net/irda/irda.h	Sat Aug 14 02:26:51 1999
+++ linux.15p9/include/net/irda/irda.h	Mon Feb  7 13:09:51 2000
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irda.h
- * Version:       
- * Description:   
- * Status:        Experimental.
+ * Version:       1.0
+ * Description:   IrDA common include file for kernel internal use
+ * Status:        Stable
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Dec  9 21:13:12 1997
- * Modified at:   Mon May 10 09:51:13 1999
+ * Modified at:   Sat Dec 25 18:58:49 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -28,6 +28,10 @@
 #include <linux/config.h>
 #include <linux/skbuff.h>
 #include <linux/kernel.h>
+#include <linux/if.h>
+#include <linux/irda.h>
+
+typedef __u32 magic_t;
 
 #include <net/irda/qos.h>
 #include <net/irda/irqueue.h>
@@ -40,8 +44,16 @@
 #define FALSE 0
 #endif
 
-#define ALIGN __attribute__((aligned))
-#define PACK __attribute__((packed))
+#ifndef IRDA_MIN /* Lets not mix this MIN with other header files */
+#define IRDA_MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef ALIGN
+#  define ALIGN __attribute__((aligned))
+#endif
+#ifndef PACK
+#  define PACK __attribute__((packed))
+#endif
 
 
 #ifdef CONFIG_IRDA_DEBUG
@@ -51,14 +63,14 @@
 /* use 0 for production, 1 for verification, >2 for debug */
 #define IRDA_DEBUG_LEVEL 0
 
-#define DEBUG(n, args...) if (irda_debug >= (n)) printk(KERN_DEBUG args)
+#define IRDA_DEBUG(n, args...) (irda_debug >= (n)) ? (printk(KERN_DEBUG args)) : 0
 #define ASSERT(expr, func) \
 if(!(expr)) { \
         printk( "Assertion failed! %s,%s,%s,line=%d\n",\
         #expr,__FILE__,__FUNCTION__,__LINE__); \
         ##func}
 #else
-#define DEBUG(n, args...)
+#define IRDA_DEBUG(n, args...)
 #define ASSERT(expr, func)
 #endif /* CONFIG_IRDA_DEBUG */
 
@@ -66,12 +78,13 @@
 #define MESSAGE(args...) printk(KERN_INFO args)
 #define ERROR(args...)   printk(KERN_ERR args)
 
-#define MSECS_TO_JIFFIES(ms) (ms*HZ/1000)
+#define MSECS_TO_JIFFIES(ms) (((ms)*HZ+999)/1000)
 
 /*
- *  Magic numbers used by Linux/IR. Random numbers which must be unique to 
+ *  Magic numbers used by Linux-IrDA. Random numbers which must be unique to 
  *  give the best protection
  */
+
 #define IRTTY_MAGIC        0x2357
 #define LAP_MAGIC          0x1357
 #define LMP_MAGIC          0x4321
@@ -86,8 +99,9 @@
 #define IRLAN_MAGIC        0x754
 #define IAS_OBJECT_MAGIC   0x34234
 #define IAS_ATTRIB_MAGIC   0x45232
+#define IRDA_TASK_MAGIC    0x38423
 
-#define IAS_DEVICE_ID 0x5342 
+#define IAS_DEVICE_ID 0x0000 /* Defined by IrDA, IrLMP section 4.1 (page 68) */
 #define IAS_PNP_ID    0xd342
 #define IAS_OBEX_ID   0x34323
 #define IAS_IRLAN_ID  0x34234
@@ -102,7 +116,9 @@
 	__u32 saddr;          /* my local address */
 	__u32 daddr;          /* peer address */
 
-	struct ias_object *ias_obj;
+	struct lsap_cb *lsap; /* LSAP used by Ultra */
+	__u8  pid;            /* Protocol IP (PID) used by Ultra */
+
 	struct tsap_cb *tsap; /* TSAP used by this connection */
 	__u8 dtsap_sel;       /* remote TSAP address */
 	__u8 stsap_sel;       /* local TSAP address */
@@ -119,9 +135,13 @@
 	__u32 ckey;           /* IrLMP client handle */
 	__u32 skey;           /* IrLMP service handle */
 
+	struct ias_object *ias_obj;   /* Our service name + lsap in IAS */
+	struct iriap_cb *iriap;	      /* Used to query remote IAS */
+	struct ias_value *ias_result; /* Used by getsockopt(IRLMP_IAS_QUERY) */
+
 	int nslots;           /* Number of slots to use for discovery */
 
-	int errno;
+	int errno;            /* status of the IAS query */
 
 	struct sock *sk;
 	struct wait_queue *ias_wait;       /* Wait for LM-IAS answer */
@@ -141,39 +161,17 @@
 	__u8  byte[2];
 } __u16_host_order;
 
-/*
- *  Information monitored by some layers
+/* 
+ * Per-packet information we need to hide inside sk_buff 
+ * (must not exceed 48 bytes, check with struct sk_buff) 
  */
-struct irda_statistics
-{
-        int     rx_packets;             /* total packets received       */
-        int     tx_packets;             /* total packets transmitted    */
-        int     rx_errors;              /* bad packets received         */
-        int     tx_errors;              /* packet transmit problems     */
-        int     rx_dropped;             /* no space in linux buffers    */
-        int     tx_dropped;             /* no space available in linux  */
-	int     rx_compressed;
-	int     tx_compressed;
-	int     rx_bytes;               /* total bytes received         */
-	int     tx_bytes;               /* total bytes transmitted      */
-
-        int     multicast;              /* multicast packets received   */
-        int     collisions;
-	
-        /* detailed rx_errors: */
-        int     rx_length_errors;
-        int     rx_over_errors;         /* receiver ring buff overflow  */
-        int     rx_crc_errors;          /* recved pkt with crc error    */
-        int     rx_frame_errors;        /* recv'd frame alignment error */
-        int     rx_fifo_errors;         /* recv'r fifo overrun          */
-        int     rx_missed_errors;       /* receiver missed packet       */
-
-        /* detailed tx_errors */
-        int     tx_aborted_errors;
-        int     tx_carrier_errors;
-        int     tx_fifo_errors;
-        int     tx_heartbeat_errors;
-        int     tx_window_errors;
+struct irda_skb_cb {
+	magic_t magic;     /* Be sure that we can trust the information */
+	__u32   speed;     /* The Speed this frame should be sent with */
+	__u16     mtt;     /* Minimum turn around time */
+	int     xbofs;     /* Number of xbofs required, used by SIR mode */
+	__u8     line;     /* Used by IrCOMM in IrLPT mode */
+	void (*destructor)(struct sk_buff *skb); /* Used for flow control */
 };
 
 /* Misc status information */
@@ -222,21 +220,21 @@
 /*
  *  Notify structure used between transport and link management layers
  */
-struct notify_t {
+typedef struct {
 	int (*data_indication)(void *priv, void *sap, struct sk_buff *skb);
 	int (*udata_indication)(void *priv, void *sap, struct sk_buff *skb);
 	void (*connect_confirm)(void *instance, void *sap, 
 				struct qos_info *qos, __u32 max_sdu_size,
 				__u8 max_header_size, struct sk_buff *skb);
 	void (*connect_indication)(void *instance, void *sap, 
-				   struct qos_info *qos, __u32 max_sdu_size,
+				   struct qos_info *qos, __u32 max_sdu_size, 
 				   __u8 max_header_size, struct sk_buff *skb);
 	void (*disconnect_indication)(void *instance, void *sap, 
 				      LM_REASON reason, struct sk_buff *);
 	void (*flow_indication)(void *instance, void *sap, LOCAL_FLOW flow);
 	void *instance; /* Layer instance pointer */
 	char name[16];  /* Name of layer */
-};
+} notify_t;
 
 #define NOTIFY_MAX_NAME 16
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/irda_device.h linux.15p9/include/net/irda/irda_device.h
--- linux.vanilla/include/net/irda/irda_device.h	Sat Aug 14 02:26:51 1999
+++ linux.15p9/include/net/irda/irda_device.h	Mon Feb  7 13:23:13 2000
@@ -1,17 +1,16 @@
 /*********************************************************************
  *                
  * Filename:      irda_device.h
- * Version:       
- * Description:   
+ * Version:       0.9
+ * Description:   Contains various declarations used by the drivers
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Apr 14 12:41:42 1998
- * Modified at:   Wed May 19 08:44:48 1999
+ * Modified at:   Fri Jan 14 10:46:56 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
  *     Copyright (c) 1998 Thomas Davis, <ratbert@radiks.net>,
- *     Copyright (c) 1998 Haris Zukanovic, <haris@stud.cs.uit.no>
  *
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -35,12 +34,11 @@
 
 #include <linux/tty.h>
 #include <linux/netdevice.h>
-
 #include <asm/spinlock.h>
+#include <linux/irda.h>
 
 #include <net/irda/irda.h>
 #include <net/irda/qos.h>
-#include <net/irda/dongle.h>
 #include <net/irda/irqueue.h>
 #include <net/irda/irlap_frame.h>
 
@@ -53,34 +51,97 @@
 #define IFF_DMA		0x0020 /* Supports DMA transfer of data */
 #define IFF_SHM         0x0040 /* Supports shared memory data transfers */
 #define IFF_DONGLE      0x0080 /* Interface has a dongle attached */
-#define IFF_AIR         0x0100 /* Supports A(dvanced)IR standards */
+#define IFF_AIR         0x0100 /* Supports Advanced IR (AIR) standards */
 
 #define IO_XMIT 0x01
 #define IO_RECV 0x02
 
-struct dongle_q {
-	QUEUE q;
-	struct dongle *dongle;
+typedef enum {
+	IRDA_IRLAP, /* IrDA mode, and deliver to IrLAP */
+	IRDA_RAW,   /* IrDA mode */
+	SHARP_ASK,
+	TV_REMOTE,  /* Also known as Consumer Electronics IR */
+} INFRARED_MODE;
+
+typedef enum {
+	IRDA_TASK_INIT,        /* All tasks are initialized with this state */
+	IRDA_TASK_DONE,        /* Signals that the task is finished */
+	IRDA_TASK_WAIT,
+	IRDA_TASK_WAIT1,
+	IRDA_TASK_WAIT2,
+	IRDA_TASK_WAIT3,
+	IRDA_TASK_CHILD_INIT,  /* Initializing child task */
+	IRDA_TASK_CHILD_WAIT,  /* Waiting for child task to finish */
+	IRDA_TASK_CHILD_DONE   /* Child task is finished */
+} TASK_STATE;
+
+struct irda_task;
+typedef int (*TASK_CALLBACK) (struct irda_task *task);
+
+struct irda_task {
+	queue_t q;
+	magic_t magic;
+
+	TASK_STATE state;
+	TASK_CALLBACK function;
+	TASK_CALLBACK finished;
+
+	struct irda_task *parent;
+	struct timer_list timer;
+
+	void *instance; /* Instance being called */
+	void *param;    /* Parameter to be used by instance */
+};
+
+/* Dongle info */
+struct dongle_reg;
+typedef struct {
+	struct dongle_reg *issue;     /* Registration info */
+	struct device *dev;           /* Device we are attached to */
+	struct irda_task *speed_task; /* Task handling speed change */
+	struct irda_task *reset_task; /* Task handling reset */
+	__u32 speed;                  /* Current speed */
+
+	/* Callbacks to the IrDA device driver */
+	int (*set_mode)(struct device *, int mode);
+	int (*read)(struct device *dev, __u8 *buf, int len);
+	int (*write)(struct device *dev, __u8 *buf, int len);
+	int (*set_dtr_rts)(struct device *dev, int dtr, int rts);
+} dongle_t;
+
+/* Dongle registration info */
+struct dongle_reg {
+	queue_t q;         /* Must be first */
+	IRDA_DONGLE type;
+
+	void (*open)(dongle_t *dongle, struct qos_info *qos);
+	void (*close)(dongle_t *dongle);
+	int  (*reset)(struct irda_task *task);
+	int  (*change_speed)(struct irda_task *task);
 };
 
 /* Chip specific info */
-struct chipio_t {
-        int iobase, iobase2;  /* IO base */
-        int io_ext, io_ext2;  /* Length of iobase */
-	int membase;          /* Shared memory base */
+typedef struct {
+	int cfg_base;         /* Config register IO base */
+        int sir_base;         /* SIR IO base */
+	int fir_base;         /* FIR IO base */
+	int mem_base;         /* Shared memory base */
+        int sir_ext;          /* Length of SIR iobase */
+	int fir_ext;          /* Length of FIR iobase */
         int irq, irq2;        /* Interrupts used */
+        int dma, dma2;        /* DMA channel(s) used */
         int fifo_size;        /* FIFO size */
-
-        int dma, dma2;        /* DMA channel used */
         int irqflags;         /* interrupt flags (ie, SA_SHIRQ|SA_INTERRUPT) */
 	int direction;        /* Link direction, used by some FIR drivers */
-
-	int baudrate;         /* Currently used baudrate */
+	int enabled;          /* Powered on? */
+	int suspended;        /* Suspended by APM */
+	__u32 speed;          /* Currently used speed */
+	__u32 new_speed;      /* Speed we must change to when Tx is finished */
 	int dongle_id;        /* Dongle or transceiver currently used */
-};
+} chipio_t;
 
 /* IO buffer specific info (inspired by struct sk_buff) */
-struct iobuff_t {
+typedef struct {
 	int state;            /* Receiving state (transmit state not used) */
 	int in_frame;         /* True if receiving frame */
 
@@ -91,116 +152,95 @@
 	int len;	      /* length of data */
 	int truesize;	      /* total size of buffer */
 	__u16 fcs;
-
-	int flags;            /* Allocation flags (GFP_KERNEL | GFP_DMA ) */
-};
-
-/* 
- * This structure contains data that _we_ would have liked to be in the device
- * structure, but we don't want to mess it up more than it is already. Better 
- * to keep the data in separate structures! This structure abstracts common 
- * stuff from IrDA port implementations.
- */
-struct irda_device {
-	QUEUE q;               /* Must be first */
-
-        int  magic;	       /* Our magic bullet */
-	char name[16];         /* Name of device "irda0" */
-	char description[32];  /* Something like "irda0 <-> ttyS0" */
-
-	struct irlap_cb *irlap; /* The link layer we are connected to  */
-	struct device netdev;   /* Yes! we are some kind of netdevice */
-	struct enet_statistics stats;
-
- 	int flags;            /* Interface flags (see defs above) */
-
- 	void *priv;           /* Pointer to low level implementation */
-
-	struct qos_info qos;  /* QoS capabilities for this device */
-
-	struct chipio_t io;
-	struct iobuff_t tx_buff;
-	struct iobuff_t rx_buff;
-
-	struct dongle *dongle; /* Dongle driver */
-
-	spinlock_t lock;       /* For serializing operations */
-	
-	/* Media busy stuff */
-	int media_busy;
-	struct timer_list media_busy_timer;
-
-	/* Callbacks for driver specific implementation */
-        void (*change_speed)(struct irda_device *idev, int baud);
- 	int  (*is_receiving)(struct irda_device *);    /* receiving? */
-	void (*set_dtr_rts)(struct irda_device *idev, int dtr, int rts);
-	int  (*raw_write)(struct irda_device *idev, __u8 *buf, int len);
-	void (*wait_until_sent)(struct irda_device *);
-	void (*set_caddr)(struct irda_device *);      /* Set connection addr */
-};
-
-extern hashbin_t *irda_device;
+} iobuff_t;
 
 /* Function prototypes */
 int  irda_device_init(void);
 void irda_device_cleanup(void);
 
-int  irda_device_open(struct irda_device *, char *name, void *priv);
-void irda_device_close(struct irda_device *);
-
 /* Interface to be uses by IrLAP */
-inline void irda_device_set_media_busy(struct irda_device *, int status);
-inline int  irda_device_is_media_busy(struct irda_device *);
-inline int  irda_device_is_receiving(struct irda_device *);
-inline void irda_device_change_speed(struct irda_device *, int);
-
-inline struct qos_info *irda_device_get_qos(struct irda_device *self);
-int irda_device_txqueue_empty(struct irda_device *self);
-void irda_device_init_dongle(struct irda_device *self, int type);
-void irda_device_unregister_dongle(struct dongle *dongle);
-int irda_device_register_dongle(struct dongle *dongle);
-
-int irda_device_setup(struct device *dev);
+void irda_device_set_media_busy(struct device *dev, int status);
+int  irda_device_is_media_busy(struct device *dev);
+int  irda_device_is_receiving(struct device *dev);
+
+/* Interface for internal use */
+int  irda_device_txqueue_empty(struct device *dev);
+int  irda_device_set_raw_mode(struct device* self, int status);
+int  irda_device_set_dtr_rts(struct device *dev, int dtr, int rts);
+int  irda_device_change_speed(struct device *dev, __u32 speed);
+int  irda_device_setup(struct device *dev);
+
+/* Dongle interface */
+void irda_device_unregister_dongle(struct dongle_reg *dongle);
+int  irda_device_register_dongle(struct dongle_reg *dongle);
+dongle_t *irda_device_dongle_init(struct device *dev, int type);
+int irda_device_dongle_cleanup(dongle_t *dongle);
 
 void setup_dma(int channel, char *buffer, int count, int mode);
 
+void irda_task_delete(struct irda_task *task);
+int  irda_task_kick(struct irda_task *task);
+struct irda_task *irda_task_execute(void *instance, TASK_CALLBACK function, 
+				    TASK_CALLBACK finished, 
+				    struct irda_task *parent, void *param);
+void irda_task_next_state(struct irda_task *task, TASK_STATE state);
+
+extern const char *infrared_mode[];
+
 /*
  * Function irda_get_mtt (skb)
  *
  *    Utility function for getting the minimum turnaround time out of 
  *    the skb, where it has been hidden in the cb field.
  */
+#define irda_get_mtt(skb) (                                                 \
+        IRDA_MIN(10000,                                                     \
+                  (((struct irda_skb_cb *) skb->cb)->magic == LAP_MAGIC) ?  \
+                          ((struct irda_skb_cb *)(skb->cb))->mtt : 10000    \
+                 )							    \
+)
+
+#if 0
 extern inline __u16 irda_get_mtt(struct sk_buff *skb)
 {
 	__u16 mtt;
 
-	if (((struct irlap_skb_cb *)(skb->cb))->magic != LAP_MAGIC)
+	if (((struct irda_skb_cb *)(skb->cb))->magic != LAP_MAGIC)
 		mtt = 10000;
 	else
-		mtt = ((struct irlap_skb_cb *)(skb->cb))->mtt;
+		mtt = ((struct irda_skb_cb *)(skb->cb))->mtt;
 
 	ASSERT(mtt <= 10000, return 10000;);
 	
 	return mtt;
 }
+#endif
 
-extern inline void irda_device_set_dtr_rts(struct irda_device *self, int dtr,
-					   int rts)
-{
-	if (self->set_dtr_rts)
-		self->set_dtr_rts(self, dtr, rts);
-}
+/*
+ * Function irda_get_speed (skb)
+ *
+ *    Extact the speed this frame should be sent out with from the skb
+ *
+ */
+#define irda_get_speed(skb) (	                                        \
+	(((struct irda_skb_cb*) skb->cb)->magic == LAP_MAGIC) ? 	\
+                  ((struct irda_skb_cb *)(skb->cb))->speed : 9600 	\
+)
 
-extern inline int irda_device_raw_write(struct irda_device *self, __u8 *buf,
-					int len)
+#if 0
+extern inline __u32 irda_get_speed(struct sk_buff *skb)
 {
-	int ret = -1;
+	__u32 speed;
 
-	if (self->raw_write)
-		ret = self->raw_write(self, buf, len);
-	return ret;
-}
+	if (((struct irda_skb_cb *)(skb->cb))->magic != LAP_MAGIC)
+		speed = 9600;
+	else
+		speed = ((struct irda_skb_cb *)(skb->cb))->speed;
 
+	return speed;
+}
 #endif
+
+#endif /* IRDA_DEVICE_H */
 
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/iriap.h linux.15p9/include/net/irda/iriap.h
--- linux.vanilla/include/net/irda/iriap.h	Sat Aug 14 02:26:51 1999
+++ linux.15p9/include/net/irda/iriap.h	Mon Feb  7 13:41:15 2000
@@ -6,10 +6,11 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Aug 21 00:02:07 1997
- * Modified at:   Sun May  9 10:56:57 1999
+ * Modified at:   Sat Dec 25 16:42:09 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1997-1999 Dag Brattli <dagb@cs.uit.no>, 
+ *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -57,9 +58,9 @@
 				 struct ias_value *value, void *priv);
 
 struct iriap_cb {
-	QUEUE queue; /* Must be first */
-	
-	int          magic;  /* Magic cookie */
+	queue_t q;      /* Must be first */	
+	magic_t magic;  /* Magic cookie */
+
 	int          mode;   /* Client or server */
 
 	__u32        saddr;
@@ -79,32 +80,38 @@
 	IRIAP_STATE r_connect_state;
 	
 	CONFIRM_CALLBACK confirm;
-	void *priv;
+	void *priv;                /* Used to identify client */
 
 	__u8 max_header_size;
+	__u32 max_data_size;
 	
 	struct timer_list watchdog_timer;
 };
 
 int  iriap_init(void);
 void iriap_cleanup(void);
-void iriap_getvaluebyclass_request( char *name, char *attr, 
-				    __u32 saddr, __u32 daddr,
-				    CONFIRM_CALLBACK callback, void *priv);
-void iriap_getvaluebyclass_confirm(struct iriap_cb *self, struct sk_buff *skb);
 
+struct iriap_cb *iriap_open(__u8 slsap_sel, int mode, void *priv, 
+			    CONFIRM_CALLBACK callback);
+void iriap_close(struct iriap_cb *self);
+
+int iriap_getvaluebyclass_request(struct iriap_cb *self, 
+				  __u32 saddr, __u32 daddr,
+				  char *name, char *attr);
+void iriap_getvaluebyclass_confirm(struct iriap_cb *self, struct sk_buff *skb);
+void iriap_connect_request(struct iriap_cb *self);
 void iriap_send_ack( struct iriap_cb *self);
 void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb);
 
 void iriap_register_server(void);
 
-void iriap_watchdog_timer_expired( unsigned long data);
+void iriap_watchdog_timer_expired(void *data);
 
-static inline void iriap_start_watchdog_timer( struct iriap_cb *self, 
-					       int timeout) 
+static inline void iriap_start_watchdog_timer(struct iriap_cb *self, 
+					      int timeout) 
 {
-	irda_start_timer( &self->watchdog_timer, timeout, 
-			  (unsigned long) self, iriap_watchdog_timer_expired);
+	irda_start_timer(&self->watchdog_timer, timeout, self, 
+			 iriap_watchdog_timer_expired);
 }
 
 #endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/iriap_event.h linux.15p9/include/net/irda/iriap_event.h
--- linux.vanilla/include/net/irda/iriap_event.h	Thu Dec 17 17:01:03 1998
+++ linux.15p9/include/net/irda/iriap_event.h	Tue Jan 18 01:08:18 2000
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Fri Sep  4 13:19:28 1998
+ * Modified at:   Sun Oct 31 22:02:54 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -65,20 +65,21 @@
 	IAP_LM_CONNECT_CONFIRM,
 } IRIAP_EVENT;
 
-void iriap_next_client_state   ( struct iriap_cb *self, IRIAP_STATE state);
-void iriap_next_call_state     ( struct iriap_cb *self, IRIAP_STATE state);
-void iriap_next_server_state   ( struct iriap_cb *self, IRIAP_STATE state);
-void iriap_next_r_connect_state( struct iriap_cb *self, IRIAP_STATE state);
-
-
-void iriap_do_client_event( struct iriap_cb *self, IRIAP_EVENT event, 
-			    struct sk_buff *skb);
-void iriap_do_call_event  ( struct iriap_cb *self, IRIAP_EVENT event, 
-			    struct sk_buff *skb);
-
-void iriap_do_server_event   ( struct iriap_cb *self, IRIAP_EVENT event, 
-			       struct sk_buff *skb);
-void iriap_do_r_connect_event( struct iriap_cb *self, IRIAP_EVENT event, 
-			       struct sk_buff *skb);
+void iriap_next_client_state   (struct iriap_cb *self, IRIAP_STATE state);
+void iriap_next_call_state     (struct iriap_cb *self, IRIAP_STATE state);
+void iriap_next_server_state   (struct iriap_cb *self, IRIAP_STATE state);
+void iriap_next_r_connect_state(struct iriap_cb *self, IRIAP_STATE state);
+
+
+void iriap_do_client_event(struct iriap_cb *self, IRIAP_EVENT event, 
+			   struct sk_buff *skb);
+void iriap_do_call_event  (struct iriap_cb *self, IRIAP_EVENT event, 
+			   struct sk_buff *skb);
+
+void iriap_do_server_event   (struct iriap_cb *self, IRIAP_EVENT event, 
+			      struct sk_buff *skb);
+void iriap_do_r_connect_event(struct iriap_cb *self, IRIAP_EVENT event, 
+			      struct sk_buff *skb);
+
+#endif /* IRIAP_FSM_H */
 
-#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/irias_object.h linux.15p9/include/net/irda/irias_object.h
--- linux.vanilla/include/net/irda/irias_object.h	Sun Mar  7 23:26:43 1999
+++ linux.15p9/include/net/irda/irias_object.h	Mon Feb  7 13:41:15 2000
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Oct  1 22:49:50 1998
- * Modified at:   Wed Feb  3 10:38:02 1999
+ * Modified at:   Wed Dec 15 11:20:57 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -25,6 +25,7 @@
 #ifndef LM_IAS_OBJECT_H
 #define LM_IAS_OBJECT_H
 
+#include <net/irda/irda.h>
 #include <net/irda/irqueue.h>
 
 /* LM-IAS Attribute types */
@@ -37,8 +38,8 @@
  *  LM-IAS Object
  */
 struct ias_object {
-	QUEUE queue;     /* Must be first! */
-	int magic;
+	queue_t q;     /* Must be first! */
+	magic_t magic;
 	
 	char  *name;
 	int   id;
@@ -65,19 +66,19 @@
  *  Attributes used by LM-IAS objects
  */
 struct ias_attrib {
-	QUEUE queue; /* Must be first! */
+	queue_t q; /* Must be first! */
 	int magic;
 
         char *name;   	         /* Attribute name */
 	struct ias_value *value; /* Attribute value */
 };
 
-char *strdup( char *str);
+char *strdup(char *str);
 
-struct ias_object *irias_new_object( char *name, int id);
-void irias_insert_object( struct ias_object *obj);
-void __irias_delete_object( struct ias_object *obj);
-void irias_delete_object( char *name);
+struct ias_object *irias_new_object(char *name, int id);
+void irias_insert_object(struct ias_object *obj);
+int  irias_delete_object(struct ias_object *obj);
+void __irias_delete_object(struct ias_object *obj);
 
 void irias_add_integer_attrib(struct ias_object *obj, char *name, int value);
 void irias_add_string_attrib(struct ias_object *obj, char *name, char *value);
@@ -85,13 +86,14 @@
 			     int len);
 int irias_object_change_attribute(char *obj_name, char *attrib_name, 
 				  struct ias_value *new_value);
-struct ias_object *irias_find_object( char *name);
-struct ias_attrib *irias_find_attrib( struct ias_object *obj, char *name);
+struct ias_object *irias_find_object(char *name);
+struct ias_attrib *irias_find_attrib(struct ias_object *obj, char *name);
 
-struct ias_value *irias_new_string_value( char *string);
-struct ias_value *irias_new_integer_value( int integer);
-struct ias_value *irias_new_octseq_value( __u8 *octseq , int len);
-void irias_delete_value( struct ias_value *value);
+struct ias_value *irias_new_string_value(char *string);
+struct ias_value *irias_new_integer_value(int integer);
+struct ias_value *irias_new_octseq_value(__u8 *octseq , int len);
+struct ias_value *irias_new_missing_value(void);
+void irias_delete_value(struct ias_value *value);
 
 extern struct ias_value missing;
 extern hashbin_t *objects;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/irlan_common.h linux.15p9/include/net/irda/irlan_common.h
--- linux.vanilla/include/net/irda/irlan_common.h	Sat Aug 14 02:26:51 1999
+++ linux.15p9/include/net/irda/irlan_common.h	Mon Feb  7 13:41:44 2000
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Mon May 31 13:54:20 1999
+ * Modified at:   Sun Oct 31 19:41:24 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -127,6 +127,8 @@
 	int tx_busy;
 	struct sk_buff_head txq; /* Transmit control queue */
 
+	struct iriap_cb *iriap;
+
 	struct timer_list kick_timer;
 };
 
@@ -159,7 +161,7 @@
  *  IrLAN control block
  */
 struct irlan_cb {
-	QUEUE queue; /* Must be first */
+	queue_t q; /* Must be first */
 
 	int    magic;
 	char   ifname[9];
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/irlap.h linux.15p9/include/net/irda/irlap.h
--- linux.vanilla/include/net/irda/irlap.h	Sat Aug 14 02:26:51 1999
+++ linux.15p9/include/net/irda/irlap.h	Mon Feb  7 13:23:13 2000
@@ -6,10 +6,11 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Sun May  9 11:38:18 1999
+ * Modified at:   Fri Dec 10 13:21:17 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
+ *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -31,9 +32,12 @@
 #include <linux/netdevice.h>
 #include <linux/ppp_defs.h>
 #include <linux/ppp-comp.h>
+#include <linux/timer.h>
 
 #include <net/irda/irlap_event.h>
 
+#define CONFIG_IRDA_DYNAMIC_WINDOW 1
+
 #define LAP_RELIABLE   1
 #define LAP_UNRELIABLE 0
 
@@ -54,7 +58,7 @@
 #define XID_FORMAT 0x01       /* Discovery XID format */
 
 #define LAP_WINDOW_SIZE 8
-#define MAX_CONNECTIONS 1
+#define LAP_MAX_QUEUE  10
 
 #define NR_EXPECTED     1
 #define NR_UNEXPECTED   0
@@ -65,6 +69,7 @@
 #define NS_INVALID     -1
 
 #ifdef CONFIG_IRDA_COMPRESSION
+
 /*  
  *  Just some shortcuts (may give you strange compiler errors if you change 
  *  them :-)
@@ -76,7 +81,7 @@
 #define irda_incomp      (*self->decompressor.cp->incomp)
 
 struct irda_compressor {
-	QUEUE queue;
+	queue_t q;
 
 	struct compressor *cp;
 	void *state; /* Not used by IrDA */
@@ -85,12 +90,10 @@
 
 /* Main structure of IrLAP */
 struct irlap_cb {
-	QUEUE q; /* Must be first */
+	queue_t q;     /* Must be first */
+	magic_t magic;
 
-	int magic;
-
-	struct irda_device *irdev;
-	struct device      *netdev;
+	struct device  *netdev;
 
 	/* Connection state */
 	volatile IRLAP_STATE state;       /* Current state */
@@ -104,13 +107,18 @@
 	struct timer_list wd_timer;
 	struct timer_list backoff_timer;
 
+	/* Media busy stuff */
+	struct timer_list media_busy_timer;
+	int media_busy;
+
 	/* Timeouts which will be different with different turn time */
 	int slot_timeout;
 	int poll_timeout;
 	int final_timeout;
 	int wd_timeout;
 
-	struct sk_buff_head tx_list;  /* Frames to be transmitted */
+	struct sk_buff_head txq;  /* Frames to be transmitted */
+	struct sk_buff_head txq_ultra;
 
  	__u8    caddr;        /* Connection address */
 	__u32   saddr;        /* Source device address */
@@ -126,7 +134,7 @@
 #ifdef CONFIG_IRDA_FAST_RR
 	int     fast_RR_timeout;
 	int     fast_RR;      
-#endif
+#endif /* CONFIG_IRDA_FAST_RR */
 	
 	int N1; /* N1 * F-timer = Negitiated link disconnect warning threshold */
 	int N2; /* N2 * F-timer = Negitiated link disconnect time */
@@ -136,14 +144,16 @@
 	int     remote_busy;
 	int     xmitflag;
 
-	__u8    vs;           /* Next frame to be sent */
-	__u8    vr;           /* Next frame to be received */
-/* 	int     tmp; */
-	__u8    va;           /* Last frame acked */
- 	int     window;       /* Nr of I-frames allowed to send */
-	int     window_size;  /* Current negotiated window size */
-	int     window_bytes; /* Number of bytes allowed to send */
-	int     bytes_left;   /* Number of bytes allowed to transmit */
+	__u8    vs;            /* Next frame to be sent */
+	__u8    vr;            /* Next frame to be received */
+	__u8    va;            /* Last frame acked */
+ 	int     window;        /* Nr of I-frames allowed to send */
+	int     window_size;   /* Current negotiated window size */
+
+#ifdef CONFIG_IRDA_DYNAMIC_WINDOW
+	__u32   line_capacity; /* Number of bytes allowed to send */
+	__u32   bytes_left;    /* Number of bytes still allowed to transmit */
+#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
 
 	struct sk_buff_head wx_list;
 
@@ -158,21 +168,22 @@
 	hashbin_t   *discovery_log;
  	discovery_t *discovery_cmd;
 
-	struct qos_info qos_tx;    /* QoS requested by peer */
-	struct qos_info qos_rx;    /* QoS requested by self */
+	__u32 speed; 
+
+	struct qos_info  qos_tx;   /* QoS requested by peer */
+	struct qos_info  qos_rx;   /* QoS requested by self */
+	struct qos_info *qos_dev;  /* QoS supported by device */
 
-	struct notify_t notify; /* Callbacks to IrLMP */
+	notify_t notify; /* Callbacks to IrLMP */
 
 	int    mtt_required;  /* Minumum turnaround time required */
 	int    xbofs_delay;   /* Nr of XBOF's used to MTT */
 	int    bofs_count;    /* Negotiated extra BOFs */
 
- 	struct irda_statistics stats;
-
 #ifdef CONFIG_IRDA_COMPRESSION
 	struct irda_compressor compressor;
         struct irda_compressor decompressor;
-#endif
+#endif /* CONFIG_IRDA_COMPRESSION */
 };
 
 extern hashbin_t *irlap;
@@ -180,55 +191,56 @@
 /* 
  *  Function prototypes 
  */
+int irlap_init(void);
+void irlap_cleanup(void);
 
-int irlap_init( void);
-void irlap_cleanup( void);
+struct irlap_cb *irlap_open(struct device *dev, struct qos_info *qos);
+void irlap_close(struct irlap_cb *self);
 
-struct irlap_cb *irlap_open( struct irda_device *dev);
-void irlap_close( struct irlap_cb *self);
+void irlap_connect_request(struct irlap_cb *self, __u32 daddr, 
+			   struct qos_info *qos, int sniff);
+void irlap_connect_response(struct irlap_cb *self, struct sk_buff *skb);
+void irlap_connect_indication(struct irlap_cb *self, struct sk_buff *skb);
+void irlap_connect_confirm(struct irlap_cb *, struct sk_buff *skb);
 
-void irlap_connect_request( struct irlap_cb *self, __u32 daddr, 
-			    struct qos_info *qos, int sniff);
-void irlap_connect_response( struct irlap_cb *self, struct sk_buff *skb);
-void irlap_connect_indication( struct irlap_cb *self, struct sk_buff *skb);
-void irlap_connect_confirm( struct irlap_cb *, struct sk_buff *skb);
+void irlap_data_indication(struct irlap_cb *, struct sk_buff *, int unreliable);
+void irlap_data_request(struct irlap_cb *, struct sk_buff *, int unreliable);
 
-inline void irlap_data_indication( struct irlap_cb *, struct sk_buff *);
-inline void irlap_unit_data_indication( struct irlap_cb *, struct sk_buff *);
-inline void irlap_data_request( struct irlap_cb *, struct sk_buff *, 
-				int reliable);
+#ifdef CONFIG_IRDA_ULTRA
+void irlap_unitdata_request(struct irlap_cb *, struct sk_buff *);
+void irlap_unitdata_indication(struct irlap_cb *, struct sk_buff *);
+#endif /* CONFIG_IRDA_ULTRA */
 
-void irlap_disconnect_request( struct irlap_cb *);
-void irlap_disconnect_indication( struct irlap_cb *, LAP_REASON reason);
+void irlap_disconnect_request(struct irlap_cb *);
+void irlap_disconnect_indication(struct irlap_cb *, LAP_REASON reason);
 
-void irlap_status_indication( int quality_of_link);
+void irlap_status_indication(int quality_of_link);
 
-void irlap_test_request( __u8 *info, int len);
+void irlap_test_request(__u8 *info, int len);
 
 void irlap_discovery_request(struct irlap_cb *, discovery_t *discovery);
 void irlap_discovery_confirm(struct irlap_cb *, hashbin_t *discovery_log);
 void irlap_discovery_indication(struct irlap_cb *, discovery_t *discovery);
 
-void irlap_reset_indication( struct irlap_cb *self);
+void irlap_reset_indication(struct irlap_cb *self);
 void irlap_reset_confirm(void);
 
-void irlap_update_nr_received( struct irlap_cb *, int nr);
-int irlap_validate_nr_received( struct irlap_cb *, int nr);
-int irlap_validate_ns_received( struct irlap_cb *, int ns);
+void irlap_update_nr_received(struct irlap_cb *, int nr);
+int irlap_validate_nr_received(struct irlap_cb *, int nr);
+int irlap_validate_ns_received(struct irlap_cb *, int ns);
 
-int  irlap_generate_rand_time_slot( int S, int s);
-void irlap_initiate_connection_state( struct irlap_cb *);
+int  irlap_generate_rand_time_slot(int S, int s);
+void irlap_initiate_connection_state(struct irlap_cb *);
 void irlap_flush_all_queues(struct irlap_cb *);
-void irlap_change_speed(struct irlap_cb *, int);
+void irlap_change_speed(struct irlap_cb *self, __u32 speed, int now);
 void irlap_wait_min_turn_around(struct irlap_cb *, struct qos_info *);
 
 void irlap_init_qos_capabilities(struct irlap_cb *, struct qos_info *);
 void irlap_apply_default_connection_parameters(struct irlap_cb *self);
-void irlap_apply_connection_parameters(struct irlap_cb *, struct qos_info *);
+void irlap_apply_connection_parameters(struct irlap_cb *self);
+void irlap_set_local_busy(struct irlap_cb *self, int status);
 
-extern inline __u8 irlap_get_header_size(struct irlap_cb *self)
-{
-	return 2;
-}
+#define IRLAP_GET_HEADER_SIZE(self) 2 /* Will be different when we get VFIR */
+#define IRLAP_GET_TX_QUEUE_LEN(self) skb_queue_len(&self->txq)
 
 #endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/irlap_event.h linux.15p9/include/net/irda/irlap_event.h
--- linux.vanilla/include/net/irda/irlap_event.h	Sat Aug 14 02:25:46 1999
+++ linux.15p9/include/net/irda/irlap_event.h	Mon Feb  7 13:23:13 2000
@@ -1,25 +1,33 @@
 /*********************************************************************
  *                
+ *                
  * Filename:      irlap_event.h
  * Version:       0.1
  * Description:   
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Aug 16 00:59:29 1997
- * Modified at:   Tue Apr  6 17:10:38 1999
+ * Modified at:   Tue Dec 21 11:20:30 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
+ *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
- *
- *     Neither Dag Brattli nor University of Tromsř admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
- *
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
  ********************************************************************/
 
 #ifndef IRLAP_EVENT_H
@@ -62,6 +70,7 @@
 
 	/* Send events */
 	SEND_I_CMD,
+	SEND_UI_FRAME,
 
 	/* Receive events */
 	RECV_DISCOVERY_XID_CMD,
@@ -71,14 +80,20 @@
 	RECV_TEST_RSP,
 	RECV_UA_RSP,
 	RECV_DM_RSP,
+	RECV_RD_RSP,
 	RECV_I_CMD,
 	RECV_I_RSP,
 	RECV_UI_FRAME,
 	RECV_FRMR_RSP,
 	RECV_RR_CMD,
 	RECV_RR_RSP,
-	RECV_RNR_FRAME,
-	RECV_DISC_FRAME,
+	RECV_RNR_CMD,
+	RECV_RNR_RSP,
+	RECV_REJ_CMD,
+	RECV_REJ_RSP,
+	RECV_SREJ_CMD,
+	RECV_SREJ_RSP,
+	RECV_DISC_CMD,
 
 	/* Timer events */
 	SLOT_TIMER_EXPIRED,
@@ -115,9 +130,11 @@
 
 extern const char *irlap_state[];
 
-void irlap_do_event( struct irlap_cb *self, IRLAP_EVENT event, 
-		     struct sk_buff *skb, struct irlap_info *info);
-void irlap_next_state( struct irlap_cb *self, IRLAP_STATE state);
-void irlap_print_event( IRLAP_EVENT event);
+void irlap_do_event(struct irlap_cb *self, IRLAP_EVENT event, 
+		    struct sk_buff *skb, struct irlap_info *info);
+void irlap_next_state(struct irlap_cb *self, IRLAP_STATE state);
+void irlap_print_event(IRLAP_EVENT event);
+
+extern int irlap_qos_negotiate(struct irlap_cb *self, struct sk_buff *skb);
 
 #endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/irlap_frame.h linux.15p9/include/net/irda/irlap_frame.h
--- linux.vanilla/include/net/irda/irlap_frame.h	Sat Aug 14 02:26:01 1999
+++ linux.15p9/include/net/irda/irlap_frame.h	Mon Feb  7 13:23:13 2000
@@ -2,24 +2,31 @@
  *                
  * Filename:      irlap_frame.h
  * Version:       0.9
- * Description:   Build and transmit IrLAP frames
+ * Description:   IrLAP frame declarations
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Aug 19 10:27:26 1997
- * Modified at:   Fri Apr 23 09:33:55 1999
+ * Modified at:   Sat Dec 25 21:07:26 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1997-1999 Dag Brattli <dagb@cs.uit.no>,
+ *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
- *
- *     Neither Dag Brattli nor University of Tromsř admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
- *
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
  ********************************************************************/
 
 #ifndef IRLAP_FRAME_H
@@ -73,7 +80,6 @@
 	__u8  flags; /* Discovery flags */
 	__u8  slotnr;
 	__u8  version;
-	__u8  discovery_info[0];
 } PACK;
 
 struct test_frame {
@@ -81,7 +87,6 @@
 	__u8 control;
 	__u32 saddr;         /* Source device address */
 	__u32 daddr;         /* Destination device address */
-	__u8 info[0];        /* Information */
 } PACK;
 
 struct ua_frame {
@@ -90,13 +95,11 @@
 
 	__u32 saddr; /* Source device address */
 	__u32 daddr; /* Dest device address */
-	__u8  params[0];
 } PACK;
 	
 struct i_frame {
 	__u8 caddr;
 	__u8 control;
-	__u8 data[0];
 } PACK;
 
 struct snrm_frame {
@@ -105,37 +108,31 @@
 	__u32 saddr;
 	__u32 daddr;
 	__u8  ncaddr;
-	__u8  params[0];
 } PACK;
 
-/* Per-packet information we need to hide inside sk_buff */
-struct irlap_skb_cb {
-	int magic; /* Be sure that we can trust the information */
-	int mtt;   /* minimum turn around time */
-	int xbofs; /* number of xbofs required */
-	int vs;    /* next frame to send */
-	int vr;    /* next frame to receive */
-};
-
-void irlap_send_discovery_xid_frame( struct irlap_cb *, int S, __u8 s, 
-				     __u8 command, discovery_t *discovery);
-void irlap_send_snrm_frame( struct irlap_cb *, struct qos_info *);
-void irlap_send_test_frame(struct irlap_cb *self, __u32 daddr, 
+void irlap_send_discovery_xid_frame(struct irlap_cb *, int S, __u8 s, 
+				    __u8 command, discovery_t *discovery);
+void irlap_send_snrm_frame(struct irlap_cb *, struct qos_info *);
+void irlap_send_test_frame(struct irlap_cb *self, __u8 caddr, __u32 daddr, 
 			   struct sk_buff *cmd);
-void irlap_send_ua_response_frame( struct irlap_cb *, struct qos_info *);
-void irlap_send_ui_frame( struct irlap_cb *self, struct sk_buff *skb,
-			  int command);
-void irlap_send_dm_frame( struct irlap_cb *);
-void irlap_send_disc_frame( struct irlap_cb *);
-void irlap_send_rr_frame( struct irlap_cb *, int command);
-
-void irlap_send_data_primary( struct irlap_cb *, struct sk_buff *);
-void irlap_send_data_primary_poll( struct irlap_cb *, struct sk_buff *);
-void irlap_send_data_secondary( struct irlap_cb *, struct sk_buff *);
-void irlap_send_data_secondary_final( struct irlap_cb *, struct sk_buff *);
-void irlap_resend_rejected_frames( struct irlap_cb *, int command);
+void irlap_send_ua_response_frame(struct irlap_cb *, struct qos_info *);
+void irlap_send_dm_frame(struct irlap_cb *self);
+void irlap_send_rd_frame(struct irlap_cb *self);
+void irlap_send_disc_frame(struct irlap_cb *self);
+void irlap_send_rr_frame(struct irlap_cb *self, int command);
+
+void irlap_send_data_primary(struct irlap_cb *, struct sk_buff *);
+void irlap_send_data_primary_poll(struct irlap_cb *, struct sk_buff *);
+void irlap_send_data_secondary(struct irlap_cb *, struct sk_buff *);
+void irlap_send_data_secondary_final(struct irlap_cb *, struct sk_buff *);
+void irlap_resend_rejected_frames(struct irlap_cb *, int command);
+void irlap_resend_rejected_frame(struct irlap_cb *self, int command);
+
+void irlap_send_i_frame(struct irlap_cb *, struct sk_buff *, int command);
+void irlap_send_ui_frame(struct irlap_cb *self, struct sk_buff *skb,
+			 __u8 caddr, int command);
 
-void irlap_send_i_frame( struct irlap_cb *, struct sk_buff *, int command);
-void irlap_send_ui_frame( struct irlap_cb *, struct sk_buff *, int command);
+extern int irlap_insert_qos_negotiation_params(struct irlap_cb *self, 
+					       struct sk_buff *skb);
 
 #endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/irlmp.h linux.15p9/include/net/irda/irlmp.h
--- linux.vanilla/include/net/irda/irlmp.h	Sat Aug 14 02:26:51 1999
+++ linux.15p9/include/net/irda/irlmp.h	Mon Feb  7 13:23:15 2000
@@ -6,10 +6,11 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 17 20:54:32 1997
- * Modified at:   Sun May  9 11:01:34 1999
+ * Modified at:   Fri Dec 10 13:23:01 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
+ *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -41,17 +42,14 @@
 #define LSAP_MASK     0x7f
 #define LSAP_IAS      0x00
 #define LSAP_ANY      0xff
+#define LSAP_MAX      0x6f /* 0x70-0x7f are reserved */
+#define LSAP_CONNLESS 0x70 /* Connectionless LSAP, mostly used for Ultra */
 
 #define DEV_ADDR_ANY  0xffffffff
 
-/* Predefined LSAPs used by the various servers */
-#define TSAP_IRLAN    0x05
-#define LSAP_IRLPT    0x06
-#define TSAP_IROBEX   0x07
-#define TSAP_IRCOMM   0x08
-
 #define LMP_HEADER          2    /* Dest LSAP + Source LSAP */
 #define LMP_CONTROL_HEADER  4
+#define LMP_PID_HEADER      1    /* Used by Ultra */
 #define LMP_MAX_HEADER      (LMP_CONTROL_HEADER+LAP_MAX_HEADER)
 
 #define LM_MAX_CONNECTIONS  10
@@ -77,13 +75,13 @@
 typedef void (*DISCOVERY_CALLBACK2) (hashbin_t *);
 
 typedef struct {
-	QUEUE queue; /* Must be first */
+	queue_t queue; /* Must be first */
 
 	__u16 hints; /* Hint bits */
 } irlmp_service_t;
 
 typedef struct {
-	QUEUE queue; /* Must be first */
+	queue_t queue; /* Must be first */
 
 	__u16 hint_mask;
 
@@ -97,24 +95,23 @@
  *  Information about each logical LSAP connection
  */
 struct lsap_cb {
-	QUEUE queue;      /* Must be first */
-
-	int   magic;
-
-	int   connected;
-	int   persistent;
-
-	struct irda_statistics stats;
+	queue_t queue;      /* Must be first */
+	magic_t magic;
 
-	__u8  slsap_sel;   /* Source (this) LSAP address */
-	__u8  dlsap_sel;   /* Destination LSAP address (if connected) */
+	int  connected;
+	int  persistent;
 
-	struct sk_buff *tmp_skb; /* Store skb here while connecting */
+	__u8 slsap_sel;   /* Source (this) LSAP address */
+	__u8 dlsap_sel;   /* Destination LSAP address (if connected) */
+#ifdef CONFIG_IRDA_ULTRA
+	__u8 pid;         /* Used by connectionless LSAP */
+#endif /* CONFIG_IRDA_ULTRA */
+	struct sk_buff *conn_skb; /* Store skb here while connecting */
 
 	struct timer_list watchdog_timer;
 
 	IRLMP_STATE     lsap_state;  /* Connection state */
-	struct notify_t notify;      /* Indication/Confirm entry points */
+	notify_t        notify;      /* Indication/Confirm entry points */
 	struct qos_info qos;         /* QoS for this connection */
 
 	struct lap_cb *lap; /* Pointer to LAP connection structure */
@@ -124,15 +121,16 @@
  *  Information about each registred IrLAP layer
  */
 struct lap_cb {
-	QUEUE queue;      /* Must be first */
+	queue_t queue; /* Must be first */
+	magic_t magic;
 
-	int magic;
 	int reason;    /* LAP disconnect reason */
 
 	IRLMP_STATE lap_state;
 
-	struct irlap_cb *irlap;    /* Instance of IrLAP layer */
+	struct irlap_cb *irlap;   /* Instance of IrLAP layer */
 	hashbin_t *lsaps;         /* LSAP associated with this link */
+	int refcount;
 
 	__u8  caddr;  /* Connection address */
  	__u32 saddr;  /* Source device address */
@@ -157,7 +155,7 @@
  *  Main structure for IrLMP
  */
 struct irlmp_cb {
-	int magic;
+	magic_t magic;
 
 	__u8 conflict_flag;
 	
@@ -187,7 +185,7 @@
 /* Prototype declarations */
 int  irlmp_init(void);
 void irlmp_cleanup(void);
-struct lsap_cb *irlmp_open_lsap( __u8 slsap, struct notify_t *notify);
+struct lsap_cb *irlmp_open_lsap(__u8 slsap, notify_t *notify, __u8 pid);
 void irlmp_close_lsap( struct lsap_cb *self);
 
 __u16 irlmp_service_to_hint(int service);
@@ -199,30 +197,36 @@
 int irlmp_update_client(__u32 handle, __u16 hint_mask, 
 			DISCOVERY_CALLBACK1, DISCOVERY_CALLBACK2);
 
-void irlmp_register_link(struct irlap_cb *, __u32 saddr, struct notify_t *);
+void irlmp_register_link(struct irlap_cb *, __u32 saddr, notify_t *);
 void irlmp_unregister_link(__u32 saddr);
 
 int  irlmp_connect_request(struct lsap_cb *, __u8 dlsap_sel, 
 			   __u32 saddr, __u32 daddr,
 			   struct qos_info *, struct sk_buff *);
 void irlmp_connect_indication(struct lsap_cb *self, struct sk_buff *skb);
-void irlmp_connect_response(struct lsap_cb *, struct sk_buff *);
+int  irlmp_connect_response(struct lsap_cb *, struct sk_buff *);
 void irlmp_connect_confirm(struct lsap_cb *, struct sk_buff *);
 struct lsap_cb *irlmp_dup(struct lsap_cb *self, void *instance);
 
 void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason, 
 				 struct sk_buff *userdata);
-void irlmp_disconnect_request(struct lsap_cb *, struct sk_buff *userdata);
+int  irlmp_disconnect_request(struct lsap_cb *, struct sk_buff *userdata);
 
 void irlmp_discovery_confirm(hashbin_t *discovery_log);
 void irlmp_discovery_request(int nslots);
 void irlmp_do_discovery(int nslots);
 discovery_t *irlmp_get_discovery_response(void);
 
-void irlmp_data_request(struct lsap_cb *, struct sk_buff *);
-inline void irlmp_udata_request(struct lsap_cb *, struct sk_buff *);
-inline void irlmp_data_indication(struct lsap_cb *, struct sk_buff *);
-inline void irlmp_udata_indication(struct lsap_cb *, struct sk_buff *);
+int  irlmp_data_request(struct lsap_cb *, struct sk_buff *);
+void irlmp_data_indication(struct lsap_cb *, struct sk_buff *);
+
+int  irlmp_udata_request(struct lsap_cb *, struct sk_buff *);
+void irlmp_udata_indication(struct lsap_cb *, struct sk_buff *);
+
+#ifdef CONFIG_IRDA_ULTRA
+int  irlmp_connless_data_request(struct lsap_cb *, struct sk_buff *);
+void irlmp_connless_data_indication(struct lsap_cb *, struct sk_buff *);
+#endif /* CONFIG_IRDA_ULTRA */
 
 void irlmp_status_request(void);
 void irlmp_status_indication(LINK_STATUS link, LOCK_STATUS lock);
@@ -235,10 +239,20 @@
 __u32 irlmp_get_daddr(struct lsap_cb *self);
 
 extern char *lmp_reasons[];
+extern int sysctl_discovery_timeout;
 extern int sysctl_discovery_slots;
 extern int sysctl_discovery;
 extern struct irlmp_cb *irlmp;
 
 static inline hashbin_t *irlmp_get_cachelog(void) { return irlmp->cachelog; }
+
+static inline int irlmp_get_lap_tx_queue_len(struct lsap_cb *self)
+{
+	ASSERT(self != NULL, return 0;);
+	ASSERT(self->lap != NULL, return 0;);
+	ASSERT(self->lap->irlap != NULL, return 0;);
+
+	return IRLAP_GET_TX_QUEUE_LEN(self->lap->irlap);
+}
 
 #endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/irlmp_event.h linux.15p9/include/net/irda/irlmp_event.h
--- linux.vanilla/include/net/irda/irlmp_event.h	Sat Aug 14 02:25:46 1999
+++ linux.15p9/include/net/irda/irlmp_event.h	Tue Jan 18 01:08:18 2000
@@ -6,10 +6,11 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Thu Feb 25 20:49:16 1999
+ * Modified at:   Thu Jul  8 12:18:54 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>, 
+ *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -98,17 +99,21 @@
 extern const char *irlmp_state[];
 extern const char *irlsap_state[];
 
-void irlmp_watchdog_timer_expired( unsigned long data);
-void irlmp_discovery_timer_expired( unsigned long data);
-void irlmp_idle_timer_expired( unsigned long data);
-
-void irlmp_next_station_state( IRLMP_STATE state);
-void irlmp_next_lsap_state( struct lsap_cb *self, LSAP_STATE state);
-void irlmp_next_lap_state( struct lap_cb *self, IRLMP_STATE state);
-
-void irlmp_do_lap_event( struct lap_cb *self, IRLMP_EVENT event, 
-			 struct sk_buff *skb);
-void irlmp_do_lsap_event( struct lsap_cb *self, IRLMP_EVENT event, 
-			  struct sk_buff *skb);
+void irlmp_watchdog_timer_expired(void *data);
+void irlmp_discovery_timer_expired(void *data);
+void irlmp_idle_timer_expired(void *data);
+
+void irlmp_next_station_state(IRLMP_STATE state);
+void irlmp_next_lsap_state(struct lsap_cb *self, LSAP_STATE state);
+void irlmp_next_lap_state(struct lap_cb *self, IRLMP_STATE state);
+
+void irlmp_do_lap_event(struct lap_cb *self, IRLMP_EVENT event, 
+			struct sk_buff *skb);
+int irlmp_do_lsap_event(struct lsap_cb *self, IRLMP_EVENT event, 
+			struct sk_buff *skb);
+
+#endif /* IRLMP_EVENT_H */
+
+
+
 
-#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/irlmp_frame.h linux.15p9/include/net/irda/irlmp_frame.h
--- linux.vanilla/include/net/irda/irlmp_frame.h	Sat Aug 14 02:25:46 1999
+++ linux.15p9/include/net/irda/irlmp_frame.h	Mon Feb  7 13:41:19 2000
@@ -6,10 +6,11 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Aug 19 02:09:59 1997
- * Modified at:   Tue Apr  6 17:12:57 1999
+ * Modified at:   Fri Dec 10 13:21:53 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>, 
+ *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -42,8 +43,12 @@
 				int expedited, struct sk_buff *skb);
 void irlmp_send_lcf_pdu(struct lap_cb *self, __u8 dlsap, __u8 slsap, 
 			__u8 opcode, struct sk_buff *skb);
-void irlmp_link_data_indication(struct lap_cb *, int reliable, 
-				struct sk_buff *);
+void irlmp_link_data_indication(struct lap_cb *, struct sk_buff *, 
+				int unreliable);
+#ifdef CONFIG_IRDA_ULTRA
+void irlmp_link_unitdata_indication(struct lap_cb *, struct sk_buff *);
+#endif /* CONFIG_IRDA_ULTRA */
+
 void irlmp_link_connect_indication(struct lap_cb *, __u32 saddr, __u32 daddr,
 				   struct qos_info *qos, struct sk_buff *skb);
 void irlmp_link_connect_request(__u32 daddr);
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/irlpt_cli.h linux.15p9/include/net/irda/irlpt_cli.h
--- linux.vanilla/include/net/irda/irlpt_cli.h	Sat Aug 14 02:26:01 1999
+++ linux.15p9/include/net/irda/irlpt_cli.h	Thu Jan  1 01:00:00 1970
@@ -1,49 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      irlpt_cli.h
- * Version:       0.1
- * Description:   
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Sat Feb 21 18:54:38 1998
- * Modified at:   Wed Apr 21 16:46:26 1999
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>
- *     Copyright (c) 1998, Dag Brattli, 
- *     All Rights Reserved
- *      
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
- *     the License, or (at your option) any later version.
- *  
- *     I, Thomas Davis, provide no warranty for any of this software. This
- *     material is provided "AS-IS" and at no charge.
- *     
- ********************************************************************/
-
-#ifndef IRLPT_CLIENT_H
-#define IRLPT_CLIENT_H
-
-/* Debug function */
-
-/* int  client_init( struct device *dev); */
-
-/*
- * if it's static, it doesn't go in here.
- */
-
-void irlpt_client_get_value_confirm(int result, __u16 obj_id, 
-				    struct ias_value *value, 
-				    void *priv);
-void irlpt_client_connect_indication( void *instance, 
-				      void *sap, 
-				      struct qos_info *qos, 
-				      int max_seg_size,
-				      struct sk_buff *skb);
-void irlpt_client_connect_request( struct irlpt_cb *self);
-
-extern hashbin_t *irlpt_clients;
-
-#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/irlpt_cli_fsm.h linux.15p9/include/net/irda/irlpt_cli_fsm.h
--- linux.vanilla/include/net/irda/irlpt_cli_fsm.h	Sun Mar  7 23:26:43 1999
+++ linux.15p9/include/net/irda/irlpt_cli_fsm.h	Thu Jan  1 01:00:00 1970
@@ -1,36 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      irlpt_cli_fsm.h
- * Version:       0.1
- * Sources:       irlan_event.h
- * 
- *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, 
- *		All Rights Reserved.
- *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>, 
- *		All Rights Reserved.
- *     
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
- *     the License, or (at your option) any later version.
- *
- *     I, Thomas Davis, provide no warranty for any of this software. 
- *     This material is provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#ifndef IRLPT_EVENT_H
-#define IRLPT_EVENT_H
-
-#include <linux/kernel.h>
-#include <linux/skbuff.h>
-
-extern void irlpt_client_do_event( struct irlpt_cb *self,  
-				   IRLPT_EVENT event, 
-				   struct sk_buff *skb, 
-				   struct irlpt_info *info);
-extern void irlpt_client_next_state( struct irlpt_cb *self, 
-				     IRLPT_CLIENT_STATE state);
-
-#endif
-
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/irlpt_common.h linux.15p9/include/net/irda/irlpt_common.h
--- linux.vanilla/include/net/irda/irlpt_common.h	Sat Aug 14 02:26:51 1999
+++ linux.15p9/include/net/irda/irlpt_common.h	Thu Jan  1 01:00:00 1970
@@ -1,190 +0,0 @@
-/*********************************************************************
- *
- * Filename:      irlpt_common.h
- * Version:       
- * Description:   
- * Status:        Experimental.
- * Author:        Thomas Davis, <ratbert@radiks.net>
- * Created at:    Sat Feb 21 18:54:38 1998
- * Modified at:   Sun Mar  8 23:44:19 1998
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * Sources:	  irlan.c
- *
- *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>,
- *			   Dag Brattli,  <dagb@cs.uit.no>
- *     All Rights Reserved.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     I, Thomas Davis, provide no warranty for any of this software.
- *     This material is provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#ifndef IRLPT_COMMON_H
-#define IRLPT_COMMON_H
-
-#include <net/irda/qos.h>
-#include <net/irda/irmod.h>
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/miscdevice.h>
-
-#include <linux/poll.h>
-
-extern char *irlpt_service_type[];
-extern char *irlpt_port_type[];
-extern char *irlpt_connected[];
-extern char *irlpt_reasons[];
-extern char *irlpt_client_fsm_state[];
-extern char *irlpt_server_fsm_state[];
-extern char *irlpt_fsm_event[];
-
-extern struct wait_queue *lpt_wait;
-
-extern struct irlpt_cb *irlpt_find_handle(unsigned int minor);
-extern void irlpt_flow_control(struct sk_buff *skb);
-
-extern ssize_t irlpt_read( struct file *file, char *buffer, 
-			   size_t count, loff_t *noidea);
-extern ssize_t irlpt_write(struct file *file, const char *buffer, 
-			   size_t count, loff_t *noidea);
-extern loff_t irlpt_seek(struct file *, loff_t, int);
-extern int irlpt_open(struct inode * inode, struct file *file);
-extern int irlpt_close(struct inode *inode, struct file *file);
-extern u_int irlpt_poll(struct file *file, poll_table *wait);
-
-/* FSM definitions */
-
-typedef enum {
-        IRLPT_CLIENT_IDLE,
-	IRLPT_CLIENT_QUERY,
-	IRLPT_CLIENT_READY,
-	IRLPT_CLIENT_WAITI,
-	IRLPT_CLIENT_CONN,
-} IRLPT_CLIENT_STATE;
-
-typedef enum {
-	IRLPT_SERVER_IDLE,
-	IRLPT_SERVER_CONN,
-} IRLPT_SERVER_STATE;
-    
-/* IrLPT Events */
-
-typedef enum {
-	QUERY_REMOTE_IAS,
-	IAS_PROVIDER_AVAIL,
-	IAS_PROVIDER_NOT_AVAIL,
-	LAP_DISCONNECT,
-	LMP_CONNECT,
-	LMP_DISCONNECT,
-	LMP_CONNECT_INDICATION,
-	LMP_DISCONNECT_INDICATION,
-        IRLPT_DISCOVERY_INDICATION,
-	IRLPT_CONNECT_REQUEST,
-	IRLPT_DISCONNECT_REQUEST,
-	CLIENT_DATA_INDICATION,
-} IRLPT_EVENT;
-
-struct irlpt_info {
-	struct lsap_cb *lsap;
-	__u8 dlsap_sel;
-	__u32 daddr;
-	__u32 saddr;
-};
-
-/* Command packet types */
-
-#define IRLPT_MAX_PACKET 1024
-#define IRLPT_MAX_HEADER LMP_MAX_HEADER
-#define IRLPT_MAX_DEVICES 3
-#define IRLPT_MAGIC 0x0755
-
-typedef enum {
-	IRLPT_DISCONNECTED,
-	IRLPT_WAITING,
-	IRLPT_CONNECTED,
-	IRLPT_FLUSHED,
-} IRLPT_SERVER_STATUS;
-
-#define IRLPT_LSAP      0x09
-
-#define PI_SERVICE_TYPE	0x00
-
-#define IRLPT_UNKNOWN         0x00            /* not defined yet. */
-#define IRLPT_THREE_WIRE_RAW  0x01		/* bit 0 */
-#define IRLPT_THREE_WIRE      0x02		/* bit 1 */
-#define IRLPT_NINE_WIRE	      0x04		/* bit 2 */
-#define IRLPT_CENTRONICS      0x08		/* bit 3 */
-#define IRLPT_SERVER_MODE     0xFF            /* our own flag */
-
-#define PI_PORT_TYPE	0x01
-
-#define IRLPT_SERIAL	0x01		/* bit 0 */
-#define IRLPT_PARALLEL	0x02		/* bit 1 */
-
-#define PI_PORT_NAME	0x02
-
-#define PI_CRITICAL	0x80
-
-struct irlpt_cb {
-	QUEUE queue;		/* must be first. */
-
-	int magic;		/* magic used to detect corruption of 
-				   the struct */
-	__u32 daddr;		/* address of remote printer */
-	__u32 saddr;            /* my local address. */
-
-	struct timer_list retry_timer;
-	
-	int volatile state;	/* Current state of IrCOMM layer */
-	int open_retries;
-        int in_use;		/* flag to prevent re-use */
-        char ifname[16];		/* name of the allocated instance, 
-				   and registered device. */
-	struct lsap_cb *lsap;	/* lmp handle */
-
-	__u8 dlsap_sel;		/* remote LSAP selector address */
-	__u8 slsap_sel;		/* local LSAP selectoraddress */
-	__u8 servicetype;	/* Type of remote service, ie THREE_WIRE_RAW */
-	__u8 porttype;		/* type of remote port. */
-
-	struct miscdevice ir_dev; /* used to register the misc device. */
-
-	int count;                /* open count */
-	int max_data_size;	/* max frame size we can send */
-	int max_header_size;    /* how much header space is needed */
-	int pkt_count;		/* how many packets are queued up */
-
-	struct wait_queue *read_wait;	/* wait queues */
-	struct wait_queue *write_wait;
-	struct wait_queue *ex_wait;
-
-	/* this is used to remove the printer when it's gone */
-	struct timer_list lpt_timer;
-	void (*timeout) (unsigned long data);
-
-	void (*do_event) (struct irlpt_cb *self, IRLPT_EVENT event, 
-			  struct sk_buff *skb,
-			  struct irlpt_info *info);
-
-	/* this is used by the server side of the system */
-
-        IRLPT_SERVER_STATE connected;
-
-	int eof;
-	int service_LSAP;
-
-	struct sk_buff_head rx_queue; /* read buffer queue */
-};
-
-/* Debug function */
-void irlpt_dump_buffer(struct sk_buff *);
-
-#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/irlpt_server.h linux.15p9/include/net/irda/irlpt_server.h
--- linux.vanilla/include/net/irda/irlpt_server.h	Sun Mar  7 23:26:43 1999
+++ linux.15p9/include/net/irda/irlpt_server.h	Thu Jan  1 01:00:00 1970
@@ -1,42 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      irlpt_server.h
- * Version:       0.1
- * Description:   
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Sat Feb 21 18:54:38 1998
- * Modified at:   Tue Sep 22 11:41:42 1998
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>
- *     Copyright (c) 1998, Dag Brattli, 
- *     All Rights Reserved
- *      
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
- *     the License, or (at your option) any later version.
- *  
- *     I, Thomas Davis, provide no warranty for any of this software. This
- *     material is provided "AS-IS" and at no charge.
- *     
- ********************************************************************/
-
-#ifndef IRLPT_SERVER_H
-#define IRLPT_SERVER_H
-
-#include "qos.h"
-#include "irmod.h"
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/miscdevice.h>
-
-/* int  server_init( struct device *dev); */
-
-extern struct irlpt_cb *irlpt_server;
-
-#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/irlpt_server_fsm.h linux.15p9/include/net/irda/irlpt_server_fsm.h
--- linux.vanilla/include/net/irda/irlpt_server_fsm.h	Sun Mar  7 23:26:43 1999
+++ linux.15p9/include/net/irda/irlpt_server_fsm.h	Thu Jan  1 01:00:00 1970
@@ -1,35 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      server_server_fsm.h
- * Version:       0.1
- * Sources:       irlan_event.h
- * 
- *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, 
- *		All Rights Reserved.
- *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>, 
- *		All Rights Reserved.
- *     
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
- *     the License, or (at your option) any later version.
- *
- *     I, Thomas Davis, provide no warranty for any of this software. 
- *     This material is provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#ifndef IRLPT_EVENT_H
-#define IRLPT_EVENT_H
-
-#include <linux/kernel.h>
-#include <linux/skbuff.h>
-
-void irlpt_server_do_event( struct irlpt_cb *self, 
-			    IRLPT_EVENT event, 
-			    struct sk_buff *skb, 
-			    struct irlpt_info *info);
-void irlpt_server_next_state( struct irlpt_cb *self, 
-			      IRLPT_SERVER_STATE state);
-
-#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/irmod.h linux.15p9/include/net/irda/irmod.h
--- linux.vanilla/include/net/irda/irmod.h	Sat Aug 14 02:26:01 1999
+++ linux.15p9/include/net/irda/irmod.h	Wed Jan 26 23:58:29 2000
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Dec 15 13:58:52 1997
- * Modified at:   Fri Apr  9 11:13:39 1999
+ * Modified at:   Sun Oct 31 20:01:17 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  *
- *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -42,10 +42,10 @@
 	EVENT_REQUEST_MODULE,
 	EVENT_IRLAN_START,
 	EVENT_IRLAN_STOP,
-	EVENT_IRLPT_START,
-	EVENT_IRLPT_STOP,
-	EVENT_IROBEX_START,
-	EVENT_IROBEX_STOP,
+	EVENT_IRLPT_START,  /* Obsolete */
+	EVENT_IRLPT_STOP,   /* Obsolete */
+	EVENT_IROBEX_START, /* Obsolete */
+	EVENT_IROBEX_STOP,  /* Obsolete */
 	EVENT_IRDA_STOP,
 	EVENT_NEED_PROCESS_CONTEXT,
 } IRMGR_EVENT;
@@ -69,7 +69,7 @@
  *  addtional information
  */
 struct irda_event {
-	QUEUE q; /* Must be first */
+	queue_t q; /* Must be first */
 	
 	struct irmanager_event event;
 };
@@ -78,7 +78,7 @@
  *  Funtions with needs to be called with a process context
  */
 struct irda_todo {
-	QUEUE q; /* Must be first */
+	queue_t q; /* Must be first */
 
 	void *self;
 	TODO_CALLBACK callback;
@@ -94,8 +94,8 @@
 
 	int in_use;
 
-	QUEUE *event_queue; /* Events queued for the irmanager */
-	QUEUE *todo_queue;  /* Todo list */
+	queue_t *event_queue; /* Events queued for the irmanager */
+	queue_t *todo_queue;  /* Todo list */
 };
 
 int irmod_init_module(void);
@@ -110,7 +110,7 @@
 static inline int irda_lock(int *lock) 
 {
 	if (test_and_set_bit( 0, (void *) lock))  {
-		DEBUG(3, __FUNCTION__ 
+		IRDA_DEBUG(3, __FUNCTION__ 
 		      "(), Trying to lock, already locked variable!\n");
 		return FALSE;
         }  
@@ -119,7 +119,7 @@
 
 inline int irda_unlock(int *lock);
 
-void irda_notify_init(struct notify_t *notify);
+void irda_notify_init(notify_t *notify);
 
 void irda_execute_as_process(void *self, TODO_CALLBACK callback, __u32 param);
 void irmanager_notify(struct irmanager_event *event);
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/irport.h linux.15p9/include/net/irda/irport.h
--- linux.vanilla/include/net/irda/irport.h	Sat Aug 14 02:26:51 1999
+++ linux.15p9/include/net/irda/irport.h	Mon Feb  7 13:23:13 2000
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug  3 13:49:59 1997
- * Modified at:   Wed May 19 15:31:16 1999
+ * Modified at:   Fri Jan 14 10:21:10 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1997, 1998-1999 Dag Brattli <dagb@cs.uit.no>
+ *     Copyright (c) 1997, 1998-2000 Dag Brattli <dagb@cs.uit.no>
  *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
@@ -29,6 +29,7 @@
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/types.h>
+#include <asm/spinlock.h>
 
 #include <net/irda/irda_device.h>
 
@@ -49,14 +50,40 @@
 
 #define FRAME_MAX_SIZE 2048
 
-void irport_start(struct irda_device *idev, int iobase);
-void irport_stop(struct irda_device *idev, int iobase);
-int  irport_probe(int iobase);
-
-void irport_change_speed(struct irda_device *idev, int speed);
+struct irport_cb {
+	struct device *netdev; /* Yes! we are some kind of netdevice */
+	struct net_device_stats stats;
+
+	struct irlap_cb *irlap;    /* The link layer we are attached to */
+
+	chipio_t io;               /* IrDA controller information */
+	iobuff_t tx_buff;          /* Transmit buffer */
+	iobuff_t rx_buff;          /* Receive buffer */
+
+	struct qos_info qos;       /* QoS capabilities for this device */
+	dongle_t *dongle;          /* Dongle driver */
+
+ 	__u32 flags;               /* Interface flags */
+	__u32 new_speed;
+	int mode;
+	int index;                 /* Instance index */
+
+	spinlock_t lock;           /* For serializing operations */
+
+	/* For piggyback drivers */
+	void *priv;                
+	void (*change_speed)(void *priv, __u32 speed);
+	void (*interrupt)(int irq, void *dev_id, struct pt_regs *regs);
+};
+
+struct irport_cb *irport_open(int i, unsigned int iobase, unsigned int irq);
+int  irport_close(struct irport_cb *self);
+void irport_start(struct irport_cb *self);
+void irport_stop(struct irport_cb *self);
+void irport_change_speed(void *priv, __u32 speed);
 void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-
 int  irport_hard_xmit(struct sk_buff *skb, struct device *dev);
-void irport_wait_until_sent(struct irda_device *idev);
+int  irport_net_open(struct device *dev);
+int  irport_net_close(struct device *dev);
 
-#endif
+#endif /* IRPORT_H */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/irqueue.h linux.15p9/include/net/irda/irqueue.h
--- linux.vanilla/include/net/irda/irqueue.h	Sat Aug 14 02:26:51 1999
+++ linux.15p9/include/net/irda/irqueue.h	Tue Jan 18 01:08:18 2000
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Jun  9 13:26:50 1998
- * Modified at:   Tue May 25 07:54:41 1999
+ * Modified at:   Thu Oct  7 13:25:16 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (C) 1998, Aage Kvalnes <aage@cs.uit.no>
+ *     Copyright (C) 1998-1999, Aage Kvalnes <aage@cs.uit.no>
  *     Copyright (c) 1998, Dag Brattli
  *     All Rights Reserved.
  *      
@@ -53,56 +53,49 @@
 #define ALIGN __attribute__((aligned))
 #endif
 
-typedef void (*FREE_FUNC)( void *arg);
+#define Q_NULL { NULL, NULL, "", 0 }
+
+typedef void (*FREE_FUNC)(void *arg);
 
 /*
  * Hashbin
  */
 #define GET_HASHBIN(x) ( x & HASHBIN_MASK )
 
-#define QUEUE struct queue_t
-struct queue_t {
-	QUEUE* q_next;
-	QUEUE* q_prev;
+struct irqueue {
+	struct irqueue *q_next;
+	struct irqueue *q_prev;
 
-	char   q_name[ NAME_SIZE];
+	char   q_name[NAME_SIZE];
 	__u32  q_hash;
 };
+typedef struct irqueue queue_t;
 
 typedef struct hashbin_t {
-	int    magic;
-	int    hb_type;
-	int    hb_size;
-	spinlock_t hb_mutex[ HASHBIN_SIZE ] ALIGN;
-	QUEUE*     hb_queue[ HASHBIN_SIZE ] ALIGN;
+	__u32      magic;
+	int        hb_type;
+	int        hb_size;
+	spinlock_t hb_mutex[HASHBIN_SIZE] ALIGN;
+	queue_t   *hb_queue[HASHBIN_SIZE] ALIGN;
 
-	QUEUE* hb_current;
+	queue_t* hb_current;
 } hashbin_t;
 
-hashbin_t *hashbin_new( int type);
-int      hashbin_delete( hashbin_t* hashbin, FREE_FUNC func);
-int      hashbin_clear( hashbin_t* hashbin, FREE_FUNC free_func);
-void     hashbin_insert( hashbin_t* hashbin, QUEUE* entry, __u32 hashv, 
-			 char* name);
-void*    hashbin_find( hashbin_t* hashbin, __u32 hashv, char* name);
-void*    hashbin_remove( hashbin_t* hashbin, __u32 hashv, char* name);
-void*    hashbin_remove_first( hashbin_t *hashbin);
-QUEUE   *hashbin_get_first( hashbin_t *hashbin);
-QUEUE   *hashbin_get_next( hashbin_t *hashbin);
-
-void enqueue_last(QUEUE **queue, QUEUE* element);
-void enqueue_first(QUEUE **queue, QUEUE* element);
-QUEUE *dequeue_first(QUEUE **queue);
+hashbin_t *hashbin_new(int type);
+int      hashbin_delete(hashbin_t* hashbin, FREE_FUNC func);
+int      hashbin_clear(hashbin_t* hashbin, FREE_FUNC free_func);
+void     hashbin_insert(hashbin_t* hashbin, queue_t* entry, __u32 hashv, 
+			char* name);
+void*    hashbin_find(hashbin_t* hashbin, __u32 hashv, char* name);
+void*    hashbin_remove(hashbin_t* hashbin, __u32 hashv, char* name);
+void*    hashbin_remove_first(hashbin_t *hashbin);
+queue_t *hashbin_get_first(hashbin_t *hashbin);
+queue_t *hashbin_get_next(hashbin_t *hashbin);
+
+void enqueue_last(queue_t **queue, queue_t* element);
+void enqueue_first(queue_t **queue, queue_t* element);
+queue_t *dequeue_first(queue_t **queue);
 
-/*
- * Function hashbin_get_size (hashbin)
- *
- *    Returns the number of elements in the hashbin
- *
- */
-extern __inline__ int  hashbin_get_size( hashbin_t* hashbin) 
-{
-	return hashbin->hb_size;
-}
+#define HASHBIN_GET_SIZE(hashbin) hashbin->hb_size
 
 #endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/irttp.h linux.15p9/include/net/irda/irttp.h
--- linux.vanilla/include/net/irda/irttp.h	Sat Aug 14 02:26:51 1999
+++ linux.15p9/include/net/irda/irttp.h	Mon Feb  7 13:41:15 2000
@@ -6,10 +6,11 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:31 1997
- * Modified at:   Mon May 10 19:14:51 1999
+ * Modified at:   Sun Dec 12 13:09:07 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
+ *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -41,26 +42,29 @@
 #define TTP_PARAMETERS         0x80
 #define TTP_MORE               0x80
 
-#define DEFAULT_INITIAL_CREDIT 22
+#define DEFAULT_INITIAL_CREDIT 14
 
-#define LOW_THRESHOLD   4
-#define HIGH_THRESHOLD  8
-#define TTP_MAX_QUEUE  22
+#define TTP_LOW_THRESHOLD       4
+#define TTP_HIGH_THRESHOLD     10
+#define TTP_MAX_QUEUE          14
 
 /* Some priorities for disconnect requests */
 #define P_NORMAL    0
 #define P_HIGH      1
 
-#define SAR_DISABLE 0
-#define SAR_UNBOUND 0xffffffff
+#define TTP_SAR_DISABLE 0
+#define TTP_SAR_UNBOUND 0xffffffff
+
+/* Parameters */
+#define TTP_MAX_SDU_SIZE 0x01
 
 /*
  *  This structure contains all data assosiated with one instance of a TTP 
  *  connection.
  */
 struct tsap_cb {
-	QUEUE queue;          /* For linking it into the hashbin */
-	int  magic;           /* Just in case */
+	queue_t q;            /* Must be first */
+	magic_t magic;        /* Just in case */
 
 	__u8 stsap_sel;       /* Source TSAP */
 	__u8 dtsap_sel;       /* Destination TSAP */
@@ -82,9 +86,9 @@
 	int rx_queue_lock;
 	spinlock_t lock;
 
-	struct notify_t notify;       /* Callbacks to client layer */
+	notify_t notify;       /* Callbacks to client layer */
 
-	struct irda_statistics stats;
+	struct net_device_stats stats;
 	struct timer_list todo_timer; 
 	
 	__u32 max_seg_size;     /* Max data that fit into an IrLAP frame */
@@ -103,16 +107,14 @@
 };
 
 struct irttp_cb {
-	int magic;
-	
+	magic_t    magic;	
 	hashbin_t *tsaps;
 };
 
 int  irttp_init(void);
 void irttp_cleanup(void);
 
-struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, 
-				struct notify_t *notify);
+struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify);
 int irttp_close_tsap(struct tsap_cb *self);
 
 int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb);
@@ -122,12 +124,12 @@
 			  __u32 saddr, __u32 daddr,
 			  struct qos_info *qos, __u32 max_sdu_size, 
 			  struct sk_buff *userdata);
-void irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size, 
+int irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size, 
 			    struct sk_buff *userdata);
-struct tsap_cb *irttp_dup(struct tsap_cb *self, void *instance);
-void irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *skb,
-			      int priority);
+int irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *skb,
+			     int priority);
 void irttp_flow_request(struct tsap_cb *self, LOCAL_FLOW flow);
+struct tsap_cb *irttp_dup(struct tsap_cb *self, void *instance);
 
 static __inline __u32 irttp_get_saddr(struct tsap_cb *self)
 {
@@ -137,6 +139,11 @@
 static __inline __u32 irttp_get_daddr(struct tsap_cb *self)
 {
 	return irlmp_get_daddr(self->lsap);
+}
+
+static __inline __u32 irttp_get_max_seg_size(struct tsap_cb *self)
+{
+	return self->max_seg_size;
 }
 
 extern struct irttp_cb *irttp;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/irtty.h linux.15p9/include/net/irda/irtty.h
--- linux.vanilla/include/net/irda/irtty.h	Sat Aug 14 02:26:51 1999
+++ linux.15p9/include/net/irda/irtty.h	Mon Feb  7 13:23:15 2000
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Dec  9 21:13:12 1997
- * Modified at:   Mon May 10 13:22:23 1999
+ * Modified at:   Tue Jan 11 12:32:03 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  *  
- *     Copyright (c) 1997, 1999 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1997, 1999-2000 Dag Brattli, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -28,30 +28,48 @@
 #include <linux/if.h>
 #include <linux/skbuff.h>
 #include <linux/termios.h>
+#include <linux/netdevice.h>
 
 #include <net/irda/irda.h>
 #include <net/irda/irqueue.h>
 #include <net/irda/irda_device.h>
 
+/* Used by ioctl */
+struct irtty_info {
+	char name[6];
+};
+
 #define IRTTY_IOC_MAGIC 'e'
 #define IRTTY_IOCTDONGLE  _IO(IRTTY_IOC_MAGIC, 1)
-#define IRTTY_IOC_MAXNR   1
-
-#ifndef N_IRDA
-#define N_IRDA         11   /* This one should go in </asm/termio.h> */
-#endif
+#define IRTTY_IOCGET     _IOR(IRTTY_IOC_MAGIC, 2, struct irtty_info)
+#define IRTTY_IOC_MAXNR   2
 
 struct irtty_cb {
-	QUEUE q; /* Must be first */
+	queue_t q;     /* Must be first */
+	magic_t magic;
+
+	struct device *netdev; /* Yes! we are some kind of netdevice */
+	struct irda_task *task;
+	struct net_device_stats stats;
+
+	struct tty_struct  *tty;
+	struct irlap_cb    *irlap; /* The link layer we are binded to */
+
+	chipio_t io;               /* IrDA controller information */
+	iobuff_t tx_buff;          /* Transmit buffer */
+	iobuff_t rx_buff;          /* Receive buffer */
+
+	struct qos_info qos;       /* QoS capabilities for this device */
+	dongle_t *dongle;          /* Dongle driver */
+
+	__u32 new_speed;
+ 	__u32 flags;               /* Interface flags */
 
-	int	magic;
-	
-	struct  tty_struct  *tty;  /* Ptr to TTY structure */
-	struct  irda_device idev;
+	INFRARED_MODE mode;
 };
  
-int irtty_register_dongle(struct dongle *dongle);
-void irtty_unregister_dongle(struct dongle *dongle);
+int irtty_register_dongle(struct dongle_reg *dongle);
+void irtty_unregister_dongle(struct dongle_reg *dongle);
 
 #endif
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/irvtd.h linux.15p9/include/net/irda/irvtd.h
--- linux.vanilla/include/net/irda/irvtd.h	Sat Aug 14 02:26:51 1999
+++ linux.15p9/include/net/irda/irvtd.h	Thu Jan  1 01:00:00 1970
@@ -1,95 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      irvtd.h
- * Version:       0.1
- * Sources:       irlpt.h
- * 
- *     Copyright (c) 1998, Takahide Higuchi <thiguchi@pluto.dti.ne.jp>,
- *     All Rights Reserved.
- *     
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
- *     the License, or (at your option) any later version.
- *
- *     I, Takahide Higuchi, provide no warranty for any of this software.
- *     This material is provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#ifndef IRVTD_H
-#define IRVTD_H
-
-#include <linux/types.h>
-#include <linux/ioctl.h>
-#include <linux/tqueue.h>
-#include <linux/serial.h>
-
-#include <net/irda/irmod.h>
-#include <net/irda/qos.h>
-#include <net/irda/ircomm_common.h>
-
-
-#define IRVTD_MAGIC 0xff545943  /* random */
-#define COMM_MAX_TTY 1
-#define IRVTD_RX_QUEUE_HIGH 10
-#define IRVTD_RX_QUEUE_LOW  2
-
-#define IRCOMM_MAJOR  60;  /* Zero means automatic allocation
-                              60,61,62,and 63 is reserved for experiment */
-#define IRVTD_MINOR 64
-
-
-
-struct irvtd_cb {
-
-        int magic;          /* magic used to detect corruption of the struct */
-
-	/* if daddr is NULL, remote device have not been discovered yet */
-
-	int tx_disable;
-	int rx_disable;
-	struct sk_buff *txbuff;     
-	struct sk_buff_head rxbuff; 
-	struct ircomm_cb *comm;     /* ircomm instance */
-
-	__u32 tx_max_sdu_size;
-	__u32 max_header_size;
-	/* 
-	 * These members are used for compatibility with usual serial device.
-	 * See linux/serial.h
-	 */
-
-	int flags;
-	struct tty_struct *tty;
-
-	int line;
-	int count;                /* open count */
-	int blocked_open;
-	struct wait_queue       *open_wait;
-	struct wait_queue       *close_wait;
-	struct wait_queue       *delta_msr_wait;
-	struct wait_queue       *tx_wait;
-
-	struct timer_list       tx_timer;
-	struct timer_list       rx_timer;
-
-	long pgrp;
-	long session;  
-	unsigned short  closing_wait;     /* time to wait before closing */
-	unsigned short  close_delay;
-	
-	int custom_divisor;
-	int mcr;
-	int msr;
-	int cts_stoptx;
-	int ttp_stoptx;
-	int ttp_stoprx;
-	int disconnect_pend;
-	struct serial_icounter_struct icount;
-	int read_status_mask;
-	int ignore_status_mask;
-};
-
-
-#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/nsc-ircc.h linux.15p9/include/net/irda/nsc-ircc.h
--- linux.vanilla/include/net/irda/nsc-ircc.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/include/net/irda/nsc-ircc.h	Wed Jan 26 23:58:32 2000
@@ -0,0 +1,263 @@
+/*********************************************************************
+ *                
+ * Filename:      nsc-ircc.h
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Fri Nov 13 14:37:40 1998
+ * Modified at:   Sun Jan 23 17:47:00 2000
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>
+ *     Copyright (c) 1998 Lichen Wang, <lwang@actisys.com>
+ *     Copyright (c) 1998 Actisys Corp., www.actisys.com
+ *     All Rights Reserved
+ *      
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ *  
+ *     Neither Dag Brattli nor University of Tromsř admit liability nor
+ *     provide warranty for any of this software. This material is 
+ *     provided "AS-IS" and at no charge.
+ *     
+ ********************************************************************/
+
+#ifndef NSC_IRCC_H
+#define NSC_IRCC_H
+
+#include <linux/time.h>
+
+#include <asm/spinlock.h>
+#include <asm/io.h>
+
+/* DMA modes needed */
+#define DMA_TX_MODE     0x08    /* Mem to I/O, ++, demand. */
+#define DMA_RX_MODE     0x04    /* I/O to mem, ++, demand. */
+
+/* Config registers for the '108 */
+#define CFG_BAIC 0x00
+#define CFG_CSRT 0x01
+#define CFG_MCTL 0x02
+
+/* Config registers for the '338 */
+#define CFG_FER  0x00
+#define CFG_FAR  0x01
+#define CFG_PTR  0x02
+#define CFG_PNP0 0x1b
+#define CFG_PNP1 0x1c
+#define CFG_PNP3 0x4f
+
+/* Flags for configuration register CRF0 */
+#define APEDCRC		0x02
+#define ENBNKSEL	0x01
+
+/* Set 0 */
+#define TXD             0x00 /* Transmit data port */
+#define RXD             0x00 /* Receive data port */
+
+/* Register 1 */
+#define IER		0x01 /* Interrupt Enable Register*/
+#define IER_RXHDL_IE    0x01 /* Receiver high data level interrupt */
+#define IER_TXLDL_IE    0x02 /* Transeiver low data level interrupt */
+#define IER_LS_IE	0x04//* Link Status Interrupt */
+#define IER_ETXURI      0x04 /* Tx underrun */
+#define IER_DMA_IE	0x10 /* DMA finished interrupt */
+#define IER_TXEMP_IE    0x20
+#define IER_SFIF_IE     0x40 /* Frame status FIFO intr */
+#define IER_TMR_IE      0x80 /* Timer event */
+
+#define FCR		0x02 /* (write only) */
+#define FCR_FIFO_EN     0x01 /* Enable FIFO's */
+#define FCR_RXSR        0x02 /* Rx FIFO soft reset */
+#define FCR_TXSR        0x04 /* Tx FIFO soft reset */
+#define FCR_RXTH	0x40 /* Rx FIFO threshold (set to 16) */
+#define FCR_TXTH	0x20 /* Tx FIFO threshold (set to 17) */
+
+#define EIR		0x02 /* (read only) */
+#define EIR_RXHDL_EV	0x01
+#define EIR_TXLDL_EV    0x02
+#define EIR_LS_EV	0x04
+#define EIR_DMA_EV	0x10
+#define EIR_TXEMP_EV	0x20
+#define EIR_SFIF_EV     0x40
+#define EIR_TMR_EV      0x80
+
+#define LCR             0x03 /* Link control register */
+#define LCR_WLS_8       0x03 /* 8 bits */
+
+#define BSR 	        0x03 /* Bank select register */
+#define BSR_BKSE        0x80
+#define BANK0 	        LCR_WLS_8 /* Must make sure that we set 8N1 */
+#define BANK1	        0x80
+#define BANK2	        0xe0
+#define BANK3	        0xe4
+#define BANK4	        0xe8
+#define BANK5	        0xec
+#define BANK6	        0xf0
+#define BANK7     	0xf4
+
+#define MCR		0x04 /* Mode Control Register */
+#define MCR_MODE_MASK	~(0xd0)
+#define MCR_UART        0x00
+#define MCR_RESERVED  	0x20	
+#define MCR_SHARP_IR    0x40
+#define MCR_SIR         0x60
+#define MCR_MIR  	0x80
+#define MCR_FIR		0xa0
+#define MCR_CEIR        0xb0
+#define MCR_IR_PLS      0x10
+#define MCR_DMA_EN	0x04
+#define MCR_EN_IRQ	0x08
+#define MCR_TX_DFR	0x08
+
+#define LSR             0x05 /* Link status register */
+#define LSR_RXDA        0x01 /* Receiver data available */
+#define LSR_TXRDY       0x20 /* Transmitter ready */
+#define LSR_TXEMP       0x40 /* Transmitter empty */
+
+#define ASCR            0x07 /* Auxillary Status and Control Register */
+#define ASCR_RXF_TOUT   0x01 /* Rx FIFO timeout */
+#define ASCR_FEND_INF   0x02 /* Frame end bytes in rx FIFO */
+#define ASCR_S_EOT      0x04 /* Set end of transmission */
+#define ASCT_RXBSY      0x20 /* Rx busy */
+#define ASCR_TXUR       0x40 /* Transeiver underrun */
+#define ASCR_CTE        0x80 /* Clear timer event */
+
+/* Bank 2 */
+#define BGDL            0x00 /* Baud Generator Divisor Port (Low Byte) */
+#define BGDH            0x01 /* Baud Generator Divisor Port (High Byte) */
+
+#define ECR1		0x02 /* Extended Control Register 1 */
+#define ECR1_EXT_SL	0x01 /* Extended Mode Select */
+#define ECR1_DMANF	0x02 /* DMA Fairness */
+#define ECR1_DMATH      0x04 /* DMA Threshold */
+#define ECR1_DMASWP	0x08 /* DMA Swap */
+
+#define EXCR2		0x04
+#define EXCR2_TFSIZ	0x01 /* Rx FIFO size = 32 */
+#define EXCR2_RFSIZ	0x04 /* Tx FIFO size = 32 */
+
+#define TXFLV           0x06 /* Tx FIFO level */
+#define RXFLV           0x07 /* Rx FIFO level */
+
+/* Bank 3 */
+#define MID		0x00
+
+/* Bank 4 */
+#define TMRL            0x00 /* Timer low byte */
+#define TMRH            0x01 /* Timer high byte */
+#define IRCR1           0x02 /* Infrared control register 1 */
+#define IRCR1_TMR_EN    0x01 /* Timer enable */
+
+#define TFRLL		0x04
+#define TFRLH		0x05
+#define RFRLL		0x06
+#define RFRLH		0x07
+
+/* Bank 5 */
+#define IRCR2           0x04 /* Infrared control register 2 */
+#define IRCR2_MDRS      0x04 /* MIR data rate select */
+#define IRCR2_FEND_MD   0x20 /* */
+
+#define FRM_ST          0x05 /* Frame status FIFO */
+#define FRM_ST_VLD      0x80 /* Frame status FIFO data valid */
+#define FRM_ST_ERR_MSK  0x5f
+#define FRM_ST_LOST_FR  0x40 /* Frame lost */
+#define FRM_ST_MAX_LEN  0x10 /* Max frame len exceeded */
+#define FRM_ST_PHY_ERR  0x08 /* Physical layer error */
+#define FRM_ST_BAD_CRC  0x04 
+#define FRM_ST_OVR1     0x02 /* Rx FIFO overrun */
+#define FRM_ST_OVR2     0x01 /* Frame status FIFO overrun */
+
+#define RFLFL           0x06
+#define RFLFH           0x07
+
+/* Bank 6 */
+#define IR_CFG2		0x00
+#define IR_CFG2_DIS_CRC	0x02
+
+/* Bank 7 */
+#define IRM_CR		0x07 /* Infrared module control register */
+#define IRM_CR_IRX_MSL	0x40
+#define IRM_CR_AF_MNT   0x80 /* Automatic format */
+
+/* NSC chip information */
+struct nsc_chip {
+	char *name;          /* Name of chipset */
+	int cfg[3];          /* Config registers */
+	u_int8_t cid_index;  /* Chip identification index reg */
+	u_int8_t cid_value;  /* Chip identification expected value */
+	u_int8_t cid_mask;   /* Chip identification revision mask */
+
+	/* Functions for probing and initializing the specific chip */
+	int (*probe)(struct nsc_chip *chip, chipio_t *info);
+	int (*init)(struct nsc_chip *chip, chipio_t *info);
+};
+typedef struct nsc_chip nsc_chip_t;
+
+/* For storing entries in the status FIFO */
+struct st_fifo_entry {
+	int status;
+	int len;
+};
+
+#define MAX_TX_WINDOW 7
+#define MAX_RX_WINDOW 7
+
+struct st_fifo {
+	struct st_fifo_entry entries[MAX_RX_WINDOW];
+	int pending_bytes;
+	int head;
+	int tail;
+	int len;
+};
+
+struct frame_cb {
+	void *start; /* Start of frame in DMA mem */
+	int len;     /* Lenght of frame in DMA mem */
+};
+
+struct tx_fifo {
+	struct frame_cb queue[MAX_TX_WINDOW]; /* Info about frames in queue */
+	int             ptr;                  /* Currently being sent */
+	int             len;                  /* Lenght of queue */
+	int             free;                 /* Next free slot */
+	void           *tail;                 /* Next free start in DMA mem */
+};
+
+/* Private data for each instance */
+struct nsc_ircc_cb {
+	struct st_fifo st_fifo;    /* Info about received frames */
+	struct tx_fifo tx_fifo;    /* Info about frames to be transmitted */
+
+	struct device *netdev;     /* Yes! we are some kind of netdevice */
+	struct net_device_stats stats;
+	
+	struct irlap_cb *irlap;    /* The link layer we are binded to */
+	struct qos_info qos;       /* QoS capabilities for this device */
+	
+	chipio_t io;               /* IrDA controller information */
+	iobuff_t tx_buff;          /* Transmit buffer */
+	iobuff_t rx_buff;          /* Receive buffer */
+
+	__u8 ier;                  /* Interrupt enable register */
+
+	struct timeval stamp;
+	struct timeval now;
+
+	spinlock_t lock;           /* For serializing operations */
+	
+	__u32 flags;               /* Interface flags */
+	__u32 new_speed;
+	int index;                 /* Instance index */
+};
+
+static inline void switch_bank(int iobase, int bank)
+{
+		outb(bank, iobase+BSR);
+}
+
+#endif /* NSC_IRCC_H */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/nsc_fir.h linux.15p9/include/net/irda/nsc_fir.h
--- linux.vanilla/include/net/irda/nsc_fir.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/include/net/irda/nsc_fir.h	Tue Jan 18 01:08:18 2000
@@ -0,0 +1,238 @@
+/*********************************************************************
+ *                
+ * Filename:      nsc_fir.h
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Fri Nov 13 14:37:40 1998
+ * Modified at:   Tue Jan 11 10:19:50 2000
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>
+ *     Copyright (c) 1998 Lichen Wang, <lwang@actisys.com>
+ *     Copyright (c) 1998 Actisys Corp., www.actisys.com
+ *     All Rights Reserved
+ *      
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ *  
+ *     Neither Dag Brattli nor University of Tromsř admit liability nor
+ *     provide warranty for any of this software. This material is 
+ *     provided "AS-IS" and at no charge.
+ *     
+ ********************************************************************/
+
+#ifndef NSC_IRCC_H
+#define NSC_IRCC_H
+
+#include <linux/time.h>
+
+#include <asm/spinlock.h>
+#include <asm/io.h>
+
+#define PC87108         0x10
+#define PC97338         0xb0
+
+/* DMA modes needed */
+#define DMA_TX_MODE     0x08    /* Mem to I/O, ++, demand. */
+#define DMA_RX_MODE     0x04    /* I/O to mem, ++, demand. */
+
+/* Flags for configuration register CRF0 */
+#define APEDCRC		0x02
+#define ENBNKSEL	0x01
+
+/* Set 0 */
+#define TXD             0x00 /* Transmit data port */
+#define RXD             0x00 /* Receive data port */
+
+/* Register 1 */
+#define IER		0x01 /* Interrupt Enable Register*/
+#define IER_RXHDL_IE    0x01 /* Receiver high data level interrupt */
+#define IER_TXLDL_IE    0x02 /* Transeiver low data level interrupt */
+#define IER_LS_IE	0x04//* Link Status Interrupt */
+#define IER_ETXURI      0x04 /* Tx underrun */
+#define IER_DMA_IE	0x10 /* DMA finished interrupt */
+#define IER_TXEMP_IE    0x20
+#define IER_SFIF_IE     0x40 /* Frame status FIFO intr */
+#define IER_TMR_IE      0x80 /* Timer event */
+
+#define FCR		0x02 /* (write only) */
+#define FCR_FIFO_EN     0x01 /* Enable FIFO's */
+#define FCR_RXSR        0x02 /* Rx FIFO soft reset */
+#define FCR_TXSR        0x04 /* Tx FIFO soft reset */
+#define FCR_RXTH	0x40 /* Rx FIFO threshold (set to 16) */
+#define FCR_TXTH	0x20 /* Tx FIFO threshold (set to 17) */
+
+#define EIR		0x02 /* (read only) */
+#define EIR_RXHDL_EV	0x01
+#define EIR_TXLDL_EV    0x02
+#define EIR_LS_EV	0x04
+#define EIR_DMA_EV	0x10
+#define EIR_TXEMP_EV	0x20
+#define EIR_SFIF_EV     0x40
+#define EIR_TMR_EV      0x80
+
+#define LCR             0x03 /* Link control register */
+#define LCR_WLS_8       0x03 /* 8 bits */
+
+#define BSR 	        0x03 /* Bank select register */
+#define BSR_BKSE        0x80
+#define BANK0 	        LCR_WLS_8 /* Must make sure that we set 8N1 */
+#define BANK1	        0x80
+#define BANK2	        0xe0
+#define BANK3	        0xe4
+#define BANK4	        0xe8
+#define BANK5	        0xec
+#define BANK6	        0xf0
+#define BANK7     	0xf4
+
+#define MCR		0x04 /* Mode Control Register */
+#define MCR_MODE_MASK	~(0xd0)
+#define MCR_UART        0x00
+#define MCR_RESERVED  	0x20	
+#define MCR_SHARP_IR    0x40
+#define MCR_SIR         0x60
+#define MCR_MIR  	0x80
+#define MCR_FIR		0xa0
+#define MCR_CEIR        0xb0
+#define MCR_IR_PLS      0x10
+#define MCR_DMA_EN	0x04
+#define MCR_EN_IRQ	0x08
+#define MCR_TX_DFR	0x08
+
+#define LSR             0x05 /* Link status register */
+#define LSR_RXDA        0x01 /* Receiver data available */
+#define LSR_TXRDY       0x20 /* Transmitter ready */
+#define LSR_TXEMP       0x40 /* Transmitter empty */
+
+#define ASCR            0x07 /* Auxillary Status and Control Register */
+#define ASCR_RXF_TOUT   0x01 /* Rx FIFO timeout */
+#define ASCR_FEND_INF   0x02 /* Frame end bytes in rx FIFO */
+#define ASCR_S_EOT      0x04 /* Set end of transmission */
+#define ASCT_RXBSY      0x20 /* Rx busy */
+#define ASCR_TXUR       0x40 /* Transeiver underrun */
+#define ASCR_CTE        0x80 /* Clear timer event */
+
+/* Bank 2 */
+#define BGDL            0x00 /* Baud Generator Divisor Port (Low Byte) */
+#define BGDH            0x01 /* Baud Generator Divisor Port (High Byte) */
+
+#define ECR1		0x02 /* Extended Control Register 1 */
+#define ECR1_EXT_SL	0x01 /* Extended Mode Select */
+#define ECR1_DMANF	0x02 /* DMA Fairness */
+#define ECR1_DMATH      0x04 /* DMA Threshold */
+#define ECR1_DMASWP	0x08 /* DMA Swap */
+
+#define EXCR2		0x04
+#define EXCR2_TFSIZ	0x01 /* Rx FIFO size = 32 */
+#define EXCR2_RFSIZ	0x04 /* Tx FIFO size = 32 */
+
+#define TXFLV           0x06 /* Tx FIFO level */
+#define RXFLV           0x07 /* Rx FIFO level */
+
+/* Bank 3 */
+#define MID		0x00
+
+/* Bank 4 */
+#define TMRL            0x00 /* Timer low byte */
+#define TMRH            0x01 /* Timer high byte */
+#define IRCR1           0x02 /* Infrared control register 1 */
+#define IRCR1_TMR_EN    0x01 /* Timer enable */
+
+#define TFRLL		0x04
+#define TFRLH		0x05
+#define RFRLL		0x06
+#define RFRLH		0x07
+
+/* Bank 5 */
+#define IRCR2           0x04 /* Infrared control register 2 */
+#define IRCR2_MDRS      0x04 /* MIR data rate select */
+#define IRCR2_FEND_MD   0x20 /* */
+
+#define FRM_ST          0x05 /* Frame status FIFO */
+#define FRM_ST_VLD      0x80 /* Frame status FIFO data valid */
+#define FRM_ST_ERR_MSK  0x5f
+#define FRM_ST_LOST_FR  0x40 /* Frame lost */
+#define FRM_ST_MAX_LEN  0x10 /* Max frame len exceeded */
+#define FRM_ST_PHY_ERR  0x08 /* Physical layer error */
+#define FRM_ST_BAD_CRC  0x04 
+#define FRM_ST_OVR1     0x02 /* Rx FIFO overrun */
+#define FRM_ST_OVR2     0x01 /* Frame status FIFO overrun */
+
+#define RFLFL           0x06
+#define RFLFH           0x07
+
+/* Bank 6 */
+#define IR_CFG2		0x00
+#define IR_CFG2_DIS_CRC	0x02
+
+/* Bank 7 */
+#define IRM_CR		0x07 /* Infrared module control register */
+#define IRM_CR_IRX_MSL	0x40
+#define IRM_CR_AF_MNT   0x80 /* Automatic format */
+
+/* For storing entries in the status FIFO */
+struct st_fifo_entry {
+	int status;
+	int len;
+};
+
+struct st_fifo {
+	struct st_fifo_entry entries[10];
+	int head;
+	int tail;
+	int len;
+};
+
+struct frame_cb {
+	void *start; /* Start of frame in DMA mem */
+	int len;     /* Lenght of frame in DMA mem */
+};
+
+#define MAX_WINDOW 7
+
+struct tx_fifo {
+	struct frame_cb queue[MAX_WINDOW]; /* Info about frames in queue */
+	int             ptr;               /* Currently being sent */
+	int             len;               /* Lenght of queue */
+	int             free;              /* Next free slot */
+	void           *tail;              /* Next free start in DMA mem */
+};
+
+/* Private data for each instance */
+struct nsc_ircc_cb {
+	struct st_fifo st_fifo;    /* Info about received frames */
+	struct tx_fifo tx_fifo;    /* Info about frames to be transmitted */
+
+	int tx_buff_offsets[10];   /* Offsets between frames in tx_buff */
+	int tx_len;                /* Number of frames in tx_buff */
+
+	struct device *netdev;     /* Yes! we are some kind of netdevice */
+	struct net_device_stats stats;
+	
+	struct irlap_cb *irlap;    /* The link layer we are binded to */
+	
+	struct chipio_t io;        /* IrDA controller information */
+	struct iobuff_t tx_buff;   /* Transmit buffer */
+	struct iobuff_t rx_buff;   /* Receive buffer */
+	struct qos_info qos;       /* QoS capabilities for this device */
+
+	struct timeval  stamp;
+	struct timeval  now;
+
+	spinlock_t lock;           /* For serializing operations */
+	
+	__u32 flags;               /* Interface flags */
+	__u32 new_speed;
+	int suspend;
+};
+
+static inline void switch_bank(int iobase, int bank)
+{
+		outb(bank, iobase+BSR);
+}
+
+#endif /* NSC_IRCC_H */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/parameters.h linux.15p9/include/net/irda/parameters.h
--- linux.vanilla/include/net/irda/parameters.h	Thu Jan  1 01:00:00 1970
+++ linux.15p9/include/net/irda/parameters.h	Mon Feb  7 12:17:43 2000
@@ -0,0 +1,105 @@
+/*********************************************************************
+ *                
+ * Filename:      parameters.h
+ * Version:       1.0
+ * Description:   A more general way to handle (pi,pl,pv) parameters
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Mon Jun  7 08:47:28 1999
+ * Modified at:   Sun Jan 30 14:05:14 2000
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#ifndef IRDA_PARAMS_H
+#define IRDA_PARAMS_H
+
+/*
+ *  The currently supported types. Beware not to change the sequence since
+ *  it a good reason why the sized integers has a value equal to their size
+ */
+typedef enum {
+	PV_INTEGER,      /* Integer of any (pl) length */
+	PV_INT_8_BITS,   /* Integer of 8 bits in length */
+	PV_INT_16_BITS,  /* Integer of 16 bits in length */
+	PV_STRING,       /* \0 terminated string */
+	PV_INT_32_BITS,  /* Integer of 32 bits in length */
+	PV_OCT_SEQ,      /* Octet sequence */
+	PV_NO_VALUE      /* Does not contain any value (pl=0) */
+} PV_TYPE;
+
+/* Bit 7 of type field */
+#define PV_BIG_ENDIAN    0x80 
+#define PV_LITTLE_ENDIAN 0x00
+#define PV_MASK          0x7f   /* To mask away endian bit */
+
+#define PV_PUT 0
+#define PV_GET 1
+
+typedef union {
+	char   *c;
+	__u8    b;
+	__u16   s;
+	__u32   i;
+	__u8  *bp;
+	__u16 *sp;
+	__u32 *ip;
+} irda_pv_t;
+
+typedef struct {
+	__u8 pi;
+	__u8 pl;
+	irda_pv_t pv;
+} irda_param_t;
+
+typedef int (*PI_HANDLER)(void *self, irda_param_t *param, int get);
+typedef int (*PV_HANDLER)(void *self, __u8 *buf, int len, __u8 pi,
+			  PV_TYPE type, PI_HANDLER func);
+
+typedef struct {
+	PI_HANDLER func;  /* Handler for this parameter identifier */
+	PV_TYPE    type;  /* Data type for this parameter */
+} pi_minor_info_t;
+
+typedef struct {
+	pi_minor_info_t *pi_minor_call_table;
+	int len;
+} pi_major_info_t;
+
+typedef struct {
+	pi_major_info_t *tables;
+	int              len;
+	__u8             pi_mask;
+	int              pi_major_offset;
+} pi_param_info_t;
+
+int irda_param_pack(__u8 *buf, char *fmt, ...);
+int irda_param_unpack(__u8 *buf, char *fmt, ...);
+
+int irda_param_insert(void *self, __u8 pi, __u8 *buf, int len, 
+		      pi_param_info_t *info);
+int irda_param_extract(void *self, __u8 *buf, int len, pi_param_info_t *info);
+int irda_param_extract_all(void *self, __u8 *buf, int len, 
+			   pi_param_info_t *info);
+
+#define irda_param_insert_byte(buf,pi,pv) irda_param_pack(buf,"bbb",pi,1,pv)
+
+#endif /* IRDA_PARAMS_H */
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/pc87108.h linux.15p9/include/net/irda/pc87108.h
--- linux.vanilla/include/net/irda/pc87108.h	Sun Mar  7 23:26:44 1999
+++ linux.15p9/include/net/irda/pc87108.h	Thu Jan  1 01:00:00 1970
@@ -1,194 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      pc87108.h
- * Version:       
- * Description:   
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Fri Nov 13 14:37:40 1998
- * Modified at:   Mon Jan 25 23:10:25 1999
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>
- *     Copyright (c) 1998 Lichen Wang, <lwang@actisys.com>
- *     Copyright (c) 1998 Actisys Corp., www.actisys.com
- *     All Rights Reserved
- *      
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
- *     the License, or (at your option) any later version.
- *  
- *     Neither Dag Brattli nor University of Tromsř admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
- *     
- ********************************************************************/
-
-#ifndef PC87108_H
-#define PC87108_H
-
-#include <asm/io.h>
-
-/* Flags for configuration register CRF0 */
-#define APEDCRC		0x02
-#define ENBNKSEL	0x01
-
-/* Set 0 */
-#define TXD             0x00 /* Transmit data port */
-#define RXD             0x00 /* Receive data port */
-
-/* Register 1 */
-#define IER		0x01 /* Interrupt Enable Register*/
-#define IER_RXHDL_IE    0x01 /* Receiver high data level interrupt */
-#define IER_TXLDL_IE    0x02 /* Transeiver low data level interrupt */
-#define IER_LS_IE	0x04//* Link Status Interrupt */
-#define IER_ETXURI      0x04 /* Tx underrun */
-#define IER_DMA_IE	0x10 /* DMA finished interrupt */
-#define IER_TXEMP_IE    0x20
-#define IER_SFIF_IE     0x40 /* Frame status FIFO intr */
-#define IER_TMR_IE      0x80 /* Timer event */
-
-#define FCR		0x02 /* (write only) */
-#define FCR_FIFO_EN     0x01 /* Enable FIFO's */
-#define FCR_RXSR        0x02 /* Rx FIFO soft reset */
-#define FCR_TXSR        0x04 /* Tx FIFO soft reset */
-#define FCR_RXTH	0x80 /* Rx FIFO threshold (set to 16) */
-#define FCR_TXTH	0x20 /* Tx FIFO threshold (set to 17) */
-
-#define EIR		0x02 /* (read only) */
-#define EIR_RXHDL_EV	0x01
-#define EIR_TXLDL_EV    0x02
-#define EIR_LS_EV	0x04
-#define EIR_DMA_EV	0x10
-#define EIR_TXEMP_EV	0x20
-#define EIR_SFIF_EV     0x40
-#define EIR_TMR_EV      0x80
-
-#define LCR             0x03 /* Link control register */
-#define LCR_WLS_8       0x03 /* 8 bits */
-
-#define BSR 	        0x03 /* Bank select register */
-#define BSR_BKSE        0x80
-#define BANK0 	        LCR_WLS_8 /* Must make sure that we set 8N1 */
-#define BANK1	        0x80
-#define BANK2	        0xe0
-#define BANK3	        0xe4
-#define BANK4	        0xe8
-#define BANK5	        0xec
-#define BANK6	        0xf0
-#define BANK7     	0xf4
-
-#define MCR		0x04 /* Mode Control Register */
-#define MCR_MODE_MASK	~(0xd0)
-#define MCR_UART        0x00
-#define MCR_RESERVED  	0x20	
-#define MCR_SHARP_IR    0x40
-#define MCR_SIR         0x60
-#define MCR_MIR  	0x80
-#define MCR_FIR		0xa0
-#define MCR_CEIR        0xb0
-#define MCR_DMA_EN	0x04
-#define MCR_EN_IRQ	0x08
-#define MCR_TX_DFR	0x08
-
-#define LSR             0x05 /* Link status register */
-#define LSR_RXDA        0x01 /* Receiver data available */
-#define LSR_TXRDY       0x20 /* Transmitter ready */
-#define LSR_TXEMP       0x40 /* Transmitter empty */
-
-#define ASCR            0x07 /* Auxillary Status and Control Register */
-#define ASCR_RXF_TOUT   0x01 /* Rx FIFO timeout */
-#define ASCR_FEND_INF   0x02 /* Frame end bytes in rx FIFO */
-#define ASCR_S_EOT      0x04 /* Set end of transmission */
-#define ASCT_RXBSY      0x20 /* Rx busy */
-#define ASCR_TXUR       0x40 /* Transeiver underrun */
-#define ASCR_CTE        0x80 /* Clear timer event */
-
-/* Bank 2 */
-#define BGDL            0x00 /* Baud Generator Divisor Port (Low Byte) */
-#define BGDH            0x01 /* Baud Generator Divisor Port (High Byte) */
-
-#define ECR1		0x02 /* Extended Control Register 1 */
-#define ECR1_EXT_SL	0x01 /* Extended Mode Select */
-#define ECR1_DMANF	0x02 /* DMA Fairness */
-#define ECR1_DMATH      0x04
-#define ECR1_DMASWP	0x08 /* DMA Swap */
-
-#define EXCR2		0x04
-#define EXCR2_TFSIZ	0x01 /* Rx FIFO size = 32 */
-#define EXCR2_RFSIZ	0x04 /* Tx FIFO size = 32 */
-
-#define TXFLV           0x06 /* Tx FIFO level */
-#define RXFLV           0x07 /* Rx FIFO level */
-
-/* Bank 3 */
-#define MID		0x00
-
-/* Bank 4 */
-#define TMRL            0x00 /* Timer low byte */
-#define TMRH            0x01 /* Timer high byte */
-#define IRCR1           0x02 /* Infrared control register 1 */
-#define IRCR1_TMR_EN    0x01 /* Timer enable */
-
-#define TFRLL		0x04
-#define TFRLH		0x05
-#define RFRLL		0x06
-#define RFRLH		0x07
-
-/* Bank 5 */
-#define IRCR2           0x04 /* Infrared control register 2 */
-#define IRCR2_MDRS      0x04 /* MIR data rate select */
-#define IRCR2_FEND_MD   0x20 /* */
-
-#define FRM_ST          0x05 /* Frame status FIFO */
-#define FRM_ST_VLD      0x80 /* Frame status FIFO data valid */
-#define FRM_ST_ERR_MSK  0x5f
-#define FRM_ST_LOST_FR  0x40 /* Frame lost */
-#define FRM_ST_MAX_LEN  0x10 /* Max frame len exceeded */
-#define FRM_ST_PHY_ERR  0x08 /* Physical layer error */
-#define FRM_ST_BAD_CRC  0x04 
-#define FRM_ST_OVR1     0x02 /* Receive overrun */
-#define FRM_ST_OVR2     0x01 /* Frame status FIFO overrun */
-
-#define RFLFL           0x06
-#define RFLFH           0x07
-
-/* Bank 6 */
-#define IR_CFG2		0x00
-#define IR_CFG2_DIS_CRC	0x02
-
-/* Bank 7 */
-#define IRM_CR		0x07 /* Infrared module control register */
-#define IRM_CR_IRX_MSL	0x40
-#define IRM_CR_AF_MNT   0x80 /* Automatic format */
-
-/* For storing entries in the status FIFO */
-struct st_fifo_entry {
-	int status;
-	int len;
-};
-
-struct st_fifo {
-	struct st_fifo_entry entries[10];
-	int head;
-	int tail;
-	int len;
-};
-
-/* Private data for each instance */
-struct pc87108 {
-	struct st_fifo st_fifo;
-
-	int tx_buff_offsets[10]; /* Offsets between frames in tx_buff */
-	int tx_len;          /* Number of frames in tx_buff */
-
-	struct irda_device idev;
-};
-
-static inline void switch_bank( int iobase, int bank)
-{
-		outb( bank, iobase+BSR);
-}
-
-#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/qos.h linux.15p9/include/net/irda/qos.h
--- linux.vanilla/include/net/irda/qos.h	Thu Dec 17 17:01:03 1998
+++ linux.15p9/include/net/irda/qos.h	Mon Feb  7 13:09:51 2000
@@ -1,33 +1,41 @@
 /*********************************************************************
  *                
  * Filename:      qos.h
- * Version:       0.1
+ * Version:       1.0
  * Description:   Quality of Service definitions
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Fri Sep 19 23:21:09 1997
- * Modified at:   Wed Dec  9 10:32:47 1998
+ * Modified at:   Thu Dec  2 13:51:54 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
- *
- *     Neither Dag Brattli nor University of Tromsř admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
- *
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
  ********************************************************************/
 
-#ifndef QOS_H
-#define QOS_H
+#ifndef IRDA_QOS_H
+#define IRDA_QOS_H
 
 #include <linux/config.h>
 #include <linux/skbuff.h>
 
+#include <net/irda/parameters.h>
+
 #define PI_BAUD_RATE     0x01
 #define PI_MAX_TURN_TIME 0x82
 #define PI_DATA_SIZE     0x83
@@ -41,26 +49,27 @@
 #define IR_115200_MAX 0x3f
 
 /* Baud rates (first byte) */
-#define IR_2400    0x01
-#define IR_9600    0x02
-#define IR_19200   0x04
-#define IR_38400   0x08
-#define IR_57600   0x10
-#define IR_115200  0x20
-#define IR_576000  0x40
-#define IR_1152000 0x80
+#define IR_2400     0x01
+#define IR_9600     0x02
+#define IR_19200    0x04
+#define IR_38400    0x08
+#define IR_57600    0x10
+#define IR_115200   0x20
+#define IR_576000   0x40
+#define IR_1152000  0x80
 
 /* Baud rates (second byte) */
-#define IR_4000000 0x01
+#define IR_4000000  0x01
+#define IR_16000000 0x02
 
 /* Quality of Service information */
 typedef struct {
-	int value;
+	__u32 value;
 	__u16 bits; /* LSB is first byte, MSB is second byte */
 } qos_value_t;
 
 struct qos_info {
-	int  magic;
+	magic_t magic;
 
 	qos_value_t baud_rate;       /* IR_11520O | ... */
 	qos_value_t max_turn_time;
@@ -77,24 +86,25 @@
 #endif
 };
 
-extern int baud_rates[];
-extern int data_size[];
-extern int min_turn_time[];
-extern int add_bofs[];
-extern int compression[];
-
-void irda_init_max_qos_capabilies( struct qos_info *qos);
-void irda_qos_compute_intersection( struct qos_info *, struct qos_info *);
-int  irda_insert_qos_negotiation_params( struct qos_info *qos, __u8 *fp);
-void irda_qos_negotiate( struct qos_info *qos_rx, struct qos_info *qos_tx,
-			 struct sk_buff *skb);
-
-int msb_index ( __u16 byte);
-int byte_value( __u8 byte, int *array);
-int value_index( int value, int *array);
-int index_value( int index, int *array);
+extern __u32 baud_rates[];
+extern __u32 data_sizes[];
+extern __u32 min_turn_times[];
+extern __u32 add_bofs[];
+extern __u32 compressions[];
+
+void irda_init_max_qos_capabilies(struct qos_info *qos);
+void irda_qos_compute_intersection(struct qos_info *, struct qos_info *);
+
+__u32 irlap_max_line_capacity(__u32 speed, __u32 max_turn_time);
+__u32 irlap_requested_line_capacity(struct qos_info *qos);
+__u32 irlap_min_turn_time_in_bytes(__u32 speed, __u32 min_turn_time);
+
+int msb_index(__u16 byte);
+int value_index(__u32 value, __u32 *array);
+__u32 byte_value(__u8 byte, __u32 *array);
+__u32 index_value(int index, __u32 *array);
 
-void irda_qos_bits_to_value( struct qos_info *qos);
+void irda_qos_bits_to_value(struct qos_info *qos);
 
 #endif
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/smc-ircc.h linux.15p9/include/net/irda/smc-ircc.h
--- linux.vanilla/include/net/irda/smc-ircc.h	Sat Aug 14 02:26:51 1999
+++ linux.15p9/include/net/irda/smc-ircc.h	Mon Feb  7 13:23:22 2000
@@ -1,160 +1,186 @@
 /*********************************************************************
  *                
- * Filename:      smc.h
- * Version:       
- * Description:   
+ * Filename:      smc-ircc.h
+ * Version:       0.3
+ * Description:   Definitions for the SMC IrCC chipset
  * Status:        Experimental.
  * Author:        Thomas Davis (tadavis@jps.net)
  *
- *     Copyright (c) 1998, 1999 Thomas Davis (tadavis@jps.net>
+ *     Copyright (c) 1999-2000, Dag Brattli <dagb@cs.uit.no>
+ *     Copyright (c) 1998-1999, Thomas Davis (tadavis@jps.net>
  *     All Rights Reserved
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
- *  
- *     I, Thomas Davis, admit no liability nor provide warranty for any
- *     of this software. This material is provided "AS-IS" and at no charge.
- *     
- * Definitions for the SMC IrCC controller.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
  *
  ********************************************************************/
 
 #ifndef SMC_IRCC_H
 #define SMC_IRCC_H
 
-#define UART_MASTER			0x07
-#define UART_MASTER_POWERDOWN	1<<7
-#define UART_MASTER_RESET		1<<6
-#define UART_MASTER_INT_EN		1<<5
-#define UART_MASTER_ERROR_RESET	1<<4
+#include <asm/spinlock.h>
+
+#include <net/irda/irport.h>
+
+/* DMA modes needed */
+#define DMA_TX_MODE                0x08    /* Mem to I/O, ++, demand. */
+#define DMA_RX_MODE                0x04    /* I/O to mem, ++, demand. */
+
+/* Master Control Register */
+#define IRCC_MASTER                0x07
+#define   IRCC_MASTER_POWERDOWN	   0x80
+#define   IRCC_MASTER_RESET        0x40
+#define   IRCC_MASTER_INT_EN       0x20
+#define   IRCC_MASTER_ERROR_RESET  0x10
 
 /* Register block 0 */
 
-#define UART_IIR	0x01
-#define UART_IER	0x02
-#define UART_LSR	0x03
-#define UART_LCR_A	0x04
-#define UART_LCR_B	0x05
-#define UART_BSR	0x06
-
-#define UART_IIR_ACTIVE_FRAME	1<<7
-#define UART_IIR_EOM 		1<<6
-#define UART_IIR_RAW_MODE		1<<5
-#define UART_IIR_FIFO		1<<4
-
-#define UART_IER_ACTIVE_FRAME	1<<7
-#define UART_IER_EOM 		1<<6
-#define UART_IER_RAW_MODE		1<<5
-#define UART_IER_FIFO		1<<4
-
-#define UART_LSR_UNDERRUN		1<<7
-#define UART_LSR_OVERRUN		1<<6
-#define UART_LSR_FRAME_ERROR 	1<<5
-#define UART_LSR_SIZE_ERROR		1<<4
-#define UART_LSR_CRC_ERROR		1<<3
-#define UART_LSR_FRAME_ABORT 	1<<2
-
-#define UART_LCR_A_FIFO_RESET        1<<7
-#define UART_LCR_A_FAST              1<<6
-#define UART_LCR_A_GP_DATA           1<<5
-#define UART_LCR_A_RAW_TX            1<<4
-#define UART_LCR_A_RAW_RX            1<<3
-#define UART_LCR_A_ABORT             1<<2
-#define UART_LCR_A_DATA_DONE         1<<1
-
-#define UART_LCR_B_SCE_DISABLED 	0x00<<6
-#define UART_LCR_B_SCE_TRANSMIT 	0x01<<6
-#define UART_LCR_B_SCE_RECEIVE		0x02<<6
-#define UART_LCR_B_SCE_UNDEFINED	0x03<<6
-#define UART_LCR_B_SIP_ENABLE		1<<5
-#define UART_LCR_B_BRICK_WALL		1<<4
-
-#define UART_BSR_NOT_EMPTY	1<<7
-#define UART_BSR_FIFO_FULL	1<<6
-#define UART_BSR_TIMEOUT	1<<5
+/* Interrupt Identification */
+#define IRCC_IIR                   0x01
+#define   IRCC_IIR_ACTIVE_FRAME    0x80
+#define   IRCC_IIR_EOM             0x40
+#define   IRCC_IIR_RAW_MODE        0x20
+#define   IRCC_IIR_FIFO		   0x10
+
+/* Interrupt Enable */
+#define IRCC_IER                   0x02
+#define   IRCC_IER_ACTIVE_FRAME	   0x80
+#define   IRCC_IER_EOM 		   0x40
+#define   IRCC_IER_RAW_MODE        0x20
+#define   IRCC_IER_FIFO		   0x10
+
+/* Line Status Register */
+#define IRCC_LSR                   0x03
+#define   IRCC_LSR_UNDERRUN        0x80
+#define   IRCC_LSR_OVERRUN         0x40
+#define   IRCC_LSR_FRAME_ERROR     0x20
+#define   IRCC_LSR_SIZE_ERROR      0x10
+#define   IRCC_LSR_CRC_ERROR       0x80
+#define   IRCC_LSR_FRAME_ABORT 	   0x40
+
+/* Line Control Register A */
+#define IRCC_LCR_A                 0x04
+#define   IRCC_LCR_A_FIFO_RESET    0x80
+#define   IRCC_LCR_A_FAST          0x40
+#define   IRCC_LCR_A_GP_DATA       0x20
+#define   IRCC_LCR_A_RAW_TX        0x10
+#define   IRCC_LCR_A_RAW_RX        0x08
+#define   IRCC_LCR_A_ABORT         0x04
+#define   IRCC_LCR_A_DATA_DONE     0x02
+
+/* Line Control Register B */
+#define IRCC_LCR_B                 0x05
+#define   IRCC_LCR_B_SCE_DISABLED  0x00
+#define   IRCC_LCR_B_SCE_TRANSMIT  0x40
+#define   IRCC_LCR_B_SCE_RECEIVE   0x80
+#define   IRCC_LCR_B_SCE_UNDEFINED 0xc0
+#define   IRCC_LCR_B_SIP_ENABLE	   0x20
+#define   IRCC_LCR_B_BRICK_WALL    0x10
+
+/* Bus Status Register */
+#define IRCC_BSR                   0x06
+#define   IRCC_BSR_NOT_EMPTY	   0x80
+#define   IRCC_BSR_FIFO_FULL	   0x40
+#define   IRCC_BSR_TIMEOUT	   0x20
 
 /* Register block 1 */
 
-#define UART_SCE_CFGA	0x00
-#define UART_SCE_CFGB	0x01
-#define UART_FIFO_THRESHOLD	0x02
-
-#define UART_CFGA_AUX_IR		0x01<<7
-#define UART_CFGA_HALF_DUPLEX	0x01<<2
-#define UART_CFGA_TX_POLARITY	0x01<<1
-#define UART_CFGA_RX_POLARITY	0x01
-
-#define UART_CFGA_COM		0x00<<3
-#define UART_CFGA_IRDA_SIR_A	0x01<<3
-#define UART_CFGA_ASK_SIR		0x02<<3
-#define UART_CFGA_IRDA_SIR_B	0x03<<3
-#define UART_CFGA_IRDA_HDLC 	0x04<<3
-#define UART_CFGA_IRDA_4PPM 	0x05<<3
-#define UART_CFGA_CONSUMER		0x06<<3
-#define UART_CFGA_RAW_IR		0x07<<3
-#define UART_CFGA_OTHER		0x08<<3
-
-#define UART_IR_HDLC			0x04
-#define UART_IR_4PPM			0x01
-#define UART_IR_CONSUMER		0x02
-
-#define UART_CFGB_LOOPBACK		0x01<<5
-#define UART_CFGB_LPBCK_TX_CRC	0x01<<4
-#define UART_CFGB_NOWAIT		0x01<<3
-#define UART_CFGB_STRING_MOVE	0x01<<2
-#define UART_CFGB_DMA_BURST 	0x01<<1
-#define UART_CFGB_DMA_ENABLE	0x01
-
-#define UART_CFGB_COM		0x00<<6
-#define UART_CFGB_IR		0x01<<6
-#define UART_CFGB_AUX		0x02<<6
-#define UART_CFGB_INACTIVE		0x03<<6
+#define IRCC_FIFO_THRESHOLD	   0x02
 
-/* Register block 2 - Consumer IR - not used */
+#define IRCC_SCE_CFGA	           0x00
+#define   IRCC_CFGA_AUX_IR	   0x80
+#define   IRCC_CFGA_HALF_DUPLEX	   0x04
+#define   IRCC_CFGA_TX_POLARITY	   0x02
+#define   IRCC_CFGA_RX_POLARITY	   0x01
+
+#define   IRCC_CFGA_COM		   0x00
+#define   IRCC_CFGA_IRDA_SIR_A	   0x08
+#define   IRCC_CFGA_ASK_SIR	   0x10
+#define   IRCC_CFGA_IRDA_SIR_B	   0x18
+#define   IRCC_CFGA_IRDA_HDLC 	   0x20
+#define   IRCC_CFGA_IRDA_4PPM 	   0x28
+#define   IRCC_CFGA_CONSUMER	   0x30
+#define   IRCC_CFGA_RAW_IR	   0x38
+#define   IRCC_CFGA_OTHER          0x40
+
+#define IRCC_IR_HDLC               0x04
+#define IRCC_IR_4PPM               0x01
+#define IRCC_IR_CONSUMER           0x02
+
+#define IRCC_SCE_CFGB	           0x01
+#define IRCC_CFGB_LOOPBACK         0x20
+#define IRCC_CFGB_LPBCK_TX_CRC	   0x10
+#define IRCC_CFGB_NOWAIT	   0x08
+#define IRCC_CFGB_STRING_MOVE	   0x04
+#define IRCC_CFGB_DMA_BURST 	   0x02
+#define IRCC_CFGB_DMA_ENABLE	   0x01
+
+#define IRCC_CFGB_MUX_COM          0x00
+#define IRCC_CFGB_MUX_IR           0x40
+#define IRCC_CFGB_MUX_AUX          0x80
+#define IRCC_CFGB_MUX_INACTIVE	   0xc0
 
 /* Register block 3 - Identification Registers! */
-
-#define UART_ID_HIGH	0x00   /* 0x10 */
-#define UART_ID_LOW	0x01   /* 0xB8 */
-#define UART_CHIP_ID 	0x02   /* 0xF1 */
-#define UART_VERSION	0x03   /* 0x01 */
-#define UART_INTERFACE	0x04   /* low 4 = DMA, high 4 = IRQ */
+#define IRCC_ID_HIGH	           0x00   /* 0x10 */
+#define IRCC_ID_LOW	           0x01   /* 0xB8 */
+#define IRCC_CHIP_ID 	           0x02   /* 0xF1 */
+#define IRCC_VERSION	           0x03   /* 0x01 */
+#define IRCC_INTERFACE	           0x04   /* low 4 = DMA, high 4 = IRQ */
 
 /* Register block 4 - IrDA */
-#define UART_CONTROL        0x00
-#define UART_BOF_COUNT_LO      0x01
-#define UART_BRICKWALL_CNT_LO 0x02
-#define UART_BRICKWALL_TX_CNT_HI   0x03
-#define UART_TX_SIZE_LO   0x04
-#define UART_RX_SIZE_HI   0x05
-#define UART_RX_SIZE_LO   0x06
-
-#define UART_1152     0x01<<7
-#define UART_CRC      0x01<<6
-
-/* For storing entries in the status FIFO */
-struct st_fifo_entry {
-	int status;
-	int len;
-};
-
-struct st_fifo {
-	struct st_fifo_entry entries[10];
-	int head;
-	int tail;
-	int len;
+#define IRCC_CONTROL               0x00
+#define IRCC_BOF_COUNT_LO          0x01 /* Low byte */
+#define IRCC_BOF_COUNT_HI          0x00 /* High nibble (bit 0-3) */
+#define IRCC_BRICKWALL_CNT_LO      0x02 /* Low byte */
+#define IRCC_BRICKWALL_CNT_HI      0x03 /* High nibble (bit 4-7) */
+#define IRCC_TX_SIZE_LO            0x04 /* Low byte */
+#define IRCC_TX_SIZE_HI            0x03 /* High nibble (bit 0-3) */
+#define IRCC_RX_SIZE_HI            0x05 /* High nibble (bit 0-3) */
+#define IRCC_RX_SIZE_LO            0x06 /* Low byte */
+
+#define IRCC_1152                  0x80
+#define IRCC_CRC                   0x40
+
+struct smc_chip {
+	char *name;
+	unsigned char entr1;
+	unsigned char entr2;
+	unsigned char cid_index;
+	unsigned char cid_value;
+	int (*probe)(struct smc_chip *chip, chipio_t *info);
 };
+typedef struct smc_chip smc_chip_t;
 
 /* Private data for each instance */
 struct ircc_cb {
-	struct st_fifo st_fifo;
-
-	int tx_buff_offsets[10]; /* Offsets between frames in tx_buff */
-	int tx_len;          /* Number of frames in tx_buff */
+	struct device *netdev;     /* Yes! we are some kind of netdevice */
+	struct irlap_cb    *irlap; /* The link layer we are binded to */
+	
+	chipio_t io;               /* IrDA controller information */
+	iobuff_t tx_buff;          /* Transmit buffer */
+	iobuff_t rx_buff;          /* Receive buffer */
+
+	struct irport_cb *irport;
+
+	spinlock_t lock;           /* For serializing operations */
+	
+	__u32 new_speed;
+	__u32 flags;               /* Interface flags */
 
-	struct irda_device idev;
+	int tx_buff_offsets[10];   /* Offsets between frames in tx_buff */
+	int tx_len;                /* Number of frames in tx_buff */
 };
 
-#endif
+#endif /* SMC_IRCC_H */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/timer.h linux.15p9/include/net/irda/timer.h
--- linux.vanilla/include/net/irda/timer.h	Sat Aug 14 02:25:46 1999
+++ linux.15p9/include/net/irda/timer.h	Mon Feb  7 13:23:15 2000
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Aug 16 00:59:29 1997
- * Modified at:   Tue Apr  6 16:17:16 1999
+ * Modified at:   Thu Oct  7 12:25:24 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1997, 1998 Dag Brattli <dagb@cs.uit.no>, 
+ *     Copyright (c) 1997, 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
  *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
@@ -26,6 +26,8 @@
 #ifndef TIMER_H
 #define TIMER_H
 
+#include <linux/netdevice.h>
+
 #include <asm/param.h>  /* for HZ */
 
 #include <net/irda/irda.h>
@@ -37,28 +39,34 @@
 /* 
  *  Timeout definitions, some defined in IrLAP p. 92
  */
-#define POLL_TIMEOUT        450*HZ/1000    /* Must never exceed 500 ms */
-#define FINAL_TIMEOUT       500*HZ/1000    /* Must never exceed 500 ms */
+#define POLL_TIMEOUT        (450*HZ/1000)    /* Must never exceed 500 ms */
+#define FINAL_TIMEOUT       (500*HZ/1000)    /* Must never exceed 500 ms */
 
 /* 
  *  Normally twice of p-timer. Note 3, IrLAP p. 60 suggests at least twice 
  *  duration of the P-timer.
  */
-#define WD_TIMEOUT          POLL_TIMEOUT*2
-#define MEDIABUSY_TIMEOUT   500*HZ/1000    /* 500 msec */
+#define WD_TIMEOUT          (POLL_TIMEOUT*2)
+#define MEDIABUSY_TIMEOUT   (500*HZ/1000)    /* 500 msec */
 
 /*
  *  Slot timer must never exceed 85 ms, and must always be at least 25 ms, 
- *  suggested to  75-85 msec by IrDA lite
+ *  suggested to  75-85 msec by IrDA lite. This doesn't work with a lot of
+ *  devices, and other stackes uses a lot more, so it's best we do it as well
  */
-#define SLOT_TIMEOUT            80*HZ/1000
-#define QUERY_TIMEOUT           HZ          /* 1 sec */
+#define SLOT_TIMEOUT            (90*HZ/1000)
 
-#define WATCHDOG_TIMEOUT        20*HZ       /* 20 sec */
+/* 
+ *  We set the query timeout to 100 ms and then expect the value to be 
+ *  multiplied with the number of slots to product the actual timeout value
+ */
+#define QUERY_TIMEOUT           (HZ/10)       
 
-typedef void (*TIMER_CALLBACK)(unsigned long);
+#define WATCHDOG_TIMEOUT        (20*HZ)       /* 20 sec */
 
-void irda_start_timer(struct timer_list *ptimer, int timeout, int data,
+typedef void (*TIMER_CALLBACK)(void *);
+
+void irda_start_timer(struct timer_list *ptimer, int timeout, void* data,
 		      TIMER_CALLBACK callback);
 
 inline void irlap_start_slot_timer(struct irlap_cb *self, int timeout);
@@ -67,16 +75,13 @@
 inline void irlap_start_wd_timer(struct irlap_cb *self, int timeout);
 inline void irlap_start_backoff_timer(struct irlap_cb *self, int timeout);
 
-inline void irda_device_start_mbusy_timer(struct irda_device *self);
+void irlap_start_mbusy_timer(struct irlap_cb *);
 
 struct lsap_cb;
 struct lap_cb;
 inline void irlmp_start_watchdog_timer(struct lsap_cb *, int timeout);
 inline void irlmp_start_discovery_timer(struct irlmp_cb *, int timeout);
 inline void irlmp_start_idle_timer(struct lap_cb *, int timeout);
-
-struct irobex_cb;
-inline void irobex_start_watchdog_timer(struct irobex_cb *, int timeout);
 
 #endif
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/toshoboe.h linux.15p9/include/net/irda/toshoboe.h
--- linux.vanilla/include/net/irda/toshoboe.h	Sat Aug 14 02:26:52 1999
+++ linux.15p9/include/net/irda/toshoboe.h	Tue Jan 18 01:08:18 2000
@@ -8,7 +8,7 @@
  * Author:        James McKenzie <james@fishsoup.dhs.org>
  * Created at:    Sat May 8  12:35:27 1999
  * 
- *     Copyright (c) 1999 James McKenzie, All Rights Reserved.
+ *     Copyright (c) 1999-2000 James McKenzie, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -23,16 +23,6 @@
  *
  ********************************************************************/
 
-/*
- * $Log: toshoboe.h,v $
- * Revision 1.2  1999/05/09 01:43:08  root
- * *** empty log message ***
- *
- * Revision 1.1  1999/05/09 01:25:58  root
- * Initial revision
- *
- */
-
 #ifndef TOSHOBOE_H
 #define TOSHOBOE_H
 
@@ -148,7 +138,17 @@
 
 struct toshoboe_cb
   {
-    struct irda_device idev;    /*IRDA device */
+    struct device *netdev;      /* Yes! we are some kind of netdevice */
+    struct net_device_stats stats;
+
+    struct irlap_cb    *irlap;  /* The link layer we are binded to */
+    struct qos_info     qos;    /* QoS capabilities for this device */
+
+    chipio_t io;                /* IrDA controller information */
+
+    __u32 flags;                /* Interface flags */
+    __u32 new_speed;
+
     struct pci_dev *pdev;       /*PCI device */
     int base;                   /*IO base */
     int txpending;              /*how many tx's are pending */
@@ -157,6 +157,8 @@
     struct OboeTaskFile *taskfile;  /*The taskfile   */
     void *xmit_bufs[TX_SLOTS];  /*The buffers   */
     void *recv_bufs[RX_SLOTS];
+    int open;
+    int stopped;		/*Stopped by some or other APM stuff*/
   };
 
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/uircc.h linux.15p9/include/net/irda/uircc.h
--- linux.vanilla/include/net/irda/uircc.h	Sat Aug 14 02:25:46 1999
+++ linux.15p9/include/net/irda/uircc.h	Thu Jan  1 01:00:00 1970
@@ -1,123 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      uircc.h
- * Version:       0.1
- * Description:   Driver for the Sharp Universal Infrared 
- *                Communications Controller (UIRCC)
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Sat Dec 26 11:00:49 1998
- * Modified at:   Thu Mar 11 01:37:20 1999
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
- *      
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
- *     the License, or (at your option) any later version.
- *  
- *     Neither Dag Brattli nor University of Tromsř admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
- *     
- ********************************************************************/
-
-#ifndef UIRCC_H
-#define UIRCC_H
-
-/* Control registers (write only) */
-#define UIRCC_CR0           0x00 /* Control register 0 */
-#define UIRCC_CR0_XMIT_RST  0x20 /* Transmit reset */
-#define UIRCC_CR0_RECV_RST  0x10 /* Receive reset */
-#define UIRCC_CR0_TMR_RST   0x08 /* Timer reset */
-#define UIRCC_CR0_SYS_RST   0x04 /* System reset */
-#define UIRCC_CR0_CARR_RST  0x02 /* Carrier latch reset */
-#define UIRCC_CR0_CNT_SWT   0x01 /* Transmit/receive length counter reset */
-
-#define UIRCC_CR1           0x01 /* Transmit/receive mode setting register */
-#define UIRCC_CR1_RX_DMA    0x80 /* Rx DMA mode */
-#define UIRCC_CR1_TX_DMA    0x20 /* Tx DMA mode */
-#define UIRCC_CR1_DMA_BRST  0x10 /* DMA burst mode */
-#define UIRCC_CR1_MUST_SET  0x0c /* Must be set */
-
-#define UIRCC_CR2           0x02 /* Interrupt mask register */
-#define UIRCC_CR2_RECV_OVR  0x40 /* Receive overrun error */
-#define UIRCC_CR2_RECV_FRM  0x20 /* Receive frame error */
-#define UIRCC_CR2_RECV_END  0x10 /* Receive end */
-#define UIRCC_CR2_TMR_OUT   0x08 /* Timer time-out */
-#define UIRCC_CR2_XMIT_UNR  0x04 /* Transmit under-run error */
-#define UIRCC_CR2_XMIT_END  0x01 /* Transmit end */
-#define UIRCC_CR2_RECV_MASK 0x70
-#define UIRCC_CR2_XMIT_MASK 0x05
-
-#define UIRCC_CR3           0x03 /* Transmit/receive control */
-#define UIRCC_CR3_XMIT_EN   0x80 /* Transmit enable */
-#define UIRCC_CR3_TX_CRC_EN 0x40 /* Transmit UIRCC_CRC enable */
-#define UIRCC_CR3_RECV_EN   0x20 /* Receive enable */
-#define UIRCC_CR3_RX_CRC_EN 0x10 /* Receive CRC enable */
-#define UIRCC_CR3_ADDR_CMP  0x08 /* Address comparison enable */
-#define UIRCC_CR3_MCAST_EN  0x04 /* Multicast enable */
-
-#define UIRCC_CR4           0x04 /* Transmit data length low byte */
-#define UIRCC_CR5           0x05 /* Transmit data length high byte */
-#define UIRCC_CR6           0x06 /* Transmit data writing low byte */
-#define UIRCC_CR7           0x07 /* Transmit data writing high byte */
-
-#define UIRCC_CR8           0x08 /* Self pole address */
-
-#define UIRCC_CR9           0x09 /* System control 1 */
-
-#define UIRCC_CR10          0x0a /* Modem selection */
-#define UIRCC_CR10_SIR      0x22 /* Set SIR mode */
-#define UIRCC_CR10_FIR      0x88 /* Set FIR mode */
-
-#define UIRCC_CR11          0x0b /* System control 2 (same as SR11) */
-#define UIRCC_CR11_TMR_EN   0x08
-
-#define UIRCC_CR12          0x0c /* Timer counter initial value (low byte) */
-#define UIRCC_CR13          0x0d /* Timer counter initial value (high byte) */
-#define UIRCC_CR15          0x0f
-
-/* Status registers (read only) */
-#define UIRCC_SR0           0x00 /* Transmit/receive status register */
-#define UIRCC_SR0_RX_RDY    0x80 /* Received data ready */
-#define UIRCC_SR0_RX_OVR    0x40 /* Receive overrun error */
-#define UIRCC_SR0_RX_CRCFRM 0x20 /* Receive CRC or framing error */
-
-#define UIRCC_SR2           0x02 /* Interrupt mask status */
-
-#define UIRCC_SR3           0x03 /* Interrupt factor register */
-#define UIRCC_SR3_RX_OVR_ER 0x40 /* Receive overrun error */
-#define UIRCC_SR3_RX_FRM_ER 0x20 /* Receive frameing error */
-#define UIRCC_SR3_RX_EOF    0x10 /* Receive end of frame */
-#define UIRCC_SR3_TMR_OUT   0x08 /* Timer timeout */
-#define UIRCC_SR3_TXUR      0x04 /* Transmit underrun */
-#define UIRCC_SR3_TX_DONE   0x01 /* Transmit all sent */
-
-#define UIRCC_SR4           0x04 /* TX/RX data length counter low byte */
-#define UIRCC_SR5           0x05 /* TX/RX data length counter high byte */
-
-#define UIRCC_SR8           0x08 /* Chip version */
-
-#define UIRCC_SR9           0x09 /* System status 1 */
-
-#define UIRCC_SR10          0x0a /* Modem select status */
-#define UIRCC_SR11          0x0b
-#define UIRCC_SR12          0x0c /* Timer counter status (low byte) */
-#define UIRCC_SR13          0x0d /* Timer counter status (high byte) */
-#define UIRCC_SR15          0x0f
-
-/* Private data for each instance */
-struct uircc_cb {
-	struct irda_device idev;
-	
-	__u8 cr3;                 /* Copy of register sr3 */
-};
-
-#define CR3_SET
-
-#endif
-
-
-
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/w83977af.h linux.15p9/include/net/irda/w83977af.h
--- linux.vanilla/include/net/irda/w83977af.h	Thu Dec 17 17:01:03 1998
+++ linux.15p9/include/net/irda/w83977af.h	Tue Jan 18 01:08:18 2000
@@ -1,54 +1,53 @@
 #ifndef W83977AF_H
 #define W83977AF_H
 
-#define W977_EFER 0x370
-#define W977_EFIR 0x370
-#define W977_EFDR 0x371
+#define W977_EFIO_BASE 0x370
+#define W977_EFIO2_BASE 0x3f0
 #define W977_DEVICE_IR 0x06
 
 
 /*
  * Enter extended function mode
  */
-static inline void w977_efm_enter(void)
+static inline void w977_efm_enter(unsigned int efio)
 {
-        outb(0x87, W977_EFER);
-        outb(0x87, W977_EFER);
+        outb(0x87, efio);
+        outb(0x87, efio);
 }
 
 /*
  * Select a device to configure 
  */
 
-static inline void w977_select_device(__u8 devnum)
+static inline void w977_select_device(__u8 devnum, unsigned int efio)
 {
-	outb(0x07, W977_EFIR);
-	outb(devnum, W977_EFDR);
+	outb(0x07, efio);
+	outb(devnum, efio+1);
 } 
 
 /* 
  * Write a byte to a register
  */
-static inline void w977_write_reg(__u8 reg, __u8 value)
+static inline void w977_write_reg(__u8 reg, __u8 value, unsigned int efio)
 {
-	outb(reg, W977_EFIR);
-	outb(value, W977_EFDR);
+	outb(reg, efio);
+	outb(value, efio+1);
 }
 
 /*
  * read a byte from a register
  */
-static inline __u8 w977_read_reg(__u8 reg)
+static inline __u8 w977_read_reg(__u8 reg, unsigned int efio)
 {
-	outb(reg, W977_EFIR);
-	return inb(W977_EFDR);
+	outb(reg, efio);
+	return inb(efio+1);
 }
 
 /*
  * Exit extended function mode
  */
-static inline void w977_efm_exit(void)
+static inline void w977_efm_exit(unsigned int efio)
 {
-	outb(0xAA, W977_EFER);
+	outb(0xAA, efio);
 }
 #endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/w83977af_ir.h linux.15p9/include/net/irda/w83977af_ir.h
--- linux.vanilla/include/net/irda/w83977af_ir.h	Sat Aug 14 02:26:52 1999
+++ linux.15p9/include/net/irda/w83977af_ir.h	Wed Jan 26 23:58:34 2000
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Paul VanderSpek
  * Created at:    Thu Nov 19 13:55:34 1998
- * Modified at:   Mon May  3 12:07:25 1999
+ * Modified at:   Tue Jan 11 13:08:19 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1998-2000 Dag Brattli, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -170,12 +170,23 @@
 	int tx_buff_offsets[10]; /* Offsets between frames in tx_buff */
 	int tx_len;          /* Number of frames in tx_buff */
 
-	struct irda_device idev;
+	struct device *netdev; /* Yes! we are some kind of netdevice */
+	struct net_device_stats stats;
+	
+	struct irlap_cb    *irlap; /* The link layer we are binded to */
+	struct qos_info     qos;   /* QoS capabilities for this device */
+	
+	chipio_t io;               /* IrDA controller information */
+	iobuff_t tx_buff;          /* Transmit buffer */
+	iobuff_t rx_buff;          /* Receive buffer */
+	
+	__u32 flags;               /* Interface flags */
+	__u32 new_speed;
 };
 
 static inline void switch_bank( int iobase, int set)
 {
-	outb( set, iobase+SSR);
+	outb(set, iobase+SSR);
 }
 
 #endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/irda/wrapper.h linux.15p9/include/net/irda/wrapper.h
--- linux.vanilla/include/net/irda/wrapper.h	Sat Aug 14 02:26:52 1999
+++ linux.15p9/include/net/irda/wrapper.h	Mon Feb  7 13:23:13 2000
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Mon May  3 09:02:36 1999
+ * Modified at:   Tue Jan 11 12:37:29 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
+ *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>, 
  *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
@@ -28,6 +28,7 @@
 
 #include <linux/types.h>
 #include <linux/skbuff.h>
+#include <linux/netdevice.h>
 
 #include <net/irda/irda_device.h>
 
@@ -51,6 +52,9 @@
 
 /* Proto definitions */
 int async_wrap_skb(struct sk_buff *skb, __u8 *tx_buff, int buffsize);
-inline void async_unwrap_char(struct irda_device *idev, __u8 byte);
+void async_bump(struct device *dev, struct net_device_stats *stats,
+		__u8 *buf, int len);
+void async_unwrap_char(struct device *dev, struct net_device_stats *stats,
+		       iobuff_t *buf, __u8 byte);
 
 #endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/include/net/tcp.h linux.15p9/include/net/tcp.h
--- linux.vanilla/include/net/tcp.h	Tue Jan  4 21:19:03 2000
+++ linux.15p9/include/net/tcp.h	Mon Feb  7 13:10:43 2000
@@ -777,10 +777,16 @@
 	return tp->packets_out - tp->fackets_out + tp->retrans_out;
 }
 
+/* Is SKB at the tail of the write queue? */
+static __inline__ int tcp_skb_is_last(struct sock *sk, struct sk_buff *skb)
+{
+	return (skb->next == (struct sk_buff*)&sk->write_queue);
+}
+
 /* This checks if the data bearing packet SKB (usually tp->send_head)
  * should be put on the wire right now.
  */
-static __inline__ int tcp_snd_test(struct sock *sk, struct sk_buff *skb)
+static __inline__ int tcp_snd_test(struct sock *sk, struct sk_buff *skb, int tail)
 {
 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 	int nagle_check = 1;
@@ -796,20 +802,26 @@
 	 *	c) We are retransmiting [Nagle]
 	 *	d) We have too many packets 'in flight'
 	 *
-	 * 	Don't use the nagle rule for urgent data (or
-	 *	for the final FIN -DaveM).
+	 * 	FIN overrides nagle, even for the TCP_CORK
+	 *	case. -DaveM
+	 *
+	 *	Also, Nagle rule does not apply to frames, which
+	 *	sit in the middle of queue (they have no chances
+	 *	to get new data) and if room at tail of skb is
+	 *	not enough to save something seriously (<32 for now).
 	 */
-	if ((sk->nonagle == 2 && (skb->len < tp->mss_cache)) ||
-	    (!sk->nonagle &&
-	     skb->len < (tp->mss_cache >> 1) &&
-	     tp->packets_out &&
-	     !(TCP_SKB_CB(skb)->flags & (TCPCB_FLAG_URG|TCPCB_FLAG_FIN))))
-		nagle_check = 0;
+	if (!(TCP_SKB_CB(skb)->flags & (TCPCB_FLAG_URG|TCPCB_FLAG_FIN))) {
+		if ((sk->nonagle == 2 && (skb->len < tp->mss_cache)) ||
+		    (!sk->nonagle &&
+		     skb->len < (tp->mss_cache >> 1) &&
+		     tp->packets_out))
+			nagle_check = 0;
+	}
 
 	/* Don't be strict about the congestion window for the
 	 * final FIN frame.  -DaveM
 	 */
-	return (nagle_check &&
+	return ((!tail || nagle_check || skb_tailroom(skb) < 32) &&
 		((tcp_packets_in_flight(tp) < tp->snd_cwnd) ||
 		 (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN)) &&
 		!after(TCP_SKB_CB(skb)->end_seq, tp->snd_una + tp->snd_wnd) &&
@@ -822,8 +834,10 @@
  */
 static __inline__ void tcp_push_pending_frames(struct sock *sk, struct tcp_opt *tp)
 {
-	if(tp->send_head) {
-		if(tcp_snd_test(sk, tp->send_head))
+	struct sk_buff *skb = tp->send_head;
+
+	if(skb) {
+		if(tcp_snd_test(sk, skb, tcp_skb_is_last(sk, skb)))
 			tcp_write_xmit(sk);
 		else if(tp->packets_out == 0 && !tp->pending) {
 			/* We held off on this in tcp_send_skb() */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/init/main.c linux.15p9/init/main.c
--- linux.vanilla/init/main.c	Tue Jan  4 21:19:03 2000
+++ linux.15p9/init/main.c	Thu Feb 17 13:42:31 2000
@@ -75,8 +75,7 @@
 extern int kswapd(void *);
 extern int kpiod(void *);
 extern void kswapd_setup(void);
-
-extern void init_IRQ(void);
+extern unsigned long init_IRQ( unsigned long);
 extern void init_modules(void);
 extern long console_init(long, long);
 extern void sock_init(void);
@@ -111,6 +110,9 @@
 #ifdef CONFIG_PRINTER
 extern void lp_setup(char *str, int *ints);
 #endif
+#ifdef CONFIG_VIDEO_CPIA_PP
+extern void cpia_pp_setup(char *str, int *ints);
+#endif
 #ifdef CONFIG_JOY_AMIGA
 extern void js_am_setup(char *str, int *ints);
 #endif
@@ -151,6 +153,12 @@
 #ifdef CONFIG_CTC  
 extern void ctc_setup(char *str, int *ints);
 #endif
+#ifdef CONFIG_IUCV
+extern void iucv_setup(char *str, int *ints);
+#endif
+#ifdef CONFIG_IUCV
+extern void iucv_setup(char *str, int *ints);
+#endif
 #ifdef CONFIG_ARCNET_COM90xxIO
 extern void com90io_setup(char *str, int *ints);
 #endif
@@ -182,6 +190,12 @@
 #ifdef CONFIG_PARIDE_PCD
 extern void pcd_setup(char *str, int *ints);
 #endif
+#ifdef CONFIG_3215
+extern void con3215_setup(char *str, int *ints);
+#endif
+#ifdef CONFIG_3215
+extern void con3215_setup(char *str, int *ints);
+#endif
 #ifdef CONFIG_MDISK
 extern void mdisk_setup(char *str, int *ints);
 #endif
@@ -486,6 +500,24 @@
 	{ "rd/c0d14p",0x3070 },
 	{ "rd/c0d15p",0x3078 },
 #endif
+#if defined(CONFIG_BLK_CPQ_DA) || defined(CONFIG_BLK_CPQ_DA_MODULE)
+	{ "ida/c0d0p",0x4800 },
+	{ "ida/c0d1p",0x4810 },
+	{ "ida/c0d2p",0x4820 },
+	{ "ida/c0d3p",0x4830 },
+	{ "ida/c0d4p",0x4840 },
+	{ "ida/c0d5p",0x4850 },
+	{ "ida/c0d6p",0x4860 },
+	{ "ida/c0d7p",0x4870 },
+	{ "ida/c0d8p",0x4880 },
+	{ "ida/c0d9p",0x4890 },
+	{ "ida/c0d10p",0x48A0 },
+	{ "ida/c0d11p",0x48B0 },
+	{ "ida/c0d12p",0x48C0 },
+	{ "ida/c0d13p",0x48D0 },
+	{ "ida/c0d14p",0x48E0 },
+	{ "ida/c0d15p",0x48F0 },
+#endif
 #ifdef CONFIG_ATARI_ACSI
 	{ "ada",     0x1c00 },
 	{ "adb",     0x1c10 },
@@ -551,24 +583,24 @@
 	{ "ddv", DDV_MAJOR << 8},
 #endif
 #ifdef CONFIG_MDISK
-        { "mnd0", (MDISK_MAJOR << MINORBITS)},
-        { "mnd1", (MDISK_MAJOR << MINORBITS) + 1},
-        { "mnd2", (MDISK_MAJOR << MINORBITS) + 2},
-        { "mnd3", (MDISK_MAJOR << MINORBITS) + 3},
-        { "mnd4", (MDISK_MAJOR << MINORBITS) + 4},
-        { "mnd5", (MDISK_MAJOR << MINORBITS) + 5},
-        { "mnd6", (MDISK_MAJOR << MINORBITS) + 6},
-        { "mnd7", (MDISK_MAJOR << MINORBITS) + 7},
+        { "mnda", (MDISK_MAJOR << MINORBITS)},
+        { "mndb", (MDISK_MAJOR << MINORBITS) + 1},
+        { "mndc", (MDISK_MAJOR << MINORBITS) + 2},
+        { "mndd", (MDISK_MAJOR << MINORBITS) + 3},
+        { "mnde", (MDISK_MAJOR << MINORBITS) + 4},
+        { "mndf", (MDISK_MAJOR << MINORBITS) + 5},
+        { "mndg", (MDISK_MAJOR << MINORBITS) + 6},
+        { "mndh", (MDISK_MAJOR << MINORBITS) + 7},
 #endif
 #ifdef CONFIG_DASD
-       { "dasd0", (DASD_MAJOR << MINORBITS) },
-       { "dasd1", (DASD_MAJOR << MINORBITS) + (1 << 2) },
-       { "dasd2", (DASD_MAJOR << MINORBITS) + (2 << 2) },
-       { "dasd3", (DASD_MAJOR << MINORBITS) + (3 << 2) },
-       { "dasd4", (DASD_MAJOR << MINORBITS) + (4 << 2) },
-       { "dasd5", (DASD_MAJOR << MINORBITS) + (5 << 2) },
-       { "dasd6", (DASD_MAJOR << MINORBITS) + (6 << 2) },
-       { "dasd7", (DASD_MAJOR << MINORBITS) + (7 << 2) },
+       { "dasda", (DASD_MAJOR << MINORBITS) },
+       { "dasdb", (DASD_MAJOR << MINORBITS) + (1 << 2) },
+       { "dasdc", (DASD_MAJOR << MINORBITS) + (2 << 2) },
+       { "dasdd", (DASD_MAJOR << MINORBITS) + (3 << 2) },
+       { "dasde", (DASD_MAJOR << MINORBITS) + (4 << 2) },
+       { "dasdf", (DASD_MAJOR << MINORBITS) + (5 << 2) },
+       { "dasdg", (DASD_MAJOR << MINORBITS) + (6 << 2) },
+       { "dasdh", (DASD_MAJOR << MINORBITS) + (7 << 2) },
 #endif
 	{ NULL, 0 }
 };
@@ -624,6 +656,10 @@
 	{ "noapic", ioapic_setup },
 	{ "pirq=", ioapic_pirq_setup },
 #endif
+#ifdef CONFIG_IUCV
+        { "iucv=", iucv_setup } ,
+#endif
+
 #endif
 #ifdef CONFIG_BLK_DEV_RAM
 	{ "ramdisk_start=", ramdisk_start_setup },
@@ -638,6 +674,10 @@
 #ifdef CONFIG_CTC
         { "ctc=", ctc_setup } ,
 #endif
+#ifdef CONFIG_IUCV
+        { "iucv=", iucv_setup } ,
+#endif
+
 #endif
 
 #ifdef CONFIG_FB
@@ -683,6 +723,9 @@
 #ifdef CONFIG_PRINTER
         { "lp=", lp_setup },
 #endif
+#ifdef CONFIG_VIDEO_CPIA_PP
+        { "cpia_pp=", cpia_pp_setup },
+#endif
 #ifdef CONFIG_JOY_AMIGA
 	{ "js_am=", js_am_setup },
 #endif
@@ -981,6 +1024,12 @@
 #ifdef CONFIG_APM
 	{ "apm=", apm_setup },
 #endif
+#ifdef CONFIG_3215
+	{ "condev=", con3215_setup },
+#endif
+#ifdef CONFIG_3215
+	{ "condev=", con3215_setup },
+#endif
 #ifdef CONFIG_MDISK
         { "mdisk=", mdisk_setup },
 #endif
@@ -1227,7 +1276,7 @@
 	setup_arch(&command_line, &memory_start, &memory_end);
 	memory_start = paging_init(memory_start,memory_end);
 	trap_init();
-	init_IRQ();
+        memory_start = init_IRQ( memory_start );
 	sched_init();
 	time_init();
 	parse_options(command_line);
@@ -1418,6 +1467,10 @@
 
 	/* .. filesystems .. */
 	filesystem_setup();
+
+#ifdef CONFIG_IRDA
+	irda_device_init(); /* Must be done after protocol initialization */
+#endif
 
 	/* Mount the root filesystem.. */
 	mount_root();
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/ipc/shm.c linux.15p9/ipc/shm.c
--- linux.vanilla/ipc/shm.c	Tue Jan  4 21:19:03 2000
+++ linux.15p9/ipc/shm.c	Thu Feb 17 14:27:20 2000
@@ -79,6 +79,7 @@
 	struct shmid_kernel *shp;
 	int numpages = (size + PAGE_SIZE -1) >> PAGE_SHIFT;
 	int id, i;
+	pte_t tmp_pte;
 
 	if (size < SHMMIN)
 		return -EINVAL;
@@ -107,7 +108,11 @@
 		return -ENOMEM;
 	}
 
-	for (i = 0; i < numpages; shp->shm_pages[i++] = 0);
+	pte_clear(&tmp_pte);
+
+	for (i = 0; i < numpages; i++)
+		shp->shm_pages[i] = pte_val(tmp_pte);
+
 	shm_tot += numpages;
 	shp->u.shm_perm.key = key;
 	shp->u.shm_perm.mode = (shmflg & S_IRWXUGO);
@@ -630,11 +635,12 @@
 		printk ("shm_nopage: id=%d invalid. Race.\n", id);
 		return 0;
 	}
+#endif
+	/* This can occur on a remap */
+	
 	if (idx >= shp->shm_npages) {
-		printk ("shm_nopage : too large page index. id=%d\n", id);
 		return 0;
 	}
-#endif
 
 	pte = __pte(shp->shm_pages[idx]);
 	if (!pte_present(pte)) {
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/kernel/ksyms.c linux.15p9/kernel/ksyms.c
--- linux.vanilla/kernel/ksyms.c	Tue Jan  4 21:19:03 2000
+++ linux.15p9/kernel/ksyms.c	Thu Feb 17 13:38:52 2000
@@ -424,3 +424,4 @@
 
 /* init task, for moving kthread roots - ought to export a function ?? */
 EXPORT_SYMBOL(init_task_union);
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/kernel/module.c linux.15p9/kernel/module.c
--- linux.vanilla/kernel/module.c	Sun Dec 27 18:41:41 1998
+++ linux.15p9/kernel/module.c	Fri Jan 21 18:16:03 2000
@@ -13,6 +13,7 @@
  * 0.99.14 version by Jon Tombs <jon@gtex02.us.es>,
  * Heavily modified by Bjorn Ekwall <bj0rn@blox.se> May 1994 (C)
  * Rewritten by Richard Henderson <rth@tamu.edu> Dec 1996
+ * Add MOD_INITIALIZING Keith Owens <kaos@ocs.com.au> Nov 1999
  *
  * This source is covered by the GNU GPL, the same as all kernel sources.
  */
@@ -329,16 +330,18 @@
 	put_mod_name(name);
 
 	/* Initialize the module.  */
+	mod->flags |= MOD_INITIALIZING;
 	atomic_set(&mod->uc.usecount,1);
 	if (mod->init && mod->init() != 0) {
 		atomic_set(&mod->uc.usecount,0);
+		mod->flags &= ~MOD_INITIALIZING;
 		error = -EBUSY;
 		goto err0;
 	}
 	atomic_dec(&mod->uc.usecount);
 
 	/* And set it running.  */
-	mod->flags |= MOD_RUNNING;
+	mod->flags = (mod->flags | MOD_RUNNING) & ~MOD_INITIALIZING;
 	error = 0;
 	goto err0;
 
@@ -462,7 +465,7 @@
 
 	if (mod == &kernel_module)
 		return -EINVAL;
-	if ((mod->flags & (MOD_RUNNING | MOD_DELETED)) != MOD_RUNNING)
+	if (!MOD_CAN_QUERY(mod))
 		if (put_user(0, ret))
 			return -EFAULT;
 		else
@@ -506,7 +509,7 @@
 
 	if (mod == &kernel_module)
 		return -EINVAL;
-	if ((mod->flags & (MOD_RUNNING | MOD_DELETED)) != MOD_RUNNING)
+	if (!MOD_CAN_QUERY(mod))
 		if (put_user(0, ret))
 			return -EFAULT;
 		else
@@ -550,7 +553,7 @@
 	char *strings;
 	unsigned long *vals;
 
-	if ((mod->flags & (MOD_RUNNING | MOD_DELETED)) != MOD_RUNNING)
+	if (!MOD_CAN_QUERY(mod))
 		if (put_user(0, ret))
 			return -EFAULT;
 		else
@@ -716,7 +719,7 @@
 		struct module_symbol *msym;
 		unsigned int j;
 
-		if ((mod->flags & (MOD_RUNNING|MOD_DELETED)) != MOD_RUNNING)
+		if (!MOD_CAN_QUERY(mod))
 			continue;
 
 		/* magic: write module info as a pseudo symbol */
@@ -865,7 +868,10 @@
 				safe_copy_cstr(" (autoclean)");
 			if (!(mod->flags & MOD_USED_ONCE))
 				safe_copy_cstr(" (unused)");
-		} else
+		}
+		else if (mod->flags & MOD_INITIALIZING)
+			safe_copy_cstr(" (initializing)");
+		else
 			safe_copy_cstr(" (uninitialized)");
 
 		if ((ref = mod->refs) != NULL) {
@@ -909,7 +915,7 @@
 		unsigned i;
 		struct module_symbol *sym;
 
-		if (!(mod->flags & MOD_RUNNING) || (mod->flags & MOD_DELETED))
+		if (!MOD_CAN_QUERY(mod))
 			continue;
 
 		for (i = mod->nsyms, sym = mod->syms; i > 0; --i, ++sym) {
@@ -957,7 +963,7 @@
 
 	for (mp = module_list; mp; mp = mp->next) {
 		if (((modname == NULL) || (strcmp(mp->name, modname) == 0)) &&
-			(mp->flags & (MOD_RUNNING | MOD_DELETED)) == MOD_RUNNING &&
+			MOD_CAN_QUERY(mp) &&
 			(mp->nsyms > 0)) {
 			for (i = mp->nsyms, sym = mp->syms;
 				i > 0; --i, ++sym) {
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/kernel/panic.c linux.15p9/kernel/panic.c
--- linux.vanilla/kernel/panic.c	Tue Jan  4 21:19:03 2000
+++ linux.15p9/kernel/panic.c	Thu Feb 17 13:39:35 2000
@@ -16,10 +16,6 @@
 #include <linux/sysrq.h>
 #include <linux/interrupt.h>
 
-#ifdef __alpha__
-#include <asm/machvec.h>
-#endif
-
 asmlinkage void sys_sync(void);	/* it's really int */
 extern void unblank_console(void);
 extern int C_A_D;
@@ -38,6 +34,9 @@
 {
 	static char buf[1024];
 	va_list args;
+#ifdef CONFIG_ARCH_S390
+        unsigned long caller = (unsigned long) __builtin_return_address(0);
+#endif
 
 	va_start(args, fmt);
 	vsprintf(buf, fmt, args);
@@ -81,12 +80,8 @@
 		printk("Press L1-A to return to the boot prom\n");
 	}
 #endif
-#ifdef __alpha__
-	if (alpha_using_srm)
-		halt();
-#endif
 #ifdef CONFIG_ARCH_S390
-        disabled_wait(0x1234);
+        disabled_wait(caller);
 #endif
 	sti();
 	for(;;) {
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/kernel/signal.c linux.15p9/kernel/signal.c
--- linux.vanilla/kernel/signal.c	Tue Jan  4 21:19:03 2000
+++ linux.15p9/kernel/signal.c	Thu Jan 13 22:35:46 2000
@@ -740,11 +740,11 @@
 
 	if (copy_from_user(&these, uthese, sizeof(these)))
 		return -EFAULT;
-	else {
-		/* Invert the set of allowed signals to get those we
-		   want to block.  */
-		signotset(&these);
-	}
+	/* Invert the set of allowed signals to get those we
+	   want to block.  */
+
+	sigdelsetmask (&these, sigmask(SIGKILL)|sigmask(SIGSTOP));
+	signotset(&these);
 
 	if (uts) {
 		if (copy_from_user(&ts, uts, sizeof(ts)))
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/mm/page_alloc.c linux.15p9/mm/page_alloc.c
--- linux.vanilla/mm/page_alloc.c	Tue Jan  4 21:19:03 2000
+++ linux.15p9/mm/page_alloc.c	Wed Feb  9 16:10:54 2000
@@ -20,6 +20,7 @@
 
 int nr_swap_pages = 0;
 int nr_free_pages = 0;
+extern struct wait_queue * kswapd_wait;
 
 /*
  * Free area management
@@ -184,8 +185,6 @@
 	atomic_set(&map->count, 1); \
 } while (0)
 
-int low_on_memory = 0;
-
 unsigned long __get_free_pages(int gfp_mask, unsigned long order)
 {
 	unsigned long flags;
@@ -211,22 +210,30 @@
 	 */
 	if (!(current->flags & PF_MEMALLOC)) {
 		int freed;
+#ifdef SLEEP_MEMORY_DEBUGGING
+		if (current->state != TASK_RUNNING && (gfp_mask & __GFP_WAIT)) {
+			printk("gfp called by non-running (%d) task from %p!\n",
+				current->state, __builtin_return_address(0));
+			/* if we're not running, we can't sleep */
+			gfp_mask &= ~__GFP_WAIT;
+		}
+#endif		
 
-		if (nr_free_pages > freepages.min) {
-			if (!low_on_memory)
-				goto ok_to_allocate;
-			if (nr_free_pages >= freepages.high) {
-				low_on_memory = 0;
-				goto ok_to_allocate;
-			}
+		if (nr_free_pages <= freepages.low) {
+			wake_up_interruptible(&kswapd_wait);
 		}
+		if (nr_free_pages > freepages.min)
+			goto ok_to_allocate;
 
-		low_on_memory = 1;
+		/* Danger, danger! Do something or fail */
 		current->flags |= PF_MEMALLOC;
 		freed = try_to_free_pages(gfp_mask);
 		current->flags &= ~PF_MEMALLOC;
 
-		if (!freed && !(gfp_mask & (__GFP_MED | __GFP_HIGH)))
+		if ((gfp_mask & __GFP_MED) && nr_free_pages > freepages.min / 2)
+			goto ok_to_allocate;
+
+		if (!freed && !(gfp_mask & __GFP_HIGH))
 			goto nopage;
 	}
 ok_to_allocate:
@@ -236,16 +243,6 @@
 		RMQUEUE_TYPE(order, 0);
 	RMQUEUE_TYPE(order, 1);
 	spin_unlock_irqrestore(&page_alloc_lock, flags);
-
-	/*
-	 * If we can schedule, do so, and make sure to yield.
-	 * We may be a real-time process, and if kswapd is
-	 * waiting for us we need to allow it to run a bit.
-	 */
-	if (gfp_mask & __GFP_WAIT) {
-		current->policy |= SCHED_YIELD;
-		schedule();
-	}
 
 nopage:
 	return 0;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/mm/vmscan.c linux.15p9/mm/vmscan.c
--- linux.vanilla/mm/vmscan.c	Tue Jan  4 21:19:03 2000
+++ linux.15p9/mm/vmscan.c	Wed Feb 16 20:11:07 2000
@@ -64,6 +64,14 @@
 		return 0;
 
 	/*
+	 * By setting this bit shrink_mmap() will do
+	 * second-chance page replacement, only do this
+	 * when we are the only (non-pagecache) user.
+	 */
+	if (atomic_read(&page_map->count) <= 2)
+		set_bit(PG_referenced, &page_map->flags);
+
+	/*
 	 * Is the page already in the swap cache? If so, then
 	 * we can just drop our reference to it without doing
 	 * any IO - it's already up-to-date on disk.
@@ -437,7 +445,7 @@
        printk ("Starting kswapd v%.*s\n", i, s);
 }
 
-static struct wait_queue * kswapd_wait = NULL;
+struct wait_queue * kswapd_wait = NULL;
 
 /*
  * The background pageout daemon, started as a kernel thread
@@ -485,41 +493,26 @@
 		 * the processes needing more memory will wake us
 		 * up on a more timely basis.
 		 */
-		interruptible_sleep_on_timeout(&kswapd_wait, HZ);
 		while (nr_free_pages < freepages.high)
 		{
-			if (do_try_to_free_pages(GFP_KSWAPD))
-			{
-				if (tsk->need_resched)
-					schedule();
-				continue;
-			}
-			tsk->state = TASK_INTERRUPTIBLE;
-			schedule_timeout(10*HZ);
+			if (!do_try_to_free_pages(GFP_KSWAPD))
+				break;
+			if (tsk->need_resched)
+				schedule();
 		}
+		run_task_queue(&tq_disk);
+		interruptible_sleep_on_timeout(&kswapd_wait, HZ);
 	}
 }
 
 /*
- * Called by non-kswapd processes when they want more
- * memory.
- *
- * In a perfect world, this should just wake up kswapd
- * and return. We don't actually want to swap stuff out
- * from user processes, because the locking issues are
- * nasty to the extreme (file write locks, and MM locking)
- *
- * One option might be to let kswapd do all the page-out
- * and VM page table scanning that needs locking, and this
- * process thread could do just the mmap shrink stage that
- * can be done by just dropping cached pages without having
- * any deadlock issues.
+ * Called by non-kswapd processes when kswapd really cannot
+ * keep up with the demand for free memory.
  */
 int try_to_free_pages(unsigned int gfp_mask)
 {
 	int retval = 1;
 
-	wake_up_interruptible(&kswapd_wait);
 	if (gfp_mask & __GFP_WAIT)
 		retval = do_try_to_free_pages(gfp_mask);
 	return retval;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/ax25/af_ax25.c linux.15p9/net/ax25/af_ax25.c
--- linux.vanilla/net/ax25/af_ax25.c	Tue Jan  4 21:19:03 2000
+++ linux.15p9/net/ax25/af_ax25.c	Wed Feb  9 15:48:24 2000
@@ -96,6 +96,7 @@
  *      AX.25 038       Matthias(DG2FEF)        Small fixes to the syscall interface to make kernel
  *                                              independent of AX25_MAX_DIGIS used by applications.
  *                      Tomi(OH2BNS)            Fixed ax25_getname().
+ *                      Tomi(OH2BNS)            recvmsg() returns source not dest in msg.
  */
 
 #include <linux/config.h>
@@ -1482,16 +1483,16 @@
 	if (msg->msg_namelen != 0) {
 		struct sockaddr_ax25 *sax = (struct sockaddr_ax25 *)msg->msg_name;
 		ax25_digi digi;
-		ax25_address dest;
+		ax25_address src;
 
-		ax25_addr_parse(skb->mac.raw+1, skb->data-skb->mac.raw-1, NULL, &dest, &digi, NULL, NULL);
+		ax25_addr_parse(skb->mac.raw+1, skb->data-skb->mac.raw-1, &src, NULL, &digi, NULL, NULL);
 
 		sax->sax25_family = AF_AX25;
 		/* We set this correctly, even though we may not let the
 		   application know the digi calls further down (because it
 		   did NOT ask to know them).  This could get political... **/
 		sax->sax25_ndigis = digi.ndigi;
-		sax->sax25_call   = dest;
+		sax->sax25_call   = src;
 
 		if (sax->sax25_ndigis != 0) {
 			int ct;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/core/dev.c linux.15p9/net/core/dev.c
--- linux.vanilla/net/core/dev.c	Tue Jan  4 21:19:03 2000
+++ linux.15p9/net/core/dev.c	Wed Jan 26 23:15:27 2000
@@ -784,6 +784,9 @@
 #else
 		netdev_dropping = 0;
 #endif
+		if (skb->dev->flags & IFF_SLAVE  &&  skb->dev->slave) {
+			skb->dev = skb->dev->slave;
+		}
 		skb_queue_tail(&backlog,skb);
 		mark_bh(NET_BH);
 		return;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/core/filter.c linux.15p9/net/core/filter.c
--- linux.vanilla/net/core/filter.c	Sat Aug 14 02:26:52 1999
+++ linux.15p9/net/core/filter.c	Tue Jan 18 00:58:15 2000
@@ -49,7 +49,7 @@
 	else if (k>=SKF_LL_OFF)
 		ptr = skb->mac.raw + k - SKF_LL_OFF;
 
-	if (ptr<skb->head && ptr < skb->tail)
+	if (ptr >= skb->head && ptr < skb->tail)
 		return ptr;
 	return NULL;
 }
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/ipv4/af_inet.c linux.15p9/net/ipv4/af_inet.c
--- linux.vanilla/net/ipv4/af_inet.c	Sat Aug 14 02:27:41 1999
+++ linux.15p9/net/ipv4/af_inet.c	Fri Jan 14 16:01:19 2000
@@ -5,7 +5,7 @@
  *
  *		PF_INET protocol family socket handler.
  *
- * Version:	$Id: af_inet.c,v 1.87.2.5 1999/08/08 08:43:10 davem Exp $
+ * Version:	$Id: af_inet.c,v 1.87.2.6 2000/01/13 04:28:16 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -309,6 +309,7 @@
 				((struct tcp_bind_bucket*)sk->prev)->fastreuse = 0;
 		}
 
+		sk->zapped = 0;
 		dst_release(xchg(&sk->dst_cache, NULL));
 		sk->prot->hash(sk);
 		sk->socket->flags |= SO_ACCEPTCON;
@@ -546,6 +547,7 @@
 	if (sk->prot->get_port(sk, snum) != 0)
 		return -EADDRINUSE;
 
+	sk->zapped = 0;
 	sk->sport = htons(sk->num);
 	sk->daddr = 0;
 	sk->dport = 0;
@@ -626,6 +628,7 @@
 		if (inet_autobind(sk) != 0)
 			return(-EAGAIN);
 
+		sk->zapped = 0;
 		err = sk->prot->connect(sk, uaddr, addr_len);
 		/* Note: there is a theoretical race here when an wake up
 		   occurred before inet_wait_for_connect is entered. In 2.3
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/ipv4/arp.c linux.15p9/net/ipv4/arp.c
--- linux.vanilla/net/ipv4/arp.c	Tue Jan  4 21:19:03 2000
+++ linux.15p9/net/ipv4/arp.c	Fri Jan 14 16:01:28 2000
@@ -1,6 +1,6 @@
 /* linux/net/inet/arp.c
  *
- * Version:	$Id: arp.c,v 1.77.2.4 1999/09/23 19:03:36 davem Exp $
+ * Version:	$Id: arp.c,v 1.77.2.5 1999/12/14 10:32:39 davem Exp $
  *
  * Copyright (C) 1994 by Florian  La Roche
  *
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/ipv4/devinet.c linux.15p9/net/ipv4/devinet.c
--- linux.vanilla/net/ipv4/devinet.c	Tue Jan  4 21:19:03 2000
+++ linux.15p9/net/ipv4/devinet.c	Fri Jan 14 16:01:28 2000
@@ -1,7 +1,7 @@
 /*
  *	NET3	IP device support routines.
  *
- *	Version: $Id: devinet.c,v 1.28.2.2 1999/08/07 10:56:18 davem Exp $
+ *	Version: $Id: devinet.c,v 1.28.2.3 1999/12/14 10:32:42 davem Exp $
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/ipv4/proc.c linux.15p9/net/ipv4/proc.c
--- linux.vanilla/net/ipv4/proc.c	Mon Feb  8 17:26:29 1999
+++ linux.15p9/net/ipv4/proc.c	Fri Jan 14 16:01:28 2000
@@ -7,7 +7,7 @@
  *		PROC file system.  It is mainly used for debugging and
  *		statistics.
  *
- * Version:	$Id: proc.c,v 1.34 1999/02/08 11:20:34 davem Exp $
+ * Version:	$Id: proc.c,v 1.34.2.1 2000/01/14 01:22:20 davem Exp $
  *
  * Authors:	Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de>
@@ -78,7 +78,7 @@
 {
 	unsigned long  dest, src;
 	unsigned short destp, srcp;
-	int timer_active, timer_active1, timer_active2;
+	int timer_active;
 	int tw_bucket = 0;
 	unsigned long timer_expires;
 	struct tcp_opt *tp = &sp->tp_pinfo.af_tcp;
@@ -105,27 +105,29 @@
 		int slot_dist;
 
 		tw_bucket	= 1;
-		timer_active1	= timer_active2 = 0;
 		timer_active	= 3;
 		slot_dist	= tw->death_slot;
-		if(slot_dist > tcp_tw_death_row_slot)
-			slot_dist = (TCP_TWKILL_SLOTS - slot_dist) + tcp_tw_death_row_slot;
+		if(slot_dist >= tcp_tw_death_row_slot)
+			slot_dist = slot_dist - tcp_tw_death_row_slot;
 		else
-			slot_dist = tcp_tw_death_row_slot - slot_dist;
+			slot_dist = (TCP_TWKILL_SLOTS - tcp_tw_death_row_slot) + slot_dist;
 		timer_expires	= jiffies + (slot_dist * TCP_TWKILL_PERIOD);
 	} else {
-		timer_active1 = del_timer(&tp->retransmit_timer);
-		timer_active2 = del_timer(&sp->timer);
-		if (!timer_active1) tp->retransmit_timer.expires=0;
-		if (!timer_active2) sp->timer.expires=0;
 		timer_active	= 0;
 		timer_expires	= (unsigned) -1;
 	}
-	if (timer_active1 && tp->retransmit_timer.expires < timer_expires) {
+	if (tp->retransmit_timer.prev != NULL &&
+	    tp->retransmit_timer.expires < timer_expires) {
 		timer_active	= 1;
 		timer_expires	= tp->retransmit_timer.expires;
 	}
-	if (timer_active2 && sp->timer.expires < timer_expires) {
+	if (tp->probe_timer.prev != NULL &&
+	    tp->probe_timer.expires < timer_expires) {
+		timer_active	= 4;
+		timer_expires	= tp->probe_timer.expires;
+	}
+	if (sp->timer.prev != NULL &&
+	    sp->timer.expires < timer_expires) {
 		timer_active	= 2;
 		timer_expires	= sp->timer.expires;
 	}
@@ -147,9 +149,6 @@
 		(!tw_bucket && sp->socket) ? sp->socket->inode->i_uid : 0,
 		(!tw_bucket && timer_active) ? sp->timeout : 0,
 		(!tw_bucket && sp->socket) ? sp->socket->inode->i_ino : 0);
-	
-	if (timer_active1) add_timer(&tp->retransmit_timer);
-	if (timer_active2) add_timer(&sp->timer);	
 }
 
 /*
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/ipv4/tcp.c linux.15p9/net/ipv4/tcp.c
--- linux.vanilla/net/ipv4/tcp.c	Tue Jan  4 21:19:03 2000
+++ linux.15p9/net/ipv4/tcp.c	Wed Feb  9 15:49:20 2000
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp.c,v 1.140.2.5 1999/09/23 19:21:16 davem Exp $
+ * Version:	$Id: tcp.c,v 1.140.2.9 2000/02/07 20:20:00 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1448,12 +1448,11 @@
 		return;
 
 	/* If we've already sent a FIN, or it's a closed state, skip this. */
-	if ((1 << sk->state) &
-	    (TCPF_ESTABLISHED|TCPF_SYN_SENT|TCPF_SYN_RECV|TCPF_CLOSE_WAIT)) {
+	if ((1 << sk->state) & (TCPF_ESTABLISHED|TCPF_SYN_RECV|TCPF_SYN_SENT)) {
 		lock_sock(sk);
 
 		/* Clear out any half completed packets.  FIN if needed. */
-		if (tcp_close_state(sk,0))
+		if (tcp_close_state(sk,sk->state == TCP_CLOSE_WAIT))
 			tcp_send_fin(sk);
 
 		release_sock(sk);
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/ipv4/tcp_input.c linux.15p9/net/ipv4/tcp_input.c
--- linux.vanilla/net/ipv4/tcp_input.c	Tue Jan  4 21:19:03 2000
+++ linux.15p9/net/ipv4/tcp_input.c	Mon Feb  7 12:08:45 2000
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_input.c,v 1.164.2.8 1999/09/23 19:21:23 davem Exp $
+ * Version:	$Id: tcp_input.c,v 1.164.2.12 2000/01/31 20:43:36 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -270,10 +270,12 @@
 /* When we get a reset we do this. */
 static void tcp_reset(struct sock *sk)
 {
+	unsigned char orig_state = sk->state;
+
 	sk->zapped = 1;
 
 	/* We want the right error as BSD sees it (and indeed as we do). */
-	switch (sk->state) {
+	switch (orig_state) {
 		case TCP_SYN_SENT:
 			sk->err = ECONNREFUSED;
 			break;
@@ -284,6 +286,16 @@
 			sk->err = ECONNRESET;
 	};
 	tcp_set_state(sk, TCP_CLOSE);
+	if (orig_state == TCP_SYN_SENT) {
+		/* Back out identity changes done by connect.
+		 * The move to TCP_CLOSE has unhashed us and
+		 * killed the bind bucket reference, making this
+		 * safe. -DaveM
+		 */
+		sk->dport = 0;
+		sk->daddr = 0;
+		sk->num = 0;
+	}
 	sk->shutdown = SHUTDOWN_MASK;
 	if (!sk->dead) 
 		sk->state_change(sk);
@@ -988,7 +1000,7 @@
 	}
 
 	/* Check RST or SYN */
-	if(th->rst || th->syn) {
+	if(th->rst) {
 		/* This is TIME_WAIT assasination, in two flavors.
 		 * Oh well... nobody has a sufficient solution to this
 		 * protocol bug yet.
@@ -997,8 +1009,6 @@
 			tcp_tw_deschedule(tw);
 			tcp_timewait_kill(tw);
 		}
-		if(!th->rst)
-			return TCP_TW_RST; /* toss a reset back */
 		return 0;
 	} else {
 		/* In this case we must reset the TIMEWAIT timer. */
@@ -1129,11 +1139,6 @@
 
 	tcp_send_ack(sk);
 
-	if (!sk->dead) {
-		sk->state_change(sk);
-		sock_wake_async(sk->socket, 1);
-	}
-
 	switch(sk->state) {
 		case TCP_SYN_RECV:
 		case TCP_ESTABLISHED:
@@ -1177,6 +1182,11 @@
 			printk("tcp_fin: Impossible, sk->state=%d\n", sk->state);
 			break;
 	};
+
+	if (!sk->dead) {
+		sk->state_change(sk);
+		sock_wake_async(sk->socket, 1);
+	}
 }
 
 /* These routines update the SACK block as out-of-order packets arrive or
@@ -2405,7 +2415,8 @@
 		 * BSD 4.4 also does reset.
 		 */
 		if ((sk->shutdown & RCV_SHUTDOWN) && sk->dead) {
-			if (after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt)) {
+			if (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq &&
+			    after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt)) {
 				tcp_reset(sk);
 				return 1;
 			}
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/ipv4/tcp_output.c linux.15p9/net/ipv4/tcp_output.c
--- linux.vanilla/net/ipv4/tcp_output.c	Sat Aug 14 02:26:52 1999
+++ linux.15p9/net/ipv4/tcp_output.c	Wed Feb  9 15:49:20 2000
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_output.c,v 1.108.2.1 1999/05/14 23:07:36 davem Exp $
+ * Version:	$Id: tcp_output.c,v 1.108.2.6 2000/02/07 20:20:11 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -165,7 +165,7 @@
 	tp->write_seq += (TCP_SKB_CB(skb)->end_seq - TCP_SKB_CB(skb)->seq);
 	__skb_queue_tail(&sk->write_queue, skb);
 
-	if (!force_queue && tp->send_head == NULL && tcp_snd_test(sk, skb)) {
+	if (!force_queue && tp->send_head == NULL && tcp_snd_test(sk, skb, 1)) {
 		/* Send it out now. */
 		TCP_SKB_CB(skb)->when = tcp_time_stamp;
 		tp->snd_nxt = TCP_SKB_CB(skb)->end_seq;
@@ -341,7 +341,8 @@
 		 * b) not exceeding our congestion window.
 		 * c) not retransmitting [Nagle]
 		 */
-		while((skb = tp->send_head) && tcp_snd_test(sk, skb)) {
+		while((skb = tp->send_head) &&
+		      tcp_snd_test(sk, skb, tcp_skb_is_last(sk, skb))) {
 			if (skb->len > mss_now) {
 				if (tcp_fragment(sk, skb, mss_now))
 					break;
@@ -752,12 +753,16 @@
 		}
 	} else {
 		/* Socket is locked, keep trying until memory is available. */
-		do {
+		for (;;) {
 			skb = sock_wmalloc(sk,
 					   (MAX_HEADER +
 					    sk->prot->max_header),
 					   1, GFP_KERNEL);
-		} while (skb == NULL);
+			if (skb)
+				break;
+			current->policy |= SCHED_YIELD;
+			schedule();
+		}
 
 		/* Reserve space for headers and prepare control bits. */
 		skb_reserve(skb, MAX_HEADER + sk->prot->max_header);
@@ -1004,7 +1009,7 @@
 	unsigned long timeout;
 
 	/* Stay within the limit we were given */
-	timeout = tp->ato;
+	timeout = (tp->ato << 1) >> 1;
 	if (timeout > max_timeout)
 		timeout = max_timeout;
 	timeout += jiffies;
@@ -1040,10 +1045,14 @@
 			 *
 			 * This is the one possible way that we can delay an
 			 * ACK and have tp->ato indicate that we are in
-			 * quick ack mode, so clear it.
+			 * quick ack mode, so clear it.  It is also the only
+			 * possible way for ato to be zero, when ACK'ing a
+			 * SYNACK because we've taken no ATO measurement yet.
 			 */
-			if(tcp_in_quickack_mode(tp))
+			if (tcp_in_quickack_mode(tp))
 				tcp_exit_quickack_mode(tp);
+			if (!tp->ato)
+				tp->ato = tp->rto;
 			tcp_send_delayed_ack(tp, HZ/2);
 			return;
 		}
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/ipv4/tcp_timer.c linux.15p9/net/ipv4/tcp_timer.c
--- linux.vanilla/net/ipv4/tcp_timer.c	Tue Jan  4 21:19:03 2000
+++ linux.15p9/net/ipv4/tcp_timer.c	Fri Jan 14 16:02:40 2000
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_timer.c,v 1.62.2.4 1999/09/23 19:21:39 davem Exp $
+ * Version:	$Id: tcp_timer.c,v 1.62.2.6 2000/01/13 04:28:06 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -131,6 +131,7 @@
 	} else {
 		/* Clean up time. */
 		tcp_set_state(sk, TCP_CLOSE);
+		sk->shutdown |= SHUTDOWN_MASK;
 		return 0;
 	}
 	return 1;
@@ -140,26 +141,46 @@
 static int tcp_write_timeout(struct sock *sk)
 {
 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+	unsigned char orig_state = sk->state;
+	int ret;
 
 	/* Look for a 'soft' timeout. */
-	if ((sk->state == TCP_ESTABLISHED &&
+	if ((orig_state == TCP_ESTABLISHED &&
 	     tp->retransmits && (tp->retransmits % TCP_QUICK_TRIES) == 0) ||
-	    (sk->state != TCP_ESTABLISHED && tp->retransmits > sysctl_tcp_retries1)) {
+	    (orig_state != TCP_ESTABLISHED && tp->retransmits > sysctl_tcp_retries1)) {
 		dst_negative_advice(&sk->dst_cache);
 	}
 	
 	/* Have we tried to SYN too many times (repent repent 8)) */
-	if(tp->retransmits > sysctl_tcp_syn_retries && sk->state==TCP_SYN_SENT) {
+	if(tp->retransmits > sysctl_tcp_syn_retries && orig_state==TCP_SYN_SENT) {
 		tcp_write_err(sk, 1);
+
 		/* Don't FIN, we got nothing back */
-		return 0;
+		ret = 0;
+	} else {
+		/* Has it gone just too far? */
+		if (tp->retransmits > sysctl_tcp_retries2) 
+			ret = tcp_write_err(sk, 0);
+		else
+			ret = 1;
 	}
 
-	/* Has it gone just too far? */
-	if (tp->retransmits > sysctl_tcp_retries2) 
-		return tcp_write_err(sk, 0);
+	/* Did we timeout a connecting socket?  The check must be
+	 * like this just in case someone sets syn_retries larger
+	 * than retries2, which is silly but handle it.  -DaveM
+	 */
+	if (orig_state == TCP_SYN_SENT && sk->state == TCP_CLOSE) {
+		/* Back out identity changes done by connect.
+		 * The move to TCP_CLOSE has unhashed us and
+		 * killed the bind bucket reference, making this
+		 * safe. -DaveM
+		 */
+		sk->dport = 0;
+		sk->daddr = 0;
+		sk->num = 0;
+	}
 
-	return 1;
+	return ret;
 }
 
 void tcp_delack_timer(unsigned long data)
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/ipv6/Config.in linux.15p9/net/ipv6/Config.in
--- linux.vanilla/net/ipv6/Config.in	Thu Feb 19 22:46:16 1998
+++ linux.15p9/net/ipv6/Config.in	Wed Feb 16 18:13:07 2000
@@ -6,8 +6,10 @@
   bool 'IPv6: disable provider based addresses' CONFIG_IPV6_NO_PB
 fi
 if [ "$CONFIG_NETLINK" = "y" ]; then
-  if [ "$CONFIG_RTNETLINK" = "n" ]; then
-    bool 'IPv6: routing messages via old netlink' CONFIG_IPV6_NETLINK
+  if [ "$CONFIG_NETLINK_DEV" != "n" ]; then
+    if [ "$CONFIG_RTNETLINK" = "n" ]; then
+      bool 'IPv6: routing messages via old netlink' CONFIG_IPV6_NETLINK
+    fi
   fi
 fi
 #bool 'IPv6: flow policy support' CONFIG_RT6_POLICY
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/ipv6/addrconf.c linux.15p9/net/ipv6/addrconf.c
--- linux.vanilla/net/ipv6/addrconf.c	Tue Jan  4 21:19:03 2000
+++ linux.15p9/net/ipv6/addrconf.c	Fri Jan 14 16:02:40 2000
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: addrconf.c,v 1.48.2.1 1999/06/28 10:39:39 davem Exp $
+ *	$Id: addrconf.c,v 1.48.2.2 1999/12/14 10:32:53 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/ipv6/af_inet6.c linux.15p9/net/ipv6/af_inet6.c
--- linux.vanilla/net/ipv6/af_inet6.c	Sat Aug 14 02:27:43 1999
+++ linux.15p9/net/ipv6/af_inet6.c	Fri Jan 14 16:02:48 2000
@@ -7,7 +7,7 @@
  *
  *	Adapted from linux/net/ipv4/af_inet.c
  *
- *	$Id: af_inet6.c,v 1.43.2.1 1999/06/20 20:15:06 davem Exp $
+ *	$Id: af_inet6.c,v 1.43.2.2 2000/01/13 04:28:23 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -243,6 +243,7 @@
 	if(sk->prot->get_port(sk, snum) != 0)
 		return -EADDRINUSE;
 
+	sk->zapped = 0;
 	sk->sport = ntohs(sk->num);
 	sk->dport = 0;
 	sk->daddr = 0;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/ipv6/proc.c linux.15p9/net/ipv6/proc.c
--- linux.vanilla/net/ipv6/proc.c	Fri Aug 28 03:33:09 1998
+++ linux.15p9/net/ipv6/proc.c	Fri Jan 14 16:02:48 2000
@@ -7,7 +7,7 @@
  *		PROC file system.  This is very similar to the IPv4 version,
  *		except it reports the sockets in the INET6 address family.
  *
- * Version:	$Id: proc.c,v 1.9 1998/08/26 12:05:11 davem Exp $
+ * Version:	$Id: proc.c,v 1.9.2.1 2000/01/14 01:22:24 davem Exp $
  *
  * Authors:	David S. Miller (davem@caip.rutgers.edu)
  *
@@ -32,7 +32,7 @@
 {
 	struct sock *sp;
 	struct tcp_opt *tp;
-	int timer_active, timer_active1, timer_active2;
+	int timer_active;
 	unsigned long timer_expires;
 	struct in6_addr *dest, *src;
 	unsigned short destp, srcp;
@@ -76,29 +76,31 @@
 			extern int tcp_tw_death_row_slot;
 			int slot_dist;
 
-			timer_active1	= timer_active2 = 0;
 			timer_active	= 3;
 			slot_dist	= tw->death_slot;
-			if(slot_dist > tcp_tw_death_row_slot)
-				slot_dist = (TCP_TWKILL_SLOTS - slot_dist) + tcp_tw_death_row_slot;
+			if(slot_dist >= tcp_tw_death_row_slot)
+				slot_dist = slot_dist - tcp_tw_death_row_slot;
 			else
-				slot_dist = tcp_tw_death_row_slot - slot_dist;
+				slot_dist = (TCP_TWKILL_SLOTS - tcp_tw_death_row_slot) + slot_dist;
 			timer_expires	= jiffies + (slot_dist * TCP_TWKILL_PERIOD);
 		} else {
-			timer_active1 = del_timer(&tp->retransmit_timer);
-			timer_active2 = del_timer(&sp->timer);
-			if(!timer_active1) tp->retransmit_timer.expires = 0;
-			if(!timer_active2) sp->timer.expires = 0;
 			timer_active = 0;
 			timer_expires = (unsigned) -1;
 		}
-		if(timer_active1 && tp->retransmit_timer.expires < timer_expires) {
-			timer_active = timer_active1;
-			timer_expires = tp->retransmit_timer.expires;
+		if (tp->retransmit_timer.prev != NULL &&
+		    tp->retransmit_timer.expires < timer_expires) {
+			timer_active	= 1;
+			timer_expires	= tp->retransmit_timer.expires;
 		}
-		if(timer_active2 && sp->timer.expires < timer_expires) {
-			timer_active = timer_active2;
-			timer_expires = sp->timer.expires;
+		if (tp->probe_timer.prev != NULL &&
+		    tp->probe_timer.expires < timer_expires) {
+			timer_active	= 4;
+			timer_expires	= tp->probe_timer.expires;
+		}
+		if (sp->timer.prev != NULL &&
+		    sp->timer.expires < timer_expires) {
+			timer_active	= 2;
+			timer_expires	= sp->timer.expires;
 		}
 		if(timer_active == 0)
 			timer_expires = jiffies;
@@ -128,8 +130,6 @@
 			((!tw_bucket && sp->socket) ?
 			 sp->socket->inode->i_ino : 0));
 
-		if(timer_active1) add_timer(&tp->retransmit_timer);
-		if(timer_active2) add_timer(&sp->timer);
 		len += sprintf(buffer+len, "%-148s\n", tmpbuf);
 		if(len >= length)
 			break;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/ipv6/tcp_ipv6.c linux.15p9/net/ipv6/tcp_ipv6.c
--- linux.vanilla/net/ipv6/tcp_ipv6.c	Tue Jan  4 21:19:03 2000
+++ linux.15p9/net/ipv6/tcp_ipv6.c	Fri Jan 14 16:02:48 2000
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: tcp_ipv6.c,v 1.104.2.10 1999/09/23 19:21:46 davem Exp $
+ *	$Id: tcp_ipv6.c,v 1.104.2.11 1999/12/03 09:30:29 davem Exp $
  *
  *	Based on: 
  *	linux/net/ipv4/tcp.c
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/Config.in linux.15p9/net/irda/Config.in
--- linux.vanilla/net/irda/Config.in	Sat Aug 14 02:26:52 1999
+++ linux.15p9/net/irda/Config.in	Tue Jan 18 01:08:18 2000
@@ -2,31 +2,30 @@
 # IrDA protocol configuration
 #
 
-if [ "$CONFIG_NET" != "n" ] ; then
+if [ "$CONFIG_NET" != "n" ]; then
 
-  mainmenu_option next_comment
-  comment 'IrDA subsystem support'
-  dep_tristate 'IrDA subsystem support' CONFIG_IRDA $CONFIG_NET
+   mainmenu_option next_comment
+   comment 'IrDA (infrared) support'
+   dep_tristate 'IrDA subsystem support' CONFIG_IRDA $CONFIG_NET
 
-  if [ "$CONFIG_IRDA" != "n" ] ; then
-    comment 'IrDA protocols'
-    source net/irda/irlan/Config.in
-    source net/irda/ircomm/Config.in
-    source net/irda/irlpt/Config.in
+   if [ "$CONFIG_IRDA" != "n" ]; then
+      comment 'IrDA protocols'
+      source net/irda/irlan/Config.in
+      source net/irda/ircomm/Config.in
+      bool '  Ultra (connectionless) protocol' CONFIG_IRDA_ULTRA
+      bool '  IrDA protocol options' CONFIG_IRDA_OPTIONS
+      if [ "$CONFIG_IRDA_OPTIONS" != "n" ]; then
+	 comment '  IrDA options'
+	 bool '    Cache last LSAP' CONFIG_IRDA_CACHE_LAST_LSAP
+	 bool '    Fast RRs' CONFIG_IRDA_FAST_RR
+	 bool '    Debug information' CONFIG_IRDA_DEBUG
+      fi
+   fi
 
-    bool 'IrDA protocol options' CONFIG_IRDA_OPTIONS
-    if [ "$CONFIG_IRDA_OPTIONS" != "n" ] ; then
-      comment '   IrDA options'
-      bool '   Cache last LSAP' CONFIG_IRDA_CACHE_LAST_LSAP
-      bool '   Fast RRs' CONFIG_IRDA_FAST_RR
-      bool '   Debug information' CONFIG_IRDA_DEBUG
-    fi
-  fi
-
-  if [ "$CONFIG_IRDA" != "n" ] ; then
-    source net/irda/compressors/Config.in
-    source drivers/net/irda/Config.in
-  fi
-  endmenu
+   if [ "$CONFIG_IRDA" != "n" ]; then
+      source net/irda/compressors/Config.in
+      source drivers/net/irda/Config.in
+   fi
+   endmenu
 fi
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/Makefile linux.15p9/net/irda/Makefile
--- linux.vanilla/net/irda/Makefile	Sat Aug 14 02:25:47 1999
+++ linux.15p9/net/irda/Makefile	Tue Jan 18 01:08:18 2000
@@ -7,7 +7,7 @@
 #
 # Note 2! The CFLAGS definition is now in the main makefile...
 
-ALL_SUB_DIRS := irlan ircomm irlpt compressors
+ALL_SUB_DIRS := irlan ircomm compressors
 SUB_DIRS :=
 MOD_SUB_DIRS :=
 OX_OBJS :=
@@ -16,7 +16,7 @@
 O_OBJS	 := iriap.o iriap_event.o irlmp.o irlmp_event.o irlmp_frame.o \
             irlap.o irlap_event.o irlap_frame.o timer.o qos.o irqueue.o \
             irttp.o irda_device.o irias_object.o crc.o wrapper.o af_irda.o \
-	    discovery.o
+	    discovery.o parameters.o
 OX_OBJS := irmod.o
 
 MOD_LIST_NAME := IRDA_MODULES
@@ -46,15 +46,6 @@
   endif
 endif
 
-ifeq ($(CONFIG_IRLPT),y)
-SUB_DIRS += irlpt
-O_OBJS += irlpt/irlpt.o
-else
-  ifeq ($(CONFIG_IRLPT),m)
-  MOD_IN_SUB_DIRS += irlpt
-  endif
-endif
-
 ifeq ($(CONFIG_IRDA_COMPRESSION),y)
 SUB_DIRS += compressors
 MOD_IN_SUB_DIRS += compressors
@@ -70,7 +61,7 @@
 
 ifeq ($(CONFIG_IRCOMM),y)
 SUB_DIRS += ircomm
-O_OBJS += ircomm/ircomm_n_vtd.o
+O_OBJS += ircomm/ircomm_and_tty.o
 else
   ifeq ($(CONFIG_IRCOMM),m)
   MOD_SUB_DIRS += ircomm
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/af_irda.c linux.15p9/net/irda/af_irda.c
--- linux.vanilla/net/irda/af_irda.c	Sat Aug 14 02:26:52 1999
+++ linux.15p9/net/irda/af_irda.c	Tue Jan 18 01:08:18 2000
@@ -1,25 +1,44 @@
 /*********************************************************************
  *                
  * Filename:      af_irda.c
- * Version:       0.6
+ * Version:       0.9
  * Description:   IrDA sockets implementation
- * Status:        Experimental.
+ * Status:        Stable
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun May 31 10:12:43 1998
- * Modified at:   Wed May 19 16:12:06 1999
+ * Modified at:   Sat Dec 25 21:10:23 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       af_netroom.c, af_ax25.c, af_rose.c, af_x25.c etc.
  * 
- *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
- *      
+ *     Copyright (c) 1999 Dag Brattli <dagb@cs.uit.no>
+ *     Copyright (c) 1999 Jean Tourrilhes <jeant@rockfort.hpl.hp.com>
+ *     All Rights Reserved.
+ *
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
- *  
- *     Neither Dag Brattli nor University of Tromsř admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *
+ *     Linux-IrDA now supports four different types of IrDA sockets:
+ *
+ *     o SOCK_STREAM:    TinyTP connections with SAR disabled. The
+ *                       max SDU size is 0 for conn. of this type
+ *     o SOCK_SEQPACKET: TinyTP connections with SAR enabled. TTP may 
+ *                       fragment the messages, but will preserve
+ *                       the message boundaries
+ *     o SOCK_DGRAM:     IRDAPROTO_UNITDATA: TinyTP connections with Unitdata 
+ *                       (unreliable) transfers
+ *                       IRDAPROTO_ULTRA: Connectionless and unreliable data
  *     
  ********************************************************************/
 
@@ -39,6 +58,7 @@
 #include <net/irda/irda.h>
 #include <net/irda/iriap.h>
 #include <net/irda/irias_object.h>
+#include <net/irda/irlmp.h>
 #include <net/irda/irttp.h>
 #include <net/irda/discovery.h>
 
@@ -47,8 +67,17 @@
 extern int  irlap_driver_rcv(struct sk_buff *, struct device *, 
 			     struct packet_type *);
 
+static int irda_create(struct socket *sock, int protocol);
+
 static struct proto_ops irda_stream_ops;
+static struct proto_ops irda_seqpacket_ops;
 static struct proto_ops irda_dgram_ops;
+
+#ifdef CONFIG_IRDA_ULTRA
+static struct proto_ops irda_ultra_ops;
+#define ULTRA_MAX_DATA 382
+#endif /* CONFIG_IRDA_ULTRA */
+
 static hashbin_t *cachelog = NULL;
 static struct wait_queue *discovery_wait; /* Wait for discovery */
 
@@ -66,8 +95,6 @@
 	struct sock *sk;
 	int err;
 
-	DEBUG(1, __FUNCTION__ "()\n");
-
 	self = (struct irda_sock *) instance;
 	ASSERT(self != NULL, return -1;);
 
@@ -76,7 +103,7 @@
 
 	err = sock_queue_rcv_skb(sk, skb);
 	if (err) {
-		DEBUG(1, __FUNCTION__ "(), error: no more mem!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), error: no more mem!\n");
 		self->rx_flow = FLOW_STOP;
 
 		/* When we return error, TTP will need to requeue the skb */
@@ -98,7 +125,7 @@
 	struct irda_sock *self;
 	struct sock *sk;
 
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	self = (struct irda_sock *) instance;
 
@@ -107,7 +134,7 @@
 		return;
 
 	sk->state     = TCP_CLOSE;
-        sk->err       = reason;
+        sk->err       = ECONNRESET;
         sk->shutdown |= SEND_SHUTDOWN;
 	if (!sk->dead) {
 		sk->state_change(sk);
@@ -129,10 +156,14 @@
 	struct irda_sock *self;
 	struct sock *sk;
 
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	self = (struct irda_sock *) instance;
 
+	sk = self->sk;
+	if (sk == NULL)
+		return;
+
 	/* How much header space do we need to reserve */
 	self->max_header_size = max_header_size;
 
@@ -140,19 +171,30 @@
 	self->max_sdu_size_tx = max_sdu_size;
 
 	/* Find out what the largest chunk of data that we can transmit is */
-	if (max_sdu_size == SAR_DISABLE)
-		self->max_data_size = qos->data_size.value - max_header_size;
-	else
+	switch (sk->type) {
+	case SOCK_STREAM:
+		if (max_sdu_size != 0) {
+			ERROR(__FUNCTION__ "(), max_sdu_size must be 0\n");
+			return;
+		}
+		self->max_data_size = irttp_get_max_seg_size(self->tsap);
+		break;
+	case SOCK_SEQPACKET:
+		if (max_sdu_size == 0) {
+			ERROR(__FUNCTION__ "(), max_sdu_size cannot be 0\n");
+			return;
+		}
 		self->max_data_size = max_sdu_size;
+		break;
+	default:
+		self->max_data_size = irttp_get_max_seg_size(self->tsap);
+	};
 
-	DEBUG(1, __FUNCTION__ "(), max_data_size=%d\n", self->max_data_size);
+	IRDA_DEBUG(2, __FUNCTION__ "(), max_data_size=%d\n", 
+		   self->max_data_size);
 
 	memcpy(&self->qos_tx, qos, sizeof(struct qos_info));
 
-	sk = self->sk;
-	if (sk == NULL)
-		return;
-
 	skb_queue_tail(&sk->receive_queue, skb);
 
 	/* We are now connected! */
@@ -173,9 +215,13 @@
 	struct irda_sock *self;
 	struct sock *sk;
 
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
-	self = (struct irda_sock *) instance;
+ 	self = (struct irda_sock *) instance;
+
+	sk = self->sk;
+	if (sk == NULL)
+		return;
 
 	/* How much header space do we need to reserve */
 	self->max_header_size = max_header_size;
@@ -184,21 +230,31 @@
 	self->max_sdu_size_tx = max_sdu_size;	
 
 	/* Find out what the largest chunk of data that we can transmit is */
-	if (max_sdu_size == SAR_DISABLE)
-		self->max_data_size = qos->data_size.value - max_header_size;
-	else
+	switch (sk->type) {
+	case SOCK_STREAM:
+		if (max_sdu_size != 0) {
+			ERROR(__FUNCTION__ "(), max_sdu_size must be 0\n");
+			return;
+		}
+		self->max_data_size = irttp_get_max_seg_size(self->tsap);
+		break;
+	case SOCK_SEQPACKET:
+		if (max_sdu_size == 0) {
+			ERROR(__FUNCTION__ "(), max_sdu_size cannot be 0\n");
+			return;
+		}
 		self->max_data_size = max_sdu_size;
+		break;
+	default:
+		self->max_data_size = irttp_get_max_seg_size(self->tsap);
+	};
 
-	DEBUG(1, __FUNCTION__ "(), max_data_size=%d\n", self->max_data_size);
+	IRDA_DEBUG(2, __FUNCTION__ "(), max_data_size=%d\n", 
+		   self->max_data_size);
 
 	memcpy(&self->qos_tx, qos, sizeof(struct qos_info));
-
-	sk = self->sk;
-	if (sk == NULL)
-		return;
 	
 	skb_queue_tail(&sk->receive_queue, skb);
-
 	sk->state_change(sk);
 }
 
@@ -212,13 +268,13 @@
 {
 	struct sk_buff *skb;
 
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 
 	skb = dev_alloc_skb(64);
 	if (skb == NULL) {
-		DEBUG(0, __FUNCTION__ "() Unable to allocate sk_buff!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "() Unable to allocate sk_buff!\n");
 		return;
 	}
 
@@ -228,7 +284,6 @@
 	irttp_connect_response(self->tsap, self->max_sdu_size_rx, skb);
 }
 
-
 /*
  * Function irda_flow_indication (instance, sap, flow)
  *
@@ -240,7 +295,7 @@
 	struct irda_sock *self;
 	struct sock *sk;
 
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 	
 	self = (struct irda_sock *) instance;
 	ASSERT(self != NULL, return;);
@@ -250,43 +305,53 @@
 	
 	switch (flow) {
 	case FLOW_STOP:
-		DEBUG(1, __FUNCTION__ "(), IrTTP wants us to slow down\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), IrTTP wants us to slow down\n");
 		self->tx_flow = flow;
 		break;
 	case FLOW_START:
 		self->tx_flow = flow;
-		DEBUG(1, __FUNCTION__ "(), IrTTP wants us to start again\n");
+		IRDA_DEBUG(1, __FUNCTION__ 
+			   "(), IrTTP wants us to start again\n");
 		wake_up_interruptible(sk->sleep);
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown flow command!\n");
+		IRDA_DEBUG( 0, __FUNCTION__ "(), Unknown flow command!\n");
+		/* Unknown flow command, better stop */
+		self->tx_flow = flow;
+		break;
 	}
 }
 
 /*
- * Function irda_get_value_confirm (obj_id, value, priv)
+ * Function irda_getvalue_confirm (obj_id, value, priv)
  *
  *    Got answer from remote LM-IAS
  *
  */
-static void irda_get_value_confirm(int result, __u16 obj_id, 
-				   struct ias_value *value, void *priv)
+static void irda_getvalue_confirm(int result, __u16 obj_id, 
+				  struct ias_value *value, void *priv)
 {
 	struct irda_sock *self;
 	
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	ASSERT(priv != NULL, return;);
 	self = (struct irda_sock *) priv;
 	
-	if (!self)
+	if (!self) {
+		WARNING(__FUNCTION__ "(), lost myself!\n");
 		return;
+	}
+
+	/* We probably don't need to make any more queries */
+	iriap_close(self->iriap);
+	self->iriap = NULL;
+
+	self->errno = result;
 
 	/* Check if request succeeded */
 	if (result != IAS_SUCCESS) {
-		DEBUG(0, __FUNCTION__ "(), IAS query failed!\n");
-
-		self->errno = result;
+		IRDA_DEBUG(0, __FUNCTION__ "(), IAS query failed!\n");
 
 		/* Wake up any processes waiting for result */
 		wake_up_interruptible(&self->ias_wait);
@@ -296,7 +361,7 @@
 
 	switch (value->type) {
 	case IAS_INTEGER:
-		DEBUG(4, __FUNCTION__ "() int=%d\n", value->t.integer);
+		IRDA_DEBUG(4, __FUNCTION__ "() int=%d\n", value->t.integer);
 		
 		if (value->t.integer != -1) {
 			self->dtsap_sel = value->t.integer;
@@ -304,9 +369,11 @@
 			self->dtsap_sel = 0;
 		break;
 	default:
-		DEBUG(0, __FUNCTION__ "(), bad type!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), bad type!\n");
 		break;
 	}
+	irias_delete_value(value);
+
 	/* Wake up any processes waiting for result */
 	wake_up_interruptible(&self->ias_wait);
 }
@@ -319,7 +386,7 @@
  */
 static void irda_discovery_indication(hashbin_t *log)
 {
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	cachelog = log;
 
@@ -335,16 +402,20 @@
  */
 static int irda_open_tsap(struct irda_sock *self, __u8 tsap_sel, char *name)
 {
-	struct notify_t notify;
-	
-	DEBUG(1, __FUNCTION__ "()\n");
+	notify_t notify;
 
+	if (self->tsap) {
+		WARNING(__FUNCTION__ "(), busy!\n");
+		return -EBUSY;
+	}
+	
 	/* Initialize callbacks to be used by the IrDA stack */
 	irda_notify_init(&notify);
 	notify.connect_confirm       = irda_connect_confirm;
 	notify.connect_indication    = irda_connect_indication;
 	notify.disconnect_indication = irda_disconnect_indication;
 	notify.data_indication       = irda_data_indication;
+	notify.udata_indication	     = irda_data_indication;
 	notify.flow_indication       = irda_flow_indication;
 	notify.instance = self;
 	strncpy(notify.name, name, NOTIFY_MAX_NAME);
@@ -352,8 +423,8 @@
 	self->tsap = irttp_open_tsap(tsap_sel, DEFAULT_INITIAL_CREDIT,
 				     &notify);	
 	if (self->tsap == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Unable to allocate TSAP!\n");
-		return -1;
+		IRDA_DEBUG( 0, __FUNCTION__ "(), Unable to allocate TSAP!\n");
+		return -ENOMEM;
 	}
 	/* Remember which TSAP selector we actually got */
 	self->stsap_sel = self->tsap->stsap_sel;
@@ -362,6 +433,38 @@
 }
 
 /*
+ * Function irda_open_lsap (self)
+ *
+ *    Open local Link Service Access Point (LSAP). Used for opening Ultra
+ *    sockets
+ */
+#ifdef CONFIG_IRDA_ULTRA
+static int irda_open_lsap(struct irda_sock *self, int pid)
+{
+	notify_t notify;
+
+	if (self->lsap) {
+		WARNING(__FUNCTION__ "(), busy!\n");
+		return -EBUSY;
+	}
+	
+	/* Initialize callbacks to be used by the IrDA stack */
+	irda_notify_init(&notify);
+	notify.udata_indication	= irda_data_indication;
+	notify.instance = self;
+	strncpy(notify.name, "Ultra", NOTIFY_MAX_NAME);
+
+	self->lsap = irlmp_open_lsap(LSAP_CONNLESS, &notify, pid);	
+	if (self->lsap == NULL) {
+		IRDA_DEBUG( 0, __FUNCTION__ "(), Unable to allocate LSAP!\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+#endif /* CONFIG_IRDA_ULTRA */
+
+/*
  * Function irda_find_lsap_sel (self, name)
  *
  *    Try to lookup LSAP selector in remote LM-IAS
@@ -369,14 +472,21 @@
  */
 static int irda_find_lsap_sel(struct irda_sock *self, char *name)
 {
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "(), name=%s\n", name);
 
 	ASSERT(self != NULL, return -1;);
 
+	if (self->iriap) {
+		WARNING(__FUNCTION__ "(), busy with a previous query\n");
+		return -EBUSY;
+	}
+
+	self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,
+				 irda_getvalue_confirm);
+
 	/* Query remote LM-IAS */
-	iriap_getvaluebyclass_request(name, "IrDA:TinyTP:LsapSel",
-				      self->saddr, self->daddr,
-				      irda_get_value_confirm, self);
+	iriap_getvaluebyclass_request(self->iriap, self->saddr, self->daddr,
+				      name, "IrDA:TinyTP:LsapSel");
 	/* Wait for answer */
 	interruptible_sleep_on(&self->ias_wait);
 
@@ -386,6 +496,104 @@
 	return -ENETUNREACH; /* May not be true */
 }
 
+ /*
+ * Function irda_discover_daddr_and_lsap_sel (self, name)
+ *
+ *    This try to find a device with the requested service.
+ *
+ * It basically look into the discovery log. For each address in the list,
+ * it queries the LM-IAS of the device to find if this device offer
+ * the requested service.
+ * If there is more than one node supporting the service, we complain
+ * to the user (it should move devices around).
+ * The, we set both the destination address and the lsap selector to point
+ * on the service on the unique device we have found.
+ *
+ * Note : this function fails if there is more than one device in range,
+ * because IrLMP doesn't disconnect the LAP when the last LSAP is closed.
+ * Moreover, we would need to wait the LAP disconnection...
+ */
+static int irda_discover_daddr_and_lsap_sel(struct irda_sock *self, char *name)
+{
+	discovery_t *discovery;
+	int err = -ENETUNREACH;
+	__u32	daddr = 0x0;		/* Address we found the service on */
+	__u8	dtsap_sel = 0x0;	/* TSAP associated with it */
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), name=%s\n", name);
+
+	ASSERT(self != NULL, return -1;);
+
+	/* Tell IrLMP we want to be notified */
+	irlmp_update_client(self->ckey, self->mask, NULL, 
+			    irda_discovery_indication);
+	
+	/* Do some discovery */
+	irlmp_discovery_request(self->nslots);
+		
+	/* Check if the we got some results */
+	if (!cachelog)
+		/* Wait for answer */
+		/*interruptible_sleep_on(&self->discovery_wait);*/
+		return -EAGAIN;
+
+	/* 
+	 * Now, check all discovered devices (if any), and connect
+	 * client only about the services that the client is
+	 * interested in...
+	 */
+	discovery = (discovery_t *) hashbin_get_first(cachelog);
+	while (discovery != NULL) {
+		/* Mask out the ones we don't want */
+		if (discovery->hints.word & self->mask) {
+			/* Try this address */
+			self->daddr = discovery->daddr;
+			self->saddr = 0x0;
+			IRDA_DEBUG(1, __FUNCTION__ "(), trying daddr = %08x\n",
+				   self->daddr);
+
+			/* Query remote LM-IAS for this service */
+			err = irda_find_lsap_sel(self, name);
+			if (err == 0) {
+				/* We found the requested service */
+				if(daddr != 0x0) {
+					IRDA_DEBUG(0, __FUNCTION__
+						   "(), discovered service ''%s'' in two different devices !!!\n",
+						   name);
+					return(-ENOTUNIQ);
+				}
+				/* First time we foun that one, save it ! */
+				daddr = self->daddr;
+				dtsap_sel = self->dtsap_sel;
+			}
+		}
+
+		/* Next node, maybe we will be more lucky...  */
+		discovery = (discovery_t *) hashbin_get_next(cachelog);
+	}
+	cachelog = NULL;
+
+	/* Check out what we found */
+	if(daddr == 0x0) {
+		IRDA_DEBUG(0, __FUNCTION__
+			   "(), cannot discover service ''%s'' in any device !!!\n",
+			   name);
+		self->daddr = 0;	/* Guessing */
+		return(-ENETUNREACH);
+	}
+
+	/* Revert back to discovered device & service */
+	self->daddr = daddr;
+	self->saddr = 0x0;
+	self->dtsap_sel = dtsap_sel;
+
+	IRDA_DEBUG(0, __FUNCTION__ 
+		   "(), discovered requested service ''%s'' at address %08x\n",
+		   name, self->daddr);
+
+	return 0;
+}
+
 /*
  * Function irda_getname (sock, uaddr, uaddr_len, peer)
  *
@@ -411,8 +619,8 @@
 		saddr.sir_addr = sk->protinfo.irda->saddr;
 	}
 	
-	DEBUG(1, __FUNCTION__ "(), tsap_sel = %#x\n", saddr.sir_lsap_sel);
-	DEBUG(1, __FUNCTION__ "(), addr = %08x\n", saddr.sir_addr);
+	IRDA_DEBUG(1, __FUNCTION__ "(), tsap_sel = %#x\n", saddr.sir_lsap_sel);
+	IRDA_DEBUG(1, __FUNCTION__ "(), addr = %08x\n", saddr.sir_addr);
 
 	if (*uaddr_len > sizeof (struct sockaddr_irda))
 		*uaddr_len = sizeof (struct sockaddr_irda);
@@ -427,16 +635,20 @@
  *    Just move to the listen state
  *
  */
-static int irda_listen( struct socket *sock, int backlog)
+static int irda_listen(struct socket *sock, int backlog)
 {
 	struct sock *sk = sock->sk;
 
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	if ((sk->type != SOCK_STREAM) && (sk->type != SOCK_SEQPACKET) &&
+	    (sk->type != SOCK_DGRAM))
+		return -EOPNOTSUPP;
 
-	if (sk->type == SOCK_STREAM && sk->state != TCP_LISTEN) {
+	if (sk->state != TCP_LISTEN) {
 		sk->max_ack_backlog = backlog;
 		sk->state           = TCP_LISTEN;
-
+		
 		return 0;
 	}
 	
@@ -457,24 +669,49 @@
 	__u16 hints = 0;
 	int err;
 
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	self = sk->protinfo.irda;
 	ASSERT(self != NULL, return -1;);
 
-	if ((addr_len < sizeof(struct sockaddr_irda)) || 
-	    (addr_len > sizeof(struct sockaddr_irda)))
+	if (addr_len != sizeof(struct sockaddr_irda))
 		return -EINVAL;
 
+#ifdef CONFIG_IRDA_ULTRA
+	/* Special care for Ultra sockets */
+	if ((sk->type == SOCK_DGRAM) && (sk->protocol == IRDAPROTO_ULTRA)) {
+		self->pid = addr->sir_lsap_sel;
+		if (self->pid & 0x80) {
+			IRDA_DEBUG(0, __FUNCTION__ 
+				   "(), extension in PID not supp!\n");
+			return -EOPNOTSUPP;
+		}
+		err = irda_open_lsap(self, self->pid);
+		if (err < 0)
+			return err;
+		
+		self->max_data_size = ULTRA_MAX_DATA - LMP_PID_HEADER;
+		self->max_header_size = IRDA_MAX_HEADER + LMP_PID_HEADER;
+
+		/* Pretend we are connected */
+		sock->state = SS_CONNECTED;
+		sk->state   = TCP_ESTABLISHED;
+
+		return 0;
+	}
+#endif /* CONFIG_IRDA_ULTRA */
+
 	err = irda_open_tsap(self, addr->sir_lsap_sel, addr->sir_name);
 	if (err < 0)
-		return -ENOMEM;
+		return err;
 	
 	/*  Register with LM-IAS */
 	self->ias_obj = irias_new_object(addr->sir_name, jiffies);
 	irias_add_integer_attrib(self->ias_obj, "IrDA:TinyTP:LsapSel", 
 				 self->stsap_sel);
 	irias_insert_object(self->ias_obj);
+	
+#if 1 /* Will be removed in near future */
 
 	/* Fill in some default hint bits values */
 	if (strncmp(addr->sir_name, "OBEX", 4) == 0)
@@ -482,7 +719,7 @@
 	
 	if (hints)
 		self->skey = irlmp_register_service(hints);
-
+#endif
 	return 0;
 }
 
@@ -498,20 +735,30 @@
 	struct sock *sk = sock->sk;
 	struct sock *newsk;
 	struct sk_buff *skb;
+#if 0 /* Linux 2.3 only */
+	int err;
+#endif
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	self = sk->protinfo.irda;
 	ASSERT(self != NULL, return -1;);
-
+#if 0 /* Linux 2.3 only */
+	err = irda_create(newsock, sk->protocol);
+	if (err)
+		return err;
+#endif
 	if (sock->state != SS_UNCONNECTED)
 		return -EINVAL;
 
 	if ((sk = sock->sk) == NULL)
 		return -EINVAL;
 
-	if (sk->type != SOCK_STREAM)
+	if ((sk->type != SOCK_STREAM) && (sk->type != SOCK_SEQPACKET) &&
+	    (sk->type != SOCK_DGRAM))
 		return -EOPNOTSUPP;
 
-	if (sk->state != TCP_LISTEN)
+	if (sk->state != TCP_LISTEN) 
 		return -EINVAL;
 
 	/*
@@ -538,7 +785,7 @@
 	/* Now attach up the new socket */
 	new->tsap = irttp_dup(self->tsap, new);
 	if (!new->tsap) {
-		DEBUG(0, __FUNCTION__ "(), dup failed!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), dup failed!\n");
 		return -1;
 	}
 		
@@ -584,9 +831,13 @@
 	struct irda_sock *self;
 	int err;
 
-	self = sk->protinfo.irda;
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
-	DEBUG(1, __FUNCTION__ "()\n");
+	self = sk->protinfo.irda;
+	
+	/* Don't allow connect for Ultra sockets */
+	if ((sk->type == SOCK_DGRAM) && (sk->protocol == IRDAPROTO_ULTRA))
+		return -ESOCKTNOSUPPORT;
 
 	if (sk->state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
 		sock->state = SS_CONNECTED;
@@ -607,18 +858,26 @@
 	if (addr_len != sizeof(struct sockaddr_irda))
 		return -EINVAL;
 
-	/* Check if user supplied the required destination device address */
-	if (!addr->sir_addr)
-		return -EINVAL;
-
-	self->daddr = addr->sir_addr;
-	DEBUG(1, __FUNCTION__ "(), daddr = %08x\n", self->daddr);
-
-	/* Query remote LM-IAS */
-	err = irda_find_lsap_sel(self, addr->sir_name);
-	if (err) {
-		DEBUG(0, __FUNCTION__ "(), connect failed!\n");
-		return err;
+	/* Check if user supplied any destination device address */
+	if (!addr->sir_addr) {
+		/* Try to find one suitable */
+		err = irda_discover_daddr_and_lsap_sel(self, addr->sir_name);
+		if (err) {
+			IRDA_DEBUG(0, __FUNCTION__ 
+				   "(), auto-connect failed!\n");
+			return -EINVAL;
+		}
+	} else {
+		/* Use the one provided by the user */
+		self->daddr = addr->sir_addr;
+		IRDA_DEBUG(1, __FUNCTION__ "(), daddr = %08x\n", self->daddr);
+		
+		/* Query remote LM-IAS */
+		err = irda_find_lsap_sel(self, addr->sir_name);
+		if (err) {
+			IRDA_DEBUG(0, __FUNCTION__ "(), connect failed!\n");
+			return err;
+		}
 	}
 
 	/* Check if we have opened a local TSAP */
@@ -634,7 +893,7 @@
 				    self->saddr, self->daddr, NULL, 
 				    self->max_sdu_size_rx, NULL);
 	if (err) {
-		DEBUG(0, __FUNCTION__ "(), connect failed!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), connect failed!\n");
 		return err;
 	}
 
@@ -678,12 +937,13 @@
 	struct sock *sk;
 	struct irda_sock *self;
 
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 	
 	/* Check for valid socket type */
 	switch (sock->type) {
-	case SOCK_STREAM:   /* FALLTHROUGH */
-	case SOCK_SEQPACKET:
+	case SOCK_STREAM:     /* For TTP connections with SAR disabled */
+	case SOCK_SEQPACKET:  /* For TTP connections with SAR enabled */
+	case SOCK_DGRAM:      /* For TTP Unitdata or LMP Ultra transfers */
 		break;
 	default:
 		return -ESOCKTNOSUPPORT;
@@ -700,13 +960,37 @@
 
 	self->sk = sk;
 	sk->protinfo.irda = self;
-
 	sock_init_data(sock, sk);
 
-	if (sock->type == SOCK_STREAM)
+	switch (sock->type) {
+	case SOCK_STREAM:
 		sock->ops = &irda_stream_ops;
-	else
-		sock->ops = &irda_dgram_ops;
+		self->max_sdu_size_rx = TTP_SAR_DISABLE;
+		break;
+	case SOCK_SEQPACKET:
+		sock->ops = &irda_seqpacket_ops;
+		self->max_sdu_size_rx = TTP_SAR_UNBOUND;
+		break;
+	case SOCK_DGRAM:
+		switch (protocol) {
+#ifdef CONFIG_IRDA_ULTRA
+		case IRDAPROTO_ULTRA:
+			sock->ops = &irda_ultra_ops;
+			break;
+#endif /* CONFIG_IRDA_ULTRA */
+		case IRDAPROTO_UNITDATA:
+			sock->ops = &irda_dgram_ops;
+			/* We let Unitdata conn. be like seqpack conn. */
+			self->max_sdu_size_rx = TTP_SAR_UNBOUND;
+			break;
+		default:
+			ERROR(__FUNCTION__ "(), protocol not supported!\n");
+			return -ESOCKTNOSUPPORT;
+		}
+		break;
+	default:
+		return -ESOCKTNOSUPPORT;
+	}		
 
 	sk->protocol = protocol;
 
@@ -714,8 +998,8 @@
 	self->ckey = irlmp_register_client(0, NULL, NULL);
 	self->mask = 0xffff;
 	self->rx_flow = self->tx_flow = FLOW_START;
-	self->max_sdu_size_rx = SAR_DISABLE; /* Default value */
 	self->nslots = DISCOVERY_DEFAULT_SLOTS;
+	self->daddr = DEV_ADDR_ANY;
 
 	/* Notify that we are using the irda module, so nobody removes it */
 	irda_mod_inc_use_count();
@@ -731,7 +1015,7 @@
  */
 void irda_destroy_socket(struct irda_sock *self)
 {
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 
@@ -741,14 +1025,22 @@
 
 	/* Unregister with LM-IAS */
 	if (self->ias_obj)
-		irias_delete_object(self->ias_obj->name);
+		irias_delete_object(self->ias_obj);
+
+	if (self->iriap) 
+		iriap_close(self->iriap);
 
 	if (self->tsap) {
 		irttp_disconnect_request(self->tsap, NULL, P_NORMAL);
 		irttp_close_tsap(self->tsap);
 		self->tsap = NULL;
 	}
-
+#ifdef CONFIG_IRDA_ULTRA
+	if (self->lsap) {
+		irlmp_close_lsap(self->lsap);
+		self->lsap = NULL;
+	}
+#endif /* CONFIG_IRDA_ULTRA */
 	kfree(self);
 
 	/* Notify that we are not using the irda module anymore */
@@ -767,7 +1059,7 @@
 {
 	struct sock *sk = sock->sk;
 	
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
         if (sk == NULL) 
 		return 0;
@@ -788,20 +1080,20 @@
 /*
  * Function irda_sendmsg (sock, msg, len, scm)
  *
- *    Send message down to TinyTP
- *
+ *    Send message down to TinyTP. This function is used for both STREAM and
+ *    SEQPACK services. This is possible since it forces the client to 
+ *    fragment the message if necessary
  */
 static int irda_sendmsg(struct socket *sock, struct msghdr *msg, int len, 
 			struct scm_cookie *scm)
 {
 	struct sock *sk = sock->sk;
-/* 	struct sockaddr_irda *addr = (struct sockaddr_irda *) msg->msg_name; */
 	struct irda_sock *self;
 	struct sk_buff *skb;
 	unsigned char *asmptr;
 	int err;
 
-	DEBUG(4, __FUNCTION__ "(), len=%d\n", len);
+	IRDA_DEBUG(4, __FUNCTION__ "(), len=%d\n", len);
 
 	if (msg->msg_flags & ~MSG_DONTWAIT)
 		return -EINVAL;
@@ -811,12 +1103,15 @@
 		return -EPIPE;
 	}
 
+	if (sk->state != TCP_ESTABLISHED)
+		return -ENOTCONN;
+
 	self = sk->protinfo.irda;
 	ASSERT(self != NULL, return -1;);
 
 	/* Check if IrTTP is wants us to slow down */
 	while (self->tx_flow == FLOW_STOP) {
-		DEBUG(2, __FUNCTION__ "(), IrTTP is busy, going to sleep!\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), IrTTP is busy, going to sleep!\n");
 		interruptible_sleep_on(sk->sleep);
 		
 		/* Check if we are still connected */
@@ -826,9 +1121,9 @@
 
 	/* Check that we don't send out to big frames */
 	if (len > self->max_data_size) {
-		DEBUG(0, __FUNCTION__ "(), Warning to much data! "
-		      "Chopping frame from %d to %d bytes!\n", len, 
-		      self->max_data_size);
+		IRDA_DEBUG(2, __FUNCTION__ 
+			   "(), Chopping frame from %d to %d bytes!\n", len, 
+			   self->max_data_size);
 		len = self->max_data_size;
 	}
 
@@ -839,7 +1134,6 @@
 
 	skb_reserve(skb, self->max_header_size);
 	
-	DEBUG(4, __FUNCTION__ "(), appending user data\n");
 	asmptr = skb->h.raw = skb_put(skb, len);
 	memcpy_fromiovec(asmptr, msg->msg_iov, len);
 
@@ -849,17 +1143,18 @@
 	 */
 	err = irttp_data_request(self->tsap, skb);
 	if (err) {
-		DEBUG(0, __FUNCTION__ "(), err=%d\n", err);
+		IRDA_DEBUG(0, __FUNCTION__ "(), err=%d\n", err);
 		return err;
 	}
+	/* Tell client how much data we actually sent */
 	return len;
 }
 
 /*
- * Function irda_recvmsg (sock, msg, size, flags, scm)
- *
- *    Try to receive message and copy it to user
+ * Function irda_recvmsg_dgram (sock, msg, size, flags, scm)
  *
+ *    Try to receive message and copy it to user. The frame is discarded
+ *    after being read, regardless of how much the user actually read
  */
 static int irda_recvmsg_dgram(struct socket *sock, struct msghdr *msg, 
 			      int size, int flags, struct scm_cookie *scm)
@@ -869,7 +1164,7 @@
 	struct sk_buff *skb;
 	int copied, err;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	self = sk->protinfo.irda;
 	ASSERT(self != NULL, return -1;);
@@ -883,6 +1178,9 @@
 	copied     = skb->len;
 	
 	if (copied > size) {
+		IRDA_DEBUG(2, __FUNCTION__ 
+			   "(), Received truncated frame (%d < %d)!\n",
+			   copied, size);
 		copied = size;
 		msg->msg_flags |= MSG_TRUNC;
 	}
@@ -898,7 +1196,7 @@
 	 */
 	if (self->rx_flow == FLOW_STOP) {
 		if ((atomic_read(&sk->rmem_alloc) << 2) <= sk->rcvbuf) {
-			DEBUG(2, __FUNCTION__ "(), Starting IrTTP\n");
+			IRDA_DEBUG(2, __FUNCTION__ "(), Starting IrTTP\n");
 			self->rx_flow = FLOW_START;
 			irttp_flow_request(self->tsap, FLOW_START);
 		}
@@ -937,7 +1235,7 @@
 	int copied = 0;
 	int target = 1;
 
-	DEBUG(3, __FUNCTION__ "()\n");
+	IRDA_DEBUG(3, __FUNCTION__ "()\n");
 
 	self = sk->protinfo.irda;
 	ASSERT(self != NULL, return -1;);
@@ -951,14 +1249,8 @@
 	if (flags & MSG_WAITALL)
 		target = size;
 		
-		
 	msg->msg_namelen = 0;
 
-	/* Lock the socket to prevent queue disordering
-	 * while sleeps in memcpy_tomsg
-	 */
-/* 	down(&self->readsem); */
-
 	do {
 		int chunk;
 		struct sk_buff *skb;
@@ -973,32 +1265,20 @@
 			 */
 			
 			if (sk->err) {
-				/* up(&self->readsem); */
 				return sock_error(sk);
 			}
 
 			if (sk->shutdown & RCV_SHUTDOWN)
 				break;
 
-		/* 	up(&self->readsem); */
-
 			if (noblock)
 				return -EAGAIN;
 			irda_data_wait(sk);
 			if (signal_pending(current))
 				return -ERESTARTSYS;
-		/* 	down(&self->readsem); */
 			continue;
 		}
 
-		/* Never glue messages from different writers */
-/* 		if (check_creds && */
-/* 		    memcmp(UNIXCREDS(skb), &scm->creds, sizeof(scm->creds)) != 0) */
-/* 		{ */
-/* 			skb_queue_head(&sk->receive_queue, skb); */
-/* 			break; */
-/* 		} */
-
 		chunk = min(skb->len, size);
 		if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) {
 			skb_queue_head(&sk->receive_queue, skb);
@@ -1009,33 +1289,20 @@
 		copied += chunk;
 		size -= chunk;
 
- 		/* Copy credentials */
-/* 		scm->creds = *UNIXCREDS(skb); */
-/* 		check_creds = 1; */
-
 		/* Mark read part of skb as used */
 		if (!(flags & MSG_PEEK)) {
 			skb_pull(skb, chunk);
 
-/* 			if (UNIXCB(skb).fp) */
-/* 				unix_detach_fds(scm, skb); */
-
 			/* put the skb back if we didn't use it up.. */
 			if (skb->len) {
-				DEBUG(1, __FUNCTION__ "(), back on q!\n");
+				IRDA_DEBUG(1, __FUNCTION__ "(), back on q!\n");
 				skb_queue_head(&sk->receive_queue, skb);
 				break;
 			}
 
-			kfree_skb(skb);
-			
-/* 			if (scm->fp) */
-/* 				break; */
+			kfree_skb(skb);			
 		} else {
-			DEBUG(0, __FUNCTION__ "() questionable!?\n");
-			/* It is questionable, see note in unix_dgram_recvmsg. */
-/* 			if (UNIXCB(skb).fp) */
-/* 				scm->fp = scm_fp_dup(UNIXCB(skb).fp); */
+			IRDA_DEBUG(0, __FUNCTION__ "() questionable!?\n");
 
 			/* put message back and return */
 			skb_queue_head(&sk->receive_queue, skb);
@@ -1051,29 +1318,171 @@
 	 */
 	if (self->rx_flow == FLOW_STOP) {
 		if ((atomic_read(&sk->rmem_alloc) << 2) <= sk->rcvbuf) {
-			DEBUG(2, __FUNCTION__ "(), Starting IrTTP\n");
+			IRDA_DEBUG(2, __FUNCTION__ "(), Starting IrTTP\n");
 			self->rx_flow = FLOW_START;
 			irttp_flow_request(self->tsap, FLOW_START);
 		}
 	}
 
-	/* up(&self->readsem); */
-
 	return copied;
 }
 
 /*
+ * Function irda_sendmsg_dgram (sock, msg, len, scm)
+ *
+ *    Send message down to TinyTP for the unreliable sequenced
+ *    packet service...
+ *
+ */
+static int irda_sendmsg_dgram(struct socket *sock, struct msghdr *msg,
+			      int len, struct scm_cookie *scm)
+{
+	struct sock *sk = sock->sk;
+	struct irda_sock *self;
+	struct sk_buff *skb;
+	unsigned char *asmptr;
+	int err;
+	
+	IRDA_DEBUG(4, __FUNCTION__ "(), len=%d\n", len);
+	
+	if (msg->msg_flags & ~MSG_DONTWAIT)
+		return -EINVAL;
+
+	if (sk->shutdown & SEND_SHUTDOWN) {
+		send_sig(SIGPIPE, current, 0);
+		return -EPIPE;
+	}
+
+	if (sk->state != TCP_ESTABLISHED)
+		return -ENOTCONN;
+
+	self = sk->protinfo.irda;
+	ASSERT(self != NULL, return -1;);
+
+	/*  
+	 * Check that we don't send out to big frames. This is an unreliable 
+	 * service, so we have no fragmentation and no coalescence 
+	 */
+	if (len > self->max_data_size) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), Warning to much data! "
+			   "Chopping frame from %d to %d bytes!\n", len, 
+			   self->max_data_size);
+		len = self->max_data_size;
+	}
+
+	skb = sock_alloc_send_skb(sk, len + self->max_header_size, 0, 
+				  msg->msg_flags & MSG_DONTWAIT, &err);
+	if (!skb)
+		return -ENOBUFS;
+
+	skb_reserve(skb, self->max_header_size);
+	
+	IRDA_DEBUG(4, __FUNCTION__ "(), appending user data\n");
+	asmptr = skb->h.raw = skb_put(skb, len);
+	memcpy_fromiovec(asmptr, msg->msg_iov, len);
+
+	/* 
+	 * Just send the message to TinyTP, and let it deal with possible 
+	 * errors. No need to duplicate all that here
+	 */
+	err = irttp_udata_request(self->tsap, skb);
+	if (err) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), err=%d\n", err);
+		return err;
+	}
+	return len;
+}
+
+/*
+ * Function irda_sendmsg_ultra (sock, msg, len, scm)
+ *
+ *    Send message down to IrLMP for the unreliable Ultra
+ *    packet service...
+ */
+#ifdef CONFIG_IRDA_ULTRA
+static int irda_sendmsg_ultra(struct socket *sock, struct msghdr *msg,
+			      int len, struct scm_cookie *scm)
+{
+	struct sock *sk = sock->sk;
+	struct irda_sock *self;
+	struct sk_buff *skb;
+	unsigned char *asmptr;
+	int err;
+	
+	IRDA_DEBUG(4, __FUNCTION__ "(), len=%d\n", len);
+	
+	if (msg->msg_flags & ~MSG_DONTWAIT)
+		return -EINVAL;
+
+	if (sk->shutdown & SEND_SHUTDOWN) {
+		send_sig(SIGPIPE, current, 0);
+		return -EPIPE;
+	}
+
+	self = sk->protinfo.irda;
+	ASSERT(self != NULL, return -1;);
+
+	/*  
+	 * Check that we don't send out to big frames. This is an unreliable 
+	 * service, so we have no fragmentation and no coalescence 
+	 */
+	if (len > self->max_data_size) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), Warning to much data! "
+			   "Chopping frame from %d to %d bytes!\n", len, 
+			   self->max_data_size);
+		len = self->max_data_size;
+	}
+
+	skb = sock_alloc_send_skb(sk, len + self->max_header_size, 0, 
+				  msg->msg_flags & MSG_DONTWAIT, &err);
+	if (!skb)
+		return -ENOBUFS;
+
+	skb_reserve(skb, self->max_header_size);
+	
+	IRDA_DEBUG(4, __FUNCTION__ "(), appending user data\n");
+	asmptr = skb->h.raw = skb_put(skb, len);
+	memcpy_fromiovec(asmptr, msg->msg_iov, len);
+
+	err = irlmp_connless_data_request(self->lsap, skb);
+	if (err) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), err=%d\n", err);
+		return err;
+	}
+	return len;
+}
+#endif /* CONFIG_IRDA_ULTRA */
+
+/*
  * Function irda_shutdown (sk, how)
  *
  *    
  *
  */
-static int irda_shutdown( struct socket *sk, int how)
+static int irda_shutdown(struct socket *sock, int how)
 {
-	DEBUG( 0, __FUNCTION__ "()\n");
+	struct irda_sock *self;
+	struct sock *sk = sock->sk;
 
-        /* FIXME - generate DM and RNR states */
-        return -EOPNOTSUPP;
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	self = sk->protinfo.irda;
+	ASSERT(self != NULL, return -1;);
+
+	sk->state       = TCP_CLOSE;
+	sk->shutdown   |= SEND_SHUTDOWN;
+	sk->state_change(sk);
+
+	if (self->iriap) 
+		iriap_close(self->iriap);
+	
+	if (self->tsap) {
+		irttp_disconnect_request(self->tsap, NULL, P_NORMAL);
+		irttp_close_tsap(self->tsap);
+		self->tsap = NULL;
+	}
+
+        return 0;
 }
 
 /*
@@ -1088,7 +1497,7 @@
 	struct sock *sk = sock->sk;
 	unsigned int mask;
 
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	poll_wait(file, sk->sleep, wait);
 	mask = 0;
@@ -1100,9 +1509,10 @@
 		mask |= POLLHUP;
 
 	/* readable? */
-	if (!skb_queue_empty(&sk->receive_queue))
+	if (!skb_queue_empty(&sk->receive_queue)) {
+		IRDA_DEBUG(4, "Socket is readable\n");
 		mask |= POLLIN | POLLRDNORM;
-
+	}
 	/* Connection-based need to check for termination and startup */
 	if (sk->type == SOCK_STREAM && sk->state==TCP_CLOSE)
 		mask |= POLLHUP;
@@ -1127,7 +1537,7 @@
 {
 	struct sock *sk = sock->sk;
 
-	DEBUG(4, __FUNCTION__ "(), cmd=%#x\n", cmd);
+	IRDA_DEBUG(4, __FUNCTION__ "(), cmd=%#x\n", cmd);
 	
 	switch (cmd) {
 	case TIOCOUTQ: {
@@ -1155,7 +1565,8 @@
 		if (sk != NULL) {
 			if (sk->stamp.tv_sec == 0)
 				return -ENOENT;
-			if (copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)))
+			if (copy_to_user((void *)arg, &sk->stamp, 
+					 sizeof(struct timeval)))
 				return -EFAULT;
 			return 0;
 		}
@@ -1171,10 +1582,9 @@
 	case SIOCSIFNETMASK:
 	case SIOCGIFMETRIC:
 	case SIOCSIFMETRIC:
-		return -EINVAL;
-		
+		return -EINVAL;		
 	default:
-		DEBUG(1, __FUNCTION__ "(), doing device ioctl!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), doing device ioctl!\n");
 		return dev_ioctl(cmd, (void *) arg);
 	}
 
@@ -1193,29 +1603,110 @@
 {
  	struct sock *sk = sock->sk;
 	struct irda_sock *self;
+	struct irda_ias_set	ias_opt;
+	struct ias_object      *ias_obj;
 	int opt;
 	
-	DEBUG(0, __FUNCTION__ "()\n");
-
 	self = sk->protinfo.irda;
 	ASSERT(self != NULL, return -1;);
 
 	if (level != SOL_IRLMP)
 		return -ENOPROTOOPT;
+		
+	switch (optname) {
+	case IRLMP_IAS_SET:
+		if (optlen != sizeof(struct irda_ias_set))
+			return -EINVAL;
 	
-	if (optlen < sizeof(int))
-		return -EINVAL;
+		/* Copy query to the driver. */
+		if (copy_from_user(&ias_opt, (char *)optval, optlen))
+		  	return -EFAULT;
+
+		/* Find the object we target */
+		ias_obj = irias_find_object(ias_opt.irda_class_name);
+		if(ias_obj == (struct ias_object *) NULL) {
+			/* Create a new object */
+			ias_obj = irias_new_object(ias_opt.irda_class_name,
+						   jiffies);
+		}
+
+		/* Do we have it already ? */
+		if(irias_find_attrib(ias_obj, ias_opt.irda_attrib_name))
+			return -EINVAL;
+
+		/* Look at the type */
+		switch(ias_opt.irda_attrib_type) {
+		case IAS_INTEGER:
+			/* Add an integer attribute */
+			irias_add_integer_attrib(ias_obj,
+						 ias_opt.irda_attrib_name, 
+					 ias_opt.attribute.irda_attrib_int);
+			break;
+		case IAS_OCT_SEQ:
+			/* Check length */
+			if(ias_opt.attribute.irda_attrib_octet_seq.len >
+			   IAS_MAX_OCTET_STRING)
+				return -EINVAL;
+			/* Add an octet sequence attribute */
+			irias_add_octseq_attrib(
+			      ias_obj,
+			      ias_opt.irda_attrib_name, 
+			      ias_opt.attribute.irda_attrib_octet_seq.octet_seq,
+			      ias_opt.attribute.irda_attrib_octet_seq.len);
+			break;
+		case IAS_STRING:
+			/* Should check charset & co */
+			/* Check length */
+			if(ias_opt.attribute.irda_attrib_string.len >
+			   IAS_MAX_STRING)
+				return -EINVAL;
+			/* NULL terminate the string (avoid troubles) */
+			ias_opt.attribute.irda_attrib_string.string[ias_opt.attribute.irda_attrib_string.len] = '\0';
+			/* Add a string attribute */
+			irias_add_string_attrib(
+				ias_obj,
+				ias_opt.irda_attrib_name, 
+				ias_opt.attribute.irda_attrib_string.string);
+			break;
+		default :
+			return -EINVAL;
+		}
+		irias_insert_object(ias_obj);
+		break;
+
+		IRDA_DEBUG(0, __FUNCTION__ "(), sorry not impl. yet!\n");
+		return -ENOPROTOOPT;
+	case IRLMP_MAX_SDU_SIZE:
+		if (optlen < sizeof(int))
+			return -EINVAL;
 	
-	if (get_user(opt, (int *)optval))
-		return -EFAULT;
+		if (get_user(opt, (int *)optval))
+			return -EFAULT;
+		
+		/* Only possible for a seqpacket service (TTP with SAR) */
+		if (sk->type != SOCK_SEQPACKET) {
+			IRDA_DEBUG(2, __FUNCTION__ 
+				   "(), setting max_sdu_size = %d\n", opt);
+			self->max_sdu_size_rx = opt;
+		} else {
+			WARNING(__FUNCTION__ 
+				"(), not allowed to set MAXSDUSIZE for this "
+				"socket type!\n");
+			return -ENOPROTOOPT;
+		}
+		break;
+	case IRLMP_HINTS_SET:
+		if (optlen < sizeof(int))
+			return -EINVAL;
 	
-	switch (optname) {
-	case IRLMP_IAS_SET:
-		DEBUG(0, __FUNCTION__ "(), sorry not impl. yet!\n");
-		return 0;
-	case IRTTP_MAX_SDU_SIZE:
-		DEBUG(0, __FUNCTION__ "(), setting max_sdu_size = %d\n", opt);
-		self->max_sdu_size_rx = opt;
+		if (get_user(opt, (int *)optval))
+			return -EFAULT;
+
+		/* Unregister any old registration */
+		if (self->skey)
+			irlmp_unregister_service(self->skey);
+
+		self->skey = irlmp_register_service((__u16) opt);
 		break;
 	default:
 		return -ENOPROTOOPT;
@@ -1223,6 +1714,104 @@
 	return 0;
 }
 
+ /*
+ * Function irda_simple_getvalue_confirm (obj_id, value, priv)
+ *
+ *    Got answer from remote LM-IAS, just copy object to requester...
+ *
+ * Note : duplicate from above, but we need our own version that
+ * doesn't touch the dtsap_sel and save the full value structure...
+ */
+static void irda_simple_getvalue_confirm(int result, __u16 obj_id, 
+					  struct ias_value *value, void *priv)
+{
+	struct irda_sock *self;
+	
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(priv != NULL, return;);
+	self = (struct irda_sock *) priv;
+	
+	if (!self) {
+		WARNING(__FUNCTION__ "(), lost myself!\n");
+		return;
+	}
+
+	/* We probably don't need to make any more queries */
+	iriap_close(self->iriap);
+	self->iriap = NULL;
+
+	/* Check if request succeeded */
+	if (result != IAS_SUCCESS) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), IAS query failed!\n");
+
+		self->errno = -EHOSTUNREACH;
+
+		/* Wake up any processes waiting for result */
+		wake_up_interruptible(&self->ias_wait);
+
+		return;
+	}
+
+	/* Clone the object (so the requester can free it) */
+	self->ias_result = kmalloc(sizeof(struct ias_value), GFP_ATOMIC);
+	memcpy(self->ias_result, value, sizeof(struct ias_value));
+	irias_delete_value(value);
+
+	self->errno = 0;
+
+	/* Wake up any processes waiting for result */
+	wake_up_interruptible(&self->ias_wait);
+}
+
+/*
+ * Function irda_extract_ias_value(ias_opt, ias_value)
+ *
+ *    Translate internal IAS value structure to the user space representation
+ *
+ * The external representation of IAS values, as we exchange them with
+ * user space program is quite different from the internal representation,
+ * as stored in the IAS database (because we need a flat structure for
+ * crossing kernel boundary).
+ * This function transform the former in the latter. We also check
+ * that the value type is valid.
+ */
+static int irda_extract_ias_value(struct irda_ias_set *ias_opt,
+				  struct ias_value *ias_value)
+{
+	/* Look at the type */
+	switch (ias_value->type) {
+	case IAS_INTEGER:
+		/* Copy the integer */
+		ias_opt->attribute.irda_attrib_int = ias_value->t.integer;
+		break;
+	case IAS_OCT_SEQ:
+		/* Set length */
+		ias_opt->attribute.irda_attrib_octet_seq.len = ias_value->len;
+		/* Copy over */
+		memcpy(ias_opt->attribute.irda_attrib_octet_seq.octet_seq,
+		       ias_value->t.oct_seq, ias_value->len);
+		break;
+	case IAS_STRING:
+		/* Set length */
+		ias_opt->attribute.irda_attrib_string.len = ias_value->len;
+		ias_opt->attribute.irda_attrib_string.charset = ias_value->charset;
+		/* Copy over */
+		memcpy(ias_opt->attribute.irda_attrib_string.string,
+		       ias_value->t.string, ias_value->len);
+		/* NULL terminate the string (avoid troubles) */
+		ias_opt->attribute.irda_attrib_string.string[ias_value->len] = '\0';
+		break;
+	default :
+		return -EINVAL;
+	}
+	
+	/* Copy type over */
+	ias_opt->irda_attrib_type = ias_value->type;
+	
+	return 0;
+}
+
 /*
  * Function irda_getsockopt (sock, level, optname, optval, optlen)
  *
@@ -1234,15 +1823,16 @@
 {
 	struct sock *sk = sock->sk;
 	struct irda_sock *self;
-	struct irda_device_list *list;
-	__u8 optbuf[sizeof(struct irda_device_list) +
-		   sizeof(struct irda_device_info)*10];
+	struct irda_device_list list;
+	struct irda_device_info *info;
 	discovery_t *discovery;
+	struct irda_ias_set	ias_opt;	/* IAS get/query params */
+	struct ias_object *	ias_obj;	/* Object in IAS */
+	struct ias_attrib *	ias_attr;	/* Attribute in IAS object */
 	int val = 0;
 	int len = 0;
-	int i = 0;
-
-	DEBUG(1, __FUNCTION__ "()\n");
+	int err;
+	int offset, total;
 
 	self = sk->protinfo.irda;
 
@@ -1254,26 +1844,26 @@
 
 	switch (optname) {
 	case IRLMP_ENUMDEVICES:
-		DEBUG(1, __FUNCTION__ "(), IRLMP_ENUMDEVICES\n");
-		
 		/* Tell IrLMP we want to be notified */
 		irlmp_update_client(self->ckey, self->mask, NULL, 
 				    irda_discovery_indication);
-
+		
 		/* Do some discovery */
 		irlmp_discovery_request(self->nslots);
+		
+		/* Check if the we got some results */
+		if (!cachelog)
+			return -EAGAIN;
+
+		info = &list.dev[0];
+
+		/* Offset to first device entry */
+		offset = sizeof(struct irda_device_list) - 
+			sizeof(struct irda_device_info);
 
-		/* Devices my be discovered already */
-		if (!cachelog) {
-			DEBUG(2, __FUNCTION__ "(), no log!\n");
-
-			/* Sleep until device(s) discovered */
-			interruptible_sleep_on(&discovery_wait);
-			if (!cachelog)
-				return -1;
-		}
+		total = offset;   /* Initialized to size of the device list */
+		list.len = 0;     /* Initialize lenght of list */
 
-		list = (struct irda_device_list *) optbuf;
 		/* 
 		 * Now, check all discovered devices (if any), and notify
 		 * client only about the services that the client is
@@ -1283,35 +1873,41 @@
 		while (discovery != NULL) {
 			/* Mask out the ones we don't want */
 			if (discovery->hints.word & self->mask) {
-				/* Copy discovery information */
-				list->dev[i].saddr = discovery->saddr;
-				list->dev[i].daddr = discovery->daddr;
-				list->dev[i].charset = discovery->charset;
-				list->dev[i].hints[0] = discovery->hints.byte[0];
-				list->dev[i].hints[1] = discovery->hints.byte[1];
-				strncpy(list->dev[i].info, discovery->info, 22);
-				if (++i >= 10)
+				/* Check if room for this device entry */
+				if (len-total<sizeof(struct irda_device_info))
 					break;
+
+				/* Copy discovery information */
+				info->saddr = discovery->saddr;
+				info->daddr = discovery->daddr;
+				info->charset = discovery->charset;
+				info->hints[0] = discovery->hints.byte[0];
+				info->hints[1] = discovery->hints.byte[1];
+				strncpy(info->info, discovery->nickname,
+					NICKNAME_MAX_LEN);
+
+				if (copy_to_user(optval+total, info, 
+						 sizeof(struct irda_device_info)))
+					return -EFAULT;
+				list.len++;
+				total += sizeof(struct irda_device_info);
 			}
 			discovery = (discovery_t *) hashbin_get_next(cachelog);
 		}
 		cachelog = NULL;
 
-		list->len = i;
-		len = sizeof(struct irda_device_list) +
-			sizeof(struct irda_device_info) * i;
-
-		DEBUG(1, __FUNCTION__ "(), len=%d, i=%d\n", len, i);
-
-		if (put_user(len, optlen))
+		/* Write total number of bytes used back to client */
+		if (put_user(total, optlen))
 			return -EFAULT;
-		
-		if (copy_to_user(optval, &optbuf, len))
+
+		/* Write total list length back to client */
+		if (copy_to_user(optval, &list, 
+				 sizeof(struct irda_device_list) -
+				 sizeof(struct irda_device_info)))
 			return -EFAULT;
 		break;
-	case IRTTP_MAX_SDU_SIZE:
+	case IRLMP_MAX_SDU_SIZE:
 		val = self->max_data_size;
-		DEBUG(0, __FUNCTION__ "(), getting max_sdu_size = %d\n", val);
 		len = sizeof(int);
 		if (put_user(len, optlen))
 			return -EFAULT;
@@ -1319,10 +1915,95 @@
 		if (copy_to_user(optval, &val, len))
 			return -EFAULT;
 		break;
+	case IRLMP_IAS_GET:
+		/* The user want an object from our local IAS database.
+		 * We just need to query the IAS and return the value
+		 * that we found */
+
+		/* Check that the user has allocated the right space for us */
+		if (len != sizeof(ias_opt))
+			return -EINVAL;
+
+		/* Copy query to the driver. */
+		if (copy_from_user((char *) &ias_opt, (char *)optval, len))
+		  	return -EFAULT;
+
+		/* Find the object we target */
+		ias_obj = irias_find_object(ias_opt.irda_class_name);
+		if(ias_obj == (struct ias_object *) NULL)
+			return -EINVAL;
+
+		/* Find the attribute (in the object) we target */
+		ias_attr = irias_find_attrib(ias_obj,
+					     ias_opt.irda_attrib_name); 
+		if(ias_attr == (struct ias_attrib *) NULL)
+			return -EINVAL;
+
+		/* Translate from internal to user structure */
+		err = irda_extract_ias_value(&ias_opt, ias_attr->value);
+		if(err)
+			return err;
+
+		/* Copy reply to the user */
+		if (copy_to_user((char *)optval, (char *) &ias_opt,
+				 sizeof(ias_opt)))
+		  	return -EFAULT;
+		/* Note : don't need to put optlen, we checked it */
+		break;
+	case IRLMP_IAS_QUERY:
+		/* The user want an object from a remote IAS database.
+		 * We need to use IAP to query the remote database and
+		 * then wait for the answer to come back. */
+
+		/* Check that the user has allocated the right space for us */
+		if (len != sizeof(ias_opt))
+			return -EINVAL;
+
+		/* Copy query to the driver. */
+		if (copy_from_user((char *) &ias_opt, (char *)optval, len))
+		  	return -EFAULT;
+
+		/* Check that we can proceed with IAP */
+		if (self->iriap) {
+			WARNING(__FUNCTION__
+				"(), busy with a previous query\n");
+			return -EBUSY;
+		}
+
+		self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,
+					 irda_simple_getvalue_confirm);
+
+		/* Treat unexpected signals as disconnect */
+		self->errno = -EHOSTUNREACH;
+
+		/* Query remote LM-IAS */
+		iriap_getvaluebyclass_request(self->iriap, 
+					      self->saddr, self->daddr,
+					      ias_opt.irda_class_name,
+					      ias_opt.irda_attrib_name);
+		/* Wait for answer */
+		interruptible_sleep_on(&self->ias_wait);
+		/* Check what happened */
+		if (self->errno)
+			return (self->errno);
+
+		/* Translate from internal to user structure */
+		err = irda_extract_ias_value(&ias_opt, self->ias_result);
+		if (self->ias_result)
+			kfree(self->ias_result);
+		if (err)
+			return err;
+
+		/* Copy reply to the user */
+		if (copy_to_user((char *)optval, (char *) &ias_opt,
+				 sizeof(ias_opt)))
+		  	return -EFAULT;
+		/* Note : don't need to put optlen, we checked it */
+		break;
 	default:
 		return -ENOPROTOOPT;
 	}
-
+	
 	return 0;
 }
 
@@ -1350,12 +2031,12 @@
 	irda_getsockopt,
 	sock_no_fcntl,
 	irda_sendmsg,
-	irda_recvmsg_stream
+	irda_recvmsg_stream,
 };
 
-static struct proto_ops irda_dgram_ops = {
+static struct proto_ops irda_seqpacket_ops = {
 	PF_IRDA,
-	
+       
 	sock_no_dup,
 	irda_release,
 	irda_bind,
@@ -1371,13 +2052,57 @@
 	irda_getsockopt,
 	sock_no_fcntl,
 	irda_sendmsg,
-	irda_recvmsg_dgram
+	irda_recvmsg_dgram,
+};
+
+static struct proto_ops irda_dgram_ops = {
+	PF_IRDA,
+       
+	sock_no_dup,
+	irda_release,
+	irda_bind,
+	irda_connect,
+	sock_no_socketpair,
+	irda_accept,
+	irda_getname,
+	datagram_poll,
+	irda_ioctl,
+	irda_listen,
+	irda_shutdown,
+	irda_setsockopt,
+	irda_getsockopt,
+	sock_no_fcntl,
+	irda_sendmsg_dgram,
+	irda_recvmsg_dgram,
 };
 
+#ifdef CONFIG_IRDA_ULTRA
+static struct proto_ops irda_ultra_ops = {
+	PF_IRDA,
+       
+	sock_no_dup,
+	irda_release,
+	irda_bind,
+	sock_no_connect,
+	sock_no_socketpair,
+	sock_no_accept,
+	irda_getname,
+	datagram_poll,
+	irda_ioctl,
+	sock_no_listen,
+	irda_shutdown,
+	irda_setsockopt,
+	irda_getsockopt,
+	sock_no_fcntl,
+	irda_sendmsg_ultra,
+	irda_recvmsg_dgram,
+};
+#endif /* CONFIG_IRDA_ULTRA */
+
 /*
  * Function irda_device_event (this, event, ptr)
  *
- *    
+ *    Called when a device is taken up or down
  *
  */
 static int irda_device_event(struct notifier_block *this, unsigned long event,
@@ -1385,19 +2110,17 @@
 {
 	struct device *dev = (struct device *) ptr;
 	
-	DEBUG(3, __FUNCTION__ "()\n");
-	
         /* Reject non IrDA devices */
 	if (dev->type != ARPHRD_IRDA) 
 		return NOTIFY_DONE;
 	
         switch (event) {
 	case NETDEV_UP:
-		DEBUG(3, __FUNCTION__ "(), NETDEV_UP\n");
+		IRDA_DEBUG(3, __FUNCTION__ "(), NETDEV_UP\n");
 		/* irda_dev_device_up(dev); */
 		break;
 	case NETDEV_DOWN:
-		DEBUG(3, __FUNCTION__ "(), NETDEV_DOWN\n");
+		IRDA_DEBUG(3, __FUNCTION__ "(), NETDEV_DOWN\n");
 		/* irda_kill_by_device(dev); */
 		/* irda_rt_device_down(dev); */
 		/* irda_dev_device_down(dev); */
@@ -1430,16 +2153,14 @@
  *    Initialize IrDA protocol layer
  *
  */
-__initfunc(void irda_proto_init(struct net_proto *pro))
+void __init irda_proto_init(struct net_proto *pro)
 {
-	DEBUG( 4, __FUNCTION__ "\n");
-
 	sock_register(&irda_family_ops);
 
 	irda_packet_type.type = htons(ETH_P_IRDA);
         dev_add_pack(&irda_packet_type);
 
-	register_netdevice_notifier( &irda_dev_notifier);
+	register_netdevice_notifier(&irda_dev_notifier);
 
 	irda_init();
 }
@@ -1453,8 +2174,6 @@
 #ifdef MODULE
 void irda_proto_cleanup(void)
 {
-	DEBUG( 4, __FUNCTION__ "\n");
-
 	irda_packet_type.type = htons(ETH_P_IRDA);
         dev_remove_pack(&irda_packet_type);
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/compressors/Config.in linux.15p9/net/irda/compressors/Config.in
--- linux.vanilla/net/irda/compressors/Config.in	Thu Dec 17 17:01:03 1998
+++ linux.15p9/net/irda/compressors/Config.in	Tue Jan 18 01:08:18 2000
@@ -1,9 +1,11 @@
 
-bool 'IrLAP compression' CONFIG_IRDA_COMPRESSION
+bool '  IrLAP compression' CONFIG_IRDA_COMPRESSION
 
-if [ "$CONFIG_IRDA_COMPRESSION" != "n" ] ; then
-        comment '   IrDA compressors'
-        dep_tristate '   Deflate compression (experimental)' CONFIG_IRDA_DEFLATE $CONFIG_IRDA
-#	tristate '   BZIP2 compression' CONFIG_IRDA_BZIP2
-#	tristate '   BSD compression' CONFIG_IRDA_BSD
+if [ "$CONFIG_IRDA_COMPRESSION" != "n" ]; then
+   comment '    IrDA compressors'
+   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+      dep_tristate '    Deflate compression (EXPERIMENTAL)' CONFIG_IRDA_DEFLATE $CONFIG_IRDA
+   fi
+#   tristate '    BZIP2 compression' CONFIG_IRDA_BZIP2
+#   tristate '    BSD compression' CONFIG_IRDA_BSD
 fi
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/compressors/irda_deflate.c linux.15p9/net/irda/compressors/irda_deflate.c
--- linux.vanilla/net/irda/compressors/irda_deflate.c	Fri Dec 18 16:06:39 1998
+++ linux.15p9/net/irda/compressors/irda_deflate.c	Tue Jan 18 01:08:18 2000
@@ -54,7 +54,6 @@
 #include <linux/malloc.h>
 #include <linux/vmalloc.h> 
 #include <linux/errno.h>
-#include <linux/sched.h>	/* to get the struct task_struct */
 #include <linux/string.h>	/* used in new tty drivers */
 #include <linux/signal.h>	/* used in new tty drivers */
 
@@ -595,7 +594,7 @@
 	z_comp_stats,		/* decomp_stat */
 };
 
-__initfunc(int irda_deflate_init(void))
+int __init irda_deflate_init(void)
 {
         int answer = irda_register_compressor ( &irda_deflate);
         if (answer == 0)
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/discovery.c linux.15p9/net/irda/discovery.c
--- linux.vanilla/net/irda/discovery.c	Sat Aug 14 02:26:52 1999
+++ linux.15p9/net/irda/discovery.c	Tue Jan 18 01:08:18 2000
@@ -6,8 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Apr  6 15:33:50 1999
- * Modified at:   Fri May 28 20:46:38 1999
+ * Modified at:   Sat Oct  9 17:11:31 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * Modified at:   Fri May 28  3:11 CST 1999
+ * Modified by:   Horst von Brand <vonbrand@sleipnir.valparaiso.cl>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
  *     
@@ -28,8 +30,8 @@
  *     
  ********************************************************************/
 
+#include <linux/string.h>
 #include <linux/socket.h>
-#include <linux/irda.h>
 
 #include <net/irda/irda.h>
 #include <net/irda/irlmp.h>
@@ -63,7 +65,7 @@
 			discovery = (discovery_t *) hashbin_get_next(cachelog);
 			
 			if ((node->daddr == new->daddr) || 
-			    (strcmp(node->info, new->info) == 0))
+			    (strcmp(node->nickname, new->nickname) == 0))
 			{
 				/* This discovery is a previous discovery 
 				 * from the same device, so just remove it
@@ -75,7 +77,7 @@
 
 
 	/* Insert the new and updated version */
-	hashbin_insert(cachelog, (QUEUE *) new, new->daddr, NULL);
+	hashbin_insert(cachelog, (queue_t *) new, new->daddr, NULL);
 
 	spin_unlock_irqrestore(&irlmp->lock, flags);
 }
@@ -90,7 +92,7 @@
 {
 	discovery_t *discovery;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	/*
 	 *  If log is missing this means that IrLAP was unable to perform the
@@ -119,11 +121,11 @@
  *    Go through all discoveries and expire all that has stayed to long
  *
  */
-void irlmp_expire_discoveries(hashbin_t *log, int saddr, int force)
+void irlmp_expire_discoveries(hashbin_t *log, __u32 saddr, int force)
 {
 	discovery_t *discovery, *curr;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	discovery = (discovery_t *) hashbin_get_first(log);
 	while (discovery != NULL) {
@@ -157,10 +159,10 @@
 
 	discovery = (discovery_t *) hashbin_get_first(log);
 	while (discovery != NULL) {
-		DEBUG(0, "Discovery:\n");
-		DEBUG(0, "  daddr=%08x\n", discovery->daddr);
-		DEBUG(0, "  saddr=%08x\n", discovery->saddr); 
-		DEBUG(0, "  name=%s\n", discovery->info);
+		IRDA_DEBUG(0, "Discovery:\n");
+		IRDA_DEBUG(0, "  daddr=%08x\n", discovery->daddr);
+		IRDA_DEBUG(0, "  saddr=%08x\n", discovery->saddr); 
+		IRDA_DEBUG(0, "  nickname=%s\n", discovery->nickname);
 
 		discovery = (discovery_t *) hashbin_get_next(log);
 	}
@@ -175,19 +177,19 @@
  */
 __u32 irlmp_find_device(hashbin_t *cachelog, char *name, __u32 *saddr)
 {
-	discovery_t *d;
 	unsigned long flags;
+	discovery_t *d;
 
 	spin_lock_irqsave(&irlmp->lock, flags);
 
 	/* Look at all discoveries for that link */
 	d = (discovery_t *) hashbin_get_first(cachelog);
 	while (d != NULL) {
-		DEBUG(1, "Discovery:\n");
-		DEBUG(1, "  daddr=%08x\n", d->daddr);
-		DEBUG(1, "  name=%s\n", d->info);
+		IRDA_DEBUG(1, "Discovery:\n");
+		IRDA_DEBUG(1, "  daddr=%08x\n", d->daddr);
+		IRDA_DEBUG(1, "  nickname=%s\n", d->nickname);
 		
-		if (strcmp(name, d->info) == 0) {
+		if (strcmp(name, d->nickname) == 0) {
 			*saddr = d->saddr;
 			
 			spin_unlock_irqrestore(&irlmp->lock, flags);
@@ -224,7 +226,7 @@
 	
 	discovery = (discovery_t *) hashbin_get_first(cachelog);
 	while ( discovery != NULL) {
-		len += sprintf(buf+len, "name: %s,", discovery->info);
+		len += sprintf(buf+len, "nickname: %s,", discovery->nickname);
 		
 		len += sprintf(buf+len, " hint: 0x%02x%02x", 
 			       discovery->hints.byte[0], 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/ircomm/Config.in linux.15p9/net/irda/ircomm/Config.in
--- linux.vanilla/net/irda/ircomm/Config.in	Thu Dec 17 17:01:03 1998
+++ linux.15p9/net/irda/ircomm/Config.in	Tue Jan 18 01:08:18 2000
@@ -1,3 +1,3 @@
 
-dep_tristate 'IrCOMM protocol' CONFIG_IRCOMM $CONFIG_IRDA
+dep_tristate '  IrCOMM protocol' CONFIG_IRCOMM $CONFIG_IRDA
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/ircomm/Makefile linux.15p9/net/irda/ircomm/Makefile
--- linux.vanilla/net/irda/ircomm/Makefile	Sat Aug 14 02:25:47 1999
+++ linux.15p9/net/irda/ircomm/Makefile	Tue Jan 18 01:08:18 2000
@@ -7,10 +7,10 @@
 #
 # Note 2! The CFLAGS definition is now in the main makefile...
 
-O_TARGET := ircomm_n_vtd.o
-O_OBJS	 := ircomm_common.o irvtd_driver.o
-M_OBJS   := ircomm.o ircomm_tty.o
-MI_OBJS  := ircomm_common.o irvtd_driver.o
+O_TARGET := ircomm_and_tty.o
+O_OBJS	 := ircomm_param.o ircomm_core.o ircomm_event.o ircomm_lmp.o ircomm_ttp.o ircomm_tty.o ircomm_tty_attach.o ircomm_tty_ioctl.o
+M_OBJS   := ircomm.o ircomm-tty.o
+MI_OBJS  := ircomm_param.o ircomm_core.o ircomm_event.o ircomm_lmp.o ircomm_ttp.o ircomm_tty.o ircomm_tty_attach.o ircomm_tty_ioctl.o
 
 OX_OBJS  += 
 
@@ -18,10 +18,12 @@
 
 ifeq ($(CONFIG_IRCOMM),m)
 ircomm.o:  $(MI_OBJS)
-	$(LD) $(LD_RFLAG) -r -o $@ ircomm_common.o
+	$(LD) $(LD_RFLAG) -r -o $@ ircomm_core.o ircomm_event.o ircomm_lmp.o ircomm_ttp.o
+
+ircomm-tty.o: $(MI_OBJS)
+	$(LD) $(LD_RFLAG) -r -o $@ ircomm_tty.o ircomm_tty_attach.o ircomm_tty_ioctl.o ircomm_param.o
+
 
-ircomm_tty.o: $(MI_OBJS)
-	$(LD) $(LD_RFLAG) -r -o $@ irvtd_driver.o
 endif
 
 include $(TOPDIR)/Rules.make
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/ircomm/ircomm_common.c linux.15p9/net/irda/ircomm/ircomm_common.c
--- linux.vanilla/net/irda/ircomm/ircomm_common.c	Sat Aug 14 02:26:52 1999
+++ linux.15p9/net/irda/ircomm/ircomm_common.c	Thu Jan  1 01:00:00 1970
@@ -1,1921 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      ircomm_common.c
- * Version:       
- * Description:   An implementation of IrCOMM service interface, 
- *                state machine, and incidental function(s).
- * Status:        Experimental.
- * Author:        Takahide Higuchi <thiguchi@pluto.dti.ne.jp>
- * Source:        irlpt_event.c
- *
- *     Copyright (c) 1998-1999, Takahide Higuchi, <thiguchi@pluto.dti.ne.jp>,
- *     All Rights Reserved.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     I, Takahide Higuchi, provide no warranty for any of this software.
- *     This material is provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-/*
- *    Reference: 
- *    "'IrCOMM':Serial and Parallel Port Emulation Over IR(Wire Replacement)"
- *    version 1.0, which is available at http://www.irda.org/.
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/proc_fs.h>
-#include <linux/init.h>
-
-#include <net/irda/irda.h>
-#include <net/irda/irlmp.h>
-#include <net/irda/iriap.h>
-#include <net/irda/irttp.h>
-#include <net/irda/irias_object.h>
-
-#include <net/irda/ircomm_common.h>
-
-static char *revision_date = "Tue May 18 03:11:39 1999";
-
-
-static void ircomm_state_idle(struct ircomm_cb *self, IRCOMM_EVENT event, 
-			      struct sk_buff *skb );
-static void ircomm_state_discoverywait(struct ircomm_cb *self, 
-				       IRCOMM_EVENT event, 
-				       struct sk_buff *skb );
-static void ircomm_state_queryparamwait(struct ircomm_cb *self, 
-					IRCOMM_EVENT event, 
-					struct sk_buff *skb );
-static void ircomm_state_querylsapwait(struct ircomm_cb *self, 
-				       IRCOMM_EVENT event, 
-				       struct sk_buff *skb );
-static void ircomm_state_waiti( struct ircomm_cb *self, IRCOMM_EVENT event, 
-				struct sk_buff *skb );
-static void ircomm_state_waitr( struct ircomm_cb *self, IRCOMM_EVENT event, 
-				struct sk_buff *skb );
-static void ircomm_state_conn( struct ircomm_cb *self, IRCOMM_EVENT event, 
-			       struct sk_buff *skb );
-static void ircomm_do_event( struct ircomm_cb *self, IRCOMM_EVENT event,
-			     struct sk_buff *skb);
-static void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state);
-
-static void ircomm_discovery_indication(discovery_t *discovery);
-static void ircomm_tx_controlchannel(struct ircomm_cb *self );
-static int ircomm_proc_read(char *buf, char **start, off_t offset,
-			    int len, int unused);
-
-static void start_discovering(struct ircomm_cb *self);
-static void query_lsapsel(struct ircomm_cb * self);
-static void query_parameters(struct ircomm_cb *self);
-static void queryias_done(struct ircomm_cb *self);
-static void ircomm_getvalue_confirm(int result, __u16 obj_id, 
-				    struct ias_value *value, void *priv);
-
-
-struct ircomm_cb *discovering_instance;
-
-/*
- * debug parameter ircomm_cs:
- *  0 = client/server, 1 = client only 2 = server only
- * usage for example: 
- *  insmod ircomm ircomm_cs=1
- *  LILO boot : Linux ircomm_cs=2   etc.
- */
-
-static int ircomm_cs = 0;
-MODULE_PARM(ircomm_cs, "i");
-
-
-
-static char *ircommstate[] = {
-	"IDLE",
-
-	"DISCOVERY_WAIT",
-	"QUERYPARAM_WAIT",
-	"QUERYLSAP_WAIT",
-
-	"WAITI",
-	"WAITR",
-	"CONN",
-};
-
-static char *ircommservicetype[] = {
-	"N/A",
-	"THREE_WIRE_RAW",
-	"THREE_WIRE",
-	"NINE_WIRE",
-	"CENTRONICS",
-};
-static char *ircommporttype[] = {
-	"Unknown",
-	"SERIAL",
-	"PARALLEL",
-};
-
-
-struct ircomm_cb **ircomm = NULL;
-
-static char *ircommevent[] = {
-	"IRCOMM_CONNECT_REQUEST",
-	"TTP_CONNECT_INDICATION",
-	"LMP_CONNECT_INDICATION",
-
-	"TTP_CONNECT_CONFIRM",
-	"TTP_DISCONNECT_INDICATION",
-	"LMP_CONNECT_CONFIRM",
-	"LMP_DISCONNECT_INDICATION",
-
-	"IRCOMM_CONNECT_RESPONSE",
-	"IRCOMM_DISCONNECT_REQUEST",
-
-	"TTP_DATA_INDICATION",
-	"IRCOMM_DATA_REQUEST",
-	"LMP_DATA_INDICATION",
-	"IRCOMM_CONTROL_REQUEST",
-
-	"DISCOVERY_INDICATION",
-	"GOT_PARAMETERS",
-	"GOT_LSAPSEL",
-	"QUERYIAS_ERROR",
-};
-
-#ifdef CONFIG_PROC_FS
-extern struct proc_dir_entry *proc_irda;
-#endif
-
-static void (*state[])( struct ircomm_cb *self, IRCOMM_EVENT event,
-			struct sk_buff *skb) = 
-{
-	ircomm_state_idle,
-
-	ircomm_state_discoverywait,
-	ircomm_state_queryparamwait,
-	ircomm_state_querylsapwait,
-
-	ircomm_state_waiti,
-	ircomm_state_waitr,
-	ircomm_state_conn,
-};
-
-__initfunc(int ircomm_init(void))
-{
-	int i;
-
-	printk( "Linux-IrDA: IrCOMM protocol ( revision:%s ) \n",
-		revision_date);
-	DEBUG( 4, __FUNCTION__"()\n");
-
-	/* allocate master array */
-
-	ircomm = (struct ircomm_cb **) kmalloc( sizeof(struct ircomm_cb *) *
-						IRCOMM_MAX_CONNECTION,
-						GFP_KERNEL);
-	if ( ircomm == NULL) {
-		printk( KERN_ERR __FUNCTION__"(): kmalloc failed!\n");
-		return -ENOMEM;
-	}
-
-	memset( ircomm, 0, sizeof(struct ircomm_cb *) * IRCOMM_MAX_CONNECTION);
-
-	/* initialize structures */
-	   
-	for(i = 0;i < IRCOMM_MAX_CONNECTION; i++){
-		ircomm[i] = kmalloc( sizeof(struct ircomm_cb), GFP_KERNEL );
-
-		if(!ircomm[i]){
-			printk( KERN_ERR __FUNCTION__"(): kmalloc failed!\n");
-			return -ENOMEM;
-		} 
-
-		
-		memset( ircomm[i], 0, sizeof(struct ircomm_cb));
-
-		ircomm[i]->magic = IRCOMM_MAGIC;
-		/* default settings */
-		ircomm[i]->data_format = CS8;
-		ircomm[i]->flow_ctrl = USE_RTS|USE_DTR;  /*TODO: is this OK? */
-		ircomm[i]->xon_char = 0x11; 
-		ircomm[i]->xoff_char = 0x13;
-		ircomm[i]->enq_char = 0x05;
-		ircomm[i]->ack_char = 0x06;  
-
-		ircomm[i]->max_header_size = COMM_MAX_HEADER_SIZE;
-		ircomm[i]->tx_max_sdu_size = COMM_DEFAULT_SDU_SIZE;
-		ircomm[i]->rx_max_sdu_size = SAR_DISABLE;  
-		ircomm[i]->ctrl_skb = dev_alloc_skb(COMM_DEFAULT_SDU_SIZE
-						    + COMM_MAX_HEADER_SIZE);
-		if (ircomm[i]->ctrl_skb == NULL){
-			DEBUG(0,"ircomm:init_module:alloc_skb failed!\n");
-			return -ENOMEM;
-		}
-
-		skb_reserve(ircomm[i]->ctrl_skb,COMM_MAX_HEADER_SIZE);
-
-	}
-
-	/*
-	 * we register /proc/irda/ircomm
-	 */
-
-#ifdef CONFIG_PROC_FS
-	create_proc_entry("ircomm", 0, proc_irda)->get_info = ircomm_proc_read;
-#endif /* CONFIG_PROC_FS */
-
-	discovering_instance = NULL;
-	return 0;
-}
-
-#ifdef MODULE
-void ircomm_cleanup(void)
-{
-	int i;
-
-	DEBUG( 4, "ircomm:cleanup_module\n");
-	/*
-	 * free some resources
-	 */
-	if (ircomm) {
-		for (i=0; i<IRCOMM_MAX_CONNECTION; i++) {
-			if (ircomm[i]) {
-
-				if(ircomm[i]->ctrl_skb){
-					dev_kfree_skb(ircomm[i]->ctrl_skb);
-
-					ircomm[i]->ctrl_skb = NULL;
-				}
-
-				DEBUG( 4, "freeing structures(%d)\n",i);
-				kfree(ircomm[i]);
-				ircomm[i] = NULL;
-			}
-		}
-		DEBUG( 4, "freeing master array\n");
-		kfree(ircomm);
-		ircomm = NULL;
-	}
-
-#ifdef CONFIG_PROC_FS
-	remove_proc_entry("ircomm", proc_irda);
-#endif /* CONFIG_PROC_FS */
-}
-#endif /* MODULE */
-
-/*
- * ---------------------------------------------------------------------- 
- * callbacks which accept incoming indication/confirm from IrTTP  (or IrLMP)
- * ---------------------------------------------------------------------- 
- */
-
-static int ircomm_accept_data_indication(void *instance, void *sap, 
-					 struct sk_buff *skb)
-{
-	struct ircomm_cb *self = (struct ircomm_cb *) instance;
-
-	ASSERT(self != NULL, return -1;);
-	ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
-	ASSERT(skb != NULL, return -1;);
-       
-	DEBUG(4,__FUNCTION__"():\n");
-	ircomm_do_event(self, TTP_DATA_INDICATION, skb);
-	self->rx_packets++;
-	
-	return 0;
-}
-
-static void ircomm_accept_connect_confirm(void *instance, void *sap,
-					  struct qos_info *qos, 
-					  __u32 max_sdu_size, 
-					  __u8 max_header_size,
-					  struct sk_buff *skb)
-{
-	struct ircomm_cb *self = (struct ircomm_cb *) instance;
-
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRCOMM_MAGIC, return;);
-	ASSERT(skb != NULL, return;);
-	ASSERT(qos != NULL, return;);
-
-	DEBUG(0,__FUNCTION__"(): got connected!\n");
-
-	if (max_sdu_size == SAR_DISABLE)
-		self->tx_max_sdu_size =(qos->data_size.value - max_header_size
-					- COMM_HEADER_SIZE);
-	else {
-		ASSERT(max_sdu_size >= COMM_DEFAULT_SDU_SIZE, return;);
-		/* use fragmentation */
-		self->tx_max_sdu_size = max_sdu_size - COMM_HEADER_SIZE;
-	}
-
-	self->qos = qos;
-	self->max_header_size = max_header_size + COMM_HEADER_SIZE;
-	self->null_modem_mode = 0;         /* disable null modem emulation */
-
-	ircomm_do_event(self, TTP_CONNECT_CONFIRM, skb);
-}
-
-static void ircomm_accept_connect_indication(void *instance, void *sap,
-					     struct qos_info *qos,
-					     __u32 max_sdu_size,
-					     __u8 max_header_size,
-					     struct sk_buff *skb)
-{
-	struct ircomm_cb *self = (struct ircomm_cb *)instance;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRCOMM_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
-	ASSERT( qos != NULL, return;);
-
-	DEBUG(0,__FUNCTION__"()\n");
-
-	if (max_sdu_size == SAR_DISABLE)
-		self->tx_max_sdu_size =(qos->data_size.value - max_header_size
-					- COMM_HEADER_SIZE);
-	else
-		self->tx_max_sdu_size = max_sdu_size - COMM_HEADER_SIZE;
-
-	self->qos = qos;
-	self->max_header_size = max_header_size + COMM_HEADER_SIZE;
-
-	ircomm_do_event( self, TTP_CONNECT_INDICATION, skb);
-
-	/* stop connecting */
-	wake_up_interruptible( &self->discovery_wait);
-	wake_up_interruptible( &self->ias_wait);
-
-}
-
-static void ircomm_accept_disconnect_indication(void *instance, void *sap, 
-					 LM_REASON reason,
-					 struct sk_buff *skb)
-{
-	struct ircomm_cb *self = (struct ircomm_cb *)instance;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRCOMM_MAGIC, return;);
-
-	DEBUG(0,__FUNCTION__"():\n");
-	ircomm_do_event( self, TTP_DISCONNECT_INDICATION, skb);
-
-}
-
-static void ircomm_accept_flow_indication( void *instance, void *sap,
-					   LOCAL_FLOW cmd)
-{
-	IRCOMM_CMD command;
-	struct ircomm_cb *self = (struct ircomm_cb *)instance;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRCOMM_MAGIC, return;);
-
-	switch(cmd){
-	case FLOW_START:
-		DEBUG(4,__FUNCTION__"():START\n"); 
-		command = TX_READY;
-		self->ttp_stop = 0;
-		if(self->notify.flow_indication)
-			self->notify.flow_indication( self->notify.instance, 
-						      self, command);
-		break;
-		
-	case FLOW_STOP:
-		DEBUG(4,__FUNCTION__":STOP\n"); 
-		command = TX_BUSY;
-		self->ttp_stop = 1;
-		if(self->notify.flow_indication)
-			self->notify.flow_indication( self->notify.instance, 
-						      self, command);
-		break;
-
-	default:
-		DEBUG(0,__FUNCTION__"();unknown status!\n"); 
-	}
-
-}
-
-
-/*
- * ircomm_discovery_indication()
- *    Remote device is discovered, try query the remote IAS to see which
- *    device it is, and which services it has.
- */
-
-static void ircomm_discovery_indication(discovery_t *discovery)
-{
-	struct ircomm_cb *self;
-
-	self = discovering_instance;
-	if(self == NULL)
-		return;
-	ASSERT(self->magic == IRCOMM_MAGIC, return;);
-
-	self->daddr = discovery->daddr;
-	self->saddr = discovery->saddr;
-
-	DEBUG( 0, __FUNCTION__"():daddr=%08x\n", self->daddr);
-
-	ircomm_do_event(self, DISCOVERY_INDICATION, NULL);
-	return;
-}
-
-/*
- * ircomm_getvalue_confirm()
- * handler for iriap_getvaluebyclass_request() 
- */
-static void ircomm_getvalue_confirm(int result, __u16 obj_id, 
-				    struct ias_value *value, void *priv)
-{
-	struct ircomm_cb *self = (struct ircomm_cb *) priv;
-	struct sk_buff *skb= NULL;
-	__u8 *frame;
-	__u8 servicetype = 0 ;
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRCOMM_MAGIC, return;);
-
-	/* Check if request succeeded */
-	if (result != IAS_SUCCESS) {
-		DEBUG( 0, __FUNCTION__ "(), got NULL value!\n");
-		ircomm_do_event(self, QUERYIAS_ERROR, NULL);
-		return;
-	}
-
-	DEBUG(4, __FUNCTION__"():type(%d)\n", value->type);
-
-	self->ias_type = value->type;
-	switch(value->type){
- 	case IAS_OCT_SEQ:
-		
-		DEBUG(4, __FUNCTION__"():got octet sequence:\n");
-#if 0
-		{
-			int i;
-			for ( i=0;i<value->len;i++)
-				printk("%02x",
-				       (__u8)(*(value->t.oct_seq + i)));
-			printk("\n");
-		}
-#endif
-		skb = dev_alloc_skb((value->len) + 2);
-		ASSERT(skb != NULL, ircomm_do_event(self, QUERYIAS_ERROR, NULL);return;);
-		frame = skb_put(skb,2);
-		/* MSB first */
-		frame[0] = ( value->len >> 8 ) & 0xff;
-		frame[1] = value->len & 0xff;
-		
-		frame = skb_put(skb,value->len);
-		memcpy(frame, value->t.oct_seq, value->len);
-		ircomm_parse_tuples(self, skb, IAS_PARAM);
-		kfree_skb(skb);
-
-		/* 
-		 * check if servicetype we want is available 
-		 */
-
-		DEBUG(0,__FUNCTION__"():peer capability is:\n");
-		DEBUG(0,"3wire raw: %s\n",
-		      ((self->peer_servicetype & THREE_WIRE_RAW) ? "yes":"no"));
-		DEBUG(0,"3wire    : %s\n",
-		      ((self->peer_servicetype & THREE_WIRE) ? "yes":"no"));
-		DEBUG(0,"9wire    : %s\n",
-		      ((self->peer_servicetype & NINE_WIRE) ? "yes":"no"));
-		DEBUG(0,"IEEE1284 : %s\n",
-		      ((self->peer_servicetype & CENTRONICS) ? "yes":"no"));
-
-		self->servicetype &= self->peer_servicetype;
-		if(!(self->servicetype)){
-			DEBUG(0,__FUNCTION__"(): servicetype mismatch!\n");
-			ircomm_do_event(self, QUERYIAS_ERROR, NULL);
-			break;
-		}
-
-		/*
-		 * then choose better one 
-		 */
-		if(self->servicetype & THREE_WIRE_RAW)
-			servicetype = THREE_WIRE_RAW;
-		if(self->servicetype & THREE_WIRE)
-			servicetype = THREE_WIRE;
-		if(self->servicetype & NINE_WIRE)
-			servicetype = NINE_WIRE;
-		if(self->servicetype & CENTRONICS)
-			servicetype = CENTRONICS;
-
-		self->servicetype = servicetype;
-
-		/* enter next state */
-		ircomm_do_event(self, GOT_PARAMETERS, NULL);
-		break;
-
-	case IAS_INTEGER:
-		/* LsapSel seems to be sent to me */	
-		DEBUG(0, __FUNCTION__"():got lsapsel = %d\n", value->t.integer);
-
-		if ( value->t.integer == -1){
-			DEBUG( 0, __FUNCTION__"():invalid value!\n");
-			ircomm_do_event(self, QUERYIAS_ERROR, NULL);
-			return;
-		}
-		self->dlsap = value->t.integer;
-		ircomm_do_event(self, GOT_LSAPSEL, NULL);
-		break;
-
-	case IAS_MISSING:
-		DEBUG( 0, __FUNCTION__":got IAS_MISSING\n");
-		ircomm_do_event(self, QUERYIAS_ERROR, NULL);
-		break;
-   
-	default:
-		DEBUG( 0, __FUNCTION__":got unknown (strange?)type!\n");
-		ircomm_do_event(self, QUERYIAS_ERROR, NULL);
-		break;
-	}
-}
-
-
-
-/* 
- * ----------------------------------------------------------------------
- * Impl. of actions (descrived in section 7.4 of the reference)
- * ----------------------------------------------------------------------
- */
-
-static void issue_connect_request(struct ircomm_cb *self,
-				  struct sk_buff *userdata )
-{
-	/* TODO: we have to send/build userdata field which contains 
-	   InitialControlParameters */
-
-	switch(self->servicetype){
-	case THREE_WIRE_RAW:
-		DEBUG(0, __FUNCTION__"():THREE_WIRE_RAW is not implemented\n");
-		break;
-
-	case DEFAULT: 
-	case THREE_WIRE:
-	case NINE_WIRE:
-	case CENTRONICS:
-
-		irttp_connect_request(self->tsap, self->dlsap, 
-				      self->saddr, self->daddr, 
-				      NULL, self->rx_max_sdu_size, userdata); 
-		break;
-
-	default:
-		printk(KERN_ERR __FUNCTION__"():Illegal servicetype %d\n"
-		       ,self->servicetype);
-	}
-}	
-
-static void disconnect_indication(struct ircomm_cb *self, struct sk_buff *skb)
-{
-
-	/*
-	 * Not implemented parameter"Reason".That is optional.
-	 * What is reason? maybe discribed in irmod.h?
-	 */
-
-	if(self->notify.disconnect_indication)
-		self->notify.disconnect_indication( self->notify.instance,
-						    self,
-						    self->reason, skb);
-						    
-}
-
-static void connect_indication(struct ircomm_cb *self, struct qos_info *qos, 
-			       struct sk_buff *skb)
-{
-
-/* If controlparameters don't exist, we use the servicetype"DEFAULT".*/
-/* 	if( !ircomm_parse_controlchannel( self, data)) */
-/* 		self->servicetype = DEFAULT;     TODOD:fix this! TH */
-
-	if (self->notify.connect_indication)
-		self->notify.connect_indication(self->notify.instance, self, 
-						qos, self->tx_max_sdu_size,
-						self->max_header_size, skb);
-}
-    
-#if 0
-/*   it's for THREE_WIRE_RAW.*/
-static void connect_indication_three_wire_raw(void)
-{ 
-	DEBUG(0,"ircomm:connect_indication_threewire():not implemented!");
-}    
-#endif 
-
-
-static void connect_confirm(struct ircomm_cb *self, struct sk_buff *skb)
-{
-	DEBUG(4 ,__FUNCTION__"()\n");
-
-	/* give a connect_confirm to the client */
-	if( self->notify.connect_confirm )
-		self->notify.connect_confirm(self->notify.instance,
-					     self, NULL, self->tx_max_sdu_size,
-					     self->max_header_size, skb);
-}
-
-static void issue_connect_response(struct ircomm_cb *self,
-				   struct sk_buff *skb)
-{
-	DEBUG(0,__FUNCTION__"()\n");
-	
-	if( self->servicetype == THREE_WIRE_RAW){
-		DEBUG(0,__FUNCTION__"():THREE_WIRE_RAW is not implemented yet\n");
-		/* irlmp_connect_rsp(); */
-	} else
-		irttp_connect_response(self->tsap, self->rx_max_sdu_size, skb);
-}
-
-static void issue_disconnect_request(struct ircomm_cb *self,
-				     struct sk_buff *userdata)
-{
-	if(self->servicetype == THREE_WIRE_RAW){
-		DEBUG(0,__FUNCTION__"():3wireraw is not implemented\n");
-	}
-	else
-		irttp_disconnect_request(self->tsap, userdata, 
-					 self->disconnect_priority);
-}
-    
-static void issue_data_request(struct ircomm_cb *self,
-			       struct sk_buff *userdata )
-{
-	int err;
-
-	if (self->servicetype == THREE_WIRE_RAW){
-		/* irlmp_data_request(self->lmhandle,userdata); */
-		DEBUG(0,__FUNCTION__"():not implemented!");
-		return;
-	}
-
-	DEBUG(4,__FUNCTION__"():sending frame\n");
-	err = irttp_data_request(self->tsap, userdata);
-	if (err){
-		printk(KERN_ERR __FUNCTION__":ttp_data_request failed\n");
-		if (userdata)
-			dev_kfree_skb( userdata);
-	}
-	self->tx_packets++;
-}
-
-static void issue_control_request(struct ircomm_cb *self,
-				  struct sk_buff *userdata)
-{
-	int err;
-
-	DEBUG(4,__FUNCTION__"()\n"); 
-	if (self->servicetype == THREE_WIRE_RAW) {
-		DEBUG(0,__FUNCTION__"():THREE_WIRE_RAW is not implemented\n");
-		
-	}
-	else 
-	{
-		err = irttp_data_request(self->tsap,userdata);
-		if(err)
-		{
-			printk( __FUNCTION__"():ttp_data_request failed\n");
-			if(userdata)
-				dev_kfree_skb(userdata);
-		}
-		else
-			self->tx_controls++;
-
-		self->pending_control_tuples = 0;
-	}
-}
-
-static void process_data(struct ircomm_cb *self, struct sk_buff *skb )
-{
-	
-	DEBUG(4,__FUNCTION__":skb->len=%d, ircomm header = 1, clen=%d\n",
-	      (int)skb->len ,(int)skb->data[0]);
-
-	/* we have to parse control channel when receiving.  (see
-	 * page17 of IrCOMM standard) but it is not parsed here since
-	 * upper layer may have some receive buffer.
-	 *
-	 * hence upper layer have to parse it when it consumes a packet.
-	 *   -- TH
-	 */
-
- 	/* ircomm_parse_control(self, skb, CONTROL_CHANNEL); */
-
-	if (self->notify.data_indication && skb->len)
-		self->notify.data_indication(self->notify.instance, self,
-					     skb);
-}
-
-int ircomm_data_indication(struct ircomm_cb *self, struct sk_buff *skb)
-{
-	/* Not implemented yet:THREE_WIRE_RAW service uses this function.  */
-	DEBUG(0,"ircomm_data_indication:not implemented yet!\n");
-
-	return 0;
-}
-
-
-/* 
- * ----------------------------------------------------------------------
- * Implementation of state chart,
- * descrived in section 7.1 of the specification.
- * ----------------------------------------------------------------------
- */
-
-static void ircomm_do_event( struct ircomm_cb *self, IRCOMM_EVENT event,
-			     struct sk_buff *skb) 
-{
-	
-	DEBUG( 4, __FUNCTION__": STATE = %s, EVENT = %s\n",
-	       ircommstate[self->state], ircommevent[event]);
-	(*state[self->state])(self, event, skb);
-}
-
-static void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state) 
-{
-	self->state = state;
-	DEBUG( 0, __FUNCTION__": NEXT STATE=%d(%s), servicetype=(%d)\n", 
-	       (int)state, ircommstate[self->state],self->servicetype);
-}
-
-
-
-/*
- * ircomm_state_idle
- */
-
-static void ircomm_state_idle( struct ircomm_cb *self, IRCOMM_EVENT event, 
-			       struct sk_buff *skb )
-{
-	switch (event){
-	case IRCOMM_CONNECT_REQUEST:
-
-		/* ircomm_next_state(self, COMM_WAITI); */
-		/* issue_connect_request( self, skb ); */
-
-		ircomm_next_state(self, COMM_DISCOVERY_WAIT);
-		start_discovering(self);
-		break;
-		
-	case TTP_CONNECT_INDICATION:
-
-		ircomm_next_state(self, COMM_WAITR);
-		connect_indication( self, self->qos, skb);
-		break;
-
-	case LMP_CONNECT_INDICATION:
-
-		DEBUG(0,__FUNCTION__"():LMP_CONNECT_IND is notimplemented!");
- 		/* connect_indication_three_wire_raw(); */
- 		/* ircomm_next_state(self, COMM_WAITR); */
-		break;
-
-	default:
-		DEBUG(0,__FUNCTION__"():unknown event =%d(%s)\n",
-		      event, ircommevent[event]);
-	}
-}
-
-/*
- * ircomm_state_discoverywait
- */
-static void ircomm_state_discoverywait(struct ircomm_cb *self, 
-				       IRCOMM_EVENT event, 
-				       struct sk_buff *skb )
-{
-	switch(event){
-
-	case TTP_CONNECT_INDICATION:
-
-		ircomm_next_state(self, COMM_WAITR);
-		queryias_done(self);
-		connect_indication( self, self->qos, skb);
-		break;
-
-	case DISCOVERY_INDICATION:
-		ircomm_next_state(self, COMM_QUERYPARAM_WAIT);
-		query_parameters(self);
-		break;
-
-	case IRCOMM_DISCONNECT_REQUEST:
-		ircomm_next_state(self, COMM_IDLE);
-		queryias_done(self);
-		break;
-
-	case QUERYIAS_ERROR:
-		ircomm_next_state(self, COMM_IDLE);
-		disconnect_indication(self, NULL);
-		queryias_done(self);
-		break;
-
-	default:
-		DEBUG(0,__FUNCTION__"():unknown event =%d(%s)\n",
-		      event, ircommevent[event]);
-	}
-}
-
-/*
- * ircomm_state_queryparamwait
- */
-
-static void ircomm_state_queryparamwait(struct ircomm_cb *self, 
-					IRCOMM_EVENT event, 
-					struct sk_buff *skb)
-{
-	switch (event) {
-	case TTP_CONNECT_INDICATION:
-
-		ircomm_next_state(self, COMM_WAITR);
-		connect_indication( self, self->qos, skb);
-		break;
-
-	case GOT_PARAMETERS:
-		
-		ircomm_next_state(self, COMM_QUERYLSAP_WAIT);
-		query_lsapsel( self );
-		break;
-
-	case IRCOMM_DISCONNECT_REQUEST:
-		ircomm_next_state(self, COMM_IDLE);
-		queryias_done(self);
-		break;
-
-	case QUERYIAS_ERROR:
-		ircomm_next_state(self, COMM_IDLE);
-		disconnect_indication(self, NULL);
-		queryias_done(self);
-		break;
-
-	default:
-		DEBUG(0,__FUNCTION__"():unknown event =%d(%s)\n",
-		      event, ircommevent[event]);
-	}
-}
-
-/*
- * ircomm_state_querylsapwait
- */
-
-static void ircomm_state_querylsapwait(struct ircomm_cb *self, 
-				       IRCOMM_EVENT event, 
-				       struct sk_buff *skb )
-{
-	switch (event) {
-
-	case TTP_CONNECT_INDICATION:
-
-		ircomm_next_state(self, COMM_WAITR);
-		connect_indication( self, self->qos, skb);
-		break;
-
-	case GOT_LSAPSEL:
-		
-		ircomm_next_state(self, COMM_WAITI);
-		queryias_done(self);
-		issue_connect_request( self, skb );
-		break;
-
-	case IRCOMM_DISCONNECT_REQUEST:
-		ircomm_next_state(self, COMM_IDLE);
-		queryias_done(self);
-		break;
-
-	case QUERYIAS_ERROR:
-		ircomm_next_state(self, COMM_IDLE);
-		disconnect_indication(self, NULL);
-		queryias_done(self);
-		break;
-
-
-	default:
-		DEBUG(0,__FUNCTION__"():unknown event =%d(%s)\n",
-		      event, ircommevent[event]);
-	}
-}
-
-/*
- * ircomm_state_waiti
- */
-
-static void ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event, 
-			  struct sk_buff *skb )
-{
-	switch (event) {
-	case TTP_CONNECT_CONFIRM:
-		ircomm_next_state(self, COMM_CONN);
-		connect_confirm(self, skb );
-		break;
-	case TTP_DISCONNECT_INDICATION:
-		ircomm_next_state(self, COMM_IDLE);
-		disconnect_indication(self, skb);
-		break;
-/* 	case LMP_CONNECT_CONFIRM: */
-/* 		ircomm_connect_cnfirmation; */
-/* 		ircomm_next_state(self, COMM_CONN); */
-/* 		break; */
-/* 	case LMP_DISCONNECT_INDICATION: */
-/* 		ircomm_disconnect_ind; */
-/* 		ircomm_next_state(self, COMM_IDLE); */
-/* 		break; */
-	default:
-		DEBUG(0,__FUNCTION__"():unknown event =%d(%s)\n",
-		      event, ircommevent[event]);
-	}
-}
-
-/*
- * ircomm_state_waitr
- */
-static void ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event, 
-			       struct sk_buff *skb ) 
-{
-	switch (event) {
-	case IRCOMM_CONNECT_RESPONSE:
-
-	        /* issue_connect_response */
-		
-		if (self->servicetype==THREE_WIRE_RAW) {
-			DEBUG(0,__FUNCTION__"():3WIRE_RAW is not implemented\n");
-			/* irlmp_connect_response(Vpeersap,
-			 *                         ACCEPT,null);
-			 */
-		} else {
-			ircomm_next_state(self, COMM_CONN);
-			issue_connect_response(self, skb);
-		}
-		break;
-
-	case IRCOMM_DISCONNECT_REQUEST:
-		ircomm_next_state(self, COMM_IDLE);
-		issue_disconnect_request(self, skb);
-		queryias_done(self);
-		break;
-
-	case TTP_DISCONNECT_INDICATION:
-		ircomm_next_state(self, COMM_IDLE);
-		disconnect_indication(self, skb);
-		break;
-
-	case DISCOVERY_INDICATION:
-		DEBUG(0, __FUNCTION__"():DISCOVERY_INDICATION\n");
-		queryias_done(self);
-		break;
-	case GOT_PARAMETERS:
-		DEBUG(0, __FUNCTION__"():GOT_PARAMETERS\n");
-		queryias_done(self);
-		break;
-	case GOT_LSAPSEL:
-		DEBUG(0, __FUNCTION__"():GOT_LSAPSEL\n");
-		queryias_done(self);
-		break;
-
-/* 	case LMP_DISCONNECT_INDICATION: */
-/* 		disconnect_indication();		 */
-/* 		ircomm_next_state(self, COMM_IDLE);		 */
-/* 		break; */
-	default:
-		DEBUG(0,"ircomm_state_waitr:unknown event =%d(%s)\n",
-		      event, ircommevent[event]);
-	}
-}
-
-/*
- * ircomm_state_conn
- */
-
-static void ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event, 
-			      struct sk_buff *skb )
-{
-	switch (event) {
-	case TTP_DATA_INDICATION:
-		process_data(self, skb);
-		break;
-	case IRCOMM_DATA_REQUEST:
-		issue_data_request(self, skb);
-		break;
-/* 	case LMP_DATA_INDICATION: */
-/* 		ircomm_data_indicated(); */
-/* 		break; */
-	case IRCOMM_CONTROL_REQUEST:
-		issue_control_request(self, skb);
-		break;
-	case TTP_DISCONNECT_INDICATION:
-		ircomm_next_state(self, COMM_IDLE);
-		disconnect_indication(self, skb);
-		break;
-	case IRCOMM_DISCONNECT_REQUEST:
-		ircomm_next_state(self, COMM_IDLE);
-		issue_disconnect_request(self, skb);
-		queryias_done(self);
-		break;
-/* 	case LM_DISCONNECT_INDICATION: */
-/* 		disconnect_indication(); */
-/* 		ircomm_next_state(self, COMM_IDLE); */
-/* 		break; */
-
-	case DISCOVERY_INDICATION:
-		DEBUG(0, __FUNCTION__"():DISCOVERY_INDICATION\n");
-		queryias_done(self);
-		break;
-	case GOT_PARAMETERS:
-		DEBUG(0, __FUNCTION__"():GOT_PARAMETERS\n");
-		queryias_done(self);
-		break;
-	case GOT_LSAPSEL:
-		DEBUG(0, __FUNCTION__"():GOT_LSAPSEL\n");
-		queryias_done(self);
-		break;
-
-	default:
-		DEBUG(0,"ircomm_state_conn:unknown event =%d(%s)\n",
-		      event, ircommevent[event]);
-	}
-}
-
-/*
- *  ----------------------------------------------------------------------
- *  IrCOMM service interfaces and supporting functions
- *
- *  ----------------------------------------------------------------------
- */
-
-/*
- * Function start_discovering (self)
- *
- *    Start discovering and enter DISCOVERY_WAIT state
- *
- */
-static void start_discovering(struct ircomm_cb *self)
-{
-	__u16  hints; 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRCOMM_MAGIC, return;);
-	DEBUG(4,__FUNCTION__"():servicetype = %d\n",self->servicetype);
-	
-
-	hints = irlmp_service_to_hint(S_COMM);
-
-	DEBUG(1,__FUNCTION__"():start discovering..\n");
-	switch (ircomm_cs) {
-	case 0:
-		MOD_INC_USE_COUNT;
-		self->queryias_lock = 1;
-		discovering_instance = self;
-		self->skey = irlmp_register_service(hints);
-		self->ckey = irlmp_register_client(hints, ircomm_discovery_indication,
-					     NULL);
-		break;
-		
-	case 1:    /* client only */
-		MOD_INC_USE_COUNT;
-		self->queryias_lock = 1;
-		discovering_instance = self;
-		DEBUG( 0, __FUNCTION__"():client only mode\n");
-		self->ckey = irlmp_register_client(hints, ircomm_discovery_indication,
-					     NULL);
-		break;
-
-	case 2:     /*  server only  */
-	default:
-		DEBUG( 0, __FUNCTION__"():server only mode\n");
-		self->skey = irlmp_register_service(hints);
-		discovering_instance = NULL;
-		break;
-	}
-	
-	return;
-}
-
-/*
- * queryias_done(self)
- *
- * 
- */
-
-/*
- * Function queryias_done (self)
- *
- *    Called when discovery process got wrong results, completed, or
- *    terminated.
- * 
- */
-static void queryias_done(struct ircomm_cb *self)
-{
-	DEBUG(0, __FUNCTION__"():\n");
-	if (self->queryias_lock){
-		self->queryias_lock = 0;
-		discovering_instance = NULL;
-		MOD_DEC_USE_COUNT;
-		irlmp_unregister_client(self->ckey);
-	}
-	if (ircomm_cs != 1)
-		irlmp_unregister_service(self->skey);
-	return;
-}
-
-
-
-static void query_parameters(struct ircomm_cb *self)
-{
-
-	DEBUG(0, __FUNCTION__"():querying IAS: Parameters..\n");
-	iriap_getvaluebyclass_request( "IrDA:IrCOMM", "Parameters",
-				       self->saddr, self->daddr,
-				       ircomm_getvalue_confirm, self );
-}
-
-static void query_lsapsel(struct ircomm_cb * self)
-{
-	DEBUG(0, __FUNCTION__"():querying IAS: Lsapsel...\n");
-
-	if (!(self->servicetype & THREE_WIRE_RAW)) {
-		iriap_getvaluebyclass_request( 
-			"IrDA:IrCOMM", "IrDA:TinyTP:LsapSel",
-			self->saddr, self->daddr,
-			ircomm_getvalue_confirm, self );
-	} else {
-		DEBUG(0, __FUNCTION__ "THREE_WIRE_RAW is not implemented!\n");
-	}
-}
-
-/*
- * Function ircomm_connect_request (self, servicetype)
- *
- *    Impl. of this function is differ from one of the reference. This
- *    function does discovery as well as sending connect request
- * 
- */
-void ircomm_connect_request(struct ircomm_cb *self, __u8 servicetype)
-{
-	/*
-	 * TODO:build a packet which contains "initial control parameters"
-	 * and send it with connect_request
-	 */
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRCOMM_MAGIC, return;);
-
-
-	DEBUG(1, __FUNCTION__"():sending connect_request...\n");
-
-	self->servicetype= servicetype;
-	/* ircomm_control_request(self, SERVICETYPE); */ /*servictype*/
-
-	self->rx_max_sdu_size = SAR_DISABLE;
-	ircomm_do_event(self, IRCOMM_CONNECT_REQUEST, NULL);
-}
-
-void ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata,
-			     __u32 max_sdu_size)
-{
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRCOMM_MAGIC, return;);
-	/* ASSERT( userdata != NULL, return;); */
-
-	DEBUG(4,"ircomm_connect_response:\n");
-
-	/*
-	 * TODO:build a packet which contains "initial control parameters"
-	 * and send it with connect_response
-	 */
-
-	if (!userdata){
-		/* FIXME: check for errors and initialize? DB */
-		userdata = dev_alloc_skb(COMM_DEFAULT_SDU_SIZE + COMM_MAX_HEADER_SIZE);
-		if (userdata == NULL)
-			return;
-
-		skb_reserve(userdata,COMM_MAX_HEADER_SIZE);
-	}
-
-	/* enable null-modem emulation (i.e. server mode )*/
-	self->null_modem_mode = 1;
-
-	self->rx_max_sdu_size = max_sdu_size;
-	
-	ircomm_do_event(self, IRCOMM_CONNECT_RESPONSE, userdata);
-}	
-
-void ircomm_disconnect_request(struct ircomm_cb *self, 
-			       struct sk_buff *userdata,
-			       int priority)
-{
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRCOMM_MAGIC, return;);
-	DEBUG(0,__FUNCTION__"()\n");
-
-#if 0
-	/* unregister layer */
-	switch (ircomm_cs) {
-	case 1:    /* client only */
-		irlmp_unregister_client(ckey);
-		break;
-
-	case 2:     /*  server only  */
-		irlmp_unregister_service(skey);
-		break;
-	case 0:
-	default:
-		irlmp_unregister_client(ckey);
-		irlmp_unregister_service(skey);
-		break;
-	}
-#endif
-
-	self->disconnect_priority = priority;
-	if(priority != P_HIGH)
-		self->disconnect_priority = P_NORMAL;
-
-	ircomm_do_event(self, IRCOMM_DISCONNECT_REQUEST, userdata);
-}	
-
-
-int ircomm_data_request(struct ircomm_cb *self, struct sk_buff *userdata)
-{
-	__u8 * frame;
-
-	DEBUG(4,__FUNCTION__"()\n");
-	ASSERT( self != NULL, return -EFAULT;);
-	ASSERT( self->magic == IRCOMM_MAGIC, return -EFAULT;);
-	ASSERT( userdata != NULL, return -EFAULT;);
-	
-
-	if(self->state != COMM_CONN){
-		DEBUG(4,__FUNCTION__"():not connected, data is ignored\n");
-		return -EINVAL;
-	}
-
-	if(self->ttp_stop)
-		return -EBUSY;
-
-	if(self->control_ch_pending){
-		/* send control_channel */
-		ircomm_tx_controlchannel(self);
-	}
-
-	if(self->ttp_stop)
-		return -EBUSY;
-
-	/* add "clen" field */
-	frame = skb_push(userdata,1);
-	frame[0]=0;          /* without control channel */
-
-	ircomm_do_event(self, IRCOMM_DATA_REQUEST, userdata);
-	return 0;
-}
-
-/*
- *  ----------------------------------------------------------------------
- *  IrCOMM_control.req and friends
- *
- *  ----------------------------------------------------------------------
- */
-
-
-static void ircomm_tx_controlchannel(struct ircomm_cb *self )
-{
-
-	__u8 clen;
-	struct sk_buff *skb = self->ctrl_skb;
-	
-	DEBUG(4,__FUNCTION__"()\n");
-	/* 'self' should have been checked */
-	ASSERT(!self->ttp_stop, return ;);
-	ASSERT(self->state == COMM_CONN, return ;);
-
-	/* add "clen" field */
-
-	clen=skb->len;
-	ASSERT(clen != 0,return;);
-
-	skb_push(skb,1);
-	skb->data[0]=clen;
-
-#if 0
-	printk("tx_ctrl:");
-	{
-		int i;
-		for ( i=0;i<skb->len;i++)
-			printk("%02x", skb->data[i]);
-		printk("\n");
-	}
-#endif
-	
-	ircomm_do_event(self, IRCOMM_CONTROL_REQUEST, skb);
-	self->control_ch_pending = 0;
-
-	skb = dev_alloc_skb(COMM_DEFAULT_SDU_SIZE + COMM_MAX_HEADER_SIZE);
-	ASSERT(skb != NULL, return ;);
-
-	skb_reserve(skb,COMM_MAX_HEADER_SIZE);
-	self->ctrl_skb = skb;
-}
-
-
-static void append_tuple(struct ircomm_cb *self, __u8 instruction, __u8 pl , 
-			 __u8 *value)
-{
-	__u8 *frame;
-	struct sk_buff *skb;
-	int i,c = 0;
-	unsigned long flags;
-
-	save_flags(flags);cli();
-
-	skb = self->ctrl_skb;
-	ASSERT(skb != NULL, return;);
-	
-	if(skb_tailroom(skb) < (pl+2)){
-		DEBUG(0, __FUNCTION__"there's no room.. ignore it\n");
-		self->ignored_control_tuples++;
-		restore_flags(flags);
-		return;
-	}
-
-	frame = skb_put(skb,pl+2);
-	frame[c++] = instruction;     /* PI */
-	frame[c++] = pl;              /* PL */
-	for(i=0; i < pl ; i++)
-		frame[c++] = *value++;   /* PV */
-	restore_flags(flags);	
-	self->pending_control_tuples++;
-	self->control_ch_pending = 1;
-}
-
-/*
- * Function ircomm_control_request (self, instruction)
- *
- *    This function is exported as a request to send some control-channel
- *    tuples * to peer device
- * 
- */
-void ircomm_control_request(struct ircomm_cb *self,  __u8 instruction)
-{
-
-	__u8  pv[32];      /* 32 max, for PORT_NAME */
-	__u8  *value = &pv[0];
-	__u32 temp;
-	int notsupp=0;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRCOMM_MAGIC, return;);
-
-	if(self->servicetype == THREE_WIRE_RAW){
-		DEBUG(0,__FUNCTION__"():THREE_WIRE_RAW shuold not use me!\n");
-		return;
-	}
-
-	DEBUG(4,__FUNCTION__"()\n");
-
-	/* find parameter and its length */
-
-	if(self->servicetype == THREE_WIRE) goto threewire;
-	if(self->servicetype == NINE_WIRE) goto ninewire;
-
-
-	/* FIXME: centronics service is not fully implemented yet*/
-	switch(instruction){
-	case IEEE1284_MODE_SUPPORT:
-	case IEEE1284_DEVICEID:
-		append_tuple(self,instruction,0,NULL);
-		break;
-	case STATUS_QUERY:
-		append_tuple(self,instruction,0,NULL);
-		break;
-	case SET_BUSY_TIMEOUT:
-		value[0] = self->busy_timeout;
-		append_tuple(self,instruction,1,value);
-		break;
- 	case IEEE1284_ECP_EPP_DATA_TRANSFER: 
-		value[0] = self->ecp_epp_mode;
-		value[1] = self->channel_or_addr;
-		append_tuple(self,instruction,2,value); 
-		break; 
-	default:
-		notsupp=1;
-	}
-
- ninewire:
-	switch(instruction){
-	case POLL_FOR_LINE_SETTINGS:
-		append_tuple(self,instruction,0,NULL);
-		break;
-	case DTELINE_STATE:		
-		if(self->null_modem_mode){
-			/* null modem emulation */
-
-			/* output RTS as CTS */
-
-			if(self->dte & DELTA_RTS)
-				value[0] = DELTA_CTS;
-			if(self->dte & MCR_RTS)
-				value[0] |= MSR_CTS;
-
-			/* output DTR as {DSR & CD & RI} */
-
-			if(self->dte & DELTA_DTR)
-				value[0] |= (DELTA_DSR|DELTA_RI|DELTA_DCD);
-			if(self->dte & MCR_DTR)
-				value[0] |= (MSR_DSR|MSR_RI|MSR_DCD);
-			append_tuple(self,DCELINE_STATE,1,value);
-		}else{
-			value[0] = self->dte;
-			append_tuple(self,instruction,1,value);
-		}
-		self->dte &= ~(DELTA_RTS|DELTA_DTR);
-		break;
-
-	case DCELINE_STATE:		
-		value[0] = self->dce;
-		append_tuple(self,instruction,1,value);
-		break;
-
-	default:
-		notsupp=1;
-	}
-
- threewire:
-	switch(instruction){
-
-	case SERVICETYPE:
-		value[0] = self->servicetype;
-		append_tuple(self,instruction,1,value);
-		break;
-
-	case DATA_FORMAT:
-		value[0] = self->data_format;
-		append_tuple(self,instruction,1,value);
-		break;
-
-	case FLOW_CONTROL:
-		if(self->null_modem_mode){
-			/* inside out */
-			value[0]  = (self->flow_ctrl & 0x55) << 1;
-			value[0] |= (self->flow_ctrl & 0xAA) >> 1;
-		}else{
-			value[0] = self->flow_ctrl;
-		}
-		append_tuple(self,instruction,1,value);
-		break;
-
-	case LINESTATUS:
-		value[0] = self->line_status;
-		append_tuple(self,instruction,1,value);
-		break;
-
-	case BREAK_SIGNAL:
-		value[0] = self->break_signal;
-		append_tuple(self,instruction,1,value);
-		break;
-
-	case XON_XOFF_CHAR:
-		value[0] = self->xon_char;
-		value[1] = self->xoff_char;
-		append_tuple(self,instruction,2,value); 
-		break; 
-
-	case ENQ_ACK_CHAR:
-		value[0] = self->enq_char;
-		value[1] = self->ack_char;
-		append_tuple(self,instruction,2,value); 
-		break; 
-
-	case DATA_RATE:
-		temp = self->data_rate;
-		value[3] = (__u8)((temp >> 24) & 0x000000ff);
-		value[2] = (__u8)((temp >> 16) & 0x000000ff);
-		value[1] = (__u8)((temp >> 8) & 0x000000ff);
-		value[0] = (__u8)(temp & 0x000000ff);
- 		append_tuple(self,instruction,4,value);
- 		break;
-#if 0
-	case PORT_NAME:
-	case FIXED_PORT_NAME:
-		temp = strlen(&self->port_name);
-		if(temp < 32){
-			value = (__u8) (self->port_name);
-			append_tuple(self,instruction,temp,value);
-		}else
-			DEBUG(0,__FUNCTION__"() PORT_NAME:too long\n");
-#endif
-		break;
-
-	default:
-		if(notsupp)
-			DEBUG(0,__FUNCTION__"():instruction(0x%02x)is not"
-			      "implemented\n",instruction);
-	}
-
-
-}
-
-void ircomm_parse_tuples(struct ircomm_cb *self, struct sk_buff *skb, int type)
-{
-
-	__u8 *data;
-	__u8 pi,plen;
-	int clen = 0;
-	int indicate=0;
-
-	ASSERT(skb != NULL, return;);
-	ASSERT(self != NULL, return ;);
-	ASSERT(self->magic == IRCOMM_MAGIC, return ;);
-
-
-#ifdef IRCOMM_DEBUG_TUPLE
-	DEBUG(0, __FUNCTION__"():tuple sequence is:\n");
-	{
-		int i;
-		for ( i=0;i< skb->len;i++)
-			printk("%02x", (__u8)(skb->data[i]));
-		printk("\n");
-	}
-#endif
-
-	data = skb->data;
-	if(type == IAS_PARAM)
-	{
-		clen = (data[0] << 8) & 0xff00;
-		clen |= data[1] & 0x00ff;
-		ASSERT( clen <= (skb->len - 2) && clen <= 1024, goto corrupted;);
-		DEBUG(4, __FUNCTION__"():IAS_PARAM len = %d\n",clen );
-		skb_pull( skb, 2);
-	}
-	else
-	{
-		/* CONTROL_CHANNEL */
-		clen = data[0];
-		ASSERT( clen < skb->len, goto corrupted;);
-		DEBUG(4, __FUNCTION__"():CONTROL_CHANNEL:len = %d\n",clen );
-		skb_pull( skb, 1);
-	}
-
-	while( clen >= 2 ){
-		data = skb->data;
-		indicate = 0;
-
-		/* 
-		 * parse controlparameters and set value into structure 
-		 */
-		pi = data[0];
-		plen = data[1];
-
-		ASSERT( clen >= 2+plen, goto corrupted; );
-		DEBUG(4, __FUNCTION__"():instruction=0x%02x,len=%d\n",
-		      pi, plen) ;
-
-
-		switch(pi)
-		{
-		case POLL_FOR_LINE_SETTINGS:
-			ircomm_control_request(self, DTELINE_STATE);
-			break;
-		
-		case SERVICETYPE:
-			self->peer_servicetype = data[2];
-			break;
-
-		case PORT_TYPE:
-			self->peer_port_type = data[2];
-			break;
-
-		case DATA_FORMAT:   
-			self->peer_data_format = data[2];
-			break;
-
-		case FLOW_CONTROL:
-			self->peer_flow_ctrl = data[2];
-			indicate = 1;
-			break;
-
-		case LINESTATUS:
-			self->peer_line_status = data[2];
-			indicate = 1;
-			break;
-
-		case BREAK_SIGNAL:
-			self->peer_break_signal = data[2];
-			/* indicate = 1; */
-			break;
-
-		case DCELINE_STATE:
-			self->peer_dce = data[2];
-			indicate = 1;
-			break;
-
-		case DTELINE_STATE:
-			if(self->null_modem_mode){
-				/* input DTR as {DSR & CD & RI} */
-				self->peer_dce = 0;
-				if(data[2] & DELTA_DTR)
-					self->peer_dce |= (DELTA_DSR|
-							   DELTA_RI|
-							   DELTA_DCD);
-				if(data[2] & MCR_DTR)
-					self->peer_dce |= (MSR_DSR|
-							   MSR_RI|
-							   MSR_DCD);
-				/* rts as cts */
-				if(data[2] & DELTA_RTS)
-					self->peer_dce |= DELTA_CTS;
-				if(data[2] & MCR_RTS)
-					self->peer_dce |= MSR_CTS;
-			}else{
-				self->peer_dte = data[2];
-			}
-			indicate = 1;			
-			break;
-			
-		case XON_XOFF_CHAR:
-			self->peer_xon_char = data[2];
-			self->peer_xoff_char = data[3];
-			indicate = 1;
-			break;
-
-		case ENQ_ACK_CHAR:
-			self->peer_enq_char = data[2];
-			self->peer_ack_char = data[3];
-			indicate = 1;
-			break;
-
-		case DATA_RATE:
-			self->peer_data_rate = (  data[5]<<24
-						  & data[4]<<16
-						  & data[3]<<8
-						  & data[2]);
-			indicate = 1;
-			break;
-
-		case PORT_NAME:
-			ASSERT(plen <= 32 , goto corrupted;);
-			memcpy(self->port_name, data + 2, plen);
-			*(__u8 *)(self->port_name+plen) = 0;
-			break;
-
-		case FIXED_PORT_NAME:
-			ASSERT(plen <= 32 , goto corrupted;);
-			memcpy(self->port_name, data + 2, plen);
-			*(__u8 *)(self->port_name+plen) = 0;
-			/* 
-			 * We should not connect if user of IrCOMM can't
-			 * recognize the port name
-			 */
-			self->port_name_critical = TRUE;
-			break;
-
-		default:
-			DEBUG(0, __FUNCTION__
-			      "():not implemented (PI=%d)\n", pi);
-		}
-
-
-		if(indicate && 
-		   self->notify.flow_indication && type == CONTROL_CHANNEL)
-		{
-			DEBUG(4,__FUNCTION__":indicating..:\n");
-			self->pi = pi;
-			if(self->notify.flow_indication)
-				self->notify.flow_indication(self->notify.instance,
-							     self,
-							     CONTROL_CHANNEL);
-		}
-		skb_pull(skb, 2+plen);
-		clen -= (2+plen);
-	}
-
-	return;
-
- corrupted:
-	skb_pull(skb, skb->len);   /* remove suspicious data */
-	return;
-}
-
-/*
- * ----------------------------------------------------------------------
- * Function ircomm_open_instance() ,ircomm_close_instance() and friends
- *
- * ircomm_open_instance discoveres the peer device and then issues a
- * connect request
- * ----------------------------------------------------------------------
- */
-
-
-
-struct ircomm_cb * ircomm_open_instance( struct notify_t client_notify)
-{
-	int i;
-	struct ircomm_cb *self = NULL;
-	struct notify_t notify;
-	unsigned long flags;
-
-	ASSERT(ircomm != NULL,return NULL;);
-	DEBUG(0,__FUNCTION__"():\n");
-
-	/* find free handle */
-
-	save_flags(flags);
-	cli();
-	for(i = 0; i < IRCOMM_MAX_CONNECTION; i++){
-		ASSERT(ircomm[i] != NULL,return(NULL););
-		if(!ircomm[i]->in_use){
-			self = ircomm[i];
-			break;
-		}
-	}
-
-	if (!self){
-		DEBUG(0,__FUNCTION__"():no free handle!\n");
-		return (NULL);
-	}
-
-	self->in_use = 1;
-	restore_flags(flags);
-
-	self->notify = client_notify;
-	self->ttp_stop = 0;
-	self->control_ch_pending = 0;
-
-	/* register callbacks */
-
-	irda_notify_init(&notify);
-	notify.data_indication = ircomm_accept_data_indication;
-	notify.connect_confirm = ircomm_accept_connect_confirm;
-	notify.connect_indication = ircomm_accept_connect_indication;
-	notify.flow_indication = ircomm_accept_flow_indication;
-	notify.disconnect_indication = ircomm_accept_disconnect_indication;
-	notify.instance = self;
-	strncpy( notify.name, "IrCOMM", NOTIFY_MAX_NAME);
-
-	self->tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT,
-				     &notify);
-	if(!self->tsap){
-		DEBUG(0,__FUNCTION__"failed to allocate tsap\n");
-		return NULL;
-	}
-
-	ircomm_next_state(self, COMM_IDLE);	
-	return (self);
-}
-
-int ircomm_close_instance(struct ircomm_cb *self)
-{
-	ASSERT( self != NULL, return -EIO;);
-	ASSERT( self->magic == IRCOMM_MAGIC, return -EIO;);
-	ASSERT( self->ctrl_skb != NULL, return -EIO;);
-
-	DEBUG(0,__FUNCTION__"()\n");
-
-	/* shutdown ircomm layer */
-	if(self->state != COMM_IDLE && self->state != COMM_WAITI)
-	{
-		DEBUG(0,__FUNCTION__"():force disconnecting..\n");
-		ircomm_disconnect_request(self, NULL, P_HIGH);
-	}
-
-	skb_trim(self->ctrl_skb,0);
-	/* remove a tsap */
-	if(self->tsap)
-		irttp_close_tsap(self->tsap);
-	self->tsap = NULL;
-	self->in_use = 0;
-	return 0;
-}
-
-
-/*
- * ----------------------------------------------------------------------
- * Function init_module(void) ,cleanup_module()
- *
- *   Initializes the ircomm control structure
- *   These Function are called when you insmod / rmmod .
- * ----------------------------------------------------------------------
- */
-
-#ifdef MODULE
-int init_module(void) 
-{
-	int err;
-
-	err = ircomm_init();
-
-	DEBUG( 4, __FUNCTION__"():done.\n");
-	return err;
-}
-	
-void cleanup_module(void)
-{
-	ircomm_cleanup();
-	DEBUG( 4, __FUNCTION__"():done.\n");
-}
-#endif /* MODULE */
-
-/************************************************************
- *     proc stuff
- ************************************************************/
-
-#ifdef CONFIG_PROC_FS
-
-/*
- * Function proc_ircomm_read (buf, start, offset, len, unused)
- *
- * this function is called if there is a access on /proc/irda/comm .
- *
- */
-int ircomm_proc_read(char *buf, char **start, off_t offset,
-		     int len, int unused)
-{
-	int i, index;
-
-	len = 0;
-	for (i=0; i<IRCOMM_MAX_CONNECTION; i++) {
-
-		len += sprintf(buf+len, "instance %d:\n",i);
-		if(ircomm[i]->in_use == 0){
-			len += sprintf(buf+len, "\tunused\n");
-			continue;
-		}
-
-		if (ircomm[i] == NULL || ircomm[i]->magic != IRCOMM_MAGIC) {
-			len += sprintf(buf+len, "\tbroken???\n");
-			continue;
-		}
-
-		switch (ircomm[i]->servicetype) {
-		case UNKNOWN:
-			index = 0;
-			break;
-		case THREE_WIRE_RAW:
-			index = 1;
-			break;
-		case THREE_WIRE:
-			index = 2;
-			break;
-		case NINE_WIRE:
-			index = 3;
-			break;
-		case CENTRONICS:
-			index = 4;
-			break;
-		default:
-			index = 0;
-			break;
-		}
-		len += sprintf(buf+len, "    service: %s  ",
-			       ircommservicetype[index]);
-		if(!index)
-			continue;
-
-		len += sprintf(buf+len, "porttype: %s  ",
-			       ircommporttype[ircomm[i]->port_type]);
-		len += sprintf(buf+len, "state: %s  ",
-			       ircommstate[ircomm[i]->state]);
-		len += sprintf(buf+len, "user: %s\n",
-			       ircomm[i]->notify.name);
-		
-		len += sprintf(buf+len, "    tx packets: %d  ",
-			       ircomm[i]->tx_packets);
-		len += sprintf(buf+len, "rx packets: %d  ",
-			       ircomm[i]->rx_packets);
-		len += sprintf(buf+len, "tx controls: %d\n",
-			       ircomm[i]->tx_controls);
-		
-		len += sprintf(buf+len, "    pending tuples: %d  ",
-			       ircomm[i]->pending_control_tuples);
-		len += sprintf(buf+len, "    ignored tuples: %d\n",
-			       ircomm[i]->ignored_control_tuples);
-		
-		len += sprintf(buf+len, "    nullmodem emulation: %s  ",
-			       (ircomm[i]->null_modem_mode ? "yes":"no"));
-		len += sprintf(buf+len, "IrTTP: %s\n",
-			       (ircomm[i]->ttp_stop ? "BUSY":"READY"));
-
-		len += sprintf(buf+len, "    Peer capability: ");
-		if(ircomm[i]->peer_cap & THREE_WIRE_RAW)
-			len += sprintf(buf+len, "3wire-raw ");
-		if(ircomm[i]->peer_cap & THREE_WIRE)
-			len += sprintf(buf+len, "3wire ");
-		if(ircomm[i]->peer_cap & NINE_WIRE)
-			len += sprintf(buf+len, "9wire ");
-		if(ircomm[i]->peer_cap & CENTRONICS)
-			len += sprintf(buf+len, "centronics");
-
-		len += sprintf(buf+len, "\n    Port name: %s\n",
-			       (ircomm[i]->port_name));
-	}
-
-	return len;
-}
-
-#endif /* CONFIG_PROC_FS */
-
-
-
-
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/ircomm/ircomm_core.c linux.15p9/net/irda/ircomm/ircomm_core.c
--- linux.vanilla/net/irda/ircomm/ircomm_core.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/net/irda/ircomm/ircomm_core.c	Tue Jan 18 01:08:18 2000
@@ -0,0 +1,527 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_core.c
+ * Version:       1.0
+ * Description:   IrCOMM service interface
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Jun  6 20:37:34 1999
+ * Modified at:   Tue Dec 21 13:26:41 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/iriap.h>
+#include <net/irda/irttp.h>
+#include <net/irda/irias_object.h>
+
+#include <net/irda/ircomm_event.h>
+#include <net/irda/ircomm_lmp.h>
+#include <net/irda/ircomm_ttp.h>
+#include <net/irda/ircomm_param.h>
+#include <net/irda/ircomm_core.h>
+
+static int __ircomm_close(struct ircomm_cb *self);
+static void ircomm_control_indication(struct ircomm_cb *self, 
+				      struct sk_buff *skb, int clen);
+
+#ifdef CONFIG_PROC_FS
+static int ircomm_proc_read(char *buf, char **start, off_t offset, int len, 
+			    int unused);
+
+extern struct proc_dir_entry *proc_irda;
+#endif /* CONFIG_PROC_FS */
+
+hashbin_t *ircomm = NULL;
+
+int __init ircomm_init(void)
+{
+	ircomm = hashbin_new(HB_LOCAL); 
+	if (ircomm == NULL) {
+		ERROR(__FUNCTION__ "(), can't allocate hashbin!\n");
+		return -ENOMEM;
+	}
+	
+#ifdef CONFIG_PROC_FS
+	create_proc_entry("ircomm", 0, proc_irda)->get_info = ircomm_proc_read;
+#endif /* CONFIG_PROC_FS */
+	
+	MESSAGE("IrCOMM protocol (Dag Brattli)\n");
+		
+	return 0;
+}
+
+#ifdef MODULE
+void ircomm_cleanup(void)
+{
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	hashbin_delete(ircomm, (FREE_FUNC) __ircomm_close);
+
+#ifdef CONFIG_PROC_FS
+	remove_proc_entry("ircomm", proc_irda);
+#endif /* CONFIG_PROC_FS */
+}
+#endif /* MODULE */
+
+/*
+ * Function ircomm_open (client_notify)
+ *
+ *    Start a new IrCOMM instance
+ *
+ */
+struct ircomm_cb *ircomm_open(notify_t *notify, __u8 service_type, int line)
+{
+	struct ircomm_cb *self = NULL;
+	int ret;
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), service_type=0x%02x\n",
+		   service_type);
+
+	ASSERT(ircomm != NULL, return NULL;);
+
+	self = kmalloc(sizeof(struct ircomm_cb), GFP_ATOMIC);
+	if (self == NULL)
+		return NULL;
+
+	memset(self, 0, sizeof(struct ircomm_cb));
+
+	self->notify = *notify;
+	self->magic = IRCOMM_MAGIC;
+
+	/* Check if we should use IrLMP or IrTTP */
+	if (service_type & IRCOMM_3_WIRE_RAW) {
+		self->flow_status = FLOW_START;
+		ret = ircomm_open_lsap(self);
+	} else
+		ret = ircomm_open_tsap(self);
+
+	if (ret < 0)
+		return NULL;
+
+	self->service_type = service_type;
+	self->line = line;
+
+	hashbin_insert(ircomm, (queue_t *) self, line, NULL);
+
+	ircomm_next_state(self, IRCOMM_IDLE);	
+
+	return self;
+}
+
+/*
+ * Function ircomm_close_instance (self)
+ *
+ *    Remove IrCOMM instance
+ *
+ */
+static int __ircomm_close(struct ircomm_cb *self)
+{
+	IRDA_DEBUG(2, __FUNCTION__"()\n");
+
+	/* Disconnect link if any */
+	ircomm_do_event(self, IRCOMM_DISCONNECT_REQUEST, NULL, NULL);
+
+	/* Remove TSAP */
+	if (self->tsap) {
+		irttp_close_tsap(self->tsap);
+		self->tsap = NULL;
+	}
+
+	/* Remove LSAP */
+	if (self->lsap) {
+		irlmp_close_lsap(self->lsap);
+		self->lsap = NULL;
+	}
+	self->magic = 0;
+
+	kfree(self);
+
+	return 0;
+}
+
+/*
+ * Function ircomm_close (self)
+ *
+ *    Closes and removes the specified IrCOMM instance
+ *
+ */
+int ircomm_close(struct ircomm_cb *self)
+{
+	struct ircomm_cb *entry;
+
+	ASSERT(self != NULL, return -EIO;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return -EIO;);
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	entry = hashbin_remove(ircomm, self->line, NULL);
+
+	ASSERT(entry == self, return -1;);
+	
+        return __ircomm_close(self);
+}
+
+/*
+ * Function ircomm_connect_request (self, service_type)
+ *
+ *    Impl. of this function is differ from one of the reference. This
+ *    function does discovery as well as sending connect request
+ * 
+ */
+int ircomm_connect_request(struct ircomm_cb *self, __u8 dlsap_sel, 
+			   __u32 saddr, __u32 daddr, struct sk_buff *skb,
+			   __u8 service_type)
+{
+	struct ircomm_info info;
+	int ret;
+
+	IRDA_DEBUG(2 , __FUNCTION__"()\n");
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
+
+	self->service_type= service_type;
+
+	info.dlsap_sel = dlsap_sel;
+	info.saddr = saddr;
+	info.daddr = daddr;
+
+	ret = ircomm_do_event(self, IRCOMM_CONNECT_REQUEST, skb, &info);
+
+	return ret;
+}
+
+/*
+ * Function ircomm_connect_indication (self, qos, skb)
+ *
+ *    Notify user layer about the incomming connection
+ *
+ */
+void ircomm_connect_indication(struct ircomm_cb *self, struct sk_buff *skb,
+			       struct ircomm_info *info)
+{
+	int clen = 0;
+	
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	/* Check if the packet contains data on the control channel */
+	if (skb->len > 0)
+		clen = skb->data[0];
+	
+	/* 
+	 * If there are any data hiding in the control channel, we must 
+	 * deliver it first. The side effect is that the control channel 
+	 * will be removed from the skb
+	 */
+	if (self->notify.connect_indication)
+		self->notify.connect_indication(self->notify.instance, self, 
+						info->qos, info->max_data_size,
+						info->max_header_size, skb);
+	else {
+		IRDA_DEBUG(0, __FUNCTION__ "(), missing handler\n");
+		dev_kfree_skb(skb);
+	}
+}
+
+/*
+ * Function ircomm_connect_response (self, userdata, max_sdu_size)
+ *
+ *    User accepts connection
+ *
+ */
+int ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata)
+{
+	int ret;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
+
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+	ret = ircomm_do_event(self, IRCOMM_CONNECT_RESPONSE, userdata, NULL);
+
+	return ret;
+}	
+
+/*
+ * Function connect_confirm (self, skb)
+ *
+ *    Notify user layer that the link is now connected
+ *
+ */
+void ircomm_connect_confirm(struct ircomm_cb *self, struct sk_buff *skb,
+			    struct ircomm_info *info)
+{
+	IRDA_DEBUG(4, __FUNCTION__"()\n");
+
+	if (self->notify.connect_confirm )
+		self->notify.connect_confirm(self->notify.instance,
+					     self, info->qos, 
+					     info->max_data_size,
+					     info->max_header_size, skb);
+	else {
+		IRDA_DEBUG(0, __FUNCTION__ "(), missing handler\n");
+		dev_kfree_skb(skb);
+	}
+}
+
+/*
+ * Function ircomm_data_request (self, userdata)
+ *
+ *    Send IrCOMM data to peer device
+ *
+ */
+int ircomm_data_request(struct ircomm_cb *self, struct sk_buff *skb)
+{
+	int ret;
+
+	IRDA_DEBUG(4, __FUNCTION__"()\n");
+
+	ASSERT(self != NULL, return -EFAULT;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return -EFAULT;);
+	ASSERT(skb != NULL, return -EFAULT;);
+	
+	ret = ircomm_do_event(self, IRCOMM_DATA_REQUEST, skb, NULL);
+
+	return ret;
+}
+
+/*
+ * Function ircomm_data_indication (self, skb)
+ *
+ *    Data arrived, so deliver it to user
+ *
+ */
+void ircomm_data_indication(struct ircomm_cb *self, struct sk_buff *skb)
+{	
+	IRDA_DEBUG(4, __FUNCTION__"()\n");
+
+	ASSERT(skb->len > 0, return;);
+
+	if (self->notify.data_indication)
+		self->notify.data_indication(self->notify.instance, self, skb);
+	else {
+		IRDA_DEBUG(0, __FUNCTION__ "(), missing handler\n");
+		dev_kfree_skb(skb);
+	}
+}
+
+/*
+ * Function ircomm_process_data (self, skb)
+ *
+ *    Data arrived which may contain control channel data
+ *
+ */
+void ircomm_process_data(struct ircomm_cb *self, struct sk_buff *skb)
+{
+	int clen;
+
+	ASSERT(skb->len > 0, return;);
+
+	clen = skb->data[0];
+
+	/* 
+	 * If there are any data hiding in the control channel, we must 
+	 * deliver it first. The side effect is that the control channel 
+	 * will be removed from the skb
+	 */
+	if (clen > 0)
+		ircomm_control_indication(self, skb, clen);
+
+	/* Remove control channel from data channel */
+	skb_pull(skb, clen+1);
+
+	if (skb->len)
+		ircomm_data_indication(self, skb);		
+	else {
+		IRDA_DEBUG(4, __FUNCTION__ 
+			   "(), data was control info only!\n");
+		dev_kfree_skb(skb);
+	}
+}
+
+/*
+ * Function ircomm_control_request (self, params)
+ *
+ *    Send control data to peer device
+ *
+ */
+int ircomm_control_request(struct ircomm_cb *self, struct sk_buff *skb)
+{
+	int ret;
+	
+	IRDA_DEBUG(2, __FUNCTION__"()\n");
+
+	ASSERT(self != NULL, return -EFAULT;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return -EFAULT;);
+	ASSERT(skb != NULL, return -EFAULT;);
+	
+	ret = ircomm_do_event(self, IRCOMM_CONTROL_REQUEST, skb, NULL);
+
+	return ret;
+}
+
+/*
+ * Function ircomm_control_indication (self, skb)
+ *
+ *    Data has arrived on the control channel
+ *
+ */
+static void ircomm_control_indication(struct ircomm_cb *self, 
+				      struct sk_buff *skb, int clen)
+{
+	struct sk_buff *ctrl_skb;
+
+	IRDA_DEBUG(2, __FUNCTION__"()\n");	
+
+	ctrl_skb = skb_clone(skb, GFP_ATOMIC);
+	if (!ctrl_skb)
+		return;
+
+	/* Remove data channel from control channel */
+	skb_trim(ctrl_skb, clen+1);
+	
+	/* Use udata for delivering data on the control channel */
+	if (self->notify.udata_indication)
+		self->notify.udata_indication(self->notify.instance, self, 
+					      ctrl_skb);
+	else {
+		IRDA_DEBUG(0, __FUNCTION__ "(), missing handler\n");
+		dev_kfree_skb(skb);
+	}
+}
+
+/*
+ * Function ircomm_disconnect_request (self, userdata, priority)
+ *
+ *    User layer wants to disconnect the IrCOMM connection
+ *
+ */
+int ircomm_disconnect_request(struct ircomm_cb *self, struct sk_buff *userdata)
+{
+	struct ircomm_info info;
+	int ret;
+
+	IRDA_DEBUG(2, __FUNCTION__"()\n");
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
+
+	ret = ircomm_do_event(self, IRCOMM_DISCONNECT_REQUEST, userdata, 
+			      &info);
+	return ret;
+}
+
+/*
+ * Function disconnect_indication (self, skb)
+ *
+ *    Tell user that the link has been disconnected
+ *
+ */
+void ircomm_disconnect_indication(struct ircomm_cb *self, struct sk_buff *skb,
+				  struct ircomm_info *info)
+{
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+       
+	ASSERT(info != NULL, return;);
+
+	if (self->notify.disconnect_indication) {
+		self->notify.disconnect_indication(self->notify.instance, self,
+						   info->reason, skb);
+	} else {
+		IRDA_DEBUG(0, __FUNCTION__ "(), missing handler\n");
+		dev_kfree_skb(skb);
+	}
+}
+
+/*
+ * Function ircomm_flow_request (self, flow)
+ *
+ *    
+ *
+ */
+void ircomm_flow_request(struct ircomm_cb *self, LOCAL_FLOW flow)
+{
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return;);
+
+	if (self->service_type == IRCOMM_3_WIRE_RAW)
+		return;
+
+	irttp_flow_request(self->tsap, flow);
+}
+
+#ifdef CONFIG_PROC_FS
+/*
+ * Function ircomm_proc_read (buf, start, offset, len, unused)
+ *
+ *    
+ *
+ */
+int ircomm_proc_read(char *buf, char **start, off_t offset, int len, 
+		     int unused)
+{ 	
+	struct ircomm_cb *self;
+	unsigned long flags;
+	int i=0;
+	
+	save_flags(flags);
+	cli();
+
+	len = 0;
+
+	len += sprintf(buf+len, "Instance %d:\n", i++);
+
+	self = (struct ircomm_cb *) hashbin_get_first(ircomm);
+	while (self != NULL) {
+		ASSERT(self->magic == IRCOMM_MAGIC, return len;);
+
+		self = (struct ircomm_cb *) hashbin_get_next(ircomm);
+ 	} 
+	restore_flags(flags);
+
+	return len;
+}
+#endif /* CONFIG_PROC_FS */
+
+#ifdef MODULE
+int init_module(void) 
+{
+	return ircomm_init();
+}
+	
+void cleanup_module(void)
+{
+	ircomm_cleanup();
+}
+#endif /* MODULE */
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/ircomm/ircomm_event.c linux.15p9/net/irda/ircomm/ircomm_event.c
--- linux.vanilla/net/irda/ircomm/ircomm_event.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/net/irda/ircomm/ircomm_event.c	Tue Jan 18 01:08:18 2000
@@ -0,0 +1,257 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_event.c
+ * Version:       1.0
+ * Description:   IrCOMM layer state machine
+ * Status:        Stable
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Jun  6 20:33:11 1999
+ * Modified at:   Sun Dec 12 13:44:32 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/iriap.h>
+#include <net/irda/irttp.h>
+#include <net/irda/irias_object.h>
+
+#include <net/irda/ircomm_core.h>
+#include <net/irda/ircomm_event.h>
+
+static int ircomm_state_idle(struct ircomm_cb *self, IRCOMM_EVENT event, 
+			     struct sk_buff *skb, struct ircomm_info *info);
+static int ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event, 
+			      struct sk_buff *skb, struct ircomm_info *info);
+static int ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event, 
+			      struct sk_buff *skb, struct ircomm_info *info);
+static int ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event, 
+			     struct sk_buff *skb, struct ircomm_info *info);
+
+char *ircomm_state[] = {
+	"IRCOMM_IDLE",
+	"IRCOMM_WAITI",
+	"IRCOMM_WAITR",
+	"IRCOMM_CONN",
+};
+
+char *ircomm_event[] = {
+	"IRCOMM_CONNECT_REQUEST",
+        "IRCOMM_CONNECT_RESPONSE",
+        "IRCOMM_TTP_CONNECT_INDICATION",
+	"IRCOMM_LMP_CONNECT_INDICATION",
+        "IRCOMM_TTP_CONNECT_CONFIRM",
+	"IRCOMM_LMP_CONNECT_CONFIRM",
+
+        "IRCOMM_LMP_DISCONNECT_INDICATION",
+	"IRCOMM_TTP_DISCONNECT_INDICATION",
+        "IRCOMM_DISCONNECT_REQUEST",
+
+        "IRCOMM_TTP_DATA_INDICATION",
+	"IRCOMM_LMP_DATA_INDICATION",
+        "IRCOMM_DATA_REQUEST",
+        "IRCOMM_CONTROL_REQUEST",
+        "IRCOMM_CONTROL_INDICATION",
+};
+
+static int (*state[])(struct ircomm_cb *self, IRCOMM_EVENT event,
+		      struct sk_buff *skb, struct ircomm_info *info) = 
+{
+	ircomm_state_idle,
+	ircomm_state_waiti,
+	ircomm_state_waitr,
+	ircomm_state_conn,
+};
+
+/*
+ * Function ircomm_state_idle (self, event, skb)
+ *
+ *    IrCOMM is currently idle
+ *
+ */
+static int ircomm_state_idle(struct ircomm_cb *self, IRCOMM_EVENT event, 
+			     struct sk_buff *skb, struct ircomm_info *info)
+{
+	int ret = 0;
+
+	switch (event) {
+	case IRCOMM_CONNECT_REQUEST:
+		ircomm_next_state(self, IRCOMM_WAITI);		
+		ret = self->issue.connect_request(self, skb, info);
+		break;
+	case IRCOMM_TTP_CONNECT_INDICATION:
+	case IRCOMM_LMP_CONNECT_INDICATION:
+		ircomm_next_state(self, IRCOMM_WAITR);
+		ircomm_connect_indication(self, skb, info);
+		break;
+	default:
+		IRDA_DEBUG(4, __FUNCTION__"(), unknown event: %s\n",
+			   ircomm_event[event]);
+		if (skb)
+			dev_kfree_skb(skb);
+		return -EINVAL;
+	}
+	return ret;
+}
+
+/*
+ * Function ircomm_state_waiti (self, event, skb)
+ *
+ *    The IrCOMM user has requested an IrCOMM connection to the remote 
+ *    device and is awaiting confirmation
+ */
+static int ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event, 
+			      struct sk_buff *skb, struct ircomm_info *info)
+{
+	int ret = 0;
+
+	switch (event) {
+	case IRCOMM_TTP_CONNECT_CONFIRM:
+	case IRCOMM_LMP_CONNECT_CONFIRM:
+		ircomm_next_state(self, IRCOMM_CONN);
+		ircomm_connect_confirm(self, skb, info);
+		break;
+	case IRCOMM_TTP_DISCONNECT_INDICATION:
+	case IRCOMM_LMP_DISCONNECT_INDICATION:
+		ircomm_next_state(self, IRCOMM_IDLE);
+		ircomm_disconnect_indication(self, skb, info);
+		break;
+	default:
+		IRDA_DEBUG(0, __FUNCTION__"(), unknown event: %s\n",
+			   ircomm_event[event]);
+		if (skb)
+			dev_kfree_skb(skb);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+/*
+ * Function ircomm_state_waitr (self, event, skb)
+ *
+ *    IrCOMM has received an incomming connection request and is awaiting
+ *    response from the user
+ */
+static int ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event, 
+			      struct sk_buff *skb, struct ircomm_info *info) 
+{
+	int ret = 0;
+
+	switch (event) {
+	case IRCOMM_CONNECT_RESPONSE:
+		ircomm_next_state(self, IRCOMM_CONN);
+		ret = self->issue.connect_response(self, skb);
+		break;
+	case IRCOMM_DISCONNECT_REQUEST:
+		ircomm_next_state(self, IRCOMM_IDLE);
+		ret = self->issue.disconnect_request(self, skb, info);
+		break;
+	case IRCOMM_TTP_DISCONNECT_INDICATION:
+	case IRCOMM_LMP_DISCONNECT_INDICATION:
+		ircomm_next_state(self, IRCOMM_IDLE);
+		ircomm_disconnect_indication(self, skb, info);
+		break;
+	default:
+		IRDA_DEBUG(0, __FUNCTION__ "(), unknown event = %s\n",
+			   ircomm_event[event]);
+		if (skb)
+			dev_kfree_skb(skb);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+/*
+ * Function ircomm_state_conn (self, event, skb)
+ *
+ *    IrCOMM is connected to the peer IrCOMM device
+ *
+ */
+static int ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event, 
+			     struct sk_buff *skb, struct ircomm_info *info)
+{
+	int ret = 0;
+
+	switch (event) {
+	case IRCOMM_DATA_REQUEST:
+		ret = self->issue.data_request(self, skb, 0);
+		break;
+	case IRCOMM_TTP_DATA_INDICATION:
+		ircomm_process_data(self, skb);
+		break;
+	case IRCOMM_LMP_DATA_INDICATION:
+		ircomm_data_indication(self, skb);
+		break;
+	case IRCOMM_CONTROL_REQUEST:
+		/* Just send a separate frame for now */
+		ret = self->issue.data_request(self, skb, skb->len);
+		break;
+	case IRCOMM_TTP_DISCONNECT_INDICATION:
+	case IRCOMM_LMP_DISCONNECT_INDICATION:
+		ircomm_next_state(self, IRCOMM_IDLE);
+		ircomm_disconnect_indication(self, skb, info);
+		break;
+	case IRCOMM_DISCONNECT_REQUEST:
+		ircomm_next_state(self, IRCOMM_IDLE);
+		ret = self->issue.disconnect_request(self, skb, info);
+		break;
+	default:
+		IRDA_DEBUG(0, __FUNCTION__ "(), unknown event = %s\n",
+			   ircomm_event[event]);
+		if (skb)
+			dev_kfree_skb(skb);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+/*
+ * Function ircomm_do_event (self, event, skb)
+ *
+ *    Process event
+ *
+ */
+int ircomm_do_event(struct ircomm_cb *self, IRCOMM_EVENT event,
+		    struct sk_buff *skb, struct ircomm_info *info) 
+{
+	IRDA_DEBUG(4, __FUNCTION__": state=%s, event=%s\n",
+		   ircomm_state[self->state], ircomm_event[event]);
+
+	return (*state[self->state])(self, event, skb, info);
+}
+
+/*
+ * Function ircomm_next_state (self, state)
+ *
+ *    Switch state
+ *
+ */
+void ircomm_next_state(struct ircomm_cb *self, IRCOMM_STATE state)
+{
+	self->state = state;
+	
+	IRDA_DEBUG(4, __FUNCTION__": next state=%s, service type=%d\n", 
+		   ircomm_state[self->state], self->service_type);
+}
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/ircomm/ircomm_lmp.c linux.15p9/net/irda/ircomm/ircomm_lmp.c
--- linux.vanilla/net/irda/ircomm/ircomm_lmp.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/net/irda/ircomm/ircomm_lmp.c	Tue Jan 18 01:08:18 2000
@@ -0,0 +1,322 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_lmp.c
+ * Version:       1.0
+ * Description:   Interface between IrCOMM and IrLMP
+ * Status:        Stable
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Jun  6 20:48:27 1999
+ * Modified at:   Sun Dec 12 13:44:17 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * Sources:       Previous IrLPT work by Thomas Davis
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/iriap.h>
+
+#include <net/irda/ircomm_event.h>
+#include <net/irda/ircomm_lmp.h>
+
+/*
+ * Function ircomm_open_lsap (self)
+ *
+ *    Open LSAP. This function will only be used when using "raw" services
+ *
+ */
+int ircomm_open_lsap(struct ircomm_cb *self)
+{
+	notify_t notify;
+	
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+	
+        /* Register callbacks */
+        irda_notify_init(&notify);
+	notify.data_indication       = ircomm_lmp_data_indication;
+	notify.connect_confirm       = ircomm_lmp_connect_confirm;
+        notify.connect_indication    = ircomm_lmp_connect_indication;
+	notify.disconnect_indication = ircomm_lmp_disconnect_indication;
+	notify.instance = self;
+	strncpy(notify.name, "IrCOMM", NOTIFY_MAX_NAME);
+
+	self->lsap = irlmp_open_lsap(LSAP_ANY, &notify, 0);
+	if (!self->lsap) {
+		IRDA_DEBUG(0,__FUNCTION__"failed to allocate tsap\n");
+		return -1;
+	}
+	self->slsap_sel = self->lsap->slsap_sel;
+
+	/*
+	 *  Initialize the call-table for issuing commands
+	 */
+	self->issue.data_request       = ircomm_lmp_data_request;
+	self->issue.connect_request    = ircomm_lmp_connect_request;
+	self->issue.connect_response   = ircomm_lmp_connect_response;
+	self->issue.disconnect_request = ircomm_lmp_disconnect_request;
+
+	return 0;
+}
+
+/*
+ * Function ircomm_lmp_connect_request (self, userdata)
+ *
+ *    
+ *
+ */
+int ircomm_lmp_connect_request(struct ircomm_cb *self, 
+			       struct sk_buff *userdata, 
+			       struct ircomm_info *info)
+{
+	int ret = 0;
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	ret = irlmp_connect_request(self->lsap, info->dlsap_sel,
+				    info->saddr, info->daddr, NULL, userdata); 
+	return ret;
+}	
+
+/*
+ * Function ircomm_lmp_connect_response (self, skb)
+ *
+ *    
+ *
+ */
+int ircomm_lmp_connect_response(struct ircomm_cb *self, struct sk_buff *skb)
+{
+	int ret;
+
+	IRDA_DEBUG(0, __FUNCTION__"()\n");
+	
+	ret = irlmp_connect_response(self->lsap, skb);
+
+	return 0;
+}
+
+int ircomm_lmp_disconnect_request(struct ircomm_cb *self, 
+				  struct sk_buff *userdata, 
+				  struct ircomm_info *info)
+{
+        struct sk_buff *skb;
+	int ret;
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+        if (!userdata) {
+                skb = dev_alloc_skb(64);
+		if (!skb)
+			return -ENOMEM;
+		
+		/*  Reserve space for MUX and LAP header */
+		skb_reserve(skb, LMP_MAX_HEADER);		
+		userdata = skb;
+	}
+	ret = irlmp_disconnect_request(self->lsap, userdata);
+
+	return ret;
+}
+
+/*
+ * Function ircomm_lmp_flow_control (skb)
+ *
+ *    This function is called when a data frame we have sent to IrLAP has
+ *    been deallocated. We do this to make sure we don't flood IrLAP with 
+ *    frames, since we are not using the IrTTP flow control mechanism
+ */
+void ircomm_lmp_flow_control(struct sk_buff *skb)
+{
+	struct irda_skb_cb *cb;
+	struct ircomm_cb *self;
+	int line;
+
+	ASSERT(skb != NULL, return;);
+
+	cb = (struct irda_skb_cb *) skb->cb;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+ 
+        line = cb->line;
+
+	self = (struct ircomm_cb *) hashbin_find(ircomm, line, NULL);
+        if (!self) {
+		IRDA_DEBUG(2, __FUNCTION__ "(), didn't find myself\n");
+                return;
+	}
+
+        ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return;);
+
+	self->pkt_count--;
+
+        if ((self->pkt_count < 2) && (self->flow_status == FLOW_STOP)) {
+                IRDA_DEBUG(2, __FUNCTION__ "(), asking TTY to start again!\n");
+                self->flow_status = FLOW_START;
+                if (self->notify.flow_indication)
+                        self->notify.flow_indication(self->notify.instance, 
+						     self, FLOW_START);
+        }
+}
+    
+/*
+ * Function ircomm_lmp_data_request (self, userdata)
+ *
+ *    Send data frame to peer device
+ *
+ */
+int ircomm_lmp_data_request(struct ircomm_cb *self, struct sk_buff *skb, 
+			    int not_used)
+{
+	struct irda_skb_cb *cb;
+	int ret;
+
+	ASSERT(skb != NULL, return -1;);
+
+	cb = (struct irda_skb_cb *) skb->cb;
+	
+        cb->line = self->line;
+
+	IRDA_DEBUG(4, __FUNCTION__"(), sending frame\n");
+
+	skb->destructor = ircomm_lmp_flow_control;
+	
+        if ((self->pkt_count++ > 7) && (self->flow_status == FLOW_START)) {
+		IRDA_DEBUG(2, __FUNCTION__ "(), asking TTY to slow down!\n");
+	        self->flow_status = FLOW_STOP;
+                if (self->notify.flow_indication)
+             	        self->notify.flow_indication(self->notify.instance, 
+				                     self, FLOW_STOP);
+        }
+	ret = irlmp_data_request(self->lsap, skb);
+	if (ret) {
+		ERROR(__FUNCTION__ "(), failed\n");
+		dev_kfree_skb(skb);
+	}
+
+	return ret;
+}
+
+/*
+ * Function ircomm_lmp_data_indication (instance, sap, skb)
+ *
+ *    Incomming data which we must deliver to the state machine, to check
+ *    we are still connected.
+ */
+int ircomm_lmp_data_indication(void *instance, void *sap,
+			       struct sk_buff *skb)
+{
+	struct ircomm_cb *self = (struct ircomm_cb *) instance;
+
+	IRDA_DEBUG(4, __FUNCTION__"()\n");
+	
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
+	ASSERT(skb != NULL, return -1;);
+	
+	ircomm_do_event(self, IRCOMM_LMP_DATA_INDICATION, skb, NULL);
+
+	return 0;
+}
+
+/*
+ * Function ircomm_lmp_connect_confirm (instance, sap, qos, max_sdu_size, 
+ *                                       max_header_size, skb)
+ *
+ *    Connection has been confirmed by peer device
+ *
+ */
+void ircomm_lmp_connect_confirm(void *instance, void *sap,
+				struct qos_info *qos, 
+				__u32 max_seg_size, 
+				__u8 max_header_size,
+				struct sk_buff *skb)
+{
+	struct ircomm_cb *self = (struct ircomm_cb *) instance;
+	struct ircomm_info info;
+
+	IRDA_DEBUG(0, __FUNCTION__"()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
+	ASSERT(qos != NULL, return;);
+
+	info.max_data_size = max_seg_size;
+	info.max_header_size = max_header_size;
+	info.qos = qos;
+
+	ircomm_do_event(self, IRCOMM_LMP_CONNECT_CONFIRM, skb, &info);
+}
+
+/*
+ * Function ircomm_lmp_connect_indication (instance, sap, qos, max_sdu_size,
+ *                                         max_header_size, skb)
+ *
+ *    Peer device wants to make a connection with us
+ *
+ */
+void ircomm_lmp_connect_indication(void *instance, void *sap,
+				   struct qos_info *qos,
+				   __u32 max_seg_size,
+				   __u8 max_header_size,
+				   struct sk_buff *skb)
+{
+	struct ircomm_cb *self = (struct ircomm_cb *)instance;
+	struct ircomm_info info;
+
+	IRDA_DEBUG(0, __FUNCTION__"()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
+	ASSERT(qos != NULL, return;);
+
+	info.max_data_size = max_seg_size;
+	info.max_header_size = max_header_size;
+	info.qos = qos;
+
+	ircomm_do_event(self, IRCOMM_LMP_CONNECT_INDICATION, skb, &info);
+}
+
+/*
+ * Function ircomm_lmp_disconnect_indication (instance, sap, reason, skb)
+ *
+ *    Peer device has closed the connection, or the link went down for some
+ *    other reason
+ */
+void ircomm_lmp_disconnect_indication(void *instance, void *sap, 
+				      LM_REASON reason,
+				      struct sk_buff *skb)
+{
+	struct ircomm_cb *self = (struct ircomm_cb *) instance;
+	struct ircomm_info info;
+
+	IRDA_DEBUG(0, __FUNCTION__"()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return;);
+
+	info.reason = reason;
+
+	ircomm_do_event(self, IRCOMM_LMP_DISCONNECT_INDICATION, skb, &info);
+}
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/ircomm/ircomm_param.c linux.15p9/net/irda/ircomm/ircomm_param.c
--- linux.vanilla/net/irda/ircomm/ircomm_param.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/net/irda/ircomm/ircomm_param.c	Mon Feb  7 12:17:43 2000
@@ -0,0 +1,518 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_param.c
+ * Version:       1.0
+ * Description:   Parameter handling for the IrCOMM protocol
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Mon Jun  7 10:25:11 1999
+ * Modified at:   Sun Jan 30 14:32:03 2000
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/parameters.h>
+
+#include <net/irda/ircomm_core.h>
+#include <net/irda/ircomm_tty_attach.h>
+#include <net/irda/ircomm_tty.h>
+
+#include <net/irda/ircomm_param.h>
+
+static int ircomm_param_service_type(void *instance, irda_param_t *param, 
+				     int get);
+static int ircomm_param_port_type(void *instance, irda_param_t *param, 
+				  int get);
+static int ircomm_param_port_name(void *instance, irda_param_t *param, 
+				  int get);
+static int ircomm_param_service_type(void *instance, irda_param_t *param, 
+				     int get);
+static int ircomm_param_data_rate(void *instance, irda_param_t *param, 
+				  int get);
+static int ircomm_param_data_format(void *instance, irda_param_t *param, 
+				    int get);
+static int ircomm_param_flow_control(void *instance, irda_param_t *param, 
+				     int get);
+static int ircomm_param_xon_xoff(void *instance, irda_param_t *param, int get);
+static int ircomm_param_enq_ack(void *instance, irda_param_t *param, int get);
+static int ircomm_param_line_status(void *instance, irda_param_t *param, 
+				    int get);
+static int ircomm_param_dte(void *instance, irda_param_t *param, int get);
+static int ircomm_param_dce(void *instance, irda_param_t *param, int get);
+static int ircomm_param_poll(void *instance, irda_param_t *param, int get);
+
+static pi_minor_info_t pi_minor_call_table_common[] = {
+	{ ircomm_param_service_type, PV_INT_8_BITS },
+	{ ircomm_param_port_type,    PV_INT_8_BITS },
+	{ ircomm_param_port_name,    PV_STRING }
+};
+static pi_minor_info_t pi_minor_call_table_non_raw[] = {
+	{ ircomm_param_data_rate,    PV_INT_32_BITS | PV_BIG_ENDIAN },
+	{ ircomm_param_data_format,  PV_INT_8_BITS },
+	{ ircomm_param_flow_control, PV_INT_8_BITS },
+	{ ircomm_param_xon_xoff,     PV_INT_16_BITS },
+	{ ircomm_param_enq_ack,      PV_INT_16_BITS },
+	{ ircomm_param_line_status,  PV_INT_8_BITS }
+};
+static pi_minor_info_t pi_minor_call_table_9_wire[] = {
+	{ ircomm_param_dte,          PV_INT_8_BITS },
+	{ ircomm_param_dce,          PV_INT_8_BITS },
+	{ ircomm_param_poll,         PV_NO_VALUE },
+};
+
+static pi_major_info_t pi_major_call_table[] = {
+	{ pi_minor_call_table_common,  3 },
+	{ pi_minor_call_table_non_raw, 6 },
+ 	{ pi_minor_call_table_9_wire,  3 }
+/* 	{ pi_minor_call_table_centronics }  */
+};
+
+pi_param_info_t ircomm_param_info = { pi_major_call_table, 3, 0x0f, 4 };
+
+/*
+ * Function ircomm_param_flush (self)
+ *
+ *    Flush (send) out all queued parameters
+ *
+ */
+int ircomm_param_flush(struct ircomm_tty_cb *self)
+{
+	if (self->ctrl_skb) {
+		ircomm_control_request(self->ircomm, self->ctrl_skb);
+		self->ctrl_skb = NULL;	
+	}
+	return 0;
+}
+
+/*
+ * Function ircomm_param_request (self, pi, flush)
+ *
+ *    Queue a parameter for the control channel
+ *
+ */
+int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush)
+{
+	struct tty_struct *tty;
+	unsigned long flags;
+	struct sk_buff *skb;
+	int count;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+	tty = self->tty;
+	if (!tty)
+		return 0;
+
+	/* Make sure we don't send parameters for raw mode */
+	if (self->service_type == IRCOMM_3_WIRE_RAW)
+		return 0;
+
+	save_flags(flags);
+	cli();
+
+	skb = self->ctrl_skb;	
+	if (!skb) {
+		skb = dev_alloc_skb(256);
+		if (!skb) {
+			restore_flags(flags);
+			return -ENOMEM;
+		}
+		
+		skb_reserve(skb, self->max_header_size);
+		self->ctrl_skb = skb;
+	}
+	/* 
+	 * Inserting is a little bit tricky since we don't know how much
+	 * room we will need. But this should hopefully work OK 
+	 */
+	count = irda_param_insert(self, pi, skb->tail, skb_tailroom(skb),
+				  &ircomm_param_info);
+	if (count < 0) {
+		WARNING(__FUNCTION__ "(), no room for parameter!\n");
+		restore_flags(flags);
+		return -1;
+	}
+	skb_put(skb, count);
+
+	restore_flags(flags);
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), skb->len=%d\n", skb->len);
+
+	if (flush) {
+		/* ircomm_tty_do_softint will take care of the rest */
+		queue_task(&self->tqueue, &tq_immediate);
+		mark_bh(IMMEDIATE_BH);
+	}
+
+	return count;
+}
+
+/*
+ * Function ircomm_param_service_type (self, buf, len)
+ *
+ *    Handle service type, this function will both be called after the LM-IAS
+ *    query and then the remote device sends its initial paramters
+ *
+ */
+static int ircomm_param_service_type(void *instance, irda_param_t *param, 
+				     int get)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+	__u8 service_type = param->pv.b; /* We know it's a one byte integer */
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+	if (get) {
+		param->pv.b = self->settings.service_type;
+		return 0;
+	}
+
+	/* Find all common service types */
+	service_type &= self->service_type;
+	if (!service_type) {
+		IRDA_DEBUG(2, __FUNCTION__
+			   "(), No common service type to use!\n");
+		return -1;
+	}
+	IRDA_DEBUG(0, __FUNCTION__ "(), services in common=%02x\n",
+		   service_type);
+
+	/*
+	 * Now choose a preferred service type of those available
+	 */
+	if (service_type & IRCOMM_CENTRONICS)
+		self->settings.service_type = IRCOMM_CENTRONICS;
+	else if (service_type & IRCOMM_9_WIRE)
+		self->settings.service_type = IRCOMM_9_WIRE;
+	else if (service_type & IRCOMM_3_WIRE)
+		self->settings.service_type = IRCOMM_3_WIRE;
+	else if (service_type & IRCOMM_3_WIRE_RAW)
+		self->settings.service_type = IRCOMM_3_WIRE_RAW;
+
+	IRDA_DEBUG(0, __FUNCTION__ "(), resulting service type=0x%02x\n", 
+		   self->settings.service_type);
+
+	/* 
+	 * Now the line is ready for some communication. Check if we are a
+         * server, and send over some initial parameters 
+	 */
+	if (!self->client && (self->settings.service_type != IRCOMM_3_WIRE_RAW))
+	{
+		/* Init connection */
+		ircomm_tty_send_initial_parameters(self);
+		ircomm_tty_link_established(self);
+	}
+
+	return 0;
+}
+
+/*
+ * Function ircomm_param_port_type (self, param)
+ *
+ *    The port type parameter tells if the devices are serial or parallel.
+ *    Since we only advertise serial service, this parameter should only
+ *    be equal to IRCOMM_SERIAL.
+ */
+static int ircomm_param_port_type(void *instance, irda_param_t *param, int get)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+	
+	if (get)
+		param->pv.b = IRCOMM_SERIAL;
+	else {
+		self->settings.port_type = param->pv.b;
+
+		IRDA_DEBUG(0, __FUNCTION__ "(), port type=%d\n", 
+			   self->settings.port_type);
+	}
+	return 0;
+}
+
+/*
+ * Function ircomm_param_port_name (self, param)
+ *
+ *    Exchange port name
+ *
+ */
+static int ircomm_param_port_name(void *instance, irda_param_t *param, int get)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+	
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+	if (get) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), not imp!\n");
+	} else {
+		IRDA_DEBUG(0, __FUNCTION__ "(), port-name=%s\n", param->pv.c);
+		strncpy(self->settings.port_name, param->pv.c, 32);
+	}
+
+	return 0;
+}
+
+/*
+ * Function ircomm_param_data_rate (self, param)
+ *
+ *    Exchange data rate to be used in this settings
+ *
+ */
+static int ircomm_param_data_rate(void *instance, irda_param_t *param, int get)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+	
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+	if (get)
+		param->pv.i = self->settings.data_rate;
+	else
+		self->settings.data_rate = param->pv.i;
+	
+	IRDA_DEBUG(2, __FUNCTION__ "(), data rate = %d\n", param->pv.i);
+
+	return 0;
+}
+
+/*
+ * Function ircomm_param_data_format (self, param)
+ *
+ *    Exchange data format to be used in this settings
+ *
+ */
+static int ircomm_param_data_format(void *instance, irda_param_t *param, 
+				    int get)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+	if (get)
+		param->pv.b = self->settings.data_format;
+	else
+		self->settings.data_format = param->pv.b;
+	
+	return 0;
+}
+
+/*
+ * Function ircomm_param_flow_control (self, param)
+ *
+ *    Exchange flow control settings to be used in this settings
+ *
+ */
+static int ircomm_param_flow_control(void *instance, irda_param_t *param, 
+				     int get)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+	
+	if (get)
+		param->pv.b = self->settings.flow_control;
+	else
+		self->settings.flow_control = param->pv.b;
+
+	IRDA_DEBUG(1, __FUNCTION__ "(), flow control = 0x%02x\n", param->pv.b);
+
+	return 0;
+}
+
+/*
+ * Function ircomm_param_xon_xoff (self, param)
+ *
+ *    Exchange XON/XOFF characters
+ *
+ */
+static int ircomm_param_xon_xoff(void *instance, irda_param_t *param, int get)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+	
+	if (get) {
+		param->pv.s = self->settings.xonxoff[0];
+		param->pv.s |= self->settings.xonxoff[1] << 8;
+	} else {
+		self->settings.xonxoff[0] = param->pv.s & 0xff;
+		self->settings.xonxoff[1] = param->pv.s >> 8;
+	}
+
+	IRDA_DEBUG(0, __FUNCTION__ "(), XON/XOFF = 0x%02x,0x%02x\n", 
+		   param->pv.s & 0xff, param->pv.s >> 8);
+
+	return 0;
+}
+
+/*
+ * Function ircomm_param_enq_ack (self, param)
+ *
+ *    Exchange ENQ/ACK characters
+ *
+ */
+static int ircomm_param_enq_ack(void *instance, irda_param_t *param, int get)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+	
+	if (get) {
+		param->pv.s = self->settings.enqack[0];
+		param->pv.s |= self->settings.enqack[1] << 8;
+	} else {
+		self->settings.enqack[0] = param->pv.s & 0xff;
+		self->settings.enqack[1] = param->pv.s >> 8;
+	}
+
+	IRDA_DEBUG(0, __FUNCTION__ "(), ENQ/ACK = 0x%02x,0x%02x\n",
+		   param->pv.s & 0xff, param->pv.s >> 8);
+
+	return 0;
+}
+
+/*
+ * Function ircomm_param_line_status (self, param)
+ *
+ *    
+ *
+ */
+static int ircomm_param_line_status(void *instance, irda_param_t *param, 
+				    int get)
+{
+	IRDA_DEBUG(2, __FUNCTION__ "(), not impl.\n");
+
+	return 0;
+}
+
+/*
+ * Function ircomm_param_dte (instance, param)
+ *
+ *    If we get here, there must be some sort of null-modem connection, and
+ *    we are probably working in server mode as well.
+ */
+static int ircomm_param_dte(void *instance, irda_param_t *param, int get)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+	__u8 dte;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+	if (get)
+		param->pv.b = self->settings.dte;
+	else {
+		dte = param->pv.b;
+		
+		if (dte & IRCOMM_DELTA_DTR)
+			self->settings.dce |= (IRCOMM_DELTA_DSR|
+					      IRCOMM_DELTA_RI |
+					      IRCOMM_DELTA_CD);
+		if (dte & IRCOMM_DTR)
+			self->settings.dce |= (IRCOMM_DSR|
+					      IRCOMM_RI |
+					      IRCOMM_CD);
+		
+		if (dte & IRCOMM_DELTA_RTS)
+			self->settings.dce |= IRCOMM_DELTA_CTS;
+		if (dte & IRCOMM_RTS)
+			self->settings.dce |= IRCOMM_CTS;
+
+		/* Take appropriate actions */
+		ircomm_tty_check_modem_status(self);
+
+		/* Null modem cable emulator */
+		self->settings.null_modem = TRUE;
+	}
+
+	return 0;
+}
+
+/*
+ * Function ircomm_param_dce (instance, param)
+ *
+ *    
+ *
+ */
+static int ircomm_param_dce(void *instance, irda_param_t *param, int get)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+	__u8 dce;
+
+	IRDA_DEBUG(1, __FUNCTION__ "(), dce = 0x%02x\n", param->pv.b);
+
+	dce = param->pv.b;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+	self->settings.dce = dce;
+
+	/* Check if any of the settings have changed */
+	if (dce & 0x0f) {
+		if (dce & IRCOMM_DELTA_CTS) {
+			IRDA_DEBUG(2, __FUNCTION__ "(), CTS \n");
+		}
+	}
+
+	ircomm_tty_check_modem_status(self);
+
+	return 0;
+}
+
+/*
+ * Function ircomm_param_poll (instance, param)
+ *
+ *    Called when the peer device is polling for the line settings
+ *
+ */
+static int ircomm_param_poll(void *instance, irda_param_t *param, int get)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+	/* Poll parameters are always of lenght 0 (just a signal) */
+	if (!get) {
+		/* Respond with DTE line settings */
+		ircomm_param_request(self, IRCOMM_DTE, TRUE);
+	}
+	return 0;
+}
+
+
+
+
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/ircomm/ircomm_ttp.c linux.15p9/net/irda/ircomm/ircomm_ttp.c
--- linux.vanilla/net/irda/ircomm/ircomm_ttp.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/net/irda/ircomm/ircomm_ttp.c	Tue Jan 18 01:08:18 2000
@@ -0,0 +1,304 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_ttp.c
+ * Version:       1.0
+ * Description:   Interface between IrCOMM and IrTTP
+ * Status:        Stable
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Jun  6 20:48:27 1999
+ * Modified at:   Mon Dec 13 11:35:13 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/iriap.h>
+#include <net/irda/irttp.h>
+
+#include <net/irda/ircomm_event.h>
+#include <net/irda/ircomm_ttp.h>
+
+/*
+ * Function ircomm_open_tsap (self)
+ *
+ *    
+ *
+ */
+int ircomm_open_tsap(struct ircomm_cb *self)
+{
+	notify_t notify;
+
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+	/* Register callbacks */
+	irda_notify_init(&notify);
+	notify.data_indication       = ircomm_ttp_data_indication;
+	notify.connect_confirm       = ircomm_ttp_connect_confirm;
+	notify.connect_indication    = ircomm_ttp_connect_indication;
+	notify.flow_indication       = ircomm_ttp_flow_indication;
+	notify.disconnect_indication = ircomm_ttp_disconnect_indication;
+	notify.instance = self;
+	strncpy(notify.name, "IrCOMM", NOTIFY_MAX_NAME);
+
+	self->tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT,
+				     &notify);
+	if (!self->tsap) {
+		IRDA_DEBUG(0, __FUNCTION__"failed to allocate tsap\n");
+		return -1;
+	}
+	self->slsap_sel = self->tsap->stsap_sel;
+
+	/*
+	 *  Initialize the call-table for issuing commands
+	 */
+	self->issue.data_request       = ircomm_ttp_data_request;
+	self->issue.connect_request    = ircomm_ttp_connect_request;
+	self->issue.connect_response   = ircomm_ttp_connect_response;
+	self->issue.disconnect_request = ircomm_ttp_disconnect_request;
+
+	return 0;
+}
+
+/*
+ * Function ircomm_ttp_connect_request (self, userdata)
+ *
+ *    
+ *
+ */
+int ircomm_ttp_connect_request(struct ircomm_cb *self, 
+			       struct sk_buff *userdata, 
+			       struct ircomm_info *info)
+{
+	int ret = 0;
+
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+	ret = irttp_connect_request(self->tsap, info->dlsap_sel,
+				    info->saddr, info->daddr, NULL, 
+				    TTP_SAR_DISABLE, userdata); 
+	return ret;
+}	
+
+/*
+ * Function ircomm_ttp_connect_response (self, skb)
+ *
+ *    
+ *
+ */
+int ircomm_ttp_connect_response(struct ircomm_cb *self, struct sk_buff *skb)
+{
+	int ret;
+
+	IRDA_DEBUG(4, __FUNCTION__"()\n");
+	
+	ret = irttp_connect_response(self->tsap, TTP_SAR_DISABLE, skb);
+
+	return ret;
+}
+
+/*
+ * Function ircomm_ttp_data_request (self, userdata)
+ *
+ *    Send IrCOMM data to IrTTP layer. Currently we do not try to combine 
+ *    control data with pure data, so they will be sent as separate frames. 
+ *    Should not be a big problem though, since control frames are rare. But
+ *    some of them are sent after connection establishment, so this can 
+ *    increase the latency a bit.
+ */
+int ircomm_ttp_data_request(struct ircomm_cb *self, struct sk_buff *skb, 
+			    int clen)
+{
+	int ret;
+
+	ASSERT(skb != NULL, return -1;);
+
+	IRDA_DEBUG(2, __FUNCTION__"(), clen=%d\n", clen);
+
+	/* 
+	 * Insert clen field, currently we either send data only, or control
+	 * only frames, to make things easier and avoid queueing
+	 */
+	ASSERT(skb_headroom(skb) >= IRCOMM_HEADER_SIZE, return -1;);
+	skb_push(skb, IRCOMM_HEADER_SIZE);
+
+	skb->data[0] = clen;
+
+	ret = irttp_data_request(self->tsap, skb);
+	if (ret) {
+		ERROR(__FUNCTION__ "(), failed\n");
+		dev_kfree_skb(skb);
+	}
+
+	return ret;
+}
+
+/*
+ * Function ircomm_ttp_data_indication (instance, sap, skb)
+ *
+ *    Incomming data
+ *
+ */
+int ircomm_ttp_data_indication(void *instance, void *sap,
+			       struct sk_buff *skb)
+{
+	struct ircomm_cb *self = (struct ircomm_cb *) instance;
+
+	IRDA_DEBUG(4, __FUNCTION__"()\n");
+	
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
+	ASSERT(skb != NULL, return -1;);
+
+	ircomm_do_event(self, IRCOMM_TTP_DATA_INDICATION, skb, NULL);
+
+	return 0;
+}
+
+void ircomm_ttp_connect_confirm(void *instance, void *sap,
+				struct qos_info *qos, 
+				__u32 max_sdu_size, 
+				__u8 max_header_size,
+				struct sk_buff *skb)
+{
+	struct ircomm_cb *self = (struct ircomm_cb *) instance;
+	struct ircomm_info info;
+
+	IRDA_DEBUG(4, __FUNCTION__"()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
+	ASSERT(qos != NULL, return;);
+
+	if (max_sdu_size != TTP_SAR_DISABLE) {
+		ERROR(__FUNCTION__ "(), SAR not allowed for IrCOMM!\n");
+		dev_kfree_skb(skb);
+		return;
+	}
+
+	info.max_data_size = irttp_get_max_seg_size(self->tsap)
+		- IRCOMM_HEADER_SIZE;
+	info.max_header_size = max_header_size + IRCOMM_HEADER_SIZE;
+	info.qos = qos;
+
+	ircomm_do_event(self, IRCOMM_TTP_CONNECT_CONFIRM, skb, &info);
+}
+
+/*
+ * Function ircomm_ttp_connect_indication (instance, sap, qos, max_sdu_size,
+ *                                         max_header_size, skb)
+ *
+ *    
+ *
+ */
+void ircomm_ttp_connect_indication(void *instance, void *sap,
+				   struct qos_info *qos,
+				   __u32 max_sdu_size,
+				   __u8 max_header_size,
+				   struct sk_buff *skb)
+{
+	struct ircomm_cb *self = (struct ircomm_cb *)instance;
+	struct ircomm_info info;
+
+	IRDA_DEBUG(4, __FUNCTION__"()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
+	ASSERT(qos != NULL, return;);
+
+	if (max_sdu_size != TTP_SAR_DISABLE) {
+		ERROR(__FUNCTION__ "(), SAR not allowed for IrCOMM!\n");
+		dev_kfree_skb(skb);
+		return;
+	}
+
+	info.max_data_size = irttp_get_max_seg_size(self->tsap)
+		- IRCOMM_HEADER_SIZE;
+	info.max_header_size = max_header_size + IRCOMM_HEADER_SIZE;
+	info.qos = qos;
+
+	ircomm_do_event(self, IRCOMM_TTP_CONNECT_INDICATION, skb, &info);
+}
+
+/*
+ * Function ircomm_ttp_disconnect_request (self, userdata, info)
+ *
+ *    
+ *
+ */
+int ircomm_ttp_disconnect_request(struct ircomm_cb *self, 
+				  struct sk_buff *userdata, 
+				  struct ircomm_info *info)
+{
+	int ret;
+
+	ret = irttp_disconnect_request(self->tsap, userdata, P_NORMAL);
+
+	return ret;
+}
+
+/*
+ * Function ircomm_ttp_disconnect_indication (instance, sap, reason, skb)
+ *
+ *    
+ *
+ */
+void ircomm_ttp_disconnect_indication(void *instance, void *sap, 
+				      LM_REASON reason,
+				      struct sk_buff *skb)
+{
+	struct ircomm_cb *self = (struct ircomm_cb *) instance;
+	struct ircomm_info info;
+
+	IRDA_DEBUG(2, __FUNCTION__"()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return;);
+
+	info.reason = reason;
+
+	ircomm_do_event(self, IRCOMM_TTP_DISCONNECT_INDICATION, skb, &info);
+}
+
+/*
+ * Function ircomm_ttp_flow_indication (instance, sap, cmd)
+ *
+ *    Layer below is telling us to start or stop the flow of data
+ *
+ */
+void ircomm_ttp_flow_indication(void *instance, void *sap, LOCAL_FLOW cmd)
+{
+	struct ircomm_cb *self = (struct ircomm_cb *) instance;
+
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return;);
+	
+	if (self->notify.flow_indication)
+		self->notify.flow_indication(self->notify.instance, self, cmd);
+}
+
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/ircomm/ircomm_tty.c linux.15p9/net/irda/ircomm/ircomm_tty.c
--- linux.vanilla/net/irda/ircomm/ircomm_tty.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/net/irda/ircomm/ircomm_tty.c	Tue Jan 18 01:08:18 2000
@@ -0,0 +1,1367 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_tty.c
+ * Version:       1.0
+ * Description:   IrCOMM serial TTY driver
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Jun  6 21:00:56 1999
+ * Modified at:   Tue Jan  4 14:12:06 2000
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * Sources:       serial.c and previous IrCOMM work by Takahide Higuchi
+ * 
+ *     Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/termios.h>
+#include <linux/tty.h>
+#include <linux/interrupt.h>
+
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+
+#include <net/irda/ircomm_core.h>
+#include <net/irda/ircomm_param.h>
+#include <net/irda/ircomm_tty_attach.h>
+#include <net/irda/ircomm_tty.h>
+
+static int  ircomm_tty_open(struct tty_struct *tty, struct file *filp);
+static void ircomm_tty_close(struct tty_struct * tty, struct file *filp);
+static int  ircomm_tty_write(struct tty_struct * tty, int from_user,
+			     const unsigned char *buf, int count);
+static int  ircomm_tty_write_room(struct tty_struct *tty);
+static void ircomm_tty_throttle(struct tty_struct *tty);
+static void ircomm_tty_unthrottle(struct tty_struct *tty);
+static int  ircomm_tty_chars_in_buffer(struct tty_struct *tty);
+static void ircomm_tty_flush_buffer(struct tty_struct *tty);
+static void ircomm_tty_send_xchar(struct tty_struct *tty, char ch);
+static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout);
+static void ircomm_tty_hangup(struct tty_struct *tty);
+static void ircomm_tty_do_softint(void *private_);
+static void ircomm_tty_shutdown(struct ircomm_tty_cb *self);
+
+static int ircomm_tty_data_indication(void *instance, void *sap,
+				      struct sk_buff *skb);
+static int ircomm_tty_control_indication(void *instance, void *sap,
+					 struct sk_buff *skb);
+static void ircomm_tty_flow_indication(void *instance, void *sap, 
+				       LOCAL_FLOW cmd);
+static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len,
+				int *eof, void *unused);
+
+static struct tty_driver driver;
+static int ircomm_tty_refcount;       /* If we manage several devices */
+
+static struct tty_struct *ircomm_tty_table[NR_PTYS];
+static struct termios *ircomm_tty_termios[NR_PTYS];
+static struct termios *ircomm_tty_termios_locked[NR_PTYS];
+
+hashbin_t *ircomm_tty = NULL;
+
+/*
+ * Function ircomm_tty_init()
+ *
+ *    Init IrCOMM TTY layer/driver
+ *
+ */
+int __init ircomm_tty_init(void)
+{	
+	ircomm_tty = hashbin_new(HB_LOCAL); 
+	if (ircomm_tty == NULL) {
+		ERROR(__FUNCTION__ "(), can't allocate hashbin!\n");
+		return -ENOMEM;
+	}
+
+	memset(&driver, 0, sizeof(struct tty_driver));
+	driver.magic           = TTY_DRIVER_MAGIC;
+	driver.driver_name     = "ircomm";
+	driver.name            = "ircomm";
+	driver.major           = IRCOMM_TTY_MAJOR;
+	driver.minor_start     = IRCOMM_TTY_MINOR;
+	driver.num             = IRCOMM_TTY_PORTS;
+	driver.type            = TTY_DRIVER_TYPE_SERIAL;
+	driver.subtype         = SERIAL_TYPE_NORMAL;
+	driver.init_termios    = tty_std_termios;
+	driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	driver.flags           = TTY_DRIVER_REAL_RAW;
+	driver.refcount        = &ircomm_tty_refcount;
+	driver.table           = ircomm_tty_table;
+	driver.termios         = ircomm_tty_termios;
+	driver.termios_locked  = ircomm_tty_termios_locked;
+	driver.open            = ircomm_tty_open;
+	driver.close           = ircomm_tty_close;
+	driver.write           = ircomm_tty_write;
+	driver.write_room      = ircomm_tty_write_room;
+	driver.chars_in_buffer = ircomm_tty_chars_in_buffer;
+	driver.flush_buffer    = ircomm_tty_flush_buffer;
+	driver.ioctl           = ircomm_tty_ioctl;
+	driver.throttle        = ircomm_tty_throttle;
+	driver.unthrottle      = ircomm_tty_unthrottle;
+	driver.send_xchar      = ircomm_tty_send_xchar;
+	driver.set_termios     = ircomm_tty_set_termios;
+	driver.stop            = ircomm_tty_stop;
+	driver.start           = ircomm_tty_start;
+	driver.hangup          = ircomm_tty_hangup;
+	driver.wait_until_sent = ircomm_tty_wait_until_sent;
+	driver.read_proc       = ircomm_tty_read_proc;
+
+	if (tty_register_driver(&driver)) {
+		ERROR(__FUNCTION__ "Couldn't register serial driver\n");
+		return -1;
+	}
+	return 0;
+}
+
+#ifdef MODULE
+static void __ircomm_tty_cleanup(struct ircomm_tty_cb *self)
+{
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	ircomm_tty_shutdown(self);
+
+	self->magic = 0;
+	kfree(self);
+}
+
+/*
+ * Function ircomm_tty_cleanup ()
+ *
+ *    Remove IrCOMM TTY layer/driver
+ *
+ */
+void ircomm_tty_cleanup(void)
+{
+	int ret;
+
+	IRDA_DEBUG(4, __FUNCTION__"()\n");	
+
+	ret = tty_unregister_driver(&driver);
+        if (ret) {
+                ERROR(__FUNCTION__ "(), failed to unregister driver\n");
+		return;
+	}
+
+	hashbin_delete(ircomm_tty, (FREE_FUNC) __ircomm_tty_cleanup);
+}
+#endif /* MODULE */
+
+/*
+ * Function ircomm_startup (self)
+ *
+ *    
+ *
+ */
+static int ircomm_tty_startup(struct ircomm_tty_cb *self)
+{
+	notify_t notify;
+	int ret;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+	/* Already open */
+	if (self->flags & ASYNC_INITIALIZED) {
+		IRDA_DEBUG(2, __FUNCTION__ "(), already open so break out!\n");
+		return 0;
+	}
+
+	/* Register with IrCOMM */
+	irda_notify_init(&notify);
+	/* These callbacks we must handle ourselves */
+	notify.data_indication       = ircomm_tty_data_indication;
+	notify.udata_indication      = ircomm_tty_control_indication;
+ 	notify.flow_indication       = ircomm_tty_flow_indication;
+
+	/* Use the ircomm_tty interface for these ones */
+ 	notify.disconnect_indication = ircomm_tty_disconnect_indication;
+	notify.connect_confirm       = ircomm_tty_connect_confirm;
+ 	notify.connect_indication    = ircomm_tty_connect_indication;
+	strncpy(notify.name, "ircomm_tty", NOTIFY_MAX_NAME);
+	notify.instance = self;
+
+	if (!self->ircomm) {
+		self->ircomm = ircomm_open(&notify, self->service_type, 
+					   self->line);
+	}
+	if (!self->ircomm)
+		return -ENODEV;
+
+	self->slsap_sel = self->ircomm->slsap_sel;
+
+	/* Connect IrCOMM link with remote device */
+	ret = ircomm_tty_attach_cable(self);
+	if (ret < 0) {
+		ERROR(__FUNCTION__ "(), error attaching cable!\n");
+		return ret;
+	}
+
+	self->flags |= ASYNC_INITIALIZED;
+
+	return 0;
+}
+
+/*
+ * Function ircomm_block_til_ready (self, filp)
+ *
+ *    
+ *
+ */
+static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self, 
+				      struct file *filp)
+{
+	struct wait_queue wait = { NULL, NULL };
+	int		retval;
+	int		do_clocal = 0, extra_count = 0;
+	unsigned long	flags;
+	struct tty_struct *tty;
+	
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	tty = self->tty;
+	wait.task = current;
+
+	if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
+		/* this is a callout device */
+		/* just verify that normal device is not in use */
+		if (self->flags & ASYNC_NORMAL_ACTIVE)
+			return -EBUSY;
+		if ((self->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    (self->flags & ASYNC_SESSION_LOCKOUT) &&
+		    (self->session != current->session))
+			return -EBUSY;
+		if ((self->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    (self->flags & ASYNC_PGRP_LOCKOUT) &&
+		    (self->pgrp != current->pgrp))
+			return -EBUSY;
+		self->flags |= ASYNC_CALLOUT_ACTIVE;
+		return 0;
+	}
+	
+	/*
+	 * If non-blocking mode is set, or the port is not enabled,
+	 * then make the check up front and then exit.
+	 */	
+	if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
+		/* nonblock mode is set or port is not enabled */
+		/* just verify that callout device is not active */
+		if (self->flags & ASYNC_CALLOUT_ACTIVE)
+			return -EBUSY;
+		self->flags |= ASYNC_NORMAL_ACTIVE;
+
+		IRDA_DEBUG(1, __FUNCTION__ "(), O_NONBLOCK requested!\n");
+		return 0;
+	}
+
+	if (self->flags & ASYNC_CALLOUT_ACTIVE) {
+		if (self->normal_termios.c_cflag & CLOCAL) {
+			IRDA_DEBUG(1, __FUNCTION__ "(), doing CLOCAL!\n");
+			do_clocal = 1;
+		}
+	} else {
+		if (tty->termios->c_cflag & CLOCAL) {
+			IRDA_DEBUG(1, __FUNCTION__ "(), doing CLOCAL!\n");
+			do_clocal = 1;
+		}
+	}
+	
+	/* Wait for carrier detect and the line to become
+	 * free (i.e., not in use by the callout).  While we are in
+	 * this loop, self->open_count is dropped by one, so that
+	 * mgsl_close() knows when to free things.  We restore it upon
+	 * exit, either normal or abnormal.
+	 */
+	 
+	retval = 0;
+	add_wait_queue(&self->open_wait, &wait);
+	
+	IRDA_DEBUG(2, "%s(%d):block_til_ready before block on %s open_count=%d\n",
+	      __FILE__,__LINE__, tty->driver.name, self->open_count );
+
+	save_flags(flags); cli();
+	if (!tty_hung_up_p(filp)) {
+		extra_count = 1;
+		self->open_count--;
+	}
+	restore_flags(flags);
+	self->blocked_open++;
+	
+	while (1) {
+		if (!(self->flags & ASYNC_CALLOUT_ACTIVE) &&
+ 		    (tty->termios->c_cflag & CBAUD)) {
+			save_flags(flags); cli();
+			self->settings.dte |= IRCOMM_RTS + IRCOMM_DTR;
+		 	
+			ircomm_param_request(self, IRCOMM_DTE, TRUE);
+			restore_flags(flags);
+		}
+		
+		current->state = TASK_INTERRUPTIBLE;
+		
+		if (tty_hung_up_p(filp) || !(self->flags & ASYNC_INITIALIZED)){
+			retval = (self->flags & ASYNC_HUP_NOTIFY) ?
+					-EAGAIN : -ERESTARTSYS;
+			break;
+		}
+		
+		/*  
+		 * Check if link is ready now. Even if CLOCAL is
+		 * specified, we cannot return before the IrCOMM link is
+		 * ready 
+		 */
+ 		if (!(self->flags & ASYNC_CALLOUT_ACTIVE) &&
+ 		    !(self->flags & ASYNC_CLOSING) &&
+ 		    (do_clocal || (self->settings.dce & IRCOMM_CD)) &&
+		    self->state == IRCOMM_TTY_READY)
+		{
+ 			break;
+		}
+			
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			break;
+		}
+		
+		IRDA_DEBUG(1, "%s(%d):block_til_ready blocking on %s open_count=%d\n",
+		      __FILE__,__LINE__, tty->driver.name, self->open_count );
+		
+		schedule();
+	}
+	
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&self->open_wait, &wait);
+	
+	if (extra_count)
+		self->open_count++;
+	self->blocked_open--;
+	
+	IRDA_DEBUG(1, "%s(%d):block_til_ready after blocking on %s open_count=%d\n",
+	      __FILE__,__LINE__, tty->driver.name, self->open_count);
+			 
+	if (!retval)
+		self->flags |= ASYNC_NORMAL_ACTIVE;
+		
+	return retval;	
+}
+
+/*
+ * Function ircomm_tty_open (tty, filp)
+ *
+ *    This routine is called when a particular tty device is opened. This
+ *    routine is mandatory; if this routine is not filled in, the attempted
+ *    open will fail with ENODEV.
+ */
+static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
+{
+	struct ircomm_tty_cb *self;
+	int line;
+	int ret;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	MOD_INC_USE_COUNT;
+	line = MINOR(tty->device) - tty->driver.minor_start;
+	if ((line < 0) || (line >= IRCOMM_TTY_PORTS)) {
+		MOD_DEC_USE_COUNT;
+		return -ENODEV;
+	}
+
+	/* Check if instance already exists */
+	self = hashbin_find(ircomm_tty, line, NULL);
+	if (!self) {
+		/* No, so make new instance */
+		self = kmalloc(sizeof(struct ircomm_tty_cb), GFP_KERNEL);
+		if (self == NULL) {
+			ERROR(__FUNCTION__"(), kmalloc failed!\n");
+			MOD_DEC_USE_COUNT;
+			return -ENOMEM;
+		}
+		memset(self, 0, sizeof(struct ircomm_tty_cb));
+		
+		self->magic = IRCOMM_TTY_MAGIC;
+		self->flow = FLOW_STOP;
+
+		self->line = line;
+		self->tqueue.routine = ircomm_tty_do_softint;
+		self->tqueue.data = self;
+		self->max_header_size = 5;
+		self->max_data_size = 64-self->max_header_size;
+		self->close_delay = 5*HZ/10;
+		self->closing_wait = 30*HZ;
+
+		/* Init some important stuff */
+		init_timer(&self->watchdog_timer);
+		/* init_waitqueue_head(&self->open_wait); */
+/* 		init_waitqueue_head(&self->close_wait); */
+
+		/* 
+		 * Force TTY into raw mode by default which is usually what
+		 * we want for IrCOMM and IrLPT. This way applications will
+		 * not have to twiddle with printcap etc.  
+		 */
+		tty->termios->c_iflag = 0;
+		tty->termios->c_oflag = 0;
+
+		/* Insert into hash */
+		hashbin_insert(ircomm_tty, (queue_t *) self, line, NULL);
+	}
+	self->open_count++;
+
+	tty->driver_data = self;
+	self->tty = tty;
+
+	IRDA_DEBUG(1, __FUNCTION__"(), %s%d, count = %d\n", tty->driver.name, 
+		   self->line, self->open_count);
+
+	/* Not really used by us, but lets do it anyway */
+	self->tty->low_latency = (self->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+
+	/*
+	 * If the port is the middle of closing, bail out now
+	 */
+	if (tty_hung_up_p(filp) ||
+	    (self->flags & ASYNC_CLOSING)) {
+		if (self->flags & ASYNC_CLOSING)
+			interruptible_sleep_on(&self->close_wait);
+		/* MOD_DEC_USE_COUNT; "info->tty" will cause this? */
+#ifdef SERIAL_DO_RESTART
+		return ((self->flags & ASYNC_HUP_NOTIFY) ?
+			-EAGAIN : -ERESTARTSYS);
+#else
+		return -EAGAIN;
+#endif
+	}
+
+	/* Check if this is a "normal" ircomm device, or an irlpt device */
+	if (line < 0x10) {
+		self->service_type = IRCOMM_3_WIRE | IRCOMM_9_WIRE;
+		self->settings.service_type = IRCOMM_9_WIRE; /* Default */
+		IRDA_DEBUG(2, __FUNCTION__ "(), IrCOMM device\n");
+	} else {
+		IRDA_DEBUG(2, __FUNCTION__ "(), IrLPT device\n");
+		self->service_type = IRCOMM_3_WIRE_RAW;
+		self->settings.service_type = IRCOMM_3_WIRE_RAW; /* Default */
+	}
+
+	ret = ircomm_tty_startup(self);
+	if (ret)
+		return ret;
+
+	ret = ircomm_tty_block_til_ready(self, filp);
+	if (ret) {
+		/* MOD_DEC_USE_COUNT; "info->tty" will cause this? */
+		IRDA_DEBUG(2, __FUNCTION__ 
+		      "(), returning after block_til_ready with %d\n",
+		      ret);
+
+		return ret;
+	}
+
+	self->session = current->session;
+	self->pgrp = current->pgrp;
+
+	return 0;
+}
+
+/*
+ * Function ircomm_tty_close (tty, filp)
+ *
+ *    This routine is called when a particular tty device is closed.
+ *
+ */
+static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+	unsigned long flags;
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	if (!tty)
+		return;
+
+	save_flags(flags); 
+	cli();
+
+	if (tty_hung_up_p(filp)) {
+		MOD_DEC_USE_COUNT;
+		restore_flags(flags);
+
+		IRDA_DEBUG(0, __FUNCTION__ "(), returning 1\n");
+		return;
+	}
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	if ((tty->count == 1) && (self->open_count != 1)) {
+		/*
+		 * Uh, oh.  tty->count is 1, which means that the tty
+		 * structure will be freed.  state->count should always
+		 * be one in these conditions.  If it's greater than
+		 * one, we've got real problems, since it means the
+		 * serial port won't be shutdown.
+		 */
+		IRDA_DEBUG(0, __FUNCTION__ "(), bad serial port count; "
+			   "tty->count is 1, state->count is %d\n", 
+			   self->open_count);
+		self->open_count = 1;
+	}
+
+	if (--self->open_count < 0) {
+		ERROR(__FUNCTION__ 
+		      "(), bad serial port count for ttys%d: %d\n",
+		      self->line, self->open_count);
+		self->open_count = 0;
+	}
+	if (self->open_count) {
+		MOD_DEC_USE_COUNT;
+		restore_flags(flags);
+
+		IRDA_DEBUG(0, __FUNCTION__ "(), open count > 0\n");
+		return;
+	}
+	self->flags |= ASYNC_CLOSING;
+
+	/*
+	 * Now we wait for the transmit buffer to clear; and we notify 
+	 * the line discipline to only process XON/XOFF characters.
+	 */
+	tty->closing = 1;
+	if (self->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+		tty_wait_until_sent(tty, self->closing_wait);
+
+	ircomm_tty_shutdown(self);
+
+	if (tty->driver.flush_buffer)
+		tty->driver.flush_buffer(tty);
+	if (tty->ldisc.flush_buffer)
+		tty->ldisc.flush_buffer(tty);
+
+	tty->closing = 0;
+	self->tty = 0;
+
+	if (self->blocked_open) {
+		if (self->close_delay) {
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout(self->close_delay);
+		}
+		wake_up_interruptible(&self->open_wait);
+	}
+
+	self->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
+			 ASYNC_CLOSING);
+	wake_up_interruptible(&self->close_wait);
+
+	MOD_DEC_USE_COUNT;
+	restore_flags(flags);
+}
+
+/*
+ * Function ircomm_tty_flush_buffer (tty)
+ *
+ *    
+ *
+ */
+static void ircomm_tty_flush_buffer(struct tty_struct *tty)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	/* 
+	 * Let do_softint() do this to avoid race condition with 
+	 * do_softint() ;-) 
+	 */
+	queue_task(&self->tqueue, &tq_immediate);
+	mark_bh(IMMEDIATE_BH);
+}
+
+/*
+ * Function ircomm_tty_do_softint (private_)
+ *
+ *    We use this routine to give the write wakeup to the user at at a
+ *    safe time (as fast as possible after write have completed). This 
+ *    can be compared to the Tx interrupt.
+ */
+static void ircomm_tty_do_softint(void *private_)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) private_;
+	struct tty_struct *tty;
+	unsigned long flags;
+	struct sk_buff *skb, *ctrl_skb;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	if (!self || self->magic != IRCOMM_TTY_MAGIC)
+		return;
+
+	tty = self->tty;
+	if (!tty)
+		return;
+
+	/* Unlink control buffer */
+	save_flags(flags);
+	cli();
+
+	ctrl_skb = self->ctrl_skb;
+	self->ctrl_skb = NULL;
+
+	restore_flags(flags);
+
+	/* Flush control buffer if any */
+	if (ctrl_skb && self->flow == FLOW_START)
+		ircomm_control_request(self->ircomm, ctrl_skb);
+
+	if (tty->hw_stopped)
+		return;
+
+	/* Unlink transmit buffer */
+	save_flags(flags);
+	cli();
+	
+	skb = self->tx_skb;
+	self->tx_skb = NULL;
+
+	restore_flags(flags);	
+
+	/* Flush transmit buffer if any */
+	if (skb)
+		ircomm_tty_do_event(self, IRCOMM_TTY_DATA_REQUEST, skb, NULL);
+		
+	/* Check if user (still) wants to be waken up */
+	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && 
+	    tty->ldisc.write_wakeup)
+	{
+		(tty->ldisc.write_wakeup)(tty);
+	}
+	wake_up_interruptible(&tty->write_wait);
+}
+
+/*
+ * Function ircomm_tty_write (tty, from_user, buf, count)
+ *
+ *    This routine is called by the kernel to write a series of characters
+ *    to the tty device. The characters may come from user space or kernel
+ *    space. This routine will return the number of characters actually
+ *    accepted for writing. This routine is mandatory.
+ */
+static int ircomm_tty_write(struct tty_struct *tty, int from_user,
+			    const unsigned char *buf, int count)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+	unsigned long flags;
+	struct sk_buff *skb;
+	int tailroom = 0;
+	int len = 0;
+	int size;
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), count=%d, hw_stopped=%d\n", count,
+		   tty->hw_stopped);
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+	save_flags(flags);
+	cli();
+
+	/* Fetch current transmit buffer */
+	skb = self->tx_skb;
+
+	/*  
+	 * Send out all the data we get, possibly as multiple fragmented
+	 * frames, but this will only happen if the data is larger than the
+	 * max data size. The normal case however is just the opposite, and
+	 * this function may be called multiple times, and will then actually
+	 * defragment the data and send it out as one packet as soon as 
+	 * possible, but at a safer point in time
+	 */
+	while (count) {
+		size = count;
+
+		/* Adjust data size to the max data size */
+		if (size > self->max_data_size)
+			size = self->max_data_size;
+		
+		/* 
+		 * Do we already have a buffer ready for transmit, or do
+		 * we need to allocate a new frame 
+		 */
+		if (skb) {			
+			/* 
+			 * Any room for more data at the end of the current 
+			 * transmit buffer? Cannot use skb_tailroom, since
+			 * dev_alloc_skb gives us a larger skb than we 
+			 * requested
+			 */
+			if ((tailroom = (self->max_data_size-skb->len)) > 0) {
+				/* Adjust data to tailroom */
+				if (size > tailroom)
+					size = tailroom;
+			} else {
+				/* 
+				 * Current transmit frame is full, so break 
+				 * out, so we can send it as soon as possible
+				 */
+				break;
+			}
+		} else {
+			/* Prepare a full sized frame */
+			skb = dev_alloc_skb(self->max_data_size+
+					    self->max_header_size);
+			if (!skb) {
+				restore_flags(flags);
+				return -ENOBUFS;
+			}
+			skb_reserve(skb, self->max_header_size);
+			self->tx_skb = skb;
+		}
+		
+		/* Copy data */
+		if (from_user)
+			copy_from_user(skb_put(skb,size), buf+len, size);
+		else
+			memcpy(skb_put(skb,size), buf+len, size);
+		
+		count -= size;
+		len += size;
+	}
+
+	restore_flags(flags);
+
+	/*     
+	 * Schedule a new thread which will transmit the frame as soon
+	 * as possible, but at a safe point in time. We do this so the
+	 * "user" can give us data multiple times, as PPP does (because of
+	 * its 256 byte tx buffer). We will then defragment and send out
+	 * all this data as one single packet.  
+	 */
+	queue_task(&self->tqueue, &tq_immediate);
+	mark_bh(IMMEDIATE_BH);
+	
+	return len;
+}
+
+/*
+ * Function ircomm_tty_write_room (tty)
+ *
+ *    This routine returns the numbers of characters the tty driver will
+ *    accept for queuing to be written. This number is subject to change as
+ *    output buffers get emptied, or if the output flow control is acted.
+ */
+static int ircomm_tty_write_room(struct tty_struct *tty)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+	unsigned long flags;
+	int ret;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+	/* Check if we are allowed to transmit any data */
+	if (tty->hw_stopped)
+		ret = 0;
+	else {
+		save_flags(flags);
+		cli();
+		if (self->tx_skb)
+			ret = self->max_data_size - self->tx_skb->len;
+		else
+			ret = self->max_data_size;
+		restore_flags(flags);
+	}
+	IRDA_DEBUG(2, __FUNCTION__ "(), ret=%d\n", ret);
+
+	return ret;
+}
+
+/*
+ * Function ircomm_tty_wait_until_sent (tty, timeout)
+ *
+ *    This routine waits until the device has written out all of the
+ *    characters in its transmitter FIFO.
+ */
+static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+	unsigned long orig_jiffies, poll_time;
+	
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	orig_jiffies = jiffies;
+
+	/* Set poll time to 200 ms */
+	poll_time = IRDA_MIN(timeout, MSECS_TO_JIFFIES(200));
+
+	while (self->tx_skb && self->tx_skb->len) {
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(poll_time);
+		if (signal_pending(current))
+			break;
+		if (timeout && time_after(jiffies, orig_jiffies + timeout))
+			break;
+	}
+	current->state = TASK_RUNNING;
+}
+
+/*
+ * Function ircomm_tty_throttle (tty)
+ *
+ *    This routine notifies the tty driver that input buffers for the line
+ *    discipline are close to full, and it should somehow signal that no
+ *    more characters should be sent to the tty.  
+ */
+static void ircomm_tty_throttle(struct tty_struct *tty)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	/* Software flow control? */
+	if (I_IXOFF(tty))
+		ircomm_tty_send_xchar(tty, STOP_CHAR(tty));
+	
+	/* Hardware flow control? */
+	if (tty->termios->c_cflag & CRTSCTS) {
+		self->settings.dte &= ~IRCOMM_RTS;
+		self->settings.dte |= IRCOMM_DELTA_RTS;
+	
+		ircomm_param_request(self, IRCOMM_DTE, TRUE);
+	}
+
+        ircomm_flow_request(self->ircomm, FLOW_STOP);
+}
+
+/*
+ * Function ircomm_tty_unthrottle (tty)
+ *
+ *    This routine notifies the tty drivers that it should signals that
+ *    characters can now be sent to the tty without fear of overrunning the
+ *    input buffers of the line disciplines.
+ */
+static void ircomm_tty_unthrottle(struct tty_struct *tty)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	/* Using software flow control? */
+	if (I_IXOFF(tty)) {
+		ircomm_tty_send_xchar(tty, START_CHAR(tty));
+	}
+
+	/* Using hardware flow control? */
+	if (tty->termios->c_cflag & CRTSCTS) {
+		self->settings.dte |= (IRCOMM_RTS|IRCOMM_DELTA_RTS);
+
+		ircomm_param_request(self, IRCOMM_DTE, TRUE);
+		IRDA_DEBUG(1, __FUNCTION__"(), FLOW_START\n");
+	}
+        ircomm_flow_request(self->ircomm, FLOW_START);
+}
+
+/*
+ * Function ircomm_tty_chars_in_buffer (tty)
+ *
+ *    Indicates if there are any data in the buffer
+ *
+ */
+static int ircomm_tty_chars_in_buffer(struct tty_struct *tty)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+	unsigned long flags;
+	int len = 0;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+	save_flags(flags);
+	cli();
+
+	if (self->tx_skb)
+		len = self->tx_skb->len;
+
+	restore_flags(flags);
+
+	return len;
+}
+
+static void ircomm_tty_shutdown(struct ircomm_tty_cb *self)
+{
+	unsigned long flags;
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+	
+	if (!(self->flags & ASYNC_INITIALIZED))
+		return;
+
+	save_flags(flags);
+	cli();
+
+	del_timer(&self->watchdog_timer);
+	
+	/* Free parameter buffer */
+	if (self->ctrl_skb) {
+		dev_kfree_skb(self->ctrl_skb);
+		self->ctrl_skb = NULL;
+	}
+
+	/* Free transmit buffer */
+	if (self->tx_skb) {
+		dev_kfree_skb(self->tx_skb);
+		self->tx_skb = NULL;
+	}
+
+	ircomm_tty_detach_cable(self);
+
+	if (self->ircomm) {
+		ircomm_close(self->ircomm);
+		self->ircomm = NULL;
+	}
+	self->flags &= ~ASYNC_INITIALIZED;
+
+	restore_flags(flags);
+}
+
+/*
+ * Function ircomm_tty_hangup (tty)
+ *
+ *    This routine notifies the tty driver that it should hangup the tty
+ *    device.
+ * 
+ */
+static void ircomm_tty_hangup(struct tty_struct *tty)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+
+	IRDA_DEBUG(0, __FUNCTION__"()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	if (!tty)
+		return;
+
+	/* ircomm_tty_flush_buffer(tty); */
+	ircomm_tty_shutdown(self);
+
+	self->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
+	self->tty = 0;
+	self->open_count = 0;
+	wake_up_interruptible(&self->open_wait);
+}
+
+/*
+ * Function ircomm_tty_send_xchar (tty, ch)
+ *
+ *    This routine is used to send a high-priority XON/XOFF character to
+ *    the device.
+ */
+static void ircomm_tty_send_xchar(struct tty_struct *tty, char ch)
+{
+	IRDA_DEBUG(0, __FUNCTION__"(), not impl\n");
+}
+
+/*
+ * Function ircomm_tty_start (tty)
+ *
+ *    This routine notifies the tty driver that it resume sending
+ *    characters to the tty device.  
+ */
+void ircomm_tty_start(struct tty_struct *tty)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+
+	ircomm_flow_request(self->ircomm, FLOW_START);
+}
+
+/*
+ * Function ircomm_tty_stop (tty)
+ *
+ *     This routine notifies the tty driver that it should stop outputting
+ *     characters to the tty device. 
+ */
+void ircomm_tty_stop(struct tty_struct *tty) 
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	ircomm_flow_request(self->ircomm, FLOW_STOP);
+}
+
+/*
+ * Function ircomm_check_modem_status (self)
+ *
+ *    Check for any changes in the DCE's line settings. This function should
+ *    be called whenever the dce parameter settings changes, to update the
+ *    flow control settings and other things
+ */
+void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
+{
+	struct tty_struct *tty;
+	int status;
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	tty = self->tty;
+
+	status = self->settings.dce;
+
+	if (status & IRCOMM_DCE_DELTA_ANY) {
+		/*wake_up_interruptible(&self->delta_msr_wait);*/
+	}
+	if ((self->flags & ASYNC_CHECK_CD) && (status & IRCOMM_DELTA_CD)) {
+		IRDA_DEBUG(2, __FUNCTION__ 
+			   "(), ircomm%d CD now %s...\n", self->line,
+			   (status & IRCOMM_CD) ? "on" : "off");
+
+		if (status & IRCOMM_CD) {
+			wake_up_interruptible(&self->open_wait);
+		} else if (!((self->flags & ASYNC_CALLOUT_ACTIVE) &&
+			   (self->flags & ASYNC_CALLOUT_NOHUP))) 
+		{
+			IRDA_DEBUG(2, __FUNCTION__ 
+				   "(), Doing serial hangup..\n");
+			if (tty)
+				tty_hangup(tty);
+
+			/* Hangup will remote the tty, so better break out */
+			return;
+		}
+	}
+	if (self->flags & ASYNC_CTS_FLOW) {
+		if (tty->hw_stopped) {
+			if (status & IRCOMM_CTS) {
+				IRDA_DEBUG(2, __FUNCTION__ 
+					   "(), CTS tx start...\n");
+				tty->hw_stopped = 0;
+				
+				queue_task(&self->tqueue, &tq_immediate);
+				mark_bh(IMMEDIATE_BH);
+				return;
+			}
+		} else {
+			if (!(status & IRCOMM_CTS)) {
+				IRDA_DEBUG(2, __FUNCTION__ 
+					   "(), CTS tx stop...\n");
+				tty->hw_stopped = 1;
+			}
+		}
+	}
+}
+
+/*
+ * Function ircomm_tty_data_indication (instance, sap, skb)
+ *
+ *    Handle incomming data, and deliver it to the line discipline
+ *
+ */
+static int ircomm_tty_data_indication(void *instance, void *sap,
+				      struct sk_buff *skb)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+
+	IRDA_DEBUG(2, __FUNCTION__"()\n");
+	
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+	ASSERT(skb != NULL, return -1;);
+
+	if (!self->tty) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), no tty!\n");
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
+	/* 
+	 * If we receive data when hardware is stopped then something is wrong.
+	 * We try to poll the peers line settings to check if we are up todate.
+	 * Devices like WinCE can do this, and since they don't send any 
+	 * params, we can just as well declare the hardware for running.
+	 */
+	if (self->tty->hw_stopped && (self->flow == FLOW_START)) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), polling for line settings!\n");
+		ircomm_param_request(self, IRCOMM_POLL, TRUE);
+
+		/* We can just as well declare the hardware for running */
+		ircomm_tty_send_initial_parameters(self);
+		ircomm_tty_link_established(self);
+	}
+
+	/* 
+	 * Just give it over to the line discipline. There is no need to
+	 * involve the flip buffers, since we are not running in an interrupt 
+	 * handler
+	 */
+	self->tty->ldisc.receive_buf(self->tty, skb->data, NULL, skb->len);
+	dev_kfree_skb(skb);
+
+	return 0;
+}
+
+/*
+ * Function ircomm_tty_control_indication (instance, sap, skb)
+ *
+ *    Parse all incomming parameters (easy!)
+ *
+ */
+static int ircomm_tty_control_indication(void *instance, void *sap,
+					 struct sk_buff *skb)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+	int clen;
+
+	IRDA_DEBUG(4, __FUNCTION__"()\n");
+	
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+	ASSERT(skb != NULL, return -1;);
+
+	clen = skb->data[0];
+
+	irda_param_extract_all(self, skb->data+1, IRDA_MIN(skb->len-1, clen), 
+			       &ircomm_param_info);
+	dev_kfree_skb(skb);
+
+	return 0;
+}
+
+/*
+ * Function ircomm_tty_flow_indication (instance, sap, cmd)
+ *
+ *    This function is called by IrTTP when it wants us to slow down the
+ *    transmission of data. We just mark the hardware as stopped, and wait
+ *    for IrTTP to notify us that things are OK again.
+ */
+static void ircomm_tty_flow_indication(void *instance, void *sap, 
+				       LOCAL_FLOW cmd)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+	struct tty_struct *tty;
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	tty = self->tty;
+
+	switch (cmd) {
+	case FLOW_START:
+		IRDA_DEBUG(2, __FUNCTION__ "(), hw start!\n");
+		tty->hw_stopped = 0;
+
+		/* ircomm_tty_do_softint will take care of the rest */
+		queue_task(&self->tqueue, &tq_immediate);
+		mark_bh(IMMEDIATE_BH);
+		break;
+	default:  /* If we get here, something is very wrong, better stop */
+	case FLOW_STOP:
+		IRDA_DEBUG(2, __FUNCTION__ "(), hw stopped!\n");
+		tty->hw_stopped = 1;
+		break;
+	}
+	self->flow = cmd;
+}
+
+static int ircomm_tty_line_info(struct ircomm_tty_cb *self, char *buf)
+{
+        int  ret=0;
+
+	ret += sprintf(buf+ret, "State: %s\n", ircomm_tty_state[self->state]);
+
+	ret += sprintf(buf+ret, "Service type: ");
+	if (self->service_type & IRCOMM_9_WIRE)
+		ret += sprintf(buf+ret, "9_WIRE");
+	else if (self->service_type & IRCOMM_3_WIRE)
+		ret += sprintf(buf+ret, "3_WIRE");
+	else if (self->service_type & IRCOMM_3_WIRE_RAW)
+		ret += sprintf(buf+ret, "3_WIRE_RAW");
+	else
+		ret += sprintf(buf+ret, "No common service type!\n");
+        ret += sprintf(buf+ret, "\n");
+
+	ret += sprintf(buf+ret, "Port name: %s\n", self->settings.port_name);
+
+	ret += sprintf(buf+ret, "DTE status: ");	
+        if (self->settings.dte & IRCOMM_RTS)
+                ret += sprintf(buf+ret, "RTS|");
+        if (self->settings.dte & IRCOMM_DTR)
+                ret += sprintf(buf+ret, "DTR|");
+	if (self->settings.dte)
+		ret--; /* remove the last | */
+        ret += sprintf(buf+ret, "\n");
+
+	ret += sprintf(buf+ret, "DCE status: ");
+        if (self->settings.dce & IRCOMM_CTS)
+                ret += sprintf(buf+ret, "CTS|");
+        if (self->settings.dce & IRCOMM_DSR)
+                ret += sprintf(buf+ret, "DSR|");
+        if (self->settings.dce & IRCOMM_CD)
+                ret += sprintf(buf+ret, "CD|");
+        if (self->settings.dce & IRCOMM_RI) 
+                ret += sprintf(buf+ret, "RI|");
+	if (self->settings.dce)
+		ret--; /* remove the last | */
+        ret += sprintf(buf+ret, "\n");
+
+	ret += sprintf(buf+ret, "Configuration: ");
+	if (!self->settings.null_modem)
+		ret += sprintf(buf+ret, "DTE <-> DCE\n");
+	else
+		ret += sprintf(buf+ret, 
+			       "DTE <-> DTE (null modem emulation)\n");
+
+	ret += sprintf(buf+ret, "Data rate: %d\n", self->settings.data_rate);
+
+	ret += sprintf(buf+ret, "Flow control: ");
+	if (self->settings.flow_control & IRCOMM_XON_XOFF_IN)
+		ret += sprintf(buf+ret, "XON_XOFF_IN|");
+	if (self->settings.flow_control & IRCOMM_XON_XOFF_OUT)
+		ret += sprintf(buf+ret, "XON_XOFF_OUT|");
+	if (self->settings.flow_control & IRCOMM_RTS_CTS_IN)
+		ret += sprintf(buf+ret, "RTS_CTS_IN|");
+	if (self->settings.flow_control & IRCOMM_RTS_CTS_OUT)
+		ret += sprintf(buf+ret, "RTS_CTS_OUT|");
+	if (self->settings.flow_control & IRCOMM_DSR_DTR_IN)
+		ret += sprintf(buf+ret, "DSR_DTR_IN|");
+	if (self->settings.flow_control & IRCOMM_DSR_DTR_OUT)
+		ret += sprintf(buf+ret, "DSR_DTR_OUT|");
+	if (self->settings.flow_control & IRCOMM_ENQ_ACK_IN)
+		ret += sprintf(buf+ret, "ENQ_ACK_IN|");
+	if (self->settings.flow_control & IRCOMM_ENQ_ACK_OUT)
+		ret += sprintf(buf+ret, "ENQ_ACK_OUT|");
+	if (self->settings.flow_control)
+		ret--; /* remove the last | */
+        ret += sprintf(buf+ret, "\n");
+
+	ret += sprintf(buf+ret, "Flags: ");
+	if (self->flags & ASYNC_CTS_FLOW)
+		ret += sprintf(buf+ret, "ASYNC_CTS_FLOW|");
+	if (self->flags & ASYNC_CHECK_CD)
+		ret += sprintf(buf+ret, "ASYNC_CHECK_CD|");
+	if (self->flags & ASYNC_INITIALIZED)
+		ret += sprintf(buf+ret, "ASYNC_INITIALIZED|");
+	if (self->flags & ASYNC_LOW_LATENCY)
+		ret += sprintf(buf+ret, "ASYNC_LOW_LATENCY|");
+	if (self->flags & ASYNC_CLOSING)
+		ret += sprintf(buf+ret, "ASYNC_CLOSING|");
+	if (self->flags & ASYNC_NORMAL_ACTIVE)
+		ret += sprintf(buf+ret, "ASYNC_NORMAL_ACTIVE|");
+	if (self->flags & ASYNC_CALLOUT_ACTIVE)
+		ret += sprintf(buf+ret, "ASYNC_CALLOUT_ACTIVE|");
+	if (self->flags)
+		ret--; /* remove the last | */
+	ret += sprintf(buf+ret, "\n");
+
+	ret += sprintf(buf+ret, "Role: %s\n", self->client ? 
+		       "client" : "server");
+	ret += sprintf(buf+ret, "Open count: %d\n", self->open_count);
+	ret += sprintf(buf+ret, "Max data size: %d\n", self->max_data_size);
+	ret += sprintf(buf+ret, "Max header size: %d\n", self->max_header_size);
+		
+	if (self->tty)
+		ret += sprintf(buf+ret, "Hardware: %s\n", 
+			       self->tty->hw_stopped ? "Stopped" : "Running");
+
+        ret += sprintf(buf+ret, "\n");
+        return ret;
+}
+
+
+/*
+ * Function ircomm_tty_read_proc (buf, start, offset, len, eof, unused)
+ *
+ *    
+ *
+ */
+static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len,
+				int *eof, void *unused)
+{
+	struct ircomm_tty_cb *self;
+        int count = 0, l;
+        off_t begin = 0;
+
+	self = (struct ircomm_tty_cb *) hashbin_get_first(ircomm_tty);
+	while ((self != NULL) && (count < 4000)) {
+		if (self->magic != IRCOMM_TTY_MAGIC)
+			return 0;
+
+                l = ircomm_tty_line_info(self, buf + count);
+                count += l;
+                if (count+begin > offset+len)
+                        goto done;
+                if (count+begin < offset) {
+                        begin += count;
+                        count = 0;
+                }
+				
+		self = (struct ircomm_tty_cb *) hashbin_get_next(ircomm_tty);
+        }
+        *eof = 1;
+done:
+        if (offset >= count+begin)
+                return 0;
+        *start = buf + (begin-offset);
+        return ((len < begin+count-offset) ? len : begin+count-offset);
+}
+
+
+#ifdef MODULE
+int init_module(void) 
+{
+	return ircomm_tty_init();
+}
+
+void cleanup_module(void)
+{
+	ircomm_tty_cleanup();
+}
+
+#endif /* MODULE */
+
+
+
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/ircomm/ircomm_tty_attach.c linux.15p9/net/irda/ircomm/ircomm_tty_attach.c
--- linux.vanilla/net/irda/ircomm/ircomm_tty_attach.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/net/irda/ircomm/ircomm_tty_attach.c	Tue Jan 18 01:08:18 2000
@@ -0,0 +1,925 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_tty_attach.c
+ * Version:       
+ * Description:   Code for attaching the serial driver to IrCOMM
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sat Jun  5 17:42:00 1999
+ * Modified at:   Tue Jan  4 14:20:49 2000
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/iriap.h>
+#include <net/irda/irttp.h>
+#include <net/irda/irias_object.h>
+#include <net/irda/parameters.h>
+
+#include <net/irda/ircomm_core.h>
+#include <net/irda/ircomm_param.h>
+#include <net/irda/ircomm_event.h>
+
+#include <net/irda/ircomm_tty.h>
+#include <net/irda/ircomm_tty_attach.h>
+
+static void ircomm_tty_ias_register(struct ircomm_tty_cb *self);
+static void ircomm_tty_discovery_indication(discovery_t *discovery);
+static void ircomm_tty_getvalue_confirm(int result, __u16 obj_id, 
+					struct ias_value *value, void *priv);
+void ircomm_tty_start_watchdog_timer(struct ircomm_tty_cb *self, int timeout);
+void ircomm_tty_watchdog_timer_expired(void *data);
+
+static int ircomm_tty_state_idle(struct ircomm_tty_cb *self, 
+				 IRCOMM_TTY_EVENT event, 
+				 struct sk_buff *skb, 
+				 struct ircomm_tty_info *info);
+static int ircomm_tty_state_search(struct ircomm_tty_cb *self, 
+				   IRCOMM_TTY_EVENT event, 
+				   struct sk_buff *skb, 
+				   struct ircomm_tty_info *info);
+static int ircomm_tty_state_query_parameters(struct ircomm_tty_cb *self, 
+					     IRCOMM_TTY_EVENT event, 
+					     struct sk_buff *skb, 
+					     struct ircomm_tty_info *info);
+static int ircomm_tty_state_query_lsap_sel(struct ircomm_tty_cb *self, 
+					   IRCOMM_TTY_EVENT event, 
+					   struct sk_buff *skb, 
+					   struct ircomm_tty_info *info);
+static int ircomm_tty_state_setup(struct ircomm_tty_cb *self, 
+				  IRCOMM_TTY_EVENT event, 
+				  struct sk_buff *skb, 
+				  struct ircomm_tty_info *info);
+static int ircomm_tty_state_ready(struct ircomm_tty_cb *self, 
+				  IRCOMM_TTY_EVENT event, 
+				  struct sk_buff *skb, 
+				  struct ircomm_tty_info *info);
+
+char *ircomm_tty_state[] = {
+	"IRCOMM_TTY_IDLE",
+	"IRCOMM_TTY_SEARCH",
+	"IRCOMM_TTY_QUERY_PARAMETERS",
+	"IRCOMM_TTY_QUERY_LSAP_SEL",
+	"IRCOMM_TTY_SETUP",
+	"IRCOMM_TTY_READY",
+	"*** ERROR *** ",
+};
+
+char *ircomm_tty_event[] = {
+	"IRCOMM_TTY_ATTACH_CABLE",
+	"IRCOMM_TTY_DETACH_CABLE",
+	"IRCOMM_TTY_DATA_REQUEST",
+	"IRCOMM_TTY_DATA_INDICATION",
+	"IRCOMM_TTY_DISCOVERY_REQUEST",
+	"IRCOMM_TTY_DISCOVERY_INDICATION",
+	"IRCOMM_TTY_CONNECT_CONFIRM",
+	"IRCOMM_TTY_CONNECT_INDICATION",
+	"IRCOMM_TTY_DISCONNECT_REQUEST",
+	"IRCOMM_TTY_DISCONNECT_INDICATION",
+	"IRCOMM_TTY_WD_TIMER_EXPIRED",
+	"IRCOMM_TTY_GOT_PARAMETERS",
+	"IRCOMM_TTY_GOT_LSAPSEL",
+	"*** ERROR ****",
+};
+
+static int (*state[])(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event,
+		      struct sk_buff *skb, struct ircomm_tty_info *info) = 
+{
+	ircomm_tty_state_idle,
+	ircomm_tty_state_search,
+	ircomm_tty_state_query_parameters,
+	ircomm_tty_state_query_lsap_sel,
+	ircomm_tty_state_setup,
+	ircomm_tty_state_ready,
+};
+
+/*
+ * Function ircomm_tty_attach_cable (driver)
+ *
+ *    Try to attach cable (IrCOMM link). This function will only return
+ *    when the link has been connected, or if an error condition occurs. 
+ *    If success, the return value is the resulting service type.
+ */
+int ircomm_tty_attach_cable(struct ircomm_tty_cb *self)
+{
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+       	/* Check if somebody has already connected to us */
+	if (ircomm_is_connected(self->ircomm)) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), already connected!\n");
+		return 0;
+	}
+
+	/* Make sure nobody tries to write before the link is up */
+	self->tty->hw_stopped = 1;
+
+	ircomm_tty_ias_register(self);
+
+	/* Check if somebody has already connected to us */
+	if (ircomm_is_connected(self->ircomm)) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), already connected!\n");
+		return 0;
+	}
+
+	ircomm_tty_do_event(self, IRCOMM_TTY_ATTACH_CABLE, NULL, NULL);
+
+	return 0;
+}
+
+/*
+ * Function ircomm_detach_cable (driver)
+ *
+ *    Detach cable, or cable has been detached by peer
+ *
+ */
+void ircomm_tty_detach_cable(struct ircomm_tty_cb *self)
+{
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	del_timer(&self->watchdog_timer);
+
+	/* Remove IrCOMM hint bits */
+	irlmp_unregister_client(self->ckey);
+	irlmp_unregister_service(self->skey);
+
+	if (self->iriap) { 
+		iriap_close(self->iriap);
+		self->iriap = NULL;
+	}
+
+	/* Remove LM-IAS object */
+	if (self->obj) {
+		irias_delete_object(self->obj);
+		self->obj = NULL;
+	}
+
+	ircomm_tty_do_event(self, IRCOMM_TTY_DETACH_CABLE, NULL, NULL);
+
+	/* Reset some values */
+	self->daddr = self->saddr = 0;
+	self->dlsap_sel = self->slsap_sel = 0;
+
+	memset(&self->settings, 0, sizeof(struct ircomm_params));
+}
+
+/*
+ * Function ircomm_tty_ias_register (self)
+ *
+ *    Register with LM-IAS depending on which service type we are
+ *
+ */
+static void ircomm_tty_ias_register(struct ircomm_tty_cb *self)
+{
+	__u8 oct_seq[6];
+	__u16 hints;
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+	
+	if (self->service_type & IRCOMM_3_WIRE_RAW) {
+		hints = irlmp_service_to_hint(S_PRINTER);
+		hints |= irlmp_service_to_hint(S_COMM);
+		
+		/* Register IrLPT with LM-IAS */
+		self->obj = irias_new_object("IrLPT", IAS_IRLPT_ID);
+		irias_add_integer_attrib(self->obj, "IrDA:IrLMP:LsapSel", 
+					 self->slsap_sel);
+		irias_insert_object(self->obj);
+	} else {
+		hints = irlmp_service_to_hint(S_COMM);
+
+		/* Register IrCOMM with LM-IAS */
+		self->obj = irias_new_object("IrDA:IrCOMM", IAS_IRCOMM_ID);
+		irias_add_integer_attrib(self->obj, "IrDA:TinyTP:LsapSel", 
+					 self->slsap_sel);
+		
+		/* Code the parameters into the buffer */
+		irda_param_pack(oct_seq, "bbbbbb", 
+				IRCOMM_SERVICE_TYPE, 1, self->service_type,
+				IRCOMM_PORT_TYPE,    1, IRCOMM_SERIAL);
+		
+		/* Register parameters with LM-IAS */
+		irias_add_octseq_attrib(self->obj, "Parameters", oct_seq, 6);
+		irias_insert_object(self->obj);
+	}
+	self->skey = irlmp_register_service(hints);
+	self->ckey = irlmp_register_client(
+		hints, ircomm_tty_discovery_indication, NULL);
+}
+
+/*
+ * Function ircomm_send_initial_parameters (self)
+ *
+ *    Send initial parameters to the remote IrCOMM device. These parameters
+ *    must be sent before any data.
+ */
+int ircomm_tty_send_initial_parameters(struct ircomm_tty_cb *self)
+{
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+	if (self->service_type & IRCOMM_3_WIRE_RAW) 
+		return 0;
+
+	/* 
+	 * Set default values, but only if the application for some reason 
+	 * haven't set them already
+	 */
+	IRDA_DEBUG(2, __FUNCTION__ "(), data-rate = %d\n", 
+		   self->settings.data_rate);
+	if (!self->settings.data_rate)
+		self->settings.data_rate = 9600;
+	IRDA_DEBUG(2, __FUNCTION__ "(), data-format = %d\n", 
+		   self->settings.data_format);
+	if (!self->settings.data_format)
+		self->settings.data_format = IRCOMM_WSIZE_8;  /* 8N1 */
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), flow-control = %d\n", 
+		   self->settings.flow_control);
+	/*self->settings.flow_control = IRCOMM_RTS_CTS_IN|IRCOMM_RTS_CTS_OUT;*/
+
+	/* Do not set delta values for the initial parameters */
+	self->settings.dte = IRCOMM_DTR | IRCOMM_RTS;
+
+	/* Only send service type parameter when we are the client */
+	if (self->client)
+		ircomm_param_request(self, IRCOMM_SERVICE_TYPE, FALSE);
+	ircomm_param_request(self, IRCOMM_DATA_RATE, FALSE);
+	ircomm_param_request(self, IRCOMM_DATA_FORMAT, FALSE);
+	
+	/* For a 3 wire service, we just flush the last parameter and return */
+	if (self->settings.service_type == IRCOMM_3_WIRE) {
+		ircomm_param_request(self, IRCOMM_FLOW_CONTROL, TRUE);
+		return 0;
+	}
+
+	/* Only 9-wire service types continue here */
+	ircomm_param_request(self, IRCOMM_FLOW_CONTROL, FALSE);
+#if 0
+	ircomm_param_request(self, IRCOMM_XON_XOFF, FALSE);
+	ircomm_param_request(self, IRCOMM_ENQ_ACK, FALSE);
+#endif	
+	/* Notify peer that we are ready to receive data */
+	ircomm_param_request(self, IRCOMM_DTE, TRUE);
+	
+	return 0;
+}
+
+/*
+ * Function ircomm_tty_discovery_indication (discovery)
+ *
+ *    Remote device is discovered, try query the remote IAS to see which
+ *    device it is, and which services it has.
+ *
+ */
+static void ircomm_tty_discovery_indication(discovery_t *discovery)
+{
+	struct ircomm_tty_cb *self;
+	struct ircomm_tty_info info;
+
+	IRDA_DEBUG(2, __FUNCTION__"()\n");
+
+	info.daddr = discovery->daddr;
+	info.saddr = discovery->saddr;
+
+	self = (struct ircomm_tty_cb *) hashbin_get_first(ircomm_tty);
+	while (self != NULL) {
+		ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+		
+		ircomm_tty_do_event(self, IRCOMM_TTY_DISCOVERY_INDICATION, 
+				    NULL, &info);
+
+		self = (struct ircomm_tty_cb *) hashbin_get_next(ircomm_tty);
+	}
+}
+
+/*
+ * Function ircomm_tty_disconnect_indication (instance, sap, reason, skb)
+ *
+ *    Link disconnected
+ *
+ */
+void ircomm_tty_disconnect_indication(void *instance, void *sap, 
+				      LM_REASON reason,
+				      struct sk_buff *skb)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	if (!self->tty)
+		return;
+
+	/* This will stop control data transfers */
+	self->flow = FLOW_STOP;
+
+	/* Stop data transfers */
+	self->tty->hw_stopped = 1;
+
+	ircomm_tty_do_event(self, IRCOMM_TTY_DISCONNECT_INDICATION, NULL, 
+			    NULL);
+}
+
+/*
+ * Function ircomm_tty_getvalue_confirm (result, obj_id, value, priv)
+ *
+ *    Got result from the IAS query we make
+ *
+ */
+static void ircomm_tty_getvalue_confirm(int result, __u16 obj_id, 
+					struct ias_value *value, 
+					void *priv)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) priv;
+
+	IRDA_DEBUG(2, __FUNCTION__"()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	/* We probably don't need to make any more queries */
+	iriap_close(self->iriap);
+	self->iriap = NULL;
+
+	/* Check if request succeeded */
+	if (result != IAS_SUCCESS) {
+		IRDA_DEBUG(4, __FUNCTION__ "(), got NULL value!\n");
+		return;
+	}
+
+	switch (value->type) {
+ 	case IAS_OCT_SEQ:
+		IRDA_DEBUG(2, __FUNCTION__"(), got octet sequence\n");
+
+		irda_param_extract_all(self, value->t.oct_seq, value->len,
+				       &ircomm_param_info);
+
+		ircomm_tty_do_event(self, IRCOMM_TTY_GOT_PARAMETERS, NULL, 
+				    NULL);
+		break;
+	case IAS_INTEGER:
+		/* Got LSAP selector */	
+		IRDA_DEBUG(2, __FUNCTION__"(), got lsapsel = %d\n", 
+			   value->t.integer);
+
+		if (value->t.integer == -1) {
+			IRDA_DEBUG(0, __FUNCTION__"(), invalid value!\n");
+		} else
+			self->dlsap_sel = value->t.integer;
+
+		ircomm_tty_do_event(self, IRCOMM_TTY_GOT_LSAPSEL, NULL, NULL);
+		break;
+	case IAS_MISSING:
+		IRDA_DEBUG(0, __FUNCTION__"(), got IAS_MISSING\n");
+		break;
+	default:
+		IRDA_DEBUG(0, __FUNCTION__"(), got unknown type!\n");
+		break;
+	}
+	irias_delete_value(value);
+}
+
+/*
+ * Function ircomm_tty_connect_confirm (instance, sap, qos, max_sdu_size, skb)
+ *
+ *    Connection confirmed
+ *
+ */
+void ircomm_tty_connect_confirm(void *instance, void *sap, 
+				struct qos_info *qos, 
+				__u32 max_data_size, 
+				__u8 max_header_size, 
+				struct sk_buff *skb)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	self->client = TRUE;
+	self->max_data_size = max_data_size;
+	self->max_header_size = max_header_size;
+	self->flow = FLOW_START;
+
+	ircomm_tty_do_event(self, IRCOMM_TTY_CONNECT_CONFIRM, NULL, NULL);
+
+	dev_kfree_skb(skb);
+}
+
+/*
+ * Function ircomm_tty_connect_indication (instance, sap, qos, max_sdu_size, 
+ *                                         skb)
+ *
+ *    we are discovered and being requested to connect by remote device !
+ *
+ */
+void ircomm_tty_connect_indication(void *instance, void *sap, 
+				   struct qos_info *qos, 
+				   __u32 max_data_size,
+				   __u8 max_header_size, 
+				   struct sk_buff *skb)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+	int clen;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	self->client = FALSE;
+	self->max_data_size = max_data_size;
+	self->max_header_size = max_header_size;
+	self->flow = FLOW_START;
+
+	clen = skb->data[0];
+	if (clen)
+		irda_param_extract_all(self, skb->data+1, 
+				       IRDA_MIN(skb->len, clen), 
+				       &ircomm_param_info);
+
+	ircomm_tty_do_event(self, IRCOMM_TTY_CONNECT_INDICATION, NULL, NULL);
+
+	dev_kfree_skb(skb);
+}
+
+/*
+ * Function ircomm_tty_link_established (self)
+ *
+ *    Called when the IrCOMM link is established
+ *
+ */
+void ircomm_tty_link_established(struct ircomm_tty_cb *self)
+{
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	if (!self->tty)
+		return;
+	
+	del_timer(&self->watchdog_timer);
+
+	/* 
+	 * IrCOMM link is now up, and if we are not using hardware
+	 * flow-control, then declare the hardware as running. Otherwise we
+	 * will have to wait for the peer device (DCE) to raise the CTS
+	 * line.  
+	 */
+	if (self->flags & ASYNC_CTS_FLOW) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), waiting for CTS ...\n");
+		return;
+	} else {
+		IRDA_DEBUG(2, __FUNCTION__ "(), starting hardware!\n");
+
+		self->tty->hw_stopped = 0;
+	
+		/* Wake up processes blocked on open */
+		wake_up_interruptible(&self->open_wait);
+	}
+
+	queue_task(&self->tqueue, &tq_immediate);
+	mark_bh(IMMEDIATE_BH);
+}
+
+/*
+ * Function irlan_start_watchdog_timer (self, timeout)
+ *
+ *    Start the watchdog timer. This timer is used to make sure that any 
+ *    connection attempt is successful, and if not, we will retry after 
+ *    the timeout
+ */
+void ircomm_tty_start_watchdog_timer(struct ircomm_tty_cb *self, int timeout)
+{
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	irda_start_timer(&self->watchdog_timer, timeout, (void *) self,
+			 ircomm_tty_watchdog_timer_expired);
+}
+
+/*
+ * Function ircomm_tty_watchdog_timer_expired (data)
+ *
+ *    Called when the connect procedure have taken to much time.
+ *
+ */
+void ircomm_tty_watchdog_timer_expired(void *data)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) data;
+	
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	ircomm_tty_do_event(self, IRCOMM_TTY_WD_TIMER_EXPIRED, NULL, NULL);
+}
+
+/*
+ * Function ircomm_tty_state_idle (self, event, skb, info)
+ *
+ *    Just hanging around
+ *
+ */
+static int ircomm_tty_state_idle(struct ircomm_tty_cb *self, 
+				 IRCOMM_TTY_EVENT event, 
+				 struct sk_buff *skb, 
+				 struct ircomm_tty_info *info)
+{
+	int ret = 0;
+
+	IRDA_DEBUG(2, __FUNCTION__": state=%s, event=%s\n",
+		   ircomm_tty_state[self->state], ircomm_tty_event[event]);
+	switch (event) {
+	case IRCOMM_TTY_ATTACH_CABLE:
+		/* Try to discover any remote devices */		
+		ircomm_tty_start_watchdog_timer(self, 3*HZ);
+		ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH);
+		
+		irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS);
+		break;
+	case IRCOMM_TTY_DISCOVERY_INDICATION:
+		self->daddr = info->daddr;
+		self->saddr = info->saddr;
+
+		if (self->iriap) {
+			WARNING(__FUNCTION__ 
+				"(), busy with a previous query\n");
+			return -EBUSY;
+		}
+
+		self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,
+					 ircomm_tty_getvalue_confirm);
+
+		iriap_getvaluebyclass_request(self->iriap,
+					      self->saddr, self->daddr,
+					      "IrDA:IrCOMM", "Parameters");
+		
+		ircomm_tty_start_watchdog_timer(self, 3*HZ);
+		ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_PARAMETERS);
+		break;
+	case IRCOMM_TTY_CONNECT_INDICATION:
+		del_timer(&self->watchdog_timer);
+
+		/* Accept connection */
+		ircomm_connect_response(self->ircomm, NULL);
+		ircomm_tty_next_state(self, IRCOMM_TTY_READY);
+		break;
+	case IRCOMM_TTY_WD_TIMER_EXPIRED:
+		/* Just stay idle */
+		break;
+	case IRCOMM_TTY_DETACH_CABLE:
+		ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
+		break;
+	default:
+		IRDA_DEBUG(2, __FUNCTION__"(), unknown event: %s\n",
+			   ircomm_tty_event[event]);
+		return -EINVAL;
+	}
+	return ret;
+}
+
+/*
+ * Function ircomm_tty_state_search (self, event, skb, info)
+ *
+ *    Trying to discover an IrCOMM device
+ *
+ */
+static int ircomm_tty_state_search(struct ircomm_tty_cb *self, 
+				   IRCOMM_TTY_EVENT event, 
+				   struct sk_buff *skb, 
+				   struct ircomm_tty_info *info)
+{
+	int ret = 0;
+
+	IRDA_DEBUG(2, __FUNCTION__": state=%s, event=%s\n",
+		   ircomm_tty_state[self->state], ircomm_tty_event[event]);
+
+	switch (event) {
+	case IRCOMM_TTY_DISCOVERY_INDICATION:
+		self->daddr = info->daddr;
+		self->saddr = info->saddr;
+
+		if (self->iriap) {
+			WARNING(__FUNCTION__ 
+				"(), busy with a previous query\n");
+			return -EBUSY;
+		}
+		
+		self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,
+					 ircomm_tty_getvalue_confirm);
+		
+		if (self->service_type == IRCOMM_3_WIRE_RAW) {
+			iriap_getvaluebyclass_request(self->iriap, self->saddr,
+						      self->daddr, "IrLPT", 
+						      "IrDA:IrLMP:LsapSel");
+			ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_LSAP_SEL);
+		} else {
+			iriap_getvaluebyclass_request(self->iriap, self->saddr,
+						      self->daddr, 
+						      "IrDA:IrCOMM", 
+						      "Parameters");
+
+			ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_PARAMETERS);
+		}
+		ircomm_tty_start_watchdog_timer(self, 3*HZ);
+		break;
+	case IRCOMM_TTY_CONNECT_INDICATION:
+		del_timer(&self->watchdog_timer);
+
+		/* Accept connection */
+		ircomm_connect_response(self->ircomm, NULL);
+		ircomm_tty_next_state(self, IRCOMM_TTY_READY);
+		break;
+	case IRCOMM_TTY_WD_TIMER_EXPIRED:
+#if 1
+		/* Give up */
+#else
+		/* Try to discover any remote devices */		
+		ircomm_tty_start_watchdog_timer(self, 3*HZ);
+		irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS);
+#endif
+		break;
+	case IRCOMM_TTY_DETACH_CABLE:
+		ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
+		break;
+	default:
+		IRDA_DEBUG(2, __FUNCTION__"(), unknown event: %s\n",
+			   ircomm_tty_event[event]);
+		return -EINVAL;
+	}
+	return ret;
+}
+
+/*
+ * Function ircomm_tty_state_query (self, event, skb, info)
+ *
+ *    Querying the remote LM-IAS for IrCOMM parameters
+ *
+ */
+static int ircomm_tty_state_query_parameters(struct ircomm_tty_cb *self, 
+					     IRCOMM_TTY_EVENT event, 
+					     struct sk_buff *skb, 
+					     struct ircomm_tty_info *info)
+{
+	int ret = 0;
+
+	IRDA_DEBUG(2, __FUNCTION__": state=%s, event=%s\n",
+		   ircomm_tty_state[self->state], ircomm_tty_event[event]);
+
+	switch (event) {
+	case IRCOMM_TTY_GOT_PARAMETERS:
+		if (self->iriap) {
+			WARNING(__FUNCTION__ 
+				"(), busy with a previous query\n");
+			return -EBUSY;
+		}
+		
+		self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,
+					 ircomm_tty_getvalue_confirm);
+
+		iriap_getvaluebyclass_request(self->iriap, self->saddr, 
+					      self->daddr, "IrDA:IrCOMM", 
+					      "IrDA:TinyTP:LsapSel");
+
+		ircomm_tty_start_watchdog_timer(self, 3*HZ);
+		ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_LSAP_SEL);
+		break;
+	case IRCOMM_TTY_WD_TIMER_EXPIRED:
+		/* Go back to search mode */
+		ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH);
+		ircomm_tty_start_watchdog_timer(self, 3*HZ); 
+		break;
+	case IRCOMM_TTY_CONNECT_INDICATION:
+		del_timer(&self->watchdog_timer);
+
+		/* Accept connection */
+		ircomm_connect_response(self->ircomm, NULL);
+		ircomm_tty_next_state(self, IRCOMM_TTY_READY);
+		break;
+	case IRCOMM_TTY_DETACH_CABLE:
+		ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
+		break;
+	default:
+		IRDA_DEBUG(2, __FUNCTION__"(), unknown event: %s\n",
+			   ircomm_tty_event[event]);
+		return -EINVAL;
+	}
+	return ret;
+}
+
+/*
+ * Function ircomm_tty_state_query_lsap_sel (self, event, skb, info)
+ *
+ *    Query remote LM-IAS for the LSAP selector which we can connect to
+ *
+ */
+static int ircomm_tty_state_query_lsap_sel(struct ircomm_tty_cb *self, 
+					   IRCOMM_TTY_EVENT event, 
+					   struct sk_buff *skb, 
+					   struct ircomm_tty_info *info)
+{
+	int ret = 0;
+
+	IRDA_DEBUG(2, __FUNCTION__": state=%s, event=%s\n",
+		   ircomm_tty_state[self->state], ircomm_tty_event[event]);
+
+	switch (event) {
+	case IRCOMM_TTY_GOT_LSAPSEL:
+		/* Connect to remote device */
+		ret = ircomm_connect_request(self->ircomm, self->dlsap_sel,
+					     self->saddr, self->daddr, 
+					     NULL, self->service_type);
+		ircomm_tty_start_watchdog_timer(self, 3*HZ);
+		ircomm_tty_next_state(self, IRCOMM_TTY_SETUP);
+		break;
+	case IRCOMM_TTY_WD_TIMER_EXPIRED:
+		/* Go back to search mode */
+		ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH);
+		ircomm_tty_start_watchdog_timer(self, 3*HZ);
+		break;
+	case IRCOMM_TTY_CONNECT_INDICATION:
+		del_timer(&self->watchdog_timer);
+
+		/* Accept connection */
+		ircomm_connect_response(self->ircomm, NULL);
+		ircomm_tty_next_state(self, IRCOMM_TTY_READY);
+		break;
+	case IRCOMM_TTY_DETACH_CABLE:
+		ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
+		break;
+	default:
+		IRDA_DEBUG(2, __FUNCTION__"(), unknown event: %s\n",
+			   ircomm_tty_event[event]);
+		return -EINVAL;
+	}
+	return ret;
+}
+
+/*
+ * Function ircomm_tty_state_setup (self, event, skb, info)
+ *
+ *    Trying to connect
+ *
+ */
+static int ircomm_tty_state_setup(struct ircomm_tty_cb *self, 
+				  IRCOMM_TTY_EVENT event, 
+				  struct sk_buff *skb, 
+				  struct ircomm_tty_info *info)
+{
+	int ret = 0;
+
+	IRDA_DEBUG(2, __FUNCTION__": state=%s, event=%s\n",
+		   ircomm_tty_state[self->state], ircomm_tty_event[event]);
+
+	switch (event) {
+	case IRCOMM_TTY_CONNECT_CONFIRM:
+		del_timer(&self->watchdog_timer);
+		ircomm_tty_next_state(self, IRCOMM_TTY_READY);
+		
+		/* 
+		 * Send initial parameters. This will also send out queued
+		 * parameters waiting for the connection to come up 
+		 */
+		ircomm_tty_send_initial_parameters(self);
+		ircomm_tty_link_established(self);
+		break;
+	case IRCOMM_TTY_CONNECT_INDICATION:
+		del_timer(&self->watchdog_timer);
+		
+		/* Accept connection */
+		ircomm_connect_response(self->ircomm, NULL);
+		ircomm_tty_next_state(self, IRCOMM_TTY_READY);
+		break;
+	case IRCOMM_TTY_WD_TIMER_EXPIRED:
+		/* Go back to search mode */
+		ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH);
+		ircomm_tty_start_watchdog_timer(self, 3*HZ);
+		break;
+	case IRCOMM_TTY_DETACH_CABLE:
+		/* ircomm_disconnect_request(self->ircomm, NULL); */
+		ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
+		break;
+	default:
+		IRDA_DEBUG(2, __FUNCTION__"(), unknown event: %s\n",
+			   ircomm_tty_event[event]);
+		return -EINVAL;
+	}
+	return ret;
+}
+
+/*
+ * Function ircomm_tty_state_ready (self, event, skb, info)
+ *
+ *    IrCOMM is now connected
+ *
+ */
+static int ircomm_tty_state_ready(struct ircomm_tty_cb *self, 
+				  IRCOMM_TTY_EVENT event, 
+				  struct sk_buff *skb, 
+				  struct ircomm_tty_info *info)
+{
+	int ret = 0;
+
+	switch (event) {
+	case IRCOMM_TTY_DATA_REQUEST:
+		ret = ircomm_data_request(self->ircomm, skb);
+		break;		
+	case IRCOMM_TTY_DETACH_CABLE:
+		ircomm_disconnect_request(self->ircomm, NULL);
+		ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
+		break;
+	case IRCOMM_TTY_DISCONNECT_INDICATION:
+		ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH);
+		ircomm_tty_start_watchdog_timer(self, 3*HZ);
+
+		if (self->flags & ASYNC_CHECK_CD) {
+			/* Drop carrier */
+			self->settings.dce = IRCOMM_DELTA_CD;
+			ircomm_tty_check_modem_status(self);
+		} else {
+			IRDA_DEBUG(0, __FUNCTION__ "(), hanging up!\n");
+			if (self->tty)
+				tty_hangup(self->tty);
+		}
+		break;
+	default:
+		IRDA_DEBUG(2, __FUNCTION__"(), unknown event: %s\n",
+			   ircomm_tty_event[event]);
+		return -EINVAL;
+	}
+	return ret;
+}
+
+/*
+ * Function ircomm_tty_do_event (self, event, skb)
+ *
+ *    Process event
+ *
+ */
+int ircomm_tty_do_event(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event,
+			struct sk_buff *skb, struct ircomm_tty_info *info) 
+{
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+	IRDA_DEBUG(2, __FUNCTION__": state=%s, event=%s\n",
+		   ircomm_tty_state[self->state], ircomm_tty_event[event]);
+	
+	return (*state[self->state])(self, event, skb, info);
+}
+
+/*
+ * Function ircomm_tty_next_state (self, state)
+ *
+ *    Switch state
+ *
+ */
+void ircomm_tty_next_state(struct ircomm_tty_cb *self, IRCOMM_TTY_STATE state)
+{
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	self->state = state;
+	
+	IRDA_DEBUG(2, __FUNCTION__": next state=%s, service type=%d\n", 
+		   ircomm_tty_state[self->state], self->service_type);
+}
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/ircomm/ircomm_tty_ioctl.c linux.15p9/net/irda/ircomm/ircomm_tty_ioctl.c
--- linux.vanilla/net/irda/ircomm/ircomm_tty_ioctl.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/net/irda/ircomm/ircomm_tty_ioctl.c	Tue Jan 18 01:08:18 2000
@@ -0,0 +1,465 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_tty_ioctl.c
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Thu Jun 10 14:39:09 1999
+ * Modified at:   Wed Jan  5 14:46:17 2000
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/termios.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+
+#include <net/irda/ircomm_core.h>
+#include <net/irda/ircomm_param.h>
+#include <net/irda/ircomm_tty_attach.h>
+#include <net/irda/ircomm_tty.h>
+
+#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
+
+/*
+ * Function ircomm_tty_change_speed (driver)
+ *
+ *    Change speed of the driver. If the remote device is a DCE, then this
+ *    should make it change the speed of its serial port
+ */
+void ircomm_tty_change_speed(struct ircomm_tty_cb *self)
+{
+	unsigned cflag, cval;
+	int baud;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	if (!self->tty || !self->tty->termios || !self->ircomm)
+		return;
+
+	cflag = self->tty->termios->c_cflag;
+
+	/*  byte size and parity */
+	switch (cflag & CSIZE) {
+	case CS5: cval = IRCOMM_WSIZE_5; break;
+	case CS6: cval = IRCOMM_WSIZE_6; break;
+	case CS7: cval = IRCOMM_WSIZE_7; break;
+	case CS8: cval = IRCOMM_WSIZE_8; break;
+	default:  cval = IRCOMM_WSIZE_5; break;
+	}
+	if (cflag & CSTOPB)
+		cval |= IRCOMM_2_STOP_BIT;
+	
+	if (cflag & PARENB)
+		cval |= IRCOMM_PARITY_ENABLE;
+	if (!(cflag & PARODD))
+		cval |= IRCOMM_PARITY_EVEN;
+
+	/* Determine divisor based on baud rate */
+	baud = tty_get_baud_rate(self->tty);
+	if (!baud)
+		baud = 9600;	/* B0 transition handled in rs_set_termios */
+
+	self->settings.data_rate = baud;
+	ircomm_param_request(self, IRCOMM_DATA_RATE, FALSE);
+	
+	/* CTS flow control flag and modem status interrupts */
+	if (cflag & CRTSCTS) {
+		self->flags |= ASYNC_CTS_FLOW;
+		self->settings.flow_control |= IRCOMM_RTS_CTS_IN;
+	} else {
+		self->flags &= ~ASYNC_CTS_FLOW;
+		self->settings.flow_control &= ~IRCOMM_RTS_CTS_IN;
+	}
+	if (cflag & CLOCAL)
+		self->flags &= ~ASYNC_CHECK_CD;
+	else
+		self->flags |= ASYNC_CHECK_CD;
+#if 0	
+	/*
+	 * Set up parity check flag
+	 */
+
+	if (I_INPCK(self->tty))
+		driver->read_status_mask |= LSR_FE | LSR_PE;
+	if (I_BRKINT(driver->tty) || I_PARMRK(driver->tty))
+		driver->read_status_mask |= LSR_BI;
+	
+	/*
+	 * Characters to ignore
+	 */
+	driver->ignore_status_mask = 0;
+	if (I_IGNPAR(driver->tty))
+		driver->ignore_status_mask |= LSR_PE | LSR_FE;
+
+	if (I_IGNBRK(self->tty)) {
+		self->ignore_status_mask |= LSR_BI;
+		/*
+		 * If we're ignore parity and break indicators, ignore 
+		 * overruns too. (For real raw support).
+		 */
+		if (I_IGNPAR(self->tty)) 
+			self->ignore_status_mask |= LSR_OE;
+	}
+#endif
+	self->settings.data_format = cval;
+
+	ircomm_param_request(self, IRCOMM_DATA_FORMAT, FALSE);
+ 	ircomm_param_request(self, IRCOMM_FLOW_CONTROL, TRUE);
+}
+
+/*
+ * Function ircomm_tty_set_termios (tty, old_termios)
+ *
+ *    This routine allows the tty driver to be notified when device's
+ *    termios settings have changed.  Note that a well-designed tty driver
+ *    should be prepared to accept the case where old == NULL, and try to
+ *    do something rational.
+ */
+void ircomm_tty_set_termios(struct tty_struct *tty, 
+			    struct termios *old_termios)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+	unsigned int cflag = tty->termios->c_cflag;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	if ((cflag == old_termios->c_cflag) && 
+	    (RELEVANT_IFLAG(tty->termios->c_iflag) == 
+	     RELEVANT_IFLAG(old_termios->c_iflag)))
+	{
+		return;
+	}
+
+	ircomm_tty_change_speed(self);
+
+	/* Handle transition to B0 status */
+	if ((old_termios->c_cflag & CBAUD) &&
+	    !(cflag & CBAUD)) {
+		self->settings.dte &= ~(IRCOMM_DTR|IRCOMM_RTS);
+		ircomm_param_request(self, IRCOMM_DTE, TRUE);
+	}
+	
+	/* Handle transition away from B0 status */
+	if (!(old_termios->c_cflag & CBAUD) &&
+	    (cflag & CBAUD)) {
+		self->settings.dte |= IRCOMM_DTR;
+		if (!(tty->termios->c_cflag & CRTSCTS) || 
+		    !test_bit(TTY_THROTTLED, &tty->flags)) {
+			self->settings.dte |= IRCOMM_RTS;
+		}
+		ircomm_param_request(self, IRCOMM_DTE, TRUE);
+	}
+	
+	/* Handle turning off CRTSCTS */
+	if ((old_termios->c_cflag & CRTSCTS) &&
+	    !(tty->termios->c_cflag & CRTSCTS)) 
+	{
+		tty->hw_stopped = 0;
+		ircomm_tty_start(tty);
+	}
+}
+
+/*
+ * Function ircomm_tty_get_modem_info (self, value)
+ *
+ *    
+ *
+ */
+static int ircomm_tty_get_modem_info(struct ircomm_tty_cb *self, 
+				     unsigned int *value)
+{
+	unsigned int result;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	result =  ((self->settings.dte & IRCOMM_RTS) ? TIOCM_RTS : 0)
+		| ((self->settings.dte & IRCOMM_DTR) ? TIOCM_DTR : 0)
+		| ((self->settings.dce & IRCOMM_CD)  ? TIOCM_CAR : 0)
+		| ((self->settings.dce & IRCOMM_RI)  ? TIOCM_RNG : 0)
+		| ((self->settings.dce & IRCOMM_DSR) ? TIOCM_DSR : 0)
+		| ((self->settings.dce & IRCOMM_CTS) ? TIOCM_CTS : 0);
+
+	return put_user(result, value);
+}
+
+/*
+ * Function set_modem_info (driver, cmd, value)
+ *
+ *    
+ *
+ */
+static int ircomm_tty_set_modem_info(struct ircomm_tty_cb *self, 
+				     unsigned int cmd, unsigned int *value)
+{ 
+	unsigned int arg;
+	__u8 old_rts, old_dtr;
+	int error;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+	error = get_user(arg, value);
+	if (error)
+		return error;
+
+	old_rts = self->settings.dte & IRCOMM_RTS;
+	old_dtr = self->settings.dte & IRCOMM_DTR;
+
+	switch (cmd) {
+	case TIOCMBIS: 
+		if (arg & TIOCM_RTS) 
+			self->settings.dte |= IRCOMM_RTS;
+		if (arg & TIOCM_DTR)
+			self->settings.dte |= IRCOMM_DTR;
+		break;
+		
+	case TIOCMBIC:
+		if (arg & TIOCM_RTS)
+			self->settings.dte &= ~IRCOMM_RTS;
+		if (arg & TIOCM_DTR)
+ 			self->settings.dte &= ~IRCOMM_DTR;
+ 		break;
+		
+	case TIOCMSET:
+ 		self->settings.dte = 
+			((self->settings.dte & ~(IRCOMM_RTS | IRCOMM_DTR))
+			 | ((arg & TIOCM_RTS) ? IRCOMM_RTS : 0)
+			 | ((arg & TIOCM_DTR) ? IRCOMM_DTR : 0));
+		break;
+		
+	default:
+		return -EINVAL;
+	}
+	
+	if ((self->settings.dte & IRCOMM_RTS) != old_rts)
+		self->settings.dte |= IRCOMM_DELTA_RTS;
+
+	if ((self->settings.dte & IRCOMM_DTR) != old_dtr)
+		self->settings.dte |= IRCOMM_DELTA_DTR;
+
+	ircomm_param_request(self, IRCOMM_DTE, TRUE);
+	
+	return 0;
+}
+
+/*
+ * Function get_serial_info (driver, retinfo)
+ *
+ *    
+ *
+ */
+static int ircomm_tty_get_serial_info(struct ircomm_tty_cb *self,
+				      struct serial_struct *retinfo)
+{
+	struct serial_struct info;
+   
+	if (!retinfo)
+		return -EFAULT;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	memset(&info, 0, sizeof(info));
+	info.line = self->line;
+	info.flags = self->flags;
+	info.baud_base = self->settings.data_rate;
+	info.close_delay = self->close_delay;
+	info.closing_wait = self->closing_wait;
+
+	/* For compatibility  */
+ 	info.type = PORT_16550A;
+ 	info.port = 0;
+ 	info.irq = 0;
+	info.xmit_fifo_size = 0;
+	info.hub6 = 0;   
+	info.custom_divisor = 0;
+
+	if (copy_to_user(retinfo, &info, sizeof(*retinfo)))
+		return -EFAULT;
+
+	return 0;
+}
+
+/*
+ * Function set_serial_info (driver, new_info)
+ *
+ *    
+ *
+ */
+static int ircomm_tty_set_serial_info(struct ircomm_tty_cb *self,
+				      struct serial_struct *new_info)
+{
+#if 0
+	struct serial_struct new_serial;
+	struct ircomm_tty_cb old_state, *state;
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
+		return -EFAULT;
+
+
+	state = self
+	old_state = *self;
+  
+	if (!capable(CAP_SYS_ADMIN)) {
+		if ((new_serial.baud_base != state->settings.data_rate) ||
+		    (new_serial.close_delay != state->close_delay) ||
+		    ((new_serial.flags & ~ASYNC_USR_MASK) !=
+		     (self->flags & ~ASYNC_USR_MASK)))
+			return -EPERM;
+		state->flags = ((state->flags & ~ASYNC_USR_MASK) |
+				 (new_serial.flags & ASYNC_USR_MASK));
+		self->flags = ((self->flags & ~ASYNC_USR_MASK) |
+			       (new_serial.flags & ASYNC_USR_MASK));
+		/* self->custom_divisor = new_serial.custom_divisor; */
+		goto check_and_exit;
+	}
+
+	/*
+	 * OK, past this point, all the error checking has been done.
+	 * At this point, we start making changes.....
+	 */
+
+	if (self->settings.data_rate != new_serial.baud_base) {
+		self->settings.data_rate = new_serial.baud_base;
+		ircomm_param_request(self, IRCOMM_DATA_RATE, TRUE);
+	}
+
+	self->close_delay = new_serial.close_delay * HZ/100;
+	self->closing_wait = new_serial.closing_wait * HZ/100;
+	/* self->custom_divisor = new_serial.custom_divisor; */
+
+	self->flags = ((self->flags & ~ASYNC_FLAGS) |
+		       (new_serial.flags & ASYNC_FLAGS));
+	self->tty->low_latency = (self->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+
+ check_and_exit:
+
+	if (self->flags & ASYNC_INITIALIZED) {
+		if (((old_state.flags & ASYNC_SPD_MASK) !=
+		     (self->flags & ASYNC_SPD_MASK)) ||
+		    (old_driver.custom_divisor != driver->custom_divisor)) {
+			if ((driver->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+				driver->tty->alt_speed = 57600;
+			if ((driver->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+				driver->tty->alt_speed = 115200;
+			if ((driver->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+				driver->tty->alt_speed = 230400;
+			if ((driver->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+				driver->tty->alt_speed = 460800;
+			ircomm_tty_change_speed(driver);
+		}
+	}
+#endif
+	return 0;
+}
+
+/*
+ * Function ircomm_tty_ioctl (tty, file, cmd, arg)
+ *
+ *    
+ *
+ */
+int ircomm_tty_ioctl(struct tty_struct *tty, struct file *file, 
+		     unsigned int cmd, unsigned long arg)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+	int ret = 0;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
+	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+		if (tty->flags & (1 << TTY_IO_ERROR))
+		    return -EIO;
+	}
+
+	switch (cmd) {
+	case TIOCMGET:
+		ret = ircomm_tty_get_modem_info(self, (unsigned int *) arg);
+		break;
+	case TIOCMBIS:
+	case TIOCMBIC:
+	case TIOCMSET:
+		ret = ircomm_tty_set_modem_info(self, cmd, (unsigned int *) arg);
+		break;
+	case TIOCGSERIAL:
+		ret = ircomm_tty_get_serial_info(self, (struct serial_struct *) arg);
+		break;
+	case TIOCSSERIAL:
+		ret = ircomm_tty_set_serial_info(self, (struct serial_struct *) arg);
+		break;
+	case TIOCMIWAIT:
+		IRDA_DEBUG(0, "(), TIOCMIWAIT, not impl!\n");
+		break;
+
+	case TIOCGICOUNT:
+		IRDA_DEBUG(0, __FUNCTION__ "(), TIOCGICOUNT not impl!\n");
+#if 0
+		save_flags(flags); cli();
+		cnow = driver->icount;
+		restore_flags(flags);
+		p_cuser = (struct serial_icounter_struct *) arg;
+		error = put_user(cnow.cts, &p_cuser->cts);
+		if (error) return error;
+		error = put_user(cnow.dsr, &p_cuser->dsr);
+		if (error) return error;
+		error = put_user(cnow.rng, &p_cuser->rng);
+		if (error) return error;
+		error = put_user(cnow.dcd, &p_cuser->dcd);
+		if (error) return error;
+		error = put_user(cnow.rx, &p_cuser->rx);
+		if (error) return error;
+		error = put_user(cnow.tx, &p_cuser->tx);
+		if (error) return error;
+		error = put_user(cnow.frame, &p_cuser->frame);
+		if (error) return error;
+		error = put_user(cnow.overrun, &p_cuser->overrun);
+		if (error) return error;
+		error = put_user(cnow.parity, &p_cuser->parity);
+		if (error) return error;
+		error = put_user(cnow.brk, &p_cuser->brk);
+		if (error) return error;
+		error = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
+		if (error) return error;			
+#endif		
+		return 0;
+	default:
+		ret = -ENOIOCTLCMD;  /* ioctls which we must ignore */
+	}
+	return ret;
+}
+
+
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/ircomm/irvtd_driver.c linux.15p9/net/irda/ircomm/irvtd_driver.c
--- linux.vanilla/net/irda/ircomm/irvtd_driver.c	Sat Aug 14 02:26:52 1999
+++ linux.15p9/net/irda/ircomm/irvtd_driver.c	Thu Jan  1 01:00:00 1970
@@ -1,2067 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      irvtd_driver.c
- * Version:       
- * Description:   Virtual tty driver (the "port emulation entity" of IrCOMM)
- * Status:        Experimental.
- * Author:        Takahide Higuchi <thiguchi@pluto.dti.ne.jp>
- * Source:        serial.c by Linus Torvalds
- *                isdn_tty.c by Fritz Elfert
- *
- *     Copyright (c) 1998-1999, Takahide Higuchi, <thiguchi@pluto.dti.ne.jp>,
- *     All Rights Reserved.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     I, Takahide Higuchi, provide no warranty for any of this software.
- *     This material is provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include <linux/fs.h>
-#include <linux/sched.h>
-#include <linux/termios.h>
-#include <linux/tty.h>
-#include <asm/segment.h>
-#include <asm/uaccess.h>
-
-#include <net/irda/irda.h>
-#include <net/irda/irttp.h>
-#include <net/irda/irias_object.h>
-
-#include <net/irda/irvtd.h>
-
-#ifndef MIN
-#define MIN(a,b)        ((a) < (b) ? (a) : (b))
-#endif
-
-#define DO_RESTART
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
-struct tty_driver irvtd_drv;
-struct tty_struct *irvtd_table[COMM_MAX_TTY];
-struct termios *irvtd_termios[COMM_MAX_TTY];
-struct termios *irvtd_termios_locked[COMM_MAX_TTY];
-static int irvtd_refcount;
-struct irvtd_cb **irvtd = NULL;
-
-static char *revision_date = "Wed May 26 00:49:11 1999";
-
-
-/*
- * prototypes
- */
-
-int irvtd_open(struct tty_struct *tty, struct file *filp);
-void irvtd_close(struct tty_struct * tty, struct file * filp);
-int irvtd_write(struct tty_struct * tty, int from_user,
-			const unsigned char *buf, int count);
-void irvtd_put_char(struct tty_struct *tty, unsigned char ch);
-int irvtd_write_room(struct tty_struct *tty);
-int irvtd_chars_in_buffer(struct tty_struct *tty);
-int irvtd_ioctl(struct tty_struct *tty, struct file * file,
-	     unsigned int cmd, unsigned long arg);
-void irvtd_set_termios(struct tty_struct *tty, struct termios * old);
-void irvtd_throttle(struct tty_struct *tty);
-void irvtd_unthrottle(struct tty_struct *tty);
-void irvtd_stop(struct tty_struct *tty);
-void irvtd_start(struct tty_struct *tty);
-void irvtd_hangup(struct tty_struct *tty);
-void irvtd_flush_buffer(struct tty_struct *tty);
-void irvtd_flush_chars(struct tty_struct *tty);
-
-static void change_speed(struct irvtd_cb *driver);
-static void irvtd_write_to_tty( struct irvtd_cb *);
-static void irvtd_send_data_request( struct irvtd_cb *);
-static void irvtd_break(struct tty_struct *tty, int break_state);
-static void irvtd_send_xchar(struct tty_struct *tty, char ch);
-static void irvtd_wait_until_sent(struct tty_struct *tty, int timeout);
-
-static void irvtd_start_tx_timer( struct irvtd_cb *driver, int timeout);
-static void irvtd_tx_timer_expired(unsigned long data);
-static void irvtd_start_rx_timer( struct irvtd_cb *driver, int timeout);
-static void irvtd_rx_timer_expired(unsigned long data);
-
-static int line_info(char *buf, struct irvtd_cb *driver);
-static int irvtd_read_proc(char *buf, char **start, off_t offset, int len,
-			   int *eof, void *unused);
-
-
-/*
- **********************************************************************
- *
- * ircomm_receive_data() and friends
- *
- * like interrupt handler in the serial.c,we receive data when 
- * ircomm_data_indication comes
- *
- **********************************************************************
- */
-
-
-
-/* 
- * irvtd_write_to_tty
- * send incoming/queued data to tty
- */
-
-static void irvtd_write_to_tty( struct irvtd_cb *driver)
-{	
-	int status, c, flag;
-	struct sk_buff *skb;
-	struct tty_struct *tty = driver->tty;
-	
-	if(driver->rx_disable)
-		return;
-
- 	skb = skb_dequeue(&driver->rxbuff);
-	if(skb == NULL)
-		return; /* there's nothing */
-
-	/* 
-	 * we should parse controlchannel field here. 
-	 * (see process_data() in ircomm.c)
-	 */
-	ircomm_parse_tuples(driver->comm, skb, CONTROL_CHANNEL);
-	
-#ifdef IRVTD_DEBUG_RX
-	printk("received data:");
-	{
-		int i;
-		for ( i=0;i<skb->len;i++)
-			printk("%02x ", skb->data[i]);
-		printk("\n");
-	}
-#endif
-	
-	status = driver->comm->peer_line_status & driver->read_status_mask;
-	
-	/* 
-	 * if there are too many errors which make a character ignored,
-	 * drop characters
-	 */
-
-	if(status & driver->ignore_status_mask){
-		DEBUG(0,__FUNCTION__":some error:ignore characters.\n");
-		dev_kfree_skb(skb);
-		return;
-	}
-	
-	c = MIN(skb->len, (TTY_FLIPBUF_SIZE - tty->flip.count));
-	DEBUG(4, __FUNCTION__"skb_len=%d, tty->flip.count=%d \n"
-	      ,(int)skb->len, tty->flip.count);
-	
-	if (driver->comm->peer_break_signal ) {
-		driver->comm->peer_break_signal = 0;
-		DEBUG(0,"handling break....\n");
-		
-		flag = TTY_BREAK;
-		if (driver->flags & ASYNC_SAK)
-			/*
-			 * do_SAK() seems to be an implementation of the 
-			 * idea called "Secure Attention Key",
-			 * which seems to be discribed in "Orange book".
-			 * (which is published by U.S.military!!?? ,
-			 * see source of do_SAK())
-			 *
-			 * but what kind of security do we need 
-			 * when we use infrared communication??? :p)
-			 */
-			do_SAK(tty);
-	}else if (status & LSR_PE)
-		flag = TTY_PARITY;
-	else if (status & LSR_FE)
-		flag = TTY_FRAME;
-	else if (status & LSR_OE)
-		flag = TTY_OVERRUN;
-	else 
-		flag = TTY_NORMAL;
-	
-	if(c){
-		DEBUG(4,"writing %d chars to tty\n",c);
-		driver->icount.rx += c;
-		memset(tty->flip.flag_buf_ptr, flag, c);
-		memcpy(tty->flip.char_buf_ptr, skb->data, c);
-		tty->flip.flag_buf_ptr += c;
-		tty->flip.char_buf_ptr += c;
-		tty->flip.count += c;
-		skb_pull(skb,c);
-	}
-
-	if(skb->len == 0)
-		dev_kfree_skb(skb);
-	else
-	{
-		/* queue rest of data again */
-		DEBUG(4,__FUNCTION__":retrying frame!\n");
-
-		/* build a dummy control channel */
-		skb_push(skb,1);
-		*skb->data = 0;  /* clen is 0 */
-		skb_queue_head( &driver->rxbuff, skb );
-	}
-	
-	if(c)
-	/* let the process read its buffer! */
-		tty_flip_buffer_push(tty);
-	
-	if(skb_queue_len(&driver->rxbuff)< IRVTD_RX_QUEUE_LOW &&
-	   driver->ttp_stoprx){
-		DEBUG(1, __FUNCTION__"():FLOW_START\n");
-		/* 
-		 * next 2 lines must follow this order since irttp_flow_request()
-		 * will run its rx queue
-		 */
-		driver->ttp_stoprx = 0;
-		irttp_flow_request(driver->comm->tsap, FLOW_START);
-	}
-
-	if(skb_queue_empty(&driver->rxbuff) && driver->disconnect_pend){
-		/* disconnect */
-		driver->disconnect_pend = 0;
-		driver->rx_disable = 1;
-		tty_hangup(driver->tty);
-	}
-}
-
-static int irvtd_receive_data(void *instance, void *sap, struct sk_buff *skb)
-{	
-	struct irvtd_cb *driver = (struct irvtd_cb *)instance;
-
-	ASSERT(driver != NULL, return -1;);
-	ASSERT(driver->magic == IRVTD_MAGIC, return -1;);
-	DEBUG(4, __FUNCTION__"(): queue frame\n");
-
-	/* queue incoming data and make bottom half handler ready */
-
-	skb_queue_tail( &driver->rxbuff, skb );
-
-	if(skb_queue_len(&driver->rxbuff) > IRVTD_RX_QUEUE_HIGH){
-		DEBUG(1, __FUNCTION__"():FLOW_STOP\n");
-		irttp_flow_request(driver->comm->tsap, FLOW_STOP);
-		driver->ttp_stoprx = 1;
-	}
-	irvtd_write_to_tty(driver);
-
-	if(!skb_queue_empty(&driver->rxbuff))
-		irvtd_start_rx_timer(driver,0);
-	return 0;
-}
-
-/*
- ***********************************************************************
- *
- * irvtd_send_data() and friends
- *
- * like interrupt handler in the serial.c,we send data when 
- * a timer is expired
- *
- ***********************************************************************
- */
-
-
-static void irvtd_start_tx_timer( struct irvtd_cb *driver, int timeout)
-{
-	ASSERT( driver != NULL, return;);
-	ASSERT( driver->magic == IRVTD_MAGIC, return;);
-
-	del_timer( &driver->tx_timer);
-	
-	driver->tx_timer.data     = (unsigned long) driver;
-	driver->tx_timer.function = &irvtd_tx_timer_expired;
-	driver->tx_timer.expires  = jiffies + timeout;
-	
-	add_timer( &driver->tx_timer);
-}
-
-static void irvtd_start_rx_timer( struct irvtd_cb *driver, int timeout)
-{
-	ASSERT( driver != NULL, return;);
-	ASSERT( driver->magic == IRVTD_MAGIC, return;);
-
-	del_timer( &driver->rx_timer);
-	
-	driver->rx_timer.data     = (unsigned long) driver;
-	driver->rx_timer.function = &irvtd_rx_timer_expired;
-	driver->rx_timer.expires  = jiffies + timeout;
-	
-	add_timer( &driver->rx_timer);
-}
-
-
-static void irvtd_tx_timer_expired(unsigned long data)
-{
-	struct irvtd_cb *driver = (struct irvtd_cb *)data;
-
-	ASSERT(driver != NULL,return;);
-	ASSERT(driver->magic == IRVTD_MAGIC,return;);
-	DEBUG(4, __FUNCTION__"()\n");
-
-	irvtd_send_data_request(driver);
-}
-
-static void irvtd_rx_timer_expired(unsigned long data)
-{
-	struct irvtd_cb *driver = (struct irvtd_cb *)data;
-
-	ASSERT(driver != NULL,return;);
-	ASSERT(driver->magic == IRVTD_MAGIC,return;);
-	DEBUG(4, __FUNCTION__"()\n");
-
-	while(TTY_FLIPBUF_SIZE - driver->tty->flip.count
-	      && !skb_queue_empty(&driver->rxbuff))
-		irvtd_write_to_tty(driver);
-
-	DEBUG(1, __FUNCTION__"(): room in flip_buffer = %d\n",
-	      TTY_FLIPBUF_SIZE - driver->tty->flip.count);
-	
-	if(!skb_queue_empty(&driver->rxbuff))
-		/* handle it later */
-		irvtd_start_rx_timer(driver, 1);
-}
-
-
-static void irvtd_send_data_request(struct irvtd_cb *driver)
-{
-	int err;
-	struct sk_buff *skb = driver->txbuff;
-
-	ASSERT(skb != NULL,return;);
-	DEBUG(4, __FUNCTION__"()\n");
-
-	if(driver->tty->hw_stopped || driver->tx_disable)
-		return;
-	if(!skb->len)
-		return;   /* no data to send */
-
-#ifdef IRVTD_DEBUG_TX
-	DEBUG(4, "flush_txbuff:count(%d)\n",(int)skb->len);
-	{
-		int i;
-		for ( i=0;i<skb->len;i++)
-			printk("%02x", skb->data[i]);
-		printk("\n");
-	}
-#endif
-
-	DEBUG(1, __FUNCTION__"():len = %d, room = %d\n",(int)skb->len,
-	      skb_tailroom(skb));
-	driver->icount.tx += skb->len;
-	err = ircomm_data_request(driver->comm, driver->txbuff);
-	if (err){
-		ASSERT(err == 0,;);
-		DEBUG(1,"%d chars are lost\n",(int)skb->len);
-		skb_trim(skb, 0);
-	}
-
-	/* allocate a new frame */
-	skb = driver->txbuff 
-		= dev_alloc_skb(driver->tx_max_sdu_size + driver->max_header_size);
-	if (skb == NULL){
-		printk(__FUNCTION__"():alloc_skb failed!\n");
-	} else {
-		skb_reserve(skb, driver->max_header_size);
-	}
-
-	wake_up_interruptible(&driver->tty->write_wait);
-}
-
-
-/*
- ***********************************************************************
- *
- * indication/confirmation handlers:
- *
- * these routines are handlers for IrCOMM protocol stack
- *
- ***********************************************************************
- */
-
-/*
- * Function irvtd_connect_confirm (instance, sap, qos, max_sdu_size, skb)
- *
- *    ircomm_connect_request which we have send, has succeeded!
- *
- */
-void irvtd_connect_confirm(void *instance, void *sap, struct qos_info *qos,
-			   __u32 max_sdu_size, __u8 max_header_size, 
-			   struct sk_buff *skb)
-{
-	struct irvtd_cb *driver = (struct irvtd_cb *)instance;
-	ASSERT(driver != NULL, return;);
-	ASSERT(driver->magic == IRVTD_MAGIC, return;);
-
-
-	driver->tx_max_sdu_size = max_sdu_size;
-	driver->max_header_size = max_header_size;
-	/*
-	 * set default value
-	 */
-	
-	driver->msr |= (MSR_DCD|MSR_RI|MSR_DSR|MSR_CTS);
-
-	/*
-	 * sending initial control parameters here
-	 */
-	if (driver->comm->servicetype ==	THREE_WIRE_RAW)
-		return;                /* do nothing */
-
-	driver->comm->dte |= (MCR_DTR | MCR_RTS | DELTA_DTR | DELTA_RTS);
-
-	ircomm_control_request(driver->comm, SERVICETYPE);
-	ircomm_control_request(driver->comm, DATA_RATE);
-	ircomm_control_request(driver->comm, DATA_FORMAT);
-	ircomm_control_request(driver->comm, FLOW_CONTROL);
-	ircomm_control_request(driver->comm, XON_XOFF_CHAR);
-	/* ircomm_control_request(driver->comm, ENQ_ACK_CHAR); */
-
-	switch (driver->comm->servicetype) {
-	case CENTRONICS:
-		break;
-
-	case NINE_WIRE:
-		ircomm_control_request(driver->comm, DTELINE_STATE);
-		break;
-	default:
-	}
-	
-	driver->tx_disable = 0;
-	wake_up_interruptible(&driver->open_wait);
-}
-
-/*
- * Function irvtd_connect_indication (instance, sap, qos, max_sdu_size, skb)
- *
- *    we are discovered and being requested to connect by remote device !
- *
- */
-void irvtd_connect_indication(void *instance, void *sap, struct qos_info *qos,
-			      __u32 max_sdu_size, __u8 max_header_size, 
-			      struct sk_buff *skb)
-{
-	struct irvtd_cb *driver = (struct irvtd_cb *)instance;
-	struct ircomm_cb *comm = (struct ircomm_cb *)sap;
-
-	ASSERT(driver != NULL, return;);
-	ASSERT(driver->magic == IRVTD_MAGIC, return;);
-	ASSERT(comm != NULL, return;);
-	ASSERT(comm->magic == IRCOMM_MAGIC, return;);
-
-	driver->tx_max_sdu_size = max_sdu_size;
-	driver->max_header_size = max_header_size;
-	DEBUG(4, __FUNCTION__ "():sending connect_response...\n");
-
-	ircomm_connect_response(comm, NULL, SAR_DISABLE );
-
-	driver->tx_disable = 0;
-
-	/*
-	 * send initial control parameters
-	 */
-	if (driver->comm->servicetype == THREE_WIRE_RAW)
-		return;                /* do nothing */
-
-	driver->comm->dte |= (MCR_DTR | MCR_RTS | DELTA_DTR | DELTA_RTS);
-
-	switch(driver->comm->servicetype){
-	case NINE_WIRE:
-		ircomm_control_request(driver->comm, DTELINE_STATE);
-		break;
-	default:
-		DEBUG(0, __FUNCTION__ "(), not implemented!\n");
-	}
-
-
-	driver->msr |= (MSR_DCD|MSR_RI|MSR_DSR|MSR_CTS);
-	wake_up_interruptible(&driver->open_wait);
-}
-
-/*
- * Function irvtd_disconnect_indication (instance, sap, reason, skb)
- *
- *    This is a handler for ircomm_disconnect_indication. since this
- *    function is called in the context of interrupt handler,
- *    interruptible_sleep_on() MUST not be used.
- */
-void irvtd_disconnect_indication(void *instance, void *sap , LM_REASON reason,
-				 struct sk_buff *skb)
-{
-	struct irvtd_cb *driver = (struct irvtd_cb *)instance;
-
-	ASSERT(driver != NULL, return;);
-	ASSERT(driver->tty != NULL, return;);
-	ASSERT(driver->magic == IRVTD_MAGIC, return;);
-
-	DEBUG(4,"irvtd_disconnect_indication:\n");
-
-	driver->tx_disable = 1;
-	if(skb_queue_empty(&driver->rxbuff)){
-		/* disconnect */
-		driver->rx_disable = 1;
-		tty_hangup(driver->tty);
-	} else {
-		driver->disconnect_pend = 1;
-	}
-}
-
-/*
- * Function irvtd_control_indication (instance, sap, cmd)
- *
- *    
- *
- */
-void irvtd_control_indication(void *instance, void *sap, IRCOMM_CMD cmd)
-{
-	struct irvtd_cb *driver = (struct irvtd_cb *)instance;
-
-	ASSERT(driver != NULL, return;);
-	ASSERT(driver->magic == IRVTD_MAGIC, return;);
-
-	DEBUG(4,__FUNCTION__"()\n");
-
-	if(cmd == TX_READY){
-		driver->ttp_stoptx = 0;
-		driver->tty->hw_stopped = driver->cts_stoptx;
-
-		if(driver->cts_stoptx)
-			return;
-
-		/* push tx queue so that client can send at least 1 octet */
-		irvtd_send_data_request(driver);
-		/* 
-		 * driver->tty->write_wait will keep asleep if
-		 * our txbuff is full.
-		 * now that we can send packets to IrTTP layer,
-		 * we kick it here.
-		 */
-		if ((driver->tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && 
-		    driver->tty->ldisc.write_wakeup)
-			(driver->tty->ldisc.write_wakeup)(driver->tty);
-		return;
-	}
-
-	if(cmd == TX_BUSY){
-		driver->ttp_stoptx = driver->tty->hw_stopped = 1;
-		del_timer( &driver->tx_timer);
-		return;
-	}
-
-
-	ASSERT(cmd == CONTROL_CHANNEL,return;);
-
-	switch(driver->comm->pi){
-
-	case DCELINE_STATE:
-	driver->msr = driver->comm->peer_dce;
-
-	if(driver->msr & (DELTA_CTS|DELTA_DSR|DELTA_RI|DELTA_DCD)){
-		if(driver->msr & DELTA_CTS)
-			driver->icount.cts++;
-		if(driver->msr & DELTA_DSR)
-			driver->icount.dsr++;
-		if(driver->msr & DELTA_RI)
-			driver->icount.rng++;
-		if(driver->msr & DELTA_DCD)
-			driver->icount.dcd++;
-		wake_up_interruptible(&driver->delta_msr_wait);
-	}
-
-	if ((driver->flags & ASYNC_CHECK_CD) && (driver->msr & DELTA_DCD)) {
-
-		DEBUG(0,"CD now %s...\n",
-		      (driver->msr & MSR_DCD) ? "on" : "off");
-
-		if (driver->msr & MSR_DCD)
-		{
-			/* DCD raised! */
-			wake_up_interruptible(&driver->open_wait);
-		}
-		else
-		{
-			/* DCD falled */
-                        DEBUG(0,__FUNCTION__"():hangup..\n");
-			tty_hangup(driver->tty);
-		}
-
-	}
-
-	if (driver->comm->flow_ctrl & USE_CTS) {
-		if (driver->tty->hw_stopped) {
-			if (driver->msr & MSR_CTS) {
-				DEBUG(0,"CTS tx start...\n");
-
-				driver->cts_stoptx = 0;
-				driver->tty->hw_stopped = driver->ttp_stoptx;
-				/*  
-				 * replacement of 
-				 * rs_sched_event(info, RS_EVENT_WRITE_WAKEUP)
-				 * in serial.c
-				 */
-
-				if ((driver->tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-				    driver->tty->ldisc.write_wakeup)
-					(driver->tty->ldisc.write_wakeup)(driver->tty);
-
-				wake_up_interruptible(&driver->tty->write_wait);
-				return;
-			}
-		} else {
-			if (!(driver->msr & MSR_CTS)) {
-				DEBUG(0,"CTS tx stop...");
-
-				driver->cts_stoptx = 1;
-				driver->tty->hw_stopped = 1;
-                        }
-                }
-        }
-	break;
-
-	case FLOW_CONTROL:
-	case DATA_RATE:
-	case XON_XOFF_CHAR:
-	case DTELINE_STATE:
-	case ENQ_ACK_CHAR:	/* got this from win95 */
-		/* (maybe) nothing to do  */
-		break;
-	default:
-		DEBUG(0,__FUNCTION__"():PI = 0x%02x is not implemented\n",
-		      (int)driver->comm->pi);
-	}
-}
-
-/*
- ***********************************************************************
- *
- * driver kernel interfaces
- * these functions work as an interface between the kernel and this driver
- *
- ***********************************************************************
- */
-
-
-
-/*
- * ----------------------------------------------------------------------
- * irvtd_open() and friends
- *
- * ----------------------------------------------------------------------
- */
-
-
-static int irvtd_block_til_ready(struct tty_struct *tty, struct file * filp,
-				 struct irvtd_cb *driver)
-{
-
- 	struct wait_queue wait = { current, NULL };
-	int		retval = 0;
-	int		do_clocal = 0;
-
-	/*
-	 * If non-blocking mode is set, or the port is not enabled,
-	 * then make the check up front and then exit.
-	 */
-
-	if ((filp->f_flags & O_NONBLOCK) ||
-	    (tty->flags & (1 << TTY_IO_ERROR))) {
-
-		return 0;
-	}
-
-	if (tty->termios->c_cflag & CLOCAL)
-		do_clocal = 1;
-
-
-	/*
-	 * We wait until ircomm_connect_request() succeed or
-	 *   ircomm_connect_indication comes
-	 */
-
-
-	add_wait_queue(&driver->open_wait, &wait);
-
-	DEBUG(0,__FUNCTION__"():before block( line = %d, count = %d )\n",
-	      driver->line, driver->count);
-
-	driver->blocked_open++;
-
-	/* wait for a connection established */
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		
-		if (tty_hung_up_p(filp) ||
-		    !(driver->flags & ASYNC_INITIALIZED)) {
-#ifdef DO_RESTART
-			if (driver->flags & ASYNC_HUP_NOTIFY)
-				retval = -EAGAIN;
-			else
-				retval = -ERESTARTSYS;	
-#else
-			retval = -EAGAIN;
-#endif
-			break;
-		}
-
-		if (!(driver->flags & ASYNC_CLOSING) &&
-		    (driver->comm->state == COMM_CONN) && 
-		    ( do_clocal || (driver->msr & MSR_DCD)))
-			break;
-
-		if(signal_pending(current)){
-			retval = -ERESTARTSYS;
-			break;
-		}
-
-
-		DEBUG(4,__FUNCTION__"():blocking( %s%d, count = %d )\n",
-		      tty->driver.name, driver->line, driver->count);
-
-		schedule();
-	}
-
-	current->state = TASK_RUNNING;
-	remove_wait_queue(&driver->open_wait, &wait);
-
-	driver->blocked_open--;
-
-	DEBUG(1, __FUNCTION__"():after blocking\n");
-
-	if (retval)
-		return retval;
-	return 0;
-}	
-
-static void change_speed(struct irvtd_cb *driver)
-{
-	unsigned cflag,cval;
-
-	if (!driver->tty || !driver->tty->termios || !driver->comm)
-		return;
-	cflag = driver->tty->termios->c_cflag;
-
-	/* 
-	 * byte size and parity
-	 */
-	switch (cflag & CSIZE) 
-	{
-	case CS5: cval = IRCOMM_WLEN5; break;
-	case CS6: cval = IRCOMM_WLEN6; break;
-	case CS7: cval = IRCOMM_WLEN7; break;
-	case CS8: cval = IRCOMM_WLEN8; break;
-	default:  cval = IRCOMM_WLEN5; break;	/* too keep GCC shut... */
-	}
-	if (cflag & CSTOPB) {      /* use 2 stop bit mode */
-		cval |= IRCOMM_STOP2;
-	}
-	if (cflag & PARENB)
-		cval |= IRCOMM_PARENB;    /* enable parity check */
-	if (!(cflag & PARODD))
-		cval |= IRCOMM_PAREVEN;         /* even parity */
-	
-	/* CTS flow control flag and modem status interrupts */
-
-	if (cflag & CRTSCTS)
-		driver->comm->flow_ctrl |= USE_CTS;
-	else
-		driver->comm->flow_ctrl |= ~USE_CTS;
-	
-	if (cflag & CLOCAL)
-		driver->flags &= ~ASYNC_CHECK_CD;
-	else
-		driver->flags |= ASYNC_CHECK_CD;
-	
-	/*
-	 * Set up parity check flag
-	 */
-
-	driver->read_status_mask = LSR_OE;
-	if (I_INPCK(driver->tty))
-		driver->read_status_mask |= LSR_FE | LSR_PE;
-	if (I_BRKINT(driver->tty) || I_PARMRK(driver->tty))
-		driver->read_status_mask |= LSR_BI;
-	
-	/*
-	 * Characters to ignore
-	 */
-	driver->ignore_status_mask = 0;
-	if (I_IGNPAR(driver->tty))
-		driver->ignore_status_mask |= LSR_PE | LSR_FE;
-
-	if (I_IGNBRK(driver->tty)) {
-		driver->ignore_status_mask |= LSR_BI;
-		/*
-		 * If we're ignore parity and break indicators, ignore 
-		 * overruns too.  (For real raw support).
-		 */
-		if (I_IGNPAR(driver->tty)) 
-			driver->ignore_status_mask |= LSR_OE;
-	}
-
-	driver->comm->data_format = cval;
-	ircomm_control_request(driver->comm, DATA_FORMAT);
- 	ircomm_control_request(driver->comm, FLOW_CONTROL);
-}
-
-
-
-
-static int irvtd_startup(struct irvtd_cb *driver)
-{
-	struct ias_object* obj;
-	struct notify_t irvtd_notify;
-
-	/* FIXME: it should not be hard coded */
-	__u8 oct_seq[6] = { 0,1,6,1,1,1 }; 
-
-	DEBUG(4,__FUNCTION__"()\n" );
-	if(driver->flags & ASYNC_INITIALIZED)
-		return 0;
-
-	/*
-	 * initialize our tx/rx buffer
-	 */
-
-	skb_queue_head_init(&driver->rxbuff);
-	driver->txbuff = dev_alloc_skb(COMM_DEFAULT_SDU_SIZE + COMM_MAX_HEADER_SIZE); 
-	if (!driver->txbuff){
-		DEBUG(0,__FUNCTION__"(), alloc_skb failed!\n");
-		return -ENOMEM;
-	}
-	skb_reserve(driver->txbuff, COMM_MAX_HEADER_SIZE);
-
-	irda_notify_init(&irvtd_notify);
-	irvtd_notify.data_indication = irvtd_receive_data;
-	irvtd_notify.connect_confirm = irvtd_connect_confirm;
-	irvtd_notify.connect_indication = irvtd_connect_indication;
-	irvtd_notify.disconnect_indication = irvtd_disconnect_indication;
-	irvtd_notify.flow_indication = irvtd_control_indication;
-	strncpy( irvtd_notify.name, "ircomm_tty", NOTIFY_MAX_NAME);
-	irvtd_notify.instance = driver;
-
-	driver->comm = ircomm_open_instance(irvtd_notify);
-	if (!driver->comm)
-		return -ENODEV;
-
-
-	/* 
-         *  Register with LM-IAS as a server
-         */
-
-	obj = irias_new_object( "IrDA:IrCOMM", IAS_IRCOMM_ID);
-	irias_add_integer_attrib( obj, "IrDA:TinyTP:LsapSel", 
-				  driver->comm->tsap->stsap_sel );
-
-	irias_add_octseq_attrib( obj, "Parameters", &oct_seq[0], 6);
-	irias_insert_object( obj);
-
-	driver->flags |= ASYNC_INITIALIZED;
-
-	if (driver->tty)
-		clear_bit(TTY_IO_ERROR, &driver->tty->flags);
-
-	change_speed(driver);
-
-	/*
-	 * discover a peer device
-	 */
-	if(driver->tty->termios->c_cflag & CRTSCTS)
-	  ircomm_connect_request(driver->comm, NINE_WIRE);
-	else
-	  ircomm_connect_request(driver->comm, THREE_WIRE);
-
-	/* irvtd_start_timer( driver); */
-
-	driver->rx_disable = 0;
-	driver->tx_disable = 1;
-	driver->disconnect_pend = 0;
-	return 0;
-}
-
-
-int irvtd_open(struct tty_struct * tty, struct file * filp)
-{
-	struct irvtd_cb *driver;
-	int retval;
-	int line;
-
-	DEBUG(4, __FUNCTION__"():\n");
-	MOD_INC_USE_COUNT;
-
-	line = MINOR(tty->device) - tty->driver.minor_start;
-	if ((line <0) || (line >= COMM_MAX_TTY)){
-		MOD_DEC_USE_COUNT;
-		return -ENODEV;
-	}
-
-	driver = irvtd[line];
-	ASSERT(driver != NULL, MOD_DEC_USE_COUNT;return -ENOMEM;);
-	ASSERT(driver->magic == IRVTD_MAGIC, MOD_DEC_USE_COUNT;return -EINVAL;);
-
-	driver->count++;
-
-	DEBUG(0, __FUNCTION__"():%s%d count %d\n", tty->driver.name, line, 
-	      driver->count);
-	
-	tty->driver_data = driver;
-	driver->tty = tty;
-
-	driver->tty->low_latency = (driver->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-
-	/*
-	 * If the device is in the middle of being closed, then block
-	 * (sleep) until it's done, then exit.
-	 */
-
-	if (tty_hung_up_p(filp) ||
-	    (driver->flags & ASYNC_CLOSING)) {
-		if (driver->flags & ASYNC_CLOSING)
-			interruptible_sleep_on(&driver->close_wait);
-#ifdef DO_RESTART
-		if (driver->flags & ASYNC_HUP_NOTIFY)
-			return -EAGAIN;
-		else
-			return -ERESTARTSYS;
-#else
-		return -EAGAIN;
-#endif
-	}
-
-	/* 
-	 * start up discovering process and ircomm_layer 
-	 */
-	
-	retval = irvtd_startup(driver);
-	if (retval){
-		DEBUG(0, __FUNCTION__"():irvtd_startup returns %d\n",retval);
-		return retval;
-	}
-
-	retval = irvtd_block_til_ready(tty, filp, driver);
-	if (retval){
-		DEBUG(0,__FUNCTION__
-		      "():returning after block_til_ready (errno = %d)\n", retval);
-                return retval;
-	}
-
-	driver->session = current->session;
-	driver->pgrp = current->pgrp;
-	return 0;
-}
-
-
-
-
-
-/*
- * ----------------------------------------------------------------------
- * irvtd_close() and friends
- *
- * most of this function is stolen from serial.c
- * ----------------------------------------------------------------------
- */
-
-/*
- * Function irvtd_wait_until_sent (tty, timeout)
- *
- *    wait until Tx queue of IrTTP is empty 
- *
- */
-static void irvtd_wait_until_sent(struct tty_struct *tty, int timeout)
-{
-	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
-	unsigned long orig_jiffies;
-
-	ASSERT(driver != NULL, return;);
-	ASSERT(driver->magic == IRVTD_MAGIC, return;);
-	ASSERT(driver->comm != NULL, return;);
-
-	DEBUG(1, __FUNCTION__"():\n");	
-	if(!tty->closing)
-		return;   /* nothing to do */
-	
-	/* 
-	 * at disconnection, we should wait until Tx queue of IrTTP is
-	 * flushed
-	 */
-
- 	ircomm_disconnect_request(driver->comm, NULL, P_NORMAL);
-	orig_jiffies = jiffies;
-
-	while (driver->comm->tsap->disconnect_pend) {
-		DEBUG(1, __FUNCTION__"():wait..\n");
-		current->state = TASK_INTERRUPTIBLE;
-		current->counter = 0;	/* make us low-priority */
-		schedule_timeout(HZ);    /* 1sec */
-		if (signal_pending(current))
-			break;
-		if (timeout && time_after(jiffies, orig_jiffies + timeout))
-			break;
-	}
-	current->state = TASK_RUNNING;
-}
-
-
-static void irvtd_shutdown(struct irvtd_cb * driver)
-{
-	unsigned long	flags;
-
-	if (!(driver->flags & ASYNC_INITIALIZED))
-		return;
-
-	DEBUG(1,__FUNCTION__"()\n");
-
-	/*
-	 * This comment is written in serial.c:
-	 *
-	 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
-	 * here so the queue might never be waken up
-	 */
- 	wake_up_interruptible(&driver->delta_msr_wait);
-	
-	/* clear DTR and RTS */
-	if (!driver->tty || (driver->tty->termios->c_cflag & HUPCL))
- 		driver->mcr &= ~(MCR_DTR|MCR_RTS);
-
-	driver->comm->dte = driver->mcr;
-	ircomm_control_request(driver->comm, DTELINE_STATE );
-
-
-
-	save_flags(flags); cli(); /* Disable interrupts */
-
-	if (driver->tty)
-		set_bit(TTY_IO_ERROR, &driver->tty->flags);
-	
-	del_timer( &driver->tx_timer);
-	del_timer( &driver->rx_timer);
-
-	irias_delete_object("IrDA:IrCOMM");
-
-	/*
-	 * Free the transmit buffer here 
-	 */
-
-	while(skb_queue_len(&driver->rxbuff)){
-		struct sk_buff *skb;
-		skb = skb_dequeue( &driver->rxbuff);
-		dev_kfree_skb(skb);
-	}
-	if(driver->txbuff){
-		dev_kfree_skb(driver->txbuff);
-		driver->txbuff = NULL;
-	}
-	ircomm_close_instance(driver->comm);
-	driver->comm = NULL;
-	driver->flags &= ~ASYNC_INITIALIZED;
-	restore_flags(flags);
-}
-
-void irvtd_close(struct tty_struct * tty, struct file * filp)
-{
-	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
-	int line;
-	unsigned long flags;
-
-	DEBUG(1, __FUNCTION__"():refcount= %d\n",irvtd_refcount);
-
-	ASSERT(driver != NULL, return;);
-	ASSERT(driver->magic == IRVTD_MAGIC, return;);
-
-	save_flags(flags);cli();
-
-
-	if(tty_hung_up_p(filp)){
-		/*
-		 * upper tty layer caught a HUP signal and called irvtd_hangup()
-		 * before. so we do nothing here.
-		 */
-		DEBUG(1, __FUNCTION__"():tty_hung_up_p.\n");
-		MOD_DEC_USE_COUNT;
-		restore_flags(flags);
-		return;
-	}
-	
-
-	line = MINOR(tty->device) - tty->driver.minor_start;
-	DEBUG(0, __FUNCTION__"():%s%d count %d\n", tty->driver.name, line, 
-	      driver->count);
-
-	if ((tty->count == 1) && (driver->count != 1)) {
-		/*
-		 * Uh, oh.  tty->count is 1, which means that the tty
-		 * structure will be freed.  Driver->count should always
-		 * be one in these conditions.  If it's greater than
-		 * one, we've got real problems, since it means the
-		 * ircomm service layer won't be shutdown.
-		 */
-		printk(KERN_ERR"irvtd_close: bad serial port count;" 
-		       "tty->count is 1, but driver->count is %d\n", driver->count);
-		driver->count = 1;
-	}
-	if (--driver->count < 0) {
-		printk(KERN_ERR"irvtd_close: bad count for line%d: %d\n",
-		       line, driver->count);
-		driver->count = 0;
-	}
-
-	if (driver->count) { 	/* do nothing */
-		DEBUG(0, __FUNCTION__"():driver->count is not 0\n");
-		MOD_DEC_USE_COUNT;
-		restore_flags(flags);
-		return; 
-	}
-
-	driver->flags |= ASYNC_CLOSING;
-	
-	/*
-	 * Now we wait for the transmit buffer to clear; and we notify 
-	 * the line discipline to only process XON/XOFF characters.
-	 */
-	tty->closing = 1;
-	if (driver->closing_wait != ASYNC_CLOSING_WAIT_NONE){
-		DEBUG(4, __FUNCTION__"():calling tty_wait_until_sent()\n");
-		tty_wait_until_sent(tty, driver->closing_wait);
-	}
-	/* 
-	 * we can send disconnect_request with P_HIGH since
-	 * tty_wait_until_sent() and irvtd_wait_until_sent() should
-	 * have disconnected the link
-	 */
-	ircomm_disconnect_request(driver->comm, NULL, P_HIGH);
-	
-	/* 
-	 * Now we stop accepting input.
-	 */
-
-	driver->rx_disable = TRUE;
-	/* drop ldisc's buffer */
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
-
- 	if (tty->driver.flush_buffer) 
- 		tty->driver.flush_buffer(driver->tty);  
-
-	tty->closing = 0;
-	driver->tty = NULL;
-
-	if (driver->blocked_open)
-	{
-		if (driver->close_delay) {
-			/* kill time */
-			current->state = TASK_INTERRUPTIBLE;
-			schedule_timeout(driver->close_delay);
-		}
-		wake_up_interruptible(&driver->open_wait);
-	}
-	irvtd_shutdown(driver);
-	driver->flags &= ~ASYNC_CLOSING;
-        wake_up_interruptible(&driver->close_wait); 
-
-	MOD_DEC_USE_COUNT;
-        restore_flags(flags);
-	DEBUG(4, __FUNCTION__"():done\n");
-}
-
-/*
- * ----------------------------------------------------------------------
- * irvtd_write() and friends
- * This routine will be called when something data are passed from
- * kernel or user.
- * ----------------------------------------------------------------------
- */
-
-int irvtd_write(struct tty_struct * tty, int from_user,
-		const unsigned char *buf, int count)
-{
-	struct irvtd_cb *driver;
-	int c = 0;
-	int wrote = 0;
- 	unsigned long flags;
-	struct sk_buff *skb;
-	__u8 *frame;
-
-	ASSERT(tty != NULL, return -EFAULT;);
-	driver = (struct irvtd_cb *)tty->driver_data;
-	ASSERT(driver != NULL, return -EFAULT;);
-	ASSERT(driver->magic == IRVTD_MAGIC, return -EFAULT;);
-
-	DEBUG(4, __FUNCTION__"()\n");
-
-	save_flags(flags);
-	while(count > 0){
-		cli();
-		skb = driver->txbuff;
-		ASSERT(skb != NULL, break;);
-		c = MIN(count, (skb_tailroom(skb)));
-		if (c <= 0)
-		{
-			if(!driver->ttp_stoptx)
-			{
-				irvtd_send_data_request(driver);
-				continue;
-			}
-			else
-				break;
-		}
-
-		/* write to the frame */
-
-		frame = skb_put(skb,c);
-		if(from_user){
-			copy_from_user(frame,buf,c);
-		} else
-			memcpy(frame, buf, c);
-
-		restore_flags(flags);
-		wrote += c;
-		count -= c;
-		buf += c;
-	}
-	restore_flags(flags);
-	irvtd_send_data_request(driver);
-	return (wrote);
-}
-
-void irvtd_flush_chars(struct tty_struct *tty)
-{
-	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
-	ASSERT( driver != NULL, return;);
-	ASSERT( driver->magic == IRVTD_MAGIC, return;);
-
-	DEBUG(4, __FUNCTION__"()\n");
-	irvtd_send_data_request(driver);
-}
-
-
-/*
- * Function irvtd_put_char (tty, ch)
- *
- *    This routine is called by the kernel to pass a single character.
- *    If we exausted our buffer,we can ignore the character!
- *
- */
-void irvtd_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	__u8 *frame ;
-	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
-	struct sk_buff *skb;
-	unsigned long flags;
-
-	ASSERT(driver != NULL, return;);
-	DEBUG(4, __FUNCTION__"()\n");
-
-
- again:
-	save_flags(flags);cli();
-	skb = driver->txbuff;
-	ASSERT(skb != NULL,return;);
-	if(!skb_tailroom(skb))
-	{
-		restore_flags(flags);
-		irvtd_send_data_request(driver);
-		goto again;
-	}
-	ASSERT(skb_tailroom(skb) > 0, return;);
-	DEBUG(4, "irvtd_put_char(0x%02x) skb_len(%d) room(%d):\n",
-	      (int)ch ,(int)skb->len,
-	      skb_tailroom(skb));
-
-	/* append a character  */
-	frame = skb_put(skb,1);
-	frame[0] = ch;
-
-	restore_flags(flags);
-	irvtd_start_tx_timer(driver,20);
-	return;
-}
-
-/*
- * Function irvtd_write_room (tty)
- *
- *    This routine returns the room that our buffer has now.
- *
- */
-int irvtd_write_room(struct tty_struct *tty){
-
-	int ret;
-	struct sk_buff *skb = ((struct irvtd_cb *) tty->driver_data)->txbuff;
-
-	ASSERT(skb !=NULL, return 0;);
-
-	ret = skb_tailroom(skb);
-
-	DEBUG(4, __FUNCTION__"(): room is %d bytes\n",ret);
-
-	return(ret);
-}
-
-/*
- * Function irvtd_chars_in_buffer (tty)
- *
- *    This function returns how many characters which have not been sent yet 
- *    are still in buffer.
- *
- */
-int irvtd_chars_in_buffer(struct tty_struct *tty){
-
-	struct sk_buff *skb;
-	unsigned long flags;
-
-	DEBUG(4, __FUNCTION__"()\n");
-
-	save_flags(flags);cli();
-	skb = ((struct irvtd_cb *) tty->driver_data)->txbuff;
-	if(skb == NULL) goto err;
-
-	restore_flags(flags);
-	return (skb->len );
-err:	
-	ASSERT(skb != NULL, ;);
-	restore_flags(flags);
-	return 0;   /* why not -EFAULT or such? see driver/char/serial.c */
-}
-
-/*
- * Function irvtd_break (tty, break_state)
- *
- *    Routine which turns the break handling on or off
- *
- */
-static void irvtd_break(struct tty_struct *tty, int break_state){
-	
- 	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
-	unsigned long flags;
-
-	DEBUG(0, __FUNCTION__"()\n");
-	ASSERT(tty->driver_data != NULL, return;);
-	ASSERT(driver->magic == IRVTD_MAGIC, return;);
-	
-	save_flags(flags);cli();
-	if (break_state == -1)
-	{
-		driver->comm->break_signal = 0x01;
-		ircomm_control_request(driver->comm, BREAK_SIGNAL);
-
-	}
-	else
-	{
-		driver->comm->break_signal = 0x00;
-		ircomm_control_request(driver->comm, BREAK_SIGNAL);
-
-	}
-
-	restore_flags(flags);
-}
-
-/*
- * ----------------------------------------------------------------------
- * irvtd_ioctl() and friends
- * This routine allows us to implement device-specific ioctl's.
- * If passed ioctl number (i.e.cmd) is unknown one, we should return 
- * ENOIOCTLCMD.
- *
- * TODO: we can't use setserial on IrCOMM because some ioctls are not implemented.
- * we should add some ioctls and make some tool which is resemble to setserial.
- * ----------------------------------------------------------------------
- */
-
-static int get_modem_info(struct irvtd_cb * driver, unsigned int *value)
-{
-	unsigned int result;
-	result =  ((driver->mcr & MCR_RTS) ? TIOCM_RTS : 0)
-		| ((driver->mcr & MCR_DTR) ? TIOCM_DTR : 0)
-		| ((driver->msr & DELTA_DCD) ? TIOCM_CAR : 0)
-		| ((driver->msr & DELTA_RI) ? TIOCM_RNG : 0)
-		| ((driver->msr & DELTA_DSR) ? TIOCM_DSR : 0)
-		| ((driver->msr & DELTA_CTS) ? TIOCM_CTS : 0);
-	return put_user(result,value);
-}
-
-static int set_modem_info(struct irvtd_cb * driver, unsigned int cmd,
-			  unsigned int *value)
-{ 
-	int error;
-	unsigned int arg;
-
-	error = get_user(arg, value);
-	if(error)
-		return error;
-
-	switch (cmd) {
-	case TIOCMBIS: 
-		if (arg & TIOCM_RTS) 
-			driver->mcr |= MCR_RTS;
-		if (arg & TIOCM_DTR)
-			driver->mcr |= MCR_DTR;
-		break;
-		
-	case TIOCMBIC:
-		if (arg & TIOCM_RTS)
-			driver->mcr &= ~MCR_RTS;
-		if (arg & TIOCM_DTR)
- 			driver->mcr &= ~MCR_DTR;
- 		break;
-		
-	case TIOCMSET:
- 		driver->mcr = ((driver->mcr & ~(MCR_RTS | MCR_DTR))
-			       | ((arg & TIOCM_RTS) ? MCR_RTS : 0)
-			       | ((arg & TIOCM_DTR) ? MCR_DTR : 0));
-		break;
-		
-	default:
-		return -EINVAL;
-	}
-	
-	driver->comm->dte = driver->mcr;
-	ircomm_control_request(driver->comm, DTELINE_STATE );
-
-	return 0;
-}
-
-static int get_serial_info(struct irvtd_cb * driver,
-			   struct serial_struct * retinfo)
-{
-	struct serial_struct tmp;
-   
-	if (!retinfo)
-		return -EFAULT;
-	memset(&tmp, 0, sizeof(tmp));
-	tmp.line = driver->line;
-	tmp.flags = driver->flags;
-	tmp.baud_base = driver->comm->data_rate;
-	tmp.close_delay = driver->close_delay;
-	tmp.closing_wait = driver->closing_wait;
-
-	/* for compatibility  */
-
- 	tmp.type = PORT_16550A;
- 	tmp.port = 0;
- 	tmp.irq = 0;
-	tmp.xmit_fifo_size = 0;
-	tmp.hub6 = 0;   
-	tmp.custom_divisor = driver->custom_divisor;
-
-	if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
-		return -EFAULT;
-	return 0;
-}
-
-static int set_serial_info(struct irvtd_cb * driver,
-			   struct serial_struct * new_info)
-{
-	struct serial_struct new_serial;
-	struct irvtd_cb old_driver;
-
-	if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
-		return -EFAULT;
-
-	old_driver = *driver;
-  
-	if (!capable(CAP_SYS_ADMIN)) {
-		if ((new_serial.baud_base != driver->comm->data_rate) ||
-		    (new_serial.close_delay != driver->close_delay) ||
-		    ((new_serial.flags & ~ASYNC_USR_MASK) !=
-		     (driver->flags & ~ASYNC_USR_MASK)))
-			return -EPERM;
-		driver->flags = ((driver->flags & ~ASYNC_USR_MASK) |
-				 (new_serial.flags & ASYNC_USR_MASK));
-		driver->custom_divisor = new_serial.custom_divisor;
-		goto check_and_exit;
-	}
-
-	/*
-	 * OK, past this point, all the error checking has been done.
-	 * At this point, we start making changes.....
-	 */
-
-	if(driver->comm->data_rate != new_serial.baud_base){
-		driver->comm->data_rate = new_serial.baud_base;
-		if(driver->comm->state == COMM_CONN)
-			ircomm_control_request(driver->comm,DATA_RATE);
-	}
-	driver->close_delay = new_serial.close_delay * HZ/100;
-	driver->closing_wait = new_serial.closing_wait * HZ/100;
-	driver->custom_divisor = new_serial.custom_divisor;
-
-	driver->flags = ((driver->flags & ~ASYNC_FLAGS) |
-			 (new_serial.flags & ASYNC_FLAGS));
-	driver->tty->low_latency = (driver->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-
- check_and_exit:
-	if (driver->flags & ASYNC_INITIALIZED) {
-		if (((old_driver.flags & ASYNC_SPD_MASK) !=
-		     (driver->flags & ASYNC_SPD_MASK)) ||
-		    (old_driver.custom_divisor != driver->custom_divisor)) {
-			if ((driver->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-				driver->tty->alt_speed = 57600;
-			if ((driver->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-				driver->tty->alt_speed = 115200;
-			if ((driver->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-				driver->tty->alt_speed = 230400;
-			if ((driver->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-				driver->tty->alt_speed = 460800;
-			change_speed(driver);
-		}
-	}
-	return 0;
-}
-
-
-
-
-int irvtd_ioctl(struct tty_struct *tty, struct file * file,
-		unsigned int cmd, unsigned long arg)
-{
-	int error;
-	unsigned long flags;
- 	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
-
-	struct serial_icounter_struct cnow,cprev;
-	struct serial_icounter_struct *p_cuser;	/* user space */
-
-
-	DEBUG(4,"irvtd_ioctl:requested ioctl(0x%08x)\n",cmd);
-
-#ifdef IRVTD_DEBUG_IOCTL
-	{
-		/* kill time so that debug messages will come slowly  */
-		save_flags(flags);cli();
-		current->state = TASK_INTERRUPTIBLE;
-		current->timeout = jiffies + HZ/4; /*0.25sec*/
-		schedule();
-		restore_flags(flags);
-	}
-#endif
-
-
-
-	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
-	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
-		if (tty->flags & (1 << TTY_IO_ERROR)){
-			return -EIO;
-		}
-	}
-	
-	switch (cmd) {
-
-	case TIOCMGET:
-		return get_modem_info(driver, (unsigned int *) arg);
-
-	case TIOCMBIS:
-	case TIOCMBIC:
-	case TIOCMSET:
-		return set_modem_info(driver, cmd, (unsigned int *) arg);
-	case TIOCGSERIAL:
-		return get_serial_info(driver, (struct serial_struct *) arg);
-	case TIOCSSERIAL:
-		return set_serial_info(driver, (struct serial_struct *) arg);
-
-
-	case TIOCMIWAIT:
-		save_flags(flags); cli();
-		/* note the counters on entry */
-		cprev = driver->icount;
-		restore_flags(flags);
-		while (1) {
-			interruptible_sleep_on(&driver->delta_msr_wait);
-				/* see if a signal did it */
-			if (signal_pending(current))
-				return -ERESTARTSYS;
-			save_flags(flags); cli();
-			cnow = driver->icount; /* atomic copy */
-			restore_flags(flags);
-			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && 
-			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
-				return -EIO; /* no change => error */
-			if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-			     ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-			     ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
-			     ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
-				return 0;
-			}
-			cprev = cnow;
-		}
-		/* NOTREACHED */
-
-	case TIOCGICOUNT:
-		save_flags(flags); cli();
-		cnow = driver->icount;
-		restore_flags(flags);
-		p_cuser = (struct serial_icounter_struct *) arg;
-		error = put_user(cnow.cts, &p_cuser->cts);
-		if (error) return error;
-		error = put_user(cnow.dsr, &p_cuser->dsr);
-		if (error) return error;
-		error = put_user(cnow.rng, &p_cuser->rng);
-		if (error) return error;
-		error = put_user(cnow.dcd, &p_cuser->dcd);
-		if (error) return error;
-		error = put_user(cnow.rx, &p_cuser->rx);
-		if (error) return error;
-		error = put_user(cnow.tx, &p_cuser->tx);
-		if (error) return error;
-		error = put_user(cnow.frame, &p_cuser->frame);
-		if (error) return error;
-		error = put_user(cnow.overrun, &p_cuser->overrun);
-		if (error) return error;
-		error = put_user(cnow.parity, &p_cuser->parity);
-		if (error) return error;
-		error = put_user(cnow.brk, &p_cuser->brk);
-		if (error) return error;
-		error = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
-		if (error) return error;			
-		return 0;
-		
-		
-		/* ioctls which are imcompatible with serial.c */
-
-	case TIOCSERGSTRUCT:
-		DEBUG(0,__FUNCTION__"():sorry, TIOCSERGSTRUCT is not supported\n");
-		return -ENOIOCTLCMD;  
-	case TIOCSERGETLSR:
-		DEBUG(0,__FUNCTION__"():sorry, TIOCSERGETLSR is not supported\n");
-		return -ENOIOCTLCMD;  
- 	case TIOCSERCONFIG:
-		DEBUG(0,__FUNCTION__"():sorry, TIOCSERCONFIG is not supported\n");
-		return -ENOIOCTLCMD;  
-
-
-	default:
-		return -ENOIOCTLCMD;  /* ioctls which we must ignore */
-	}
-	return 0;
-}
-
-
-
-/*
- * ----------------------------------------------------------------------
- * irvtd_set_termios()
- * This is called when termios is changed.
- * If things that changed is significant for us,(i.e. changing baud rate etc.)
- * send something to peer device.
- * ----------------------------------------------------------------------
- */
-
-void irvtd_set_termios(struct tty_struct *tty, struct termios * old_termios){
-
-	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
-
-	ASSERT(driver != NULL,return;);
-	ASSERT(driver->magic == IRVTD_MAGIC ,return;);
-
-	DEBUG(0, "irvtd_set_termios:\n");
-	return;
-
-	if((tty->termios->c_cflag == old_termios->c_cflag) &&
-	   (RELEVANT_IFLAG(tty->termios->c_iflag) 
-	    == RELEVANT_IFLAG(old_termios->c_iflag)))
-		return;
-
-	change_speed(driver);
-
-	if((old_termios->c_cflag & CRTSCTS) &&
-	   !(tty->termios->c_cflag & CRTSCTS)) {
-		tty->hw_stopped = driver->ttp_stoptx;
-		/* irvtd_start(tty); */       /* we don't need this */
-	}
-}
-
-/*
- * ----------------------------------------------------------------------
- * irvtd_throttle,irvtd_unthrottle
- *   These routines will be called when we have to pause sending up data to tty.
- *   We use RTS virtual signal when servicetype is NINE_WIRE
- * ----------------------------------------------------------------------
- */
-
-static void irvtd_send_xchar(struct tty_struct *tty, char ch){
-
-	DEBUG(1, __FUNCTION__"():\n");
-	irvtd_put_char(tty, ch);
-}
-
-void irvtd_throttle(struct tty_struct *tty){
-	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
-
-	DEBUG(1, "irvtd_throttle:\n");
-
-	if (I_IXOFF(tty))
-		irvtd_put_char(tty, STOP_CHAR(tty));
-
-	driver->mcr &= ~MCR_RTS; 
-	driver->mcr |= DELTA_RTS; 
-	driver->comm->dte = driver->mcr;
-	ircomm_control_request(driver->comm, DTELINE_STATE );
-
-	DEBUG(1, __FUNCTION__"():FLOW_STOP\n");
-        irttp_flow_request(driver->comm->tsap, FLOW_STOP);
-}
-
-void irvtd_unthrottle(struct tty_struct *tty){
-	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
-	DEBUG(1, "irvtd_unthrottle:\n");
-
-	if (I_IXOFF(tty))
-		irvtd_put_char(tty, START_CHAR(tty));
-
-	driver->mcr |= (MCR_RTS|DELTA_RTS);
-	driver->comm->dte = driver->mcr;
-	ircomm_control_request(driver->comm, DTELINE_STATE );
-
-	DEBUG(1, __FUNCTION__"():FLOW_START\n");
-        irttp_flow_request(driver->comm->tsap, FLOW_START);
-}
-
-
-/*
- * ------------------------------------------------------------
- * irvtd_stop() and irvtd_start()
- *
- * This routines are called before setting or resetting tty->stopped.
- * They enable or disable an interrupt which means "transmitter-is-ready"
- * in serial.c, but  I think these routine are not necessary for us. 
- * ------------------------------------------------------------
- */
-
-#if 0
-irvtd_stop(struct tty_struct *tty){
- 	DEBUG(0, "irvtd_stop()\n");
-
-	struct irvtd_cb *info = (struct irvtd_cb *)tty->driver_data; 
-	DEBUG(0, "irvtd_start():not implemented!\n");
-}
-irvtd_start(struct tty_struct *tty){
-
-	struct irvtd_cb *info = (struct irvtd_cb *)tty->driver_data;
-	DEBUG(0, "irvtd_start():not_implemented!\n");
-}
-#endif
-
-/*
- * ------------------------------------------------------------
- * irvtd_hangup()
- * This routine notifies that tty layer have got HUP signal
- * ------------------------------------------------------------
- */
-
-void irvtd_hangup(struct tty_struct *tty){
-
-	struct irvtd_cb *info = (struct irvtd_cb *)tty->driver_data;
-	DEBUG(0, __FUNCTION__"()\n");
-
-	irvtd_flush_buffer(tty);
-	irvtd_shutdown(info);
-	info->count = 0;
-	info->tty = NULL;
-	wake_up_interruptible(&info->open_wait);
-}
-
-void irvtd_flush_buffer(struct tty_struct *tty){
-
-	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
-	struct sk_buff *skb;
-
-	skb = driver->txbuff;
-	ASSERT(skb != NULL, return;); 
-
-	if(skb->len){
-		DEBUG(0, __FUNCTION__"():%d chars in txbuff are lost..\n",(int)skb->len);
-		skb_trim(skb,0); 
-	}
-	
-	/* write_wait is a wait queue of tty_wait_until_sent().
-	 * see tty_io.c of kernel 
-	 */
-	wake_up_interruptible(&tty->write_wait); 
-
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
-}
-
-
-
-/*
- * Function ircomm_register_device(void), init_module() and friends
- *
- *   we register "port emulation entity"(see IrCOMM specification) here
- *   as a tty device.
- */
-
-int irvtd_register_ttydriver(void){
-
-        DEBUG( 4, "-->irvtd_register_ttydriver\n");
-
-	/* setup virtual serial port device */
-
-        /* Initialize the tty_driver structure ,which is defined in 
-	   tty_driver.h */
-        
-        memset(&irvtd_drv, 0, sizeof(struct tty_driver));
-	irvtd_drv.magic = IRVTD_MAGIC;
-	irvtd_drv.driver_name = "IrCOMM_tty";
-	irvtd_drv.name = "irnine";
-	irvtd_drv.major = IRCOMM_MAJOR;
-	irvtd_drv.minor_start = IRVTD_MINOR;
-	irvtd_drv.num = COMM_MAX_TTY;
-	irvtd_drv.type = TTY_DRIVER_TYPE_SERIAL;  /* see tty_driver.h */
-
-
-	/*
-	 * see drivers/char/tty_io.c and termios(3)
-	 */
-
-        irvtd_drv.init_termios = tty_std_termios;
-        irvtd_drv.init_termios.c_cflag =
-		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-        irvtd_drv.flags = TTY_DRIVER_REAL_RAW;   /* see tty_driver.h */
-        irvtd_drv.refcount = &irvtd_refcount;
-
-	/* pointer to the tty data structures */
-
-        irvtd_drv.table = irvtd_table;  
-        irvtd_drv.termios = irvtd_termios;
-        irvtd_drv.termios_locked = irvtd_termios_locked;
-
-        /*
-         * Interface table from the kernel(tty driver) to the ircomm
-         * layer
-         */
-
-        irvtd_drv.open = irvtd_open;
-        irvtd_drv.close = irvtd_close;
-        irvtd_drv.write = irvtd_write;
-        irvtd_drv.put_char = irvtd_put_char;
-	irvtd_drv.flush_chars = irvtd_flush_chars;
-        irvtd_drv.write_room = irvtd_write_room;
-	irvtd_drv.chars_in_buffer = irvtd_chars_in_buffer; 
-        irvtd_drv.flush_buffer = irvtd_flush_buffer;
- 	irvtd_drv.ioctl = irvtd_ioctl; 
-	irvtd_drv.throttle = irvtd_throttle;
-	irvtd_drv.unthrottle = irvtd_unthrottle;
- 	irvtd_drv.set_termios = irvtd_set_termios;
-	irvtd_drv.stop = NULL;          /*  irvtd_stop; */
-	irvtd_drv.start = NULL;         /* irvtd_start; */
-        irvtd_drv.hangup = irvtd_hangup;
-
-        irvtd_drv.send_xchar = irvtd_send_xchar;
-	irvtd_drv.break_ctl = irvtd_break;
-	irvtd_drv.read_proc = irvtd_read_proc;
- 	irvtd_drv.wait_until_sent = irvtd_wait_until_sent;
-
-
-
-	if (tty_register_driver(&irvtd_drv)){
-		DEBUG(0,"IrCOMM:Couldn't register tty driver\n");
-		return(1);
-	}
-
-	DEBUG( 4, "irvtd_register_ttydriver: done.\n");
-	return(0);
-}
-
-
-/*
- * Function irvtd_unregister_device(void) 
- *   it will be called when you rmmod
- */
-
-void irvtd_unregister_ttydriver(void){
-
-	int err;	
-        DEBUG( 4, "--> irvtd_unregister_device\n");
-
-	/* unregister tty device   */
-
-	err = tty_unregister_driver(&irvtd_drv);
-        if (err)
-                printk("IrCOMM: failed to unregister vtd driver(%d)\n",err);
-        DEBUG( 4, "irvtd_unregister_device -->\n");
-	return;
-}
-
-/*
- **********************************************************************
- *    proc stuff
- *
- **********************************************************************
- */
-
-static int line_info(char *buf, struct irvtd_cb *driver)
-{
-	int	ret=0;
-
-	ASSERT(driver != NULL,goto exit;);
-	ASSERT(driver->magic == IRVTD_MAGIC,goto exit;);
-
-	ret += sprintf(buf, "tx: %d rx: %d"
-		      ,driver->icount.tx, driver->icount.rx);
-
-	if (driver->icount.frame)
-                ret += sprintf(buf+ret, " fe:%d", driver->icount.frame);
-        if (driver->icount.parity)
-                ret += sprintf(buf+ret, " pe:%d", driver->icount.parity);
-        if (driver->icount.brk)
-                ret += sprintf(buf+ret, " brk:%d", driver->icount.brk);  
-        if (driver->icount.overrun)
-                ret += sprintf(buf+ret, " oe:%d", driver->icount.overrun);
-
-	if (driver->mcr & MCR_RTS)
-                ret += sprintf(buf+ret, "|RTS");
-        if (driver->msr & MSR_CTS)
-                ret += sprintf(buf+ret, "|CTS");
-        if (driver->mcr & MCR_DTR)
-                ret += sprintf(buf+ret, "|DTR");
-        if (driver->msr & MSR_DSR)
-                ret += sprintf(buf+ret, "|DSR");
-        if (driver->msr & MSR_DCD)
-                ret += sprintf(buf+ret, "|CD");
-	if (driver->msr & MSR_RI) 
-		ret += sprintf(buf+ret, "|RI");
-
-	ret += sprintf(buf+ret, "\n");
-	ret += sprintf(buf+ret, "rx queue:%d",
-		       skb_queue_len( &driver->rxbuff));
-	ret += sprintf(buf+ret, "ttp_stoprx:%s",
-		       driver->ttp_stoprx?"TRUE":"FALSE");
-
- exit:
-	ret += sprintf(buf+ret, "\n");
-	return ret;
-}
-
-
-
-static int irvtd_read_proc(char *buf, char **start, off_t offset, int len,
-		 int *eof, void *unused)
-{
-	int i, count = 0, l;
-	off_t	begin = 0;
-
-	count += sprintf(buf, "driver revision:%s\n", revision_date);
-	for (i = 0; i < COMM_MAX_TTY && count < 4000; i++) {
-		l = line_info(buf + count, irvtd[i]);
-		count += l;
-		if (count+begin > offset+len)
-			goto done;
-		if (count+begin < offset) {
-			begin += count;
-			count = 0;
-		}
-	}
-	*eof = 1;
-done:
-	if (offset >= count+begin)
-		return 0;
-	*start = buf + (begin-offset);
-	return ((len < begin+count-offset) ? len : begin+count-offset);
-}
-
-
-
-
-/************************************************************
- *    init & cleanup this module 
- ************************************************************/
-
-__initfunc(int irvtd_init(void))
-{
-	int i;
-
-	DEBUG( 4, __FUNCTION__"()\n");
-	printk( KERN_INFO 
-		"ircomm_tty: virtual tty driver for IrCOMM ( revision:%s )\n",
-		revision_date);
-
-
-	/* allocate a master array */
-
-	irvtd = (struct irvtd_cb **) kmalloc( sizeof(void *) *
-						COMM_MAX_TTY,GFP_KERNEL);
-	if ( irvtd == NULL) {
-		printk( KERN_WARNING __FUNCTION__"(): kmalloc failed!\n");
-		return -ENOMEM;
-	}
-
-	memset( irvtd, 0, sizeof(void *) * COMM_MAX_TTY);
-
-	for (i=0; i < COMM_MAX_TTY; i++){
-		irvtd[i] = kmalloc( sizeof(struct irvtd_cb), GFP_KERNEL);	
-		if(irvtd[i] == NULL){
-			printk(KERN_ERR __FUNCTION__"(): kmalloc failed!\n");
-			return -ENOMEM;
-		}
-		memset( irvtd[i], 0, sizeof(struct irvtd_cb));
-		irvtd[i]->magic = IRVTD_MAGIC;
-		irvtd[i]->line = i;
-		irvtd[i]->closing_wait = 10*HZ ;
-		irvtd[i]->close_delay = 5*HZ/10 ; 
-	}
-
-	/* 
-	 * initialize a "port emulation entity"
-	 */
-
-	if(irvtd_register_ttydriver()){
-		printk( KERN_WARNING "IrCOMM: Error in ircomm_register_device\n");
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-void irvtd_cleanup(void)
-{
-	int i;
-	DEBUG( 4, __FUNCTION__"()\n");
-
-	/*
-	 * free some resources
-	 */
-	if (irvtd) {
-		for (i=0; i<COMM_MAX_TTY; i++) {
-			if (irvtd[i]) {
-				if(irvtd[i]->comm)
-					ircomm_close_instance(irvtd[i]->comm);
-				if(irvtd[i]->txbuff)
-					dev_kfree_skb(irvtd[i]->txbuff);
-				DEBUG( 4, "freeing structures\n");
-				kfree(irvtd[i]);
-				irvtd[i] = NULL;
-			}
-		}
-		DEBUG( 4, "freeing master array\n");
-		kfree(irvtd);
-		irvtd = NULL;
-	}
-
- 	irvtd_unregister_ttydriver();
-
-}
-
-#ifdef MODULE
-
-int init_module(void) 
-{
-	irvtd_init();
-	return 0;
-}
-
-/*
- * Function ircomm_cleanup (void)
- *   This is called when you rmmod.
- */
-
-void cleanup_module(void)
-{
-	irvtd_cleanup();
-}
-
-#endif /* MODULE */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irda_device.c linux.15p9/net/irda/irda_device.c
--- linux.vanilla/net/irda/irda_device.c	Tue Jan  4 21:19:03 2000
+++ linux.15p9/net/irda/irda_device.c	Thu Jan 27 00:13:22 2000
@@ -1,28 +1,35 @@
 /*********************************************************************
  *                
  * Filename:      irda_device.c
- * Version:       0.5
- * Description:   Abstract device driver layer and helper functions
+ * Version:       0.9
+ * Description:   Utility functions used by the device drivers
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Wed Sep  2 20:22:08 1998
- * Modified at:   Tue Jun  1 09:05:13 1999
+ * Created at:    Sat Oct  9 09:22:27 1999
+ * Modified at:   Sun Jan 23 09:16:36 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
- *      
+ *     Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
+ *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
- *  
- *     Neither Dag Brattli nor University of Tromsř admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
  *     
  ********************************************************************/
 
 #include <linux/config.h>
+#include <linux/string.h>
 #include <linux/proc_fs.h>
 #include <linux/skbuff.h>
 #include <linux/if.h>
@@ -33,59 +40,74 @@
 #include <linux/tty.h>
 #include <linux/kmod.h>
 #include <linux/wireless.h>
+#include <asm/spinlock.h>
 
 #include <asm/ioctls.h>
 #include <asm/segment.h>
 #include <asm/uaccess.h>
 #include <asm/dma.h>
-#include <asm/spinlock.h>
 
 #include <net/pkt_sched.h>
 
 #include <net/irda/irda_device.h>
-#include <net/irda/irlap_frame.h>
+#include <net/irda/irlap.h>
 #include <net/irda/timer.h>
 #include <net/irda/wrapper.h>
 
 extern int irtty_init(void);
-extern int pc87108_init(void);
+extern int nsc_ircc_init(void);
+extern int ircc_init(void);
 extern int w83977af_init(void);
 extern int esi_init(void);
 extern int tekram_init(void);
 extern int actisys_init(void);
 extern int girbil_init(void);
 
-static hashbin_t *irda_device = NULL;
+static void __irda_task_delete(struct irda_task *task);
+
 static hashbin_t *dongles = NULL;
+static hashbin_t *tasks = NULL;
+
+const char *infrared_mode[] = {
+	"IRDA_IRLAP",
+	"IRDA_RAW",
+	"SHARP_ASK",
+	"TV_REMOTE",
+};
+
+static const char *task_state[] = {
+	"IRDA_TASK_INIT",
+	"IRDA_TASK_DONE", 
+	"IRDA_TASK_WAIT",
+	"IRDA_TASK_WAIT1",
+	"IRDA_TASK_WAIT2",
+	"IRDA_TASK_WAIT3",
+	"IRDA_TASK_CHILD_INIT",
+	"IRDA_TASK_CHILD_WAIT",
+	"IRDA_TASK_CHILD_DONE",
+};
+
+static void irda_task_timer_expired(void *data);
 
-/* Netdevice functions */
-static int irda_device_net_rebuild_header(struct sk_buff *skb);
-static int irda_device_net_hard_header(struct sk_buff *skb, 
-				       struct device *dev,
-				       unsigned short type, void *daddr, 
-				       void *saddr, unsigned len);
-static int irda_device_net_set_config(struct device *dev, struct ifmap *map);
-static int irda_device_net_change_mtu(struct device *dev, int new_mtu);
-static int irda_device_net_ioctl(struct device *dev, struct ifreq *rq,int cmd);
 #ifdef CONFIG_PROC_FS
-int irda_device_proc_read( char *buf, char **start, off_t offset, int len, 
-			   int unused);
+int irda_device_proc_read(char *buf, char **start, off_t offset, int len, 
+			  int unused);
 
 #endif /* CONFIG_PROC_FS */
 
-__initfunc(int irda_device_init( void))
+int __init irda_device_init( void)
 {
-	/* Allocate master array */
-	irda_device = hashbin_new( HB_LOCAL);
-	if (irda_device == NULL) {
-		WARNING("IrDA: Can't allocate irda_device hashbin!\n");
+	dongles = hashbin_new(HB_GLOBAL);
+	if (dongles == NULL) {
+		printk(KERN_WARNING 
+		       "IrDA: Can't allocate dongles hashbin!\n");
 		return -ENOMEM;
 	}
 
-	dongles = hashbin_new(HB_LOCAL);
-	if (dongles == NULL) {
+	tasks = hashbin_new(HB_GLOBAL);
+	if (tasks == NULL) {
 		printk(KERN_WARNING 
-		       "IrDA: Can't allocate dongles hashbin!\n");
+		       "IrDA: Can't allocate tasks hashbin!\n");
 		return -ENOMEM;
 	}
 
@@ -100,7 +122,7 @@
 	w83977af_init();
 #endif
 #ifdef CONFIG_NSC_FIR
-	pc87108_init();
+	nsc_ircc_init();
 #endif
 #ifdef CONFIG_TOSHIBA_FIR
 	toshoboe_init();
@@ -123,289 +145,263 @@
 #ifdef CONFIG_LITELINK_DONGLE
 	litelink_init();
 #endif
-
+#ifdef CONFIG_OLD_BELKIN
+ 	old_belkin_init();
+#endif
 	return 0;
 }
 
 void irda_device_cleanup(void)
 {
-	DEBUG(4, __FUNCTION__ "()\n");
-
-	ASSERT(irda_device != NULL, return;);
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
+	hashbin_delete(tasks, (FREE_FUNC) __irda_task_delete);
 	hashbin_delete(dongles, NULL);
-	hashbin_delete(irda_device, (FREE_FUNC) irda_device_close);
 }
 
 /*
- * Function irda_device_open (self)
- *
- *    Open a new IrDA port device
+ * Function irda_device_set_media_busy (self, status)
  *
+ *    Called when we have detected that another station is transmiting
+ *    in contention mode.
  */
-int irda_device_open(struct irda_device *self, char *name, void *priv)
-{        
-	int result;
-	int i=0;
+void irda_device_set_media_busy(struct device *dev, int status) 
+{
+	struct irlap_cb *self;
 
-	/* Allocate memory if needed */
-	if (self->rx_buff.truesize > 0) {
-		self->rx_buff.head = ( __u8 *) kmalloc(self->rx_buff.truesize,
-						       self->rx_buff.flags);
-		if (self->rx_buff.head == NULL)
-			return -ENOMEM;
+	IRDA_DEBUG(4, __FUNCTION__ "(%s)\n", status ? "TRUE" : "FALSE");
 
-		memset(self->rx_buff.head, 0, self->rx_buff.truesize);
-	}
-	if (self->tx_buff.truesize > 0) {
-		self->tx_buff.head = ( __u8 *) kmalloc(self->tx_buff.truesize, 
-						       self->tx_buff.flags);
-		if (self->tx_buff.head == NULL)
-			return -ENOMEM;
+	self = (struct irlap_cb *) dev->atalk_ptr;
 
-		memset(self->tx_buff.head, 0, self->tx_buff.truesize);
-	}
-	
-      	self->magic = IRDA_DEVICE_MAGIC;
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
 
-	self->rx_buff.in_frame = FALSE;
-	self->rx_buff.state = OUTSIDE_FRAME;
-	self->tx_buff.data = self->tx_buff.head;
-	self->rx_buff.data = self->rx_buff.head;
+	if (status) {
+		self->media_busy = TRUE;
+		irlap_start_mbusy_timer(self);
+		IRDA_DEBUG( 4, "Media busy!\n");
+	} else {
+		self->media_busy = FALSE;
+		del_timer(&self->media_busy_timer);
+	}
+}
 
-	/* Initialize timers */
-	init_timer(&self->media_busy_timer);	
+int irda_device_set_dtr_rts(struct device *dev, int dtr, int rts)
+{	
+	struct if_irda_req req;
+	int ret;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	if (!dev->do_ioctl) {
+		ERROR(__FUNCTION__ "(), do_ioctl not impl. by "
+		      "device driver\n");
+		return -1;
+	}
 
-	self->lock = SPIN_LOCK_UNLOCKED;
+	req.ifr_dtr = dtr;
+	req.ifr_rts = rts;
 
-	/* A pointer to the low level implementation */
-	self->priv = priv;
+	ret = dev->do_ioctl(dev, (struct ifreq *) &req, SIOCSDTRRTS);
 
-	/* Initialize IrDA net device */
-	do {
-		sprintf(self->name, "%s%d", "irda", i++);
-	} while (dev_get(self->name) != NULL);
-	
-	self->netdev.name = self->name;
-	self->netdev.priv = (void *) self;
-	self->netdev.next = NULL;
+	return ret;
+}
 
-	if ((result = register_netdev(&self->netdev)) != 0) {
-		DEBUG(0, __FUNCTION__ "(), register_netdev() failed!\n");
+int irda_device_change_speed(struct device *dev, __u32 speed)
+{	
+	struct if_irda_req req;
+	int ret;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	if (!dev->do_ioctl) {
+		ERROR(__FUNCTION__ "(), do_ioctl not impl. by "
+		      "device driver\n");
 		return -1;
 	}
-	
-	/* 
-	 * Make the description for the device. self->netdev.name will get
-	 * a name like "irda0" and the self->descriptin will get a name
-	 * like "irda0 <-> irtty0" 
-	 */
-	strncpy(self->description, self->name, 5);
-	strcat(self->description, " <-> ");
-	strncat(self->description, name, 23);
-	
-	hashbin_insert(irda_device, (QUEUE *) self, (int) self, NULL);
-	
-	/* Open network device */
-	dev_open(&self->netdev);
 
-	MESSAGE("IrDA: Registered device %s\n", self->name);
+	req.ifr_baudrate = speed;
 
-	irda_device_set_media_busy(self, FALSE);
+	ret = dev->do_ioctl(dev, (struct ifreq *) &req, SIOCSBANDWIDTH);
 
-	/* 
-	 * Open new IrLAP layer instance, now that everything should be
-	 * initialized properly 
-	 */
-	self->irlap = irlap_open(self);
-        
-	/* It's now safe to initilize the saddr */
-	memcpy(self->netdev.dev_addr, &self->irlap->saddr, 4);
-
-	return 0;
+	return ret;
 }
 
 /*
- * Function irda_device_close (self)
+ * Function irda_device_is_receiving (dev)
  *
- *    Close this instance of the irda_device, just deallocate buffers
+ *    Check if the device driver is currently receiving data
  *
  */
-void __irda_device_close(struct irda_device *self)
+int irda_device_is_receiving(struct device *dev)
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	struct if_irda_req req;
+	int ret;
 
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;);
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
-	/* We do this test to know if the device has been registered at all */
-	if (self->netdev.type == ARPHRD_IRDA) {
-		dev_close(&self->netdev);
-		
-		/* Remove netdevice */
-		unregister_netdev(&self->netdev);
+	if (!dev->do_ioctl) {
+		ERROR(__FUNCTION__ "(), do_ioctl not impl. by "
+		      "device driver\n");
+		return -1;
 	}
 
-	/* Stop timers */
-	del_timer(&self->media_busy_timer);
-
-	if (self->tx_buff.head)
-		kfree(self->tx_buff.head);
+	ret = dev->do_ioctl(dev, (struct ifreq *) &req, SIOCGRECEIVING);
+	if (ret < 0)
+		return ret;
 
-	if (self->rx_buff.head)
-		kfree(self->rx_buff.head);
-
-	self->magic = 0;
+	return req.ifr_receiving;
 }
 
-/*
- * Function irda_device_close (self)
- *
- *    Close the device
- *
- */
-void irda_device_close(struct irda_device *self)
+void irda_task_next_state(struct irda_task *task, TASK_STATE state)
 {
-	DEBUG(4, __FUNCTION__ "()\n");
-
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;);
+	IRDA_DEBUG(2, __FUNCTION__ "(), state = %s\n", task_state[state]);
 
-	/* We are not using any dongle anymore! */
-	if (self->dongle)
-		self->dongle->close(self);
-
-	/* Stop and remove instance of IrLAP */
-	if (self->irlap)
-		irlap_close(self->irlap);
-	self->irlap = NULL;
-
-	hashbin_remove(irda_device, (int) self, NULL);
-
-	__irda_device_close(self);
+	task->state = state;
 }
 
-/*
- * Function irda_device_set_media_busy (self, status)
- *
- *    Called when we have detected that another station is transmiting
- *    in contention mode.
- */
-void irda_device_set_media_busy(struct irda_device *self, int status) 
+static void __irda_task_delete(struct irda_task *task)
 {
-	DEBUG(4, __FUNCTION__ "(%s)\n", status ? "TRUE" : "FALSE");
+	del_timer(&task->timer);
+	
+	kfree(task);
+}
 
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;);
+void irda_task_delete(struct irda_task *task)
+{
+	/* Unregister task */
+	hashbin_remove(tasks, (int) task, NULL);
 
-	if (status) {
-		self->media_busy = TRUE;
-		irda_device_start_mbusy_timer(self);
-		DEBUG( 4, "Media busy!\n");
-	} else {
-		self->media_busy = FALSE;
-		del_timer(&self->media_busy_timer);
-	}
+	__irda_task_delete(task);
 }
 
 /*
- * Function __irda_device_change_speed (self, speed)
+ * Function irda_task_kick (task)
  *
- *    When this function is called, we will have a process context so its
- *    possible for us to sleep, wait or whatever :-)
+ *    Tries to execute a task possible multiple times until the task is either
+ *    finished, or askes for a timeout. When a task is finished, we do post
+ *    processing, and notify the parent task, that is waiting for this task
+ *    to complete.
  */
-static void __irda_device_change_speed(struct irda_device *self, int speed)
+int irda_task_kick(struct irda_task *task)
 {
-	int n = 0;
+	int finished = TRUE;
+	int count = 0;
+	int timeout;
 
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;);
-	
-	/*
-	 *  Is is possible to change speed yet? Wait until the last byte 
-	 *  has been transmitted.
-	 */
-	if (!self->wait_until_sent) {
-		ERROR("IrDA: wait_until_sent() "
-		      "has not implemented by the IrDA device driver!\n");
-		return;
-	}
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
-	/* Make sure all transmitted data has actually been sent */
-	self->wait_until_sent(self);
+	ASSERT(task != NULL, return -1;);
+	ASSERT(task->magic == IRDA_TASK_MAGIC, return -1;);
 
-	/* Make sure nobody tries to transmit during the speed change */
-	while (irda_lock((void *) &self->netdev.tbusy) == FALSE) {
-		WARNING(__FUNCTION__ "(), device locked!\n");
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(MSECS_TO_JIFFIES(10));
-
-		if (n++ > 10) {
-			WARNING(__FUNCTION__ "(), breaking loop!\n");
-			break;
-		}
-	}
-	
-	if (self->dongle)
-		self->dongle->change_speed(self, speed);
-	
-	if (self->change_speed) {
-		self->change_speed(self, speed);
-		
-		/* Update the QoS value only */
-		self->qos.baud_rate.value = speed;
+	/* Execute task until it's finished, or askes for a timeout */
+	do {
+		timeout = task->function(task);
+		if (count++ > 100) {
+			ERROR(__FUNCTION__ "(), error in task handler!\n");
+			irda_task_delete(task);
+			return TRUE;
+		}			
+	} while ((timeout == 0) && (task->state != IRDA_TASK_DONE));
+
+	if (timeout < 0) {
+		ERROR(__FUNCTION__ "(), Error executing task!\n");
+		irda_task_delete(task);
+		return TRUE;
+	}
+
+	/* Check if we are finished */
+	if (task->state == IRDA_TASK_DONE) {
+		del_timer(&task->timer);
+
+		/* Do post processing */
+		if (task->finished)
+			task->finished(task);
+
+		/* Notify parent */
+		if (task->parent) {
+			/* Check if parent is waiting for us to complete */
+			if (task->parent->state == IRDA_TASK_CHILD_WAIT) {
+				task->parent->state = IRDA_TASK_CHILD_DONE;
+
+				/* Stop timer now that we are here */
+				del_timer(&task->parent->timer);
+
+				/* Kick parent task */
+				irda_task_kick(task->parent);
+			}
+		}		
+		irda_task_delete(task);
+	} else if (timeout > 0) {
+		irda_start_timer(&task->timer, timeout, (void *) task, 
+				 irda_task_timer_expired);
+		finished = FALSE;
+	} else {
+		IRDA_DEBUG(0, __FUNCTION__ 
+			   "(), not finished, and no timeout!\n");
+		finished = FALSE;
 	}
-	self->netdev.tbusy = FALSE;
+
+	return finished;
 }
 
 /*
- * Function irda_device_change_speed (self, speed)
- *
- *    Change the speed of the currently used irda_device
+ * Function irda_task_execute (instance, function, finished)
  *
+ *    This function registers and tries to execute tasks that may take some
+ *    time to complete. We do it this hairy way since we may have been
+ *    called from interrupt context, so it's not possible to use
+ *    schedule_timeout() 
  */
-inline void irda_device_change_speed(struct irda_device *self, int speed)
+struct irda_task *irda_task_execute(void *instance, TASK_CALLBACK function, 
+				    TASK_CALLBACK finished, 
+				    struct irda_task *parent, void *param)
 {
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;);
+	struct irda_task *task;
+	int ret;
 
-	irda_execute_as_process(self, 
-				(TODO_CALLBACK) __irda_device_change_speed, 
-				speed);
-}
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
-inline int irda_device_is_media_busy( struct irda_device *self)
-{
-	ASSERT(self != NULL, return FALSE;);
-	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return FALSE;);
-	
-	return self->media_busy;
-}
+	task = kmalloc(sizeof(struct irda_task), GFP_ATOMIC);
+	if (!task)
+		return NULL;
 
-inline int irda_device_is_receiving( struct irda_device *self)
-{
-	ASSERT(self != NULL, return FALSE;);
-	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return FALSE;);
+	task->state    = IRDA_TASK_INIT;
+	task->instance = instance;
+	task->function = function;
+	task->finished = finished;
+	task->parent   = parent;
+	task->param    = param;	
+	task->magic    = IRDA_TASK_MAGIC;
+
+	init_timer(&task->timer);
+
+	/* Register task */
+	hashbin_insert(tasks, (queue_t *) task, (int) task, NULL);
 
-	if (self->is_receiving)
-		return self->is_receiving(self);
+	/* No time to waste, so lets get going! */
+	ret = irda_task_kick(task);
+	if (ret)
+		return NULL;
 	else
-		return FALSE;
+		return task;
 }
 
-inline struct qos_info *irda_device_get_qos(struct irda_device *self)
+/*
+ * Function irda_task_timer_expired (data)
+ *
+ *    Task time has expired. We now try to execute task (again), and restart
+ *    the timer if the task has not finished yet
+ */
+static void irda_task_timer_expired(void *data)
 {
-	ASSERT(self != NULL, return NULL;);
-	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return NULL;);
+	struct irda_task *task;
 
-	return &self->qos;
-}
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
-static struct enet_statistics *irda_device_get_stats( struct device *dev)
-{
-	struct irda_device *priv = (struct irda_device *) dev->priv;
+	task = (struct irda_task *) data;
 
-	return &priv->stats;
+	irda_task_kick(task);
 }
 
 /*
@@ -416,24 +412,14 @@
  */
 int irda_device_setup(struct device *dev) 
 {
-	struct irda_device *self;
-
 	ASSERT(dev != NULL, return -1;);
 
-	self = (struct irda_device *) dev->priv;
-
-	ASSERT(self != NULL, return -1;);
-	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return -1;);	
-
-	dev->get_stats	     = irda_device_get_stats;
-	dev->rebuild_header  = irda_device_net_rebuild_header;
-	dev->set_config      = irda_device_net_set_config;
-	dev->change_mtu      = irda_device_net_change_mtu;
-/*  	dev->hard_header     = irda_device_net_hard_header; */
-	dev->do_ioctl        = irda_device_net_ioctl;
         dev->hard_header_len = 0;
         dev->addr_len        = 0;
 
+	/* dev->new_style       = 1; */
+	/* dev->destructor      = irda_device_destructor; */
+
         dev->type            = ARPHRD_IRDA;
         dev->tx_queue_len    = 8; /* Window size + 1 s-frame */
  
@@ -450,254 +436,73 @@
 }
 
 /*
- * Function irda_device_net_rebuild_header (buff, dev, dst, skb)
- *
- *    
- *
- */
-static int irda_device_net_rebuild_header( struct sk_buff *skb)
-{
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	return 0;
-}
-
-static int irda_device_net_hard_header(struct sk_buff *skb, struct device *dev,
-				       unsigned short type, void *daddr, 
-				       void *saddr, unsigned len)
-{
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-	skb->mac.raw = skb->data;
-        /* skb_push(skb,PPP_HARD_HDR_LEN); */
-        /* return PPP_HARD_HDR_LEN; */
-	
-	return 0;
-}
-
-static int irda_device_net_set_config( struct device *dev, struct ifmap *map)
-{
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-	return 0;
-}
-
-static int irda_device_net_change_mtu( struct device *dev, int new_mtu)
-{
-     DEBUG( 0, __FUNCTION__ "()\n");
-     
-     return 0;  
-}
-
-
-#define SIOCSDONGLE     SIOCDEVPRIVATE
-static int irda_device_net_ioctl(struct device *dev, /* ioctl device */
-				 struct ifreq *rq,   /* Data passed */
-				 int	cmd)	     /* Ioctl number */
-{
-	unsigned long flags;
-	int			ret = 0;
-#ifdef WIRELESS_EXT
-	struct iwreq *wrq = (struct iwreq *) rq;
-#endif
-	struct irda_device *self;
-
-	DEBUG(4, __FUNCTION__ "()\n");
-
-	ASSERT(dev != NULL, return -1;);
-
-	self = (struct irda_device *) dev->priv;
-
-	ASSERT(self != NULL, return -1;);
-	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return -1;);
-
-	DEBUG(0, "%s: ->irda_device_net_ioctl(cmd=0x%X)\n", dev->name, cmd);
-	
-	/* Disable interrupts & save flags */
-	save_flags(flags);
-	cli();
-	
-	/* Look what is the request */
-	switch (cmd) {
-#ifdef WIRELESS_EXT
-	case SIOCGIWNAME:
-		/* Get name */
-		strcpy(wrq->u.name, self->name);
-		break;
-	case SIOCSIWNWID:
-		/* Set domain */
-		if (!wrq->u.nwid.disabled) {
-			
-		} break;
-	case SIOCGIWNWID:
-		/* Read domain*/
-/* 		wrq->u.nwid.nwid = domain; */
-/* 		wrq->u.nwid.disabled = 0; */
-		break;
-	case SIOCGIWENCODE:
-		/* Get scramble key */
-		/* 	wrq->u.encoding.code = scramble_key; */
-/* 		wrq->u.encoding.method = 1; */
-		break;
-	case SIOCSIWENCODE:
-		/* Set  scramble key */
-		/* scramble_key = wrq->u.encoding.code; */
-		break;
-	case SIOCGIWRANGE:
-		/* Basic checking... */
-		if(wrq->u.data.pointer != (caddr_t) 0) {
-			struct iw_range	range;
-			
-			/* Verify the user buffer */
-			ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer,
-					  sizeof(struct iw_range));
-			if(ret)
-				break;
-			
-			/* Set the length (useless : its constant...) */
-			wrq->u.data.length = sizeof(struct iw_range);
-			
-			/* Set information in the range struct */
-			range.throughput = 1.6 * 1024 * 1024;	/* don't argue on this ! */
-			range.min_nwid = 0x0000;
-			range.max_nwid = 0x01FF;
-			
-			range.num_channels = range.num_frequency = 0;
-			
-			range.sensitivity = 0x3F;
-			range.max_qual.qual = 255;
-			range.max_qual.level = 255;
-			range.max_qual.noise = 0;
-			
-			/* Copy structure to the user buffer */
-			copy_to_user(wrq->u.data.pointer, &range,
-				     sizeof(struct iw_range));
-		}
-		break;
-	case SIOCGIWPRIV:
-		/* Basic checking... */
-#if 0
-		if (wrq->u.data.pointer != (caddr_t) 0) {
-			struct iw_priv_args	priv[] =
-			{	/* cmd,		set_args,	get_args,	name */
-				{ SIOCGIPSNAP, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 0, 
-				  sizeof(struct site_survey), 
-				  "getsitesurvey" },
-			};
-			
-			/* Verify the user buffer */
-			ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer,
-					  sizeof(priv));
-			if (ret)
-				break;
-			
-			/* Set the number of ioctl available */
-			wrq->u.data.length = 1;
-			
-			/* Copy structure to the user buffer */
-			copy_to_user(wrq->u.data.pointer, (u_char *) priv,
-				     sizeof(priv));
-		}
-#endif 
-		break;
-#endif
-	case SIOCSDONGLE: /* Set dongle */
-		/* Initialize dongle */
-		irda_device_init_dongle(self, (int) rq->ifr_data);
-		break;
-	default:
-		ret = -EOPNOTSUPP;
-	}
-	
-	restore_flags(flags);
-	
-	return ret;
-}
-
-/*
- * Function irda_device_transmit_finished (void)
+ * Function irda_device_txqueue_empty (dev)
  *
  *    Check if there is still some frames in the transmit queue for this
  *    device. Maybe we should use: q->q.qlen == 0.
  *
  */
-int irda_device_txqueue_empty(struct irda_device *self)
+int irda_device_txqueue_empty(struct device *dev)
 {
-	ASSERT(self != NULL, return -1;);
-	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return -1;);	
-
-	if (skb_queue_len(&self->netdev.qdisc->q))
+	if (skb_queue_len(&dev->qdisc->q))
 		return FALSE;
 
 	return TRUE;
 }
 
 /*
- * Function irda_device_init_dongle (self, type)
+ * Function irda_device_init_dongle (self, type, qos)
  *
- *    Initialize attached dongle. Warning, must be called with a process
- *    context!
+ *    Initialize attached dongle.
  */
-void irda_device_init_dongle(struct irda_device *self, int type)
+dongle_t *irda_device_dongle_init(struct device *dev, int type)
 {
-	struct dongle_q *node;
+	struct dongle_reg *reg;
+	char modname[32];
+	dongle_t *dongle;
 
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;);
+	ASSERT(dev != NULL, return NULL;);
 
 #ifdef CONFIG_KMOD
 	/* Try to load the module needed */
-	switch (type) {
-	case ESI_DONGLE:
-		MESSAGE("IrDA: Initializing ESI dongle!\n");
-		request_module("esi");
-		break;
-	case TEKRAM_DONGLE:
-		MESSAGE("IrDA: Initializing Tekram dongle!\n");
-		request_module("tekram");
-		break;
-	case ACTISYS_DONGLE:     /* FALLTHROUGH */
-	case ACTISYS_PLUS_DONGLE:
-		MESSAGE("IrDA: Initializing ACTiSYS dongle!\n");
-		request_module("actisys");
-		break;
-	case GIRBIL_DONGLE:
-		MESSAGE("IrDA: Initializing GIrBIL dongle!\n");
-		request_module("girbil");
-		break;
-	case LITELINK_DONGLE:
-		MESSAGE("IrDA: Initializing Litelink dongle!\n");
-		request_module("litelink");
-		break;
-	default:
-		ERROR("Unknown dongle type!\n");
-		return;
-	}
+	sprintf(modname, "irda-dongle-%d", type);
+	request_module(modname);
 #endif /* CONFIG_KMOD */
 
-	node = hashbin_find(dongles, type, NULL);
-	if (!node) {
+	if (!(reg = hashbin_find(dongles, type, NULL))) {
 		ERROR("IrDA: Unable to find requested dongle\n");
-		return;
-	}
-	
-	/* Check if we're already using a dongle */
-	if (self->dongle) {
-		self->dongle->close(self);
+		return NULL;
 	}
 
-	/* Set the dongle to be used by this driver */
-	self->dongle = node->dongle;
+	/* Allocate dongle info for this instance */
+	dongle = kmalloc(sizeof(dongle_t), GFP_KERNEL);
+	if (!dongle)
+		return NULL;
 
-	/* Now initialize the dongle!  */
-	node->dongle->open(self, type);
-	node->dongle->qos_init(self, &self->qos);
-	
-	/* Reset dongle */
-	node->dongle->reset(self);
+	memset(dongle, 0, sizeof(dongle_t));
+
+	/* Bind the registration info to this particular instance */
+	dongle->issue = reg;
+	dongle->dev = dev;
+
+	return dongle;
+}
+
+/*
+ * Function irda_device_dongle_cleanup (dongle)
+ *
+ *    
+ *
+ */
+int irda_device_dongle_cleanup(dongle_t *dongle)
+{
+	ASSERT(dongle != NULL, return -1;);
+
+	dongle->issue->close(dongle);
+
+	kfree(dongle);
 
-	/* Set to default baudrate */
-	irda_device_change_speed(self, 9600);
+	return 0;
 }
 
 /*
@@ -706,26 +511,16 @@
  *    
  *
  */
-int irda_device_register_dongle(struct dongle *dongle)
+int irda_device_register_dongle(struct dongle_reg *new)
 {
-	struct dongle_q *new;
-	
 	/* Check if this dongle has been registred before */
-	if (hashbin_find(dongles, dongle->type, NULL)) {
+	if (hashbin_find(dongles, new->type, NULL)) {
 		MESSAGE(__FUNCTION__ "(), Dongle already registered\n");
                 return 0;
         }
 	
-	/* Make new IrDA dongle */
-        new = (struct dongle_q *) kmalloc(sizeof(struct dongle_q), GFP_KERNEL);
-        if (new == NULL)
-                return -1;
-		
-	memset(new, 0, sizeof( struct dongle_q));
-        new->dongle = dongle;
-
 	/* Insert IrDA dongle into hashbin */
-	hashbin_insert(dongles, (QUEUE *) new, dongle->type, NULL);
+	hashbin_insert(dongles, (queue_t *) new, new->type, NULL);
 	
         return 0;
 }
@@ -733,25 +528,51 @@
 /*
  * Function irda_device_unregister_dongle (dongle)
  *
- *    
+ *    Unregister dongle, and remove dongle from list of registred dongles
  *
  */
-void irda_device_unregister_dongle(struct dongle *dongle)
+void irda_device_unregister_dongle(struct dongle_reg *dongle)
 {
-	struct dongle_q *node;
+	struct dongle *node;
 
 	node = hashbin_remove(dongles, dongle->type, NULL);
 	if (!node) {
 		ERROR(__FUNCTION__ "(), dongle not found!\n");
 		return;
 	}
-	kfree(node);
+}
+
+/*
+ * Function irda_device_set_mode (self, mode)
+ *
+ *    Set the Infrared device driver into mode where it sends and receives
+ *    data without using IrLAP framing. Check out the particular device
+ *    driver to find out which modes it support.
+ */
+int irda_device_set_mode(struct device* dev, int mode)
+{	
+	struct if_irda_req req;
+	int ret;
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	if (!dev->do_ioctl) {
+		ERROR(__FUNCTION__ "(), set_raw_mode not impl. by "
+		      "device driver\n");
+		return -1;
+	}
+	
+	req.ifr_mode = mode;
+
+	ret = dev->do_ioctl(dev, (struct ifreq *) &req, SIOCSMODE);
+	
+	return ret;
 }
 
 /*
  * Function setup_dma (idev, buffer, count, mode)
  *
- *    Setup the DMA channel
+ *    Setup the DMA channel. Commonly used by ISA FIR drivers
  *
  */
 void setup_dma(int channel, char *buffer, int count, int mode)
@@ -769,88 +590,3 @@
 
 	release_dma_lock(flags);
 }
-
-#ifdef CONFIG_PROC_FS
-
-int irda_device_print_flags(struct irda_device *idev, char *buf)
-{
-	int len=0;
-
-	len += sprintf( buf+len, "\t");
-
-	if (idev->netdev.flags & IFF_UP)
-		len += sprintf( buf+len, "UP ");
-	if (!idev->netdev.tbusy)
-		len += sprintf( buf+len, "RUNNING ");
-
-	if (idev->flags & IFF_SIR)
-		len += sprintf( buf+len, "SIR ");
-	if (idev->flags & IFF_MIR)
-		len += sprintf( buf+len, "MIR ");
-	if (idev->flags & IFF_FIR)
-		len += sprintf( buf+len, "FIR ");
-	if (idev->flags & IFF_PIO)
-		len += sprintf( buf+len, "PIO ");
-	if (idev->flags & IFF_DMA)
-		len += sprintf( buf+len, "DMA ");
-	if (idev->flags & IFF_SHM)
-		len += sprintf( buf+len, "SHM ");
-	if (idev->flags & IFF_DONGLE)
-		len += sprintf( buf+len, "DONGLE ");
-
-	len += sprintf( buf+len, "\n");
-
-	return len;
-}
-
-/*
- * Function irda_device_proc_read (buf, start, offset, len, unused)
- *
- *    Give some info to the /proc file system
- *
- */
-int irda_device_proc_read(char *buf, char **start, off_t offset, int len, 
-			  int unused)
-{
-	struct irda_device *self;
-	unsigned long flags;
-     
-	save_flags(flags);
-	cli();
-
-	len = 0;
-
-	self = (struct irda_device *) hashbin_get_first(irda_device);
-	while ( self != NULL) {
-		len += sprintf(buf+len, "\n%s,", self->name);
-		len += sprintf(buf+len, "\tbinding: %s\n", 
-			       self->description);
-		
-		len += irda_device_print_flags(self, buf+len);
-		len += sprintf(buf+len, "\tbps\tmaxtt\tdsize\twinsize\taddbofs\tmintt\tldisc\n");
-		
-		len += sprintf(buf+len, "\t%d\t", 
-			       self->qos.baud_rate.value);
-		len += sprintf(buf+len, "%d\t", 
-			       self->qos.max_turn_time.value);
-		len += sprintf(buf+len, "%d\t",
-			       self->qos.data_size.value);
-		len += sprintf(buf+len, "%d\t",
-			       self->qos.window_size.value);
-		len += sprintf(buf+len, "%d\t",
-			       self->qos.additional_bofs.value);
-		len += sprintf(buf+len, "%d\t", 
-			       self->qos.min_turn_time.value);
-		len += sprintf(buf+len, "%d", 
-			       self->qos.link_disc_time.value);
-		len += sprintf(buf+len, "\n");
-		
-		self = (struct irda_device *) hashbin_get_next(irda_device);
-	}
-	restore_flags(flags);
-
-	return len;
-}
-
-#endif /* CONFIG_PROC_FS */
-
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/iriap.c linux.15p9/net/irda/iriap.c
--- linux.vanilla/net/irda/iriap.c	Sat Aug 14 02:26:52 1999
+++ linux.15p9/net/irda/iriap.c	Tue Jan 18 01:08:18 2000
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Aug 21 00:02:07 1997
- * Modified at:   Sun May  9 15:59:05 1999
+ * Modified at:   Sat Dec 25 16:42:42 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -28,7 +28,6 @@
 #include <linux/skbuff.h>
 #include <linux/string.h>
 #include <linux/init.h>
-#include <linux/irda.h>
 
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
@@ -61,8 +60,8 @@
 
 extern char *lmp_reasons[];
 
-static struct iriap_cb *iriap_open( __u8 slsap, int mode);
 static void __iriap_close(struct iriap_cb *self);
+static int iriap_register_lsap(struct iriap_cb *self, __u8 slsap_sel, int mode);
 static void iriap_disconnect_indication(void *instance, void *sap, 
 					LM_REASON reason, struct sk_buff *skb);
 static void iriap_connect_indication(void *instance, void *sap, 
@@ -82,22 +81,21 @@
  *    Initializes the IrIAP layer, called by the module initialization code
  *    in irmod.c 
  */
-__initfunc(int iriap_init(void))
+int __init iriap_init(void)
 {
-	__u16 hints;
 	struct ias_object *obj;
+	struct iriap_cb *server;
+	__u8 oct_seq[6];
+	__u16 hints;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
 	/* Allocate master array */
-	iriap = hashbin_new( HB_LOCAL);
-	if ( iriap == NULL)
+	iriap = hashbin_new(HB_LOCAL);
+	if (!iriap)
 		return -ENOMEM;
 
-	objects = hashbin_new( HB_LOCAL);
-	if ( objects == NULL) {
-		printk( KERN_WARNING 
-			"IrIAP: Can't allocate objects hashbin!\n");
+	objects = hashbin_new(HB_LOCAL);
+	if (!objects) {
+		WARNING(__FUNCTION__ "(), Can't allocate objects hashbin!\n");
 		return -ENOMEM;
 	}
 
@@ -105,22 +103,32 @@
 	 *  Register some default services for IrLMP 
 	 */
 	hints  = irlmp_service_to_hint(S_COMPUTER);
-	hints |= irlmp_service_to_hint(S_PNP);
 	service_handle = irlmp_register_service(hints);
 
-	/* 
-	 *  Register the Device object with LM-IAS
-	 */
-	obj = irias_new_object( "Device", IAS_DEVICE_ID);
-	irias_add_string_attrib( obj, "DeviceName", "Linux");
-	irias_insert_object( obj);
+	/* Register the Device object with LM-IAS */
+	obj = irias_new_object("Device", IAS_DEVICE_ID);
+	irias_add_string_attrib(obj, "DeviceName", "Linux");
+
+	oct_seq[0] = 0x01;  /* Version 1 */
+	oct_seq[1] = 0x00;  /* IAS support bits */
+	oct_seq[2] = 0x00;  /* LM-MUX support bits */
+#ifdef CONFIG_IRDA_ULTRA
+	oct_seq[2] |= 0x04; /* Connectionless Data support */
+#endif
+	irias_add_octseq_attrib(obj, "IrLMPSupport", oct_seq, 3);
+	irias_insert_object(obj);
 
 	/*  
 	 *  Register server support with IrLMP so we can accept incoming 
 	 *  connections 
 	 */
-	iriap_open( LSAP_IAS, IAS_SERVER);
-	
+	server = iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL);
+	if (!server) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), unable to open server\n");
+		return -1;
+	}
+	iriap_register_lsap(server, LSAP_IAS, IAS_SERVER);
+
 	return 0;
 }
 
@@ -130,7 +138,7 @@
  *    Initializes the IrIAP layer, called by the module cleanup code in 
  *    irmod.c
  */
-void iriap_cleanup(void) 
+void iriap_cleanup(void)
 {
 	irlmp_unregister_service(service_handle);
 	
@@ -143,57 +151,41 @@
  *
  *    Opens an instance of the IrIAP layer, and registers with IrLMP
  */
-struct iriap_cb *iriap_open( __u8 slsap_sel, int mode)
+struct iriap_cb *iriap_open(__u8 slsap_sel, int mode, void *priv, 
+			    CONFIRM_CALLBACK callback)
 {
 	struct iriap_cb *self;
-	struct notify_t notify;
-	struct lsap_cb *lsap;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
-	self = kmalloc( sizeof(struct iriap_cb), GFP_ATOMIC);
-	if ( self == NULL) {
-		DEBUG( 0, "iriap_open(), Unable to kmalloc!\n");
+	self = kmalloc(sizeof(struct iriap_cb), GFP_ATOMIC);
+	if (!self) {
+		WARNING(__FUNCTION__ "(), Unable to kmalloc!\n");
 		return NULL;
 	}
 
 	/*
 	 *  Initialize instance
 	 */
-	memset( self, 0, sizeof(struct iriap_cb));
-
-	irda_notify_init( &notify);
-	notify.connect_confirm = iriap_connect_confirm;
-	notify.connect_indication = iriap_connect_indication;
-	notify.disconnect_indication = iriap_disconnect_indication;
-	notify.data_indication = iriap_data_indication;
-	notify.instance = self;
-	if ( mode == IAS_CLIENT)
-		strcpy( notify.name, "IrIAS cli");
-	else
-		strcpy( notify.name, "IrIAS srv");
-
-	lsap = irlmp_open_lsap( slsap_sel, &notify);
-	if ( lsap == NULL) {
-		DEBUG( 0, "iriap_open: Unable to allocated LSAP!\n");
-		return NULL;
-	}
-	slsap_sel = lsap->slsap_sel;
-	DEBUG( 4, __FUNCTION__ "(), source LSAP sel=%02x\n", slsap_sel);
+	memset(self, 0, sizeof(struct iriap_cb));
 	
 	self->magic = IAS_MAGIC;
-	self->lsap = lsap;
-	self->slsap_sel = slsap_sel;
 	self->mode = mode;
+	if (mode == IAS_CLIENT)
+		iriap_register_lsap(self, slsap_sel, mode);
+
+	self->confirm = callback;
+	self->priv = priv;
 
 	init_timer(&self->watchdog_timer);
 
-	hashbin_insert( iriap, (QUEUE*) self, slsap_sel, NULL);
+	hashbin_insert(iriap, (queue_t *) self, (int) self, NULL);
 	
-	iriap_next_client_state( self, S_DISCONNECT);
-	iriap_next_call_state( self, S_MAKE_CALL);
-	iriap_next_server_state( self, R_DISCONNECT);
-	iriap_next_r_connect_state( self, R_WAITING);
+	/* Initialize state machines */
+	iriap_next_client_state(self, S_DISCONNECT);
+	iriap_next_call_state(self, S_MAKE_CALL);
+	iriap_next_server_state(self, R_DISCONNECT);
+	iriap_next_r_connect_state(self, R_WAITING);
 	
 	return self;
 }
@@ -204,18 +196,21 @@
  *    Removes (deallocates) the IrIAP instance
  *
  */
-static void __iriap_close( struct iriap_cb *self)
+static void __iriap_close(struct iriap_cb *self)
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
 
 	del_timer(&self->watchdog_timer);
 
+	if (self->skb)
+		dev_kfree_skb(self->skb);
+
 	self->magic = 0;
 
-	kfree( self);
+	kfree(self);
 }
 
 /*
@@ -223,25 +218,51 @@
  *
  *    Closes IrIAP and deregisters with IrLMP
  */
-void iriap_close( struct iriap_cb *self)
+void iriap_close(struct iriap_cb *self)
 {
 	struct iriap_cb *entry;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
 
-	if ( self->lsap) {
-		irlmp_close_lsap( self->lsap);
+	if (self->lsap) {
+		irlmp_close_lsap(self->lsap);
 		self->lsap = NULL;
 	}
 
-	entry = (struct iriap_cb *) hashbin_remove( iriap, self->slsap_sel, 
-						    NULL);
-	ASSERT( entry == self, return;);
+	entry = (struct iriap_cb *) hashbin_remove(iriap, (int) self, NULL);
+	ASSERT(entry == self, return;);
+
+	__iriap_close(self);
+}
+
+static int iriap_register_lsap(struct iriap_cb *self, __u8 slsap_sel, int mode)
+{
+	notify_t notify;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	irda_notify_init(&notify);
+	notify.connect_confirm       = iriap_connect_confirm;
+	notify.connect_indication    = iriap_connect_indication;
+	notify.disconnect_indication = iriap_disconnect_indication;
+	notify.data_indication       = iriap_data_indication;
+	notify.instance = self;
+	if (mode == IAS_CLIENT)
+		strcpy(notify.name, "IrIAS cli");
+	else
+		strcpy(notify.name, "IrIAS srv");
+
+	self->lsap = irlmp_open_lsap(slsap_sel, &notify, 0);
+	if (self->lsap == NULL) {
+		ERROR(__FUNCTION__ "(), Unable to allocated LSAP!\n");
+		return -1;
+	}
+	self->slsap_sel = self->lsap->slsap_sel;
 
-	__iriap_close( self);
+	return 0;
 }
 
 /*
@@ -250,47 +271,45 @@
  *    Got disconnect, so clean up everything assosiated with this connection
  *
  */
-static void iriap_disconnect_indication( void *instance, void *sap, 
-					 LM_REASON reason, 
-					 struct sk_buff *userdata)
+static void iriap_disconnect_indication(void *instance, void *sap, 
+					LM_REASON reason, 
+					struct sk_buff *userdata)
 {
 	struct iriap_cb *self;
 
-	DEBUG(4, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);
+	IRDA_DEBUG(4, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);
 
 	self = (struct iriap_cb *) instance;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
 
-	ASSERT( iriap != NULL, return;);
+	ASSERT(iriap != NULL, return;);
 
 	del_timer(&self->watchdog_timer);
 
-	if ( self->mode == IAS_CLIENT) {
-		DEBUG( 4, __FUNCTION__ "(), disconnect as client\n");
+	if (self->mode == IAS_CLIENT) {
+		IRDA_DEBUG(4, __FUNCTION__ "(), disconnect as client\n");
 
+
+		iriap_do_client_event(self, IAP_LM_DISCONNECT_INDICATION, 
+				      NULL);
 		/* 
 		 * Inform service user that the request failed by sending 
-		 * it a NULL value.
+		 * it a NULL value. Warning, the client might close us, so
+		 * remember no to use self anymore after calling confirm
 		 */
 		if (self->confirm)
  			self->confirm(IAS_DISCONNECT, 0, NULL, self->priv);
-		
-		
-		iriap_do_client_event( self, IAP_LM_DISCONNECT_INDICATION, 
-				       NULL);
-		/* Close instance only if client */
-		iriap_close( self);
-		
 	} else {
-		DEBUG( 4, __FUNCTION__ "(), disconnect as server\n");
-		iriap_do_server_event( self, IAP_LM_DISCONNECT_INDICATION, 
-				       NULL);
+		IRDA_DEBUG(4, __FUNCTION__ "(), disconnect as server\n");
+		iriap_do_server_event(self, IAP_LM_DISCONNECT_INDICATION, 
+				      NULL);
+		iriap_close(self);
 	}
 
 	if (userdata)
-		dev_kfree_skb( userdata);
+		dev_kfree_skb(userdata);
 }
 
 /*
@@ -303,14 +322,14 @@
 {
 	struct sk_buff *skb;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IAS_MAGIC, return;);
 
 	skb = dev_alloc_skb(64);
 	if (skb == NULL) {
-		DEBUG(0, __FUNCTION__
+		IRDA_DEBUG(0, __FUNCTION__
 		      "(), Could not allocate an sk_buff of length %d\n", 64);
 		return;
 	}
@@ -325,27 +344,27 @@
 
 void iriap_getinfobasedetails_request(void) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
+	IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
 }
 
 void iriap_getinfobasedetails_confirm(void) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
+	IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
 }
 
 void iriap_getobjects_request(void) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
+	IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
 }
 
 void iriap_getobjects_confirm(void) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
+	IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
 }
 
 void iriap_getvalue(void) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
+	IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
 }
 
 /*
@@ -354,26 +373,21 @@
  *    Retreive all values from attribute in all objects with given class
  *    name
  */
-void iriap_getvaluebyclass_request(char *name, char *attr, 
-				   __u32 saddr, __u32 daddr,
-				   CONFIRM_CALLBACK callback, void *priv)
+int iriap_getvaluebyclass_request(struct iriap_cb *self,
+				  __u32 saddr, __u32 daddr, 
+				  char *name, char *attr)
 {
 	struct sk_buff *skb;
-	struct iriap_cb *self;
-	__u8 *frame;
 	int name_len, attr_len;
-	__u8 slsap = LSAP_ANY;  /* Source LSAP to use */
-
-	DEBUG(4, __FUNCTION__ "()\n");
-	
-	self = iriap_open(slsap, IAS_CLIENT);
-	if (!self)
-		return;
+	__u8 *frame;
 
-	self->mode = IAS_CLIENT;
-	self->confirm = callback;
-	self->priv = priv;
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IAS_MAGIC, return -1;);
 
+	/* Client must supply the destination device address */
+	if (!daddr)
+		return -1;
+	
 	self->daddr = daddr;
 	self->saddr = saddr;
 
@@ -387,7 +401,7 @@
 	
 	skb = dev_alloc_skb(64);
 	if (!skb)
-		return;
+		return -ENOMEM;
 
 	name_len = strlen(name);
 	attr_len = strlen(attr);
@@ -405,6 +419,8 @@
 	memcpy(frame+3+name_len, attr, attr_len);  /* Insert attr */
 
 	iriap_do_client_event(self, IAP_CALL_REQUEST_GVBC, skb);
+
+	return 0;
 }
 
 /*
@@ -417,7 +433,6 @@
 void iriap_getvaluebyclass_confirm(struct iriap_cb *self, struct sk_buff *skb) 
 {
 	struct ias_value *value;
-	int n;
 	int charset;
 	__u32 value_len;
 	__u32 tmp_cpu32;
@@ -425,6 +440,7 @@
 	__u16 len;
 	__u8  type;
 	__u8 *fp;
+	int n;
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IAS_MAGIC, return;);
@@ -437,29 +453,27 @@
 	/* Get length, MSB first */
 	len = be16_to_cpu(get_unaligned((__u16 *)(fp+n))); n += 2;
 
-	DEBUG(4, __FUNCTION__ "(), len=%d\n", len);
+	IRDA_DEBUG(4, __FUNCTION__ "(), len=%d\n", len);
 
 	/* Get object ID, MSB first */
 	obj_id = be16_to_cpu(get_unaligned((__u16 *)(fp+n))); n += 2;
-/* 	memcpy(&obj_id, fp+n, 2); n += 2; */
-/* 	be16_to_cpus(&obj_id); */
 
 	type = fp[n++];
-	DEBUG( 4, __FUNCTION__ "(), Value type = %d\n", type);
+	IRDA_DEBUG(4, __FUNCTION__ "(), Value type = %d\n", type);
 
-	switch( type) {
+	switch (type) {
 	case IAS_INTEGER:
 		memcpy(&tmp_cpu32, fp+n, 4); n += 4;
 		be32_to_cpus(&tmp_cpu32);
 		value = irias_new_integer_value(tmp_cpu32);
 
 		/*  Legal values restricted to 0x01-0x6f, page 15 irttp */
-		DEBUG( 4, __FUNCTION__ "(), lsap=%d\n", value->t.integer); 
+		IRDA_DEBUG(4, __FUNCTION__ "(), lsap=%d\n", value->t.integer); 
 		break;
 	case IAS_STRING:
 		charset = fp[n++];
 
-		switch(charset) {
+		switch (charset) {
 		case CS_ASCII:
 			break;
 /* 		case CS_ISO_8859_1: */
@@ -473,41 +487,52 @@
 /* 		case CS_ISO_8859_9: */
 /* 		case CS_UNICODE: */
 		default:
-			DEBUG(0, __FUNCTION__"(), charset %s, not supported\n",
-			      ias_charset_types[charset]);
+			IRDA_DEBUG(0, __FUNCTION__
+				   "(), charset %s, not supported\n",
+				   ias_charset_types[charset]);
+
+			/* Aborting, close connection! */
+			iriap_disconnect_request(self);
+			dev_kfree_skb(skb);
 			return;
 			/* break; */
 		}
 		value_len = fp[n++];
-		DEBUG(4, __FUNCTION__ "(), strlen=%d\n", value_len);
-		ASSERT( value_len < 64, return;);
+		IRDA_DEBUG(4, __FUNCTION__ "(), strlen=%d\n", value_len);
+		ASSERT(value_len < 64, return;);
 		
 		/* Make sure the string is null-terminated */
 		fp[n+value_len] = 0x00;
 		
-		DEBUG(4, "Got string %s\n", fp+n);
+		IRDA_DEBUG(4, "Got string %s\n", fp+n);
 		value = irias_new_string_value(fp+n);
 		break;
 	case IAS_OCT_SEQ:
 		value_len = be16_to_cpu(get_unaligned((__u16 *)(fp+n)));
 		n += 2;
 		
-		/* FIXME:should be 1024, but.... */
-		DEBUG(0, __FUNCTION__ "():octet sequence:len=%d\n", value_len);
 		ASSERT(value_len <= 55, return;);      
 		
 		value = irias_new_octseq_value(fp+n, value_len);
 		break;
 	default:
-		value = &missing;
+		value = irias_new_missing_value();
 		break;
 	}
 	
 	/* Finished, close connection! */
 	iriap_disconnect_request(self);
 
+	/* Warning, the client might close us, so remember no to use self
+	 * anymore after calling confirm 
+	 */
 	if (self->confirm)
 		self->confirm(IAS_SUCCESS, obj_id, value, self->priv);
+	else {
+		IRDA_DEBUG(0, __FUNCTION__ "(), missing handler!\n");
+		irias_delete_value(value);
+	}
+	dev_kfree_skb(skb);
 }
 
 /*
@@ -524,22 +549,22 @@
 	__u32 tmp_be32, tmp_be16;
 	__u8 *fp;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
-	ASSERT( value != NULL, return;);
-	ASSERT( value->len <= 1024, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
+	ASSERT(value != NULL, return;);
+	ASSERT(value->len <= 1024, return;);
 
 	/* Initialize variables */
 	n = 0;
 
 	/* 
 	 *  We must adjust the size of the response after the length of the 
-	 *  value. We add 9 bytes because of the 6 bytes for the frame and
-	 *  max 3 bytes for the value coding.
+	 *  value. We add 32 bytes because of the 6 bytes for the frame and
+	 *  max 5 bytes for the value coding.
 	 */
-	skb = dev_alloc_skb(value->len + self->max_header_size + 9);
+	skb = dev_alloc_skb(value->len + self->max_header_size + 32);
 	if (!skb)
 		return;
 
@@ -561,7 +586,7 @@
 	tmp_be16 = cpu_to_be16(obj_id);
 	memcpy(fp+n, &tmp_be16, 2); n += 2;
 
-	switch(value->type) {
+	switch (value->type) {
 	case IAS_STRING:
 		skb_put(skb, 3 + value->len);
 		fp[n++] = value->type;
@@ -585,13 +610,12 @@
 		memcpy(fp+n, value->t.oct_seq, value->len); n+=value->len;
 		break;
 	case IAS_MISSING:
-		DEBUG( 3, __FUNCTION__ ": sending IAS_MISSING\n");
-		skb_put( skb, 1);
+		IRDA_DEBUG( 3, __FUNCTION__ ": sending IAS_MISSING\n");
+		skb_put(skb, 1);
 		fp[n++] = value->type;
 		break;
-
 	default:
-		DEBUG(0, __FUNCTION__ "(), type not implemented!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), type not implemented!\n");
 		break;
 	}
 	iriap_do_r_connect_event(self, IAP_CALL_RESPONSE, skb);
@@ -606,64 +630,58 @@
 void iriap_getvaluebyclass_indication(struct iriap_cb *self, 
 				      struct sk_buff *skb)
 {
-	__u8 *fp;
-	int n;
+ 	struct ias_object *obj;
+	struct ias_attrib *attrib;
 	int name_len;
 	int attr_len;
 	char name[64];
 	char attr[64];
- 	struct ias_object *obj;
-	struct ias_attrib *attrib;
+	__u8 *fp;
+	int n;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
 
 	fp = skb->data;
 	n = 1;
 
 	name_len = fp[n++];
-	memcpy( name, fp+n, name_len); n+=name_len;
+	memcpy(name, fp+n, name_len); n+=name_len;
 	name[name_len] = '\0';
 
 	attr_len = fp[n++]; 
-	memcpy( attr, fp+n, attr_len); n+=attr_len;
+	memcpy(attr, fp+n, attr_len); n+=attr_len;
 	attr[attr_len] = '\0';
 
-	dev_kfree_skb( skb);
+	/* We do not need the buffer anymore */
+	dev_kfree_skb(skb);
 
-	/* 
-	 *  Now, do some advanced parsing! :-) 
-	 */
-	DEBUG(4, "LM-IAS: Looking up %s: %s\n", name, attr);
+	IRDA_DEBUG(4, "LM-IAS: Looking up %s: %s\n", name, attr);
 	obj = irias_find_object(name);
 	
-	if ( obj == NULL) {
-		DEBUG( 0, "LM-IAS: Object not found\n");
-		iriap_getvaluebyclass_response( self, 0x1235, 
-						IAS_CLASS_UNKNOWN, &missing);
+	if (obj == NULL) {
+		IRDA_DEBUG(2, "LM-IAS: Object %s not found\n", name);
+		iriap_getvaluebyclass_response(self, 0x1235, IAS_CLASS_UNKNOWN,
+					       &missing);
 		return;
 	}
-	DEBUG(4, "LM-IAS: found %s, id=%d\n", obj->name, obj->id);
+	IRDA_DEBUG(4, "LM-IAS: found %s, id=%d\n", obj->name, obj->id);
 	
-	attrib = irias_find_attrib( obj, attr);
-	if ( attrib == NULL) {
-		DEBUG( 0, "LM-IAS: Attribute %s not found\n", attr);
+	attrib = irias_find_attrib(obj, attr);
+	if (attrib == NULL) {
+		IRDA_DEBUG(2, "LM-IAS: Attribute %s not found\n", attr);
 		iriap_getvaluebyclass_response(self, obj->id,
 					       IAS_ATTRIB_UNKNOWN, &missing);
 		return;
 	}
 	
-	DEBUG(4, "LM-IAS: found %s\n", attrib->name);
+	/* We have a match; send the value.  */
+	iriap_getvaluebyclass_response(self, obj->id, IAS_SUCCESS, 
+				       attrib->value);
 	
-	/*
-	 * We have a match; send the value.
-	 */
-	iriap_getvaluebyclass_response( self, obj->id, IAS_SUCCESS, 
-					attrib->value);
-
 	return;
 }
 
@@ -673,15 +691,15 @@
  *    Currently not used
  *
  */
-void iriap_send_ack( struct iriap_cb *self) 
+void iriap_send_ack(struct iriap_cb *self) 
 {
 	struct sk_buff *skb;
 	__u8 *frame;
 
-	DEBUG( 6, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
 
 	skb = dev_alloc_skb(64);
 	if (!skb)
@@ -693,7 +711,25 @@
 	frame = skb->data;
 
 	/* Build frame */
-	frame[0] = IAP_LST | self->operation;
+	frame[0] = IAP_LST | IAP_ACK | self->operation;
+
+	irlmp_data_request(self->lsap, skb);
+}
+
+void iriap_connect_request(struct iriap_cb *self)
+{
+	int ret;
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
+
+	ret = irlmp_connect_request(self->lsap, LSAP_IAS, 
+				    self->saddr, self->daddr, 
+				    NULL, NULL);
+	if (ret < 0) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), connect failed!\n");
+		self->confirm(IAS_DISCONNECT, 0, NULL, self->priv);
+	}
 }
 
 /*
@@ -703,8 +739,8 @@
  *
  */
 static void iriap_connect_confirm(void *instance, void *sap, 
-				  struct qos_info *qos, 
-				  __u32 max_sdu_size, __u8 header_size, 
+				  struct qos_info *qos, __u32 max_seg_size, 
+				  __u8 max_header_size, 
 				  struct sk_buff *userdata)
 {
 	struct iriap_cb *self;
@@ -715,7 +751,8 @@
 	ASSERT(self->magic == IAS_MAGIC, return;);
 	ASSERT(userdata != NULL, return;);
 	
-	DEBUG(4, __FUNCTION__ "()\n");
+	self->max_data_size = max_seg_size;
+	self->max_header_size = max_header_size;
 	
 	del_timer(&self->watchdog_timer);
 
@@ -729,18 +766,43 @@
  *
  */
 static void iriap_connect_indication(void *instance, void *sap, 
-				     struct qos_info *qos, __u32 max_sdu_size,
-				     __u8 header_size, 
+				     struct qos_info *qos, __u32 max_seg_size,
+				     __u8 max_header_size, 
 				     struct sk_buff *userdata)
 {
-	struct iriap_cb *self;
+	struct iriap_cb *self, *new;
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
 	self = (struct iriap_cb *) instance;
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IAS_MAGIC, return;);
+	
+	/* Start new server */
+	new = iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL); 
+	if (!new) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), open failed\n");
+		dev_kfree_skb(userdata);
+		return;
+	}
+	
+	/* Now attach up the new "socket" */
+	new->lsap = irlmp_dup(self->lsap, new);
+	if (!new->lsap) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), dup failed!\n");
+		return;
+	}
+		
+	new->max_data_size = max_seg_size;
+	new->max_header_size = max_header_size;
 
-	iriap_do_server_event(self, IAP_LM_CONNECT_INDICATION, userdata);
+	/* Clean up the original one to keep it in listen state */
+	self->lsap->dlsap_sel = LSAP_ANY;
+	self->lsap->lsap_state = LSAP_DISCONNECTED;
+	/* FIXME: refcount in irlmp might get wrong */
+	
+	iriap_do_server_event(new, IAP_LM_CONNECT_INDICATION, userdata);
 }
  
 /*
@@ -756,7 +818,7 @@
 	__u8  *frame;
 	__u8  opcode;
 	
-	DEBUG( 4, __FUNCTION__ "()\n"); 
+	IRDA_DEBUG(3, __FUNCTION__ "()\n"); 
 	
 	self = (struct iriap_cb *) instance;
 
@@ -769,65 +831,74 @@
 	
 	if (self->mode == IAS_SERVER) {
 		/* Call server */
-		DEBUG(4, __FUNCTION__ "(), Calling server!\n");
-		iriap_do_r_connect_event( self, IAP_RECV_F_LST, skb);
+		IRDA_DEBUG(4, __FUNCTION__ "(), Calling server!\n");
+		iriap_do_r_connect_event(self, IAP_RECV_F_LST, skb);
 
 		return 0;
 	}
 	opcode = frame[0];
-	if ( ~opcode & 0x80) {
-		printk( KERN_ERR "IrIAS multiframe commands or results is "
-			"not implemented yet!\n");
+	if (~opcode & IAP_LST) {
+		WARNING(__FUNCTION__ "(), IrIAS multiframe commands or "
+			"results is not implemented yet!\n");
+		dev_kfree_skb(skb);
 		return 0;
 	}
-
-	if (~opcode & IAP_ACK) {
-		DEBUG(2, __FUNCTION__ "() Got ack frame!\n");
-	/* 	return; */
+	
+	/* Check for ack frames since they don't contain any data */
+	if (opcode & IAP_ACK) {
+		IRDA_DEBUG(0, __FUNCTION__ "() Got ack frame!\n");
+		dev_kfree_skb(skb);
+	 	return 0;
 	}
 
 	opcode &= ~IAP_LST; /* Mask away LST bit */
-	
-	switch(opcode) {
+
+	switch (opcode) {
 	case GET_INFO_BASE:
-		DEBUG( 0, "IrLMP GetInfoBaseDetails not implemented!\n");
+		IRDA_DEBUG(0, "IrLMP GetInfoBaseDetails not implemented!\n");
+		dev_kfree_skb(skb);
 		break;
 	case GET_VALUE_BY_CLASS:
-		DEBUG( 4,"IrLMP GetValueByClass\n");
-		
-		switch(frame[1]) {
+		iriap_do_call_event(self, IAP_RECV_F_LST, NULL);
+			
+		switch (frame[1]) {
 		case IAS_SUCCESS:
 			iriap_getvaluebyclass_confirm(self, skb);
 			break;
 		case IAS_CLASS_UNKNOWN:
-			printk(KERN_WARNING "IrIAP No such class!\n");
+			WARNING(__FUNCTION__ "(), No such class!\n");
 			/* Finished, close connection! */
 			iriap_disconnect_request(self);
 
+			/* 
+			 * Warning, the client might close us, so remember
+			 * no to use self anymore after calling confirm 
+			 */
 			if (self->confirm)
-				self->confirm(IAS_CLASS_UNKNOWN, 0, NULL, 
+				self->confirm(IAS_CLASS_UNKNOWN, 0, NULL,
 					      self->priv);
+			dev_kfree_skb(skb);
 			break;
 		case IAS_ATTRIB_UNKNOWN:
-			printk(KERN_WARNING "IrIAP No such attribute!\n");
+			WARNING(__FUNCTION__ "(), No such attribute!\n");
 		       	/* Finished, close connection! */
 			iriap_disconnect_request(self);
 
+			/* 
+			 * Warning, the client might close us, so remember
+			 * no to use self anymore after calling confirm 
+			 */
 			if (self->confirm)
 				self->confirm(IAS_CLASS_UNKNOWN, 0, NULL, 
 					      self->priv);
+			dev_kfree_skb(skb);
 			break;
-		}
-		iriap_do_call_event( self, IAP_RECV_F_LST, skb);
-
-		/*  
-		 *  We remove LSAPs used by IrIAS as a client since these
-		 *  are more difficult to reuse!  
-		 */
-		iriap_close( self);
+		}		
 		break;
 	default:
-		DEBUG(0, __FUNCTION__ "(), Unknown op-code: %02x\n", opcode);
+		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown op-code: %02x\n", 
+			   opcode);
+		dev_kfree_skb(skb);
 		break;
 	}
 	return 0;
@@ -839,33 +910,34 @@
  *    Received call to server from peer LM-IAS
  *
  */
-void iriap_call_indication( struct iriap_cb *self, struct sk_buff *skb)
+void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb)
 {
 	__u8 *fp;
-	__u8  opcode;
+	__u8 opcode;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
 
 	fp = skb->data;
 
 	opcode = fp[0];
-	if ( ~opcode & 0x80) {
-		printk( KERN_ERR "IrIAS multiframe commands or results is "
-			"not implemented yet!\n");
+	if (~opcode & 0x80) {
+		WARNING(__FUNCTION__ "(), IrIAS multiframe commands or results"
+			"is not implemented yet!\n");
 		return;
 	}
 	opcode &= 0x7f; /* Mask away LST bit */
 	
 	switch (opcode) {
 	case GET_INFO_BASE:
-		DEBUG( 0, "IrLMP GetInfoBaseDetails not implemented!\n");
+		WARNING(__FUNCTION__ 
+			"(), GetInfoBaseDetails not implemented yet!\n");
 		break;
 	case GET_VALUE_BY_CLASS:
-		iriap_getvaluebyclass_indication( self, skb);
+		iriap_getvaluebyclass_indication(self, skb);
 		break;
 	}
 }
@@ -873,18 +945,17 @@
 /*
  * Function iriap_watchdog_timer_expired (data)
  *
- *    
+ *    Query has taken to long time, so abort
  *
  */
-void iriap_watchdog_timer_expired( unsigned long data)
+void iriap_watchdog_timer_expired(void *data)
 {
-	struct iriap_cb *self = ( struct iriap_cb *) data;
+	struct iriap_cb *self = (struct iriap_cb *) data;
 	
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IAS_MAGIC, return;);
 
-	DEBUG(0, __FUNCTION__ "() Timeout! closing myself!\n");
-	iriap_close( self);
+	/* iriap_close(self); */
 }
 
 #ifdef CONFIG_PROC_FS
@@ -909,56 +980,56 @@
 
 	len = 0;
 
-	len += sprintf( buf+len, "LM-IAS Objects:\n");
+	len += sprintf(buf+len, "LM-IAS Objects:\n");
 
 	/* List all objects */
-	obj = (struct ias_object *) hashbin_get_first( objects);
+	obj = (struct ias_object *) hashbin_get_first(objects);
 	while ( obj != NULL) {
-		ASSERT( obj->magic == IAS_OBJECT_MAGIC, return 0;);
+		ASSERT(obj->magic == IAS_OBJECT_MAGIC, return 0;);
 
-		len += sprintf( buf+len, "name: %s, ", obj->name);
-		len += sprintf( buf+len, "id=%d", obj->id);
-		len += sprintf( buf+len, "\n");
+		len += sprintf(buf+len, "name: %s, ", obj->name);
+		len += sprintf(buf+len, "id=%d", obj->id);
+		len += sprintf(buf+len, "\n");
 
 		/* List all attributes for this object */
 		attrib = (struct ias_attrib *) 
-			hashbin_get_first( obj->attribs);
-		while ( attrib != NULL) {
-			ASSERT( attrib->magic == IAS_ATTRIB_MAGIC, return 0;);
-
-			len += sprintf( buf+len, " - Attribute name: \"%s\", ",
- 					attrib->name);
-			len += sprintf( buf+len, "value[%s]: ", 
-					ias_value_types[ attrib->value->type]);
+			hashbin_get_first(obj->attribs);
+		while (attrib != NULL) {
+			ASSERT(attrib->magic == IAS_ATTRIB_MAGIC, return 0;);
+
+			len += sprintf(buf+len, " - Attribute name: \"%s\", ",
+				       attrib->name);
+			len += sprintf(buf+len, "value[%s]: ", 
+				       ias_value_types[attrib->value->type]);
 			
-			switch( attrib->value->type) {
+			switch (attrib->value->type) {
 			case IAS_INTEGER:
-				len += sprintf( buf+len, "%d\n", 
-						attrib->value->t.integer);
+				len += sprintf(buf+len, "%d\n", 
+					       attrib->value->t.integer);
 				break;
 			case IAS_STRING:
-				len += sprintf( buf+len, "\"%s\"\n", 
-						attrib->value->t.string);
+				len += sprintf(buf+len, "\"%s\"\n", 
+					       attrib->value->t.string);
 				break;
 			case IAS_OCT_SEQ:
-				len += sprintf( buf+len, "octet sequence\n");
+				len += sprintf(buf+len, "octet sequence\n");
 				break;
 			case IAS_MISSING:
-				len += sprintf( buf+len, "missing\n");
+				len += sprintf(buf+len, "missing\n");
 				break;
 			default:
-				DEBUG( 0, __FUNCTION__ 
-				       "(), Unknown value type!\n");
+				IRDA_DEBUG(0, __FUNCTION__ 
+				      "(), Unknown value type!\n");
 				return -1;
 			}
-			len += sprintf( buf+len, "\n");
+			len += sprintf(buf+len, "\n");
 			
 			attrib = (struct ias_attrib *) 
 				hashbin_get_next(obj->attribs);
 		}
-	        obj = ( struct ias_object *) hashbin_get_next( objects);
+	        obj = (struct ias_object *) hashbin_get_next(objects);
  	} 
-	restore_flags( flags);
+	restore_flags(flags);
 
 	return len;
 }
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/iriap_event.c linux.15p9/net/irda/iriap_event.c
--- linux.vanilla/net/irda/iriap_event.c	Sat Aug 14 02:26:52 1999
+++ linux.15p9/net/irda/iriap_event.c	Tue Jan 18 01:08:18 2000
@@ -6,10 +6,11 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Aug 21 00:02:07 1997
- * Modified at:   Sun May  9 11:01:47 1999
+ * Modified at:   Sat Dec 25 21:09:47 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>, 
+ *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -27,43 +28,43 @@
 #include <net/irda/iriap.h>
 #include <net/irda/iriap_event.h>
 
-static void state_s_disconnect   ( struct iriap_cb *self, IRIAP_EVENT event, 
-				   struct sk_buff *skb);
-static void state_s_connecting   ( struct iriap_cb *self, IRIAP_EVENT event, 
-				   struct sk_buff *skb);
-static void state_s_call         ( struct iriap_cb *self, IRIAP_EVENT event, 
-				   struct sk_buff *skb);
-
-static void state_s_make_call    ( struct iriap_cb *self, IRIAP_EVENT event, 
-				   struct sk_buff *skb);
-static void state_s_calling      ( struct iriap_cb *self, IRIAP_EVENT event, 
-				   struct sk_buff *skb);
-static void state_s_outstanding  ( struct iriap_cb *self, IRIAP_EVENT event, 
-				   struct sk_buff *skb);
-static void state_s_replying     ( struct iriap_cb *self, IRIAP_EVENT event, 
-				   struct sk_buff *skb);
-static void state_s_wait_for_call( struct iriap_cb *self, IRIAP_EVENT event, 
-				   struct sk_buff *skb);
-static void state_s_wait_active  ( struct iriap_cb *self, IRIAP_EVENT event, 
-				   struct sk_buff *skb);
-
-static void state_r_disconnect   ( struct iriap_cb *self, IRIAP_EVENT event, 
-				   struct sk_buff *skb);
-static void state_r_call         ( struct iriap_cb *self, IRIAP_EVENT event, 
-				   struct sk_buff *skb);
-static void state_r_waiting      ( struct iriap_cb *self, IRIAP_EVENT event, 
-				   struct sk_buff *skb);
-static void state_r_wait_active  ( struct iriap_cb *self, IRIAP_EVENT event, 
-				   struct sk_buff *skb);
-static void state_r_receiving    ( struct iriap_cb *self, IRIAP_EVENT event, 
-				   struct sk_buff *skb);
-static void state_r_execute      ( struct iriap_cb *self, IRIAP_EVENT event, 
-				   struct sk_buff *skb);
-static void state_r_returning    ( struct iriap_cb *self, IRIAP_EVENT event, 
-				   struct sk_buff *skb);
+static void state_s_disconnect   (struct iriap_cb *self, IRIAP_EVENT event, 
+				  struct sk_buff *skb);
+static void state_s_connecting   (struct iriap_cb *self, IRIAP_EVENT event, 
+				  struct sk_buff *skb);
+static void state_s_call         (struct iriap_cb *self, IRIAP_EVENT event, 
+				  struct sk_buff *skb);
+
+static void state_s_make_call    (struct iriap_cb *self, IRIAP_EVENT event, 
+				  struct sk_buff *skb);
+static void state_s_calling      (struct iriap_cb *self, IRIAP_EVENT event, 
+				  struct sk_buff *skb);
+static void state_s_outstanding  (struct iriap_cb *self, IRIAP_EVENT event, 
+				  struct sk_buff *skb);
+static void state_s_replying     (struct iriap_cb *self, IRIAP_EVENT event, 
+				  struct sk_buff *skb);
+static void state_s_wait_for_call(struct iriap_cb *self, IRIAP_EVENT event, 
+				  struct sk_buff *skb);
+static void state_s_wait_active  (struct iriap_cb *self, IRIAP_EVENT event, 
+				  struct sk_buff *skb);
+
+static void state_r_disconnect   (struct iriap_cb *self, IRIAP_EVENT event, 
+				  struct sk_buff *skb);
+static void state_r_call         (struct iriap_cb *self, IRIAP_EVENT event, 
+				  struct sk_buff *skb);
+static void state_r_waiting      (struct iriap_cb *self, IRIAP_EVENT event, 
+				  struct sk_buff *skb);
+static void state_r_wait_active  (struct iriap_cb *self, IRIAP_EVENT event, 
+				  struct sk_buff *skb);
+static void state_r_receiving    (struct iriap_cb *self, IRIAP_EVENT event, 
+				  struct sk_buff *skb);
+static void state_r_execute      (struct iriap_cb *self, IRIAP_EVENT event, 
+				  struct sk_buff *skb);
+static void state_r_returning    (struct iriap_cb *self, IRIAP_EVENT event, 
+				  struct sk_buff *skb);
 
-static void (*iriap_state[])( struct iriap_cb *self, IRIAP_EVENT event, 
-			      struct sk_buff *skb) = { 
+static void (*iriap_state[])(struct iriap_cb *self, IRIAP_EVENT event, 
+			     struct sk_buff *skb) = { 
 	/* Client FSM */
 	state_s_disconnect,
 	state_s_connecting,
@@ -89,89 +90,72 @@
 	state_r_returning,
 };
 
-void iriap_next_client_state( struct iriap_cb *self, IRIAP_STATE state) 
+void iriap_next_client_state(struct iriap_cb *self, IRIAP_STATE state) 
 {
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
 
- 	switch ( state) { 
- /* 	case S_DISCONNECT: DEBUG( 0, "IAP Client = S_DISCONNECT\n"); break;  */
-/*  	case S_CONNECTING: DEBUG( 0, "IAP Client = S_CONNECTING\n"); break;  */
-/*  	case S_CALL:       DEBUG( 0, "IAP Client = S_CALL\n");       break;  */
- 	default: 
- 		break; 
- 	} 
 	self->client_state = state;
 }
 
-void iriap_next_call_state( struct iriap_cb *self, IRIAP_STATE state) 
+void iriap_next_call_state(struct iriap_cb *self, IRIAP_STATE state) 
 {
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
 
-/* 	switch ( state) { */
-/* 	case S_MAKE_CALL:     DEBUG( 0, "IAP Call = S_MAKE_CALL\n"); break; */
-/* 	case S_CALLING:       DEBUG( 0, "IAP Call = S_CALLING\n"); break; */
-/* 	case S_OUTSTANDING:   DEBUG( 0, "IAP Call = S_OUTSTANDING\n");break; */
-/* 	case S_REPLYING:      DEBUG( 0, "IAP Call = S_REPLYING\n"); break; */
-/* 	case S_WAIT_FOR_CALL: DEBUG( 0, "IAP Call = S_WAIT_FOR_CALL\n"); break; */
-/* 	case S_WAIT_ACTIVE:   DEBUG( 0, "IAP Call = S_WAIT_ACTIVE\n"); break; */
-/* 	default: */
-/* 		break; */
-/* 	} */
 	self->call_state = state;
 }
 
-void iriap_next_server_state( struct iriap_cb *self, IRIAP_STATE state)
+void iriap_next_server_state(struct iriap_cb *self, IRIAP_STATE state)
 {
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
 
 	self->server_state = state;
 }
 
-void iriap_next_r_connect_state( struct iriap_cb *self, IRIAP_STATE state)
+void iriap_next_r_connect_state(struct iriap_cb *self, IRIAP_STATE state)
 {
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
 	
 	self->r_connect_state = state;
 }
 
-void iriap_do_client_event( struct iriap_cb *self, IRIAP_EVENT event, 
-			    struct sk_buff *skb) 
+void iriap_do_client_event(struct iriap_cb *self, IRIAP_EVENT event, 
+			   struct sk_buff *skb) 
 {
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
 
-	(*iriap_state[ self->client_state]) ( self, event, skb);
+	(*iriap_state[ self->client_state]) (self, event, skb);
 }
 
-void iriap_do_call_event( struct iriap_cb *self, IRIAP_EVENT event, 
-			  struct sk_buff *skb) 
+void iriap_do_call_event(struct iriap_cb *self, IRIAP_EVENT event, 
+			 struct sk_buff *skb) 
 {
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
 	
-	(*iriap_state[ self->call_state]) ( self, event, skb);
+	(*iriap_state[ self->call_state]) (self, event, skb);
 }
 
-void iriap_do_server_event( struct iriap_cb *self, IRIAP_EVENT event, 
-			    struct sk_buff *skb) 
+void iriap_do_server_event(struct iriap_cb *self, IRIAP_EVENT event, 
+			   struct sk_buff *skb) 
 {
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
 	
-	(*iriap_state[ self->server_state]) ( self, event, skb);
+	(*iriap_state[ self->server_state]) (self, event, skb);
 }
 
-void iriap_do_r_connect_event( struct iriap_cb *self, IRIAP_EVENT event, 
-			       struct sk_buff *skb) 
+void iriap_do_r_connect_event(struct iriap_cb *self, IRIAP_EVENT event, 
+			      struct sk_buff *skb) 
 {
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
 	
-	(*iriap_state[ self->r_connect_state]) ( self, event, skb);
+	(*iriap_state[ self->r_connect_state]) (self, event, skb);
 }
 
 
@@ -181,26 +165,23 @@
  *    S-Disconnect, The device has no LSAP connection to a particular
  *    remote device.
  */
-static void state_s_disconnect( struct iriap_cb *self, IRIAP_EVENT event, 
-				struct sk_buff *skb) 
+static void state_s_disconnect(struct iriap_cb *self, IRIAP_EVENT event, 
+			       struct sk_buff *skb) 
 {
-	int ret;
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
-
-	switch( event) {
+	switch (event) {
 	case IAP_CALL_REQUEST_GVBC:
-		iriap_next_client_state( self, S_CONNECTING);
+		iriap_next_client_state(self, S_CONNECTING);
+		ASSERT(self->skb == NULL, return;);
 		self->skb = skb;
-		ret = irlmp_connect_request( self->lsap, LSAP_IAS, 
-					     self->saddr, self->daddr, 
-					     NULL, NULL);
+		iriap_connect_request(self);
 		break;
 	case IAP_LM_DISCONNECT_INDICATION:
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__"(), Unknown event %d\n", event);
+		IRDA_DEBUG(0, __FUNCTION__"(), Unknown event %d\n", event);
 		break;
 	}
 }
@@ -211,28 +192,28 @@
  *    S-Connecting
  *
  */
-static void state_s_connecting( struct iriap_cb *self, IRIAP_EVENT event, 
-				struct sk_buff *skb) 
+static void state_s_connecting(struct iriap_cb *self, IRIAP_EVENT event, 
+			       struct sk_buff *skb) 
 {
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
 
-	switch( event) {
+	switch (event) {
 	case IAP_LM_CONNECT_CONFIRM:
 		/*
 		 *  Jump to S-Call FSM
 		 */
-		iriap_do_call_event( self, IAP_CALL_REQUEST, skb);
-		/* iriap_call_request( self, 0,0,0); */
-		iriap_next_client_state( self, S_CALL);
+		iriap_do_call_event(self, IAP_CALL_REQUEST, skb);
+		/* iriap_call_request(self, 0,0,0); */
+		iriap_next_client_state(self, S_CALL);
 		break;
 	case IAP_LM_DISCONNECT_INDICATION:
 		/* Abort calls */
-		iriap_next_call_state( self, S_MAKE_CALL);
-		iriap_next_client_state( self, S_DISCONNECT);
+		iriap_next_call_state(self, S_MAKE_CALL);
+		iriap_next_client_state(self, S_DISCONNECT);
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;
 	}
 }
@@ -244,19 +225,19 @@
  *    device. Whenever the LSAP connection is disconnected, this state
  *    catches that event and clears up 
  */
-static void state_s_call( struct iriap_cb *self, IRIAP_EVENT event, 
-			  struct sk_buff *skb) 
+static void state_s_call(struct iriap_cb *self, IRIAP_EVENT event, 
+			 struct sk_buff *skb) 
 {
-	ASSERT( self != NULL, return;);
+	ASSERT(self != NULL, return;);
 
-	switch( event) {
+	switch (event) {
 	case IAP_LM_DISCONNECT_INDICATION:
 		/* Abort calls */
-		iriap_next_call_state( self, S_MAKE_CALL);
-		iriap_next_client_state( self, S_DISCONNECT);
+		iriap_next_call_state(self, S_MAKE_CALL);
+		iriap_next_client_state(self, S_DISCONNECT);
 		break;
 	default:
-		DEBUG( 0, "state_s_call: Unknown event %d\n", event);
+		IRDA_DEBUG(0, "state_s_call: Unknown event %d\n", event);
 		break;
 	}
 }
@@ -267,23 +248,25 @@
  *    S-Make-Call
  *
  */
-static void state_s_make_call( struct iriap_cb *self, IRIAP_EVENT event, 
-			       struct sk_buff *skb) 
+static void state_s_make_call(struct iriap_cb *self, IRIAP_EVENT event, 
+			      struct sk_buff *skb) 
 {
-	ASSERT( self != NULL, return;);
+	ASSERT(self != NULL, return;);
 
-	switch( event) {
+	switch (event) {
 	case IAP_CALL_REQUEST:
-		irlmp_data_request( self->lsap, self->skb);
-		iriap_next_call_state( self, S_OUTSTANDING);
+		skb = self->skb;
+		self->skb = NULL;
+		
+		irlmp_data_request(self->lsap, skb);
+		iriap_next_call_state(self, S_OUTSTANDING);
 		break;
 	default:
-		DEBUG( 0, "state_s_make_call: Unknown event %d\n", event);
+		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %d\n", event);
+		if (skb)
+			dev_kfree_skb(skb);
 		break;
 	}
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
 }
 
 /*
@@ -292,10 +275,10 @@
  *    S-Calling
  *
  */
-static void state_s_calling( struct iriap_cb *self, IRIAP_EVENT event, 
-			     struct sk_buff *skb) 
+static void state_s_calling(struct iriap_cb *self, IRIAP_EVENT event, 
+			    struct sk_buff *skb) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented\n");
+	IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented\n");
 }
 
 /*
@@ -304,21 +287,20 @@
  *    S-Outstanding, The device is waiting for a response to a command
  *
  */
-static void state_s_outstanding( struct iriap_cb *self, IRIAP_EVENT event, 
-				 struct sk_buff *skb) 
+static void state_s_outstanding(struct iriap_cb *self, IRIAP_EVENT event, 
+				struct sk_buff *skb) 
 {
-	ASSERT( self != NULL, return;);
+	ASSERT(self != NULL, return;);
 
-	switch( event) {
+	switch (event) {
 	case IAP_RECV_F_LST:
-		iriap_send_ack( self);
+		iriap_send_ack(self);
 		/*LM_Idle_request(idle); */
 
-		dev_kfree_skb( skb);
-		iriap_next_call_state( self, S_WAIT_FOR_CALL);
+		iriap_next_call_state(self, S_WAIT_FOR_CALL);
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;
 	}		
 }
@@ -328,10 +310,10 @@
  *
  *    S-Replying, The device is collecting a multiple part response
  */
-static void state_s_replying( struct iriap_cb *self, IRIAP_EVENT event, 
-			      struct sk_buff *skb) 
+static void state_s_replying(struct iriap_cb *self, IRIAP_EVENT event, 
+			     struct sk_buff *skb) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented\n");
+	IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented\n");
 }
 
 /*
@@ -340,10 +322,10 @@
  *    S-Wait-for-Call
  *
  */
-static void state_s_wait_for_call( struct iriap_cb *self, IRIAP_EVENT event, 
-				   struct sk_buff *skb) 
+static void state_s_wait_for_call(struct iriap_cb *self, IRIAP_EVENT event, 
+				  struct sk_buff *skb) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented\n");
+	IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented\n");
 }
 
 
@@ -353,10 +335,10 @@
  *    S-Wait-Active
  *
  */
-static void state_s_wait_active( struct iriap_cb *self, IRIAP_EVENT event, 
-				 struct sk_buff *skb) 
+static void state_s_wait_active(struct iriap_cb *self, IRIAP_EVENT event, 
+				struct sk_buff *skb) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented\n");
+	IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented\n");
 }
 
 /**************************************************************************
@@ -371,18 +353,16 @@
  *    LM-IAS server is disconnected (not processing any requests!)
  *
  */
-static void state_r_disconnect( struct iriap_cb *self, IRIAP_EVENT event, 
-				struct sk_buff *skb) 
+static void state_r_disconnect(struct iriap_cb *self, IRIAP_EVENT event, 
+			       struct sk_buff *skb) 
 {
 	struct sk_buff *tx_skb;
 	
-	switch( event) {
+	switch (event) {
 	case IAP_LM_CONNECT_INDICATION:
-		tx_skb = dev_alloc_skb( 64);
-		if ( tx_skb == NULL) {
-			DEBUG( 0,"state_r_disconnect: "
-			       "Could not allocate an sk_buff of length %d\n",
-			       64);
+		tx_skb = dev_alloc_skb(64);
+		if (tx_skb == NULL) {
+			WARNING(__FUNCTION__ "(), unable to malloc!\n");
 			return;
 		}
 
@@ -392,20 +372,20 @@
 		irlmp_connect_response(self->lsap, tx_skb);
 		/*LM_Idle_request(idle); */
 		
-		iriap_next_server_state( self, R_CALL);
+		iriap_next_server_state(self, R_CALL);
 		
 		/*
 		 *  Jump to R-Connect FSM, we skip R-Waiting since we do not
 		 *  care about LM_Idle_request()!
 		 */
-		iriap_next_r_connect_state( self, R_RECEIVING);
+		iriap_next_r_connect_state(self, R_RECEIVING);
 
 		if (skb)
-			dev_kfree_skb( skb);
+			dev_kfree_skb(skb);
 		
 		break;
 	default:
-		DEBUG( 0, "state_r_disconnect: Unknown event %d\n", event);
+		IRDA_DEBUG(0, __FUNCTION__ "(), unknown event %d\n", event);
 		break;
 	}		
 }
@@ -416,20 +396,19 @@
  *    
  *
  */
-static void state_r_call( struct iriap_cb *self, IRIAP_EVENT event, 
-			  struct sk_buff *skb) 
+static void state_r_call(struct iriap_cb *self, IRIAP_EVENT event, 
+			 struct sk_buff *skb) 
 {
-	DEBUG( 4, "state_r_call()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
-	switch( event) {
+	switch (event) {
 	case IAP_LM_DISCONNECT_INDICATION:
 		/* Abort call */
-		iriap_next_server_state( self, R_DISCONNECT);
-		iriap_next_r_connect_state( self, R_WAITING);
-		
+		iriap_next_server_state(self, R_DISCONNECT);
+		iriap_next_r_connect_state(self, R_WAITING);		
 		break;
 	default:
-		DEBUG( 0, "state_r_call, unknown event!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), unknown event!\n");
 		break;
 	}
 }
@@ -444,16 +423,16 @@
  *    
  *
  */
-static void state_r_waiting( struct iriap_cb *self, IRIAP_EVENT event, 
-			     struct sk_buff *skb) 
+static void state_r_waiting(struct iriap_cb *self, IRIAP_EVENT event, 
+			    struct sk_buff *skb) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented\n");
+	IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented\n");
 }
 
-static void state_r_wait_active( struct iriap_cb *self, 
-				 IRIAP_EVENT event, struct sk_buff *skb) 
+static void state_r_wait_active(struct iriap_cb *self, IRIAP_EVENT event, 
+				struct sk_buff *skb) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented\n");
+	IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented\n");
 }
 
 /*
@@ -462,19 +441,19 @@
  *    We are receiving a command
  *
  */
-static void state_r_receiving( struct iriap_cb *self, IRIAP_EVENT event, 
-			       struct sk_buff *skb) 
+static void state_r_receiving(struct iriap_cb *self, IRIAP_EVENT event, 
+			      struct sk_buff *skb) 
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
-	switch( event) {
+	switch (event) {
 	case IAP_RECV_F_LST:
-		iriap_next_r_connect_state( self, R_EXECUTE);
+		iriap_next_r_connect_state(self, R_EXECUTE);
 	 		
-		iriap_call_indication( self, skb);
+		iriap_call_indication(self, skb);
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), unknown event!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), unknown event!\n");
 		break;
 	}
 
@@ -486,40 +465,40 @@
  *    The server is processing the request
  *
  */
-static void state_r_execute( struct iriap_cb *self, IRIAP_EVENT event, 
-			     struct sk_buff *skb) 
+static void state_r_execute(struct iriap_cb *self, IRIAP_EVENT event, 
+			    struct sk_buff *skb) 
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( skb != NULL, return;);
+	ASSERT(skb != NULL, return;);
 	
-	if ( !self || self->magic != IAS_MAGIC) {
-		DEBUG( 0, "state_r_execute: bad pointer self\n");
+	if (!self || self->magic != IAS_MAGIC) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), bad pointer self\n");
 		return;
 	}	
 
-	switch( event) {
+	switch (event) {
 	case IAP_CALL_RESPONSE:
 		/*  
 		 *  Since we don't implement the Waiting state, we return
 		 *  to state Receiving instead, DB.
 		 */
-		iriap_next_r_connect_state( self, R_RECEIVING);
+		iriap_next_r_connect_state(self, R_RECEIVING);
 	 		
-		irlmp_data_request( self->lsap, skb);
+		irlmp_data_request(self->lsap, skb);
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), unknown event!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), unknown event!\n");
 		break;
 	}
 }
 
-static void state_r_returning( struct iriap_cb *self, IRIAP_EVENT event, 
-			       struct sk_buff *skb) 
+static void state_r_returning(struct iriap_cb *self, IRIAP_EVENT event, 
+			      struct sk_buff *skb) 
 {
-	DEBUG( 0, __FUNCTION__ "(), event=%d\n", event);
+	IRDA_DEBUG(0, __FUNCTION__ "(), event=%d\n", event);
 
-	switch( event) {
+	switch (event) {
 	case IAP_RECV_F_LST:
 		
 		break;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irias_object.c linux.15p9/net/irda/irias_object.c
--- linux.vanilla/net/irda/irias_object.c	Sat Aug 14 02:25:47 1999
+++ linux.15p9/net/irda/irias_object.c	Tue Jan 18 01:08:18 2000
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Oct  1 22:50:04 1998
- * Modified at:   Mon Mar 22 13:22:35 1999
+ * Modified at:   Wed Dec 15 11:23:16 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -24,7 +24,6 @@
 
 #include <linux/string.h>
 #include <linux/socket.h>
-#include <linux/irda.h>
 
 #include <net/irda/irda.h>
 #include <net/irda/irmod.h>
@@ -35,9 +34,7 @@
 /*
  *  Used when a missing value needs to be returned
  */
-struct ias_value missing = {
-        IAS_MISSING,	0,	0,	{ 0 }
-};
+struct ias_value missing = { IAS_MISSING, 0, 0, {0}};
 
 /*
  * Function strdup (str)
@@ -45,20 +42,20 @@
  *    My own kernel version of strdup!
  *
  */
-char *strdup( char *str)
+char *strdup(char *str)
 {
 	char *new_str;
 	
-	if ( str == NULL)
+	if (str == NULL)
 		return NULL;
 
-	ASSERT( strlen( str) < 64, return NULL;);
+	ASSERT(strlen( str) < 64, return NULL;);
 	
-        new_str = kmalloc( strlen( str)+1, GFP_ATOMIC);
-        if ( new_str == NULL)
+        new_str = kmalloc(strlen(str)+1, GFP_ATOMIC);
+        if (new_str == NULL)
 		return NULL;
 	
-	strcpy( new_str, str);
+	strcpy(new_str, str);
 	
 	return new_str;
 }
@@ -73,21 +70,21 @@
 {
         struct ias_object *obj;
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG( 4, __FUNCTION__ "()\n");
 
-	obj = (struct ias_object *) kmalloc( sizeof( struct ias_object), 
-					     GFP_ATOMIC);
-	if ( obj == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Unable to allocate object!\n");
+	obj = (struct ias_object *) kmalloc(sizeof(struct ias_object), 
+					    GFP_ATOMIC);
+	if (obj == NULL) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), Unable to allocate object!\n");
 		return NULL;
 	}
-	memset( obj, 0, sizeof( struct ias_object));
+	memset(obj, 0, sizeof( struct ias_object));
 
 	obj->magic = IAS_OBJECT_MAGIC;
 	obj->name = strdup( name);
 	obj->id = id;
 
-	obj->attribs = hashbin_new( HB_LOCAL);
+	obj->attribs = hashbin_new(HB_LOCAL);
 	
 	return obj;
 }
@@ -98,59 +95,56 @@
  *    Delete given attribute and deallocate all its memory
  *
  */
-void __irias_delete_attrib( struct ias_attrib *attrib)
+void __irias_delete_attrib(struct ias_attrib *attrib)
 {
-	ASSERT( attrib != NULL, return;);
-	ASSERT( attrib->magic == IAS_ATTRIB_MAGIC, return;);
+	ASSERT(attrib != NULL, return;);
+	ASSERT(attrib->magic == IAS_ATTRIB_MAGIC, return;);
 
-	if ( attrib->name)
-		kfree( attrib->name);
+	if (attrib->name)
+		kfree(attrib->name);
 
-	irias_delete_value( attrib->value);
+	irias_delete_value(attrib->value);
 	attrib->magic = ~IAS_ATTRIB_MAGIC;
 	
-	kfree( attrib);
+	kfree(attrib);
 }
 
-/*
- * Function irias_delete_object (obj)
- *
- *    Remove object from hashbin and deallocate all attributes assosiated with
- *    with this object and the object itself
- *
- */
-void __irias_delete_object( struct ias_object *obj) 
+void __irias_delete_object(struct ias_object *obj)
 {
-	ASSERT( obj != NULL, return;);
-	ASSERT( obj->magic == IAS_OBJECT_MAGIC, return;);
-	
-	if ( obj->name)
-		kfree( obj->name);
+	ASSERT(obj != NULL, return;);
+	ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
+
+	if (obj->name)
+		kfree(obj->name);
 	
-	hashbin_delete( obj->attribs, (FREE_FUNC) __irias_delete_attrib);
+	hashbin_delete(obj->attribs, (FREE_FUNC) __irias_delete_attrib);
 	
 	obj->magic = ~IAS_OBJECT_MAGIC;
 	
-	kfree( obj);
+	kfree(obj);
 }
 
 /*
- * Function irias_remove_object (obj)
+ * Function irias_delete_object (obj)
  *
- *    Remove object with give name from the LM-IAS object database
+ *    Remove object from hashbin and deallocate all attributes assosiated with
+ *    with this object and the object itself
  *
  */
-void irias_delete_object( char *obj_name)
+int irias_delete_object(struct ias_object *obj) 
 {
-	struct ias_object *obj;
+	struct ias_object *node;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	ASSERT(obj != NULL, return -1;);
+	ASSERT(obj->magic == IAS_OBJECT_MAGIC, return -1;);
 
-	ASSERT( obj_name != NULL, return;);
+	node = hashbin_remove(objects, 0, obj->name);
+	if (!node)
+		return 0; /* Already removed */
 
-	obj = hashbin_remove( objects, 0, obj_name);
+	__irias_delete_object(node);
 
-	__irias_delete_object( obj);
+	return 0;
 }
 
 /*
@@ -159,14 +153,12 @@
  *    Insert an object into the LM-IAS database
  *
  */
-void irias_insert_object( struct ias_object *obj)
+void irias_insert_object(struct ias_object *obj)
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	ASSERT( obj != NULL, return;);
-	ASSERT( obj->magic == IAS_OBJECT_MAGIC, return;);
+	ASSERT(obj != NULL, return;);
+	ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
 	
-	hashbin_insert( objects, (QUEUE *) obj, 0, obj->name);
+	hashbin_insert(objects, (queue_t *) obj, 0, obj->name);
 }
 
 /*
@@ -175,11 +167,11 @@
  *    Find object with given name
  *
  */
-struct ias_object *irias_find_object( char *name)
+struct ias_object *irias_find_object(char *name)
 {
-	ASSERT( name != NULL, return NULL;);
+	ASSERT(name != NULL, return NULL;);
 
-	return hashbin_find( objects, 0, name);
+	return hashbin_find(objects, 0, name);
 }
 
 /*
@@ -188,18 +180,16 @@
  *    Find named attribute in object
  *
  */
-struct ias_attrib *irias_find_attrib( struct ias_object *obj, char *name)
+struct ias_attrib *irias_find_attrib(struct ias_object *obj, char *name)
 {
 	struct ias_attrib *attrib;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	ASSERT(obj != NULL, return NULL;);
+	ASSERT(obj->magic == IAS_OBJECT_MAGIC, return NULL;);
+	ASSERT(name != NULL, return NULL;);
 
-	ASSERT( obj != NULL, return NULL;);
-	ASSERT( obj->magic == IAS_OBJECT_MAGIC, return NULL;);
-	ASSERT( name != NULL, return NULL;);
-
-	attrib = hashbin_find( obj->attribs, 0, name);
-	if ( attrib == NULL)
+	attrib = hashbin_find(obj->attribs, 0, name);
+	if (attrib == NULL)
 		return NULL;
 
 	return attrib;
@@ -213,15 +203,13 @@
  */
 void irias_add_attrib( struct ias_object *obj, struct ias_attrib *attrib)
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	ASSERT( obj != NULL, return;);
-	ASSERT( obj->magic == IAS_OBJECT_MAGIC, return;);
+	ASSERT(obj != NULL, return;);
+	ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
 	
-	ASSERT( attrib != NULL, return;);
-	ASSERT( attrib->magic == IAS_ATTRIB_MAGIC, return;);
+	ASSERT(attrib != NULL, return;);
+	ASSERT(attrib->magic == IAS_ATTRIB_MAGIC, return;);
 
-	hashbin_insert( obj->attribs, (QUEUE *) attrib, 0, attrib->name);
+	hashbin_insert(obj->attribs, (queue_t *) attrib, 0, attrib->name);
 }
 
 /*
@@ -230,36 +218,36 @@
  *    Change the value of an objects attribute.
  *
  */
-int irias_object_change_attribute( char *obj_name, char *attrib_name, 
-				   struct ias_value *new_value) 
+int irias_object_change_attribute(char *obj_name, char *attrib_name, 
+				  struct ias_value *new_value) 
 {
 	struct ias_object *obj;
 	struct ias_attrib *attrib;
 
 	/* Find object */
-	obj = hashbin_find( objects, 0, obj_name);
-	if ( obj == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Unable to find object: %s\n",
-		       obj_name);
+	obj = hashbin_find(objects, 0, obj_name);
+	if (obj == NULL) {
+		WARNING(__FUNCTION__ "(), Unable to find object: %s\n",
+			obj_name);
 		return -1;
 	}
 
 	/* Find attribute */
-	attrib = hashbin_find( obj->attribs, 0, attrib_name);
-	if ( attrib == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Unable to find attribute: %s\n",
-		       attrib_name);
+	attrib = hashbin_find(obj->attribs, 0, attrib_name);
+	if (attrib == NULL) {
+		WARNING(__FUNCTION__ "(), Unable to find attribute: %s\n",
+			attrib_name);
 		return -1;
 	}
-
+	
 	if ( attrib->value->type != new_value->type) {
-		DEBUG( 0, __FUNCTION__ 
+		IRDA_DEBUG( 0, __FUNCTION__ 
 		       "(), changing value type not allowed!\n");
 		return -1;
 	}
 
 	/* Delete old value */
-	irias_delete_value( attrib->value);
+	irias_delete_value(attrib->value);
 	
 	/* Insert new value */
 	attrib->value = new_value;
@@ -274,33 +262,29 @@
  *    Add an integer attribute to an LM-IAS object
  *
  */
-void irias_add_integer_attrib( struct ias_object *obj, char *name, int value)
+void irias_add_integer_attrib(struct ias_object *obj, char *name, int value)
 {
 	struct ias_attrib *attrib;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( obj != NULL, return;);
-	ASSERT( obj->magic == IAS_OBJECT_MAGIC, return;);
-	ASSERT( name != NULL, return;);
-	
-	attrib = (struct ias_attrib *) kmalloc( sizeof( struct ias_attrib), 
-						GFP_ATOMIC);
-	if ( attrib == NULL) {
-		DEBUG( 0, __FUNCTION__ 
-		       "(), Unable to allocate attribute!\n");
+	ASSERT(obj != NULL, return;);
+	ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
+	ASSERT(name != NULL, return;);
+	
+	attrib = (struct ias_attrib *) kmalloc(sizeof(struct ias_attrib), 
+					       GFP_ATOMIC);
+	if (attrib == NULL) {
+		WARNING(__FUNCTION__ "(), Unable to allocate attribute!\n");
 		return;
 	}
-	memset( attrib, 0, sizeof( struct ias_attrib));
+	memset(attrib, 0, sizeof( struct ias_attrib));
 
 	attrib->magic = IAS_ATTRIB_MAGIC;
-	attrib->name = strdup( name);
-/* 	attrib->attr = NULL; */
+	attrib->name = strdup(name);
 
 	/* Insert value */
-	attrib->value = irias_new_integer_value( value);
+	attrib->value = irias_new_integer_value(value);
 	
-	irias_add_attrib( obj, attrib);
+	irias_add_attrib(obj, attrib);
 }
 
  /*
@@ -310,38 +294,32 @@
  *
  */
 
-void irias_add_octseq_attrib( struct ias_object *obj, char *name, 
-			      __u8 *octets, int len)
+void irias_add_octseq_attrib(struct ias_object *obj, char *name, __u8 *octets,
+			     int len)
 {
 	struct ias_attrib *attrib;
 	
-	DEBUG( 0, __FUNCTION__ "()\n");
-	
-	DEBUG( 0, __FUNCTION__ ": name=%s\n", name);
-	DEBUG( 0, __FUNCTION__ ": len=%d\n", len);
+	ASSERT(obj != NULL, return;);
+	ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
 	
-	ASSERT( obj != NULL, return;);
-	ASSERT( obj->magic == IAS_OBJECT_MAGIC, return;);
+	ASSERT(name != NULL, return;);
+	ASSERT(octets != NULL, return;);
 	
-	ASSERT( name != NULL, return;);
-	ASSERT( octets != NULL, return;);
-	ASSERT( len < 55, return;);          /* FIXME: must be 1024, but... */
-	
-	attrib = (struct ias_attrib *) kmalloc( sizeof( struct ias_attrib), 
-						GFP_ATOMIC);
-	if ( attrib == NULL) {
-		DEBUG( 0, __FUNCTION__ 
-		       "(), Unable to allocate attribute!\n");
+	attrib = (struct ias_attrib *) kmalloc(sizeof(struct ias_attrib), 
+					       GFP_ATOMIC);
+	if (attrib == NULL) {
+		WARNING(__FUNCTION__ 
+			"(), Unable to allocate attribute!\n");
 		return;
 	}
-	memset( attrib, 0, sizeof( struct ias_attrib));
+	memset(attrib, 0, sizeof( struct ias_attrib));
 	
 	attrib->magic = IAS_ATTRIB_MAGIC;
 	attrib->name = strdup( name);
 	
 	attrib->value = irias_new_octseq_value( octets, len);
 	
-	irias_add_attrib( obj, attrib);
+	irias_add_attrib(obj, attrib);
 }
 
 /*
@@ -350,36 +328,30 @@
  *    Add a string attribute to an LM-IAS object
  *
  */
-void irias_add_string_attrib( struct ias_object *obj, char *name, char *value)
+void irias_add_string_attrib(struct ias_object *obj, char *name, char *value)
 {
 	struct ias_attrib *attrib;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	ASSERT(obj != NULL, return;);
+	ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
 
-	DEBUG( 4, __FUNCTION__ ": name=%s\n", name);
-	DEBUG( 4, __FUNCTION__ ": name=%s\n", value);
+	ASSERT(name != NULL, return;);
+	ASSERT(value != NULL, return;);
 	
-	ASSERT( obj != NULL, return;);
-	ASSERT( obj->magic == IAS_OBJECT_MAGIC, return;);
-
-	ASSERT( name != NULL, return;);
-	ASSERT( value != NULL, return;);
-	
-	attrib = (struct ias_attrib *) kmalloc( sizeof( struct ias_attrib), 
-						GFP_ATOMIC);
-	if ( attrib == NULL) {
-		DEBUG( 0, __FUNCTION__ 
-		       "(), Unable to allocate attribute!\n");
+	attrib = (struct ias_attrib *) kmalloc(sizeof( struct ias_attrib), 
+					       GFP_ATOMIC);
+	if (attrib == NULL) {
+		WARNING(__FUNCTION__ "(), Unable to allocate attribute!\n");
 		return;
 	}
-	memset( attrib, 0, sizeof( struct ias_attrib));
+	memset(attrib, 0, sizeof( struct ias_attrib));
 
 	attrib->magic = IAS_ATTRIB_MAGIC;
-	attrib->name = strdup( name);
+	attrib->name = strdup(name);
 
-	attrib->value = irias_new_string_value( value);
+	attrib->value = irias_new_string_value(value);
 
-	irias_add_attrib( obj, attrib);
+	irias_add_attrib(obj, attrib);
 }
 
 /*
@@ -388,16 +360,16 @@
  *    Create new IAS integer value
  *
  */
-struct ias_value *irias_new_integer_value( int integer)
+struct ias_value *irias_new_integer_value(int integer)
 {
 	struct ias_value *value;
 
-	value = kmalloc( sizeof( struct ias_value), GFP_ATOMIC);
-	if ( value == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Unable to kmalloc!\n");
+	value = kmalloc(sizeof(struct ias_value), GFP_ATOMIC);
+	if (value == NULL) {
+		WARNING(__FUNCTION__ "(), Unable to kmalloc!\n");
 		return NULL;
 	}
-	memset( value, 0, sizeof( struct ias_value));
+	memset(value, 0, sizeof(struct ias_value));
 
 	value->type = IAS_INTEGER;
 	value->len = 4;
@@ -412,21 +384,21 @@
  *    Create new IAS string value
  *
  */
-struct ias_value *irias_new_string_value( char *string)
+struct ias_value *irias_new_string_value(char *string)
 {
 	struct ias_value *value;
 
-	value = kmalloc( sizeof( struct ias_value), GFP_ATOMIC);
-	if ( value == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Unable to kmalloc!\n");
+	value = kmalloc(sizeof(struct ias_value), GFP_ATOMIC);
+	if (value == NULL) {
+		WARNING(__FUNCTION__ "(), Unable to kmalloc!\n");
 		return NULL;
 	}
 	memset( value, 0, sizeof( struct ias_value));
 
 	value->type = IAS_STRING;
 	value->charset = CS_ASCII;
-	value->len = strlen( string);
-	value->t.string = strdup( string);
+	value->len = strlen(string);
+	value->t.string = strdup(string);
 
 	return value;
 }
@@ -438,63 +410,78 @@
  *    Create new IAS octet-sequence value
  *
  */
-struct ias_value *irias_new_octseq_value( __u8 *octseq , int len)
+struct ias_value *irias_new_octseq_value(__u8 *octseq , int len)
 {
 	struct ias_value *value;
 
-	ASSERT(len <= 55, return NULL;); /*FIXME: must be 1024, but.....*/
-
-	value = kmalloc( sizeof( struct ias_value), GFP_ATOMIC);
-	if ( value == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Unable to kmalloc!\n");
+	value = kmalloc(sizeof(struct ias_value), GFP_ATOMIC);
+	if (value == NULL) {
+		WARNING(__FUNCTION__ "(), Unable to kmalloc!\n");
 		return NULL;
 	}
-	memset( value, 0, sizeof( struct ias_value));
+	memset(value, 0, sizeof(struct ias_value));
 
 	value->type = IAS_OCT_SEQ;
 	value->len = len;
 
 	value->t.oct_seq = kmalloc(len, GFP_ATOMIC);
-	if( value->t.oct_seq == NULL){
-		DEBUG(0, __FUNCTION__"(), Unable to kmalloc!\n");
+	if (value->t.oct_seq == NULL){
+		WARNING(__FUNCTION__"(), Unable to kmalloc!\n");
 		return NULL;
 	}
 	memcpy(value->t.oct_seq, octseq , len);
 	return value;
 }
 
+struct ias_value *irias_new_missing_value(void)
+{
+	struct ias_value *value;
+
+	value = kmalloc(sizeof(struct ias_value), GFP_ATOMIC);
+	if (value == NULL) {
+		WARNING(__FUNCTION__ "(), Unable to kmalloc!\n");
+		return NULL;
+	}
+	memset(value, 0, sizeof(struct ias_value));
+
+	value->type = IAS_MISSING;
+	value->len = 0;
+
+	return value;
+}
+
 /*
  * Function irias_delete_value (value)
  *
  *    Delete IAS value
  *
  */
-void irias_delete_value( struct ias_value *value)
+void irias_delete_value(struct ias_value *value)
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( value != NULL, return;);
+	ASSERT(value != NULL, return;);
 
-	switch( value->type) {
+	switch (value->type) {
 	case IAS_INTEGER: /* Fallthrough */
 	case IAS_MISSING:
 		/* No need to deallocate */
 		break;
 	case IAS_STRING:
 		/* If string, deallocate string */
-		if ( value->t.string != NULL)
-			kfree( value->t.string);
+		if (value->t.string != NULL)
+			kfree(value->t.string);
 		break;
 	case IAS_OCT_SEQ:
 		/* If byte stream, deallocate byte stream */
-		 if ( value->t.oct_seq != NULL)
+		 if (value->t.oct_seq != NULL)
 			 kfree(value->t.oct_seq);
 		 break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown value type!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown value type!\n");
 		break;
 	}
-	kfree( value);
+	kfree(value);
 }
 
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irlan/Config.in linux.15p9/net/irda/irlan/Config.in
--- linux.vanilla/net/irda/irlan/Config.in	Sun Mar  7 23:26:44 1999
+++ linux.15p9/net/irda/irlan/Config.in	Tue Jan 18 01:08:18 2000
@@ -1 +1 @@
-dep_tristate 'IrLAN protocol' CONFIG_IRLAN $CONFIG_IRDA
+dep_tristate '  IrLAN protocol' CONFIG_IRLAN $CONFIG_IRDA
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irlan/irlan_client.c linux.15p9/net/irda/irlan/irlan_client.c
--- linux.vanilla/net/irda/irlan/irlan_client.c	Sat Aug 14 02:26:52 1999
+++ linux.15p9/net/irda/irlan/irlan_client.c	Tue Jan 18 01:08:18 2000
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Mon May 31 14:19:34 1999
+ * Modified at:   Tue Dec 14 15:47:02 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
  *                slip.c by Laurence Culhane, <loz@holmes.demon.co.uk>
@@ -67,11 +67,11 @@
 static void irlan_check_response_param(struct irlan_cb *self, char *param, 
 				       char *value, int val_len);
 
-static void irlan_client_kick_timer_expired(unsigned long data)
+static void irlan_client_kick_timer_expired(void *data)
 {
 	struct irlan_cb *self = (struct irlan_cb *) data;
 	
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -90,10 +90,9 @@
 
 void irlan_client_start_kick_timer(struct irlan_cb *self, int timeout)
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
-	irda_start_timer(&self->client.kick_timer, timeout, 
-			 (unsigned long) self, 
+	irda_start_timer(&self->client.kick_timer, timeout, (void *) self, 
 			 irlan_client_kick_timer_expired);
 }
 
@@ -107,7 +106,7 @@
 {
 	struct irmanager_event mgr_event;
 
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(1, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -166,10 +165,10 @@
  */
 void irlan_client_discovery_indication(discovery_t *discovery) 
 {
-	struct irlan_cb *self, *entry;
+	struct irlan_cb *self;
 	__u32 saddr, daddr;
 	
-	DEBUG(1, __FUNCTION__"()\n");
+	IRDA_DEBUG(1, __FUNCTION__"()\n");
 
 	ASSERT(irlan != NULL, return;);
 	ASSERT(discovery != NULL, return;);
@@ -184,7 +183,7 @@
       	if (self) {
 		ASSERT(self->magic == IRLAN_MAGIC, return;);
 
-		DEBUG(1, __FUNCTION__ "(), Found instance (%08x)!\n",
+		IRDA_DEBUG(1, __FUNCTION__ "(), Found instance (%08x)!\n",
 		      daddr);
 		
 		irlan_client_wakeup(self, saddr, daddr);
@@ -195,7 +194,7 @@
 	/* 
 	 * We have no instance for daddr, so start a new one
 	 */
-	DEBUG(1, __FUNCTION__ "(), starting new instance!\n");
+	IRDA_DEBUG(1, __FUNCTION__ "(), starting new instance!\n");
 	self = irlan_open(saddr, daddr, TRUE);
 
 	/* Restart watchdog timer */
@@ -213,7 +212,7 @@
 {
 	struct irlan_cb *self;
 	
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 	
 	self = (struct irlan_cb *) instance;
 	
@@ -223,7 +222,8 @@
 	
 	irlan_do_client_event(self, IRLAN_DATA_INDICATION, skb); 
 
-	/* Ready for a new command */
+	/* Ready for a new command */	
+	IRDA_DEBUG(2, __FUNCTION__ "(), clearing tx_busy\n");
 	self->client.tx_busy = FALSE;
 
 	/* Check if we have some queued commands waiting to be sent */
@@ -238,8 +238,9 @@
 {
 	struct irlan_cb *self;
 	struct tsap_cb *tsap;
+	struct sk_buff *skb;
 
-	DEBUG(4, __FUNCTION__ "(), reason=%d\n", reason);
+	IRDA_DEBUG(4, __FUNCTION__ "(), reason=%d\n", reason);
 	
 	self = (struct irlan_cb *) instance;
 	tsap = (struct tsap_cb *) sap;
@@ -251,6 +252,12 @@
 	
 	ASSERT(tsap == self->client.tsap_ctrl, return;);
 
+       	/* Remove frames queued on the control channel */
+	while ((skb = skb_dequeue(&self->client.txq))) {
+		dev_kfree_skb(skb);
+	}
+	self->client.tx_busy = FALSE;
+
 	irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
 }
 
@@ -262,10 +269,10 @@
  */
 void irlan_client_open_ctrl_tsap(struct irlan_cb *self)
 {
-	struct notify_t notify;
 	struct tsap_cb *tsap;
+	notify_t notify;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -285,7 +292,7 @@
 	
 	tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);
 	if (!tsap) {
-		DEBUG(2, __FUNCTION__ "(), Got no tsap!\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), Got no tsap!\n");
 		return;
 	}
 	self->client.tsap_ctrl = tsap;
@@ -305,7 +312,7 @@
 {
 	struct irlan_cb *self;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	self = (struct irlan_cb *) instance;
 
@@ -331,7 +338,7 @@
 	struct sk_buff *skb;
 	__u8 *frame;
 		
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -374,7 +381,7 @@
 
 	ASSERT(skb != NULL, return;);	
 	
-	DEBUG(4, __FUNCTION__ "() skb->len=%d\n", (int) skb->len);
+	IRDA_DEBUG(4, __FUNCTION__ "() skb->len=%d\n", (int) skb->len);
 	
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -405,7 +412,7 @@
 	/* How many parameters? */
 	count = frame[1];
 
-	DEBUG(4, __FUNCTION__ "(), got %d parameters\n", count);
+	IRDA_DEBUG(4, __FUNCTION__ "(), got %d parameters\n", count);
 	
 	ptr = frame+2;
 
@@ -413,7 +420,7 @@
  	for (i=0; i<count;i++) {
 		ret = irlan_extract_param(ptr, name, value, &val_len);
 		if (ret < 0) {
-			DEBUG(2, __FUNCTION__ "(), IrLAN, Error!\n");
+			IRDA_DEBUG(2, __FUNCTION__ "(), IrLAN, Error!\n");
 			break;
 		}
 		ptr += ret;
@@ -437,7 +444,7 @@
 	__u8 *bytes;
 	int i;
 
-	DEBUG(4, __FUNCTION__ "(), parm=%s\n", param);
+	IRDA_DEBUG(4, __FUNCTION__ "(), parm=%s\n", param);
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -477,14 +484,14 @@
 		else if (strcmp(value, "HOSTED") == 0)
 			self->client.access_type = ACCESS_HOSTED;
 		else {
-			DEBUG(2, __FUNCTION__ "(), unknown access type!\n");
+			IRDA_DEBUG(2, __FUNCTION__ "(), unknown access type!\n");
 		}
 	}
 	/*
 	 *  IRLAN version
 	 */
 	if (strcmp(param, "IRLAN_VER") == 0) {
-		DEBUG(4, "IrLAN version %d.%d\n", (__u8) value[0], 
+		IRDA_DEBUG(4, "IrLAN version %d.%d\n", (__u8) value[0], 
 		      (__u8) value[1]);
 
 		self->version[0] = value[0];
@@ -496,41 +503,41 @@
 	 */
 	if (strcmp(param, "DATA_CHAN") == 0) {
 		self->dtsap_sel_data = value[0];
-		DEBUG(4, "Data TSAP = %02x\n", self->dtsap_sel_data);
+		IRDA_DEBUG(4, "Data TSAP = %02x\n", self->dtsap_sel_data);
 		return;
 	}
 	if (strcmp(param, "CON_ARB") == 0) {
 		memcpy(&tmp_cpu, value, 2); /* Align value */
 		le16_to_cpus(&tmp_cpu);     /* Convert to host order */
 		self->client.recv_arb_val = tmp_cpu;
-		DEBUG(2, __FUNCTION__ "(), receive arb val=%d\n", 
-		      self->client.recv_arb_val);
+		IRDA_DEBUG(2, __FUNCTION__ "(), receive arb val=%d\n", 
+			   self->client.recv_arb_val);
 	}
 	if (strcmp(param, "MAX_FRAME") == 0) {
 		memcpy(&tmp_cpu, value, 2); /* Align value */
 		le16_to_cpus(&tmp_cpu);     /* Convert to host order */
 		self->client.max_frame = tmp_cpu;
-		DEBUG(4, __FUNCTION__ "(), max frame=%d\n", 
-		      self->client.max_frame);
+		IRDA_DEBUG(4, __FUNCTION__ "(), max frame=%d\n", 
+			   self->client.max_frame);
 	}
 	 
 	/*
 	 *  RECONNECT_KEY, in case the link goes down!
 	 */
 	if (strcmp(param, "RECONNECT_KEY") == 0) {
-		DEBUG(4, "Got reconnect key: ");
+		IRDA_DEBUG(4, "Got reconnect key: ");
 		/* for (i = 0; i < val_len; i++) */
 /* 			printk("%02x", value[i]); */
 		memcpy(self->client.reconnect_key, value, val_len);
 		self->client.key_len = val_len;
-		DEBUG(4, "\n");
+		IRDA_DEBUG(4, "\n");
 	}
 	/*
 	 *  FILTER_ENTRY, have we got an ethernet address?
 	 */
 	if (strcmp(param, "FILTER_ENTRY") == 0) {
 		bytes = value;
-		DEBUG(4, "Ethernet address = %02x:%02x:%02x:%02x:%02x:%02x\n",
+		IRDA_DEBUG(4, "Ethernet address = %02x:%02x:%02x:%02x:%02x:%02x\n",
 		      bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], 
 		      bytes[5]);
 		for (i = 0; i < 6; i++) 
@@ -549,16 +556,20 @@
 {
 	struct irlan_cb *self;
 	
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(priv != NULL, return;);
 
 	self = (struct irlan_cb *) priv;
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
 
+	/* We probably don't need to make any more queries */
+	iriap_close(self->client.iriap);
+	self->client.iriap = NULL;
+
 	/* Check if request succeeded */
 	if (result != IAS_SUCCESS) {
-		DEBUG(2, __FUNCTION__ "(), got NULL value!\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), got NULL value!\n");
 		irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL, 
 				      NULL);
 		return;
@@ -573,18 +584,10 @@
 					      NULL);
 			return;
 		}
-		break;
-	case IAS_STRING:
-		DEBUG(2, __FUNCTION__ "(), got string %s\n", value->t.string);
-		break;
-	case IAS_OCT_SEQ:
-		DEBUG(2, __FUNCTION__ "(), OCT_SEQ not implemented\n");
-		break;
-	case IAS_MISSING:
-		DEBUG(2, __FUNCTION__ "(), MISSING not implemented\n");
+		irias_delete_value(value);
 		break;
 	default:
-		DEBUG(2, __FUNCTION__ "(), unknown type!\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), unknown type!\n");
 		break;
 	}
 	irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL, NULL);
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irlan/irlan_client_event.c linux.15p9/net/irda/irlan/irlan_client_event.c
--- linux.vanilla/net/irda/irlan/irlan_client_event.c	Sat Aug 14 02:26:52 1999
+++ linux.15p9/net/irda/irlan/irlan_client_event.c	Tue Jan 18 01:08:18 2000
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Fri May 14 23:08:15 1999
+ * Modified at:   Sun Dec 26 21:52:24 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -92,26 +92,33 @@
 static int irlan_client_state_idle(struct irlan_cb *self, IRLAN_EVENT event, 
 				   struct sk_buff *skb) 
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == IRLAN_MAGIC, return -1;);
 	
 	switch (event) {
 	case IRLAN_DISCOVERY_INDICATION:
+		if (self->client.iriap) {
+			WARNING(__FUNCTION__ 
+				"(), busy with a previous query\n");
+			return -EBUSY;
+		}
+		
+		self->client.iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,
+						irlan_client_get_value_confirm);
 		/* Get some values from peer IAS */
-		iriap_getvaluebyclass_request(
-			"IrLAN", "IrDA:TinyTP:LsapSel",
-			self->saddr, self->daddr,
-			irlan_client_get_value_confirm, self);
+		iriap_getvaluebyclass_request(self->client.iriap,
+					      self->saddr, self->daddr,
+					      "IrLAN", "IrDA:TinyTP:LsapSel");
 		
 		irlan_next_client_state(self, IRLAN_QUERY);
 		break;
 	case IRLAN_WATCHDOG_TIMEOUT:
-		DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
 		break;
 	default:
-		DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;
 	}
 	if (skb) 
@@ -130,7 +137,7 @@
 static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event, 
 				    struct sk_buff *skb) 
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == IRLAN_MAGIC, return -1;);
@@ -148,7 +155,7 @@
 		irlan_next_client_state(self, IRLAN_CONN);
 		break;
 	case IRLAN_IAS_PROVIDER_NOT_AVAIL:
-		DEBUG(2, __FUNCTION__ "(), IAS_PROVIDER_NOT_AVAIL\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), IAS_PROVIDER_NOT_AVAIL\n");
 		irlan_next_client_state(self, IRLAN_IDLE);
 
 		/* Give the client a kick! */
@@ -161,10 +168,10 @@
 		irlan_next_client_state(self, IRLAN_IDLE);
 		break;
 	case IRLAN_WATCHDOG_TIMEOUT:
-		DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
 		break;
 	default:
-		DEBUG(2, __FUNCTION__"(), Unknown event %d\n", event);
+		IRDA_DEBUG(2, __FUNCTION__"(), Unknown event %d\n", event);
 		break;
 	}
 	if (skb)
@@ -183,11 +190,11 @@
 static int irlan_client_state_conn(struct irlan_cb *self, IRLAN_EVENT event, 
 				   struct sk_buff *skb) 
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	ASSERT(self != NULL, return -1;);
 	
-	switch(event) {
+	switch (event) {
 	case IRLAN_CONNECT_COMPLETE:
 		/* Send getinfo cmd */
 		irlan_get_provider_info(self);
@@ -198,10 +205,10 @@
 		irlan_next_client_state(self, IRLAN_IDLE);
 		break;
 	case IRLAN_WATCHDOG_TIMEOUT:
-		DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
 		break;
 	default:
-		DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;
 	}
 	if (skb)
@@ -218,7 +225,7 @@
 static int irlan_client_state_info(struct irlan_cb *self, IRLAN_EVENT event, 
 				   struct sk_buff *skb) 
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return -1;);
 	
@@ -238,10 +245,10 @@
 		irlan_next_client_state(self, IRLAN_IDLE);
 		break;
 	case IRLAN_WATCHDOG_TIMEOUT:
-		DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
 		break;
 	default:
-		DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;
 	}
 	if (skb)
@@ -260,7 +267,7 @@
 static int irlan_client_state_media(struct irlan_cb *self, IRLAN_EVENT event, 
 				    struct sk_buff *skb) 
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	ASSERT(self != NULL, return -1;);
 
@@ -275,10 +282,10 @@
 		irlan_next_client_state(self, IRLAN_IDLE);
 		break;
 	case IRLAN_WATCHDOG_TIMEOUT:
-		DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
 		break;
 	default:
-		DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;
 	}
 	if (skb)
@@ -299,7 +306,7 @@
 {
 	struct qos_info qos;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	ASSERT(self != NULL, return -1;);
 
@@ -338,7 +345,7 @@
 			irlan_next_client_state(self, IRLAN_DATA);
 			break;
 		default:
-			DEBUG(2, __FUNCTION__ "(), unknown access type!\n");
+			IRDA_DEBUG(2, __FUNCTION__ "(), unknown access type!\n");
 			break;
 		}
 		break;
@@ -347,10 +354,10 @@
 		irlan_next_client_state(self, IRLAN_IDLE);
 		break;
 	case IRLAN_WATCHDOG_TIMEOUT:
-		DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
 		break;
 	default:
-		DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;
 	}
 	
@@ -370,7 +377,7 @@
 static int irlan_client_state_wait(struct irlan_cb *self, IRLAN_EVENT event, 
 				   struct sk_buff *skb) 
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	ASSERT(self != NULL, return -1;);
 	
@@ -384,10 +391,10 @@
 		irlan_next_client_state(self, IRLAN_IDLE);
 		break;
 	case IRLAN_WATCHDOG_TIMEOUT:
-		DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
 		break;
 	default:
-		DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;
 	}
 	if (skb)
@@ -401,7 +408,7 @@
 {
 	struct qos_info qos;
 
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return -1;);
 	
@@ -423,7 +430,7 @@
 		} else if (self->client.recv_arb_val >
 			   self->provider.send_arb_val) 
 		{
-			DEBUG(2, __FUNCTION__ "(), lost the battle :-(\n");
+			IRDA_DEBUG(2, __FUNCTION__ "(), lost the battle :-(\n");
 		}
 		break;
 	case IRLAN_DATA_CONNECT_INDICATION:
@@ -434,10 +441,10 @@
 		irlan_next_client_state(self, IRLAN_IDLE);
 		break;
 	case IRLAN_WATCHDOG_TIMEOUT:
-		DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
 		break;
 	default:
-		DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;
 	}
 	if (skb)
@@ -456,7 +463,7 @@
 static int irlan_client_state_data(struct irlan_cb *self, IRLAN_EVENT event, 
 				   struct sk_buff *skb) 
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == IRLAN_MAGIC, return -1;);
@@ -470,7 +477,7 @@
 		irlan_next_client_state(self, IRLAN_IDLE);
 		break;
 	default:
-		DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;
 	}
 	if (skb)
@@ -488,7 +495,7 @@
 static int irlan_client_state_close(struct irlan_cb *self, IRLAN_EVENT event, 
 				    struct sk_buff *skb) 
 {
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	if (skb)
 		dev_kfree_skb(skb);
@@ -505,7 +512,7 @@
 static int irlan_client_state_sync(struct irlan_cb *self, IRLAN_EVENT event, 
 				   struct sk_buff *skb) 
 {
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 	
 	if (skb)
 		dev_kfree_skb(skb);
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irlan/irlan_common.c linux.15p9/net/irda/irlan/irlan_common.c
--- linux.vanilla/net/irda/irlan/irlan_common.c	Sat Aug 14 02:26:52 1999
+++ linux.15p9/net/irda/irlan/irlan_common.c	Tue Jan 18 01:08:18 2000
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Mon May 31 14:25:19 1999
+ * Modified at:   Sun Dec 26 21:53:10 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -61,7 +61,6 @@
 /* Module parameters */
 static int eth = 0; /* Use "eth" or "irlan" name for devices */
 static int access = ACCESS_PEER; /* PEER, DIRECT or HOSTED */
-static int timeout = IRLAN_TIMEOUT;
 
 static char *irlan_state[] = {
 	"IRLAN_IDLE",
@@ -106,15 +105,15 @@
 /*
  * Function irlan_watchdog_timer_expired (data)
  *
- *    
+ *    Something has gone wrong during the connection establishment
  *
  */
-void irlan_watchdog_timer_expired(unsigned long data)
+void irlan_watchdog_timer_expired(void *data)
 {
 	struct irmanager_event mgr_event;
 	struct irlan_cb *self;
 	
-	DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
 	self = (struct irlan_cb *) data;
 
@@ -123,7 +122,8 @@
 
 	/* Check if device still configured */
 	if (self->dev.start) {
-		DEBUG(0, __FUNCTION__ "(), notifying irmanager to stop irlan!\n");
+		IRDA_DEBUG(0, __FUNCTION__ 
+		      "(), notifying irmanager to stop irlan!\n");
 		mgr_event.event = EVENT_IRLAN_STOP;
 		sprintf(mgr_event.devname, "%s", self->ifname);
 		irmanager_notify(&mgr_event);
@@ -136,13 +136,8 @@
 		 */
 		self->notify_irmanager = FALSE;
 	} else {
-		DEBUG(0, __FUNCTION__ "(), closing instance!\n");
-		if (self->netdev_registered) {
-			DEBUG(0, __FUNCTION__ "(), removing netdev!\n");
-			unregister_netdev(&self->dev);
-			self->netdev_registered = FALSE;
-		}
-		irlan_close(self);
+		IRDA_DEBUG(0, __FUNCTION__ "(), closing instance!\n");
+		/*irlan_close(self);*/
 	}
 }
 
@@ -154,9 +149,9 @@
  */
 void irlan_start_watchdog_timer(struct irlan_cb *self, int timeout)
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
-	irda_start_timer(&self->watchdog_timer, timeout, (unsigned long) self,
+	irda_start_timer(&self->watchdog_timer, timeout, (void *) self,
 			 irlan_watchdog_timer_expired);
 }
 
@@ -166,14 +161,14 @@
  *    Initialize IrLAN layer
  *
  */
-__initfunc(int irlan_init(void))
+int __init irlan_init(void)
 {
 	struct irlan_cb *new;
 	__u16 hints;
 
-	DEBUG(4, __FUNCTION__"()\n");
+	IRDA_DEBUG(4, __FUNCTION__"()\n");
 
-	/* Allocate master array */
+	/* Allocate master structure */
 	irlan = hashbin_new(HB_LOCAL); 
 	if (irlan == NULL) {
 		printk(KERN_WARNING "IrLAN: Can't allocate hashbin!\n");
@@ -183,7 +178,7 @@
 	create_proc_entry("irlan", 0, proc_irda)->get_info = irlan_proc_read;
 #endif /* CONFIG_PROC_FS */
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	hints = irlmp_service_to_hint(S_LAN);
 
@@ -209,7 +204,7 @@
 
 void irlan_cleanup(void) 
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	irlmp_unregister_client(ckey);
 
@@ -234,19 +229,19 @@
 {
 	int i=0;
 
-	DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
 	/* Check if we should call the device eth<x> or irlan<x> */
 	if (!eth) {
 		/* Get the first free irlan<x> name */
 		do {
 			sprintf(self->ifname, "%s%d", "irlan", i++);
-		} while (dev_get(self->ifname) != NULL);
+		} while (dev_get(self->ifname));
 	}
 	self->dev.name = self->ifname;
 	
 	if (register_netdev(&self->dev) != 0) {
-		DEBUG(2, __FUNCTION__ "(), register_netdev() failed!\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), register_netdev() failed!\n");
 		return -1;
 	}
 	self->netdev_registered = TRUE;
@@ -264,7 +259,7 @@
 {
 	struct irlan_cb *self;
 
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	/* 
 	 *  Initialize the irlan structure. 
@@ -300,7 +295,7 @@
 	init_timer(&self->watchdog_timer);
 	init_timer(&self->client.kick_timer);
 
-	hashbin_insert(irlan, (QUEUE *) self, daddr, NULL);
+	hashbin_insert(irlan, (queue_t *) self, daddr, NULL);
 	
 	skb_queue_head_init(&self->client.txq);
 	
@@ -323,7 +318,9 @@
  */
 static void __irlan_close(struct irlan_cb *self)
 {
-	DEBUG(2, __FUNCTION__ "()\n");
+	struct sk_buff *skb;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 	
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -333,6 +330,14 @@
 
 	/* Close all open connections and remove TSAPs */
 	irlan_close_tsaps(self);
+	
+	if (self->client.iriap) 
+		iriap_close(self->client.iriap);
+
+	/* Remove frames queued on the control channel */
+	while ((skb = skb_dequeue(&self->client.txq))) {
+		dev_kfree_skb(skb);
+	}
 
 	if (self->netdev_registered) {
 		unregister_netdev(&self->dev);
@@ -352,22 +357,22 @@
 void irlan_close(struct irlan_cb *self)
 {
 	struct irlan_cb *entry;
-	
-	DEBUG(0, __FUNCTION__ "()\n");
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
         ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
 
 	/* Check if device is still configured */
 	if (self->dev.start) {
-		DEBUG(0, __FUNCTION__ 
+		IRDA_DEBUG(0, __FUNCTION__ 
 		       "(), Device still configured, closing later!\n");
 
 		/* Give it a chance to reconnect */
 		irlan_start_watchdog_timer(self, IRLAN_TIMEOUT);
 		return;
 	}
-	DEBUG(2, __FUNCTION__ "(), daddr=%08x\n", self->daddr);
+	IRDA_DEBUG(2, __FUNCTION__ "(), daddr=%08x\n", self->daddr);
 	entry = hashbin_remove(irlan, self->daddr, NULL);
 
 	ASSERT(entry == self, return;);
@@ -388,7 +393,7 @@
 	struct irlan_cb *self;
 	struct tsap_cb *tsap;
 
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 	
 	self = (struct irlan_cb *) instance;
 	tsap = (struct tsap_cb *) sap;
@@ -400,7 +405,7 @@
 	self->max_sdu_size = max_sdu_size;
 	self->max_header_size = max_header_size;
 
-	DEBUG(0, "IrLAN, We are now connected!\n");
+	IRDA_DEBUG(0, "IrLAN, We are now connected!\n");
 
 	del_timer(&self->watchdog_timer);
 
@@ -435,7 +440,7 @@
 
 	/* TODO: we could set the MTU depending on the max_sdu_size */
 
-	DEBUG(2, "IrLAN, We are now connected!\n");
+	IRDA_DEBUG(2, "IrLAN, We are now connected!\n");
 	del_timer(&self->watchdog_timer);
 
 	/* 
@@ -467,7 +472,7 @@
 	struct irlan_cb *self;
 	struct tsap_cb *tsap;
 
-	DEBUG(0, __FUNCTION__ "(), reason=%d\n", reason);
+	IRDA_DEBUG(0, __FUNCTION__ "(), reason=%d\n", reason);
 	
 	self = (struct irlan_cb *) instance;
 	tsap = (struct tsap_cb *) sap;
@@ -479,7 +484,7 @@
 	
 	ASSERT(tsap == self->tsap_data, return;);
 
-	DEBUG(2, "IrLAN, data channel disconnected by peer!\n");
+	IRDA_DEBUG(2, "IrLAN, data channel disconnected by peer!\n");
 
 	switch(reason) {
 	case LM_USER_REQUEST: /* User request */
@@ -489,13 +494,13 @@
 		irlan_start_watchdog_timer(self, IRLAN_TIMEOUT);
 		break;
 	case LM_CONNECT_FAILURE: /* Failed to establish IrLAP connection */
-		DEBUG(2, __FUNCTION__ "(), LM_CONNECT_FAILURE not impl\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), LM_CONNECT_FAILURE not impl\n");
 		break;
 	case LM_LAP_RESET:  /* IrLAP reset */
-		DEBUG(2, __FUNCTION__ "(), LM_CONNECT_FAILURE not impl\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), LM_CONNECT_FAILURE not impl\n");
 		break;
 	case LM_INIT_DISCONNECT:
-		DEBUG(2, __FUNCTION__ "(), LM_CONNECT_FAILURE not impl\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), LM_CONNECT_FAILURE not impl\n");
 		break;
 	default:
 		break;
@@ -507,10 +512,10 @@
 
 void irlan_open_data_tsap(struct irlan_cb *self)
 {
-	struct notify_t notify;
 	struct tsap_cb *tsap;
+	notify_t notify;
 
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -532,7 +537,7 @@
 
 	tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);
 	if (!tsap) {
-		DEBUG(2, __FUNCTION__ "(), Got no tsap!\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), Got no tsap!\n");
 		return;
 	}
 	self->tsap_data = tsap;
@@ -546,7 +551,7 @@
 
 void irlan_close_tsaps(struct irlan_cb *self)
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -612,7 +617,7 @@
 		irias_add_string_attrib(obj, "DeviceID", "HWP19F0");
 		irias_add_integer_attrib(obj, "CompCnt", 1);
 		if (self->provider.access_type == ACCESS_PEER)
-			irias_add_string_attrib(obj, "Comp#02", "PNP8389");
+			irias_add_string_attrib(obj, "Comp#01", "PNP8389");
 		else
 			irias_add_string_attrib(obj, "Comp#01", "PNP8294");
 
@@ -631,6 +636,8 @@
 {
 	struct sk_buff *skb;
 
+	IRDA_DEBUG(3, __FUNCTION__ "()\n");
+
 	if (irda_lock(&self->client.tx_busy) == FALSE)
 		return -EBUSY;
 
@@ -639,11 +646,16 @@
 		self->client.tx_busy = FALSE;
 		return 0;
 	}
-	if (self->client.tsap_ctrl == NULL) {
+	
+	/* Check that it's really possible to send commands */
+	if ((self->client.tsap_ctrl == NULL) || 
+	    (self->client.state == IRLAN_IDLE)) 
+	{
 		self->client.tx_busy = FALSE;
 		dev_kfree_skb(skb);
 		return -1;
 	}
+	IRDA_DEBUG(3, __FUNCTION__ "(), sending ...\n");
 
 	return irttp_data_request(self->client.tsap_ctrl, skb);
 }
@@ -656,6 +668,8 @@
  */
 void irlan_ctrl_data_request(struct irlan_cb *self, struct sk_buff *skb)
 {
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
 	/* Queue command */
 	skb_queue_tail(&self->client.txq, skb);
 
@@ -674,7 +688,7 @@
 	struct sk_buff *skb;
 	__u8 *frame;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -692,7 +706,6 @@
  	frame[0] = CMD_GET_PROVIDER_INFO;
 	frame[1] = 0x00;                 /* Zero parameters */
 	
-	/* irttp_data_request(self->client.tsap_ctrl, skb); */
 	irlan_ctrl_data_request(self, skb);
 }
 
@@ -707,7 +720,7 @@
 	struct sk_buff *skb;
 	__u8 *frame;
 	
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -740,7 +753,7 @@
 	struct sk_buff *skb;
 	__u8 *frame;
 	
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -764,7 +777,6 @@
 
 	irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
 
-	/* irttp_data_request(self->client.tsap_ctrl, skb); */
 	irlan_ctrl_data_request(self, skb);
 }
 
@@ -780,7 +792,7 @@
 	struct sk_buff *skb;
 	__u8 *frame;
 	
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLAN_MAGIC, return;);	
@@ -819,7 +831,7 @@
 	struct sk_buff *skb;
 	__u8 *frame;
 	
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -859,7 +871,7 @@
 	struct sk_buff *skb;
 	__u8 *frame;
 	
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -900,7 +912,7 @@
 	struct sk_buff *skb;
 	__u8 *frame;
 		
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -936,7 +948,7 @@
 	struct sk_buff *skb;
 	__u8 *frame;
 	
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -1023,7 +1035,7 @@
 	int n=0;
 	
 	if (skb == NULL) {
-		DEBUG(2, __FUNCTION__ "(), Got NULL skb\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), Got NULL skb\n");
 		return 0;
 	}	
 
@@ -1040,7 +1052,7 @@
 		ASSERT(value_len > 0, return 0;);
 		break;
 	default:
-		DEBUG(2, __FUNCTION__ "(), Unknown parameter type!\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), Unknown parameter type!\n");
 		return 0;
 		break;
 	}
@@ -1050,7 +1062,7 @@
 
 	/* Make space for data */
 	if (skb_tailroom(skb) < (param_len+value_len+3)) {
-		DEBUG(2, __FUNCTION__ "(), No more space at end of skb\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), No more space at end of skb\n");
 		return 0;
 	}	
 	skb_put(skb, param_len+value_len+3);
@@ -1097,13 +1109,13 @@
 	__u16 val_len;
 	int n=0;
 	
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	/* get length of parameter name (1 byte) */
 	name_len = buf[n++];
 	
 	if (name_len > 254) {
-		DEBUG(2, __FUNCTION__ "(), name_len > 254\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), name_len > 254\n");
 		return -RSP_INVALID_COMMAND_FORMAT;
 	}
 	
@@ -1120,7 +1132,7 @@
 	le16_to_cpus(&val_len); n+=2;
 	
 	if (val_len > 1016) {
-		DEBUG(2, __FUNCTION__ "(), parameter length to long\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), parameter length to long\n");
 		return -RSP_INVALID_COMMAND_FORMAT;
 	}
 	*len = val_len;
@@ -1130,8 +1142,8 @@
 	value[val_len] = '\0';
 	n+=val_len;
 	
-	DEBUG(4, "Parameter: %s ", name); 
-	DEBUG(4, "Value: %s\n", value); 
+	IRDA_DEBUG(4, "Parameter: %s ", name); 
+	IRDA_DEBUG(4, "Value: %s\n", value); 
 
 	return n;
 }
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irlan/irlan_eth.c linux.15p9/net/irda/irlan/irlan_eth.c
--- linux.vanilla/net/irda/irlan/irlan_eth.c	Tue Jan  4 21:19:03 2000
+++ linux.15p9/net/irda/irlan/irlan_eth.c	Tue Jan 18 01:08:18 2000
@@ -6,13 +6,13 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Oct 15 08:37:58 1998
- * Modified at:   Mon May 31 19:57:08 1999
+ * Modified at:   Sun Jan 16 22:43:41 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
  *                slip.c by Laurence Culhane,   <loz@holmes.demon.co.uk>
  *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
  * 
- *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1998-2000 Dag Brattli, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -50,7 +50,7 @@
 	struct irmanager_event mgr_event;
 	struct irlan_cb *self;
 
-	DEBUG(2, __FUNCTION__"()\n");
+	IRDA_DEBUG(2, __FUNCTION__"()\n");
 
 	ASSERT(dev != NULL, return -1;);
        
@@ -115,7 +115,7 @@
 {
 	struct irlan_cb *self;
 	
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	ASSERT(dev != NULL, return -1;);
 
@@ -150,7 +150,7 @@
 {
 	struct irlan_cb *self = (struct irlan_cb *) dev->priv;
 
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 	
 	/* Stop device */
 	dev->tbusy = 1;
@@ -253,9 +253,6 @@
 
 	self = (struct irlan_cb *) instance;
 
-	ASSERT(self != NULL, return 0;);
-	ASSERT(self->magic == IRLAN_MAGIC, return 0;);
-
 	if (skb == NULL) {
 		++self->stats.rx_dropped; 
 		return 0;
@@ -282,7 +279,9 @@
  * Function irlan_eth_flow (status)
  *
  *    Do flow control between IP/Ethernet and IrLAN/IrTTP. This is done by 
- *    controlling the dev->tbusy variable.
+ *    controlling the dev->tbusy variable. Currently not used, since we
+ *    just drop the frames instead of asking the client layer to buffer 
+ *    them.
  */
 void irlan_eth_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
 {
@@ -345,8 +344,8 @@
 	 * is useful if we have changed access points on the same
 	 * subnet.  
 	 */
-#ifdef CONFIG_INET	 
-	DEBUG(4, "IrLAN: Sending gratuitous ARP\n");
+#ifdef CONFIG_INET
+	IRDA_DEBUG(4, "IrLAN: Sending gratuitous ARP\n");
 	in_dev = dev->ip_ptr;
 	arp_send(ARPOP_REQUEST, ETH_P_ARP, 
 		 in_dev->ifa_list->ifa_address,
@@ -369,14 +368,14 @@
 
  	self = dev->priv; 
 
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
  	ASSERT(self != NULL, return;); 
  	ASSERT(self->magic == IRLAN_MAGIC, return;);
 
 	/* Check if data channel has been connected yet */
 	if (self->client.state != IRLAN_DATA) {
-		DEBUG(1, __FUNCTION__ "(), delaying!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), delaying!\n");
 		return;
 	}
 
@@ -386,20 +385,20 @@
 	} 
 	else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > HW_MAX_ADDRS) {
 		/* Disable promiscuous mode, use normal mode. */
-		DEBUG(4, __FUNCTION__ "(), Setting multicast filter\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), Setting multicast filter\n");
 		/* hardware_set_filter(NULL); */
 
 		irlan_set_multicast_filter(self, TRUE);
 	}
 	else if (dev->mc_count) {
-		DEBUG(4, __FUNCTION__ "(), Setting multicast filter\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), Setting multicast filter\n");
 		/* Walk the address list, and load the filter */
 		/* hardware_set_filter(dev->mc_list); */
 
 		irlan_set_multicast_filter(self, TRUE);
 	}
 	else {
-		DEBUG(4, __FUNCTION__ "(), Clearing multicast filter\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), Clearing multicast filter\n");
 		irlan_set_multicast_filter(self, FALSE);
 	}
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irlan/irlan_event.c linux.15p9/net/irda/irlan/irlan_event.c
--- linux.vanilla/net/irda/irlan/irlan_event.c	Sat Aug 14 02:26:52 1999
+++ linux.15p9/net/irda/irlan/irlan_event.c	Tue Jan 18 01:08:18 2000
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Oct 20 09:10:16 1998
- * Modified at:   Sun May  9 21:17:44 1999
+ * Modified at:   Sat Oct 30 12:59:01 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -40,7 +40,7 @@
 
 void irlan_next_client_state(struct irlan_cb *self, IRLAN_STATE state) 
 {
-	DEBUG(2, __FUNCTION__"(), %s\n", irlan_state[state]);
+	IRDA_DEBUG(2, __FUNCTION__"(), %s\n", irlan_state[state]);
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -50,7 +50,7 @@
 
 void irlan_next_provider_state(struct irlan_cb *self, IRLAN_STATE state) 
 {
-	DEBUG(2, __FUNCTION__"(), %s\n", irlan_state[state]);
+	IRDA_DEBUG(2, __FUNCTION__"(), %s\n", irlan_state[state]);
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irlan/irlan_filter.c linux.15p9/net/irda/irlan/irlan_filter.c
--- linux.vanilla/net/irda/irlan/irlan_filter.c	Sat Aug 14 02:26:52 1999
+++ linux.15p9/net/irda/irlan/irlan_filter.c	Tue Jan 18 01:08:18 2000
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Fri Jan 29 11:16:38 1999
- * Modified at:   Fri May 14 23:11:01 1999
+ * Modified at:   Sat Oct 30 12:58:45 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -41,7 +41,7 @@
 	if ((self->provider.filter_type == IRLAN_DIRECTED) && 
 	    (self->provider.filter_operation == DYNAMIC))
 	{
-		DEBUG(0, "Giving peer a dynamic Ethernet address\n");
+		IRDA_DEBUG(0, "Giving peer a dynamic Ethernet address\n");
 		self->provider.mac_address[0] = 0x40;
 		self->provider.mac_address[1] = 0x00;
 		self->provider.mac_address[2] = 0x00;
@@ -71,7 +71,7 @@
 	if ((self->provider.filter_type == IRLAN_DIRECTED) && 
 	    (self->provider.filter_mode == FILTER))
 	{
-		DEBUG(0, "Directed filter on\n");
+		IRDA_DEBUG(0, "Directed filter on\n");
 		skb->data[0] = 0x00; /* Success */
 		skb->data[1] = 0x00;
 		return;
@@ -79,7 +79,7 @@
 	if ((self->provider.filter_type == IRLAN_DIRECTED) && 
 	    (self->provider.filter_mode == NONE))
 	{
-		DEBUG(0, "Directed filter off\n");
+		IRDA_DEBUG(0, "Directed filter off\n");
 		skb->data[0] = 0x00; /* Success */
 		skb->data[1] = 0x00;
 		return;
@@ -88,7 +88,7 @@
 	if ((self->provider.filter_type == IRLAN_BROADCAST) && 
 	    (self->provider.filter_mode == FILTER))
 	{
-		DEBUG(0, "Broadcast filter on\n");
+		IRDA_DEBUG(0, "Broadcast filter on\n");
 		skb->data[0] = 0x00; /* Success */
 		skb->data[1] = 0x00;
 		return;
@@ -96,7 +96,7 @@
 	if ((self->provider.filter_type == IRLAN_BROADCAST) && 
 	    (self->provider.filter_mode == NONE))
 	{
-		DEBUG(0, "Broadcast filter off\n");
+		IRDA_DEBUG(0, "Broadcast filter off\n");
 		skb->data[0] = 0x00; /* Success */
 		skb->data[1] = 0x00;
 		return;
@@ -104,7 +104,7 @@
 	if ((self->provider.filter_type == IRLAN_MULTICAST) && 
 	    (self->provider.filter_mode == FILTER))
 	{
-		DEBUG(0, "Multicast filter on\n");
+		IRDA_DEBUG(0, "Multicast filter on\n");
 		skb->data[0] = 0x00; /* Success */
 		skb->data[1] = 0x00;
 		return;
@@ -112,7 +112,7 @@
 	if ((self->provider.filter_type == IRLAN_MULTICAST) && 
 	    (self->provider.filter_mode == NONE))
 	{
-		DEBUG(0, "Multicast filter off\n");
+		IRDA_DEBUG(0, "Multicast filter off\n");
 		skb->data[0] = 0x00; /* Success */
 		skb->data[1] = 0x00;
 		return;
@@ -120,7 +120,7 @@
 	if ((self->provider.filter_type == IRLAN_MULTICAST) && 
 	    (self->provider.filter_operation == GET))
 	{
-		DEBUG(0, "Multicast filter get\n");
+		IRDA_DEBUG(0, "Multicast filter get\n");
 		skb->data[0] = 0x00; /* Success? */
 		skb->data[1] = 0x02;
 		irlan_insert_string_param(skb, "FILTER_MODE", "NONE");
@@ -130,7 +130,7 @@
 	skb->data[0] = 0x00; /* Command not supported */
 	skb->data[1] = 0x00;
 
-	DEBUG(0, "Not implemented!\n");
+	IRDA_DEBUG(0, "Not implemented!\n");
 }
 
 /*
@@ -143,20 +143,20 @@
 {
 	__u8 *bytes;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	bytes = value;
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
 
-	DEBUG(4, "%s, %s\n", param, value);
+	IRDA_DEBUG(4, "%s, %s\n", param, value);
 
 	/*
 	 *  This is experimental!! DB.
 	 */
 	 if (strcmp(param, "MODE") == 0) {
-		DEBUG(0, __FUNCTION__ "()\n");
+		IRDA_DEBUG(0, __FUNCTION__ "()\n");
 		self->use_udata = TRUE;
 		return;
 	}
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irlan/irlan_provider.c linux.15p9/net/irda/irlan/irlan_provider.c
--- linux.vanilla/net/irda/irlan/irlan_provider.c	Sat Aug 14 02:26:52 1999
+++ linux.15p9/net/irda/irlan/irlan_provider.c	Tue Jan 18 01:08:18 2000
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Sun May  9 12:22:56 1999
+ * Modified at:   Sat Oct 30 12:52:10 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
  *                slip.c by Laurence Culhane,   <loz@holmes.demon.co.uk>
@@ -70,7 +70,7 @@
 	struct irlan_cb *self;
 	__u8 code;
 	
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	self = (struct irlan_cb *) instance;
 
@@ -82,32 +82,32 @@
 	code = skb->data[0];
 	switch(code) {
 	case CMD_GET_PROVIDER_INFO:
-		DEBUG(4, "Got GET_PROVIDER_INFO command!\n");
+		IRDA_DEBUG(4, "Got GET_PROVIDER_INFO command!\n");
 		irlan_do_provider_event(self, IRLAN_GET_INFO_CMD, skb); 
 		break;
 
 	case CMD_GET_MEDIA_CHAR:
-		DEBUG(4, "Got GET_MEDIA_CHAR command!\n");
+		IRDA_DEBUG(4, "Got GET_MEDIA_CHAR command!\n");
 		irlan_do_provider_event(self, IRLAN_GET_MEDIA_CMD, skb); 
 		break;
 	case CMD_OPEN_DATA_CHANNEL:
-		DEBUG(4, "Got OPEN_DATA_CHANNEL command!\n");
+		IRDA_DEBUG(4, "Got OPEN_DATA_CHANNEL command!\n");
 		irlan_do_provider_event(self, IRLAN_OPEN_DATA_CMD, skb); 
 		break;
 	case CMD_FILTER_OPERATION:
-		DEBUG(4, "Got FILTER_OPERATION command!\n");
+		IRDA_DEBUG(4, "Got FILTER_OPERATION command!\n");
 		irlan_do_provider_event(self, IRLAN_FILTER_CONFIG_CMD, skb);
 		break;
 	case CMD_RECONNECT_DATA_CHAN:
-		DEBUG(2, __FUNCTION__"(), Got RECONNECT_DATA_CHAN command\n");
-		DEBUG(2, __FUNCTION__"(), NOT IMPLEMENTED\n");
+		IRDA_DEBUG(2, __FUNCTION__"(), Got RECONNECT_DATA_CHAN command\n");
+		IRDA_DEBUG(2, __FUNCTION__"(), NOT IMPLEMENTED\n");
 		break;
 	case CMD_CLOSE_DATA_CHAN:
-		DEBUG(2, "Got CLOSE_DATA_CHAN command!\n");
-		DEBUG(2, __FUNCTION__"(), NOT IMPLEMENTED\n");
+		IRDA_DEBUG(2, "Got CLOSE_DATA_CHAN command!\n");
+		IRDA_DEBUG(2, __FUNCTION__"(), NOT IMPLEMENTED\n");
 		break;
 	default:
-		DEBUG(2, __FUNCTION__ "(), Unknown command!\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), Unknown command!\n");
 		break;
 	}
 	return 0;
@@ -129,7 +129,7 @@
 	struct tsap_cb *tsap;
 	__u32 saddr, daddr;
 
-	DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 	
 	self = (struct irlan_cb *) instance;
 	tsap = (struct tsap_cb *) sap;
@@ -150,11 +150,11 @@
 	new = (struct irlan_cb *) hashbin_find(irlan, daddr, NULL);
       	if (new) {
 		ASSERT(new->magic == IRLAN_MAGIC, return;);
-		DEBUG(0, __FUNCTION__ "(), found instance!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), found instance!\n");
 
 		/* Update saddr, since client may have moved to a new link */
 		new->saddr = saddr;
-		DEBUG(2, __FUNCTION__ "(), saddr=%08x\n", new->saddr);
+		IRDA_DEBUG(2, __FUNCTION__ "(), saddr=%08x\n", new->saddr);
 
 		/* Make sure that any old provider control TSAP is removed */
 		if ((new != self) && new->provider.tsap_ctrl) {
@@ -165,7 +165,7 @@
 		}
 	} else {
 		/* This must be the master instance, so start a new instance */
-		DEBUG(0, __FUNCTION__ "(), starting new provider!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), starting new provider!\n");
 
 		new = irlan_open(saddr, daddr, TRUE); 
 	}
@@ -182,7 +182,7 @@
 		new->provider.tsap_ctrl = irttp_dup(self->provider.tsap_ctrl, 
 						    new);
 		if (!new->provider.tsap_ctrl) {
-			DEBUG(0, __FUNCTION__ "(), dup failed!\n");
+			IRDA_DEBUG(0, __FUNCTION__ "(), dup failed!\n");
 			return;
 		}
 		
@@ -245,7 +245,7 @@
 	struct irlan_cb *self;
 	struct tsap_cb *tsap;
 
-	DEBUG(4, __FUNCTION__ "(), reason=%d\n", reason);
+	IRDA_DEBUG(4, __FUNCTION__ "(), reason=%d\n", reason);
 	
 	self = (struct irlan_cb *) instance;
 	tsap = (struct tsap_cb *) sap;
@@ -299,7 +299,7 @@
 	
 	ASSERT(skb != NULL, return -RSP_PROTOCOL_ERROR;);
 	
-	DEBUG(4, __FUNCTION__ "(), skb->len=%d\n", (int)skb->len);
+	IRDA_DEBUG(4, __FUNCTION__ "(), skb->len=%d\n", (int)skb->len);
 
 	ASSERT(self != NULL, return -RSP_PROTOCOL_ERROR;);
 	ASSERT(self->magic == IRLAN_MAGIC, return -RSP_PROTOCOL_ERROR;);
@@ -321,7 +321,7 @@
 	/* How many parameters? */
 	count = frame[1];
 
-	DEBUG(4, "Got %d parameters\n", count);
+	IRDA_DEBUG(4, "Got %d parameters\n", count);
 	
 	ptr = frame+2;
 	
@@ -329,7 +329,7 @@
  	for (i=0; i<count;i++) {
 		ret = irlan_extract_param(ptr, name, value, &val_len);
 		if (ret < 0) {
-			DEBUG(2, __FUNCTION__ "(), IrLAN, Error!\n");
+			IRDA_DEBUG(2, __FUNCTION__ "(), IrLAN, Error!\n");
 			break;
 		}
 		ptr+=ret;
@@ -354,7 +354,7 @@
 {
 	struct sk_buff *skb;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -379,7 +379,7 @@
 			irlan_insert_string_param(skb, "MEDIA", "802.5");
 			break;
 		default:
-			DEBUG(2, __FUNCTION__ "(), unknown media type!\n");
+			IRDA_DEBUG(2, __FUNCTION__ "(), unknown media type!\n");
 			break;
 		}
 		irlan_insert_short_param(skb, "IRLAN_VER", 0x0101);
@@ -403,7 +403,7 @@
 			irlan_insert_string_param(skb, "ACCESS_TYPE", "HOSTED");
 			break;
 		default:
-			DEBUG(2, __FUNCTION__ "(), Unknown access type\n");
+			IRDA_DEBUG(2, __FUNCTION__ "(), Unknown access type\n");
 			break;
 		}
 		irlan_insert_short_param(skb, "MAX_FRAME", 0x05ee);
@@ -424,7 +424,7 @@
 		handle_filter_request(self, skb);
 		break;
 	default:
-		DEBUG(2, __FUNCTION__ "(), Unknown command!\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), Unknown command!\n");
 		break;
 	}
 
@@ -439,10 +439,10 @@
  */
 int irlan_provider_open_ctrl_tsap(struct irlan_cb *self)
 {
-	struct notify_t notify;
 	struct tsap_cb *tsap;
+	notify_t notify;
 	
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == IRLAN_MAGIC, return -1;);
@@ -463,7 +463,7 @@
 
 	tsap = irttp_open_tsap(LSAP_ANY, 1, &notify);
 	if (!tsap) {
-		DEBUG(2, __FUNCTION__ "(), Got no tsap!\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), Got no tsap!\n");
 		return -1;
 	}
 	self->provider.tsap_ctrl = tsap;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irlan/irlan_provider_event.c linux.15p9/net/irda/irlan/irlan_provider_event.c
--- linux.vanilla/net/irda/irlan/irlan_provider_event.c	Sat Aug 14 02:26:52 1999
+++ linux.15p9/net/irda/irlan/irlan_provider_event.c	Tue Jan 18 01:08:18 2000
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Fri May  7 10:53:58 1999
+ * Modified at:   Sat Oct 30 12:52:41 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -72,7 +72,7 @@
 static int irlan_provider_state_idle(struct irlan_cb *self, IRLAN_EVENT event,
 				     struct sk_buff *skb)
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	ASSERT(self != NULL, return -1;);
 	
@@ -82,7 +82,7 @@
 	     irlan_next_provider_state( self, IRLAN_INFO);
 	     break;
 	default:
-		DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;
 	}
 	if (skb)
@@ -101,7 +101,7 @@
 {
 	int ret;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	ASSERT(self != NULL, return -1;);
 
@@ -147,7 +147,7 @@
 		irlan_next_provider_state(self, IRLAN_IDLE);
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;
 	}
 	if (skb)
@@ -166,7 +166,7 @@
 static int irlan_provider_state_open(struct irlan_cb *self, IRLAN_EVENT event, 
 				     struct sk_buff *skb)
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return -1;);
 
@@ -186,7 +186,7 @@
 		irlan_next_provider_state(self, IRLAN_IDLE);
 		break;
 	default:
-		DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;
 	}
 	if (skb)
@@ -205,7 +205,7 @@
 static int irlan_provider_state_data(struct irlan_cb *self, IRLAN_EVENT event, 
 				     struct sk_buff *skb) 
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == IRLAN_MAGIC, return -1;);
@@ -221,7 +221,7 @@
 		irlan_next_provider_state(self, IRLAN_IDLE);
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;
 	}
 	if (skb)
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irlap.c linux.15p9/net/irda/irlap.c
--- linux.vanilla/net/irda/irlap.c	Sat Aug 14 02:26:52 1999
+++ linux.15p9/net/irda/irlap.c	Tue Jan 18 01:08:18 2000
@@ -6,7 +6,7 @@
  * Status:        Stable
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Mon May 31 21:43:55 1999
+ * Modified at:   Tue Dec 14 09:26:44 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -69,19 +69,20 @@
 
 #endif /* CONFIG_PROC_FS */
 
-__initfunc(int irlap_init(void))
+int __init irlap_init(void)
 {
 	/* Allocate master array */
 	irlap = hashbin_new(HB_LOCAL);
 	if (irlap == NULL) {
-		printk(KERN_WARNING "IrLAP: Can't allocate irlap hashbin!\n");
+	        ERROR(__FUNCTION__ "(), can't allocate irlap hashbin!\n");
 		return -ENOMEM;
 	}
 
 #ifdef CONFIG_IRDA_COMPRESSION
 	irlap_compressors = hashbin_new(HB_LOCAL);
 	if (irlap_compressors == NULL) {
-		printk(KERN_WARNING "IrLAP: Can't allocate compressors hashbin!\n");
+		WARNING(__FUNCTION__ 
+			"(), can't allocate compressors hashbin!\n");
 		return -ENOMEM;
 	}
 #endif
@@ -106,15 +107,12 @@
  *    Initialize IrLAP layer
  *
  */
-struct irlap_cb *irlap_open(struct irda_device *irdev)
+struct irlap_cb *irlap_open(struct device *dev, struct qos_info *qos)
 {
 	struct irlap_cb *self;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
-	ASSERT(irdev != NULL, return NULL;);
-	ASSERT(irdev->magic == IRDA_DEVICE_MAGIC, return NULL;);
-
 	/* Initialize the irlap structure. */
 	self = kmalloc(sizeof(struct irlap_cb), GFP_KERNEL);
 	if (self == NULL)
@@ -124,26 +122,22 @@
 	self->magic = LAP_MAGIC;
 
 	/* Make a binding between the layers */
-	self->irdev = irdev;
-	self->netdev = &irdev->netdev;
+	self->netdev = dev;
+	self->qos_dev = qos;
+
+	/* FIXME: should we get our own field? */
+	dev->atalk_ptr = self;
 
 	irlap_next_state(self, LAP_OFFLINE);
 
-	/* Initialize transmitt queue */
-	skb_queue_head_init(&self->tx_list);
+	/* Initialize transmit queue */
+	skb_queue_head_init(&self->txq);
+	skb_queue_head_init(&self->txq_ultra);
 	skb_queue_head_init(&self->wx_list);
 
 	/* My unique IrLAP device address! */
 	get_random_bytes(&self->saddr, sizeof(self->saddr));
-
-	/* 
-	 * Generate random connection address for this session, which must
-	 * be 7 bits wide and different from 0x00 and 0xfe 
-	 */
-	while ((self->caddr == 0x00) || (self->caddr == 0xfe)) {
-		get_random_bytes(&self->caddr, sizeof(self->caddr));
-		self->caddr &= 0xfe;
-	}
+	memcpy(dev->dev_addr, &self->saddr, 4);
 
 	init_timer(&self->slot_timer);
 	init_timer(&self->query_timer);
@@ -152,12 +146,15 @@
 	init_timer(&self->poll_timer);
 	init_timer(&self->wd_timer);
 	init_timer(&self->backoff_timer);
+	init_timer(&self->media_busy_timer);	
 
 	irlap_apply_default_connection_parameters(self);
+
+	self->N3 = 3; /* # connections attemts to try before giving up */
 	
 	irlap_next_state(self, LAP_NDM);
 
-	hashbin_insert(irlap, (QUEUE *) self, self->saddr, NULL);
+	hashbin_insert(irlap, (queue_t *) self, self->saddr, NULL);
 
 	irlmp_register_link(self, self->saddr, &self->notify);
 	
@@ -183,10 +180,10 @@
 	del_timer(&self->poll_timer);
 	del_timer(&self->wd_timer);
 	del_timer(&self->backoff_timer);
+	del_timer(&self->media_busy_timer);
 
 	irlap_flush_all_queues(self);
        
-	self->irdev = NULL;
 	self->magic = 0;
 	
 	kfree(self);
@@ -202,7 +199,7 @@
 {
 	struct irlap_cb *lap;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -215,7 +212,7 @@
 	/* Be sure that we manage to remove ourself from the hash */
 	lap = hashbin_remove(irlap, self->saddr, NULL);
 	if (!lap) {
-		DEBUG(1, __FUNCTION__ "(), Didn't find myself!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), Didn't find myself!\n");
 		return;
 	}
 	__irlap_close(lap);
@@ -229,7 +226,7 @@
  */
 void irlap_connect_indication(struct irlap_cb *self, struct sk_buff *skb) 
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -248,7 +245,7 @@
  */
 void irlap_connect_response(struct irlap_cb *self, struct sk_buff *skb) 
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	irlap_do_event(self, CONNECT_RESPONSE, skb, NULL);
 }
@@ -263,7 +260,7 @@
 void irlap_connect_request(struct irlap_cb *self, __u32 daddr, 
 			   struct qos_info *qos_user, int sniff) 
 {
-	DEBUG(3, __FUNCTION__ "(), daddr=0x%08x\n", daddr);
+	IRDA_DEBUG(3, __FUNCTION__ "(), daddr=0x%08x\n", daddr);
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -276,8 +273,7 @@
 	 */
 	irlap_init_qos_capabilities(self, qos_user);
 	
-	if ((self->state == LAP_NDM) && 
-	    !irda_device_is_media_busy(self->irdev))
+	if ((self->state == LAP_NDM) && !self->media_busy)
 		irlap_do_event(self, CONNECT_REQUEST, NULL, NULL);
 	else
 		self->connect_pending = TRUE;
@@ -291,7 +287,7 @@
  */
 void irlap_connect_confirm(struct irlap_cb *self, struct sk_buff *skb)
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -306,7 +302,8 @@
  *    IrLMP for further processing
  *
  */
-inline void irlap_data_indication(struct irlap_cb *self, struct sk_buff *skb) 
+void irlap_data_indication(struct irlap_cb *self, struct sk_buff *skb,
+			   int unreliable) 
 {
 	/* Hide LAP header from IrLMP layer */
 	skb_pull(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
@@ -315,43 +312,14 @@
 	if (self->qos_tx.compression.value) {
 		skb = irlap_decompress_frame(self, skb);
 		if (!skb) {
-			DEBUG(1, __FUNCTION__ "(), Decompress error!\n");
+			IRDA_DEBUG(1, __FUNCTION__ "(), Decompress error!\n");
 			return;
 		}
 	}
 #endif
-	irlmp_link_data_indication(self->notify.instance, LAP_RELIABLE, skb);
+	irlmp_link_data_indication(self->notify.instance, skb, unreliable);
 }
 
-/*
- * Function irlap_unit_data_indication (self, skb)
- *
- *    Received some data that was sent unreliable
- *
- */
-void irlap_unit_data_indication(struct irlap_cb *self, struct sk_buff *skb)
-{
-	DEBUG(1, __FUNCTION__ "()\n"); 
-
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == LAP_MAGIC, return;);
-	ASSERT(skb != NULL, return;);
-
-	/* Hide LAP header from IrLMP layer */
-	skb_pull(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
-
-#ifdef CONFIG_IRDA_COMPRESSION
-	if (self->qos_tx.compression.value) {
-		
-		skb = irlap_decompress_frame(self, skb);
-		if (!skb) {
-			DEBUG(1, __FUNCTION__ "(), Decompress error!\n");
-			return;
-		}
-	}
-#endif
-	irlmp_link_data_indication(self->notify.instance, LAP_UNRELIABLE, skb);
-}
 
 /*
  * Function irlap_data_request (self, skb)
@@ -359,23 +327,23 @@
  *    Queue data for transmission, must wait until XMIT state
  *
  */
-inline void irlap_data_request(struct irlap_cb *self, struct sk_buff *skb,
-				int reliable)
+void irlap_data_request(struct irlap_cb *self, struct sk_buff *skb, 
+			int unreliable)
 {
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
-	ASSERT(skb != NULL, return;);
+
+	IRDA_DEBUG(3, __FUNCTION__ "()\n");
 
 #ifdef CONFIG_IRDA_COMPRESSION
 	if (self->qos_tx.compression.value) {
 		skb = irlap_compress_frame(self, skb);
 		if (!skb) {
-			DEBUG(1, __FUNCTION__ "(), Compress error!\n");
+			IRDA_DEBUG(1, __FUNCTION__ "(), Compress error!\n");
 			return;
 		}
 	}
 #endif
-	
 	ASSERT(skb_headroom(skb) >= (LAP_ADDR_HEADER+LAP_CTRL_HEADER), 
 	       return;);
 	skb_push(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
@@ -384,12 +352,10 @@
 	 *  Must set frame format now so that the rest of the code knows 
 	 *  if its dealing with an I or an UI frame
 	 */
-	if (reliable)
-		skb->data[1] = I_FRAME;
-	else {
-		DEBUG(4, __FUNCTION__ "(), queueing unreliable frame\n");
+	if (unreliable)
 		skb->data[1] = UI_FRAME;
-	}
+	else
+		skb->data[1] = I_FRAME;
 
 	/* 
 	 *  Send event if this frame only if we are in the right state 
@@ -400,16 +366,65 @@
 		 *  Check if the transmit queue contains some unsent frames,
 		 *  and if so, make sure they are sent first
 		 */
-		if (!skb_queue_empty(&self->tx_list)) {
-			skb_queue_tail(&self->tx_list, skb);
-			skb = skb_dequeue(&self->tx_list);
+		if (!skb_queue_empty(&self->txq)) {
+			skb_queue_tail(&self->txq, skb);
+			skb = skb_dequeue(&self->txq);
 			
 			ASSERT(skb != NULL, return;);
 		}
 		irlap_do_event(self, SEND_I_CMD, skb, NULL);
 	} else
-		skb_queue_tail(&self->tx_list, skb);	
+		skb_queue_tail(&self->txq, skb);
+}
+
+/*
+ * Function irlap_unitdata_request (self, skb)
+ *
+ *    Send Ultra data. This is data that must be sent outside any connection
+ *
+ */
+#ifdef CONFIG_IRDA_ULTRA
+void irlap_unitdata_request(struct irlap_cb *self, struct sk_buff *skb)
+{
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
+
+	IRDA_DEBUG(3, __FUNCTION__ "()\n");
+
+	ASSERT(skb_headroom(skb) >= (LAP_ADDR_HEADER+LAP_CTRL_HEADER), 
+	       return;);
+	skb_push(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
+
+	skb->data[0] = CBROADCAST;
+	skb->data[1] = UI_FRAME;
+
+	skb_queue_tail(&self->txq_ultra, skb);
+
+	irlap_do_event(self, SEND_UI_FRAME, NULL, NULL);
 }
+#endif /*CONFIG_IRDA_ULTRA */
+
+/*
+ * Function irlap_udata_indication (self, skb)
+ *
+ *    Receive Ultra data. This is data that is received outside any connection
+ *
+ */
+#ifdef CONFIG_IRDA_ULTRA
+void irlap_unitdata_indication(struct irlap_cb *self, struct sk_buff *skb)
+{
+	IRDA_DEBUG(1, __FUNCTION__ "()\n"); 
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
+
+	/* Hide LAP header from IrLMP layer */
+	skb_pull(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
+
+	irlmp_link_unitdata_indication(self->notify.instance, skb);
+}
+#endif /* CONFIG_IRDA_ULTRA */
 
 /*
  * Function irlap_disconnect_request (void)
@@ -418,11 +433,19 @@
  */
 void irlap_disconnect_request(struct irlap_cb *self) 
 {
-	DEBUG(3, __FUNCTION__ "()\n");
+	IRDA_DEBUG(3, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
 	
+	/* Don't disconnect until all data frames are successfully sent */
+	if (skb_queue_len(&self->txq) > 0) {
+		self->disconnect_pending = TRUE;
+		
+		return;
+	}
+
+	/* Check if we are in the right state for disconnecting */
 	switch (self->state) {
 	case LAP_XMIT_P:        /* FALLTROUGH */
 	case LAP_XMIT_S:        /* FALLTROUGH */
@@ -432,7 +455,7 @@
 		irlap_do_event(self, DISCONNECT_REQUEST, NULL, NULL);
 		break;
 	default:
-		DEBUG(0, __FUNCTION__ "(), disconnect pending!\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), disconnect pending!\n");
 		self->disconnect_pending = TRUE;
 		break;
 	}
@@ -446,7 +469,7 @@
  */
 void irlap_disconnect_indication(struct irlap_cb *self, LAP_REASON reason) 
 {
-	DEBUG(1, __FUNCTION__ "(), reason=%s\n", lap_reasons[reason]); 
+	IRDA_DEBUG(1, __FUNCTION__ "(), reason=%s\n", lap_reasons[reason]); 
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -457,21 +480,20 @@
 	/* Flush queues */
 	irlap_flush_all_queues(self);
 	
-	switch(reason) {
+	switch (reason) {
 	case LAP_RESET_INDICATION:
-		DEBUG(1, __FUNCTION__ "(), Sending reset request!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), Sending reset request!\n");
 		irlap_do_event(self, RESET_REQUEST, NULL, NULL);
 		break;
 	case LAP_NO_RESPONSE:	   /* FALLTROUGH */	
 	case LAP_DISC_INDICATION:  /* FALLTROUGH */
 	case LAP_FOUND_NONE:       /* FALLTROUGH */
 	case LAP_MEDIA_BUSY:
-		irlmp_link_disconnect_indication(self->notify.instance, 
-						  self, reason, NULL);
+		irlmp_link_disconnect_indication(self->notify.instance, self, 
+						 reason, NULL);
 		break;
 	default:
-		DEBUG(1, __FUNCTION__ "(), Reason %d not implemented!\n", 
-		       reason);
+		ERROR(__FUNCTION__ "(), Unknown reason %d\n", reason);
 	}
 }
 
@@ -489,49 +511,53 @@
 	ASSERT(self->magic == LAP_MAGIC, return;);
 	ASSERT(discovery != NULL, return;);
 	
-	DEBUG(4, __FUNCTION__ "(), nslots = %d\n", discovery->nslots);
+	IRDA_DEBUG(4, __FUNCTION__ "(), nslots = %d\n", discovery->nslots);
 
 	ASSERT((discovery->nslots == 1) || (discovery->nslots == 6) ||
 	       (discovery->nslots == 8) || (discovery->nslots == 16), 
 	       return;);
 	
-  	/*
-	 *  Discovery is only possible in NDM mode
-	 */ 
-	if (self->state == LAP_NDM) {
-		ASSERT(self->discovery_log == NULL, return;);
-		self->discovery_log= hashbin_new(HB_LOCAL);
-		
-		info.S = discovery->nslots; /* Number of slots */
-		info.s = 0; /* Current slot */
-		
-		self->discovery_cmd = discovery;
-		info.discovery = discovery;
-		
-		/* Check if the slot timeout is within limits */
-		if (sysctl_slot_timeout < 20) {
-			ERROR(__FUNCTION__ 
-			      "(), to low value for slot timeout!\n");
-			sysctl_slot_timeout = 20;
-		}
-		/* 
-		 * Highest value is actually 8, but we allow higher since
-		 * some devices seems to require it.
-		 */
-		if (sysctl_slot_timeout > 160) {
-			ERROR(__FUNCTION__ 
-			      "(), to high value for slot timeout!\n");
-			sysctl_slot_timeout = 160;
-		}
-
-		self->slot_timeout = sysctl_slot_timeout * HZ / 1000;
-		
-		irlap_do_event(self, DISCOVERY_REQUEST, NULL, &info);
-	} else { 
- 		DEBUG(4, __FUNCTION__ 
-		       "(), discovery only possible in NDM mode\n");
+  	/* Discovery is only possible in NDM mode */
+	if (self->state != LAP_NDM) {
+		IRDA_DEBUG(4, __FUNCTION__ 
+			   "(), discovery only possible in NDM mode\n");
 		irlap_discovery_confirm(self, NULL);
- 	} 
+		return;
+	}
+
+	/* Check if last discovery request finished in time */
+	if (self->discovery_log != NULL) {
+		hashbin_delete(self->discovery_log, (FREE_FUNC) kfree);
+		self->discovery_log = NULL;
+	}
+	
+	self->discovery_log= hashbin_new(HB_LOCAL);
+	
+	info.S = discovery->nslots; /* Number of slots */
+	info.s = 0; /* Current slot */
+	
+	self->discovery_cmd = discovery;
+	info.discovery = discovery;
+	
+	/* Check if the slot timeout is within limits */
+	if (sysctl_slot_timeout < 20) {
+		ERROR(__FUNCTION__ 
+		      "(), to low value for slot timeout!\n");
+		sysctl_slot_timeout = 20;
+	}
+	/* 
+	 * Highest value is actually 8, but we allow higher since
+	 * some devices seems to require it.
+	 */
+	if (sysctl_slot_timeout > 160) {
+		ERROR(__FUNCTION__ 
+		      "(), to high value for slot timeout!\n");
+		sysctl_slot_timeout = 160;
+	}
+	
+	self->slot_timeout = sysctl_slot_timeout * HZ / 1000;
+	
+	irlap_do_event(self, DISCOVERY_REQUEST, NULL, &info);
 }
 
 /*
@@ -552,16 +578,11 @@
 	 * the media busy condition (irlap p.94). This should allow us to make 
 	 * connection attempts much easier.
 	 */
-	if (discovery_log && hashbin_get_size(discovery_log) > 0)
-		irda_device_set_media_busy(self->irdev, FALSE);
+	if (discovery_log && HASHBIN_GET_SIZE(discovery_log) > 0)
+		irda_device_set_media_busy(self->netdev, FALSE);
 	
 	/* Inform IrLMP */
 	irlmp_link_discovery_confirm(self->notify.instance, discovery_log);
-	
-	/* 
-	 *  IrLMP has now the responsibilities for the discovery_log 
-	 */
-	self->discovery_log = NULL;
 }
 
 /*
@@ -572,7 +593,7 @@
  */
 void irlap_discovery_indication(struct irlap_cb *self, discovery_t *discovery) 
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -591,12 +612,12 @@
  */
 void irlap_status_indication(int quality_of_link) 
 {
-	switch(quality_of_link) {
+	switch (quality_of_link) {
 	case STATUS_NO_ACTIVITY:
-		printk(KERN_INFO "IrLAP, no activity on link!\n");
+		MESSAGE("IrLAP, no activity on link!\n");
 		break;
 	case STATUS_NOISY:
-		printk(KERN_INFO "IrLAP, noisy link!\n");
+		MESSAGE("IrLAP, noisy link!\n");
 		break;
 	default:
 		break;
@@ -612,7 +633,7 @@
  */
 void irlap_reset_indication(struct irlap_cb *self)
 {
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(1, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -631,7 +652,7 @@
  */
 void irlap_reset_confirm(void)
 {
- 	DEBUG(1, __FUNCTION__ "()\n");
+ 	IRDA_DEBUG(1, __FUNCTION__ "()\n");
 }
 
 /*
@@ -666,16 +687,10 @@
 	struct sk_buff *skb = NULL;
 	int count = 0;
 
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == LAP_MAGIC, return;);
-
 	/*
          * Remove all the ack-ed frames from the window queue.
          */
 
-	DEBUG(4, "--> wx_list=%d, va=%d, nr=%d\n", 
-	       skb_queue_len(&self->wx_list), self->va, nr);
-
 	/* 
 	 *  Optimize for the common case. It is most likely that the receiver
 	 *  will acknowledge all the frames we have sent! So in that case we
@@ -683,7 +698,7 @@
 	 */
 	if (nr == self->vs) {
 		while ((skb = skb_dequeue(&self->wx_list)) != NULL) {
-		     dev_kfree_skb(skb);
+			dev_kfree_skb(skb);
 		}
 		/* The last acked frame is the next to send minus one */
 		self->va = nr - 1;
@@ -698,10 +713,6 @@
 			self->va = (self->va + 1) % 8;
 			count++;
 		}
-		
-		DEBUG(4, "irlap_update_nr_received(), removed %d\n", count);
-		DEBUG(4, "wx_list=%d, va=%d, nr=%d -->\n", 
-		       skb_queue_len(&self->wx_list), self->va, nr);
 	}
 	
 	/* Advance window */
@@ -715,20 +726,15 @@
  */
 int irlap_validate_ns_received(struct irlap_cb *self, int ns) 
 {
-	ASSERT(self != NULL, return -ENODEV;);
-	ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
-
 	/*  ns as expected?  */
-	if (ns == self->vr) {
-		DEBUG(4, __FUNCTION__ "(), expected!\n");
+	if (ns == self->vr)
 		return NS_EXPECTED;
-	}
 	/*
 	 *  Stations are allowed to treat invalid NS as unexpected NS
 	 *  IrLAP, Recv ... with-invalid-Ns. p. 84
 	 */
 	return NS_UNEXPECTED;
-
+	
 	/* return NR_INVALID; */
 }
 /*
@@ -739,12 +745,9 @@
  */
 int irlap_validate_nr_received(struct irlap_cb *self, int nr) 
 {
-	ASSERT(self != NULL, return -ENODEV;);
-	ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
-
 	/*  nr as expected?  */
 	if (nr == self->vs) {
-		DEBUG(4, __FUNCTION__ "(), expected!\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), expected!\n");
 		return NR_EXPECTED;
 	}
 
@@ -772,7 +775,7 @@
  */
 void irlap_initiate_connection_state(struct irlap_cb *self) 
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -799,17 +802,16 @@
  */
 void irlap_wait_min_turn_around(struct irlap_cb *self, struct qos_info *qos) 
 {
-	int usecs;
-	int speed;
-	int bytes ;
+	__u32 min_turn_time;
+	__u32 speed;
 	
 	/* Get QoS values.  */
 	speed = qos->baud_rate.value;
-	usecs = qos->min_turn_time.value;
+	min_turn_time = qos->min_turn_time.value;
 
 	/* No need to calculate XBOFs for speeds over 115200 bps */
 	if (speed > 115200) {
-		self->mtt_required = usecs;
+		self->mtt_required = min_turn_time;
 		return;
 	}
 	
@@ -818,9 +820,7 @@
 	 *  min turn time, so now we must calculate how many chars (XBOF's) we 
 	 *  must send for the requested time period (min turn time)
 	 */
-	bytes = speed * usecs / 10000000;
-
-	self->xbofs_delay = bytes;
+	self->xbofs_delay = irlap_min_turn_time_in_bytes(speed, min_turn_time);
 }
 
 /*
@@ -837,9 +837,12 @@
 	ASSERT(self->magic == LAP_MAGIC, return;);
 
 	/* Free transmission queue */
-	while ((skb = skb_dequeue(&self->tx_list)) != NULL)
+	while ((skb = skb_dequeue(&self->txq)) != NULL)
 		dev_kfree_skb(skb);
 	
+	while ((skb = skb_dequeue(&self->txq_ultra)) != NULL)
+		dev_kfree_skb(skb);
+
 	/* Free sliding window buffered packets */
 	while ((skb = skb_dequeue(&self->wx_list)) != NULL)
 		dev_kfree_skb(skb);
@@ -858,22 +861,18 @@
  *    Change the speed of the IrDA port
  *
  */
-void irlap_change_speed(struct irlap_cb *self, int speed)
+void irlap_change_speed(struct irlap_cb *self, __u32 speed, int now)
 {
-	DEBUG(4, __FUNCTION__ "(), setting speed to %d\n", speed);
+	IRDA_DEBUG(0, __FUNCTION__ "(), setting speed to %d\n", speed);
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
 
-	if (!self->irdev) {
-		DEBUG(1, __FUNCTION__ "(), driver missing!\n");
-		return;
-	}
-
-	irda_device_change_speed(self->irdev, speed);
+	self->speed = speed;
 
-	self->qos_rx.baud_rate.value = speed;
-	self->qos_tx.baud_rate.value = speed;
+	/* Change speed now, or just piggyback speed on frames */
+	if (now)
+		irda_device_change_speed(self->netdev, speed);
 }
 
 #ifdef CONFIG_IRDA_COMPRESSION
@@ -885,33 +884,33 @@
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
-
+	
 	/* 
 	 *  Find out which compressors we support. We do this be checking that
 	 *  the corresponding compressor for each bit set in the QoS bits has 
 	 *  actually been loaded. Ths is sort of hairy code but that is what 
 	 *  you get when you do a little bit flicking :-)
 	 */
-	DEBUG(4, __FUNCTION__ "(), comp bits 0x%02x\n", 
-	       self->qos_rx.compression.bits); 
+	IRDA_DEBUG(4, __FUNCTION__ "(), comp bits 0x%02x\n", 
+		   self->qos_rx.compression.bits); 
 	mask = 0x80; /* Start with testing MSB */
 	for (i=0;i<8;i++) {
-		DEBUG(4, __FUNCTION__ "(), testing bit %d\n", 8-i);
+		IRDA_DEBUG(4, __FUNCTION__ "(), testing bit %d\n", 8-i);
 		if (self->qos_rx.compression.bits & mask) {
-			DEBUG(4, __FUNCTION__ "(), bit %d is set by defalt\n",
-			       8-i);
+			IRDA_DEBUG(4, __FUNCTION__ 
+				   "(), bit %d is set by defalt\n", 8-i);
 			comp = hashbin_find(irlap_compressors, 
-					     compression[ msb_index(mask)], 
-					     NULL);
+					    compressions[msb_index(mask)], 
+					    NULL);
 			if (!comp) {
 				/* Protocol not supported, so clear the bit */
-				DEBUG(4, __FUNCTION__ "(), Compression "
-				       "protocol %d has not been loaded!\n", 
-				       compression[msb_index(mask)]);
+				IRDA_DEBUG(4, __FUNCTION__ "(), Compression "
+					   "protocol %d has not been loaded!\n", 
+					   compressions[msb_index(mask)]);
 				self->qos_rx.compression.bits &= ~mask;
-				DEBUG(4, __FUNCTION__ 
-				       "(), comp bits 0x%02x\n", 
-				       self->qos_rx.compression.bits); 
+				IRDA_DEBUG(4, __FUNCTION__ 
+					   "(), comp bits 0x%02x\n", 
+					   self->qos_rx.compression.bits); 
 			}
 		}
 		/* Try the next bit */
@@ -933,7 +932,7 @@
 {
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
-	ASSERT(self->irdev != NULL, return;);
+	ASSERT(self->netdev != NULL, return;);
 
 	/* Start out with the maximum QoS support possible */
 	irda_init_max_qos_capabilies(&self->qos_rx);
@@ -943,8 +942,7 @@
 #endif
 
 	/* Apply drivers QoS capabilities */
-	irda_qos_compute_intersection(&self->qos_rx, 
-				      irda_device_get_qos(self->irdev));
+	irda_qos_compute_intersection(&self->qos_rx, self->qos_dev);
 
 	/*
 	 *  Check for user supplied QoS parameters. The service user is only 
@@ -952,7 +950,7 @@
 	 *  user may not have set all of them.
 	 */
 	if (qos_user) {
-		DEBUG(1, __FUNCTION__ "(), Found user specified QoS!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), Found user specified QoS!\n");
 
 		if (qos_user->baud_rate.bits)
 			self->qos_rx.baud_rate.bits &= qos_user->baud_rate.bits;
@@ -969,17 +967,11 @@
 #endif
 	}
 
-	/* 
-	 *  Make the intersection between IrLAP and drivers QoS
-	 *  capabilities 
-	 */
-
 	/* Use 500ms in IrLAP for now */
-	self->qos_rx.max_turn_time.bits &= 0x03;
 	self->qos_rx.max_turn_time.bits &= 0x01;
 
 	/* Set data size */
-	/* self->qos_rx.data_size.bits &= 0x03; */
+	/*self->qos_rx.data_size.bits &= 0x03;*/
 
 	/* Set disconnect time */
 	self->qos_rx.link_disc_time.bits &= 0x07;
@@ -995,28 +987,54 @@
  */
 void irlap_apply_default_connection_parameters(struct irlap_cb *self)
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
 
-	irlap_change_speed(self, 9600);
+	irlap_change_speed(self, 9600, TRUE);
+
+	/* Set mbusy when going to NDM state */
+	irda_device_set_media_busy(self->netdev, TRUE);
 
 	/* Default value in NDM */
 	self->bofs_count = 11;
 
-	/* Use these until connection has been made */
+	/* 
+	 * Generate random connection address for this session, which must
+	 * be 7 bits wide and different from 0x00 and 0xfe 
+	 */
+	while ((self->caddr == 0x00) || (self->caddr == 0xfe)) {
+		get_random_bytes(&self->caddr, sizeof(self->caddr));
+		self->caddr &= 0xfe;
+	}
+
+	/* Use default values until connection has been negitiated */
 	self->slot_timeout = sysctl_slot_timeout;
 	self->final_timeout = FINAL_TIMEOUT;
 	self->poll_timeout = POLL_TIMEOUT;
 	self->wd_timeout = WD_TIMEOUT;
 
+	/* Set some default values */
+	self->qos_tx.baud_rate.value = 9600;
+	self->qos_rx.baud_rate.value = 9600;
+	self->qos_tx.max_turn_time.value = 0;
+	self->qos_rx.max_turn_time.value = 0;
+	self->qos_tx.min_turn_time.value = 0;
+	self->qos_rx.min_turn_time.value = 0;
 	self->qos_tx.data_size.value = 64;
+	self->qos_rx.data_size.value = 64;
+	self->qos_tx.window_size.value = 1;
+	self->qos_rx.window_size.value = 1;
 	self->qos_tx.additional_bofs.value = 11;
+	self->qos_rx.additional_bofs.value = 11;
+	self->qos_tx.link_disc_time.value = 0;
+	self->qos_rx.link_disc_time.value = 0;
 
 	irlap_flush_all_queues(self);
 
 	self->disconnect_pending = FALSE;
+	self->connect_pending = FALSE;
 }
 
 /*
@@ -1025,62 +1043,86 @@
  *    Initialize IrLAP with the negotiated QoS values
  *
  */
-void irlap_apply_connection_parameters(struct irlap_cb *self, 
-				       struct qos_info *qos) 
+void irlap_apply_connection_parameters(struct irlap_cb *self) 
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
 
-	irlap_change_speed(self, qos->baud_rate.value);
+	irlap_change_speed(self, self->qos_tx.baud_rate.value, FALSE);
 
-	self->window_size = qos->window_size.value;
-	self->window      = qos->window_size.value;
-	self->bofs_count  = qos->additional_bofs.value;
+	self->window_size = self->qos_tx.window_size.value;
+	self->window      = self->qos_tx.window_size.value;
+	self->bofs_count  = self->qos_tx.additional_bofs.value;
 
 	/*
 	 *  Calculate how many bytes it is possible to transmit before the
-	 *  link must be turned around wb = baud * mtt/1000 * 1/2
+	 *  link must be turned around
 	 */
-	self->window_bytes = qos->baud_rate.value 
-		* qos->max_turn_time.value / 10000;
-	DEBUG(4, "Setting window_bytes = %d\n", self->window_bytes);
-
+	self->line_capacity = 
+		irlap_max_line_capacity(self->qos_tx.baud_rate.value,
+					self->qos_tx.max_turn_time.value);
 	/*
 	 *  Set N1 to 0 if Link Disconnect/Threshold Time = 3 and set it to 
 	 *  3 seconds otherwise. See page 71 in IrLAP for more details.
 	 *  TODO: these values should be calculated from the final timer
          *  as well
 	 */
-	if (qos->link_disc_time.value == 3)
+	ASSERT(self->qos_tx.max_turn_time.value != 0, return;);
+	if (self->qos_tx.link_disc_time.value == 3)
 		self->N1 = 0;
 	else
-		self->N1 = 3000 / qos->max_turn_time.value;
+		self->N1 = 3000 / self->qos_tx.max_turn_time.value;
+	
+	IRDA_DEBUG(4, "Setting N1 = %d\n", self->N1);
 	
-	DEBUG(4, "Setting N1 = %d\n", self->N1);
 	
-	self->N2 = qos->link_disc_time.value * 1000 / qos->max_turn_time.value;
-	DEBUG(4, "Setting N2 = %d\n", self->N2);
+	self->N2 = self->qos_tx.link_disc_time.value * 1000 / 
+		self->qos_tx.max_turn_time.value;
+	IRDA_DEBUG(4, "Setting N2 = %d\n", self->N2);
 
 	/* 
 	 *  Initialize timeout values, some of the rules are listed on 
 	 *  page 92 in IrLAP.
 	 */
-	self->poll_timeout = qos->max_turn_time.value * HZ / 1000;
-	self->final_timeout = qos->max_turn_time.value * HZ / 1000;
+	self->poll_timeout = self->qos_tx.max_turn_time.value * HZ / 1000;
 	self->wd_timeout = self->poll_timeout * 2;
 
+	/* 
+	 * Be careful to keep our promises to the peer device about how long
+	 * time it can keep the pf bit. So here we must use the rx_qos value
+	 */
+	self->final_timeout = self->qos_rx.max_turn_time.value * HZ / 1000;
+
 #ifdef CONFIG_IRDA_COMPRESSION
-	if (qos->compression.value) {
-		DEBUG(1, __FUNCTION__ "(), Initializing compression\n");
-		irda_set_compression(self, qos->compression.value);
+	if (self->qos_tx.compression.value) {
+		IRDA_DEBUG(1, __FUNCTION__ "(), Initializing compression\n");
+		irda_set_compression(self, self->qos_tx.compression.value);
 
 		irlap_compressor_init(self, 0);
 	}
 #endif
 }
 
+/*
+ * Function irlap_set_local_busy (self, status)
+ *
+ *    
+ *
+ */
+void irlap_set_local_busy(struct irlap_cb *self, int status)
+{
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	self->local_busy = status;
+	
+	if (status)
+		IRDA_DEBUG(0, __FUNCTION__ "(), local busy ON\n");
+	else
+		IRDA_DEBUG(0, __FUNCTION__ "(), local busy OFF\n");
+}
+
 #ifdef CONFIG_PROC_FS
 /*
  * Function irlap_proc_read (buf, start, offset, len, unused)
@@ -1089,7 +1131,7 @@
  *
  */
 int irlap_proc_read(char *buf, char **start, off_t offset, int len, 
-		     int unused)
+		    int unused)
 {
 	struct irlap_cb *self;
 	unsigned long flags;
@@ -1105,27 +1147,30 @@
 		ASSERT(self != NULL, return -ENODEV;);
 		ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
 
-		len += sprintf(buf+len, "irlap%d <-> %s ",
-				i++, self->irdev->name);
+		len += sprintf(buf+len, "irlap%d ", i++);
 		len += sprintf(buf+len, "state: %s\n", 
-				irlap_state[ self->state]);
+			       irlap_state[self->state]);
 		
 		len += sprintf(buf+len, "  caddr: %#02x, ", self->caddr);
 		len += sprintf(buf+len, "saddr: %#08x, ", self->saddr);
 		len += sprintf(buf+len, "daddr: %#08x\n", self->daddr);
 		
 		len += sprintf(buf+len, "  win size: %d, ", 
-				self->window_size);
+			       self->window_size);
 		len += sprintf(buf+len, "win: %d, ", self->window);
-		len += sprintf(buf+len, "win bytes: %d, ", self->window_bytes);
+#if CONFIG_IRDA_DYNAMIC_WINDOW
+		len += sprintf(buf+len, "line capacity: %d, ", 
+			       self->line_capacity);
 		len += sprintf(buf+len, "bytes left: %d\n", self->bytes_left);
-
+#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
 		len += sprintf(buf+len, "  tx queue len: %d ", 
-				skb_queue_len(&self->tx_list));
+			       skb_queue_len(&self->txq));
 		len += sprintf(buf+len, "win queue len: %d ", 
-				skb_queue_len(&self->wx_list));
-		len += sprintf(buf+len, "rbusy: %s\n", self->remote_busy ? 
-				"TRUE" : "FALSE");
+			       skb_queue_len(&self->wx_list));
+		len += sprintf(buf+len, "rbusy: %s", self->remote_busy ?
+			       "TRUE" : "FALSE");
+		len += sprintf(buf+len, " mbusy: %s\n", self->media_busy ?
+			       "TRUE" : "FALSE");
 		
 		len += sprintf(buf+len, "  retrans: %d ", self->retry_count);
 		len += sprintf(buf+len, "vs: %d ", self->vs);
@@ -1135,42 +1180,42 @@
 		len += sprintf(buf+len, "  qos\tbps\tmaxtt\tdsize\twinsize\taddbofs\tmintt\tldisc\tcomp\n");
 		
 		len += sprintf(buf+len, "  tx\t%d\t", 
-				self->qos_tx.baud_rate.value);
+			       self->qos_tx.baud_rate.value);
 		len += sprintf(buf+len, "%d\t", 
-				self->qos_tx.max_turn_time.value);
+			       self->qos_tx.max_turn_time.value);
 		len += sprintf(buf+len, "%d\t",
-				self->qos_tx.data_size.value);
+			       self->qos_tx.data_size.value);
 		len += sprintf(buf+len, "%d\t",
-				self->qos_tx.window_size.value);
+			       self->qos_tx.window_size.value);
 		len += sprintf(buf+len, "%d\t",
-				self->qos_tx.additional_bofs.value);
+			       self->qos_tx.additional_bofs.value);
 		len += sprintf(buf+len, "%d\t", 
-				self->qos_tx.min_turn_time.value);
+			       self->qos_tx.min_turn_time.value);
 		len += sprintf(buf+len, "%d\t", 
-				self->qos_tx.link_disc_time.value);
+			       self->qos_tx.link_disc_time.value);
 #ifdef CONFIG_IRDA_COMPRESSION
 		len += sprintf(buf+len, "%d",
-				self->qos_tx.compression.value);
+			       self->qos_tx.compression.value);
 #endif
 		len += sprintf(buf+len, "\n");
 
 		len += sprintf(buf+len, "  rx\t%d\t", 
-				self->qos_rx.baud_rate.value);
+			       self->qos_rx.baud_rate.value);
 		len += sprintf(buf+len, "%d\t", 
-				self->qos_rx.max_turn_time.value);
+			       self->qos_rx.max_turn_time.value);
 		len += sprintf(buf+len, "%d\t",
-				self->qos_rx.data_size.value);
+			       self->qos_rx.data_size.value);
 		len += sprintf(buf+len, "%d\t",
-				self->qos_rx.window_size.value);
+			       self->qos_rx.window_size.value);
 		len += sprintf(buf+len, "%d\t",
-				self->qos_rx.additional_bofs.value);
+			       self->qos_rx.additional_bofs.value);
 		len += sprintf(buf+len, "%d\t", 
-				self->qos_rx.min_turn_time.value);
+			       self->qos_rx.min_turn_time.value);
 		len += sprintf(buf+len, "%d\t", 
-				self->qos_rx.link_disc_time.value);
+			       self->qos_rx.link_disc_time.value);
 #ifdef CONFIG_IRDA_COMPRESSION
 		len += sprintf(buf+len, "%d",
-				self->qos_rx.compression.value);
+			       self->qos_rx.compression.value);
 #endif
 		len += sprintf(buf+len, "\n");
 		
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irlap_comp.c linux.15p9/net/irda/irlap_comp.c
--- linux.vanilla/net/irda/irlap_comp.c	Sat Aug 14 02:26:52 1999
+++ linux.15p9/net/irda/irlap_comp.c	Tue Jan 18 01:08:18 2000
@@ -6,8 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Fri Oct  9 09:18:07 1998
- * Modified at:   Sun May  9 11:37:06 1999
+ * Modified at:   Tue Oct  5 11:34:52 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * Modified at:   Fri May 28  3:11 CST 1999
+ * Modified by:   Horst von Brand <vonbrand@sleipnir.valparaiso.cl>
  * Sources:       ppp.c, isdn_ppp.c
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -23,6 +25,8 @@
  *     
  ********************************************************************/
 
+#include <linux/string.h>
+
 #include <net/irda/irda.h>
 #include <net/irda/irqueue.h>
 #include <net/irda/irlap.h>
@@ -41,11 +45,11 @@
 {
 	struct irda_compressor *new;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG( 4, __FUNCTION__ "()\n");
 
 	/* Check if this compressor has been registred before */
 	if ( hashbin_find ( irlap_compressors, cp->compress_proto, NULL)) {
-		DEBUG( 0, __FUNCTION__ "(), Compressor already registered\n");
+		IRDA_DEBUG( 0, __FUNCTION__ "(), Compressor already registered\n");
                 return 0;
         }
 	
@@ -59,7 +63,7 @@
         new->cp = cp;
 
 	/* Insert IrDA compressor into hashbin */
-	hashbin_insert( irlap_compressors, (QUEUE *) new, cp->compress_proto,
+	hashbin_insert( irlap_compressors, (queue_t *) new, cp->compress_proto,
 			NULL);
 	
         return 0;
@@ -75,11 +79,11 @@
 {
 	struct irda_compressor *node;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG( 4, __FUNCTION__ "()\n");
 
 	node = hashbin_remove( irlap_compressors, cp->compress_proto, NULL);
 	if ( !node) {
-		DEBUG( 0, __FUNCTION__ "(), compressor not found!\n");
+		IRDA_DEBUG( 0, __FUNCTION__ "(), compressor not found!\n");
 		return;
 	}	
 	kfree( node);
@@ -98,7 +102,7 @@
 
 	__u8 options[CILEN_DEFLATE];
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG( 4, __FUNCTION__ "()\n");
 
 	ASSERT( self != NULL, return -ENODEV;);
 	ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
@@ -111,7 +115,7 @@
 
 	comp = hashbin_find( irlap_compressors, proto, NULL);
 	if ( !comp) {
-		DEBUG( 0, __FUNCTION__ "(), Unable to find compressor\n");
+		IRDA_DEBUG( 0, __FUNCTION__ "(), Unable to find compressor\n");
 		return -1;
 	}
 
@@ -126,7 +130,7 @@
 	self->compressor.cp = cp;
 	self->compressor.state = cp->comp_alloc( options, sizeof( options));
 	if ( self->compressor.state == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Failed!\n");
+		IRDA_DEBUG( 0, __FUNCTION__ "(), Failed!\n");
 		return -ENOBUFS;
 	}
 
@@ -141,7 +145,7 @@
 	self->decompressor.cp = cp;
 	self->decompressor.state = cp->decomp_alloc( options, sizeof( options));
 	if ( self->decompressor.state == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Failed!\n");
+		IRDA_DEBUG( 0, __FUNCTION__ "(), Failed!\n");
 		return -ENOBUFS;
 	}
 	return 0;
@@ -155,7 +159,7 @@
  */
 void irda_free_compression( struct irlap_cb *self)
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG( 4, __FUNCTION__ "()\n");
 
 	if ( self->compressor.state) {
 		irda_comp_free( self->compressor.state);
@@ -179,7 +183,7 @@
 	int debug = TRUE;
 	__u8 options[CILEN_DEFLATE];
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LAP_MAGIC, return;);
@@ -194,7 +198,7 @@
 	 *  We're agreeing to send compressed packets.
 	 */
 	if ( self->compressor.state == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), state == NULL\n");
+		IRDA_DEBUG( 0, __FUNCTION__ "(), state == NULL\n");
 		return;
 	}
 	
@@ -202,7 +206,7 @@
 					       options, sizeof( options),
 					       0, 0, debug)) 
 	{
-		DEBUG( 0, __FUNCTION__ "(), Compressor running!\n");
+		IRDA_DEBUG( 0, __FUNCTION__ "(), Compressor running!\n");
 		/* ppp->flags |= SC_COMP_RUN; */
 	}
 	
@@ -210,7 +214,7 @@
 	 *  Initialize decompressor
 	 */
 	if ( self->decompressor.state == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), state == NULL\n");
+		IRDA_DEBUG( 0, __FUNCTION__ "(), state == NULL\n");
 		return;
 	}
 	
@@ -218,7 +222,7 @@
 						   options, sizeof( options),
 						   0, 0, 0, debug)) 
 	{
-		DEBUG( 0, __FUNCTION__ "(), Decompressor running!\n");	
+		IRDA_DEBUG( 0, __FUNCTION__ "(), Decompressor running!\n");	
 		
 		/* ppp->flags |= SC_DECOMP_RUN; */
 		/* ppp->flags &= ~(SC_DC_ERROR | SC_DC_FERROR); */
@@ -239,7 +243,7 @@
 	
 	ASSERT( skb != NULL, return NULL;);
 	
-	DEBUG(4, __FUNCTION__ "() skb->len=%d, jiffies=%ld\n", (int) skb->len,
+	IRDA_DEBUG(4, __FUNCTION__ "() skb->len=%d, jiffies=%ld\n", (int) skb->len,
 	      jiffies);
 
 	ASSERT( self != NULL, return NULL;);
@@ -266,7 +270,7 @@
 						 skb->data, new_skb->data, 
 						 skb->len, new_skb->len);
 	if( count <= 0) {
-		DEBUG(4, __FUNCTION__ "(), Unable to compress frame!\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), Unable to compress frame!\n");
 		dev_kfree_skb( new_skb);
 
 		/* Tell peer that this frame is not compressed */
@@ -283,7 +287,7 @@
 
 	dev_kfree_skb( skb);
 	
-	DEBUG(4, __FUNCTION__ "() new_skb->len=%d\n, jiffies=%ld", 
+	IRDA_DEBUG(4, __FUNCTION__ "() new_skb->len=%d\n, jiffies=%ld", 
 	      (int) new_skb->len, jiffies);
 	
 	return new_skb;
@@ -301,7 +305,7 @@
 	struct sk_buff *new_skb;
 	int count;
 
-	DEBUG( 4, __FUNCTION__ "() skb->len=%d\n", (int) skb->len);
+	IRDA_DEBUG( 4, __FUNCTION__ "() skb->len=%d\n", (int) skb->len);
 
 	ASSERT( self != NULL, return NULL;);
 	ASSERT( self->magic == LAP_MAGIC, return NULL;);
@@ -335,7 +339,7 @@
 	count = irda_decompress( self->decompressor.state, skb->data, 
 				 skb->len, new_skb->data, new_skb->len);
 	if ( count <= 0) {
-		DEBUG( 4, __FUNCTION__ "(), Unable to decompress frame!\n");
+		IRDA_DEBUG( 4, __FUNCTION__ "(), Unable to decompress frame!\n");
 		
 		dev_kfree_skb( new_skb);
 		return skb;
@@ -343,7 +347,7 @@
 
 	skb_trim( new_skb, count);
 	
-	DEBUG( 4, __FUNCTION__ "() new_skb->len=%d\n", (int) new_skb->len);
+	IRDA_DEBUG( 4, __FUNCTION__ "() new_skb->len=%d\n", (int) new_skb->len);
 
 	return new_skb;
 }
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irlap_event.c linux.15p9/net/irda/irlap_event.c
--- linux.vanilla/net/irda/irlap_event.c	Sat Aug 14 02:26:52 1999
+++ linux.15p9/net/irda/irlap_event.c	Tue Jan 18 01:08:18 2000
@@ -1,15 +1,15 @@
 /*********************************************************************
  *                
  * Filename:      irlap_event.c
- * Version:       0.8
+ * Version:       0.9
  * Description:   IrLAP state machine implementation
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Aug 16 00:59:29 1997
- * Modified at:   Mon May 31 21:55:42 1999
+ * Modified at:   Mon Jan 17 09:07:36 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
+ *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>,
  *                        Thomas Davis <ratbert@radiks.net>
  *     All Rights Reserved.
  *     
@@ -37,11 +37,12 @@
 #include <net/irda/irlap.h>
 #include <net/irda/irlap_frame.h>
 #include <net/irda/qos.h>
+#include <net/irda/parameters.h>
 
 #include <net/irda/irda_device.h>
 
 #if CONFIG_IRDA_FAST_RR
-int sysctl_fast_poll_increase = 50;
+int sysctl_fast_poll_increase = 10;
 #endif
 
 static int irlap_state_ndm    (struct irlap_cb *self, IRLAP_EVENT event, 
@@ -84,6 +85,7 @@
 	"RESET_REQUEST",
 	"RESET_RESPONSE",
 	"SEND_I_CMD",
+	"SEND_UI_FRAME",
 	"RECV_DISCOVERY_XID_CMD",
 	"RECV_DISCOVERY_XID_RSP",
 	"RECV_SNRM_CMD",
@@ -91,14 +93,20 @@
 	"RECV_TEST_RSP",
 	"RECV_UA_RSP",
 	"RECV_DM_RSP",
+	"RECV_RD_RSP",
 	"RECV_I_CMD",
 	"RECV_I_RSP",
 	"RECV_UI_FRAME",
 	"RECV_FRMR_RSP",
 	"RECV_RR_CMD",
 	"RECV_RR_RSP",
-	"RECV_RNR_FRAME",
-	"RECV_DISC_FRAME",
+	"RECV_RNR_CMD",
+	"RECV_RNR_RSP",
+	"RECV_REJ_CMD",
+	"RECV_REJ_RSP",
+	"RECV_SREJ_CMD",
+	"RECV_SREJ_RSP",
+	"RECV_DISC_CMD",
 	"SLOT_TIMER_EXPIRED",
 	"QUERY_TIMER_EXPIRED",
 	"FINAL_TIMER_EXPIRED",
@@ -126,9 +134,9 @@
 	"LAP_RESET_CHECK",
 };
 
-static int (*state[])( struct irlap_cb *self, IRLAP_EVENT event, 
-		       struct sk_buff *skb, struct irlap_info *info) = 
-{ 
+static int (*state[])(struct irlap_cb *self, IRLAP_EVENT event, 
+		      struct sk_buff *skb, struct irlap_info *info) = 
+{
 	irlap_state_ndm,
 	irlap_state_query,
 	irlap_state_reply,
@@ -152,7 +160,7 @@
  *    Poll timer has expired. Normally we must now send a RR frame to the
  *    remote device
  */
-static void irlap_poll_timer_expired(unsigned long data)
+static void irlap_poll_timer_expired(void *data)
 {
 	struct irlap_cb *self = (struct irlap_cb *) data;
 	
@@ -168,7 +176,11 @@
 	ASSERT(self->magic == LAP_MAGIC, return;);
 
 #ifdef CONFIG_IRDA_FAST_RR
-	if (skb_queue_len(&self->tx_list) == 0) {
+	/* 
+	 * Send out the RR frames faster if our own transmit queue is empty, or
+	 * if the peer is busy. The effect is a much faster conversation
+	 */
+	if ((skb_queue_len(&self->txq) == 0) || (self->remote_busy)) {
 		if (self->fast_RR == TRUE) {
 			/*
 			 *  Assert that the fast poll timer has not reached the
@@ -179,7 +191,7 @@
 				 *  FIXME: this should be a more configurable
 				 *         function
 				 */
-				self->fast_RR_timeout += (sysctl_fast_poll_increase * HZ/1000);
+				self->fast_RR_timeout += MSECS_TO_JIFFIES(sysctl_fast_poll_increase);
 
 				/* Use this fast(er) timeout instead */
 				timeout = self->fast_RR_timeout;
@@ -194,13 +206,14 @@
 	} else
 		self->fast_RR = FALSE;
 
-	DEBUG(4, __FUNCTION__ "(), Timeout=%d\n", timeout);
-#endif
+	IRDA_DEBUG(3, __FUNCTION__ "(), timeout=%d (%ld)\n", timeout, jiffies);
+#endif /* CONFIG_IRDA_FAST_RR */
+
 	if (timeout == 0)
 		irlap_do_event(self, POLL_TIMER_EXPIRED, NULL, NULL);
 	else
-		irda_start_timer(&self->poll_timer, timeout, 
-				 (unsigned long) self, irlap_poll_timer_expired);
+		irda_start_timer(&self->poll_timer, timeout, self, 
+				 irlap_poll_timer_expired);
 }
 
 /*
@@ -217,11 +230,11 @@
 	if (!self || self->magic != LAP_MAGIC)
 		return;
 	
-  	DEBUG(4, __FUNCTION__ "(), event = %s, state = %s\n", 
-	      irlap_event[event], irlap_state[self->state]); 
-	
-	ret = (*state[ self->state]) (self, event, skb, info);
+  	IRDA_DEBUG(3, __FUNCTION__ "(), event = %s, state = %s\n", 
+		   irlap_event[event], irlap_state[self->state]); 
 	
+	ret = (*state[self->state])(self, event, skb, info);
+
 	/* 
 	 *  Check if there are any pending events that needs to be executed
 	 */
@@ -233,12 +246,12 @@
 		 * try to disconnect link if we send any data frames, since
 		 * that will change the state away form XMIT
 		 */
-		if (skb_queue_len(&self->tx_list)) {
+		if (skb_queue_len(&self->txq)) {
 			/* Try to send away all queued data frames */
-			while ((skb = skb_dequeue(&self->tx_list)) != NULL) {
+			while ((skb = skb_dequeue(&self->txq)) != NULL) {
 				ret = (*state[self->state])(self, SEND_I_CMD,
 							    skb, NULL);
-				if ( ret == -EPROTO)
+				if (ret == -EPROTO)
 					break; /* Try again later! */
 			}
 		} else if (self->disconnect_pending) {
@@ -250,9 +263,7 @@
 		break;
 	case LAP_NDM:
 		/* Check if we should try to connect */
-		if ((self->connect_pending) && 
-		    !irda_device_is_media_busy(self->irdev)) 
-		{
+		if ((self->connect_pending) && !self->media_busy) {
 			self->connect_pending = FALSE;
 			
 			ret = (*state[self->state])(self, CONNECT_REQUEST, 
@@ -278,10 +289,11 @@
 	if (!self || self->magic != LAP_MAGIC)
 		return;
 	
-	DEBUG(4, "next LAP state = %s\n", irlap_state[ state]);
+	IRDA_DEBUG(4, "next LAP state = %s\n", irlap_state[state]);
 
 	self->state = state;
 
+#ifdef CONFIG_IRDA_DYNAMIC_WINDOW
 	/*
 	 *  If we are swithing away from a XMIT state then we are allowed to 
 	 *  transmit a maximum number of bytes again when we enter the XMIT 
@@ -289,7 +301,8 @@
 	 *  we cannot do this when swithing into the XMIT state :-)
 	 */
 	if ((state != LAP_XMIT_P) && (state != LAP_XMIT_S))
-		self->bytes_left = self->window_bytes;
+		self->bytes_left = self->line_capacity;
+#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
 }
 
 /*
@@ -298,59 +311,60 @@
  *    NDM (Normal Disconnected Mode) state
  *
  */
-static int irlap_state_ndm( struct irlap_cb *self, IRLAP_EVENT event, 
-			    struct sk_buff *skb,  struct irlap_info *info) 
+static int irlap_state_ndm(struct irlap_cb *self, IRLAP_EVENT event, 
+			   struct sk_buff *skb, struct irlap_info *info) 
 {
 	discovery_t *discovery_rsp;
 	int ret = 0;
-	
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == LAP_MAGIC, return -1;);
+	int i;
 
-	switch(event) {
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LAP_MAGIC, return -1;);
+
+	switch (event) {
 	case CONNECT_REQUEST:
-		ASSERT( self->irdev != NULL, return -1;);
+		ASSERT(self->netdev != NULL, return -1;);
 
-		if (irda_device_is_media_busy(self->irdev)) {
-			DEBUG( 0, __FUNCTION__
-			      "(), CONNECT_REQUEST: media busy!\n");
+		if (self->media_busy) {
+			IRDA_DEBUG(0, __FUNCTION__
+				   "(), CONNECT_REQUEST: media busy!\n");
 			
 			/* Always switch state before calling upper layers */
-			irlap_next_state( self, LAP_NDM);
+			irlap_next_state(self, LAP_NDM);
 			
-			irlap_disconnect_indication( self, LAP_MEDIA_BUSY);
+			irlap_disconnect_indication(self, LAP_MEDIA_BUSY);
 		} else {
-			irlap_send_snrm_frame( self, &self->qos_rx);
+			irlap_send_snrm_frame(self, &self->qos_rx);
 			
 			/* Start Final-bit timer */
 			irlap_start_final_timer(self, self->final_timeout);
 
 			self->retry_count = 0;
-			irlap_next_state( self, LAP_SETUP);
+			irlap_next_state(self, LAP_SETUP);
 		}
 		break;
-
 	case RECV_SNRM_CMD:
-		self->daddr = info->daddr;
-		self->caddr = info->caddr;
-		
-		irlap_next_state( self, LAP_CONN);
-
-		irlap_connect_indication( self, skb);
+		/* Check if the frame contains and I field */
+		if (info) {		       
+			self->daddr = info->daddr;
+			self->caddr = info->caddr;
+			
+			irlap_next_state(self, LAP_CONN);
+			
+			irlap_connect_indication(self, skb);
+		} else {
+			IRDA_DEBUG(0, __FUNCTION__ "(), SNRM frame does not "
+				   "contain an I field!\n");
+			dev_kfree_skb(skb);
+		}
 		break;
-
 	case DISCOVERY_REQUEST:		
-		ASSERT( info != NULL, return -1;);
+		ASSERT(info != NULL, return -1;);
 
-	 	if (irda_device_is_media_busy(self->irdev)) {
- 			DEBUG(0, __FUNCTION__ "(), media busy!\n"); 
+	 	if (self->media_busy) {
+ 			IRDA_DEBUG(0, __FUNCTION__ "(), media busy!\n"); 
 			/* irlap->log.condition = MEDIA_BUSY; */
-			
-			/* Always switch state before calling upper layers */
-			irlap_next_state(self, LAP_NDM); 
-			
+						
 			/* This will make IrLMP try again */
  			irlap_discovery_confirm(self, NULL);
 			return 0;
@@ -365,22 +379,21 @@
 		irlap_start_slot_timer(self, self->slot_timeout);
 		irlap_next_state(self, LAP_QUERY);
 		break;
-
 	case RECV_DISCOVERY_XID_CMD:
-		ASSERT( info != NULL, return -1;);
+		ASSERT(info != NULL, return -1;);
 
 		/* Assert that this is not the final slot */
-		if ( info->s <= info->S) {
+		if (info->s <= info->S) {
 			/* self->daddr = info->daddr;  */
 			self->slot = irlap_generate_rand_time_slot(info->S,
 								   info->s);
-			DEBUG( 4, "XID_CMD: S=%d, s=%d, slot %d\n", info->S, 
-			       info->s, self->slot);
+			IRDA_DEBUG(4, "XID_CMD: S=%d, s=%d, slot %d\n", info->S, 
+			      info->s, self->slot);
 
-			if ( self->slot == info->s) {
+			if (self->slot == info->s) {
 				discovery_rsp = irlmp_get_discovery_response();
 				discovery_rsp->daddr = info->daddr;
-
+				
 				irlap_send_discovery_xid_frame(self, info->S, 
 							       self->slot, 
 							       FALSE,
@@ -389,24 +402,63 @@
 			} else
 				self->frame_sent = FALSE;
 			
-			irlap_start_query_timer( self, QUERY_TIMEOUT);
-			irlap_next_state( self, LAP_REPLY);
+			/* 
+			 * Remember to multiply the query timeout value with 
+			 * the number of slots used
+			 */
+			irlap_start_query_timer(self, QUERY_TIMEOUT*info->S);
+			irlap_next_state(self, LAP_REPLY);
 		}
 		dev_kfree_skb(skb);
 		break;
-
+#ifdef CONFIG_IRDA_ULTRA
+	case SEND_UI_FRAME:
+		/* Only allowed to repeat an operation twice */
+		for (i=0; ((i<2) && (self->media_busy == FALSE)); i++) {
+			skb = skb_dequeue(&self->txq_ultra);
+			if (skb)			
+				irlap_send_ui_frame(self, skb, CBROADCAST, 
+						    CMD_FRAME);
+			else
+				break;
+		}
+		if (i == 2) {
+			/* Force us to listen 500 ms again */
+			irda_device_set_media_busy(self->netdev, TRUE);
+		}
+		break;
+	case RECV_UI_FRAME:
+		/* Only accept broadcast frames in NDM mode */
+		if (info->caddr != CBROADCAST) {
+			IRDA_DEBUG(0, __FUNCTION__ 
+				   "(), not a broadcast frame!\n");
+			dev_kfree_skb(skb);
+		} else
+			irlap_unitdata_indication(self, skb);
+		break;
+#endif /* CONFIG_IRDA_ULTRA */
 	case RECV_TEST_CMD:
+		/* Remove test frame header */
 		skb_pull(skb, sizeof(struct test_frame));
-		irlap_send_test_frame(self, info->daddr, skb);
+
+		/* 
+		 * Send response. This skb will not be sent out again, and
+		 * will only be used to send out the same info as the cmd
+		 */
+		irlap_send_test_frame(self, CBROADCAST, info->daddr, skb);
 		dev_kfree_skb(skb);
 		break;
 	case RECV_TEST_RSP:
-		DEBUG(0, __FUNCTION__ "() not implemented!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "() not implemented!\n");
 		dev_kfree_skb(skb);
 		break;
 	default:
-		DEBUG(2, __FUNCTION__ "(), Unknown event %s", 
-		      irlap_event[event]);
+		IRDA_DEBUG(2, __FUNCTION__ "(), Unknown event %s\n", 
+			   irlap_event[event]);
+		
+		if (skb)
+			dev_kfree_skb(skb);
+
 		ret = -1;
 		break;
 	}	
@@ -419,30 +471,37 @@
  *    QUERY state
  *
  */
-static int irlap_state_query( struct irlap_cb *self, IRLAP_EVENT event, 
-			      struct sk_buff *skb, struct irlap_info *info) 
+static int irlap_state_query(struct irlap_cb *self, IRLAP_EVENT event, 
+			     struct sk_buff *skb, struct irlap_info *info) 
 {
 	int ret = 0;
 
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == LAP_MAGIC, return -1;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LAP_MAGIC, return -1;);
 
-	switch( event) {
+	switch (event) {
 	case RECV_DISCOVERY_XID_RSP:
-		ASSERT( info != NULL, return -1;);
-		ASSERT( info->discovery != NULL, return -1;);
-
-		DEBUG(4, __FUNCTION__ "(), daddr=%08x\n", 
-		      info->discovery->daddr);
+		ASSERT(info != NULL, return -1;);
+		ASSERT(info->discovery != NULL, return -1;);
 
-		hashbin_insert( self->discovery_log, 
-				(QUEUE *) info->discovery,
-				info->discovery->daddr, NULL);
+		IRDA_DEBUG(4, __FUNCTION__ "(), daddr=%08x\n", 
+			   info->discovery->daddr);
 
-		dev_kfree_skb(skb);
+		if (!self->discovery_log) {
+			WARNING(__FUNCTION__ "(), discovery log is gone! "
+				"maybe the discovery timeout has been set to "
+				"short?\n");
+			dev_kfree_skb(skb);
+			break;
+		}
+		hashbin_insert(self->discovery_log, 
+			       (queue_t *) info->discovery,
+			       info->discovery->daddr, NULL);
 
 		/* Keep state */
-		irlap_next_state( self, LAP_QUERY); 
+		/* irlap_next_state(self, LAP_QUERY);  */
+
+		dev_kfree_skb(skb);
 		break;
 	case SLOT_TIMER_EXPIRED:
 		if (self->s < self->S) {
@@ -468,14 +527,17 @@
 			 *  so now we must return the results
 			 */
 			irlap_discovery_confirm(self, self->discovery_log);
+
+			/* IrLMP should now have taken care of the log */
+			self->discovery_log = NULL;
 		}
 		break;
 	default:
-		DEBUG(2, __FUNCTION__ "(), Unknown event %d, %s\n", event, 
-		      irlap_event[event]);
+		IRDA_DEBUG(2, __FUNCTION__ "(), Unknown event %s\n", 
+			   irlap_event[event]);
 
 		if (skb)
-			dev_kfree_skb( skb);
+			dev_kfree_skb(skb);
 
 		ret = -1;
 		break;
@@ -496,14 +558,14 @@
 	discovery_t *discovery_rsp;
 	int ret=0;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == LAP_MAGIC, return -1;);
 
-	switch(event) {
+	switch (event) {
 	case QUERY_TIMER_EXPIRED:
-		DEBUG(2, __FUNCTION__ "(), QUERY_TIMER_EXPIRED <%ld>\n",
+		IRDA_DEBUG(2, __FUNCTION__ "(), QUERY_TIMER_EXPIRED <%ld>\n",
 		      jiffies);
 		irlap_next_state(self, LAP_NDM);
 		break;
@@ -535,11 +597,10 @@
 		dev_kfree_skb(skb);
 		break;
 	default:
-		DEBUG(1, __FUNCTION__ "(), Unknown event %d, %s\n", event,
-		      irlap_event[event]);
-
-		if ( skb)
-			dev_kfree_skb( skb);
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d, %s\n", event,
+			   irlap_event[event]);
+		if (skb)
+			dev_kfree_skb(skb);
 		
 		ret = -1;
 		break;
@@ -559,28 +620,40 @@
 {
 	int ret = 0;
 
-	DEBUG(4, __FUNCTION__ "(), event=%s\n", irlap_event[ event]);
+	IRDA_DEBUG(4, __FUNCTION__ "(), event=%s\n", irlap_event[ event]);
 
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == LAP_MAGIC, return -1;);
 
 	switch (event) {
 	case CONNECT_RESPONSE:
-		/* skb_pull(skb, 11); */
 		skb_pull(skb, sizeof(struct snrm_frame));
 
-		ASSERT(self->irdev != NULL, return -1;);
-		irda_qos_negotiate(&self->qos_rx, &self->qos_tx, skb);
+		ASSERT(self->netdev != NULL, return -1;);
 
-		irlap_initiate_connection_state( self);
+		irlap_qos_negotiate(self, skb);
 
-		/*
-		 * We are allowed to send two frames!
+		irlap_initiate_connection_state(self);
+
+#if 0
+		/* 
+		 * We are allowed to send two frames, but this may increase
+		 * the connect latency, so lets not do it for now.
 		 */
 		irlap_send_ua_response_frame(self, &self->qos_rx);
+#endif
+
+		/* 
+		 * Applying the parameters now will make sure we change speed
+		 * after we have sent the next frame
+		 */
+		irlap_apply_connection_parameters(self);
+
+		/* 
+		 * Sending this frame will force a speed change after it has
+		 * been sent
+		 */
 		irlap_send_ua_response_frame(self, &self->qos_rx);
-		
-		irlap_apply_connection_parameters(self, &self->qos_tx);
 
 		/*
 		 *  The WD-timer could be set to the duration of the P-timer 
@@ -588,29 +661,27 @@
 		 *  value (note 3 IrLAP p. 60). 
 		 */
 		irlap_start_wd_timer(self, self->wd_timeout);
-		irlap_next_state( self, LAP_NRM_S);
-		break;
+		irlap_next_state(self, LAP_NRM_S);
 
-	case RECV_SNRM_CMD:
-		DEBUG( 3, __FUNCTION__ "(), event RECV_SNRM_CMD!\n");
-#if 0
-		irlap_next_state( self, LAP_NDM);
-#endif
+		dev_kfree_skb(skb);
 		break;
-		
 	case RECV_DISCOVERY_XID_CMD:
-		DEBUG( 3, __FUNCTION__ "(), event RECV_DISCOVER_XID_CMD!\n");
-		irlap_next_state( self, LAP_NDM);
-		break;
-		
+		IRDA_DEBUG(3, __FUNCTION__ 
+			   "(), event RECV_DISCOVER_XID_CMD!\n");
+		irlap_next_state(self, LAP_NDM);
+
+		dev_kfree_skb(skb);
+		break;		
 	case DISCONNECT_REQUEST:
-		irlap_send_dm_frame( self);
+		irlap_send_dm_frame(self);
 		irlap_next_state( self, LAP_CONN);
 		break;
-
 	default:
-		DEBUG(1, __FUNCTION__ "(), Unknown event %d, %s\n", event, 
-		      irlap_event[event]);
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d, %s\n", event,
+			   irlap_event[event]);		
+		if (skb)
+			dev_kfree_skb(skb);
+
 		ret = -1;
 		break;
 	}
@@ -625,60 +696,63 @@
  *    a remote peer layer and is awaiting a reply .
  *
  */
-static int irlap_state_setup( struct irlap_cb *self, IRLAP_EVENT event, 
-			      struct sk_buff *skb, struct irlap_info *info) 
+static int irlap_state_setup(struct irlap_cb *self, IRLAP_EVENT event, 
+			     struct sk_buff *skb, struct irlap_info *info) 
 {
 	int ret = 0;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == LAP_MAGIC, return -1;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LAP_MAGIC, return -1;);
 
-	switch( event) {
+	switch (event) {
 	case FINAL_TIMER_EXPIRED:
-		if ( self->retry_count < self->N3) {
+		if (self->retry_count < self->N3) {
 /* 
  *  Perform random backoff, Wait a random number of time units, minimum 
  *  duration half the time taken to transmitt a SNRM frame, maximum duration 
  *  1.5 times the time taken to transmit a SNRM frame. So this time should 
  *  between 15 msecs and 45 msecs.
  */
-			irlap_start_backoff_timer( self, 2 + (jiffies % 3));
+			irlap_start_backoff_timer(self, MSECS_TO_JIFFIES(20 + 
+						        (jiffies % 30)));
 		} else {
 			/* Always switch state before calling upper layers */
-			irlap_next_state( self, LAP_NDM);
+			irlap_next_state(self, LAP_NDM);
 
-			irlap_disconnect_indication( self, LAP_FOUND_NONE);
+			irlap_disconnect_indication(self, LAP_FOUND_NONE);
 		}
 		break;
 	case BACKOFF_TIMER_EXPIRED:
-		irlap_send_snrm_frame( self, &self->qos_rx);
-		irlap_start_final_timer( self, self->final_timeout);
+		irlap_send_snrm_frame(self, &self->qos_rx);
+		irlap_start_final_timer(self, self->final_timeout);
 		self->retry_count++;
 		break;
-
 	case RECV_SNRM_CMD:
-		DEBUG( 4, __FUNCTION__ "(), SNRM battle!\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), SNRM battle!\n");
 
-		ASSERT( skb != NULL, return 0;);
-		ASSERT( info != NULL, return 0;);
+		ASSERT(skb != NULL, return 0;);
+		ASSERT(info != NULL, return 0;);
 
 		/*
 		 *  The device with the largest device address wins the battle
 		 *  (both have sent a SNRM command!)
 		 */
-		if (info->daddr > self->saddr) {
+		if (info &&(info->daddr > self->saddr)) {
 			del_timer(&self->final_timer);
 			irlap_initiate_connection_state(self);
 
-			ASSERT(self->irdev != NULL, return -1;);
-			/* skb_pull(skb, 11); */
+			ASSERT(self->netdev != NULL, return -1;);
+
 			skb_pull(skb, sizeof(struct snrm_frame));
-			irda_qos_negotiate(&self->qos_rx, &self->qos_tx, skb);
+
+			irlap_qos_negotiate(self, skb);
 			
 			irlap_send_ua_response_frame(self, &self->qos_rx);
-			irlap_apply_connection_parameters(self, &self->qos_tx);
+			irlap_apply_connection_parameters(self);
+
+			irlap_next_state(self, LAP_NRM_S);
 			irlap_connect_confirm(self, skb);
 			
 			/* 
@@ -687,51 +761,53 @@
 			 *  to use twice the value (note 3 IrLAP p. 60).  
 			 */
 			irlap_start_wd_timer(self, self->wd_timeout);
-			
-			irlap_next_state(self, LAP_NRM_S);
 		} else {
 			/* We just ignore the other device! */
+			dev_kfree_skb(skb);
 			irlap_next_state(self, LAP_SETUP);
 		}
 		break;
 	case RECV_UA_RSP:
 		/* Stop F-timer */
-		del_timer( &self->final_timer);
+		del_timer(&self->final_timer);
 
 		/* Initiate connection state */
-		irlap_initiate_connection_state( self);
+		irlap_initiate_connection_state(self);
 
 		/* Negotiate connection parameters */
-		ASSERT( skb->len > 10, return -1;);
-		/* skb_pull(skb, 10); */
+		ASSERT(skb->len > 10, return -1;);
+
 		skb_pull(skb, sizeof(struct ua_frame));
 
-		ASSERT(self->irdev != NULL, return -1;);
-		irda_qos_negotiate( &self->qos_rx, &self->qos_tx, skb);
+		ASSERT(self->netdev != NULL, return -1;);
+
+		irlap_qos_negotiate(self, skb);
 
-		irlap_apply_connection_parameters( self, &self->qos_tx); 
+		irlap_apply_connection_parameters(self);
 		self->retry_count = 0;
 		
-		/* This frame will just be sent at the old speed */
-		/* irlap_send_rr_frame( self, CMD_FRAME); */
+		/* This frame will actually force the speed change */
+		irlap_send_rr_frame(self, CMD_FRAME);
 
-		irlap_start_final_timer( self, self->final_timeout/2);
-		irlap_next_state( self, LAP_NRM_P);
+		irlap_start_final_timer(self, self->final_timeout/2);
+		irlap_next_state(self, LAP_NRM_P);
 
-		irlap_connect_confirm( self, skb);
+		irlap_connect_confirm(self, skb);
 		break;
+	case RECV_DM_RSP:     /* FALLTHROUGH */
+	case RECV_DISC_CMD: 
+		del_timer(&self->final_timer);
+		irlap_next_state(self, LAP_NDM);
 
-	case RECV_DISC_FRAME:
-		del_timer( &self->final_timer);
-		irlap_next_state( self, LAP_NDM);
-
-		irlap_disconnect_indication( self, LAP_DISC_INDICATION);
+		irlap_disconnect_indication(self, LAP_DISC_INDICATION);
+		dev_kfree_skb(skb);
 		break;
-
-       /* DM handled in irlap_frame.c, irlap_input() */
-		
 	default:
-		DEBUG( 4, "irlap_state_setup: Unknown event");
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d, %s\n", event,
+			   irlap_event[event]);		
+		if (skb)
+			dev_kfree_skb(skb);
+		
 		ret = -1;
 		break;
 	}	
@@ -744,10 +820,10 @@
  *    OFFLINE state, not used for now!
  *
  */
-static int irlap_state_offline( struct irlap_cb *self, IRLAP_EVENT event, 
-				struct sk_buff *skb, struct irlap_info *info) 
+static int irlap_state_offline(struct irlap_cb *self, IRLAP_EVENT event, 
+			       struct sk_buff *skb, struct irlap_info *info) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Unknown event\n");
+	IRDA_DEBUG( 0, __FUNCTION__ "(), Unknown event\n");
 
 	return -1;
 }
@@ -765,25 +841,23 @@
 {
 	int ret = 0;
 	
-	DEBUG(4, __FUNCTION__ "(), event=%s, vs=%d, vr=%d", 
-	      irlap_event[event], self->vs, self->vr);
-		
 	switch (event) {
 	case SEND_I_CMD:
 		/*
 		 *  Only send frame if send-window > 0.
 		 */ 
 		if ((self->window > 0) && (!self->remote_busy)) {
-
+#ifdef CONFIG_IRDA_DYNAMIC_WINDOW
 			/*
 			 *  Test if we have transmitted more bytes over the 
 			 *  link than its possible to do with the current 
 			 *  speed and turn-around-time.
 			 */
-			if ((skb->len+self->bofs_count) > self->bytes_left) {
-				DEBUG(4, __FUNCTION__ "(), Not allowed to "
-				      "transmit more bytes!\n");
-				skb_queue_head(&self->tx_list, skb);
+			if (skb->len > self->bytes_left) {
+				IRDA_DEBUG(4, __FUNCTION__ 
+					   "(), Not allowed to transmit more "
+					   "bytes!\n");
+				skb_queue_head(&self->txq, skb);
 
 				/*
 				 *  We should switch state to LAP_NRM_P, but
@@ -795,20 +869,20 @@
 				 */
 				return -EPROTO;
 			}
-			self->bytes_left -= (skb->len + self->bofs_count);
-
+			self->bytes_left -= skb->len;
+#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
 			/*
 			 *  Send data with poll bit cleared only if window > 1
 			 *  and there is more frames after this one to be sent
 			 */
-			if (( self->window > 1) && 
-			    skb_queue_len( &self->tx_list) > 0) 
+			if ((self->window > 1) && 
+			    skb_queue_len( &self->txq) > 0) 
 			{   
-				irlap_send_data_primary( self, skb);
-				irlap_next_state( self, LAP_XMIT_P);
+				irlap_send_data_primary(self, skb);
+				irlap_next_state(self, LAP_XMIT_P);
 			} else {
-				irlap_send_data_primary_poll( self, skb);
-				irlap_next_state( self, LAP_NRM_P);
+				irlap_send_data_primary_poll(self, skb);
+				irlap_next_state(self, LAP_NRM_P);
 				
 				/* 
 				 * Make sure state machine does not try to send
@@ -819,11 +893,11 @@
 #ifdef CONFIG_IRDA_FAST_RR
 			/* Peer may want to reply immediately */
 			self->fast_RR = FALSE;
-#endif
+#endif /* CONFIG_IRDA_FAST_RR */
 		} else {
-			DEBUG( 4, __FUNCTION__ 
-			       "(), Unable to send! remote busy?\n");
-			skb_queue_head(&self->tx_list, skb);
+			IRDA_DEBUG(4, __FUNCTION__ 
+				   "(), Unable to send! remote busy?\n");
+			skb_queue_head(&self->txq, skb);
 
 			/*
 			 *  The next ret is important, because it tells 
@@ -833,6 +907,8 @@
 		}
 		break;
 	case POLL_TIMER_EXPIRED:
+		IRDA_DEBUG(3, __FUNCTION__ "(), POLL_TIMER_EXPIRED (%ld)\n",
+			   jiffies);
 		irlap_send_rr_frame(self, CMD_FRAME);
 		irlap_start_final_timer(self, self->final_timeout);
 		irlap_next_state(self, LAP_NRM_P);
@@ -847,8 +923,11 @@
 		irlap_next_state(self, LAP_PCLOSE);
 		break;
 	default:
-		DEBUG(0, __FUNCTION__ "(), Unknown event %s\n", 
-		      irlap_event[event]);
+		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %s\n", 
+			   irlap_event[event]);
+		if (skb)
+			dev_kfree_skb(skb);
+
 		ret = -EINVAL;
 		break;
 	}
@@ -860,48 +939,51 @@
  *
  *    PCLOSE state
  */
-static int irlap_state_pclose( struct irlap_cb *self, IRLAP_EVENT event, 
-			       struct sk_buff *skb, struct irlap_info *info) 
+static int irlap_state_pclose(struct irlap_cb *self, IRLAP_EVENT event, 
+			      struct sk_buff *skb, struct irlap_info *info) 
 {
 	int ret = 0;
 
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(1, __FUNCTION__ "()\n");
 	
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == LAP_MAGIC, return -1;);	
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LAP_MAGIC, return -1;);	
 
-	switch( event) {
-	case RECV_UA_RSP:
-		del_timer( &self->final_timer);
+	switch (event) {
+	case RECV_UA_RSP: /* FALLTHROUGH */
+	case RECV_DM_RSP:
+		del_timer(&self->final_timer);
 		
-		irlap_apply_default_connection_parameters( self);
+		irlap_apply_default_connection_parameters(self);
 
 		/* Always switch state before calling upper layers */
-		irlap_next_state( self, LAP_NDM);
-
-		irlap_disconnect_indication( self, LAP_DISC_INDICATION);
-
+		irlap_next_state(self, LAP_NDM);
+		
+		irlap_disconnect_indication(self, LAP_DISC_INDICATION);
+		dev_kfree_skb(skb);
 		break;
 	case FINAL_TIMER_EXPIRED:
-		if ( self->retry_count < self->N3) {
-			irlap_wait_min_turn_around( self, &self->qos_tx);
-			irlap_send_disc_frame( self);
-			irlap_start_final_timer( self, self->final_timeout);
+		if (self->retry_count < self->N3) {
+			irlap_wait_min_turn_around(self, &self->qos_tx);
+			irlap_send_disc_frame(self);
+			irlap_start_final_timer(self, self->final_timeout);
 			self->retry_count++;
 			/* Keep state */
 		} else {
-			irlap_apply_default_connection_parameters( self);
+			irlap_apply_default_connection_parameters(self);
 
-			/* 
-			 *  Always switch state before calling upper layers 
-			 */
-			irlap_next_state( self, LAP_NDM);
+			/*  Always switch state before calling upper layers */
+			irlap_next_state(self, LAP_NDM);
 
-			irlap_disconnect_indication( self, LAP_NO_RESPONSE);
+			irlap_disconnect_indication(self, LAP_NO_RESPONSE);
 		}
 		break;
 	default:
-		DEBUG(1, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d\n", event);
+
+		if (skb)
+			dev_kfree_skb(skb);
+
 		ret = -1;
 		break;	
 	}
@@ -934,7 +1016,7 @@
 		 *  to transmitt
 		 */
 		self->fast_RR = FALSE;
-#endif
+#endif /* CONFIG_IRDA_FAST_RR */
 		ASSERT( info != NULL, return -1;);
 
 		ns_status = irlap_validate_ns_received(self, info->ns);
@@ -944,9 +1026,7 @@
 		 *  Check for expected I(nformation) frame
 		 */
 		if ((ns_status == NS_EXPECTED) && (nr_status == NR_EXPECTED)) {
-			/* 
-			 *  poll bit cleared?
-			 */
+			/*  poll bit cleared?  */
 			if (!info->pf) {
 				self->vr = (self->vr + 1) % 8;
 			
@@ -958,7 +1038,7 @@
 				/* Keep state, do not move this line */
 				irlap_next_state(self, LAP_NRM_P);
 				
-				irlap_data_indication(self, skb);
+				irlap_data_indication(self, skb, FALSE);
 			} else {
 				del_timer(&self->final_timer);
 
@@ -982,21 +1062,18 @@
 				 */
 				irlap_next_state(self, LAP_XMIT_P);
 			
-				irlap_data_indication(self, skb);
+				irlap_data_indication(self, skb, FALSE);
 
 				/* This is the last frame */
 				irlap_start_poll_timer(self, self->poll_timeout);
 			}
-			break;
-			
+			break;			
 		}
-		/*
-		 *  Unexpected next to send (Ns)
-		 */
+		/* Unexpected next to send (Ns) */
 		if ((ns_status == NS_UNEXPECTED) && (nr_status == NR_EXPECTED))
 		{
-			if ( !info->pf) {
-				irlap_update_nr_received( self, info->nr);
+			if (!info->pf) {
+				irlap_update_nr_received(self, info->nr);
 				
 				/*
 				 *  Wait until the last frame before doing 
@@ -1004,23 +1081,23 @@
 				 */
 
 				/* Keep state */
-				irlap_next_state( self, LAP_NRM_P);
+				irlap_next_state(self, LAP_NRM_P);
 			} else {
-				DEBUG( 4, __FUNCTION__
+				IRDA_DEBUG(4, __FUNCTION__
 				       "(), missing or duplicate frame!\n");
 				
 				/* Update Nr received */
-				irlap_update_nr_received( self, info->nr);
+				irlap_update_nr_received(self, info->nr);
 				
-				irlap_wait_min_turn_around( self, &self->qos_tx);
-				irlap_send_rr_frame( self, CMD_FRAME);
+				irlap_wait_min_turn_around(self, &self->qos_tx);
+				irlap_send_rr_frame(self, CMD_FRAME);
 				
 				self->ack_required = FALSE;
 			
-				irlap_start_final_timer( self, self->final_timeout);
-				irlap_next_state( self, LAP_NRM_P);
+				irlap_start_final_timer(self, self->final_timeout);
+				irlap_next_state(self, LAP_NRM_P);
 			}
-			dev_kfree_skb( skb);
+			dev_kfree_skb(skb);
 			break;
 		}
 		/* 
@@ -1028,22 +1105,22 @@
 		 */
 		if ((ns_status == NS_EXPECTED) && (nr_status == NR_UNEXPECTED))
 		{
-			if ( info->pf) {
+			if (info->pf) {
 				self->vr = (self->vr + 1) % 8;
 			
 				/* Update Nr received */
-				irlap_update_nr_received( self, info->nr);
+				irlap_update_nr_received(self, info->nr);
 			
 				/* Resend rejected frames */
-				irlap_resend_rejected_frames( self, CMD_FRAME);
+				irlap_resend_rejected_frames(self, CMD_FRAME);
 				
 				self->ack_required = FALSE;
-				irlap_start_final_timer( self, self->final_timeout);
+				irlap_start_final_timer(self, self->final_timeout);
 				
 				/* Keep state, do not move this line */
-				irlap_next_state( self, LAP_NRM_P);
+				irlap_next_state(self, LAP_NRM_P);
 				
-				irlap_data_indication( self, skb);
+				irlap_data_indication(self, skb, FALSE);
 			} else {
 				/* 
 				 *  Do not resend frames until the last
@@ -1054,14 +1131,14 @@
 				self->vr = (self->vr + 1) % 8;
 
 				/* Update Nr received */
-				irlap_update_nr_received( self, info->nr);
+				irlap_update_nr_received(self, info->nr);
 				
 				self->ack_required = FALSE;
 
 				/* Keep state, do not move this line!*/
-				irlap_next_state( self, LAP_NRM_P); 
+				irlap_next_state(self, LAP_NRM_P); 
 				
-				irlap_data_indication( self, skb);
+				irlap_data_indication(self, skb, FALSE);
 			}
 			break;
 		}
@@ -1072,22 +1149,24 @@
 		if ((ns_status == NS_UNEXPECTED) && 
 		    (nr_status == NR_UNEXPECTED)) 
 		{
-			DEBUG( 4, "IrLAP: unexpected nr and ns!\n");
-			if ( info->pf) {
+			IRDA_DEBUG(4, __FUNCTION__ 
+				   "(), unexpected nr and ns!\n");
+			if (info->pf) {
 				/* Resend rejected frames */
-				irlap_resend_rejected_frames( self, CMD_FRAME);
+				irlap_resend_rejected_frames(self, CMD_FRAME);
 				
 				/* Give peer some time to retransmit! */
-				irlap_start_final_timer( self, self->final_timeout);
+				irlap_start_final_timer(self, self->final_timeout);
 
 				/* Keep state, do not move this line */
-				irlap_next_state( self, LAP_NRM_P);
+				irlap_next_state(self, LAP_NRM_P);
 			} else {
 				/* Update Nr received */
 				/* irlap_update_nr_received( info->nr); */
 				
 				self->ack_required = FALSE;
 			}
+			dev_kfree_skb(skb);
 			break;
 		}
 
@@ -1099,7 +1178,7 @@
 				del_timer(&self->final_timer);
 				
 				irlap_next_state(self, LAP_RESET_WAIT);
-
+				
 				irlap_disconnect_indication(self, LAP_RESET_INDICATION);
 				self->xmitflag = TRUE;
 			} else {
@@ -1109,21 +1188,22 @@
 				
 				self->xmitflag = FALSE;
 			}
+			dev_kfree_skb(skb);
 			break;
 		}
-		DEBUG(1, __FUNCTION__ "(), Not implemented!\n");
-		DEBUG(1, __FUNCTION__ 
+		IRDA_DEBUG(1, __FUNCTION__ "(), Not implemented!\n");
+		IRDA_DEBUG(1, __FUNCTION__ 
 		      "(), event=%s, ns_status=%d, nr_status=%d\n", 
 		      irlap_event[ event], ns_status, nr_status);
 		break;
 	case RECV_UI_FRAME:
-		/*  poll bit cleared?  */
+		/* Poll bit cleared? */
 		if (!info->pf) {
-			irlap_unit_data_indication(self, skb);
+			irlap_data_indication(self, skb, TRUE);
 			irlap_next_state(self, LAP_NRM_P);
 		} else {
 			del_timer(&self->final_timer);
-			irlap_unit_data_indication(self, skb);
+			irlap_data_indication(self, skb, TRUE);
 			irlap_start_poll_timer(self, self->poll_timeout);
 		}
 		break;
@@ -1158,63 +1238,56 @@
 			/* Start poll timer */
 			irlap_start_poll_timer(self, self->poll_timeout);
 		} else if (ret == NR_UNEXPECTED) {
-			ASSERT( info != NULL, return -1;);	
+			ASSERT(info != NULL, return -1;);	
 			/* 
 			 *  Unexpected nr! 
 			 */
 			
 			/* Update Nr received */
-			irlap_update_nr_received( self, info->nr);
+			irlap_update_nr_received(self, info->nr);
 
-			DEBUG( 4, "RECV_RR_FRAME: Retrans:%d, nr=%d, va=%d, "
-			       "vs=%d, vr=%d\n",
-			       self->retry_count, info->nr, self->va, 
-			       self->vs, self->vr);
+			IRDA_DEBUG(4, "RECV_RR_FRAME: Retrans:%d, nr=%d, va=%d, "
+			      "vs=%d, vr=%d\n",
+			      self->retry_count, info->nr, self->va, 
+			      self->vs, self->vr);
 			
 			/* Resend rejected frames */
-			irlap_resend_rejected_frames( self, CMD_FRAME);
+			irlap_resend_rejected_frames(self, CMD_FRAME);
 			
-			irlap_next_state( self, LAP_NRM_P);
+			irlap_next_state(self, LAP_NRM_P);
 		} else if (ret == NR_INVALID) {
-			DEBUG(1, "irlap_state_nrm_p: received RR with "
-			      "invalid nr !\n");
-			del_timer( &self->final_timer);
+			IRDA_DEBUG(1, __FUNCTION__ "(), Received RR with "
+				   "invalid nr !\n");
+			del_timer(&self->final_timer);
 
-			irlap_next_state( self, LAP_RESET_WAIT);
+			irlap_next_state(self, LAP_RESET_WAIT);
 
 			irlap_disconnect_indication(self, LAP_RESET_INDICATION);
 			self->xmitflag = TRUE;
 		}
-		if (skb)
-			dev_kfree_skb( skb);
+		dev_kfree_skb(skb);
 		break;
-	case RECV_RNR_FRAME:
-		DEBUG( 4, "irlap_state_nrm_p: RECV_RNR_FRAME: Retrans:%d, "
-		       "nr=%d, va=%d, vs=%d, vr=%d\n",
-		       self->retry_count, info->nr, self->va, self->vs, 
-		       self->vr);
-
-		ASSERT( info != NULL, return -1;);
+	case RECV_RNR_RSP:
+		ASSERT(info != NULL, return -1;);
 
 		/* Stop final timer */
-		del_timer( &self->final_timer);
+		del_timer(&self->final_timer);
 		self->remote_busy = TRUE;
 
 		/* Update Nr received */
-		irlap_update_nr_received( self, info->nr);
-
-		irlap_next_state( self, LAP_XMIT_P);
+		irlap_update_nr_received(self, info->nr);
+		irlap_next_state(self, LAP_XMIT_P);
 			
 		/* Start poll timer */
-		irlap_start_poll_timer( self, self->poll_timeout);
-
-		dev_kfree_skb( skb);
+		irlap_start_poll_timer(self, self->poll_timeout);
+		dev_kfree_skb(skb);
 		break;
 	case RECV_FRMR_RSP:
-		del_timer( &self->final_timer);
+		del_timer(&self->final_timer);
 		self->xmitflag = TRUE;
-		irlap_next_state( self, LAP_RESET_WAIT);
-		irlap_reset_indication( self);
+		irlap_next_state(self, LAP_RESET_WAIT);
+		irlap_reset_indication(self);
+		dev_kfree_skb(skb);
 		break;
 	case FINAL_TIMER_EXPIRED:
 		/* 
@@ -1223,11 +1296,12 @@
 		 *  of receiving a frame (page 45, IrLAP). Check that
 		 *  we only do this once for each frame.
 		 */
-		if ( irda_device_is_receiving( self->irdev) && 
-		     !self->add_wait) {
-			DEBUG( 4, "FINAL_TIMER_EXPIRED when receiving a "
-			       "frame! Waiting a little bit more!\n");
-			irlap_start_final_timer( self, 30);
+		if (irda_device_is_receiving(self->netdev) && 
+		    !self->add_wait) 
+		{
+			IRDA_DEBUG(1, "FINAL_TIMER_EXPIRED when receiving a "
+			      "frame! Waiting a little bit more!\n");
+			irlap_start_final_timer(self, MSECS_TO_JIFFIES(300));
 
 			/*
 			 *  Don't allow this to happen one more time in a row, 
@@ -1239,60 +1313,72 @@
 		}
 		self->add_wait = FALSE;
 
-		if (( self->retry_count < self->N2) && 
-		    ( self->retry_count != self->N1)) {
+		if ((self->retry_count < self->N2) && 
+		    (self->retry_count != self->N1)) {
 			
-			irlap_wait_min_turn_around( self, &self->qos_tx);
-			irlap_send_rr_frame( self, CMD_FRAME);
+			irlap_wait_min_turn_around(self, &self->qos_tx);
+			irlap_send_rr_frame(self, CMD_FRAME);
 			
-			irlap_start_final_timer( self, self->final_timeout);
+			irlap_start_final_timer(self, self->final_timeout);
 		 	self->retry_count++;
 
-			DEBUG( 4, "irlap_state_nrm_p: FINAL_TIMER_EXPIRED:"
-			       " retry_count=%d\n", self->retry_count);
+			IRDA_DEBUG(4, "irlap_state_nrm_p: FINAL_TIMER_EXPIRED:"
+				   " retry_count=%d\n", self->retry_count);
 			/* Keep state */
-		} else if ( self->retry_count == self->N1) {
-			irlap_status_indication( STATUS_NO_ACTIVITY);
-			irlap_wait_min_turn_around( self, &self->qos_tx);
-			irlap_send_rr_frame( self, CMD_FRAME);
+		} else if (self->retry_count == self->N1) {
+			irlap_status_indication(STATUS_NO_ACTIVITY);
+			irlap_wait_min_turn_around(self, &self->qos_tx);
+			irlap_send_rr_frame(self, CMD_FRAME);
 			
-			irlap_start_final_timer( self, self->final_timeout);
+			irlap_start_final_timer(self, self->final_timeout);
 			self->retry_count++;
 
-			DEBUG( 4, "retry count = N1; retry_count=%d\n", 
-			       self->retry_count);
+			IRDA_DEBUG(4, "retry count = N1; retry_count=%d\n", 
+				   self->retry_count);
 			/* Keep state */
-		} else if ( self->retry_count >= self->N2) {
-			irlap_apply_default_connection_parameters( self);
+		} else if (self->retry_count >= self->N2) {
+			irlap_apply_default_connection_parameters(self);
 
 			/* Always switch state before calling upper layers */
-			irlap_next_state( self, LAP_NDM);
-			irlap_disconnect_indication( self, LAP_NO_RESPONSE);
+			irlap_next_state(self, LAP_NDM);
+			irlap_disconnect_indication(self, LAP_NO_RESPONSE);
 		}
 		break;
-	case RECV_DISC_FRAME: /* FIXME: Check how this is in the standard! */
-		DEBUG(1, __FUNCTION__ "(), RECV_DISC_FRAME()\n");
-
-		/* Always switch state before calling upper layers */
-		irlap_next_state( self, LAP_NDM);
-		
-		irlap_wait_min_turn_around( self, &self->qos_tx);
-		irlap_send_ua_response_frame( self, NULL);
-
- 		del_timer( &self->final_timer);
-		/* del_timer( &self->poll_timer); */
-
-		irlap_flush_all_queues( self);
-		irlap_apply_default_connection_parameters( self);
+	case RECV_REJ_RSP:
+		irlap_update_nr_received(self, info->nr);
+		if (self->remote_busy) {
+			irlap_wait_min_turn_around(self, &self->qos_tx);
+			irlap_send_rr_frame(self, CMD_FRAME);
+		} else
+			irlap_resend_rejected_frames(self, CMD_FRAME);
+		irlap_start_final_timer(self, self->final_timeout);
+		dev_kfree_skb(skb);
+		break;
+	case RECV_SREJ_RSP:
+		irlap_update_nr_received(self, info->nr);
+		if (self->remote_busy) {
+			irlap_wait_min_turn_around(self, &self->qos_tx);
+			irlap_send_rr_frame(self, CMD_FRAME);
+		} else
+			irlap_resend_rejected_frame(self, CMD_FRAME);
+		irlap_start_final_timer(self, self->final_timeout);
+		dev_kfree_skb(skb);
+		break;
+	case RECV_RD_RSP:
+		IRDA_DEBUG(0, __FUNCTION__ "(), RECV_RD_RSP\n");
 
-		irlap_disconnect_indication( self, LAP_DISC_INDICATION);
-		if (skb)
-			dev_kfree_skb( skb);
-		
+		irlap_next_state(self, LAP_PCLOSE);
+		irlap_send_disc_frame(self);
+		irlap_flush_all_queues(self);
+		irlap_start_final_timer(self, self->final_timeout);
+		self->retry_count = 0;
 		break;
 	default:
-		DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
-		      irlap_event[event]);
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
+			   irlap_event[event]);
+		if (skb)
+			dev_kfree_skb(skb);
+
 		ret = -1;
 		break;
 	}
@@ -1311,21 +1397,21 @@
 {
 	int ret = 0;
 	
-	DEBUG( 3, __FUNCTION__ "(), event = %s\n", irlap_event[event]);
+	IRDA_DEBUG(3, __FUNCTION__ "(), event = %s\n", irlap_event[event]);
 	
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == LAP_MAGIC, return -1;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LAP_MAGIC, return -1;);
 	
-	switch( event) {
+	switch (event) {
 	case RESET_REQUEST:
-		if ( self->xmitflag) {
-			irlap_wait_min_turn_around( self, &self->qos_tx);
-			irlap_send_snrm_frame( self, NULL);
-			irlap_start_final_timer( self, self->final_timeout);
-			irlap_next_state( self, LAP_RESET);
+		if (self->xmitflag) {
+			irlap_wait_min_turn_around(self, &self->qos_tx);
+			irlap_send_snrm_frame(self, NULL);
+			irlap_start_final_timer(self, self->final_timeout);
+			irlap_next_state(self, LAP_RESET);
 		} else {
-			irlap_start_final_timer( self, self->final_timeout);
-			irlap_next_state( self, LAP_RESET);
+			irlap_start_final_timer(self, self->final_timeout);
+			irlap_next_state(self, LAP_RESET);
 		}
 		break;
 	case DISCONNECT_REQUEST:
@@ -1337,8 +1423,11 @@
 		irlap_next_state( self, LAP_PCLOSE);
 		break;
 	default:
-		DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
-		      irlap_event[event]);
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
+			   irlap_event[event]);
+		if (skb)
+			dev_kfree_skb(skb);
+
 		ret = -1;
 		break;	
 	}
@@ -1352,76 +1441,90 @@
  *    reply.
  *
  */
-static int irlap_state_reset( struct irlap_cb *self, IRLAP_EVENT event, 
-			      struct sk_buff *skb, struct irlap_info *info)
+static int irlap_state_reset(struct irlap_cb *self, IRLAP_EVENT event, 
+			     struct sk_buff *skb, struct irlap_info *info)
 {
 	int ret = 0;
 	
-	DEBUG(3, __FUNCTION__ "(), event = %s\n", irlap_event[event]);
+	IRDA_DEBUG(3, __FUNCTION__ "(), event = %s\n", irlap_event[event]);
 	
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == LAP_MAGIC, return -1;);
 	
-	switch(event) {
-	case RECV_DISC_FRAME:
+	switch (event) {
+	case RECV_DISC_CMD:
 		del_timer(&self->final_timer);
 
-		irlap_apply_default_connection_parameters( self);
+		irlap_apply_default_connection_parameters(self);
 
 		/* Always switch state before calling upper layers */
-		irlap_next_state( self, LAP_NDM);
+		irlap_next_state(self, LAP_NDM);
+
+		irlap_disconnect_indication(self, LAP_NO_RESPONSE);
 
-		irlap_disconnect_indication( self, LAP_NO_RESPONSE);
+		dev_kfree_skb(skb);
 		break;
 	case RECV_UA_RSP:
-		del_timer( &self->final_timer);
+		del_timer(&self->final_timer);
 		
 		/* Initiate connection state */
-		irlap_initiate_connection_state( self);
+		irlap_initiate_connection_state(self);
 		
 		irlap_reset_confirm();
 		
 		self->remote_busy = FALSE;
 
-		irlap_next_state( self, LAP_XMIT_P);
+		irlap_next_state(self, LAP_XMIT_P);
 
-		irlap_start_poll_timer( self, self->poll_timeout);
+		irlap_start_poll_timer(self, self->poll_timeout);
+
+		dev_kfree_skb(skb);
 		break;
 	case FINAL_TIMER_EXPIRED:
-		if ( self->retry_count < 3) {
-			irlap_wait_min_turn_around( self, &self->qos_tx);
+		if (self->retry_count < 3) {
+			irlap_wait_min_turn_around(self, &self->qos_tx);
 
-			ASSERT( self->irdev != NULL, return -1;);
-			irlap_send_snrm_frame(self, 
-					      irda_device_get_qos( self->irdev));
+			ASSERT(self->netdev != NULL, return -1;);
+			irlap_send_snrm_frame(self, self->qos_dev);
 
 			self->retry_count++; /* Experimental!! */
 
-			irlap_start_final_timer( self, self->final_timeout);
-			irlap_next_state( self, LAP_RESET);
-		} else if ( self->retry_count >= self->N3) {
-			irlap_apply_default_connection_parameters( self);
+			irlap_start_final_timer(self, self->final_timeout);
+			irlap_next_state(self, LAP_RESET);
+		} else if (self->retry_count >= self->N3) {
+			irlap_apply_default_connection_parameters(self);
 			
 			/* Always switch state before calling upper layers */
-			irlap_next_state( self, LAP_NDM);
+			irlap_next_state(self, LAP_NDM);
 			
-			irlap_disconnect_indication( self, LAP_NO_RESPONSE);
+			irlap_disconnect_indication(self, LAP_NO_RESPONSE);
 		}
 		break;
-
 	case RECV_SNRM_CMD:
-		DEBUG(3, "lap_reset: RECV_SNRM_CMD\n");
-		irlap_initiate_connection_state( self);
-		irlap_wait_min_turn_around( self, &self->qos_tx);
-		irlap_send_ua_response_frame( self, &self->qos_rx);
-		irlap_reset_confirm();
-		irlap_start_wd_timer( self, self->wd_timeout);
-		irlap_next_state( self, LAP_NDM);
+		/* 
+		 * SNRM frame is not allowed to contain an I-field in this 
+		 * state
+		 */
+		if (!info) {
+			IRDA_DEBUG(3, __FUNCTION__ "(), RECV_SNRM_CMD\n");
+			irlap_initiate_connection_state(self);
+			irlap_wait_min_turn_around(self, &self->qos_tx);
+			irlap_send_ua_response_frame(self, &self->qos_rx);
+			irlap_reset_confirm();
+			irlap_start_wd_timer(self, self->wd_timeout);
+			irlap_next_state(self, LAP_NDM);
+		} else {
+			IRDA_DEBUG(0, __FUNCTION__ 
+				   "(), SNRM frame contained an I field!\n");
+		}
+		dev_kfree_skb(skb);
 		break;
-
 	default:
-		DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
-		      irlap_event[ event]);
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
+			   irlap_event[event]);	
+		if (skb)
+			dev_kfree_skb(skb);
+
 		ret = -1;
 		break;	
 	}
@@ -1435,54 +1538,54 @@
  *   and we therefor do not expect to receive any transmissions from other
  *   stations.  
  */
-static int irlap_state_xmit_s( struct irlap_cb *self, IRLAP_EVENT event, 
-			       struct sk_buff *skb, struct irlap_info *info) 
+static int irlap_state_xmit_s(struct irlap_cb *self, IRLAP_EVENT event, 
+			      struct sk_buff *skb, struct irlap_info *info) 
 {
 	int ret = 0;
 	
-	DEBUG( 4, __FUNCTION__ "(), event=%s\n", irlap_event[ event]); 
+	IRDA_DEBUG(4, __FUNCTION__ "(), event=%s\n", irlap_event[event]); 
 
-	ASSERT( self != NULL, return -ENODEV;);
-	ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
+	ASSERT(self != NULL, return -ENODEV;);
+	ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
 	
-	switch( event) {
+	switch (event) {
 	case SEND_I_CMD:
 		/*
 		 *  Send frame only if send window > 1
 		 */ 
-		if ((self->window > 0) && ( !self->remote_busy)) {
+		if ((self->window > 0) && (!self->remote_busy)) {
+#ifdef CONFIG_IRDA_DYNAMIC_WINDOW
 			/*
 			 *  Test if we have transmitted more bytes over the 
 			 *  link than its possible to do with the current 
 			 *  speed and turn-around-time.
 			 */
-			if ((skb->len+self->bofs_count) > self->bytes_left) {
-				DEBUG( 4, "IrDA: Not allowed to transmit more bytes!\n");
-				skb_queue_head( &self->tx_list, skb);
+			if (skb->len > self->bytes_left) {
+				skb_queue_head(&self->txq, skb);
 				/*
 				 *  Switch to NRM_S, this is only possible
 				 *  when we are in secondary mode, since we 
 				 *  must be sure that we don't miss any RR
 				 *  frames
 				 */
-				irlap_next_state( self, LAP_NRM_S);
+				irlap_next_state(self, LAP_NRM_S);
 
 				return -EPROTO; /* Try again later */
 			}
-			self->bytes_left -= ( skb->len + self->bofs_count);
-
+			self->bytes_left -= skb->len;
+#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
 			/*
 			 *  Send data with final bit cleared only if window > 1
 			 *  and there is more frames to be sent
 			 */
-			if (( self->window > 1) && 
-			    skb_queue_len( &self->tx_list) > 0) 
+			if ((self->window > 1) && 
+			    skb_queue_len(&self->txq) > 0) 
 			{   
-				irlap_send_data_secondary( self, skb);
-				irlap_next_state( self, LAP_XMIT_S);
+				irlap_send_data_secondary(self, skb);
+				irlap_next_state(self, LAP_XMIT_S);
 			} else {
-				irlap_send_data_secondary_final( self, skb);
-				irlap_next_state( self, LAP_NRM_S);
+				irlap_send_data_secondary_final(self, skb);
+				irlap_next_state(self, LAP_NRM_S);
 
 				/* 
 				 * Make sure state machine does not try to send
@@ -1491,14 +1594,23 @@
 				ret = -EPROTO;
 			}
 		} else {
-			DEBUG(1, __FUNCTION__ "(), Unable to send!\n");
-			skb_queue_head( &self->tx_list, skb);
+			IRDA_DEBUG(2, __FUNCTION__ "(), Unable to send!\n");
+			skb_queue_head(&self->txq, skb);
 			ret = -EPROTO;
 		}
 		break;
+	case DISCONNECT_REQUEST:
+		irlap_send_rd_frame(self);
+		irlap_flush_all_queues(self);
+		irlap_start_wd_timer(self, self->wd_timeout);
+		irlap_next_state(self, LAP_SCLOSE);
+		break;
 	default:
-		DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
-		      irlap_event[ event]);
+		IRDA_DEBUG(2, __FUNCTION__ "(), Unknown event %s\n", 
+			   irlap_event[event]);
+		if (skb)
+			dev_kfree_skb(skb);
+
 		ret = -EINVAL;
 		break;
 	}
@@ -1512,29 +1624,29 @@
  *    expecting to receive frames from the primary station
  *
  */
-static int irlap_state_nrm_s( struct irlap_cb *self, IRLAP_EVENT event, 
-			      struct sk_buff *skb, struct irlap_info *info) 
+static int irlap_state_nrm_s(struct irlap_cb *self, IRLAP_EVENT event, 
+			     struct sk_buff *skb, struct irlap_info *info) 
 {
-	int ret = 0;
 	int ns_status;
 	int nr_status;
+	int ret = 0;
 
-	DEBUG( 4, __FUNCTION__ "(), event=%s\n", irlap_event[ event]);
+	IRDA_DEBUG(4, __FUNCTION__ "(), event=%s\n", irlap_event[ event]);
 
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == LAP_MAGIC, return -1;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LAP_MAGIC, return -1;);
 
-	switch(event) {
+	switch (event) {
 	case RECV_I_CMD: /* Optimize for the common case */
 		/* FIXME: must check for remote_busy below */
-		DEBUG( 4, __FUNCTION__ "(), event=%s nr=%d, vs=%d, ns=%d, "
-		       "vr=%d, pf=%d\n", irlap_event[event], info->nr, 
-		       self->vs, info->ns, self->vr, info->pf);
+		IRDA_DEBUG(4, __FUNCTION__ "(), event=%s nr=%d, vs=%d, ns=%d, "
+			   "vr=%d, pf=%d\n", irlap_event[event], info->nr, 
+			   self->vs, info->ns, self->vr, info->pf);
 
 		self->retry_count = 0;
 
-		ns_status = irlap_validate_ns_received( self, info->ns);
-		nr_status = irlap_validate_nr_received( self, info->nr);
+		ns_status = irlap_validate_ns_received(self, info->ns);
+		nr_status = irlap_validate_nr_received(self, info->nr);
 		/* 
 		 *  Check for expected I(nformation) frame
 		 */
@@ -1546,7 +1658,7 @@
 				self->vr = (self->vr + 1) % 8;
 				
 				/* Update Nr received */
-				irlap_update_nr_received( self, info->nr);
+				irlap_update_nr_received(self, info->nr);
 				
 				self->ack_required = TRUE;
 				
@@ -1554,18 +1666,19 @@
 				 *  Starting WD-timer here is optional, but
 				 *  not recommended. Note 6 IrLAP p. 83
 				 */
-				/* irda_start_timer( WD_TIMER, self->wd_timeout); */
-
+#if 0
+				irda_start_timer(WD_TIMER, self->wd_timeout);
+#endif
 				/* Keep state, do not move this line */
-				irlap_next_state( self, LAP_NRM_S);
+				irlap_next_state(self, LAP_NRM_S);
 				
-				irlap_data_indication( self, skb);
+				irlap_data_indication(self, skb, FALSE);
 				break;
 			} else {
 				self->vr = (self->vr + 1) % 8;
 				
 				/* Update Nr received */
-				irlap_update_nr_received( self, info->nr);
+				irlap_update_nr_received(self, info->nr);
 				
 				/* 
 				 *  We should wait before sending RR, and
@@ -1580,10 +1693,10 @@
 				 * we decide if we should send a RR frame
 				 * or not
 				 */
-				irlap_data_indication(self, skb);
+				irlap_data_indication(self, skb, FALSE);
 
 				/* Any pending data requests?  */
-				if ((skb_queue_len(&self->tx_list) > 0) && 
+				if ((skb_queue_len(&self->txq) > 0) && 
 				    (self->window > 0)) 
 				{
 					self->ack_required = TRUE;
@@ -1593,7 +1706,8 @@
 					irlap_next_state(self, LAP_XMIT_S);
 				} else {
 					irlap_send_rr_frame(self, RSP_FRAME);
-					irlap_start_wd_timer(self, self->wd_timeout);
+					irlap_start_wd_timer(self, 
+							     self->wd_timeout);
 
 					/* Keep the state */
 					irlap_next_state(self, LAP_NRM_S);
@@ -1607,20 +1721,20 @@
 		if ((ns_status == NS_UNEXPECTED) && (nr_status == NR_EXPECTED))
 		{
 			/* Unexpected next to send, with final bit cleared */
-			if ( !info->pf) {
-				irlap_update_nr_received( self, info->nr);
+			if (!info->pf) {
+				irlap_update_nr_received(self, info->nr);
 				
-				irlap_start_wd_timer( self, self->wd_timeout);
+				irlap_start_wd_timer(self, self->wd_timeout);
 			} else {
 				/* Update Nr received */
-				irlap_update_nr_received( self, info->nr);
+				irlap_update_nr_received(self, info->nr);
 			
-				irlap_wait_min_turn_around( self, &self->qos_tx);
-				irlap_send_rr_frame( self, CMD_FRAME);
+				irlap_wait_min_turn_around(self, &self->qos_tx);
+				irlap_send_rr_frame(self, CMD_FRAME);
 			
-				irlap_start_wd_timer( self, self->wd_timeout);
+				irlap_start_wd_timer(self, self->wd_timeout);
 			}
-			dev_kfree_skb( skb);
+			dev_kfree_skb(skb);
 			break;
 		}
 
@@ -1629,81 +1743,83 @@
 		 */
 		if ((ns_status == NS_EXPECTED) && (nr_status == NR_UNEXPECTED))
 		{
-			if ( info->pf) {
-				DEBUG( 4, "RECV_I_RSP: frame(s) lost\n");
+			if (info->pf) {
+				IRDA_DEBUG(4, "RECV_I_RSP: frame(s) lost\n");
 				
 				self->vr = (self->vr + 1) % 8;
 				
 				/* Update Nr received */
-				irlap_update_nr_received( self, info->nr);
+				irlap_update_nr_received(self, info->nr);
 				
 				/* Resend rejected frames */
-				irlap_resend_rejected_frames( self, RSP_FRAME);
+				irlap_resend_rejected_frames(self, RSP_FRAME);
 
 				/* Keep state, do not move this line */
-				irlap_next_state( self, LAP_NRM_S);
-
-				irlap_data_indication( self, skb);
-				irlap_start_wd_timer( self, self->wd_timeout);
+				irlap_next_state(self, LAP_NRM_S);
 
+				irlap_data_indication(self, skb, FALSE);
+				irlap_start_wd_timer(self, self->wd_timeout);
 				break;
 			}
 			/*
 			 *  This is not documented in IrLAP!! Unexpected NR
 			 *  with poll bit cleared
 			 */
-			if ( !info->pf) {
+			if (!info->pf) {
 				self->vr = (self->vr + 1) % 8;
 				
 				/* Update Nr received */
-				irlap_update_nr_received( self, info->nr);
+				irlap_update_nr_received(self, info->nr);
 				
 				/* Keep state, do not move this line */
-				irlap_next_state( self, LAP_NRM_S);
+				irlap_next_state(self, LAP_NRM_S);
 				
-				irlap_data_indication( self, skb);
-				irlap_start_wd_timer( self, self->wd_timeout);
+				irlap_data_indication(self, skb, FALSE);
+				irlap_start_wd_timer(self, self->wd_timeout);
 			}
+			break;
 		}
 		
-		if ( ret == NR_INVALID) {
-			DEBUG( 0, "NRM_S, NR_INVALID not implemented!\n");
+		if (ret == NR_INVALID) {
+			IRDA_DEBUG(0, "NRM_S, NR_INVALID not implemented!\n");
+			dev_kfree_skb(skb);
 		}
-		if ( ret == NS_INVALID) {
-			DEBUG( 0, "NRM_S, NS_INVALID not implemented!\n");
+		if (ret == NS_INVALID) {
+			IRDA_DEBUG(0, "NRM_S, NS_INVALID not implemented!\n");
+			dev_kfree_skb(skb);
 		}
 		break;
 	case RECV_UI_FRAME:
 		/* 
 		 *  poll bit cleared?
 		 */
-		if ( !info->pf) {
-			irlap_unit_data_indication( self, skb);
-			irlap_next_state( self, LAP_NRM_S); /* Keep state */
+		if (!info->pf) {
+			irlap_data_indication(self, skb, TRUE);
+			irlap_next_state(self, LAP_NRM_S); /* Keep state */
 		} else {
 			/*
 			 *  Any pending data requests?
 			 */
-			if (( skb_queue_len( &self->tx_list) > 0) && 
-			    ( self->window > 0) && !self->remote_busy) 
+			if ((skb_queue_len(&self->txq) > 0) && 
+			    (self->window > 0) && !self->remote_busy) 
 			{
-				irlap_unit_data_indication( self, skb);
+				irlap_data_indication(self, skb, TRUE);
 				
-				del_timer( &self->wd_timer);
+				del_timer(&self->wd_timer);
 
-				irlap_next_state( self, LAP_XMIT_S);
+				irlap_next_state(self, LAP_XMIT_S);
 			} else {
-				irlap_unit_data_indication( self, skb);
+				irlap_data_indication(self, skb, TRUE);
 
-				irlap_wait_min_turn_around( self, &self->qos_tx);
+				irlap_wait_min_turn_around(self, &self->qos_tx);
 
-				irlap_send_rr_frame( self, RSP_FRAME);
+				irlap_send_rr_frame(self, RSP_FRAME);
 				self->ack_required = FALSE;
 				
-				irlap_start_wd_timer( self, self->wd_timeout);
+				irlap_start_wd_timer(self, self->wd_timeout);
 
 				/* Keep the state */
-				irlap_next_state( self, LAP_NRM_S);
+				irlap_next_state(self, LAP_NRM_S);
 			}
 		}
 		break;
@@ -1713,18 +1829,18 @@
 		/* 
 		 *  Nr as expected? 
 		 */
-		nr_status = irlap_validate_nr_received( self, info->nr);
-		if ( nr_status == NR_EXPECTED) {
-			if (( skb_queue_len( &self->tx_list) > 0) && 
-			    ( self->window > 0)) {
+		nr_status = irlap_validate_nr_received(self, info->nr);
+		if (nr_status == NR_EXPECTED) {
+			if ((skb_queue_len( &self->txq) > 0) && 
+			    (self->window > 0)) {
 				self->remote_busy = FALSE;
 				
 				/* Update Nr received */
-				irlap_update_nr_received( self, info->nr);
-				del_timer( &self->wd_timer);
+				irlap_update_nr_received(self, info->nr);
+				del_timer(&self->wd_timer);
 				
 				irlap_wait_min_turn_around(self, &self->qos_tx);
-				irlap_next_state( self, LAP_XMIT_S);
+				irlap_next_state(self, LAP_XMIT_S);
 			} else {			
 				self->remote_busy = FALSE;
 				/* Update Nr received */
@@ -1738,99 +1854,120 @@
 			}
 		} else if (nr_status == NR_UNEXPECTED) {
 			self->remote_busy = FALSE;
-			irlap_update_nr_received( self, info->nr);
-			irlap_resend_rejected_frames( self, RSP_FRAME);
+			irlap_update_nr_received(self, info->nr);
+			irlap_resend_rejected_frames(self, RSP_FRAME);
 
-			irlap_start_wd_timer( self, self->wd_timeout);
+			irlap_start_wd_timer(self, self->wd_timeout);
 
 			/* Keep state */
-			irlap_next_state( self, LAP_NRM_S); 
+			irlap_next_state(self, LAP_NRM_S); 
 		} else {
-			DEBUG(1, __FUNCTION__ "(), invalid nr not implemented!\n");
+			IRDA_DEBUG(1, __FUNCTION__ 
+				   "(), invalid nr not implemented!\n");
 		} 
-		if (skb)
-			dev_kfree_skb(skb);
-
+		dev_kfree_skb(skb);
 		break;
 	case RECV_SNRM_CMD:
-		del_timer( &self->wd_timer);
-		DEBUG(1, __FUNCTION__ "(), received SNRM cmd\n");
-		irlap_next_state( self, LAP_RESET_CHECK);
-
-		irlap_reset_indication( self);
+		/* SNRM frame is not allowed to contain an I-field */
+		if (!info) {
+			del_timer(&self->wd_timer);
+			IRDA_DEBUG(1, __FUNCTION__ "(), received SNRM cmd\n");
+			irlap_next_state(self, LAP_RESET_CHECK);
+			
+			irlap_reset_indication(self);
+		} else {
+			IRDA_DEBUG(0, __FUNCTION__ 
+				   "(), SNRM frame contained an I-field!\n");
+			
+		}
+		dev_kfree_skb(skb);
+		break;
+	case RECV_REJ_CMD:
+		irlap_update_nr_received(self, info->nr);
+		if (self->remote_busy) {
+			irlap_wait_min_turn_around(self, &self->qos_tx);
+			irlap_send_rr_frame(self, CMD_FRAME);
+		} else
+			irlap_resend_rejected_frames(self, CMD_FRAME);
+		irlap_start_wd_timer(self, self->wd_timeout);
+		dev_kfree_skb(skb);
+		break;
+	case RECV_SREJ_CMD:
+		irlap_update_nr_received(self, info->nr);
+		if (self->remote_busy) {
+			irlap_wait_min_turn_around(self, &self->qos_tx);
+			irlap_send_rr_frame(self, CMD_FRAME);
+		} else
+			irlap_resend_rejected_frame(self, CMD_FRAME);
+		irlap_start_wd_timer(self, self->wd_timeout);
+		dev_kfree_skb(skb);
 		break;
 	case WD_TIMER_EXPIRED:
-		DEBUG( 4, "WD_TIMER_EXPIRED: %ld\n", jiffies);
-	
 		/*
 		 *  Wait until retry_count * n matches negotiated threshold/
 		 *  disconnect time (note 2 in IrLAP p. 82)
 		 */
-		DEBUG(1, __FUNCTION__ "(), retry_count = %d\n", 
-		      self->retry_count);
+		IRDA_DEBUG(1, __FUNCTION__ "(), retry_count = %d\n", 
+			   self->retry_count);
 
-		if (( self->retry_count < (self->N2/2))  && 
-		    ( self->retry_count != self->N1/2)) {
+		if ((self->retry_count < (self->N2/2))  && 
+		    (self->retry_count != self->N1/2)) {
 			
-			irlap_start_wd_timer( self, self->wd_timeout);
+			irlap_start_wd_timer(self, self->wd_timeout);
 			self->retry_count++;		
-		} else if ( self->retry_count == (self->N1/2)) {
-			irlap_status_indication( STATUS_NO_ACTIVITY);
-			irlap_start_wd_timer( self, self->wd_timeout);
+		} else if (self->retry_count == (self->N1/2)) {
+			irlap_status_indication(STATUS_NO_ACTIVITY);
+			irlap_start_wd_timer(self, self->wd_timeout);
 			self->retry_count++;
-		} else if ( self->retry_count >= self->N2/2) {
-			irlap_apply_default_connection_parameters( self);
+		} else if (self->retry_count >= self->N2/2) {
+			irlap_apply_default_connection_parameters(self);
 			
 			/* Always switch state before calling upper layers */
-			irlap_next_state( self, LAP_NDM);
+			irlap_next_state(self, LAP_NDM);
 
-			irlap_disconnect_indication( self, LAP_NO_RESPONSE);
+			irlap_disconnect_indication(self, LAP_NO_RESPONSE);
 		}
 		break;
-
-	case RECV_DISC_FRAME:
+	case RECV_DISC_CMD:
 		/* Always switch state before calling upper layers */
-		irlap_next_state( self, LAP_NDM);
+		irlap_next_state(self, LAP_NDM);
 
-		irlap_wait_min_turn_around( self, &self->qos_tx);
-		irlap_send_ua_response_frame( self, NULL);
-		del_timer( &self->wd_timer);
-		irlap_flush_all_queues( self);
-		irlap_apply_default_connection_parameters( self);
+		irlap_wait_min_turn_around(self, &self->qos_tx);
+		irlap_send_ua_response_frame(self, NULL);
+		del_timer(&self->wd_timer);
+		irlap_flush_all_queues(self);
+		irlap_apply_default_connection_parameters(self);
 
-		irlap_disconnect_indication( self, LAP_DISC_INDICATION);
-		if (skb)
-			dev_kfree_skb( skb);
-		
+		irlap_disconnect_indication(self, LAP_DISC_INDICATION);
+		dev_kfree_skb(skb);		
 		break;
-
 	case RECV_DISCOVERY_XID_CMD:
-		DEBUG( 3, "irlap_state_nrm_s: got event RECV_DISCOVER_XID_CMD!\n");
-		del_timer( &self->final_timer);
-		
-		irlap_apply_default_connection_parameters( self);
-
-		/* Always switch state before calling upper layers */
-		irlap_next_state( self, LAP_NDM);
+		irlap_wait_min_turn_around(self, &self->qos_tx);
+		irlap_send_rr_frame(self, RSP_FRAME);
+		self->ack_required = TRUE;
+		irlap_start_wd_timer(self, self->wd_timeout);
+		irlap_next_state(self, LAP_NRM_S);
 
-		irlap_disconnect_indication( self, LAP_DISC_INDICATION);
-		
-#if 0
-		irlap_wait_min_turn_around( self, &self->qos_session);
-		irlap_send_rr_frame( RSP_FRAME);
-		irda_start_timer( WD_TIMER, self->wd_timeout);
-		irlap_next_state( self, LAP_NRM_S);
-#endif
+		dev_kfree_skb(skb);
 		break;
 	case RECV_TEST_CMD:
+		/* Remove test frame header */
 		skb_pull(skb, sizeof(struct test_frame));
-		irlap_send_test_frame(self, info->daddr, skb);
+
+		irlap_wait_min_turn_around(self, &self->qos_tx);
+		irlap_start_wd_timer(self, self->wd_timeout);
+
+		/* Send response (info will be copied) */
+		irlap_send_test_frame(self, self->caddr, info->daddr, skb);
 		dev_kfree_skb(skb);
 		break;
 	default:
-		DEBUG(1, __FUNCTION__ "(), Unknown event %d, (%s)\n", 
-		      event, irlap_event[event]);
-		ret = -1;
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d, (%s)\n", 
+			   event, irlap_event[event]);
+		if (skb)
+			dev_kfree_skb(skb);
+
+		ret = -EINVAL;
 		break;
 	}
 	return ret;
@@ -1842,10 +1979,53 @@
  *    
  *
  */
-static int irlap_state_sclose( struct irlap_cb *self, IRLAP_EVENT event, 
-			       struct sk_buff *skb, struct irlap_info *info) 
+static int irlap_state_sclose(struct irlap_cb *self, IRLAP_EVENT event, 
+			      struct sk_buff *skb, struct irlap_info *info) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
+	int ret = 0;
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return -ENODEV;);
+	ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
+	
+	switch (event) {
+	case RECV_DISC_CMD:
+		/* Always switch state before calling upper layers */
+		irlap_next_state(self, LAP_NDM);
+		
+		irlap_wait_min_turn_around(self, &self->qos_tx);
+		irlap_send_ua_response_frame(self, NULL);
+		del_timer(&self->wd_timer);
+		irlap_apply_default_connection_parameters(self);
+
+		irlap_disconnect_indication(self, LAP_DISC_INDICATION);
+		dev_kfree_skb(skb);
+		break;
+	case RECV_DM_RSP:
+		/* Always switch state before calling upper layers */
+		irlap_next_state(self, LAP_NDM);
+
+		del_timer(&self->wd_timer);
+		irlap_apply_default_connection_parameters(self);
+		
+		irlap_disconnect_indication(self, LAP_DISC_INDICATION);
+		dev_kfree_skb(skb);
+		break;
+	case WD_TIMER_EXPIRED:
+		irlap_apply_default_connection_parameters(self);
+		
+		irlap_disconnect_indication(self, LAP_DISC_INDICATION);
+		break;
+	default:
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d, (%s)\n", 
+			   event, irlap_event[event]);
+		if (skb)
+			dev_kfree_skb(skb);
+		
+		ret = -EINVAL;
+		break;
+	}
 
 	return -1;
 }
@@ -1856,31 +2036,34 @@
 {
 	int ret = 0;
 
-	DEBUG(1, __FUNCTION__ "(), event=%s\n", irlap_event[ event]); 
+	IRDA_DEBUG(1, __FUNCTION__ "(), event=%s\n", irlap_event[event]); 
 
-	ASSERT( self != NULL, return -ENODEV;);
-	ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
+	ASSERT(self != NULL, return -ENODEV;);
+	ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
 	
-	switch(event) {
+	switch (event) {
 	case RESET_RESPONSE:
-		irlap_send_ua_response_frame( self, &self->qos_rx);
-		irlap_initiate_connection_state( self);
-		irlap_start_wd_timer( self, WD_TIMEOUT);
-		irlap_flush_all_queues( self);
+		irlap_send_ua_response_frame(self, &self->qos_rx);
+		irlap_initiate_connection_state(self);
+		irlap_start_wd_timer(self, WD_TIMEOUT);
+		irlap_flush_all_queues(self);
 		
-		irlap_next_state( self, LAP_NRM_S);
+		irlap_next_state(self, LAP_NRM_S);
 		break;
 	case DISCONNECT_REQUEST:
-		irlap_wait_min_turn_around( self, &self->qos_tx);
-		/* irlap_send_rd_frame(self); */
-		irlap_start_wd_timer( self, WD_TIMEOUT);
+		irlap_wait_min_turn_around(self, &self->qos_tx);
+		irlap_send_rd_frame(self);
+		irlap_start_wd_timer(self, WD_TIMEOUT);
+		irlap_next_state(self, LAP_SCLOSE);
 		break;
 	default:
-		DEBUG(1, __FUNCTION__ "(), Unknown event %d, (%s)\n", 
-		      event, irlap_event[event]);
-		ret = -1;
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d, (%s)\n", 
+			   event, irlap_event[event]);
+		if (skb)
+			dev_kfree_skb(skb);
+
+		ret = -EINVAL;
 		break;
 	}
-
 	return ret;
 }
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irlap_frame.c linux.15p9/net/irda/irlap_frame.c
--- linux.vanilla/net/irda/irlap_frame.c	Sat Aug 14 02:26:52 1999
+++ linux.15p9/net/irda/irlap_frame.c	Tue Jan 18 01:08:19 2000
@@ -1,15 +1,16 @@
 /*********************************************************************
  *                
  * Filename:      irlap_frame.c
- * Version:       0.9
+ * Version:       1.0
  * Description:   Build and transmit IrLAP frames
- * Status:        Experimental.
+ * Status:        Stable
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Aug 19 10:27:26 1997
- * Modified at:   Mon May 31 09:29:13 1999
+ * Modified at:   Wed Jan  5 08:59:04 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, All Rights Resrved.
+ *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>, 
+ *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -42,26 +43,30 @@
 #include <net/irda/qos.h>
 
 /*
- * Function irlap_insert_mtt (self, skb)
- *
- *    Insert minimum turnaround time relevant information into the skb. We 
- *    need to do this since it's per packet relevant information.
+ * Function irlap_insert_info (self, skb)
  *
+ *    Insert minimum turnaround time and speed information into the skb. We 
+ *    need to do this since it's per packet relevant information. Safe to
+ *    have this function inlined since it's only called from one place
  */
-static inline void irlap_insert_mtt(struct irlap_cb *self, struct sk_buff *skb)
+static inline void irlap_insert_info(struct irlap_cb *self, 
+				     struct sk_buff *skb)
 {
-	struct irlap_skb_cb *cb;
+	struct irda_skb_cb *cb = (struct irda_skb_cb *) skb->cb;
 
-	cb = (struct irlap_skb_cb *) skb->cb;
-	
+	/*  
+	 * Insert MTT (min. turn time) and speed into skb, so that the
+	 * device driver knows which settings to use 
+	 */
 	cb->magic = LAP_MAGIC;
 	cb->mtt = self->mtt_required;
-	
+	cb->speed = self->speed;
+
 	/* Reset */
 	self->mtt_required = 0;
 	
 	/* 
-	 * Delay equals negotiated BOFs count plus the number of BOFs to 
+	 * Delay equals negotiated BOFs count, plus the number of BOFs to 
 	 * force the negotiated minimum turnaround time 
 	 */
 	cb->xbofs = self->bofs_count+self->xbofs_delay;
@@ -84,14 +89,9 @@
  	skb->protocol = htons(ETH_P_IRDA);
 	skb->priority = TC_PRIO_BESTEFFORT;
 
-	/* 
-	 * Insert MTT (min. turn time) into skb, so that the device driver 
-	 * knows which MTT to use 
-	 */
-	irlap_insert_mtt(self, skb);
-	
+	irlap_insert_info(self, skb);
+
 	dev_queue_xmit(skb);
-	self->stats.tx_packets++;
 }
 
 /*
@@ -103,7 +103,7 @@
 {
 	struct sk_buff *skb;
 	struct snrm_frame *frame;
-	int len;
+	int ret;
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -113,8 +113,7 @@
 	if (!skb)
 		return;
 
-	skb_put(skb, 2); 
-	frame = (struct snrm_frame *) skb->data;
+	frame = (struct snrm_frame *) skb_put(skb, 2); 
 
 	/* Insert connection address field */
 	if (qos)
@@ -135,9 +134,11 @@
 
 		frame->ncaddr = self->caddr;
 				
-		len = irda_insert_qos_negotiation_params(qos, frame->params);
-		/* Should not be dangerous to do this afterwards */
-		skb_put(skb, len);
+		ret = irlap_insert_qos_negotiation_params(self, skb);
+		if (ret < 0) {
+			dev_kfree_skb(skb);
+			return;
+		}
 	}
 	irlap_queue_xmit(self, skb);
 }
@@ -153,27 +154,34 @@
 {
 	struct snrm_frame *frame;
 
-	DEBUG(3, __FUNCTION__ "()\n");
-
-	ASSERT(skb != NULL, return;);
-	ASSERT(info != NULL, return;);
-
 	frame = (struct snrm_frame *) skb->data;
-
-	/* Copy peer device address */
-	info->daddr = le32_to_cpu(frame->saddr);
-
-	/* Copy connection address */
-	info->caddr = frame->ncaddr;
-
-	/* Check if connection address has got a valid value */
-	if ((info->caddr == 0x00) || (info->caddr == 0xfe)) {
-		DEBUG(3, __FUNCTION__ "(), invalid connection address!\n");
-		dev_kfree_skb(skb);
-		return;
-	}
-
-	irlap_do_event(self, RECV_SNRM_CMD, skb, info);
+	
+	if (skb->len >= sizeof(struct snrm_frame)) {
+		/* Copy the new connection address */
+		info->caddr = frame->ncaddr;
+
+		/* Check if the new connection address is valid */
+		if ((info->caddr == 0x00) || (info->caddr == 0xfe)) {
+			IRDA_DEBUG(3, __FUNCTION__ 
+			      "(), invalid connection address!\n");
+			dev_kfree_skb(skb);
+			return;
+		}
+		
+		/* Copy peer device address */
+		info->daddr = le32_to_cpu(frame->saddr);
+		info->saddr = le32_to_cpu(frame->daddr);
+		
+		/* Only accept if addressed directly to us */
+		if (info->saddr != self->saddr) {
+			IRDA_DEBUG(2, __FUNCTION__ "(), not addressed to us!\n");
+			dev_kfree_skb(skb);
+			return;
+		}
+		irlap_do_event(self, RECV_SNRM_CMD, skb, info);
+	} else
+		/* Signal that this SNRM frame does not contain and I-field */
+		irlap_do_event(self, RECV_SNRM_CMD, skb, NULL);
 }
 
 /*
@@ -186,9 +194,9 @@
 {
 	struct sk_buff *skb;
 	struct ua_frame *frame;
-	int len;
+	int ret;
 	
-	DEBUG(2, __FUNCTION__ "() <%ld>\n", jiffies);
+	IRDA_DEBUG(2, __FUNCTION__ "() <%ld>\n", jiffies);
 	
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -200,8 +208,7 @@
 	if (!skb)
 		return;
 
-	skb_put( skb, 10);
-	frame = (struct ua_frame *) skb->data;
+	frame = (struct ua_frame *) skb_put(skb, 10);
 	
 	/* Build UA response */
 	frame->caddr = self->caddr;
@@ -212,8 +219,11 @@
 
 	/* Should we send QoS negotiation parameters? */
 	if (qos) {
-		len = irda_insert_qos_negotiation_params(qos, frame->params);
-		skb_put(skb, len);
+		ret = irlap_insert_qos_negotiation_params(self, skb);
+		if (ret < 0) {
+			dev_kfree_skb(skb);
+			return;
+		}
 	}
 
 	irlap_queue_xmit(self, skb);
@@ -238,8 +248,7 @@
 	if (!skb)
 		return;
 
-	skb_put( skb, 2);
-	frame = skb->data;
+	frame = skb_put( skb, 2);
 	
 	if (self->state == LAP_NDM)
 		frame[0] = CBROADCAST;
@@ -262,17 +271,16 @@
 	struct sk_buff *skb = NULL;
 	__u8 *frame;
 	
-	DEBUG(3, __FUNCTION__ "()\n");
+	IRDA_DEBUG(3, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
 
-	skb = dev_alloc_skb(32);
+	skb = dev_alloc_skb(16);
 	if (!skb)
 		return;
 
-	skb_put(skb, 2);
-	frame = skb->data;
+	frame = skb_put(skb, 2);
 	
 	frame[0] = self->caddr | CMD_FRAME;
 	frame[1] = DISC_CMD | PF_BIT;
@@ -292,12 +300,14 @@
 	struct sk_buff *skb = NULL;
 	struct xid_frame *frame;
 	__u32 bcast = BROADCAST;
+	__u8 *info;
 
- 	DEBUG( 4, __FUNCTION__ "(), s=%d, S=%d, command=%d\n", s, S, command);
+ 	IRDA_DEBUG(4, __FUNCTION__ "(), s=%d, S=%d, command=%d\n", s, S, 
+		   command);
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LAP_MAGIC, return;);
-	ASSERT( discovery != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
+	ASSERT(discovery != NULL, return;);
 
 	skb = dev_alloc_skb(64);
 	if (!skb)
@@ -306,7 +316,7 @@
 	skb_put(skb, 14);
 	frame = (struct xid_frame *) skb->data;
 
-	if ( command) {
+	if (command) {
 		frame->caddr = CBROADCAST | CMD_FRAME;
 		frame->control =  XID_CMD | PF_BIT;
 	} else {
@@ -322,7 +332,7 @@
 	else
 		frame->daddr = cpu_to_le32(discovery->daddr);
 	
-	switch(S) {
+	switch (S) {
 	case 1:
 		frame->flags = 0x00;
 		break;
@@ -348,29 +358,24 @@
 	 *  responses. Send the second byte of the hint only if the
 	 *  EXTENSION bit is set in the first byte.
 	 */
-	if ( !command || ( frame->slotnr == 0xff)) {
-		int i;
-
-		if (discovery->hints.byte[0] & HINT_EXTENSION)
-			skb_put( skb, 3+discovery->info_len);
-		else
-			skb_put( skb, 2+discovery->info_len);
-		
-		i = 0;
-		frame->discovery_info[i++] = discovery->hints.byte[0];
-		if(discovery->hints.byte[0] & HINT_EXTENSION)
-			frame->discovery_info[i++] = discovery->hints.byte[1];
-		
-		frame->discovery_info[i++] = discovery->charset;
-
-		ASSERT( discovery->info_len < 30, return;);
+	if (!command || (frame->slotnr == 0xff)) {
+		int len;
 
-		memcpy( &frame->discovery_info[i++], discovery->info, 
-			discovery->info_len);
+		if (discovery->hints.byte[0] & HINT_EXTENSION) {
+			info = skb_put(skb, 2);		
+			info[0] = discovery->hints.byte[0];
+			info[1] = discovery->hints.byte[1];
+		} else {
+			info = skb_put(skb, 1);
+			info[0] = discovery->hints.byte[0];
+		}
+		info = skb_put(skb, 1);
+		info[0] = discovery->charset;
 
+		len = IRDA_MIN(discovery->name_len, skb_tailroom(skb));
+		info = skb_put(skb, len);
+		memcpy(info, discovery->nickname, len);
 	} 
-	ASSERT( self->netdev != NULL, return;);
-
 	irlap_queue_xmit(self, skb);
 }
 
@@ -386,51 +391,61 @@
 {
 	struct xid_frame *xid;
 	discovery_t *discovery = NULL;
+	__u8 *discovery_info;
 	char *text;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
-	ASSERT(skb != NULL, return;);
-	ASSERT(info != NULL, return;);
+
+	xid = (struct xid_frame *) skb->data;
+
+	info->daddr = le32_to_cpu(xid->saddr);
+	info->saddr = le32_to_cpu(xid->daddr);
+
+	/* Make sure frame is addressed to us */
+	if ((info->saddr != self->saddr) && (info->saddr != BROADCAST)) {
+		IRDA_DEBUG(0, __FUNCTION__ 
+			   "(), frame is not addressed to us!\n");
+		dev_kfree_skb(skb);
+		return;
+	}
 
 	if ((discovery = kmalloc(sizeof(discovery_t), GFP_ATOMIC)) == NULL) {
-		DEBUG(0, __FUNCTION__ "(), kmalloc failed!\n");
+		WARNING(__FUNCTION__ "(), kmalloc failed!\n");
+		dev_kfree_skb(skb);
 		return;
 	}
 	memset(discovery, 0, sizeof(discovery_t));
 
-	xid = (struct xid_frame *) skb->data;
-
-	/* 
-	 *  Copy peer device address and set the source address
-	 */
-	info->daddr = le32_to_cpu(xid->saddr);
 	discovery->daddr = info->daddr;
 	discovery->saddr = self->saddr;
 	discovery->timestamp = jiffies;
 
-	DEBUG(4, __FUNCTION__ "(), daddr=%08x\n", discovery->daddr);
+	IRDA_DEBUG(4, __FUNCTION__ "(), daddr=%08x\n", discovery->daddr);
+
+	discovery_info = skb_pull(skb, sizeof(struct xid_frame));
 
 	/* Get info returned from peer */
-	discovery->hints.byte[0] = xid->discovery_info[0];
-	if (xid->discovery_info[0] & HINT_EXTENSION) {
-		DEBUG(4, "EXTENSION\n");
-		discovery->hints.byte[1] = xid->discovery_info[1];
-		discovery->charset = xid->discovery_info[2];
-		text = (char *) &xid->discovery_info[3];
+	discovery->hints.byte[0] = discovery_info[0];
+	if (discovery_info[0] & HINT_EXTENSION) {
+		IRDA_DEBUG(4, "EXTENSION\n");
+		discovery->hints.byte[1] = discovery_info[1];
+		discovery->charset = discovery_info[2];
+		text = (char *) &discovery_info[3];
 	} else {
 		discovery->hints.byte[1] = 0;
-		discovery->charset = xid->discovery_info[1];
-		text = (char *) &xid->discovery_info[2];
+		discovery->charset = discovery_info[1];
+		text = (char *) &discovery_info[2];
 	}
 	/* 
-	 *  Terminate string, should be safe since this is where the 
+	 *  Terminate info string, should be safe since this is where the 
 	 *  FCS bytes resides.
 	 */
 	skb->data[skb->len] = '\0'; 
-	strcpy(discovery->info, text);
+	strncpy(discovery->nickname, text, NICKNAME_MAX_LEN);
+	discovery->name_len = strlen(discovery->nickname);
 
 	info->discovery = discovery;
 
@@ -443,27 +458,29 @@
  *    Received a XID discovery command
  *
  */
-static void irlap_recv_discovery_xid_cmd( struct irlap_cb *self, 
-					  struct sk_buff *skb, 
-					  struct irlap_info *info) 
+static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self, 
+					 struct sk_buff *skb, 
+					 struct irlap_info *info) 
 {
 	struct xid_frame *xid;
 	discovery_t *discovery = NULL;
+	__u8 *discovery_info;
 	char *text;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LAP_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
-	ASSERT( info != NULL, return;);
-
 	xid = (struct xid_frame *) skb->data;
-	
-	/* Copy peer device address */
+
 	info->daddr = le32_to_cpu(xid->saddr);
+	info->saddr = le32_to_cpu(xid->daddr);
 
-	switch ( xid->flags & 0x03) {
+	/* Make sure frame is addressed to us */
+	if ((info->saddr != self->saddr) && (info->saddr != BROADCAST)) {
+		IRDA_DEBUG(0, __FUNCTION__ 
+			   "(), frame is not addressed to us!\n");
+		dev_kfree_skb(skb);
+		return;
+	}
+
+	switch (xid->flags & 0x03) {
 	case 0x00:
 		info->S = 1;
 		break;
@@ -478,50 +495,54 @@
 		break;
 	default:
 		/* Error!! */
+		dev_kfree_skb(skb);
 		return;
 	}
 	info->s = xid->slotnr;
 	
+	discovery_info = skb_pull(skb, sizeof(struct xid_frame));
+
 	/* 
 	 *  Check if last frame 
 	 */
-	if ( info->s == 0xff) {
+	if (info->s == 0xff) {
 		/*
 		 *  We now have some discovery info to deliver!
 		 */
-		discovery = kmalloc( sizeof(discovery_t), GFP_ATOMIC);
-		if (!discovery)
+		discovery = kmalloc(sizeof(discovery_t), GFP_ATOMIC);
+		if (!discovery) {
+			WARNING(__FUNCTION__ "(), unable to malloc!\n");
+			dev_kfree_skb(skb);
 			return;
+		}
 	      
 		discovery->daddr = info->daddr;
 		discovery->saddr = self->saddr;
 		discovery->timestamp = jiffies;
 
-		DEBUG( 4, __FUNCTION__ "(), daddr=%08x\n", 
-		       discovery->daddr);
-
-		discovery->hints.byte[0] = xid->discovery_info[0];
-		if ( xid->discovery_info[0] & HINT_EXTENSION) {
-			discovery->hints.byte[1] = xid->discovery_info[1];
-			discovery->charset = xid->discovery_info[2];
-			text = (char *) &xid->discovery_info[3];
+		discovery->hints.byte[0] = discovery_info[0];
+		if (discovery_info[0] & HINT_EXTENSION) {
+			discovery->hints.byte[1] = discovery_info[1];
+			discovery->charset = discovery_info[2];
+			text = (char *) &discovery_info[3];
 		} else {
 			discovery->hints.byte[1] = 0;
-			discovery->charset = xid->discovery_info[1];
-			text = (char *) &xid->discovery_info[2];
+			discovery->charset = discovery_info[1];
+			text = (char *) &discovery_info[2];
 		}
 		/* 
 		 *  Terminate string, should be safe since this is where the 
 		 *  FCS bytes resides.
 		 */
 		skb->data[skb->len] = '\0'; 
-		strcpy( discovery->info, text);
+		strncpy(discovery->nickname, text, NICKNAME_MAX_LEN);
+		discovery->name_len = strlen(discovery->nickname);
 
 		info->discovery = discovery;
 	} else
 		info->discovery = NULL;
 	
-	irlap_do_event( self, RECV_DISCOVERY_XID_CMD, skb, info);
+	irlap_do_event(self, RECV_DISCOVERY_XID_CMD, skb, info);
 }
 
 /*
@@ -535,7 +556,7 @@
 	struct sk_buff *skb;
 	__u8 *frame;
 
-	skb = dev_alloc_skb(32);
+	skb = dev_alloc_skb(16);
 	if (!skb)
 		return;
 	
@@ -550,11 +571,34 @@
 }
 
 /*
+ * Function irlap_send_rd_frame (self)
+ *
+ *    Request disconnect. Used by a secondary station to request the 
+ *    disconnection of the link.
+ */
+void irlap_send_rd_frame(struct irlap_cb *self)
+{
+	struct sk_buff *skb;
+	__u8 *frame;
+
+	skb = dev_alloc_skb(16);
+	if (!skb)
+		return;
+	
+	frame = skb_put(skb, 2);
+	
+	frame[0] = self->caddr;
+	frame[1] = RD_RSP | PF_BIT;
+
+	irlap_queue_xmit(self, skb);
+}
+
+/*
  * Function irlap_recv_rr_frame (skb, info)
  *
  *    Received RR (Receive Ready) frame from peer station, no harm in
  *    making it inline since its called only from one single place
- *    (irlap_input).
+ *    (irlap_driver_rcv).
  */
 static inline void irlap_recv_rr_frame(struct irlap_cb *self, 
 				       struct sk_buff *skb, 
@@ -581,8 +625,7 @@
 	if (!skb)
 		return;
 
-	skb_put( skb, 2);
-	frame = skb->data;
+	frame = skb_put( skb, 2);
 	
 	frame[0] = self->caddr;
 	frame[0] |= (command) ? CMD_FRAME : 0;
@@ -593,7 +636,7 @@
 
 	frame[2] = 0;
 
-   	DEBUG( 4, __FUNCTION__ "(), vr=%d, %ld\n",self->vr, jiffies); 
+   	IRDA_DEBUG(4, __FUNCTION__ "(), vr=%d, %ld\n",self->vr, jiffies); 
 
 	irlap_queue_xmit(self, skb);
 }
@@ -604,20 +647,57 @@
  *    Received RNR (Receive Not Ready) frame from peer station
  *
  */
-static void irlap_recv_rnr_frame( struct irlap_cb *self, struct sk_buff *skb, 
-				  struct irlap_info *info) 
+static void irlap_recv_rnr_frame(struct irlap_cb *self, struct sk_buff *skb, 
+				 struct irlap_info *info, int command) 
 {
-	__u8 *frame;
+	info->nr = skb->data[1] >> 5;
 
-	ASSERT( skb != NULL, return;);
-	ASSERT( info != NULL, return;);
+	IRDA_DEBUG(4, __FUNCTION__ "(), nr=%d, %ld\n", info->nr, jiffies);
 
-	frame = skb->data;
-	info->nr = frame[1] >> 5;
+	if (command)
+		irlap_do_event(self, RECV_RNR_CMD, skb, info);
+	else
+		irlap_do_event(self, RECV_RNR_RSP, skb, info);
+}
+
+static void irlap_recv_rej_frame(struct irlap_cb *self, struct sk_buff *skb, 
+				 struct irlap_info *info, int command)
+{
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	info->nr = skb->data[1] >> 5;
+	
+	/* Check if this is a command or a response frame */
+	if (command)
+		irlap_do_event(self, RECV_REJ_CMD, skb, info);
+	else
+		irlap_do_event(self, RECV_REJ_RSP, skb, info);
+}
 
-	DEBUG( 4, __FUNCTION__ "(), nr=%d, %ld\n", info->nr, jiffies);
+static void irlap_recv_srej_frame(struct irlap_cb *self, struct sk_buff *skb, 
+				  struct irlap_info *info, int command)
+{
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
-	irlap_do_event( self, RECV_RNR_FRAME, skb, info);
+	info->nr = skb->data[1] >> 5;
+	
+	/* Check if this is a command or a response frame */
+	if (command)
+		irlap_do_event(self, RECV_SREJ_CMD, skb, info);
+	else
+		irlap_do_event(self, RECV_SREJ_RSP, skb, info);
+}
+
+static void irlap_recv_disc_frame(struct irlap_cb *self, struct sk_buff *skb, 
+				  struct irlap_info *info, int command)
+{
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	/* Check if this is a command or a response frame */
+	if (command)
+		irlap_do_event(self, RECV_DISC_CMD, skb, info);
+	else
+		irlap_do_event(self, RECV_RD_RSP, skb, info);
 }
 
 /*
@@ -626,24 +706,20 @@
  *    Received UA (Unnumbered Acknowledgement) frame
  *
  */
-static void irlap_recv_ua_frame(struct irlap_cb *self, struct sk_buff *skb, 
-				struct irlap_info *info) 
+static inline void irlap_recv_ua_frame(struct irlap_cb *self, 
+				       struct sk_buff *skb, 
+				       struct irlap_info *info) 
 {
- 	DEBUG(4, __FUNCTION__ "(), <%ld>\n", jiffies); 
-
-	ASSERT(skb != NULL, return;);
-	ASSERT(info != NULL, return;);
-
 	irlap_do_event(self, RECV_UA_RSP, skb, info);
 }
 
 /*
  * Function irlap_send_data_primary(self, skb)
  *
- *    
+ *    Send I-frames as the primary station but without the poll bit set
  *
  */
-void irlap_send_data_primary( struct irlap_cb *self, struct sk_buff *skb)
+void irlap_send_data_primary(struct irlap_cb *self, struct sk_buff *skb)
 {
 	struct sk_buff *tx_skb;
 
@@ -679,17 +755,17 @@
 
 		irlap_send_i_frame( self, tx_skb, CMD_FRAME);
 	} else {
-		DEBUG( 4, __FUNCTION__ "(), sending unreliable frame\n");
-		irlap_send_ui_frame(self, skb, CMD_FRAME);
+		IRDA_DEBUG(4, __FUNCTION__ "(), sending unreliable frame\n");
+		irlap_send_ui_frame(self, skb, self->caddr, CMD_FRAME);
 		self->window -= 1;
 	}
 }
 /*
- * Function irlap_send_data_primary_poll ( self, skb)
+ * Function irlap_send_data_primary_poll (self, skb)
  *
  *    Send I(nformation) frame as primary with poll bit set
  */
-void irlap_send_data_primary_poll( struct irlap_cb *self, struct sk_buff *skb) 
+void irlap_send_data_primary_poll(struct irlap_cb *self, struct sk_buff *skb) 
 {
 	struct sk_buff *tx_skb;
 
@@ -738,17 +814,17 @@
 
 		irlap_send_i_frame(self, tx_skb, CMD_FRAME);
 	} else {
-		DEBUG(4, __FUNCTION__ "(), sending unreliable frame\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), sending unreliable frame\n");
 
 		del_timer(&self->poll_timer);
 
 		if (self->ack_required) {
-			irlap_send_ui_frame(self, skb, CMD_FRAME);
+			irlap_send_ui_frame(self, skb, self->caddr, CMD_FRAME);
 			irlap_send_rr_frame(self, CMD_FRAME);
 			self->ack_required = FALSE;
 		} else {
 			skb->data[1] |= PF_BIT;
-			irlap_send_ui_frame(self, skb, CMD_FRAME);
+			irlap_send_ui_frame(self, skb, self->caddr, CMD_FRAME);
 		}
 		self->window = self->window_size;
 		irlap_start_final_timer(self, self->final_timeout);
@@ -766,12 +842,12 @@
 {
 	struct sk_buff *tx_skb = NULL;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LAP_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
 
 	/* Is this reliable or unreliable data? */
-	if ( skb->data[1] == I_FRAME) {
+	if (skb->data[1] == I_FRAME) {
 
 		/*  
 		 *  Insert frame sequence number (Vs) in control field before
@@ -779,17 +855,17 @@
 		 */
 		skb->data[1] = I_FRAME | (self->vs << 1);
 		
-		tx_skb = skb_clone( skb, GFP_ATOMIC);
-		if ( tx_skb == NULL) {
-			dev_kfree_skb( skb);
+		tx_skb = skb_clone(skb, GFP_ATOMIC);
+		if (tx_skb == NULL) {
+			dev_kfree_skb(skb);
 			return;
 		}		
 
 		if (skb->sk != NULL)
-			skb_set_owner_w( tx_skb, skb->sk);
+			skb_set_owner_w(tx_skb, skb->sk);
 		
 		/* Insert frame in store */
-		skb_queue_tail( &self->wx_list, skb);
+		skb_queue_tail(&self->wx_list, skb);
 		
 		tx_skb->data[1] |= PF_BIT;
 		
@@ -797,21 +873,21 @@
 		self->window = self->window_size;
 		self->ack_required = FALSE;
 		
-		irlap_start_wd_timer( self, self->wd_timeout);
+		irlap_start_wd_timer(self, self->wd_timeout);
 
-		irlap_send_i_frame( self, tx_skb, RSP_FRAME); 
+		irlap_send_i_frame(self, tx_skb, RSP_FRAME); 
 	} else {
-		if ( self->ack_required) {
-			irlap_send_ui_frame( self, skb, RSP_FRAME);
-			irlap_send_rr_frame( self, RSP_FRAME);
+		if (self->ack_required) {
+			irlap_send_ui_frame(self, skb, self->caddr, RSP_FRAME);
+			irlap_send_rr_frame(self, RSP_FRAME);
 			self->ack_required = FALSE;
 		} else {
 			skb->data[1] |= PF_BIT;
-			irlap_send_ui_frame( self, skb, RSP_FRAME);
+			irlap_send_ui_frame(self, skb, self->caddr, RSP_FRAME);
 		}
 		self->window = self->window_size;
 
-		irlap_start_wd_timer( self, self->wd_timeout);
+		irlap_start_wd_timer(self, self->wd_timeout);
 	}
 }
 
@@ -821,16 +897,12 @@
  *    Send I(nformation) frame as secondary without final bit set
  *
  */
-void irlap_send_data_secondary( struct irlap_cb *self, struct sk_buff *skb) 
+void irlap_send_data_secondary(struct irlap_cb *self, struct sk_buff *skb) 
 {
 	struct sk_buff *tx_skb = NULL;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LAP_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
-
 	/* Is this reliable or unreliable data? */
-	if ( skb->data[1] == I_FRAME) {
+	if (skb->data[1] == I_FRAME) {
 		
 		/*  
 		 *  Insert frame sequence number (Vs) in control field before
@@ -838,25 +910,25 @@
 		 */
 		skb->data[1] = I_FRAME | (self->vs << 1);
 		
-		tx_skb = skb_clone( skb, GFP_ATOMIC);
-		if ( tx_skb == NULL) {
-			dev_kfree_skb( skb);
+		tx_skb = skb_clone(skb, GFP_ATOMIC);
+		if (tx_skb == NULL) {
+			dev_kfree_skb(skb);
 			return;
 		}		
 		
 		if (skb->sk != NULL)
-			skb_set_owner_w( tx_skb, skb->sk);
+			skb_set_owner_w(tx_skb, skb->sk);
 		
 		/* Insert frame in store */
-		skb_queue_tail( &self->wx_list, skb);
+		skb_queue_tail(&self->wx_list, skb);
 		
 		self->vs = (self->vs + 1) % 8;
 		self->ack_required = FALSE;		
 		self->window -= 1;
 
-		irlap_send_i_frame( self, tx_skb, RSP_FRAME); 
+		irlap_send_i_frame(self, tx_skb, RSP_FRAME); 
 	} else {
-		irlap_send_ui_frame( self, skb, RSP_FRAME);
+		irlap_send_ui_frame(self, skb, self->caddr, RSP_FRAME);
 		self->window -= 1;
 	}
 }
@@ -864,46 +936,37 @@
 /*
  * Function irlap_resend_rejected_frames (nr)
  *
- *    Resend frames which has not been acknowledged. TODO: check that the 
- *    traversal of the list is atomic, i.e that no-one tries to insert or
- *    remove frames from the list while we travers it!
- * 
- *    FIXME: It is not safe to traverse a this list without locking it!
+ *    Resend frames which has not been acknowledged. Should be safe to 
+ *    traverse the list without locking it since this function will only be 
+ *    called from interrupt context (BH)
  */
-void irlap_resend_rejected_frames( struct irlap_cb *self, int command) 
+void irlap_resend_rejected_frames(struct irlap_cb *self, int command)
 {
 	struct sk_buff *tx_skb;
 	struct sk_buff *skb;
 	int count;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LAP_MAGIC, return;);
-
-	DEBUG(2, __FUNCTION__ "(), retry_count=%d\n", self->retry_count);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
 
 	/* Initialize variables */
 	skb = tx_skb = NULL;
 
-	/* 
-	 *  Resend all unacknowledged frames 
-	 */
-	count = skb_queue_len( &self->wx_list);
-	skb = skb_peek( &self->wx_list);
-	while ( skb != NULL) {
-		irlap_wait_min_turn_around( self, &self->qos_tx);
+	count = skb_queue_len(&self->wx_list);
+
+	/*  Resend unacknowledged frame(s) */
+	skb = skb_peek(&self->wx_list);
+	while (skb != NULL) {
+		irlap_wait_min_turn_around(self, &self->qos_tx);
 
 		/* We copy the skb to be retransmitted since we will have to 
 		 * modify it. Cloning will confuse packet sniffers 
 		 */
 		/* tx_skb = skb_clone( skb, GFP_ATOMIC); */
 		tx_skb = skb_copy(skb, GFP_ATOMIC);
-		if ( tx_skb == NULL) {
-			/* Unlink tx_skb from list */
-			tx_skb->next = tx_skb->prev = NULL;
-			tx_skb->list = NULL;
-		
-			dev_kfree_skb( skb);
-			return;	
+		if (!tx_skb) {
+			IRDA_DEBUG(0, __FUNCTION__ "(), unable to copy\n");
+			return;
 		}
 		/* Unlink tx_skb from list */
 		tx_skb->next = tx_skb->prev = NULL;
@@ -912,8 +975,8 @@
 		/*
 		 *  make sure the skb->sk accounting of memory usage is sane
 		 */
-		if ( skb->sk != NULL)
-			skb_set_owner_w( tx_skb, skb->sk);
+		if (skb->sk != NULL)
+			skb_set_owner_w(tx_skb, skb->sk);
 
 		/* Clear old Nr field + poll bit */
 		tx_skb->data[1] &= 0x0f;
@@ -921,41 +984,40 @@
 		/* 
 		 *  Set poll bit on the last frame retransmitted
 		 */
-	 	if ( count-- == 1) 
+	 	if (count-- == 1)
 	 		tx_skb->data[1] |= PF_BIT; /* Set p/f bit */
 		else
 			tx_skb->data[1] &= ~PF_BIT; /* Clear p/f bit */
 	      	
-		irlap_send_i_frame( self, tx_skb, command);
+		irlap_send_i_frame(self, tx_skb, command);
 
 		/* 
 		 *  If our skb is the last buffer in the list, then
 		 *  we are finished, if not, move to the next sk-buffer
 		 */
-		if ( skb == skb_peek_tail( &self->wx_list))
+		if (skb == skb_peek_tail(&self->wx_list))
 			skb = NULL;
 		else
 			skb = skb->next;
 	}
+#if 0 /* Not yet */
 	/* 
 	 *  We can now fill the window with additinal data frames
 	 */
-	return; /* Skip this for now, DB */
-
-	while ( skb_queue_len( &self->tx_list) > 0) {
+	while (skb_queue_len( &self->txq) > 0) {
 		
-		DEBUG( 0, __FUNCTION__ "(), sending additional frames!\n");
-		if (( skb_queue_len( &self->tx_list) > 0) && 
-		    ( self->window > 0)) {
-			skb = skb_dequeue( &self->tx_list); 
-			ASSERT( skb != NULL, return;);
+		IRDA_DEBUG(0, __FUNCTION__ "(), sending additional frames!\n");
+		if ((skb_queue_len( &self->txq) > 0) && 
+		    (self->window > 0)) {
+			skb = skb_dequeue( &self->txq); 
+			ASSERT(skb != NULL, return;);
 
 			/*
 			 *  If send window > 1 then send frame with pf 
 			 *  bit cleared
 			 */ 
 			if ((self->window > 1) && 
-			    skb_queue_len(&self->tx_list) > 0) 
+			    skb_queue_len(&self->txq) > 0) 
 			{
 				irlap_send_data_primary(self, skb);
 			} else {
@@ -963,6 +1025,52 @@
 			}
 		}
 	}
+#endif
+}
+
+void irlap_resend_rejected_frame(struct irlap_cb *self, int command)
+{
+	struct sk_buff *tx_skb;
+	struct sk_buff *skb;
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
+
+	/* Initialize variables */
+	skb = tx_skb = NULL;
+
+	/*  Resend unacknowledged frame(s) */
+	skb = skb_peek(&self->wx_list);
+	if (skb != NULL) {
+		irlap_wait_min_turn_around(self, &self->qos_tx);
+
+		/* We copy the skb to be retransmitted since we will have to 
+		 * modify it. Cloning will confuse packet sniffers 
+		 */
+		/* tx_skb = skb_clone( skb, GFP_ATOMIC); */
+		tx_skb = skb_copy(skb, GFP_ATOMIC);
+		if (!tx_skb) {
+			IRDA_DEBUG(0, __FUNCTION__ "(), unable to copy\n");
+			return;	
+		}
+		/* Unlink tx_skb from list */
+		tx_skb->next = tx_skb->prev = NULL;
+		tx_skb->list = NULL;
+
+		/*
+		 *  make sure the skb->sk accounting of memory usage is sane
+		 */
+		if (skb->sk != NULL)
+			skb_set_owner_w(tx_skb, skb->sk);
+
+		/* Clear old Nr field + poll bit */
+		tx_skb->data[1] &= 0x0f;
+
+		/*  Set poll/final bit */
+		tx_skb->data[1] |= PF_BIT; /* Set p/f bit */
+	      	
+		irlap_send_i_frame(self, tx_skb, command);
+	}
 }
 
 /*
@@ -972,21 +1080,16 @@
  *
  */
 void irlap_send_ui_frame(struct irlap_cb *self, struct sk_buff *skb, 
-			 int command) 
+			 __u8 caddr, int command)
 {
-	__u8  *frame;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LAP_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
-	frame = skb->data;
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
 	
 	/* Insert connection address */
-	frame[0] = self->caddr;
-	frame[0] |= (command) ? CMD_FRAME : 0;
+	skb->data[0] = caddr | ((command) ? CMD_FRAME : 0);
 
 	irlap_queue_xmit(self, skb);
 }
@@ -999,16 +1102,12 @@
 void irlap_send_i_frame(struct irlap_cb *self, struct sk_buff *skb, 
 			int command) 
 {
-	__u8  *frame;
-	
-	frame = skb->data;
-	
 	/* Insert connection address */
-	frame[0] = self->caddr;
-	frame[0] |= (command) ? CMD_FRAME : 0;
+	skb->data[0] = self->caddr;
+	skb->data[0] |= (command) ? CMD_FRAME : 0;
 	
 	/* Insert next to receive (Vr) */
-	frame[1] |= (self->vr << 5);  /* insert nr */
+	skb->data[1] |= (self->vr << 5);  /* insert nr */
 
 	irlap_queue_xmit(self, skb);
 }
@@ -1017,7 +1116,7 @@
  * Function irlap_recv_i_frame (skb, frame)
  *
  *    Receive and parse an I (Information) frame, no harm in making it inline
- *    since it's called only from one single place (irlap_input).
+ *    since it's called only from one single place (irlap_driver_rcv).
  */
 static inline void irlap_recv_i_frame(struct irlap_cb *self, 
 				      struct sk_buff *skb, 
@@ -1027,9 +1126,6 @@
 	info->pf = skb->data[1] & PF_BIT;      /* Final bit */
 	info->ns = (skb->data[1] >> 1) & 0x07; /* Next to send */
 
- 	DEBUG(4, __FUNCTION__"(), ns=%d, nr=%d, pf=%d, %ld\n", 
-	      info->ns, info->nr, info->pf>>4, jiffies); 
-
 	/* Check if this is a command or a response frame */
 	if (command)
 		irlap_do_event(self, RECV_I_CMD, skb, info);
@@ -1046,15 +1142,11 @@
 static void irlap_recv_ui_frame(struct irlap_cb *self, struct sk_buff *skb, 
 				struct irlap_info *info)
 {
-	__u8 *frame;
+	IRDA_DEBUG( 4, __FUNCTION__ "()\n");
 
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	frame = skb->data;
-
-	info->pf = frame[1] & PF_BIT;      /* Final bit */
+	info->pf = skb->data[1] & PF_BIT;      /* Final bit */
 
-	irlap_do_event( self, RECV_UI_FRAME, skb, info);
+	irlap_do_event(self, RECV_UI_FRAME, skb, info);
 }
 
 /*
@@ -1063,23 +1155,23 @@
  *    Received Frame Reject response.
  *
  */
-static void irlap_recv_frmr_frame( struct irlap_cb *self, struct sk_buff *skb, 
-				   struct irlap_info *info) 
+static void irlap_recv_frmr_frame(struct irlap_cb *self, struct sk_buff *skb, 
+				  struct irlap_info *info) 
 {
 	__u8 *frame;
 	int w, x, y, z;
 
-	DEBUG( 0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LAP_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
-	ASSERT( info != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
+	ASSERT(info != NULL, return;);
 	
 	frame = skb->data;
 
 	info->nr = frame[2] >> 5;          /* Next to receive */
-	info->pf = frame[2] & PF_BIT;        /* Final bit */
+	info->pf = frame[2] & PF_BIT;      /* Final bit */
 	info->ns = (frame[2] >> 1) & 0x07; /* Next to send */
 
 	w = frame[3] & 0x01;
@@ -1087,24 +1179,24 @@
 	y = frame[3] & 0x04;
 	z = frame[3] & 0x08;
 	
-	if ( w) {
-		DEBUG( 0, "Rejected control field is undefined or not "
-		       "implemented.\n");
+	if (w) {
+		IRDA_DEBUG(0, "Rejected control field is undefined or not "
+		      "implemented.\n");
 	} 
-	if ( x) {
-		DEBUG( 0, "Rejected control field was invalid because it "
-		       "contained a non permitted I field.\n");
-	}
-	if ( y) {
-		DEBUG( 0, "Received I field exceeded the maximum negotiated "
-		       "for the existing connection or exceeded the maximum "
-		       "this station supports if no connection exists.\n");
-	}
-	if ( z) {
-		DEBUG( 0, "Rejected control field control field contained an "
-		       "invalid Nr count.\n");
+	if (x) {
+		IRDA_DEBUG(0, "Rejected control field was invalid because it "
+		      "contained a non permitted I field.\n");
+	}
+	if (y) {
+		IRDA_DEBUG(0, "Received I field exceeded the maximum negotiated "
+		      "for the existing connection or exceeded the maximum "
+		      "this station supports if no connection exists.\n");
+	}
+	if (z) {
+		IRDA_DEBUG(0, "Rejected control field control field contained an "
+		      "invalid Nr count.\n");
 	}
-	irlap_do_event( self, RECV_FRMR_RSP, skb, info);
+	irlap_do_event(self, RECV_FRMR_RSP, skb, info);
 }
 
 /*
@@ -1113,35 +1205,34 @@
  *    Send a test frame response
  *
  */
-void irlap_send_test_frame(struct irlap_cb *self, __u32 daddr, 
+void irlap_send_test_frame(struct irlap_cb *self, __u8 caddr, __u32 daddr, 
 			   struct sk_buff *cmd)
 {
 	struct sk_buff *skb;
 	struct test_frame *frame;
-	
+	__u8 *info;
+
 	skb = dev_alloc_skb(32);
 	if (!skb)
 		return;
 
-	skb_put(skb, sizeof(struct test_frame));
-
-	frame = (struct test_frame *) skb->data;
+	/* Broadcast frames must include saddr and daddr fields */
+	if (caddr == CBROADCAST) {
+		frame = (struct test_frame *) 
+			skb_put(skb, sizeof(struct test_frame));
 
-	/* Build header */
-	if (self->state == LAP_NDM)
-		frame->caddr = CBROADCAST; /* Send response */
-	else
-		frame->caddr = self->caddr;
+		/* Insert the swapped addresses */
+		frame->saddr = cpu_to_le32(self->saddr);
+		frame->daddr = cpu_to_le32(daddr);
+	} else
+		frame = (struct test_frame *) skb_put(skb, LAP_MAX_HEADER);
 
+	frame->caddr = caddr;
 	frame->control = TEST_RSP;
 
-	/* Insert the swapped addresses */
-	frame->saddr = cpu_to_le32(self->saddr);
-	frame->daddr = cpu_to_le32(daddr);
-
 	/* Copy info */
-	skb_put(skb, cmd->len);
-	memcpy(frame->info, cmd->data, cmd->len);
+	info = skb_put(skb, cmd->len);
+	memcpy(info, cmd->data, cmd->len);
 
 	/* Return to sender */
 	irlap_wait_min_turn_around(self, &self->qos_tx);
@@ -1154,23 +1245,35 @@
  *    Receive a test frame
  *
  */
-void irlap_recv_test_frame(struct irlap_cb *self, struct sk_buff *skb, 
-			   struct irlap_info *info, int command)
+static void irlap_recv_test_frame(struct irlap_cb *self, struct sk_buff *skb, 
+				  struct irlap_info *info, int command)
 {
 	struct test_frame *frame;
 
-	DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 	
-	if (skb->len < sizeof(struct test_frame)) {
-		DEBUG(0, __FUNCTION__ "() test frame to short!\n");
-		return;
-	}
-
 	frame = (struct test_frame *) skb->data;
-
-	/* Read and swap addresses */
-	info->daddr = le32_to_cpu(frame->saddr);
-	info->saddr = le32_to_cpu(frame->daddr);
+		
+	/* Broadcast frames must carry saddr and daddr fields */
+	if (info->caddr == CBROADCAST) {
+		if (skb->len < sizeof(struct test_frame)) {
+			IRDA_DEBUG(0, __FUNCTION__ 
+				   "() test frame to short!\n");
+			dev_kfree_skb(skb);
+			return;
+		}
+		
+		/* Read and swap addresses */
+		info->daddr = le32_to_cpu(frame->saddr);
+		info->saddr = le32_to_cpu(frame->daddr);
+
+		/* Make sure frame is addressed to us */
+		if ((info->saddr != self->saddr) && 
+		    (info->saddr != BROADCAST)) {
+			dev_kfree_skb(skb);
+			return;
+		}
+	}
 
 	if (command)
 		irlap_do_event(self, RECV_TEST_CMD, skb, info);
@@ -1190,36 +1293,36 @@
 {
 	struct irlap_info info;
 	struct irlap_cb *self;
-	struct irda_device *idev;
-	__u8 *frame;
 	int command;
 	__u8 control;
 	
-	idev = (struct irda_device *) dev->priv;
+	/* FIXME: should we get our own field? */
+	self = (struct irlap_cb *) dev->atalk_ptr;
 
-	ASSERT( idev != NULL, return -1;);
-	self = idev->irlap;
+	/* If the net device is down, then IrLAP is gone! */
+	if (!self || self->magic != LAP_MAGIC) {
+		dev_kfree_skb(skb);
+		return -1;
+	}
 
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == LAP_MAGIC, return -1;);
-	ASSERT( skb->len > 1, return -1;);
+	/* Check if frame is large enough for parsing */
+	if (skb->len < 2) {
+		ERROR(__FUNCTION__ "(), frame to short!\n");
+		dev_kfree_skb(skb);
+		return -1;
+	}
 	
-	frame = skb->data;
-
-	command    = frame[0] & CMD_FRAME;
-	info.caddr = frame[0] & CBROADCAST;
+	command    = skb->data[0] & CMD_FRAME;
+	info.caddr = skb->data[0] & CBROADCAST;
 	
-	info.pf      = frame[1] &  PF_BIT;
-	info.control = frame[1] & ~PF_BIT; /* Mask away poll/final bit */
+	info.pf      = skb->data[1] &  PF_BIT;
+	info.control = skb->data[1] & ~PF_BIT; /* Mask away poll/final bit */
 
 	control = info.control;
 
-	/* 
-	 *  First check if this frame addressed to us 
-	 */
+	/*  First we check if this frame has a valid connection address */
 	if ((info.caddr != self->caddr) && (info.caddr != CBROADCAST)) {
-		DEBUG(2, __FUNCTION__ "(), Received frame is not for us!\n");
-
+		IRDA_DEBUG(0, __FUNCTION__ "(), wrong connection address!\n");
 		dev_kfree_skb(skb);
 		return 0;
 	}
@@ -1229,7 +1332,6 @@
 	 */
 	if (~control & 0x01) {
 		irlap_recv_i_frame(self, skb, &info, command);
-		self->stats.rx_packets++;
 		return 0;
 	}
 	/*
@@ -1243,22 +1345,22 @@
 		 */
 		switch (control & 0x0f) {
 		case RR:
-			irlap_recv_rr_frame( self, skb, &info, command);
-			self->stats.rx_packets++;
+			irlap_recv_rr_frame(self, skb, &info, command);
 			break;
 		case RNR:
-			irlap_recv_rnr_frame( self, skb, &info);
-			self->stats.rx_packets++;
+			irlap_recv_rnr_frame(self, skb, &info, command);
 			break;
 		case REJ:
-			DEBUG( 0, "*** REJ frame received! ***\n");
+			irlap_recv_rej_frame(self, skb, &info, command);
 			break;
 		case SREJ:
-			DEBUG( 0, "*** SREJ frame received! ***\n");
+			irlap_recv_srej_frame(self, skb, &info, command);
 			break;
 		default:
-			DEBUG( 0, "Unknown S frame %02x received!\n", 
-			       info.control);
+			WARNING(__FUNCTION__ 
+				"() Unknown S-frame %02x received!\n",
+				info.control);
+			dev_kfree_skb(skb);
 			break;
 		}
 		return 0;
@@ -1277,33 +1379,28 @@
 		irlap_recv_snrm_cmd(self, skb, &info);
 		break;
 	case DM_RSP:
-		DEBUG( 0, "DM rsp frame received!\n");
-		irlap_next_state(self, LAP_NDM);
+		irlap_do_event(self, RECV_DM_RSP, skb, &info);
 		break;
-	case DISC_CMD:
-		irlap_do_event(self, RECV_DISC_FRAME, skb, &info);
+	case DISC_CMD: /* And RD_RSP since they have the same value */
+		irlap_recv_disc_frame(self, skb, &info, command);
 		break;
 	case TEST_CMD:
-		DEBUG(0,__FUNCTION__ "(), TEST_FRAME\n");
 		irlap_recv_test_frame(self, skb, &info, command);
 		break;
 	case UA_RSP:
-		DEBUG( 4, "UA rsp frame received!\n");
-		irlap_recv_ua_frame( self, skb, &info);
+		irlap_recv_ua_frame(self, skb, &info);
 		break;
 	case FRMR_RSP:
-		irlap_recv_frmr_frame( self, skb, &info);
+		irlap_recv_frmr_frame(self, skb, &info);
 		break;
 	case UI_FRAME:
-		DEBUG( 4, "UI-frame received!\n");
-		irlap_recv_ui_frame( self, skb, &info);
+		irlap_recv_ui_frame(self, skb, &info);
 		break;
 	default:
-		DEBUG( 0, "Unknown frame %02x received!\n", info.control);
-		dev_kfree_skb( skb); 
+		WARNING(__FUNCTION__ "(), Unknown frame %02x received!\n", 
+			info.control);
+		dev_kfree_skb(skb); 
 		break;
 	}
-	self->stats.rx_packets++;
-
 	return 0;
 }
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irlmp.c linux.15p9/net/irda/irlmp.c
--- linux.vanilla/net/irda/irlmp.c	Sat Aug 14 02:26:52 1999
+++ linux.15p9/net/irda/irlmp.c	Tue Jan 18 01:08:19 2000
@@ -1,15 +1,15 @@
 /*********************************************************************
  *                
  * Filename:      irlmp.c
- * Version:       0.9
+ * Version:       1.0
  * Description:   IrDA Link Management Protocol (LMP) layer                 
  * Status:        Stable.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 17 20:54:32 1997
- * Modified at:   Mon May 31 21:49:41 1999
+ * Modified at:   Sun Jan  9 07:43:35 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
+ *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>, 
  *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
@@ -32,7 +32,6 @@
 #include <linux/init.h>
 #include <linux/kmod.h>
 #include <linux/random.h>
-#include <linux/irda.h>
 
 #include <net/irda/irda.h>
 #include <net/irda/irmod.h>
@@ -47,8 +46,9 @@
 struct irlmp_cb *irlmp = NULL;
 
 /* These can be altered by the sysctl interface */
-int  sysctl_discovery = 0;
-int  sysctl_discovery_slots = 6;
+int  sysctl_discovery         = 0;
+int  sysctl_discovery_timeout = 3; /* 3 seconds by default */
+int  sysctl_discovery_slots   = 6; /* 6 slots by default */
 char sysctl_devname[65];
 
 char *lmp_reasons[] = {
@@ -61,7 +61,7 @@
 	"ERROR, NOT USED",
 };
 
-__u8 *irlmp_hint_to_service( __u8 *hint);
+__u8 *irlmp_hint_to_service(__u8 *hint);
 #ifdef CONFIG_PROC_FS
 int irlmp_proc_read(char *buf, char **start, off_t offst, int len, int unused);
 #endif
@@ -69,20 +69,19 @@
 /*
  * Function irlmp_init (void)
  *
- *    Create (allocate) the main IrLMP structure and the pointer array
- *    which will contain pointers to each instance of a LSAP.
+ *    Create (allocate) the main IrLMP structure
+ *
  */
-__initfunc(int irlmp_init(void))
+int __init irlmp_init(void)
 {
 	/* Initialize the irlmp structure. */
-	if ( irlmp == NULL) {
-		irlmp = kmalloc( sizeof(struct irlmp_cb), GFP_KERNEL);
-		if ( irlmp == NULL)
-			return -ENOMEM;
-	}
-	memset( irlmp, 0, sizeof(struct irlmp_cb));
+	irlmp = kmalloc( sizeof(struct irlmp_cb), GFP_KERNEL);
+	if (irlmp == NULL)
+		return -ENOMEM;
+	memset(irlmp, 0, sizeof(struct irlmp_cb));
 	
 	irlmp->magic = LMP_MAGIC;
+	spin_lock_init(&irlmp->lock);
 
 	irlmp->clients = hashbin_new(HB_GLOBAL);
 	irlmp->services = hashbin_new(HB_GLOBAL);
@@ -90,7 +89,7 @@
 	irlmp->unconnected_lsaps = hashbin_new(HB_GLOBAL);
 	irlmp->cachelog = hashbin_new(HB_GLOBAL);
 	
-	irlmp->free_lsap_sel = 0x10; /* Servers use 0x00-0x0f */
+	irlmp->free_lsap_sel = 0x10; /* Reserved 0x00-0x0f */
 #ifdef CONFIG_IRDA_CACHE_LAST_LSAP
 	irlmp->cache.valid = FALSE;
 #endif
@@ -98,7 +97,7 @@
 	
 	/* Do discovery every 3 seconds */
 	init_timer(&irlmp->discovery_timer);
-   	irlmp_start_discovery_timer(irlmp, 600); 
+   	irlmp_start_discovery_timer(irlmp, sysctl_discovery_timeout*HZ);
 
 	return 0;
 }
@@ -134,7 +133,7 @@
  *   Register with IrLMP and create a local LSAP,
  *   returns handle to LSAP.
  */
-struct lsap_cb *irlmp_open_lsap(__u8 slsap_sel, struct notify_t *notify)
+struct lsap_cb *irlmp_open_lsap(__u8 slsap_sel, notify_t *notify, __u8 pid)
 {
 	struct lsap_cb *self;
 
@@ -142,42 +141,33 @@
 	ASSERT(irlmp != NULL, return NULL;);
 	ASSERT(irlmp->magic == LMP_MAGIC, return NULL;);
 
-	DEBUG(4, __FUNCTION__ "(), slsap_sel=%02x\n", slsap_sel);
-
-	/* 
-	 *  Does the client care which Source LSAP selector it gets? 
-	 */
+	/*  Does the client care which Source LSAP selector it gets?  */
 	if (slsap_sel == LSAP_ANY) {
-		/*
-		 *  Find unused LSAP
-		 */
 		slsap_sel = irlmp_find_free_slsap();
-		if ( slsap_sel == 0)
+		if (!slsap_sel)
 			return NULL;
-	} else {
-		/*
-		 *  Client wants specific LSAP, so check if it's already
-		 *  in use
-		 */
-		if (irlmp_slsap_inuse(slsap_sel)) {
-			return NULL;
-		}
-	}
+	} else if (irlmp_slsap_inuse(slsap_sel))
+		return NULL;
 
-	/*
-	 *  Allocate new instance of a LSAP connection
-	 */
+	/* Allocate new instance of a LSAP connection */
 	self = kmalloc(sizeof(struct lsap_cb), GFP_ATOMIC);
 	if (self == NULL) {
-		printk( KERN_ERR "IrLMP: Can't allocate memory for "
-			"LSAP control block!\n");
+		ERROR(__FUNCTION__ "(), can't allocate memory");
 		return NULL;
 	}
 	memset(self, 0, sizeof(struct lsap_cb));
 	
 	self->magic = LMP_LSAP_MAGIC;
 	self->slsap_sel = slsap_sel;
-	self->dlsap_sel = LSAP_ANY;
+
+	/* Fix connectionless LSAP's */
+	if (slsap_sel == LSAP_CONNLESS) {
+#ifdef CONFIG_IRDA_ULTRA
+		self->dlsap_sel = LSAP_CONNLESS;
+		self->pid = pid;
+#endif /* CONFIG_IRDA_ULTRA */
+	} else
+		self->dlsap_sel = LSAP_ANY;
 	self->connected = FALSE;
 
 	init_timer(&self->watchdog_timer);
@@ -187,10 +177,8 @@
 
 	irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
 	
-	/*
-	 *  Insert into queue of unconnected LSAPs
-	 */
-	hashbin_insert(irlmp->unconnected_lsaps, (QUEUE *) self, (int) self, 
+	/* Insert into queue of unconnected LSAPs */
+	hashbin_insert(irlmp->unconnected_lsaps, (queue_t *) self, (int) self, 
 		       NULL);
 	
 	return self;
@@ -203,7 +191,7 @@
  */
 static void __irlmp_close_lsap(struct lsap_cb *self)
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
@@ -211,9 +199,12 @@
 	/*
 	 *  Set some of the variables to preset values
 	 */
-	self->magic = ~LMP_LSAP_MAGIC;
+	self->magic = 0;
 	del_timer(&self->watchdog_timer); /* Important! */
 
+	if (self->conn_skb)
+		dev_kfree_skb(self->conn_skb);
+
 #ifdef CONFIG_IRDA_CACHE_LAST_LSAP
 	ASSERT(irlmp != NULL, return;);
 	irlmp->cache.valid = FALSE;
@@ -250,8 +241,8 @@
 				      NULL);
 	}
 	if (!lsap) {
-		DEBUG(0, __FUNCTION__ 
-		       "(), Looks like somebody has removed me already!\n");
+		IRDA_DEBUG(0, __FUNCTION__ 
+		     "(), Looks like somebody has removed me already!\n");
 		return;
 	}
 	__irlmp_close_lsap(self);
@@ -264,13 +255,10 @@
  *    instances of the IrLAP layer, each connected to different IrDA ports
  *
  */
-void irlmp_register_link(struct irlap_cb *irlap, __u32 saddr, 
-			 struct notify_t *notify)
+void irlmp_register_link(struct irlap_cb *irlap, __u32 saddr, notify_t *notify)
 {
 	struct lap_cb *lap;
 
-	DEBUG(4, __FUNCTION__ "(), Registered IrLAP, saddr = %08x\n", saddr);
-	
 	ASSERT(irlmp != NULL, return;);
 	ASSERT(irlmp->magic == LMP_MAGIC, return;);
 	ASSERT(notify != NULL, return;);
@@ -280,7 +268,7 @@
 	 */
 	lap = kmalloc(sizeof(struct lap_cb), GFP_KERNEL);
 	if (lap == NULL) {
-		DEBUG(3, __FUNCTION__ "(), unable to kmalloc\n");
+		ERROR(__FUNCTION__ "(), unable to kmalloc\n");
 		return;
 	}
 	memset(lap, 0, sizeof(struct lap_cb));
@@ -298,7 +286,7 @@
 	/*
 	 *  Insert into queue of unconnected LSAPs
 	 */
-	hashbin_insert(irlmp->links, (QUEUE *) lap, lap->saddr, NULL);
+	hashbin_insert(irlmp->links, (queue_t *) lap, lap->saddr, NULL);
 
 	/* 
 	 *  We set only this variable so IrLAP can tell us on which link the
@@ -318,7 +306,7 @@
 {
 	struct lap_cb *link;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	link = hashbin_remove(irlmp->links, saddr, NULL);
 	if (link) {
@@ -349,20 +337,20 @@
 	struct lsap_cb *lsap;
 	discovery_t *discovery;
 
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == LMP_LSAP_MAGIC, return -1;);
+	ASSERT(self != NULL, return -EBADR;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return -EBADR;);
 	
-	DEBUG(2, __FUNCTION__ 
+	IRDA_DEBUG(2, __FUNCTION__ 
 	      "(), slsap_sel=%02x, dlsap_sel=%02x, saddr=%08x, daddr=%08x\n", 
 	      self->slsap_sel, dlsap_sel, saddr, daddr);
 	
-	if ( self->connected) 
+	if (self->connected) 
 		return -EISCONN;
-
+	
 	/* Client must supply destination device address */
 	if (!daddr)
 		return -EINVAL;
-
+	
 	/* Any userdata? */
 	if (userdata == NULL) {
 		skb = dev_alloc_skb(64);
@@ -378,7 +366,6 @@
 	skb_push(skb, LMP_CONTROL_HEADER);
 
 	self->dlsap_sel = dlsap_sel;
-	self->tmp_skb = skb;
 	
 	/*  
 	 * Find the link to where we should try to connect since there may
@@ -389,20 +376,29 @@
 	 * device with the given daddr 
 	 */
 	if (!saddr) {
-		discovery = hashbin_find(irlmp->cachelog, daddr, NULL);
-		if (discovery)
+		if (daddr != DEV_ADDR_ANY)
+			discovery = hashbin_find(irlmp->cachelog, daddr, NULL);
+		else {
+			IRDA_DEBUG(2, __FUNCTION__ "(), no daddr\n");
+			discovery = (discovery_t *) 
+				hashbin_get_first(irlmp->cachelog);
+		}
+
+		if (discovery) {
 			saddr = discovery->saddr;
+			daddr = discovery->daddr;
+		}
 	}
 	lap = hashbin_find(irlmp->links, saddr, NULL);	
 	if (lap == NULL) {
-		DEBUG(1, __FUNCTION__ "(), Unable to find a usable link!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unable to find a usable link!\n");
 		return -EHOSTUNREACH;
 	}
 
 	if (lap->daddr == DEV_ADDR_ANY)
 		lap->daddr = daddr;
 	else if (lap->daddr != daddr) {
-		DEBUG(0, __FUNCTION__ "(), sorry, but link is busy!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), sorry, but link is busy!\n");
 		return -EBUSY;
 	}
 
@@ -419,7 +415,7 @@
 	ASSERT(lsap->lap != NULL, return -1;);
 	ASSERT(lsap->lap->magic == LMP_LAP_MAGIC, return -1;);
 
-	hashbin_insert(self->lap->lsaps, (QUEUE *) self, (int) self, NULL);
+	hashbin_insert(self->lap->lsaps, (queue_t *) self, (int) self, NULL);
 
 	self->connected = TRUE;
 	
@@ -451,23 +447,18 @@
 	ASSERT(skb != NULL, return;);
 	ASSERT(self->lap != NULL, return;);
 
-	DEBUG(2, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
-	      self->slsap_sel, self->dlsap_sel);
-
+	IRDA_DEBUG(2, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
+		   self->slsap_sel, self->dlsap_sel);
+	
 	self->qos = *self->lap->qos;
 
 	max_seg_size = self->lap->qos->data_size.value-LMP_HEADER;
-	DEBUG(2, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size);
-	
-	lap_header_size = irlap_get_header_size(self->lap->irlap);
-
+	lap_header_size = IRLAP_GET_HEADER_SIZE(self->lap->irlap);
 	max_header_size = LMP_HEADER + lap_header_size;
 
-	DEBUG(2, __FUNCTION__ "(), max_header_size=%d\n", max_header_size);
-
 	/* Hide LMP_CONTROL_HEADER header from layer above */
 	skb_pull(skb, LMP_CONTROL_HEADER);
-
+	
 	if (self->notify.connect_indication)
 		self->notify.connect_indication(self->notify.instance, self, 
 						&self->qos, max_seg_size, 
@@ -480,22 +471,40 @@
  *    Service user is accepting connection
  *
  */
-void irlmp_connect_response(struct lsap_cb *self, struct sk_buff *userdata) 
+int irlmp_connect_response(struct lsap_cb *self, struct sk_buff *userdata) 
 {
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
-	ASSERT(userdata != NULL, return;);
-
-	self->connected = TRUE;
+	struct sk_buff *skb;
 
-	DEBUG(2, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
-	      self->slsap_sel, self->dlsap_sel);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
 
-	/* Make room for MUX control header ( 3 bytes) */
-	ASSERT(skb_headroom(userdata) >= LMP_CONTROL_HEADER, return;);
-	skb_push(userdata, LMP_CONTROL_HEADER);
+	/* Any userdata supplied? */
+	if (!userdata) {
+		skb = dev_alloc_skb(64);
+		if (!skb)
+			return -ENOMEM;
+		
+		/* Reserve space for MUX_CONTROL and LAP header */
+		skb_reserve(skb, LMP_MAX_HEADER);
+	} else {
+		skb = userdata;
+		/*  
+		 *  Check that the client has reserved enough space for 
+		 *  headers
+		 */
+		ASSERT(skb_headroom(skb) >= LMP_CONTROL_HEADER, return -1;);
+	}
+	
+	self->connected = TRUE;
+	
+	IRDA_DEBUG(2, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
+		   self->slsap_sel, self->dlsap_sel);
 	
-	irlmp_do_lsap_event(self, LM_CONNECT_RESPONSE, userdata);
+	/* Make room for MUX control header (3 bytes) */
+	skb_push(skb, LMP_CONTROL_HEADER);	
+	irlmp_do_lsap_event(self, LM_CONNECT_RESPONSE, skb);
+	
+	return 0;
 }
 
 /*
@@ -505,34 +514,32 @@
  */
 void irlmp_connect_confirm(struct lsap_cb *self, struct sk_buff *skb) 
 {
-	int max_seg_size;
 	int max_header_size;
 	int lap_header_size;
+	int max_seg_size;
 
-	DEBUG(3, __FUNCTION__ "()\n");
+	IRDA_DEBUG(3, __FUNCTION__ "()\n");
 	
 	ASSERT(skb != NULL, return;);
 	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
-	
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return;);	
 	ASSERT(self->lap != NULL, return;);
-	self->qos = *self->lap->qos;
 
-	max_seg_size = self->lap->qos->data_size.value-LMP_HEADER;
-	DEBUG(2, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size);
+	self->qos = *self->lap->qos;
 
-	lap_header_size = irlap_get_header_size(self->lap->irlap);
-	
+	max_seg_size    = self->lap->qos->data_size.value-LMP_HEADER;
+	lap_header_size = IRLAP_GET_HEADER_SIZE(self->lap->irlap);	
 	max_header_size = LMP_HEADER + lap_header_size;
 
-	DEBUG(2, __FUNCTION__ "(), max_header_size=%d\n", max_header_size);
+	IRDA_DEBUG(2, __FUNCTION__ "(), max_header_size=%d\n", 
+		   max_header_size);
 
 	/* Hide LMP_CONTROL_HEADER header from layer above */
 	skb_pull(skb, LMP_CONTROL_HEADER);
 
 	if (self->notify.connect_confirm) {
 		self->notify.connect_confirm(self->notify.instance, self,
-					     &self->qos, max_seg_size, 
+					     &self->qos, max_seg_size,
 					     max_header_size, skb);
 	}
 }
@@ -548,16 +555,16 @@
 {
 	struct lsap_cb *new;
 
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(1, __FUNCTION__ "()\n");
 
 	/* Only allowed to duplicate unconnected LSAP's */
 	if (!hashbin_find(irlmp->unconnected_lsaps, (int) orig, NULL)) {
-		DEBUG(0, __FUNCTION__ "(), unable to find LSAP\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), unable to find LSAP\n");
 		return NULL;
 	}
 	new = kmalloc(sizeof(struct lsap_cb), GFP_ATOMIC);
 	if (!new)  {
-		DEBUG(0, __FUNCTION__ "(), unable to kmalloc\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), unable to kmalloc\n");
 		return NULL;
 	}
 	/* Dup */
@@ -566,7 +573,7 @@
 	
 	init_timer(&new->watchdog_timer);
 	
-	hashbin_insert(irlmp->unconnected_lsaps, (QUEUE *) new, (int) new, 
+	hashbin_insert(irlmp->unconnected_lsaps, (queue_t *) new, (int) new, 
 		       NULL);
 
 	/* Make sure that we invalidate the cache */
@@ -583,53 +590,53 @@
  *    The service user is requesting disconnection, this will not remove the 
  *    LSAP, but only mark it as disconnected
  */
-void irlmp_disconnect_request(struct lsap_cb *self, struct sk_buff *userdata) 
+int irlmp_disconnect_request(struct lsap_cb *self, struct sk_buff *userdata) 
 {
 	struct lsap_cb *lsap;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
 
 	/* Already disconnected? */
-	if ( !self->connected) {
-		DEBUG( 1, __FUNCTION__ "(), already disconnected!\n");
-		return;
+	if (!self->connected) {
+		WARNING(__FUNCTION__ "(), already disconnected!\n");
+		return -1;
 	}
 
-	ASSERT( userdata != NULL, return;);
-	ASSERT( self->connected == TRUE, return;);
+	ASSERT(userdata != NULL, return -1;);
+	ASSERT(self->connected == TRUE, return -1;);
 	
-	skb_push( userdata, LMP_CONTROL_HEADER);
+	skb_push(userdata, LMP_CONTROL_HEADER);
 
 	/* 
 	 *  Do the event before the other stuff since we must know
 	 *  which lap layer that the frame should be transmitted on
 	 */
-	irlmp_do_lsap_event( self, LM_DISCONNECT_REQUEST, userdata);
+	irlmp_do_lsap_event(self, LM_DISCONNECT_REQUEST, userdata);
 
 	/* 
 	 *  Remove LSAP from list of connected LSAPs for the particular link
 	 *  and insert it into the list of unconnected LSAPs
 	 */
-	ASSERT( self->lap != NULL, return;);
-	ASSERT( self->lap->magic == LMP_LAP_MAGIC, return;);
-	ASSERT( self->lap->lsaps != NULL, return;);
+	ASSERT(self->lap != NULL, return -1;);
+	ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
+	ASSERT(self->lap->lsaps != NULL, return -1;);
 
 	lsap = hashbin_remove(self->lap->lsaps, (int) self, NULL);
 
-	ASSERT( lsap != NULL, return;);
-	ASSERT( lsap->magic == LMP_LSAP_MAGIC, return;);
-	ASSERT( lsap == self, return;);
+	ASSERT(lsap != NULL, return -1;);
+	ASSERT(lsap->magic == LMP_LSAP_MAGIC, return -1;);
+	ASSERT(lsap == self, return -1;);
 
-	hashbin_insert(irlmp->unconnected_lsaps, (QUEUE *) self, (int) self, 
+	hashbin_insert(irlmp->unconnected_lsaps, (queue_t *) self, (int) self, 
 		       NULL);
 	
 	/* Reset some values */
 	self->connected = FALSE;
 	self->dlsap_sel = LSAP_ANY;
 	self->lap = NULL;
+	
+	return 0;
 }
 
 /*
@@ -642,14 +649,13 @@
 {
 	struct lsap_cb *lsap;
 
-	DEBUG( 1, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);	
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
- 	ASSERT( self->connected == TRUE, return;); 
+	IRDA_DEBUG(1, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);	
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+ 	ASSERT(self->connected == TRUE, return;); 
 
-	DEBUG( 3, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
-	       self->slsap_sel, self->dlsap_sel);
+	IRDA_DEBUG(3, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
+		   self->slsap_sel, self->dlsap_sel);
 
 	self->connected = FALSE;
 	self->dlsap_sel = LSAP_ANY;
@@ -661,14 +667,14 @@
 	/* 
 	 *  Remove association between this LSAP and the link it used 
 	 */
-	ASSERT( self->lap != NULL, return;);
-	ASSERT( self->lap->lsaps != NULL, return;);
+	ASSERT(self->lap != NULL, return;);
+	ASSERT(self->lap->lsaps != NULL, return;);
 
-	lsap = hashbin_remove( self->lap->lsaps, (int) self, NULL);
+	lsap = hashbin_remove(self->lap->lsaps, (int) self, NULL);
 
-	ASSERT( lsap != NULL, return;);
-	ASSERT( lsap == self, return;);
-	hashbin_insert(irlmp->unconnected_lsaps, (QUEUE *) lsap, (int) lsap, 
+	ASSERT(lsap != NULL, return;);
+	ASSERT(lsap == self, return;);
+	hashbin_insert(irlmp->unconnected_lsaps, (queue_t *) lsap, (int) lsap, 
 		       NULL);
 
 	self->lap = NULL;
@@ -676,9 +682,12 @@
 	/*
 	 *  Inform service user
 	 */
-	if ( self->notify.disconnect_indication) {
-		self->notify.disconnect_indication( self->notify.instance, 
-						    self, reason, userdata);
+	if (self->notify.disconnect_indication)
+		self->notify.disconnect_indication(self->notify.instance, 
+						   self, reason, userdata);
+	else {
+		IRDA_DEBUG(0, __FUNCTION__ "(), no handler\n");
+		dev_kfree_skb(userdata);
 	}
 }
 
@@ -692,9 +701,9 @@
 {
 	struct lap_cb *lap;
 
-	/* Make sure value is sane */
-	if ((nslots != 1) && (nslots != 6) && (nslots != 8)&&(nslots != 16)) {
-		printk(KERN_WARNING __FUNCTION__ 
+	/* Make sure the value is sane */
+	if ((nslots != 1) && (nslots != 6) && (nslots != 8) && (nslots != 16)){
+		WARNING(__FUNCTION__ 
 		       "(), invalid value for number of slots!\n");
 		nslots = sysctl_discovery_slots = 8;
 	}
@@ -708,8 +717,9 @@
 	 *  end
 	 */
 	irlmp->discovery_cmd.charset = CS_ASCII;
-	strncpy(irlmp->discovery_cmd.info, sysctl_devname, 31);
-	irlmp->discovery_cmd.info_len = strlen(irlmp->discovery_cmd.info);
+	strncpy(irlmp->discovery_cmd.nickname, sysctl_devname, 
+		NICKNAME_MAX_LEN);
+	irlmp->discovery_cmd.name_len = strlen(irlmp->discovery_cmd.nickname);
 	irlmp->discovery_cmd.nslots = nslots;
 	
 	/*
@@ -740,21 +750,18 @@
  */
 void irlmp_discovery_request(int nslots)
 {
-	DEBUG(4, __FUNCTION__ "(), nslots=%d\n", nslots);
-
 	/* Check if user wants to override the default */
 	if (nslots == DISCOVERY_DEFAULT_SLOTS)
 		nslots = sysctl_discovery_slots;
 
+	/* Return current cached discovery log */
+	irlmp_discovery_confirm(irlmp->cachelog);
+
 	/* 
-	 * If discovery is already running, then just return the current 
-	 * discovery log
+	 * Start a single discovery operation if discovery is not already
+         * running 
 	 */
-	if (sysctl_discovery) {
-		DEBUG(2, __FUNCTION__ "() discovery already running, so we"
-		      " just return the old discovery log!\n");
-		irlmp_discovery_confirm(irlmp->cachelog);
-	} else
+	if (!sysctl_discovery)
 		irlmp_do_discovery(nslots);
 }
 
@@ -773,8 +780,8 @@
 	__u8 service;
 	int i = 0;
 
-	DEBUG(1, "IrDA Discovered: %s\n", discovery->info);
-	DEBUG(1, "    Services: ");
+	IRDA_DEBUG(1, "IrDA Discovered: %s\n", discovery->info);
+	IRDA_DEBUG(1, "    Services: ");
 
 	service_log = irlmp_hint_to_service(discovery->hints.byte);
 	if (!service_log)
@@ -784,10 +791,10 @@
 	 *  Check all services on the device
 	 */
 	while ((service = service_log[i++]) != S_END) {
-		DEBUG( 4, "service=%02x\n", service);
+		IRDA_DEBUG( 4, "service=%02x\n", service);
 		client = hashbin_find(irlmp->registry, service, NULL);
 		if (entry && entry->discovery_callback) {
-			DEBUG( 4, "discovery_callback!\n");
+			IRDA_DEBUG( 4, "discovery_callback!\n");
 
 			entry->discovery_callback(discovery);
 		} else {
@@ -819,7 +826,7 @@
 {
 	discovery_t *discovery;
 
-	DEBUG(3, __FUNCTION__ "()\n");
+	IRDA_DEBUG(3, __FUNCTION__ "()\n");
 	
 	/* Check if client wants the whole log */
 	if (client->callback2)
@@ -831,9 +838,13 @@
 	 */
 	discovery = (discovery_t *) hashbin_get_first(log);
 	while (discovery != NULL) {
-		DEBUG(3, "discovery->daddr = 0x%08x\n", discovery->daddr); 
+		IRDA_DEBUG(3, "discovery->daddr = 0x%08x\n", discovery->daddr); 
 		
-		if (client->hint_mask & discovery->hints.word) {
+		/* 
+		 * Any common hint bits? Remember to mask away the extension
+		 * bits ;-)
+		 */
+		if (client->hint_mask & discovery->hints.word & 0x7f7f) {
 			if (client->callback1)
 				client->callback1(discovery);
 		}
@@ -852,11 +863,11 @@
 {
 	irlmp_client_t *client;
 	
-	DEBUG(3, __FUNCTION__ "()\n");
+	IRDA_DEBUG(3, __FUNCTION__ "()\n");
 	
 	ASSERT(log != NULL, return;);
 	
-	if (!hashbin_get_size(log))
+	if (!(HASHBIN_GET_SIZE(log)))
 		return;
 	
 	client = (irlmp_client_t *) hashbin_get_first(irlmp->clients);
@@ -876,7 +887,7 @@
  */
 discovery_t *irlmp_get_discovery_response()
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(irlmp != NULL, return NULL;);
 
@@ -889,8 +900,9 @@
 	 */
 	irlmp->discovery_rsp.charset = CS_ASCII;
 
-	strncpy(irlmp->discovery_rsp.info, sysctl_devname, 31);
-	irlmp->discovery_rsp.info_len = strlen(irlmp->discovery_rsp.info) + 2;
+	strncpy(irlmp->discovery_rsp.nickname, sysctl_devname, 
+		NICKNAME_MAX_LEN);
+	irlmp->discovery_rsp.name_len = strlen(irlmp->discovery_rsp.nickname);
 
 	return &irlmp->discovery_rsp;
 }
@@ -901,17 +913,16 @@
  *    Send some data to peer device
  *
  */
-void irlmp_data_request(struct lsap_cb *self, struct sk_buff *skb) 
+int irlmp_data_request(struct lsap_cb *self, struct sk_buff *skb) 
 {
-	ASSERT(skb != NULL, return;);
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
 	
 	/* Make room for MUX header */
-	ASSERT(skb_headroom( skb) >= LMP_HEADER, return;);
+	ASSERT(skb_headroom(skb) >= LMP_HEADER, return -1;);
 	skb_push(skb, LMP_HEADER);
-
-	irlmp_do_lsap_event(self, LM_DATA_REQUEST, skb);
+	
+	return irlmp_do_lsap_event(self, LM_DATA_REQUEST, skb);
 }
 
 /*
@@ -920,13 +931,15 @@
  *    Got data from LAP layer so pass it up to upper layer
  *
  */
-inline void irlmp_data_indication(struct lsap_cb *self, struct sk_buff *skb) 
+void irlmp_data_indication(struct lsap_cb *self, struct sk_buff *skb) 
 {
 	/* Hide LMP header from layer above */
 	skb_pull(skb, LMP_HEADER);
 
 	if (self->notify.data_indication)
 		self->notify.data_indication(self->notify.instance, self, skb);
+	else
+		dev_kfree_skb(skb);
 }
 
 /*
@@ -935,17 +948,17 @@
  *    
  *
  */
-inline void irlmp_udata_request( struct lsap_cb *self, struct sk_buff *skb) 
+int irlmp_udata_request(struct lsap_cb *self, struct sk_buff *skb) 
 {
- 	DEBUG( 4, __FUNCTION__ "()\n"); 
+ 	IRDA_DEBUG(4, __FUNCTION__ "()\n"); 
 
-	ASSERT( skb != NULL, return;);
+	ASSERT(skb != NULL, return -1;);
 	
 	/* Make room for MUX header */
-	ASSERT( skb_headroom( skb) >= LMP_HEADER, return;);
-	skb_push( skb, LMP_HEADER);
+	ASSERT(skb_headroom(skb) >= LMP_HEADER, return -1;);
+	skb_push(skb, LMP_HEADER);
 
-	irlmp_do_lsap_event( self, LM_UDATA_REQUEST, skb);
+	return irlmp_do_lsap_event(self, LM_UDATA_REQUEST, skb);
 }
 
 /*
@@ -954,51 +967,104 @@
  *    Send unreliable data (but still within the connection)
  *
  */
-void irlmp_udata_indication( struct lsap_cb *self, struct sk_buff *skb) 
+void irlmp_udata_indication(struct lsap_cb *self, struct sk_buff *skb) 
 {
- 	DEBUG( 4, __FUNCTION__ "()\n"); 
+ 	IRDA_DEBUG(4, __FUNCTION__ "()\n"); 
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
 
 	/* Hide LMP header from layer above */
-	skb_pull( skb, LMP_HEADER);
+	skb_pull(skb, LMP_HEADER);
 
 	if (self->notify.udata_indication)
-		self->notify.udata_indication(self->notify.instance, self, skb);
+		self->notify.udata_indication(self->notify.instance, self, 
+					      skb);
+	else
+		dev_kfree_skb(skb);
 }
 
 /*
- * Function irlmp_connection_less_data_request (skb)
+ * Function irlmp_connless_data_request (self, skb)
  *
- *    Send out of connection UI frames
+ *    
  *
  */
-void irlmp_connectionless_data_request( struct sk_buff *skb)
+#ifdef CONFIG_IRDA_ULTRA
+int irlmp_connless_data_request(struct lsap_cb *self, struct sk_buff *skb) 
 {
-	DEBUG( 1, __FUNCTION__ "(), Sorry not implemented\n"); 
+	struct sk_buff *clone_skb;
+	struct lap_cb *lap;
+
+ 	IRDA_DEBUG(4, __FUNCTION__ "()\n"); 
+
+	ASSERT(skb != NULL, return -1;);
+	
+	/* Make room for MUX and PID header */
+	ASSERT(skb_headroom(skb) >= LMP_HEADER+LMP_PID_HEADER, return -1;);
+	
+	/* Insert protocol identifier */
+	skb_push(skb, LMP_PID_HEADER);
+	skb->data[0] = self->pid;
+
+	/* Connectionless sockets must use 0x70 */
+	skb_push(skb, LMP_HEADER);
+	skb->data[0] = skb->data[1] = LSAP_CONNLESS;
+
+	/* Try to send Connectionless  packets out on all links */
+	lap = (struct lap_cb *) hashbin_get_first(irlmp->links);
+	while (lap != NULL) {
+		ASSERT(lap->magic == LMP_LAP_MAGIC, return -1;);
+
+		clone_skb = skb_clone(skb, GFP_ATOMIC);
+		if (!clone_skb)
+			return -ENOMEM;
+
+		irlap_unitdata_request(lap->irlap, clone_skb);
+		
+		lap = (struct lap_cb *) hashbin_get_next(irlmp->links);
+	}
+	dev_kfree_skb(skb);
+
+	return 0;
 }
+#endif /* CONFIG_IRDA_ULTRA */
 
 /*
- * Function irlmp_connection_less_data_indication (skb)
+ * Function irlmp_connless_data_indication (self, skb)
  *
- *    
+ *    Receive unreliable data outside any connection. Mostly used by Ultra
  *
  */
-void irlmp_connectionless_data_indication( struct sk_buff *skb)
+#ifdef CONFIG_IRDA_ULTRA
+void irlmp_connless_data_indication(struct lsap_cb *self, struct sk_buff *skb) 
 {
-	DEBUG( 1, __FUNCTION__ "()\n"); 
+ 	IRDA_DEBUG(4, __FUNCTION__ "()\n"); 
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
+
+	/* Hide LMP and PID header from layer above */
+	skb_pull(skb, LMP_HEADER+LMP_PID_HEADER);
+
+	if (self->notify.udata_indication)
+		self->notify.udata_indication(self->notify.instance, self,
+					      skb);
+	else
+		dev_kfree_skb(skb);
 }
+#endif /* CONFIG_IRDA_ULTRA */
 
 void irlmp_status_request(void) 
 {
-	DEBUG( 1, "irlmp_status_request(), Not implemented\n");
+	IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented\n");
 }
 
 void irlmp_status_indication(LINK_STATUS link, LOCK_STATUS lock) 
 {
-	DEBUG( 4, "irlmp_status_indication(), Not implemented\n");
+	IRDA_DEBUG(1, __FUNCTION__ "(), Not implemented\n");
 }
 
 /*
@@ -1016,32 +1082,33 @@
 	 * Allocate array to store services in. 16 entries should be safe 
 	 * since we currently only support 2 hint bytes
 	 */
-	service = kmalloc( 16, GFP_ATOMIC);
-	if ( !service) {
-		DEBUG(1, __FUNCTION__ "(), Unable to kmalloc!\n");
+	service = kmalloc(16, GFP_ATOMIC);
+	if (!service) {
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unable to kmalloc!\n");
 		return NULL;
 	}
 
-	if ( !hint[0]) {
-		DEBUG(1, "<None>\n");
+	if (!hint[0]) {
+		IRDA_DEBUG(1, "<None>\n");
+		kfree(service);
 		return NULL;
 	}
-	if ( hint[0] & HINT_PNP)
-		DEBUG(1, "PnP Compatible ");
-	if ( hint[0] & HINT_PDA)
-		DEBUG(1, "PDA/Palmtop ");
-	if ( hint[0] & HINT_COMPUTER)
-		DEBUG(1, "Computer ");
-	if ( hint[0] & HINT_PRINTER) {
-		DEBUG(1, "Printer ");
+	if (hint[0] & HINT_PNP)
+		IRDA_DEBUG(1, "PnP Compatible ");
+	if (hint[0] & HINT_PDA)
+		IRDA_DEBUG(1, "PDA/Palmtop ");
+	if (hint[0] & HINT_COMPUTER)
+		IRDA_DEBUG(1, "Computer ");
+	if (hint[0] & HINT_PRINTER) {
+		IRDA_DEBUG(1, "Printer ");
 		service[i++] = S_PRINTER;
 	}
-	if ( hint[0] & HINT_MODEM)
-		DEBUG(1, "Modem ");
-	if ( hint[0] & HINT_FAX)
-		DEBUG(1, "Fax ");
-	if ( hint[0] & HINT_LAN) {
-		DEBUG(1, "LAN Access ");		
+	if (hint[0] & HINT_MODEM)
+		IRDA_DEBUG(1, "Modem ");
+	if (hint[0] & HINT_FAX)
+		IRDA_DEBUG(1, "Fax ");
+	if (hint[0] & HINT_LAN) {
+		IRDA_DEBUG(1, "LAN Access ");		
 		service[i++] = S_LAN;
 	}
 	/* 
@@ -1049,23 +1116,23 @@
 	 *  there, but this is not really required by the standard.
 	 *  (IrLMP p. 29)
 	 */
-	if ( hint[0] & HINT_EXTENSION) {
-		if ( hint[1] & HINT_TELEPHONY) {
-			DEBUG(1, "Telephony ");
+	if (hint[0] & HINT_EXTENSION) {
+		if (hint[1] & HINT_TELEPHONY) {
+			IRDA_DEBUG(1, "Telephony ");
 			service[i++] = S_TELEPHONY;
-		} if ( hint[1] & HINT_FILE_SERVER)
-			DEBUG(1, "File Server ");
+		} if (hint[1] & HINT_FILE_SERVER)
+			IRDA_DEBUG(1, "File Server ");
 		
-		if ( hint[1] & HINT_COMM) {
-			DEBUG(1, "IrCOMM ");
+		if (hint[1] & HINT_COMM) {
+			IRDA_DEBUG(1, "IrCOMM ");
 			service[i++] = S_COMM;
 		}
-		if ( hint[1] & HINT_OBEX) {
-			DEBUG(1, "IrOBEX ");
+		if (hint[1] & HINT_OBEX) {
+			IRDA_DEBUG(1, "IrOBEX ");
 			service[i++] = S_OBEX;
 		}
 	}
-	DEBUG(1, "\n");
+	IRDA_DEBUG(1, "\n");
 
 	/* So that client can be notified about any discovery */
 	service[i++] = S_ANY;
@@ -1115,11 +1182,15 @@
 		hint.byte[0] |= HINT_EXTENSION;
 		hint.byte[1] |= HINT_OBEX;
 		break;
+	case S_TELEPHONY:
+		hint.byte[0] |= HINT_EXTENSION;
+		hint.byte[1] |= HINT_TELEPHONY;
+		break;
 	case S_ANY:
 		hint.word = 0xffff;
 		break;
 	default:
-		DEBUG( 1, __FUNCTION__ "(), Unknown service!\n");
+		IRDA_DEBUG( 1, __FUNCTION__ "(), Unknown service!\n");
 		break;
 	}
 	return hint.word;
@@ -1136,7 +1207,7 @@
 	irlmp_service_t *service;
 	__u32 handle;
 
-	DEBUG(4, __FUNCTION__ "(), hints = %04x\n", hints);
+	IRDA_DEBUG(4, __FUNCTION__ "(), hints = %04x\n", hints);
 
 	/* Get a unique handle for this service */
 	get_random_bytes(&handle, sizeof(handle));
@@ -1148,11 +1219,11 @@
 	/* Make a new registration */
  	service = kmalloc(sizeof(irlmp_service_t), GFP_ATOMIC);
 	if (!service) {
-		DEBUG(1, __FUNCTION__ "(), Unable to kmalloc!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unable to kmalloc!\n");
 		return 0;
 	}
 	service->hints = hints;
-	hashbin_insert(irlmp->services, (QUEUE*) service, handle, NULL);
+	hashbin_insert(irlmp->services, (queue_t *) service, handle, NULL);
 
 	return handle;
 }
@@ -1168,14 +1239,14 @@
 {
 	irlmp_service_t *service;
 		
- 	DEBUG(4, __FUNCTION__ "()\n");
+ 	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	if (!handle)
 		return -1;
  
 	service = hashbin_find(irlmp->services, handle, NULL);
 	if (!service) {
-		DEBUG(1, __FUNCTION__ "(), Unknown service!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown service!\n");
 		return -1;
 	}
 
@@ -1217,7 +1288,7 @@
 	/* Make a new registration */
  	client = kmalloc(sizeof(irlmp_client_t), GFP_ATOMIC);
 	if (!client) {
-		DEBUG( 1, __FUNCTION__ "(), Unable to kmalloc!\n");
+		IRDA_DEBUG( 1, __FUNCTION__ "(), Unable to kmalloc!\n");
 
 		return 0;
 	}
@@ -1227,7 +1298,7 @@
 	client->callback1 = callback1;
 	client->callback2 = callback2;
 
- 	hashbin_insert(irlmp->clients, (QUEUE *) client, handle, NULL);
+ 	hashbin_insert(irlmp->clients, (queue_t *) client, handle, NULL);
 
 	return handle;
 }
@@ -1251,7 +1322,7 @@
 
 	client = hashbin_find(irlmp->clients, handle, NULL);
 	if (!client) {
-		DEBUG(1, __FUNCTION__ "(), Unknown client!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown client!\n");
 		return -1;
 	}
 
@@ -1272,18 +1343,18 @@
 {
  	struct irlmp_client *client;
  
- 	DEBUG(4, __FUNCTION__ "()\n");
+ 	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	if (!handle)
 		return -1;
  
 	client = hashbin_find(irlmp->clients, handle, NULL);
 	if (!client) {
-		DEBUG(1, __FUNCTION__ "(), Unknown client!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown client!\n");
 		return -1;
 	}
 
-	DEBUG( 4, __FUNCTION__ "(), removing client!\n");
+	IRDA_DEBUG( 4, __FUNCTION__ "(), removing client!\n");
 	client = hashbin_remove( irlmp->clients, handle, NULL);
 	if (client)
 		kfree(client);
@@ -1296,19 +1367,25 @@
  *
  *    Check if the given source LSAP selector is in use
  */
-int irlmp_slsap_inuse( __u8 slsap_sel)
+int irlmp_slsap_inuse(__u8 slsap_sel)
 {
 	struct lsap_cb *self;
 	struct lap_cb *lap;
 
-	ASSERT( irlmp != NULL, return TRUE;);
-	ASSERT( irlmp->magic == LMP_MAGIC, return TRUE;);
-	ASSERT( slsap_sel != LSAP_ANY, return TRUE;);
-
-	DEBUG( 4, __FUNCTION__ "()\n");
+	ASSERT(irlmp != NULL, return TRUE;);
+	ASSERT(irlmp->magic == LMP_MAGIC, return TRUE;);
+	ASSERT(slsap_sel != LSAP_ANY, return TRUE;);
+
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+#ifdef CONFIG_IRDA_ULTRA
+	/* Accept all bindings to the connectionless LSAP */
+	if (slsap_sel == LSAP_CONNLESS)
+		return FALSE;
+#endif /* CONFIG_IRDA_ULTRA */
 
 	/* Valid values are between 0 and 127 */
-	if (slsap_sel > 127)
+	if (slsap_sel > LSAP_MAX)
 		return TRUE;
 
 	/*
@@ -1324,16 +1401,14 @@
 		while (self != NULL) {
 			ASSERT(self->magic == LMP_LSAP_MAGIC, return TRUE;);
 
-			if ((self->slsap_sel == slsap_sel))/*  &&  */
-/* 			    ( self->dlsap_sel == LSAP_ANY)) */
-			{
-				DEBUG( 4, "Source LSAP selector=%02x in use\n",
-				       self->slsap_sel); 
+			if ((self->slsap_sel == slsap_sel)) {
+				IRDA_DEBUG(4, "Source LSAP selector=%02x in use\n",
+				      self->slsap_sel); 
 				return TRUE;
 			}
-			self = (struct lsap_cb*) hashbin_get_next( lap->lsaps);
+			self = (struct lsap_cb*) hashbin_get_next(lap->lsaps);
 		}
-		lap = (struct lap_cb *) hashbin_get_next( irlmp->links);
+		lap = (struct lap_cb *) hashbin_get_next(irlmp->links);
 	}     
 	return FALSE;
 }
@@ -1358,8 +1433,8 @@
 	while (irlmp_slsap_inuse(irlmp->free_lsap_sel)) {
 		irlmp->free_lsap_sel++;
 
-		/* Check if we need to wraparound */
-		if (irlmp->free_lsap_sel > 127) {
+		/* Check if we need to wraparound (0x70-0x7f are reserved) */
+		if (irlmp->free_lsap_sel > LSAP_MAX) {
 			irlmp->free_lsap_sel = 10;
 
 			/* Make sure we terminate the loop */
@@ -1367,7 +1442,7 @@
 				return 0;
 		}
 	}
-	DEBUG(4, __FUNCTION__ "(), next free lsap_sel=%02x\n", lsap_sel);
+	IRDA_DEBUG(4, __FUNCTION__ "(), next free lsap_sel=%02x\n", lsap_sel);
 	
 	return lsap_sel;
 }
@@ -1385,26 +1460,26 @@
 
 	switch (lap_reason) {		
 	case LAP_DISC_INDICATION: /* Received a disconnect request from peer */
-		DEBUG( 1, __FUNCTION__ "(), LAP_DISC_INDICATION\n");
+		IRDA_DEBUG( 1, __FUNCTION__ "(), LAP_DISC_INDICATION\n");
 		reason = LM_USER_REQUEST;
 		break;
 	case LAP_NO_RESPONSE:    /* To many retransmits without response */
-		DEBUG( 1, __FUNCTION__ "(), LAP_NO_RESPONSE\n");
+		IRDA_DEBUG( 1, __FUNCTION__ "(), LAP_NO_RESPONSE\n");
 		reason = LM_LAP_DISCONNECT;
 		break;
 	case LAP_RESET_INDICATION:
-		DEBUG( 1, __FUNCTION__ "(), LAP_RESET_INDICATION\n");
+		IRDA_DEBUG( 1, __FUNCTION__ "(), LAP_RESET_INDICATION\n");
 		reason = LM_LAP_RESET;
 		break;
 	case LAP_FOUND_NONE:
 	case LAP_MEDIA_BUSY:
 	case LAP_PRIMARY_CONFLICT:
-		DEBUG( 1, __FUNCTION__ "(), LAP_FOUND_NONE, LAP_MEDIA_BUSY or LAP_PRIMARY_CONFLICT\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), LAP_FOUND_NONE, LAP_MEDIA_BUSY or LAP_PRIMARY_CONFLICT\n");
 		reason = LM_CONNECT_FAILURE;
 		break;
 	default:
-		DEBUG( 1, __FUNCTION__ 
-		       "(), Unknow IrLAP disconnect reason %d!\n", lap_reason);
+		IRDA_DEBUG(1, __FUNCTION__ 
+		      "(), Unknow IrLAP disconnect reason %d!\n", lap_reason);
 		reason = LM_LAP_DISCONNECT;
 		break;
 	}
@@ -1414,8 +1489,6 @@
 
 __u32 irlmp_get_saddr(struct lsap_cb *self)
 {
-	DEBUG(3, __FUNCTION__ "()\n");
-
 	ASSERT(self != NULL, return 0;);
 	ASSERT(self->lap != NULL, return 0;);
 
@@ -1424,8 +1497,6 @@
 
 __u32 irlmp_get_daddr(struct lsap_cb *self)
 {
-	DEBUG(3, __FUNCTION__ "()\n");
-
 	ASSERT(self != NULL, return 0;);
 	ASSERT(self->lap != NULL, return 0;);
 	
@@ -1455,21 +1526,21 @@
 	
 	len += sprintf( buf+len, "Unconnected LSAPs:\n");
 	self = (struct lsap_cb *) hashbin_get_first( irlmp->unconnected_lsaps);
-	while ( self != NULL) {
-		ASSERT( self->magic == LMP_LSAP_MAGIC, return 0;);
-		len += sprintf( buf+len, "lsap state: %s, ", 
-				irlsap_state[ self->lsap_state]);
-		len += sprintf( buf+len, 
-				"slsap_sel: %#02x, dlsap_sel: %#02x, ",
-				self->slsap_sel, self->dlsap_sel); 
-		len += sprintf( buf+len, "(%s)", self->notify.name);
-		len += sprintf( buf+len, "\n");
+	while (self != NULL) {
+		ASSERT(self->magic == LMP_LSAP_MAGIC, return 0;);
+		len += sprintf(buf+len, "lsap state: %s, ", 
+			       irlsap_state[ self->lsap_state]);
+		len += sprintf(buf+len, 
+			       "slsap_sel: %#02x, dlsap_sel: %#02x, ",
+			       self->slsap_sel, self->dlsap_sel); 
+		len += sprintf(buf+len, "(%s)", self->notify.name);
+		len += sprintf(buf+len, "\n");
 
-		self = ( struct lsap_cb *) hashbin_get_next( 
+		self = (struct lsap_cb *) hashbin_get_next(
 			irlmp->unconnected_lsaps);
  	} 
 
-	len += sprintf( buf+len, "\nRegistred Link Layers:\n");
+	len += sprintf(buf+len, "\nRegistred Link Layers:\n");
 
 	lap = (struct lap_cb *) hashbin_get_first(irlmp->links);
 	while (lap != NULL) {
@@ -1478,10 +1549,11 @@
 
 		len += sprintf(buf+len, "saddr: %#08x, daddr: %#08x, ",
 			       lap->saddr, lap->daddr); 
+		len += sprintf(buf+len, "refcount: %d", lap->refcount);
 		len += sprintf(buf+len, "\n");
 
-		len += sprintf( buf+len, "\nConnected LSAPs:\n");
-		self = (struct lsap_cb *) hashbin_get_first( lap->lsaps);
+		len += sprintf(buf+len, "\nConnected LSAPs:\n");
+		self = (struct lsap_cb *) hashbin_get_first(lap->lsaps);
 		while (self != NULL) {
 			ASSERT(self->magic == LMP_LSAP_MAGIC, return 0;);
 			len += sprintf(buf+len, "lsap state: %s, ", 
@@ -1499,9 +1571,8 @@
 
 		lap = (struct lap_cb *) hashbin_get_next(irlmp->links);
  	} 
-
-	restore_flags( flags);
-
+	restore_flags(flags);
+	
 	return len;
 }
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irlmp_event.c linux.15p9/net/irda/irlmp_event.c
--- linux.vanilla/net/irda/irlmp_event.c	Sat Aug 14 02:26:03 1999
+++ linux.15p9/net/irda/irlmp_event.c	Tue Jan 18 01:08:19 2000
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Fri Apr 23 08:57:23 1999
+ * Modified at:   Sun Jan  9 07:45:06 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
+ *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>, 
  *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
@@ -75,35 +75,35 @@
 };
 
 /* LAP Connection control proto declarations */
-static void irlmp_state_standby  ( struct lap_cb *, IRLMP_EVENT, 
-				   struct sk_buff *);
-static void irlmp_state_u_connect( struct lap_cb *, IRLMP_EVENT, 
-				   struct sk_buff *);
-static void irlmp_state_active   ( struct lap_cb *, IRLMP_EVENT, 
-				   struct sk_buff *);
+static void irlmp_state_standby  (struct lap_cb *, IRLMP_EVENT, 
+				  struct sk_buff *);
+static void irlmp_state_u_connect(struct lap_cb *, IRLMP_EVENT, 
+				  struct sk_buff *);
+static void irlmp_state_active   (struct lap_cb *, IRLMP_EVENT, 
+				  struct sk_buff *);
 
 /* LSAP Connection control proto declarations */
-static void irlmp_state_disconnected( struct lsap_cb *, IRLMP_EVENT, 
-				      struct sk_buff *);
-static void irlmp_state_connect     ( struct lsap_cb *, IRLMP_EVENT, 
-				      struct sk_buff *);
-static void irlmp_state_connect_pend( struct lsap_cb *, IRLMP_EVENT,
-				      struct sk_buff *);
-static void irlmp_state_dtr         ( struct lsap_cb *, IRLMP_EVENT, 
-				      struct sk_buff *);
-static void irlmp_state_setup       ( struct lsap_cb *, IRLMP_EVENT, 
-				      struct sk_buff *);
-static void irlmp_state_setup_pend  ( struct lsap_cb *, IRLMP_EVENT, 
-				      struct sk_buff *);
+static int irlmp_state_disconnected(struct lsap_cb *, IRLMP_EVENT, 
+				    struct sk_buff *);
+static int irlmp_state_connect     (struct lsap_cb *, IRLMP_EVENT, 
+				    struct sk_buff *);
+static int irlmp_state_connect_pend(struct lsap_cb *, IRLMP_EVENT,
+				    struct sk_buff *);
+static int irlmp_state_dtr         (struct lsap_cb *, IRLMP_EVENT, 
+				    struct sk_buff *);
+static int irlmp_state_setup       (struct lsap_cb *, IRLMP_EVENT, 
+				    struct sk_buff *);
+static int irlmp_state_setup_pend  (struct lsap_cb *, IRLMP_EVENT, 
+				    struct sk_buff *);
 
-static void (*lap_state[]) ( struct lap_cb *, IRLMP_EVENT, struct sk_buff *) =
+static void (*lap_state[]) (struct lap_cb *, IRLMP_EVENT, struct sk_buff *) =
 {
 	irlmp_state_standby,
 	irlmp_state_u_connect,
 	irlmp_state_active,
 };
 
-static void (*lsap_state[])( struct lsap_cb *, IRLMP_EVENT, struct sk_buff *) =
+static int (*lsap_state[])( struct lsap_cb *, IRLMP_EVENT, struct sk_buff *) =
 {
 	irlmp_state_disconnected,
 	irlmp_state_connect,
@@ -114,16 +114,16 @@
 };
 
 /* Do connection control events */
-void irlmp_do_lsap_event(struct lsap_cb *self, IRLMP_EVENT event, 
-			 struct sk_buff *skb)
+int irlmp_do_lsap_event(struct lsap_cb *self, IRLMP_EVENT event, 
+			struct sk_buff *skb)
 {
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
 
-	DEBUG(4, __FUNCTION__ "(), EVENT = %s, STATE = %s\n",
-	      irlmp_event[ event], irlmp_state[ self->lsap_state]);
+	IRDA_DEBUG(4, __FUNCTION__ "(), EVENT = %s, STATE = %s\n",
+		   irlmp_event[event], irlmp_state[ self->lsap_state]);
 
-	(*lsap_state[self->lsap_state]) (self, event, skb);
+	return (*lsap_state[self->lsap_state]) (self, event, skb);
 }
 
 /*
@@ -138,29 +138,29 @@
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LMP_LAP_MAGIC, return;);
 	
-	DEBUG(4, __FUNCTION__ "(), EVENT = %s, STATE = %s\n",
-	      irlmp_event[event], 
-	      irlmp_state[self->lap_state]);
+	IRDA_DEBUG(4, __FUNCTION__ "(), EVENT = %s, STATE = %s\n",
+		   irlmp_event[event], 
+		   irlmp_state[self->lap_state]);
 
 	(*lap_state[self->lap_state]) (self, event, skb);
 }
 
-void irlmp_discovery_timer_expired( unsigned long data)
+void irlmp_discovery_timer_expired(void *data)
 {
-	DEBUG(4, "IrLMP, discovery timer expired!\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	if (sysctl_discovery)
 		irlmp_do_discovery(sysctl_discovery_slots);
 
 	/* Restart timer */
-	irlmp_start_discovery_timer(irlmp, 300);
+	irlmp_start_discovery_timer(irlmp, sysctl_discovery_timeout * HZ);
 }
 
-void irlmp_watchdog_timer_expired( unsigned long data)
+void irlmp_watchdog_timer_expired(void *data)
 {
-	struct lsap_cb *self = ( struct lsap_cb *) data;
+	struct lsap_cb *self = (struct lsap_cb *) data;
 	
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
@@ -168,11 +168,11 @@
 	irlmp_do_lsap_event(self, LM_WATCHDOG_TIMEOUT, NULL);
 }
 
-void irlmp_idle_timer_expired(unsigned long data)
+void irlmp_idle_timer_expired(void *data)
 {
 	struct lap_cb *self = (struct lap_cb *) data;
 	
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LMP_LAP_MAGIC, return;);
@@ -195,10 +195,10 @@
 static void irlmp_state_standby(struct lap_cb *self, IRLMP_EVENT event, 
 				struct sk_buff *skb)
 {	
-	DEBUG( 4, __FUNCTION__ "()\n"); 
-	ASSERT( self->irlap != NULL, return;);
+	IRDA_DEBUG(4, __FUNCTION__ "()\n"); 
+	ASSERT(self->irlap != NULL, return;);
 	
-	switch( event) {
+	switch (event) {
 	case LM_LAP_DISCOVERY_REQUEST:
 		/* irlmp_next_station_state( LMP_DISCOVER); */
 		
@@ -213,27 +213,31 @@
 		 *  think that the link is free since IrLMP may then start
 		 *  discovery before the connection is properly set up. DB.
 		 */
-		irlmp_next_lap_state( self, LAP_ACTIVE);
+		irlmp_next_lap_state(self, LAP_ACTIVE);
 
 		/* Just accept connection TODO, this should be fixed */
-		irlap_connect_response( self->irlap, skb);
+		irlap_connect_response(self->irlap, skb);
 		break;
 	case LM_LAP_CONNECT_REQUEST:
-		DEBUG(4, __FUNCTION__ "() LS_CONNECT_REQUEST\n");
+		IRDA_DEBUG(4, __FUNCTION__ "() LS_CONNECT_REQUEST\n");
+
+		irlmp_next_lap_state(self, LAP_U_CONNECT);
+		self->refcount++;
 
 		/* FIXME: need to set users requested QoS */
 		irlap_connect_request(self->irlap, self->daddr, NULL, 0);
-
-		irlmp_next_lap_state( self, LAP_U_CONNECT);
 		break;
 	case LM_LAP_DISCONNECT_INDICATION:
-		DEBUG( 4, __FUNCTION__ 
-		       "(), Error LM_LAP_DISCONNECT_INDICATION\n");
+		IRDA_DEBUG(4, __FUNCTION__ 
+			   "(), Error LM_LAP_DISCONNECT_INDICATION\n");
 		
-		irlmp_next_lap_state( self, LAP_STANDBY);
+		irlmp_next_lap_state(self, LAP_STANDBY);
 		break;
 	default:
-		DEBUG(4, __FUNCTION__ "(), Unknown event\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %s\n",
+			   irlmp_event[event]);
+		if (skb)
+ 			dev_kfree_skb(skb);
 		break;
 	}
 }
@@ -245,55 +249,75 @@
  *    since the IrLAP connection does not exist, we must first start an
  *    IrLAP connection. We are now waiting response from IrLAP.
  * */
-static void irlmp_state_u_connect( struct lap_cb *self, IRLMP_EVENT event, 
-				   struct sk_buff *skb)
+static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event, 
+				  struct sk_buff *skb)
 {
 	struct lsap_cb *lsap;
 	struct lsap_cb *lsap_current;
 	
-	DEBUG(2, __FUNCTION__ "(), event=%s\n", irlmp_event[ event]);
+	IRDA_DEBUG(2, __FUNCTION__ "(), event=%s\n", irlmp_event[event]);
 
-	switch( event) {
+	switch (event) {
+	case LM_LAP_CONNECT_INDICATION:
+		/*  It's important to switch state first, to avoid IrLMP to 
+		 *  think that the link is free since IrLMP may then start
+		 *  discovery before the connection is properly set up. DB.
+		 */
+		irlmp_next_lap_state(self, LAP_ACTIVE);
+
+		/* Just accept connection TODO, this should be fixed */
+		irlap_connect_response(self->irlap, skb);
+
+		lsap = (struct lsap_cb *) hashbin_get_first(self->lsaps);
+		while (lsap != NULL) {
+			irlmp_do_lsap_event(lsap, LM_LAP_CONNECT_CONFIRM, NULL);
+			lsap = (struct lsap_cb*) hashbin_get_next(self->lsaps);
+		}
+		break;
+	case LM_LAP_CONNECT_REQUEST:
+		/* Already trying to connect */
+		self->refcount++;
+		break;
 	case LM_LAP_CONNECT_CONFIRM:
 		/* For all lsap_ce E Associated do LS_Connect_confirm */
-		irlmp_next_lap_state( self, LAP_ACTIVE);
+		irlmp_next_lap_state(self, LAP_ACTIVE);
 
-		lsap = ( struct lsap_cb *) hashbin_get_first( self->lsaps);
-		while ( lsap != NULL) {
-			irlmp_do_lsap_event(lsap, LM_LAP_CONNECT_CONFIRM, skb);
+		lsap = (struct lsap_cb *) hashbin_get_first(self->lsaps);
+		while (lsap != NULL) {
+			irlmp_do_lsap_event(lsap, LM_LAP_CONNECT_CONFIRM, NULL);
 			lsap = (struct lsap_cb*) hashbin_get_next(self->lsaps);
-		}		
+		}
 		break;
 	case LM_LAP_DISCONNECT_INDICATION:
-		DEBUG(2, __FUNCTION__ "(), IRLAP_DISCONNECT_INDICATION\n");
-	
-		irlmp_next_lap_state( self, LAP_STANDBY);
+		irlmp_next_lap_state(self, LAP_STANDBY);
+		self->refcount = 0;
 
 		/* Send disconnect event to all LSAPs using this link */
-		
-		lsap = ( struct lsap_cb *) hashbin_get_first( self->lsaps);
-		while ( lsap != NULL ) {
-			ASSERT( lsap->magic == LMP_LSAP_MAGIC, return;);
+		lsap = (struct lsap_cb *) hashbin_get_first( self->lsaps);
+		while (lsap != NULL ) {
+			ASSERT(lsap->magic == LMP_LSAP_MAGIC, return;);
 			
 			lsap_current = lsap;
 
 			/* Be sure to stay one item ahead */
-			lsap = ( struct lsap_cb *) hashbin_get_next( self->lsaps);
-			irlmp_do_lsap_event( lsap_current, 
-					     LM_LAP_DISCONNECT_INDICATION,
-					     NULL);
+			lsap = (struct lsap_cb *) hashbin_get_next(self->lsaps);
+			irlmp_do_lsap_event(lsap_current, 
+					    LM_LAP_DISCONNECT_INDICATION,
+					    NULL);
 		}
 		break;
 	case LM_LAP_DISCONNECT_REQUEST:
-		DEBUG( 4, __FUNCTION__ "(), LM_LAP_DISCONNECT_REQUEST\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), LM_LAP_DISCONNECT_REQUEST\n");
 
-		irlmp_next_lap_state( self, LAP_STANDBY);
-
-		/* FIXME */
-/* 		irlap_disconnect_request( self->irlap); */
+		self->refcount--;
+		if (self->refcount == 0)
+			irlmp_next_lap_state(self, LAP_STANDBY);
 		break;
 	default:
-		DEBUG( 4, __FUNCTION__ "(), Unknown event\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %s\n",
+			   irlmp_event[event]);
+		if (skb)
+ 			dev_kfree_skb(skb);
 		break;
 	}	
 }
@@ -310,11 +334,12 @@
 	struct lsap_cb *lsap;
 	struct lsap_cb *lsap_current;
 
-	DEBUG( 4, __FUNCTION__ "()\n"); 
+	IRDA_DEBUG(4, __FUNCTION__ "()\n"); 
 
- 	switch( event) {
+ 	switch (event) {
 	case LM_LAP_CONNECT_REQUEST:
-		DEBUG( 4, __FUNCTION__ "(), LS_CONNECT_REQUEST\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), LS_CONNECT_REQUEST\n");
+		self->refcount++;
 
 		/*
 		 *  LAP connection allready active, just bounce back! Since we 
@@ -324,7 +349,7 @@
 		 */
 		lsap = (struct lsap_cb *) hashbin_get_first(self->lsaps);
 		while (lsap != NULL) {
-			irlmp_do_lsap_event(lsap, LM_LAP_CONNECT_CONFIRM, skb);
+			irlmp_do_lsap_event(lsap, LM_LAP_CONNECT_CONFIRM, NULL);
  			lsap = (struct lsap_cb*) hashbin_get_next(self->lsaps);
 		}
 		
@@ -336,12 +361,12 @@
 			/* Be sure to stay one item ahead */
  			lsap = (struct lsap_cb*) hashbin_get_next(irlmp->unconnected_lsaps);
 			irlmp_do_lsap_event(lsap_current, 
-					    LM_LAP_CONNECT_CONFIRM, skb);
+					    LM_LAP_CONNECT_CONFIRM, NULL);
 		}
 		/* Keep state */
 		break;
 	case LM_LAP_DISCONNECT_REQUEST:
-		DEBUG(4, __FUNCTION__ "(), LM_LAP_DISCONNECT_REQUEST\n");
+		self->refcount--;
 
 		/*
 		 *  Need to find out if we should close IrLAP or not. If there
@@ -349,42 +374,44 @@
 		 *  must be the one that tries to close IrLAP. It will be 
 		 *  removed later and moved to the list of unconnected LSAPs
 		 */
-		if (hashbin_get_size(self->lsaps) == 1)
+		if (HASHBIN_GET_SIZE(self->lsaps) > 0)
 			irlmp_start_idle_timer(self, LM_IDLE_TIMEOUT);
-
+		else {
+			/* No more connections, so close IrLAP */
+			irlmp_next_lap_state(self, LAP_STANDBY);
+			irlap_disconnect_request(self->irlap);
+		}
 		break;
 	case LM_LAP_IDLE_TIMEOUT:
-		if (hashbin_get_size(self->lsaps) == 0) {
-			DEBUG(2, __FUNCTION__ 
-			      "(), no more LSAPs so time to close IrLAP\n");
+		if (HASHBIN_GET_SIZE(self->lsaps) == 0) {
 			irlmp_next_lap_state(self, LAP_STANDBY);
-			
 			irlap_disconnect_request(self->irlap);
 		}
 		break;
 	case LM_LAP_DISCONNECT_INDICATION:
-		DEBUG(4, __FUNCTION__ "(), IRLAP_DISCONNECT_INDICATION\n");
-	
-		irlmp_next_lap_state( self, LAP_STANDBY);		
+		irlmp_next_lap_state(self, LAP_STANDBY);		
+		self->refcount = 0;
 		
 		/* 
 		 *  Inform all connected LSAP's using this link
 		 */
-		lsap = ( struct lsap_cb *) hashbin_get_first( self->lsaps);
-		while ( lsap != NULL ) {
-			ASSERT( lsap->magic == LMP_LSAP_MAGIC, return;);
+		lsap = (struct lsap_cb *) hashbin_get_first(self->lsaps);
+		while (lsap != NULL ) {
+			ASSERT(lsap->magic == LMP_LSAP_MAGIC, return;);
 			
 			lsap_current = lsap;
 
 			/* Be sure to stay one item ahead */
-			lsap = ( struct lsap_cb *) hashbin_get_next( self->lsaps);
-			irlmp_do_lsap_event( lsap_current, 
-					     LM_LAP_DISCONNECT_INDICATION,
-					     NULL);
+			lsap = (struct lsap_cb *) hashbin_get_next(self->lsaps);
+			irlmp_do_lsap_event(lsap_current, 
+					    LM_LAP_DISCONNECT_INDICATION,
+					    NULL);
 		}
 		break;
 	default:
-		DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %d\n", event);
+		if (skb)
+ 			dev_kfree_skb(skb);
 		break;
 	}	
 }
@@ -401,33 +428,59 @@
  *    DISCONNECTED
  *
  */
-static void irlmp_state_disconnected( struct lsap_cb *self, IRLMP_EVENT event,
-				      struct sk_buff *skb) 
+static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event,
+				    struct sk_buff *skb) 
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	int ret = 0;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
-	switch( event) {
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+
+	switch (event) {
+#ifdef CONFIG_IRDA_ULTRA
+	case LM_UDATA_INDICATION:
+		irlmp_connless_data_indication(self, skb); 
+		break;
+#endif /* CONFIG_IRDA_ULTRA */
 	case LM_CONNECT_REQUEST:
-		DEBUG( 4, __FUNCTION__ "(), LM_CONNECT_REQUEST\n");
-		irlmp_next_lsap_state( self, LSAP_SETUP_PEND);
+		IRDA_DEBUG(4, __FUNCTION__ "(), LM_CONNECT_REQUEST\n");
+
+		if (self->conn_skb) {
+			WARNING(__FUNCTION__ 
+				"(), busy with another request!\n");
+			return -EBUSY;
+		}
+		self->conn_skb = skb;
+
+		irlmp_next_lsap_state(self, LSAP_SETUP_PEND);
 
 		irlmp_do_lap_event(self->lap, LM_LAP_CONNECT_REQUEST, NULL);
 
-		/* Start watchdog timer ( 5 secs for now) */
-		irlmp_start_watchdog_timer(self, 500);
+		/* Start watchdog timer (5 secs for now) */
+		irlmp_start_watchdog_timer(self, 5*HZ);
 		break;
 	case LM_CONNECT_INDICATION:
 		irlmp_next_lsap_state(self, LSAP_CONNECT_PEND);
 
-		irlmp_do_lap_event(self->lap, LM_LAP_CONNECT_REQUEST, skb);
+		if (self->conn_skb) {
+			WARNING(__FUNCTION__ 
+				"(), busy with another request!\n");
+			return -EBUSY;
+		}
+		self->conn_skb = skb;
+
+		irlmp_do_lap_event(self->lap, LM_LAP_CONNECT_REQUEST, NULL);
 		break;
 	default:
-		DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG(2, __FUNCTION__ "(), Unknown event %s\n", 
+			   irlmp_event[event]);
+		if (skb)
+  			dev_kfree_skb(skb);
 		break;
 	}
+	return ret;
 }
 
 /*
@@ -436,19 +489,20 @@
  *    CONNECT
  *
  */
-static void irlmp_state_connect( struct lsap_cb *self, IRLMP_EVENT event, 
-				 struct sk_buff *skb) 
+static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event, 
+				struct sk_buff *skb) 
 {
 	struct lsap_cb *lsap;
+	int ret = 0;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
 
-	switch( event) {
+	switch (event) {
 	case LM_CONNECT_RESPONSE:
-		ASSERT( skb != NULL, return;);
+		del_timer(&self->watchdog_timer);
 
 		/* 
 		 *  Bind this LSAP to the IrLAP link where the connect was
@@ -457,25 +511,27 @@
 		lsap = hashbin_remove(irlmp->unconnected_lsaps, (int) self, 
 				      NULL);
 
-		ASSERT(lsap == self, return;);
+		ASSERT(lsap == self, return -1;);		
+		ASSERT(self->lap != NULL, return -1;);
+		ASSERT(self->lap->lsaps != NULL, return -1;);
 		
-		ASSERT(self->lap != NULL, return;);
-		ASSERT(self->lap->lsaps != NULL, return;);
-		
-		hashbin_insert(self->lap->lsaps, (QUEUE *) self, (int) self, 
+		hashbin_insert(self->lap->lsaps, (queue_t *) self, (int) self, 
 			       NULL);
 
+		self->connected = TRUE;	
+		irlmp_next_lsap_state(self, LSAP_DATA_TRANSFER_READY);
+
 		irlmp_send_lcf_pdu(self->lap, self->dlsap_sel, 
 				   self->slsap_sel, CONNECT_CNF, skb);
-
-		del_timer(&self->watchdog_timer);
-
-		irlmp_next_lsap_state(self, LSAP_DATA_TRANSFER_READY);
 		break;
 	default:
-		DEBUG( 4, __FUNCTION__ "(), Unknown event\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %s\n",
+			   irlmp_event[event]);
+		if (skb)
+ 			dev_kfree_skb(skb);
 		break;
 	}
+	return ret;
 }
 
 /*
@@ -484,37 +540,47 @@
  *    CONNECT_PEND
  *
  */
-static void irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event,
-				     struct sk_buff *skb) 
+static int irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event,
+				    struct sk_buff *skb) 
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	int ret = 0;
+
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
 
-	switch( event) {
+	switch (event) {
 	case LM_CONNECT_REQUEST:
 		/* Keep state */
 		break;
 	case LM_CONNECT_RESPONSE:
-		DEBUG(0, __FUNCTION__ "(), LM_CONNECT_RESPONSE, "
-		      "no indication issued yet\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), LM_CONNECT_RESPONSE, "
+			   "no indication issued yet\n");
 		/* Keep state */
 		break;
 	case LM_DISCONNECT_REQUEST:
-		DEBUG(0, __FUNCTION__ "(), LM_DISCONNECT_REQUEST, "
-		      "not yet bound to IrLAP connection\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), LM_DISCONNECT_REQUEST, "
+			   "not yet bound to IrLAP connection\n");
 		/* Keep state */
 		break;
 	case LM_LAP_CONNECT_CONFIRM:
-		DEBUG(4, __FUNCTION__ "(), LS_CONNECT_CONFIRM\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), LS_CONNECT_CONFIRM\n");
 		irlmp_next_lsap_state(self, LSAP_CONNECT);
+
+		skb = self->conn_skb;
+		self->conn_skb = NULL;
+
 		irlmp_connect_indication(self, skb);
 		break;
 	default:
-		DEBUG( 4, __FUNCTION__ "Unknown event %d\n", event);
+		IRDA_DEBUG(0, __FUNCTION__ "Unknown event %s\n", 
+			   irlmp_event[event]);
+		if (skb)
+ 			dev_kfree_skb(skb);
 		break;	
-	}	
+	}
+	return ret;
 }
 
 /*
@@ -523,56 +589,52 @@
  *    DATA_TRANSFER_READY
  *
  */
-static void irlmp_state_dtr(struct lsap_cb *self, IRLMP_EVENT event, 
-			    struct sk_buff *skb) 
+static int irlmp_state_dtr(struct lsap_cb *self, IRLMP_EVENT event, 
+			   struct sk_buff *skb) 
 {
 	LM_REASON reason;
+	int ret = 0;
 
- 	DEBUG(4, __FUNCTION__ "()\n");
+ 	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
-	ASSERT(self->lap != NULL, return;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+	ASSERT(self->lap != NULL, return -1;);
 
 	switch (event) {
 	case LM_DATA_REQUEST: /* Optimize for the common case */
 		irlmp_send_data_pdu(self->lap, self->dlsap_sel, 
 				    self->slsap_sel, FALSE, skb);
-		/* irlmp_next_lsap_state( DATA_TRANSFER_READY, info->handle);*/
 		break;
 	case LM_DATA_INDICATION: /* Optimize for the common case */
 		irlmp_data_indication(self, skb); 
-		/* irlmp_next_lsap_state( DATA_TRANSFER_READY, info->handle);*/
 		break;
 	case LM_UDATA_REQUEST:
-		ASSERT(skb != NULL, return;);
+		ASSERT(skb != NULL, return -1;);
 		irlmp_send_data_pdu(self->lap, self->dlsap_sel, 
 				    self->slsap_sel, TRUE, skb);
 		break;
 	case LM_UDATA_INDICATION:
 		irlmp_udata_indication(self, skb); 
-		/* irlmp_next_lsap_state( DATA_TRANSFER_READY, info->handle);*/
 		break;
 	case LM_CONNECT_REQUEST:
-		DEBUG(0, __FUNCTION__ "(), LM_CONNECT_REQUEST, "
-		      "error, LSAP already connected\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), LM_CONNECT_REQUEST, "
+			   "error, LSAP already connected\n");
 		/* Keep state */
 		break;
 	case LM_CONNECT_RESPONSE:
-		DEBUG(0, __FUNCTION__ "(), LM_CONNECT_RESPONSE, " 
-		      "error, LSAP allready connected\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), LM_CONNECT_RESPONSE, " 
+			   "error, LSAP allready connected\n");
 		/* Keep state */
 		break;
 	case LM_DISCONNECT_REQUEST:
-		ASSERT(skb != NULL, return;);
-
-		irlmp_send_lcf_pdu(self->lap, self->dlsap_sel, 
-				   self->slsap_sel, DISCONNECT, skb);
+		irlmp_send_lcf_pdu(self->lap, self->dlsap_sel, self->slsap_sel,
+				   DISCONNECT, skb);
 		irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
 		
 		/* Try to close the LAP connection if its still there */
 		if (self->lap) {
-			DEBUG(4, __FUNCTION__ "(), trying to close IrLAP\n");
+			IRDA_DEBUG(4, __FUNCTION__ "(), trying to close IrLAP\n");
 			irlmp_do_lap_event(self->lap, 
 					   LM_LAP_DISCONNECT_REQUEST, 
 					   NULL);
@@ -588,23 +650,27 @@
 	case LM_DISCONNECT_INDICATION:
 		irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
 			
-		ASSERT(self->lap != NULL, return;);
-		ASSERT(self->lap->magic == LMP_LAP_MAGIC, return;);
+		ASSERT(self->lap != NULL, return -1;);
+		ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
 	
-		ASSERT(skb != NULL, return;);
-		ASSERT(skb->len > 3, return;);
+		ASSERT(skb != NULL, return -1;);
+		ASSERT(skb->len > 3, return -1;);
 		reason = skb->data[3];
 
 		 /* Try to close the LAP connection */
-		DEBUG(4, __FUNCTION__ "(), trying to close IrLAP\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), trying to close IrLAP\n");
 		irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
 
 		irlmp_disconnect_indication(self, reason, skb);
 		break;
 	default:
-		DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %s\n", 
+			   irlmp_event[event]);
+		if (skb)
+ 			dev_kfree_skb(skb);
 		break;	
-	}	
+	}
+	return ret;
 }
 
 /*
@@ -614,54 +680,70 @@
  *    An LSAP connection request has been transmitted to the peer
  *    LSAP-Connection Control FSM and we are awaiting reply.
  */
-static void irlmp_state_setup( struct lsap_cb *self, IRLMP_EVENT event, 
-			       struct sk_buff *skb) 
+static int irlmp_state_setup(struct lsap_cb *self, IRLMP_EVENT event, 
+			     struct sk_buff *skb) 
 {
 	LM_REASON reason;
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+	int ret = 0;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
 
-	switch( event) {
-	case LM_CONNECT_CONFIRM:
-		ASSERT( skb != NULL, return;);
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
-		irlmp_next_lsap_state( self, LSAP_DATA_TRANSFER_READY);
+	switch (event) {
+	case LM_CONNECT_CONFIRM:
+		irlmp_next_lsap_state(self, LSAP_DATA_TRANSFER_READY);
 
-		del_timer( &self->watchdog_timer);
+		del_timer(&self->watchdog_timer);
 		
-		irlmp_connect_confirm( self, skb);
+		irlmp_connect_confirm(self, skb);
 		break;
 	case LM_DISCONNECT_INDICATION:
-		DEBUG(0, __FUNCTION__ "(), this should never happen!!\n");
+		irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
+			
+		ASSERT(self->lap != NULL, return -1;);
+		ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
+	
+		ASSERT(skb != NULL, return -1;);
+		ASSERT(skb->len > 3, return -1;);
+		reason = skb->data[3];
+
+		 /* Try to close the LAP connection */
+		IRDA_DEBUG(4, __FUNCTION__ "(), trying to close IrLAP\n");
+		irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
+
+		irlmp_disconnect_indication(self, reason, skb);
 		break;
 	case LM_LAP_DISCONNECT_INDICATION:
 		irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
 
 		del_timer(&self->watchdog_timer);
 
-		ASSERT(self->lap != NULL, return;);
-		ASSERT(self->lap->magic == LMP_LAP_MAGIC, return;);
+		ASSERT(self->lap != NULL, return -1;);
+		ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
 		
 		reason = irlmp_convert_lap_reason(self->lap->reason);
 
 		irlmp_disconnect_indication(self, reason, skb);
 		break;
 	case LM_WATCHDOG_TIMEOUT:
-		DEBUG( 0, __FUNCTION__ "() WATCHDOG_TIMEOUT!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "() WATCHDOG_TIMEOUT!\n");
 		
-		ASSERT( self->lap != NULL, return;);
-		irlmp_do_lap_event( self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
-		irlmp_next_lsap_state( self, LSAP_DISCONNECTED);
+		ASSERT(self->lap != NULL, return -1;);
+		irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
+		irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
 		
-		irlmp_disconnect_indication( self, LM_CONNECT_FAILURE, NULL);
+		irlmp_disconnect_indication(self, LM_CONNECT_FAILURE, NULL);
 		break;
 	default:
-		DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %s\n", 
+			   irlmp_event[event]);
+		if (skb)
+ 			dev_kfree_skb(skb);
 		break;	
 	}
+	return ret;
 }
 
 /*
@@ -672,57 +754,67 @@
  *    LAP FSM to set up the underlying IrLAP connection, and we
  *    are awaiting confirm.
  */
-static void irlmp_state_setup_pend( struct lsap_cb *self, IRLMP_EVENT event, 
-				    struct sk_buff *skb) 
+static int irlmp_state_setup_pend(struct lsap_cb *self, IRLMP_EVENT event, 
+				  struct sk_buff *skb) 
 {
 	LM_REASON reason;
+	int ret = 0;
 
-	DEBUG( 4, __FUNCTION__ "()\n"); 
+	IRDA_DEBUG(4, __FUNCTION__ "()\n"); 
 
-	ASSERT( self != NULL, return;);
-	ASSERT( irlmp != NULL, return;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(irlmp != NULL, return -1;);
 
-	switch( event) {
+	switch (event) {
 	case LM_LAP_CONNECT_CONFIRM:
-		irlmp_send_lcf_pdu( self->lap, self->dlsap_sel, 
-				    self->slsap_sel, CONNECT_CMD, 
-				    self->tmp_skb);
-		irlmp_next_lsap_state( self, LSAP_SETUP);
+		ASSERT(self->conn_skb != NULL, return -1;);
+
+		skb = self->conn_skb;
+		self->conn_skb = NULL;
+
+		irlmp_send_lcf_pdu(self->lap, self->dlsap_sel, 
+				   self->slsap_sel, CONNECT_CMD, skb);
+
+		irlmp_next_lsap_state(self, LSAP_SETUP);
 		break;
 	case LM_WATCHDOG_TIMEOUT:
-		DEBUG( 0, __FUNCTION__ "() WATCHDOG_TIMEOUT!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "() WATCHDOG_TIMEOUT!\n");
 
-		ASSERT( self->lap != NULL, return;);
+		ASSERT(self->lap != NULL, return -1;);
 		irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
-		irlmp_next_lsap_state( self, LSAP_DISCONNECTED);
+		irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
 
-		irlmp_disconnect_indication( self, LM_CONNECT_FAILURE, NULL);
+		irlmp_disconnect_indication(self, LM_CONNECT_FAILURE, NULL);
 		break;
 	case LM_LAP_DISCONNECT_INDICATION: /* LS_Disconnect.indication */
 		del_timer( &self->watchdog_timer);
 
-		irlmp_next_lsap_state( self, LSAP_DISCONNECTED);
+		irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
 		
-		reason = irlmp_convert_lap_reason( self->lap->reason);
+		reason = irlmp_convert_lap_reason(self->lap->reason);
 		
-		irlmp_disconnect_indication( self, reason, NULL);
+		irlmp_disconnect_indication(self, reason, NULL);
 		break;
 	default:
-		DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %s\n", 
+			   irlmp_event[event]);
+		if (skb)
+ 			dev_kfree_skb(skb);
 		break;	
 	}
+	return ret;
 }
 
-void irlmp_next_lap_state( struct lap_cb *self, IRLMP_STATE state) 
+void irlmp_next_lap_state(struct lap_cb *self, IRLMP_STATE state) 
 {
-	DEBUG( 4, __FUNCTION__ "(), LMP LAP = %s\n", irlmp_state[state]);
+	IRDA_DEBUG(4, __FUNCTION__ "(), LMP LAP = %s\n", irlmp_state[state]);
 	self->lap_state = state;
 }
 
-void irlmp_next_lsap_state( struct lsap_cb *self, LSAP_STATE state) 
+void irlmp_next_lsap_state(struct lsap_cb *self, LSAP_STATE state) 
 {
-	ASSERT( self != NULL, return;);
+	ASSERT(self != NULL, return;);
 
-	DEBUG( 4, __FUNCTION__ "(), LMP LSAP = %s\n", irlsap_state[state]);
+	IRDA_DEBUG(4, __FUNCTION__ "(), LMP LSAP = %s\n", irlsap_state[state]);
 	self->lsap_state = state;
 }
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irlmp_frame.c linux.15p9/net/irda/irlmp_frame.c
--- linux.vanilla/net/irda/irlmp_frame.c	Sat Aug 14 02:26:52 1999
+++ linux.15p9/net/irda/irlmp_frame.c	Tue Jan 18 01:08:19 2000
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Aug 19 02:09:59 1997
- * Modified at:   Mon May 31 09:53:16 1999
+ * Modified at:   Mon Dec 13 13:41:12 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>
@@ -40,18 +40,14 @@
 inline void irlmp_send_data_pdu(struct lap_cb *self, __u8 dlsap, __u8 slsap,
 				int expedited, struct sk_buff *skb)
 {
-	__u8 *frame;
-
-	frame = skb->data;
-
-	frame[0] = dlsap;
-	frame[1] = slsap;
+	skb->data[0] = dlsap;
+	skb->data[1] = slsap;
 
 	if (expedited) {
-		DEBUG( 4, __FUNCTION__ "(), sending expedited data\n");
-		irlap_data_request( self->irlap, skb, FALSE);
+		IRDA_DEBUG(4, __FUNCTION__ "(), sending expedited data\n");
+		irlap_data_request(self->irlap, skb, TRUE);
 	} else
-		irlap_data_request( self->irlap, skb, TRUE);
+		irlap_data_request(self->irlap, skb, FALSE);
 }
 
 /*
@@ -64,8 +60,8 @@
 {
 	__u8 *frame;
 	
-	DEBUG(4, __FUNCTION__ "()\n");
-	
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LMP_LAP_MAGIC, return;);
 	ASSERT(skb != NULL, return;);
@@ -82,8 +78,7 @@
 	else
 		frame[3] = 0x00; /* rsvd */
 
-	ASSERT(self->irlap != NULL, return;);
-	irlap_data_request(self->irlap, skb, TRUE);
+	irlap_data_request(self->irlap, skb, FALSE);
 }
 
 /*
@@ -92,14 +87,16 @@
  *    Used by IrLAP to pass received data frames to IrLMP layer
  *
  */
-void irlmp_link_data_indication(struct lap_cb *self, int reliable, 
-			        struct sk_buff *skb)
+void irlmp_link_data_indication(struct lap_cb *self, struct sk_buff *skb, 
+				int unreliable)
 {
 	struct lsap_cb *lsap;
 	__u8   slsap_sel;   /* Source (this) LSAP address */
 	__u8   dlsap_sel;   /* Destination LSAP address */
 	__u8   *fp;
 	
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LMP_LAP_MAGIC, return;);
 	ASSERT(skb->len > 2, return;);
@@ -111,15 +108,16 @@
 	 *  destination LSAP of received frame is source LSAP in our view
 	 */
 	slsap_sel = fp[0] & LSAP_MASK; 
-	dlsap_sel = fp[1];
+	dlsap_sel = fp[1];	
 
 	/*
 	 *  Check if this is an incoming connection, since we must deal with
 	 *  it in a different way than other established connections.
 	 */
 	if ((fp[0] & CONTROL_BIT) && (fp[2] == CONNECT_CMD)) {
-		DEBUG(3,"Incoming connection, source LSAP=%d, dest LSAP=%d\n",
-		      slsap_sel, dlsap_sel);
+		IRDA_DEBUG(3, __FUNCTION__ "(), incoming connection, "
+			   "source LSAP=%d, dest LSAP=%d\n",
+			   slsap_sel, dlsap_sel);
 		
 		/* Try to find LSAP among the unconnected LSAPs */
 		lsap = irlmp_find_lsap(self, dlsap_sel, slsap_sel, CONNECT_CMD,
@@ -134,15 +132,15 @@
 				       self->lsaps);
 	
 	if (lsap == NULL) {
-		DEBUG(2, "IrLMP, Sorry, no LSAP for received frame!\n");
-		DEBUG(2, __FUNCTION__ 
+		IRDA_DEBUG(2, "IrLMP, Sorry, no LSAP for received frame!\n");
+		IRDA_DEBUG(2, __FUNCTION__ 
 		      "(), slsap_sel = %02x, dlsap_sel = %02x\n", slsap_sel, 
 		      dlsap_sel);
 		if (fp[0] & CONTROL_BIT) {
-			DEBUG(2, __FUNCTION__ 
+			IRDA_DEBUG(2, __FUNCTION__ 
 			      "(), received control frame %02x\n", fp[2]);
 		} else {
-			DEBUG(2, __FUNCTION__ "(), received data frame\n");
+			IRDA_DEBUG(2, __FUNCTION__ "(), received data frame\n");
 		}
 		dev_kfree_skb(skb);
 		return;
@@ -152,7 +150,7 @@
 	 *  Check if we received a control frame? 
 	 */
 	if (fp[0] & CONTROL_BIT) {
-		switch(fp[2]) {
+		switch (fp[2]) {
 		case CONNECT_CMD:
 			lsap->lap = self;
 			irlmp_do_lsap_event(lsap, LM_CONNECT_INDICATION, skb);
@@ -161,37 +159,109 @@
 			irlmp_do_lsap_event(lsap, LM_CONNECT_CONFIRM, skb);
 			break;
 		case DISCONNECT:
-			DEBUG( 4, __FUNCTION__ "(), Disconnect indication!\n");
+			IRDA_DEBUG(4, __FUNCTION__ 
+				   "(), Disconnect indication!\n");
 			irlmp_do_lsap_event(lsap, LM_DISCONNECT_INDICATION, 
 					    skb);
 			break;
 		case ACCESSMODE_CMD:
-			DEBUG( 0, "Access mode cmd not implemented!\n");
+			IRDA_DEBUG(0, "Access mode cmd not implemented!\n");
+			dev_kfree_skb(skb);
 			break;
 		case ACCESSMODE_CNF:
-			DEBUG( 0, "Access mode cnf not implemented!\n");
+			IRDA_DEBUG(0, "Access mode cnf not implemented!\n");
+			dev_kfree_skb(skb);
 			break;
 		default:
-			DEBUG( 0, __FUNCTION__ 
-			       "(), Unknown control frame %02x\n", fp[2]);
+			IRDA_DEBUG(0, __FUNCTION__ 
+				   "(), Unknown control frame %02x\n", fp[2]);
+			dev_kfree_skb(skb);
 			break;
 		}
-	} else if (reliable == LAP_RELIABLE) {
+	} else if (unreliable) {
 		/* Optimize and bypass the state machine if possible */
 		if (lsap->lsap_state == LSAP_DATA_TRANSFER_READY)
-			irlmp_data_indication(lsap, skb);
+			irlmp_udata_indication(lsap, skb);
 		else
-			irlmp_do_lsap_event(lsap, LM_DATA_INDICATION, skb);
-	} else if (reliable == LAP_UNRELIABLE) {
+			irlmp_do_lsap_event(lsap, LM_UDATA_INDICATION, skb);
+	} else {	
 		/* Optimize and bypass the state machine if possible */
 		if (lsap->lsap_state == LSAP_DATA_TRANSFER_READY)
 			irlmp_data_indication(lsap, skb);
 		else
-			irlmp_do_lsap_event(lsap, LM_UDATA_INDICATION, skb);
+			irlmp_do_lsap_event(lsap, LM_DATA_INDICATION, skb);
 	}
 }
 
 /*
+ * Function irlmp_link_unitdata_indication (self, skb)
+ *
+ *    
+ *
+ */
+#ifdef CONFIG_IRDA_ULTRA
+void irlmp_link_unitdata_indication(struct lap_cb *self, struct sk_buff *skb)
+{
+	struct lsap_cb *lsap;
+	__u8   slsap_sel;   /* Source (this) LSAP address */
+	__u8   dlsap_sel;   /* Destination LSAP address */
+	__u8   pid;         /* Protocol identifier */
+	__u8   *fp;
+	
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+	ASSERT(skb->len > 2, return;);
+
+	fp = skb->data;
+
+	/*
+	 *  The next statements may be confusing, but we do this so that 
+	 *  destination LSAP of received frame is source LSAP in our view
+	 */
+	slsap_sel = fp[0] & LSAP_MASK; 
+	dlsap_sel = fp[1];
+	pid       = fp[2];
+	
+	if (pid & 0x80) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), extension in PID not supp!\n");
+		dev_kfree_skb(skb);
+
+		return;
+	}
+
+	/* Check if frame is addressed to the connectionless LSAP */
+	if ((slsap_sel != LSAP_CONNLESS) || (dlsap_sel != LSAP_CONNLESS)) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), dropping frame!\n");
+		dev_kfree_skb(skb);
+		
+		return;
+	}
+	
+	lsap = (struct lsap_cb *) hashbin_get_first(irlmp->unconnected_lsaps);
+	while (lsap != NULL) {
+		/*
+		 *  Check if source LSAP and dest LSAP selectors and PID match.
+		 */
+		if ((lsap->slsap_sel == slsap_sel) && 
+		    (lsap->dlsap_sel == dlsap_sel) && 
+		    (lsap->pid == pid)) 
+		{			
+			break;
+		}
+		lsap = (struct lsap_cb *) hashbin_get_next(irlmp->unconnected_lsaps);
+	}
+	if (lsap)
+		irlmp_connless_data_indication(lsap, skb);
+	else {
+		IRDA_DEBUG(0, __FUNCTION__ "(), found no matching LSAP!\n");
+		dev_kfree_skb(skb);
+	}
+}
+#endif /* CONFIG_IRDA_ULTRA */
+
+/*
  * Function irlmp_link_disconnect_indication (reason, userdata)
  *
  *    IrLAP has disconnected 
@@ -202,7 +272,7 @@
 				      LAP_REASON reason, 
 				      struct sk_buff *userdata)
 {
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	ASSERT(lap != NULL, return;);
 	ASSERT(lap->magic == LMP_LAP_MAGIC, return;);
@@ -211,7 +281,9 @@
 	lap->daddr = DEV_ADDR_ANY;
 
         /* FIXME: must do something with the userdata if any */
-
+	if (userdata)
+		dev_kfree_skb(userdata);
+	
 	/*
 	 *  Inform station state machine
 	 */
@@ -228,7 +300,7 @@
 				   __u32 daddr, struct qos_info *qos,
 				   struct sk_buff *skb) 
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	/* Copy QoS settings for this session */
 	self->qos = qos;
@@ -249,12 +321,16 @@
 void irlmp_link_connect_confirm(struct lap_cb *self, struct qos_info *qos, 
 				struct sk_buff *userdata)
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LMP_LAP_MAGIC, return;);
 	ASSERT(qos != NULL, return;);
 
+	/* Don't need use the userdata for now */
+	if (userdata)
+		dev_kfree_skb(userdata);
+
 	/* Copy QoS settings for this session */
 	self->qos = qos;
 
@@ -274,9 +350,10 @@
 	ASSERT(self->magic == LMP_LAP_MAGIC, return;);
 
 	irlmp_add_discovery(irlmp->cachelog, discovery);
+	
+#if 0   /* This will just cause a lot of connection collisions */
 
 	/* Just handle it the same way as a discovery confirm */
-#if 0
 	irlmp_do_lap_event(self, LM_LAP_DISCOVERY_CONFIRM, NULL);
 #endif
 }
@@ -291,7 +368,7 @@
  */
 void irlmp_link_discovery_confirm(struct lap_cb *self, hashbin_t *log)
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LMP_LAP_MAGIC, return;);
@@ -373,5 +450,3 @@
 	/* Sorry not found! */
 	return NULL;
 }
-
-
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irlpt/Config.in linux.15p9/net/irda/irlpt/Config.in
--- linux.vanilla/net/irda/irlpt/Config.in	Wed Jan 20 19:05:33 1999
+++ linux.15p9/net/irda/irlpt/Config.in	Thu Jan  1 01:00:00 1970
@@ -1,7 +0,0 @@
-
-dep_tristate 'IrLPT protocol' CONFIG_IRLPT $CONFIG_IRDA
-
-if [ "$CONFIG_IRLPT" != "n" ]; then
-  dep_tristate '   IrLPT client support' CONFIG_IRLPT_CLIENT $CONFIG_IRLPT
-  dep_tristate '   IrLPT server support' CONFIG_IRLPT_SERVER $CONFIG_IRLPT
-fi
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irlpt/Makefile linux.15p9/net/irda/irlpt/Makefile
--- linux.vanilla/net/irda/irlpt/Makefile	Wed Jan 20 19:05:33 1999
+++ linux.15p9/net/irda/irlpt/Makefile	Thu Jan  1 01:00:00 1970
@@ -1,48 +0,0 @@
-#
-# Makefile for the Linux IrDA IrLPT protocol layer.
-#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-# Note 2! The CFLAGS definition is now in the main makefile...
-
-MOD_LIST_NAME := IRDA_MODULES
-O_TARGET := irlpt.o
-O_OBJS	 := irlpt_common.o
-M_OBJS   := $(O_TARGET)
-MI_OBJS  :=
-
-OX_OBJS  += 
-
-ifeq ($(CONFIG_IRLPT_CLIENT),y)
-O_OBJS += irlpt_cli.o irlpt_cli_fsm.o
-else
-  ifeq ($(CONFIG_IRLPT_CLIENT),m)
-  M_OBJS += irlpt_client.o
-  endif
-endif
-
-ifeq ($(CONFIG_IRLPT_SERVER),y)
-O_OBJS += irlpt_srvr.o irlpt_srvr_fsm.o
-else
-  ifeq ($(CONFIG_IRLPT_SERVER),m)
-  M_OBJS += irlpt_server.o
-  endif
-endif
-
-# Special rule to build the composite modules
-ifeq ($(CONFIG_IRLPT_CLIENT),m)
-irlpt_client.o: irlpt_cli.o irlpt_cli_fsm.o
-	$(LD) $(LD_RFLAG) -r -o $@ irlpt_cli.o irlpt_cli_fsm.o
-endif
-ifeq ($(CONFIG_IRLPT_SERVER),m)
-irlpt_server.o: irlpt_srvr.o irlpt_srvr_fsm.o
-	$(LD) $(LD_RFLAG) -r -o $@ irlpt_srvr.o irlpt_srvr_fsm.o
-endif
-
-include $(TOPDIR)/Rules.make
-
-tar:
-	tar -cvf /dev/f1 .
-
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irlpt/irlpt_cli.c linux.15p9/net/irda/irlpt/irlpt_cli.c
--- linux.vanilla/net/irda/irlpt/irlpt_cli.c	Sat Aug 14 02:26:52 1999
+++ linux.15p9/net/irda/irlpt/irlpt_cli.c	Thu Jan  1 01:00:00 1970
@@ -1,660 +0,0 @@
-/*********************************************************************
- *
- * Filename:      irlpt_cli.c
- * Version:       
- * Description:   
- * Status:        Experimental.
- * Author:        Thomas Davis, <ratbert@radiks.net>
- * Created at:    Sat Feb 21 18:54:38 1998
- * Modified at:   Sun Mar  8 23:44:19 1998
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * Sources:	  irlan.c
- *
- *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>,
- *     Copyright (c) 1998, Dag Brattli,  <dagb@cs.uit.no>
- *     All Rights Reserved.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     I, Thomas Davis, provide no warranty for any of this software.
- *     This material is provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#include <net/irda/irlap.h>
-#include <net/irda/irttp.h>
-#include <net/irda/irlmp.h>
-#include <net/irda/irias_object.h>
-#include <net/irda/iriap.h>
-#include <net/irda/irlpt_common.h>
-#include <net/irda/irlpt_cli.h>
-#include <net/irda/irlpt_cli_fsm.h>
-#include <net/irda/timer.h>
-#include <net/irda/irda.h>
-
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/module.h>
-
-#include <asm/uaccess.h>
-#include <linux/miscdevice.h>
-#include <linux/proc_fs.h>
-
-int irlpt_client_init(void);
-static void irlpt_client_close(struct irlpt_cb *self);
-
-static void irlpt_client_discovery_indication(discovery_t *);
-
-static void irlpt_client_connect_confirm(void *instance, void *sap, 
-					 struct qos_info *qos, 
-					 __u32 max_seg_size, 
-					 __u8 max_header_size,
-					 struct sk_buff *skb);
-static void irlpt_client_disconnect_indication(void *instance, void *sap, 
-					       LM_REASON reason,
-					       struct sk_buff *userdata);
-static void irlpt_client_expired(unsigned long data);
-
-#if 0
-static char *rcsid = "$Id: irlpt_client.c,v 1.10 1998/11/10 22:50:57 dagb Exp $";
-#endif
-static char *version = "IrLPT client, v2 (Thomas Davis)";
-
-static __u32 ckey; /* IrLMP client handle */
-
-struct file_operations client_fops = {
-	irlpt_seek,    /* seek */
-	NULL,          /* read_irlpt (server) */
-	irlpt_write,   /* write */
-	NULL,	       /* readdir */
-	NULL,          /* poll */
-	NULL,	       /* ioctl */
-	NULL,	       /* mmap */
-	irlpt_open,    /* open */
-	NULL,          /* flush */
-	irlpt_close,   /* release */
-	NULL,          /* fsync */
-	NULL,          /* fasync */
-	NULL,          /* check_media_change */
-	NULL,          /* revalidate */
-	NULL,          /* lock */
-};
-
-int irlpt_client_debug = 4;
-
-extern char *irlptstate[];
-
-#ifdef CONFIG_PROC_FS
-
-/*
- * Function client_proc_read (buf, start, offset, len, unused)
- *
- */
-static int irlpt_client_proc_read( char *buf, char **start, off_t offset, 
-				   int len, int unused)
-{
-	struct irlpt_cb *self;
-	int index;
-
-	len = sprintf(buf, "%s\n\n", version);
-
-	self = (struct irlpt_cb *) hashbin_get_first( irlpt_clients);
-	while( self) {
-	        ASSERT( self != NULL, return len;);
-          	ASSERT( self->magic == IRLPT_MAGIC, return len;);
-		if (self->in_use == FALSE) {
-		        break;
-		}
-
-		len += sprintf(buf+len, "ifname: %s\n", self->ifname);
-		len += sprintf(buf+len, "minor: %d\n", self->ir_dev.minor);
-
-		switch ( self->servicetype) {
-		case IRLPT_UNKNOWN:
-			index = 0;
-			break;
-		case IRLPT_THREE_WIRE_RAW:
-			index = 1;
-			break;
-		case IRLPT_THREE_WIRE:
-			index = 2;
-			break;
-		case IRLPT_NINE_WIRE:
-			index = 3;
-			break;
-		case IRLPT_CENTRONICS:
-			index = 4;
-			break;
-		case IRLPT_SERVER_MODE:
-			index = 5;
-			break;
-		default:
-			index = 0;
-			break;
-		}
-		
-		len += sprintf(buf+len, "service_type: %s, port type: %s\n", 
-			       irlpt_service_type[index],
-			       irlpt_port_type[ self->porttype]);
-
-		len += sprintf(buf+len, "saddr: 0x%08x, daddr: 0x%08x\n", 
-			       self->saddr, self->daddr);
-		len += sprintf(buf+len, 
-			       "retries: %d, count: %d, queued packets: %d\n", 
-			       self->open_retries,
-			       self->count, self->pkt_count);
-		len += sprintf(buf+len, "slsap: %d, dlsap: %d\n", 
-			       self->slsap_sel, self->dlsap_sel);
-		len += sprintf(buf+len, "fsm state: %s\n", 
-			       irlpt_client_fsm_state[self->state]);
-		len += sprintf(buf+len, "\n\n");
-		
-		self = (struct irlpt_cb *) hashbin_get_next( irlpt_clients);
-	}
-	
-	return len;
-}
-
-extern struct proc_dir_entry *proc_irda;
-
-#endif /* CONFIG_PROC_FS */
-
-/*
- * Function irlpt_client_init (dev)
- *
- *   Initializes the irlpt control structure
- *
- */
-__initfunc(int irlpt_client_init(void))
-{
-	__u16 hints;
-	
-	DEBUG( irlpt_client_debug, "--> "__FUNCTION__ "\n");
-
-	printk( KERN_INFO "%s\n", version);
-
-	irlpt_clients = hashbin_new( HB_LOCAL); 
-	if ( irlpt_clients == NULL) {
-		printk( KERN_WARNING 
-			"IrLPT client: Can't allocate hashbin!\n");
-		return -ENOMEM;
-	}
-	hints = irlmp_service_to_hint(S_PRINTER);
-	ckey = irlmp_register_client(hints, irlpt_client_discovery_indication,
-				     NULL);
-
-#ifdef CONFIG_PROC_FS
-	create_proc_entry("irlpt_client", 0, proc_irda)->get_info
-		= irlpt_client_proc_read;
-#endif /* CONFIG_PROC_FS */
-
-	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
-
-	return 0;
-}
-
-
-#ifdef MODULE
-/*
- * Function irlpt_client_cleanup (void)
- *
- */
-static void irlpt_client_cleanup(void)
-{
-	DEBUG( irlpt_client_debug, "--> "__FUNCTION__ "\n");
-
-	irlmp_unregister_client(ckey);
-
-	/*
-	 *  Delete hashbin and close all irlpt client instances in it
-	 */
-	hashbin_delete( irlpt_clients, (FREE_FUNC) irlpt_client_close);
-
-#ifdef CONFIG_PROC_FS
-	remove_proc_entry("irlpt_client", proc_irda);
-#endif
-	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
-}
-#endif /* MODULE */
-
-
-/*
- * Function irlpt_client_open (void)
- *
- */
-static struct irlpt_cb *irlpt_client_open( __u32 daddr)
-{
-	struct irmanager_event mgr_event;
-	struct irlpt_cb *self;
-
-	DEBUG( irlpt_client_debug, "--> "__FUNCTION__ "\n");
-
-	self = (struct irlpt_cb *) hashbin_find(irlpt_clients, daddr, NULL);
-
-	if (self == NULL) {
-	        self = kmalloc(sizeof(struct irlpt_cb), GFP_ATOMIC);
-		if (self == NULL)
-		        return NULL;
-
-		memset(self, 0, sizeof(struct irlpt_cb));
-
-		ASSERT( self != NULL, return NULL;);
-
-		sprintf(self->ifname, "irlpt%d", 
-			hashbin_get_size(irlpt_clients));
-
-		hashbin_insert( irlpt_clients, (QUEUE *) self, daddr, NULL);
-	}
-
-	self->ir_dev.minor = MISC_DYNAMIC_MINOR;
-	self->ir_dev.name = self->ifname;
-	self->ir_dev.fops = &client_fops;
-
-	misc_register(&self->ir_dev);
-
-	self->magic = IRLPT_MAGIC;
-	self->in_use = TRUE;
-	self->servicetype = IRLPT_THREE_WIRE_RAW;
-	self->porttype = IRLPT_SERIAL;
-	self->do_event = irlpt_client_do_event;
-
-	skb_queue_head_init(&self->rx_queue);
-
-	irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
-
-	/* Tell irmanager to create /dev/irlpt<X> */
-	mgr_event.event = EVENT_IRLPT_START;
-	sprintf(mgr_event.devname, "%s", self->ifname);
-	irmanager_notify(&mgr_event);
-
-	MOD_INC_USE_COUNT;
-
-	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
-
-	return self;
-}
-
-/*
- * Function irlpt_client_close (self)
- *
- *    This function closes and marks the IrLPT instance as not in use.
- */
-static void irlpt_client_close( struct irlpt_cb *self)
-{
-	struct irmanager_event mgr_event;
-	struct sk_buff *skb;
-
-	DEBUG( irlpt_client_debug, "--> " __FUNCTION__ "\n");
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLPT_MAGIC, return;);
-
-	/* Tell irmanager to remove /dev/irlpt<X> */
-	mgr_event.event = EVENT_IRLPT_STOP;
- 	sprintf(mgr_event.devname, "%s", self->ifname);
- 	irmanager_notify(&mgr_event);
-
-	while (( skb = skb_dequeue(&self->rx_queue)) != NULL) {
-		DEBUG(irlpt_client_debug, 
-		      __FUNCTION__ ": freeing SKB\n");
-                dev_kfree_skb( skb);
-	}
-
-	misc_deregister(&self->ir_dev);
-	self->in_use = FALSE;
-
-	MOD_DEC_USE_COUNT;
-
-	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
-}
-
-/*
- * Function irlpt_discovery_indication (daddr)
- *
- *    Remote device discovered, try query the remote IAS to see which
- *    device it is, and which services it has.
- *
- */
-static void irlpt_client_discovery_indication(discovery_t *discovery)
-{
-	struct irlpt_info info;
-	struct irlpt_cb *self;
-	__u32 daddr; /* address of remote printer */
-	__u32 saddr; /* address of local link where it was discovered */
-
-	DEBUG( irlpt_client_debug, "--> " __FUNCTION__ "\n");
-
-	ASSERT( irlpt_clients != NULL, return;);
-	ASSERT( discovery != NULL, return;);
-
-	daddr = info.daddr = discovery->daddr;
-	saddr = info.saddr = discovery->saddr;
-
-	/*
-	 *  Check if an instance is already dealing with this device
-	 *  (daddr)
-	 */
-	self = (struct irlpt_cb *) hashbin_find( irlpt_clients, daddr, NULL);
-      	if (self == NULL || self->in_use == FALSE) {
-	        DEBUG( irlpt_client_debug, __FUNCTION__ 
-		       ": daddr 0x%08x not found or was closed\n", daddr);
-	        /*
-		 * We have no instance for daddr, so time to start a new 
-		 * instance. First we must find a free entry in master array
-		 */
-		if (( self = irlpt_client_open( daddr)) == NULL) {
-			DEBUG(irlpt_client_debug, __FUNCTION__ 
-			      ": failed!\n");
-			return;
-		}
-	}
-
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRLPT_MAGIC, return;);
-
-	self->daddr = daddr;
-	self->saddr = saddr;
-	self->timeout = irlpt_client_expired;
-
-	irda_start_timer( &self->lpt_timer, 5000, (unsigned long) self, 
-			  self->timeout);
-	
-#if 0
-	/* changed to wake up when we get connected; that way,
-	   if the connection drops, we can easily kill the link. */
-	wake_up_interruptible( &self->write_wait);
-#endif
-
-	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
-}
-
-/*
- * Function irlpt_disconnect_indication (handle)
- *
- */
-static void irlpt_client_disconnect_indication( void *instance,
-						void *sap, 
-						LM_REASON reason,
-						struct sk_buff *skb)
-{
-	struct irlpt_info info;
-	struct irlpt_cb *self;
-
-	DEBUG( irlpt_client_debug, "--> " __FUNCTION__ "\n");
-
-	self = ( struct irlpt_cb *) instance;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLPT_MAGIC, return;);
-
-	info.daddr = self->daddr;
-
-        DEBUG( irlpt_client_debug, 
-	       __FUNCTION__ ": reason=%d (%s), peersap=%d\n",
-	       reason, irlpt_reasons[reason], self->dlsap_sel);
-
-	self->connected = IRLPT_DISCONNECTED;
-	self->eof = reason;
-
-	wake_up_interruptible( &self->write_wait);
-
-	irlpt_client_do_event( self, LMP_DISCONNECT, NULL, NULL);
-
-	if (skb)
-		dev_kfree_skb( skb);
-
-	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
-}
-
-/*
- * Function irlpt_connect_confirm (handle, qos, skb)
- *
- *    LSAP connection confirmed!
- */
-static void irlpt_client_connect_confirm(void *instance, void *sap, 
-					 struct qos_info *qos, 
-					 __u32 max_seg_size,
-					 __u8 max_header_size,
-					 struct sk_buff *skb)
-{
-	struct irlpt_info info;
-	struct irlpt_cb *self;
-
-	DEBUG( irlpt_client_debug, "--> " __FUNCTION__ "\n");
-
-	self = ( struct irlpt_cb *) instance;
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLPT_MAGIC, return;);
-
-	info.daddr = self->daddr;
-
-#if 0
-	/*
-	 *  Check if we have got some QoS parameters back! This should be the
-	 *  negotiated QoS for the link.
-	 */
-	if ( qos) {
-		DEBUG( irlpt_client_debug, __FUNCTION__ ": Frame Size: %d\n",
-		       qos->data_size.value);
-	}
-#endif
-
-	self->max_data_size = max_seg_size;
-	self->max_header_size = max_header_size;
-	self->connected = TRUE;
-	
-	irlpt_client_do_event( self, LMP_CONNECT, NULL, NULL);
-
-	if (skb)
-		dev_kfree_skb( skb);
-
-	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
-}
-
-/*
- * Function client_data_indication (handle, skb)
- *
- *    This function gets the data that is received on the data channel
- *
- */
-static int irlpt_client_data_indication(void *instance, void *sap, 
-					struct sk_buff *skb) 
-{
-	struct irlpt_cb *self;
-
-	DEBUG( irlpt_client_debug, "--> " __FUNCTION__ "\n");
-
-	ASSERT( skb != NULL, return -1;);
-	DEBUG( irlpt_client_debug, __FUNCTION__ ": len=%d\n", (int) skb->len);
-
-	self = ( struct irlpt_cb *) instance;
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
-#if 1
-	{
-		int i;
-
-		for(i=0;i<skb->len;i++)
-			if (skb->data[i] > 31 && skb->data[i] < 128) {
-				printk("%c", skb->data[i]);
-			} else {
-				if (skb->data[i] == 0x0d) {
-					printk("\n");
-				} else {
-					printk(".");
-				}
-			}
-
-		printk("\n");
-	}
-#endif
-	
-	skb_queue_tail(&self->rx_queue, skb);
-        wake_up_interruptible(&self->read_wait);
-
-/* 	if (skb) { */
-/* 		dev_kfree_skb( skb); */
-/* 	} */
-
-	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
-
-	return 0;
-}
-
-/*
- * Function irlpt_get_value_confirm (obj_id, type, value_int, value_char, priv)
- *
- *    Fixed to match changes in iriap.h, DB.
- *
- */
-void irlpt_client_get_value_confirm(int result, __u16 obj_id, 
-				    struct ias_value *value, void *priv)
-{
-	struct irlpt_info info;
-	struct irlpt_cb *self;
-
-	DEBUG( irlpt_client_debug, "--> " __FUNCTION__ "\n");
-
-	ASSERT( priv != NULL, return;);
-
-	self = (struct irlpt_cb *) priv;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLPT_MAGIC, return;);
-
-	/* Check if request succeeded */
-	if (result != IAS_SUCCESS) {
-		DEBUG( 0, __FUNCTION__ "(), got NULL value!\n");
-		irlpt_client_do_event( self, IAS_PROVIDER_NOT_AVAIL, NULL, 
-				       &info);
-		return;
-	}
-
-	if ( value->type == IAS_INTEGER && value->t.integer != -1) {
-	        info.dlsap_sel = value->t.integer;
-		self->dlsap_sel = value->t.integer;
-
-		DEBUG( irlpt_client_debug, __FUNCTION__ 
-		       ": obj_id = %d, value = %d\n", 
-		       obj_id, value->t.integer);
-
-		irlpt_client_do_event( self, IAS_PROVIDER_AVAIL, NULL, &info);
-	} else
-		irlpt_client_do_event( self, IAS_PROVIDER_NOT_AVAIL, NULL, 
-				       &info);
-
-	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
-}
-
-void irlpt_client_connect_request( struct irlpt_cb *self) 
-{
-	struct notify_t lpt_notify;
-
-	DEBUG( irlpt_client_debug, "--> " __FUNCTION__ "\n");
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLPT_MAGIC, return;);
-
-	irda_notify_init( &lpt_notify);
-
-	lpt_notify.connect_confirm = irlpt_client_connect_confirm;
-	lpt_notify.disconnect_indication = irlpt_client_disconnect_indication;
-	lpt_notify.data_indication = irlpt_client_data_indication;
-	strcpy( lpt_notify.name, "IrLPT client");
-	lpt_notify.instance = self;
-
-	self->lsap = irlmp_open_lsap( LSAP_ANY, &lpt_notify);
-	DEBUG( irlpt_client_debug, __FUNCTION__ ": Dest LSAP sel= %d\n", 
-	       self->dlsap_sel);
-	
-	if (self->servicetype == IRLPT_THREE_WIRE_RAW) {
-	        DEBUG( irlpt_client_debug, __FUNCTION__ 
-		       ": issue THREE_WIRE_RAW connect\n");
-		irlmp_connect_request( self->lsap, self->dlsap_sel, 
-				       self->saddr, self->daddr, NULL, NULL);
-	}
-
-	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
-}
-
-static void irlpt_client_expired(unsigned long data)
-{
-	struct irlpt_cb *self = (struct irlpt_cb *) data;
-	struct sk_buff *skb;
-
-	DEBUG( irlpt_client_debug, "--> " __FUNCTION__ "\n");
-
-	DEBUG( irlpt_client_debug, __FUNCTION__
-	       ": removing irlpt_cb!\n");
-
-	ASSERT(self != NULL, return; );
-	ASSERT(self->magic == IRLPT_MAGIC, return;);
-
-	if (self->state == IRLPT_CLIENT_CONN) {
-		skb = dev_alloc_skb(64);
-		if (skb == NULL) {
-			DEBUG( 0, __FUNCTION__ "(: Could not allocate an "
-			       "sk_buff of length %d\n", 64);
-			return;
-		}
-
-		skb_reserve(skb, LMP_MAX_HEADER);
-		irlmp_disconnect_request(self->lsap, skb);
-		DEBUG(irlpt_client_debug, __FUNCTION__
-		      ": irlmp_close_slap(self->lsap)\n");
-		irlmp_close_lsap(self->lsap);
-	}
-
-	irlpt_client_close(self);
-
-	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
-}
-
-#ifdef MODULE
-
-MODULE_AUTHOR("Thomas Davis <ratbert@radiks.net>");
-MODULE_DESCRIPTION("The Linux IrDA/IrLPT client protocol");
-MODULE_PARM(irlpt_client_debug,"1i");
-MODULE_PARM(irlpt_client_fsm_debug,"1i");
-
-/*
- * Function init_module (void)
- *
- *    Initialize the IrLPT client module, this function is called by the
- *    modprobe(1) program.
- */
-int init_module(void)
-{
-
-        DEBUG( irlpt_client_debug, "--> IrLPT client: init_module\n");
-
-        irlpt_client_init();
-
-        DEBUG( irlpt_client_debug, "IrLPT client: init_module -->\n");
-
-        return 0;
-}
-
-/*
- * Function cleanup_module (void)
- *
- *    Remove the IrLPT server module, this function is called by the rmmod(1)
- *    program
- */
-void cleanup_module(void)
-{
-        DEBUG( irlpt_client_debug, "--> IrLPT client: cleanup_module\n");
-        /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
-
-        /* Free some memory */
-        irlpt_client_cleanup();
-
-        DEBUG( irlpt_client_debug, "IrLPT client: cleanup_module -->\n");
-}
-
-#endif /* MODULE */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irlpt/irlpt_cli_fsm.c linux.15p9/net/irda/irlpt/irlpt_cli_fsm.c
--- linux.vanilla/net/irda/irlpt/irlpt_cli_fsm.c	Sat Aug 14 02:26:53 1999
+++ linux.15p9/net/irda/irlpt/irlpt_cli_fsm.c	Thu Jan  1 01:00:00 1970
@@ -1,369 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      irlpt_cli_fsm.c
- * Version:       0.1
- * Description:   
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Tue Jan 12 11:06:00 1999
- * Modified at:   Sun May  9 13:36:13 1999
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     Copyright (c) 1998-1999, Thomas Davis, <ratbert@radiks.net>
- *     Copyright (c) 1998, Dag Brattli, <dagb@cs.uit.no>
- *     All Rights Reserved.
- *      
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
- *     the License, or (at your option) any later version.
- *  
- *     I, Thomas Davis, provide no warranty for any of this software. This 
- *     material is provided "AS-IS" and at no charge.
- *     
- ********************************************************************/
-
-#include <net/irda/iriap.h>
-#include <net/irda/irlmp.h>
-#include <net/irda/irttp.h>
-#include <net/irda/irlpt_common.h>
-#include <net/irda/irlpt_cli.h>
-#include <net/irda/irlpt_cli_fsm.h>
-#include <net/irda/irda.h>
-
-#if 0
-static char *rcsid = "$Id: irlpt_client_fsm.c,v 1.3 1998/10/05 05:46:44 ratbert Exp $";
-#endif
-
-static int irlpt_client_state_idle  ( struct irlpt_cb *self, 
-				      IRLPT_EVENT event,
-				      struct sk_buff *skb, 
-				      struct irlpt_info *info);
-static int irlpt_client_state_query ( struct irlpt_cb *self, 
-				      IRLPT_EVENT event,
-				      struct sk_buff *skb, 
-				      struct irlpt_info *info);
-static int irlpt_client_state_ready ( struct irlpt_cb *self, 
-				      IRLPT_EVENT event, 
-				      struct sk_buff *skb, 
-				      struct irlpt_info *info);
-static int irlpt_client_state_waiti ( struct irlpt_cb *self, 
-				      IRLPT_EVENT event,
-				      struct sk_buff *skb, 
-				      struct irlpt_info *info);
-static int irlpt_client_state_conn  ( struct irlpt_cb *self, 
-				      IRLPT_EVENT event,
-				      struct sk_buff *skb, 
-				      struct irlpt_info *info);
-
-int irlpt_client_fsm_debug = 4;
-
-int (*irlpt_client_state[])( struct irlpt_cb *self, 
-			     IRLPT_EVENT event, 
-			     struct sk_buff *skb, 
-			     struct irlpt_info *info) = 
-{ 
-	irlpt_client_state_idle,
-	irlpt_client_state_query,
-	irlpt_client_state_ready,
-	irlpt_client_state_waiti,
-	irlpt_client_state_conn,
-};
-
-void irlpt_client_do_event( struct irlpt_cb *self, 
-			    IRLPT_EVENT event, 
-			    struct sk_buff *skb, 
-			    struct irlpt_info *info) 
-{
-	DEBUG( irlpt_client_fsm_debug, "--> "  __FUNCTION__ "\n");
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLPT_MAGIC, return;);
-
-	DEBUG( irlpt_client_fsm_debug, 
-	       __FUNCTION__ ": STATE = %s, EVENT = %s\n", 
-	       irlpt_server_fsm_state[self->state], irlpt_fsm_event[event]);
-
-	(*irlpt_client_state[ self->state]) ( self, event, skb, info);
-
-	DEBUG( irlpt_client_fsm_debug, __FUNCTION__ " -->\n");
-}
-
-void irlpt_client_next_state( struct irlpt_cb *self, 
-			      IRLPT_CLIENT_STATE state) 
-{
-	DEBUG( irlpt_client_fsm_debug, "--> "  __FUNCTION__ ":\n");
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLPT_MAGIC, return;);
-
-	DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": NEXT STATE = %s\n", 
-	       irlpt_client_fsm_state[state]);
-
-	self->state = state;
-
-	DEBUG( irlpt_client_fsm_debug, __FUNCTION__ " -->\n");
-}
-
-/*
- * Function irlpt_client_state_idle (self, event, skb, info)
- *
- *    IDLE, We are waiting for an indication that there is a provider
- *    available.
- */
-static int irlpt_client_state_idle( struct irlpt_cb *self, 
-				    IRLPT_EVENT event, 
-				    struct sk_buff *skb, 
-				    struct irlpt_info *info) 
-{
-	DEBUG( irlpt_client_fsm_debug, "--> "  __FUNCTION__ ":\n");
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
-
-	switch( event) {
-	case IRLPT_DISCOVERY_INDICATION:
-		/* Get some values from peer IAS */
-		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
-		       ": IRLPT_DISCOVERY_INDICATION, "
-		       "sending getvaluebyclass command..\n");
-		iriap_getvaluebyclass_request( 
-			"IrLPT", "IrDA:IrLMP:LsapSel",
-			info->saddr, info->daddr,
-			irlpt_client_get_value_confirm,
-			(void *) self);
-		irlpt_client_next_state( self, IRLPT_CLIENT_QUERY);
-		break;
-
-	default:
-		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
-		       ": Unknown event %d (%s)\n",
-		       event, irlpt_fsm_event[event]);
-		break;
-	}
-
-	if (skb) {
-		dev_kfree_skb( skb);
-	}
-
-	DEBUG( irlpt_client_fsm_debug, __FUNCTION__ " -->\n");
-
-	return 0;
-}
-
-/*
- * Function irlpt_client_state_query
- *
- *    QUERY, We have queryed the remote IAS and is ready to connect
- *    to provider, just waiting for the confirm.
- *
- */
-static int irlpt_client_state_query( struct irlpt_cb *self, 
-				     IRLPT_EVENT event, 
-				     struct sk_buff *skb, 
-				     struct irlpt_info *info) 
-{
-	DEBUG( irlpt_client_fsm_debug, "--> "  __FUNCTION__ ":\n");
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
-
-	switch( event) {
-	case IAS_PROVIDER_AVAIL:
-		DEBUG( irlpt_client_fsm_debug, 
-		       __FUNCTION__ ": IAS_PROVIDER_AVAIL\n");
-		self->open_retries = 0;
-		irlpt_client_next_state( self, IRLPT_CLIENT_READY);
-		irlpt_client_do_event( self, IRLPT_CONNECT_REQUEST, 
-				       NULL, NULL);
-		break;
-
-	case IAS_PROVIDER_NOT_AVAIL:
-		DEBUG( irlpt_client_fsm_debug, 
-		       __FUNCTION__ ": IAS_PROVIDER_NOT_AVAIL\n");
-		irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
-		DEBUG(irlpt_client_fsm_debug, __FUNCTION__
-		      ": waking any sleepers..\n");
-		wake_up_interruptible(&self->read_wait);
-		break;
-
-	case LMP_DISCONNECT:
-	case LAP_DISCONNECT:
-	        DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
-		       ": LMP_DISCONNECT or LAP_DISCONNECT\n");
-		irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
-		DEBUG(irlpt_client_fsm_debug, __FUNCTION__
-		      ": waking any sleepers..\n");
-		wake_up_interruptible(&self->read_wait);
-		break;
-	default:
-		DEBUG( irlpt_client_fsm_debug, 
-		       __FUNCTION__ ": Unknown event %d (%s)\n",
-		       event, irlpt_fsm_event[event]);
-		break;
-	}
-
-	if (skb) {
-		dev_kfree_skb( skb);
-	}
-
-	DEBUG( irlpt_client_fsm_debug, __FUNCTION__ " -->\n");
-
-	return 0;
-}
-
-/*
- * Function irlpt_client_state_info 
- *
- *    INFO, We have issued a GetInfo command and is awaiting a reply.
- */
-static int irlpt_client_state_ready( struct irlpt_cb *self, 
-				     IRLPT_EVENT event,
-				     struct sk_buff *skb, 
-				     struct irlpt_info *info) 
-{
-	DEBUG( irlpt_client_fsm_debug,"--> "  __FUNCTION__ ":\n");
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
-
-	switch( event) {
-	case IRLPT_CONNECT_REQUEST:
-	        DEBUG( irlpt_client_fsm_debug, 
-		       __FUNCTION__ ": IRLPT_CONNECT_REQUEST\n");
-		irlpt_client_connect_request(self);
-		irlpt_client_next_state( self, IRLPT_CLIENT_WAITI);
-		break;
-	case LMP_DISCONNECT:
-	case LAP_DISCONNECT:
-	        DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
-		       ": LMP_DISCONNECT or LAP_DISCONNECT\n");
-		DEBUG(irlpt_client_fsm_debug, __FUNCTION__
-		      ": waking any sleepers..\n");
-		wake_up_interruptible(&self->read_wait);
-		irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
-		break;
-	default:
-		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
-		       ": Unknown event %d (%s)\n", 
-		       event, irlpt_fsm_event[event]);
-		break;
-	}
-
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-
-	DEBUG( irlpt_client_fsm_debug, __FUNCTION__ " -->\n");
-
-	return 0;
-}
-
-
-/*
- * Function irlpt_client_state_waiti 
- *
- *
- */
-static int irlpt_client_state_waiti( struct irlpt_cb *self, 
-				     IRLPT_EVENT event, 
-				     struct sk_buff *skb, 
-				     struct irlpt_info *info) 
-{
-	DEBUG( irlpt_client_fsm_debug,"--> "  __FUNCTION__ ":\n");
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
-
-	switch( event) {
-	case LMP_CONNECT:
-	        DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": LMP_CONNECT\n");
-	        irlpt_client_next_state(self, IRLPT_CLIENT_CONN);
-		DEBUG(irlpt_client_fsm_debug, __FUNCTION__
-		      ": waking any sleepers..\n");
-		wake_up_interruptible(&self->read_wait);
-	        break;
-	case LAP_DISCONNECT:
-	case LMP_DISCONNECT:
-	        DEBUG( irlpt_client_fsm_debug, 
-		       __FUNCTION__ ": LMP_DISCONNECT\n");
-		DEBUG(irlpt_client_fsm_debug, __FUNCTION__
-		      ": waking any sleepers..\n");
-		wake_up_interruptible(&self->read_wait);
-	        irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
-	        break;
-
-	default:
-		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
-		       ": Unknown event %d (%s)\n", 
-		       event, irlpt_fsm_event[event]);
-		break;
-	}
-
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-
-	DEBUG( irlpt_client_fsm_debug, __FUNCTION__ " -->\n");
-
-	return 0;
-}
-
-/*
- * Function irlpt_client_state_conn (self, event, skb, info)
- *
- *    CONN, We have connected to a provider but has not issued any
- *    commands yet.
- *
- */
-static int irlpt_client_state_conn( struct irlpt_cb *self, 
-				    IRLPT_EVENT event, 
-				    struct sk_buff *skb, 
-				    struct irlpt_info *info) 
-{
-	DEBUG( irlpt_client_fsm_debug, "--> " __FUNCTION__ ":\n");
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
-
-	switch( event) {
-	case CLIENT_DATA_INDICATION:
-		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
-		       ": CLIENT_DATA_INDICATION\n");
-		irlpt_client_next_state( self, IRLPT_CLIENT_CONN);
-		break;
-
-	case LMP_DISCONNECT:
-	case LAP_DISCONNECT:
-		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
-		       ": LMP_DISCONNECT/LAP_DISCONNECT\n");
-		DEBUG(irlpt_client_fsm_debug, __FUNCTION__
-		      ": waking any sleepers..\n");
-		wake_up_interruptible(&self->read_wait);
-	        irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
-		irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
-		break;
-
-	default:
-		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
-		       ": Unknown event %d (%s)\n",
-		       event, irlpt_fsm_event[event]);
-		break;
-	}
-
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-
-	DEBUG( irlpt_client_fsm_debug, __FUNCTION__ " -->\n");
-
-	return 0;
-}
-
-void irlpt_client_print_event( IRLPT_EVENT event) 
-{
-	DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
-	       ": IRLPT_EVENT = %s\n", irlpt_fsm_event[event]);
-}
-
-
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irlpt/irlpt_common.c linux.15p9/net/irda/irlpt/irlpt_common.c
--- linux.vanilla/net/irda/irlpt/irlpt_common.c	Sat Aug 14 02:26:54 1999
+++ linux.15p9/net/irda/irlpt/irlpt_common.c	Thu Jan  1 01:00:00 1970
@@ -1,509 +0,0 @@
-/*********************************************************************
- *
- * Filename:      irlpt_common.c
- * Version:       
- * Description:   
- * Status:        Experimental.
- * Author:        Thomas Davis, <ratbert@radiks.net>
- * Created at:    Sat Feb 21 18:54:38 1998
- * Modified at:   Sun Mar  8 23:44:19 1998
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * Sources:	  irlpt.c
- *
- *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>,
- *     Copyright (c) 1998, Dag Brattli,  <dagb@cs.uit.no>
- *     All Rights Reserved.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     I, Thomas Davis, provide no warranty for any of this software.
- *     This material is provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#include <linux/module.h> 
-
-#include <asm/segment.h>
-
-#include <net/irda/irda.h>
-#include <net/irda/irlap.h>
-#include <net/irda/irlmp.h>
-#include <net/irda/iriap.h>
-#include <net/irda/irttp.h>
-#include <net/irda/timer.h>
-
-#include <net/irda/irlpt_common.h>
-/* #include "irlpt_client.h" */
-/* #include "irlpt_server.h" */
-
-#include <asm/uaccess.h>
-#include <linux/miscdevice.h>
-#include <linux/proc_fs.h>
-#include <linux/fs.h>
-
-char *irlpt_service_type[] = {
-	"IRLPT_UNKNOWN",
-	"IRLPT_THREE_WIRE_RAW",
-	"IRLPT_THREE_WIRE",
-	"IRLPT_NINE_WIRE",
-	"IRLPT_CENTRONICS",
-	"IRLPT_SERVER_MODE",
-};
-
-char *irlpt_port_type[] = {
-	"IRLPT_UNKNOWN",
-	"IRLPT_SERIAL",
-	"IRLPT_PARALLEL",
-};
-
-char *irlpt_connected[] = {
-	"IRLPT_DISCONNECTED",
-	"IRLPT_WAITING",
-	"IRLPT_CONNECTED",
-	"IRLPT_FLUSHED",
-};
-
-char *irlpt_reasons[] = {
-	"SERVICE_CLOSE",     /* Service has closed the connection */
-	"DISC_INDICATION",   /* Received disconnect request from peer entity*/
-	"NO_RESPONSE",       /* To many retransmits without response */
-	"DEADLOCK_DETECTED", /* To many retransmits _with_ response */
-	"FOUND_NONE",        /* No devices were discovered */
-	"MEDIA_BUSY",
-
-};
-
-char *irlpt_client_fsm_state[] = {
-	"IRLPT_CLIENT_IDLE",
-	"IRLPT_CLIENT_QUERY",
-	"IRLPT_CLIENT_READY",
-	"IRLPT_CLIENT_WAITI",
-	"IRLPT_CLIENT_CONN"
-};
-
-char *irlpt_server_fsm_state[] = {
-	"IRLPT_SERVER_IDLE",
-	"IRLPT_SERVER_CONN"
-};
-
-char *irlpt_fsm_event[] = {
-	"QUERY_REMOTE_IAS",
-	"IAS_PROVIDER_AVAIL",
-	"IAS_PROVIDER_NOT_AVAIL",
-	"LAP_DISCONNECT",
-	"LMP_CONNECT",
-	"LMP_DISCONNECT",
-	"LMP_CONNECT_INDICATION",
-	"LMP_DISCONNECT_INDICATION",
-        "IRLPT_DISCOVERY_INDICATION",
-	"IRLPT_CONNECT_REQUEST",
-	"IRLPT_DISCONNECT_REQUEST",
-	"CLIENT_DATA_INDICATION",
-};
-
-hashbin_t *irlpt_clients = NULL;
-struct irlpt_cb *irlpt_server = NULL;
-int irlpt_common_debug = 4;  /* want to change this? please don't! 
-				use irlpt_common_debug=3 on the 
-				command line! */
-
-#if 0
-static char *rcsid = "$Id: irlpt_common.c,v 1.6 1998/11/10 22:50:58 dagb Exp $";
-#endif
-
-struct irlpt_cb *irlpt_find_handle(unsigned int minor)
-{
-	struct irlpt_cb *self;
-
-	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
-	
-	/* Check for server */
-	if (irlpt_server != NULL && irlpt_server->ir_dev.minor == minor) {
-		DEBUG(irlpt_common_debug, __FUNCTION__ 
-		      ": irlpt_server file handle!\n");
-		return irlpt_server;
-	}
-
-	/* Check the clients */
-	self = (struct irlpt_cb *) hashbin_get_first( irlpt_clients);
-	while ( self) {
-		ASSERT( self->magic == IRLPT_MAGIC, return NULL;);
-		
-		if ( minor == self->ir_dev.minor)
-			return self;
-
-		self = (struct irlpt_cb *) hashbin_get_next( irlpt_clients);
-	}
-
-	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
-
-	return NULL;
-}
-
-ssize_t irlpt_read( struct file *file, char *buffer, size_t count, loff_t
-		    *noidea)
-{
-	int len=0;
-	char *ptr = buffer;
-	struct irlpt_cb *self;
-	struct sk_buff *skb = NULL;
-
-	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
-
-	self = irlpt_find_handle(MINOR( file->f_dentry->d_inode->i_rdev));
-
-	ASSERT( self != NULL, return 0;);
-	ASSERT( self->magic == IRLPT_MAGIC, return 0;);
-
-	DEBUG( irlpt_common_debug, __FUNCTION__ 
-	       ": count=%d, skb_len=%d, connected=%d (%s) eof=%d\n", 
-	       count, skb_queue_len(&self->rx_queue), self->connected, 
-	       irlpt_connected[self->connected], self->eof);
-
-	if (self->eof && !skb_queue_len(&self->rx_queue)) {
-		switch (self->eof) {
-		case LM_USER_REQUEST:
-			self->eof = FALSE;
-			DEBUG(irlpt_common_debug, 
-			      __FUNCTION__ ": returning 0\n");
-			return 0;
-		case LM_LAP_DISCONNECT:
-			self->eof = FALSE;
-			return 0;
-		case LM_LAP_RESET:
-			self->eof = FALSE;
-			return -ECONNRESET;
-		default:
-			self->eof = FALSE;
-			return -EIO;
-		}
-	}
-
-	while (len <= count) {
-		skb = skb_dequeue(&self->rx_queue);
-
-		if (skb != NULL) {
-			DEBUG(irlpt_common_debug, __FUNCTION__ 
-			      ": len=%d, skb->len=%d, count=%d\n", 
-			       len, (int) skb->len, count);
-
-			if ((skb->len + len) < count) {
-				copy_to_user(ptr, skb->data, skb->len);
-				len += skb->len;
-				ptr += skb->len;
-		
-				dev_kfree_skb( skb);
-			} else {
-				skb_queue_head(&self->rx_queue, skb);
-				break;
-			}
-		} else {
-			DEBUG( irlpt_common_debug, __FUNCTION__ 
-			       ": skb=NULL, len=%d, count=%d, eof=%d\n", 
-			       len, count, self->eof);
-
-			if (!signal_pending(current) && !self->eof) {
-				interruptible_sleep_on(&self->read_wait);
-			} else
-				break;
-		}
-	}
-
-	DEBUG(irlpt_common_debug, __FUNCTION__ ": len=%d\n", len);
-	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
-	return len;
-}
-
-ssize_t irlpt_write(struct file *file, const char *buffer,
-		    size_t count, loff_t *noidea)
-{
-	struct irlpt_cb *self;
-	struct sk_buff *skb;
-
-	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
-
-	self = irlpt_find_handle(MINOR( file->f_dentry->d_inode->i_rdev));
-
-	ASSERT( self != NULL, return 0;);
-	ASSERT( self->magic == IRLPT_MAGIC, return 0;);
-	
-	DEBUG( irlpt_common_debug, __FUNCTION__ 
-	       ": count = %d\n", count);
-
-	DEBUG( irlpt_common_debug, __FUNCTION__ 
-	       ": pkt_count = %d\n", self->pkt_count);
-	if (self->pkt_count > 8) {
-		DEBUG( irlpt_common_debug, __FUNCTION__ 
-		       ": too many outstanding buffers, going to sleep\n");
-		interruptible_sleep_on(&self->write_wait);
-	}
-
-	DEBUG( irlpt_common_debug, __FUNCTION__ 
-	       ": pkt_count = %d\n", self->pkt_count);
-
-	if (self->state != IRLPT_CLIENT_CONN) {
-		DEBUG( irlpt_common_debug, __FUNCTION__ 
-		       ": state != IRLPT_CONN (possible link problems?)\n");
-		return -ENOLINK;
-	}
-
-	DEBUG( irlpt_common_debug, __FUNCTION__ 
-	       ": count = %d, max_data_size = %d, IRLPT_MAX_HEADER = %d\n",
-		count, self->max_data_size, IRLPT_MAX_HEADER);
-
- 	if (count > self->max_data_size) {
- 		count = self->max_data_size;
- 		DEBUG(irlpt_common_debug, __FUNCTION__ 
-		      ": setting count to %d\n", count);
- 	}
-
-	DEBUG( irlpt_common_debug, __FUNCTION__ ": count = %d\n", count);
-
-	skb = dev_alloc_skb(count + self->max_header_size);
-	if ( skb == NULL) {
-		printk( KERN_INFO 
-			__FUNCTION__ ": couldn't allocate skbuff!\n");
-		return 0;
-	}
-
-	/*
-	 * we use the unused stamp field to hold the device minor
-	 * number, so we can look it up when the skb is destroyed.
-	 */
-	*((__u32 *) &skb->stamp) = MINOR( file->f_dentry->d_inode->i_rdev);
-
-	skb_reserve( skb, IRLPT_MAX_HEADER);
-	skb_put( skb, count);
-
-	skb->destructor = irlpt_flow_control;
-	self->pkt_count++;
-
-	copy_from_user( skb->data, buffer, count);
-
-	irlmp_data_request(self->lsap, skb);
-
-	irda_start_timer( &self->lpt_timer, 5000, (unsigned long) self, 
-			  self->timeout);
-
-	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
-
-	return(count);
-}
-
-loff_t irlpt_seek( struct file *file, loff_t offset, int count)
-{
-	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
-
-	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
-	return -ESPIPE;
-}
-
-/*
- * Function irlpt_poll (file, wait)
- *
- *    
- *
- */
-u_int irlpt_poll(struct file *file, poll_table *wait)
-{
-	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
-
-	/* check out /usr/src/pcmcia/modules/ds.c for an example */
-	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
-	return 0;
-}
-
-/*
- * Function open_irlpt (inode, file)
- *
- *
- *
- */
-int irlpt_open(struct inode *inode, struct file *file)
-{
-	struct irlpt_cb *self;
-	struct irlpt_info info;
-
-	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
-
-	self = irlpt_find_handle(MINOR( file->f_dentry->d_inode->i_rdev));
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
-
-	if (self->count++) {
-		DEBUG( irlpt_common_debug, __FUNCTION__ 
-		       ": count not zero; actual = %d\n", self->count);
-		self->count--;
-		return -EBUSY;
-	}
-
-	self->eof = FALSE;
-
-	/* ok, now, if it's idle, try to get some information
-	   about the remote end, and sleep till we get totally connected.. */
-
-	if ((self->servicetype != IRLPT_SERVER_MODE) && 
-	    self->state != IRLPT_CLIENT_CONN) {
-		DEBUG(irlpt_common_debug, __FUNCTION__
-		      ": self->state != IRLPT_CLIENT_CONN\n");
-
-		info.daddr = self->daddr;
-		info.saddr = self->saddr;
-
-		if (self->do_event != NULL) {
-			DEBUG(irlpt_common_debug, __FUNCTION__ 
-			      ": doing a discovery..\n");
-			self->do_event( self, 
-					IRLPT_DISCOVERY_INDICATION, 
-					NULL, &info);
-			DEBUG(irlpt_common_debug, __FUNCTION__ 
-			      ": sleeping until connected.\n");
-			interruptible_sleep_on(&self->read_wait);
-		}
-	}
-
-	/* at this point, if it's a client, we have a connection.
-	 * if it's the server, it's waiting for a connection.
-	 */
-
-	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
-
-	return 0;
-}
-
-/*
- * Function close_irlpt (inode, file)
- *
- *
- *
- */
-int irlpt_close(struct inode *inode, 
-		struct file *file)
-{
-	struct irlpt_cb *self;
-	struct sk_buff *skb;
-	struct irlpt_info info;
-
-	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
-
-	self = irlpt_find_handle(MINOR( file->f_dentry->d_inode->i_rdev));
-
-	DEBUG(irlpt_common_debug, __FUNCTION__ ": have handle!\n");
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
-
-	DEBUG(irlpt_common_debug, 
-	      __FUNCTION__ ": self->count=%d\n", self->count);
-
-	if (self->count > 0)
-		self->count--;
-
-	while (self->pkt_count > 0) {
-		interruptible_sleep_on(&self->write_wait);
-	}
-
-	/* all done, tear down the connection and wait for the next open */
-	if ((self->servicetype != IRLPT_SERVER_MODE) &&
-	    self->state == IRLPT_CLIENT_CONN) {
-		skb = dev_alloc_skb(64);
-		if (skb == NULL) {
-			DEBUG( 0, __FUNCTION__ "(: Could not allocate an "
-			       "sk_buff of length %d\n", 64);
-			return 0;
-		}
-
-		skb_reserve( skb, LMP_MAX_HEADER);
-		irlmp_disconnect_request(self->lsap, skb);
-		DEBUG(irlpt_common_debug, __FUNCTION__
-		      ": irlmp_close_slap(self->lsap)\n");
-		irlmp_close_lsap(self->lsap);
-	}
-
-	info.daddr = self->daddr;
-
-	if (self->do_event != NULL) {
-	        DEBUG(irlpt_common_debug, __FUNCTION__ 
-		      ": closing connection..\n");
-		self->do_event( self, LMP_DISCONNECT, NULL, &info);
-	}
-
-	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
-	return 0;
-}
-
-void irlpt_dump_buffer( struct sk_buff *skb) 
-{
-	int i;
-
-	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
-
-	for(i=0;i<skb->len;i++)
-		if (skb->data[i] > 31 && skb->data[i] < 128) {
-			printk("%c", skb->data[i]);
-		} else {
-			if (skb->data[i] == 0x0d) {
-				printk("\n");
-			} else {
-				printk(".");
-			}
-		}
-	
-	printk("\n");
-	
-	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
-}
-
-void irlpt_flow_control(struct sk_buff *skb)
-{
-	struct irlpt_cb *self;
-
-	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
-
-	self = irlpt_find_handle( *((__u32 *) &skb->stamp));
-
-	self->pkt_count--;
-
-	ASSERT(self->pkt_count >= 0, return;);
-
-	DEBUG(irlpt_common_debug, __FUNCTION__ 
-	      ": packet destroyed, count = %d\n", self->pkt_count);
-
-	wake_up_interruptible( &self->write_wait);
-
-	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
-}
-
-#ifdef MODULE
-
-MODULE_AUTHOR("Thomas Davis <ratbert@radiks.net>");
-MODULE_DESCRIPTION("The Linux IrDA/IrLPT common");
-MODULE_PARM(irlpt_common_debug,"1i");
-
-/*
- * Function init_module (void)
- *
- *    Initialize the module, this function is called by the
- *    modprobe(1) program.
- */
-int init_module(void) 
-{
-	return 0;
-}
-
-/*
- * Function cleanup_module (void)
- *
- *    Remove the module, this function is called by the rmmod(1)
- *    program
- */
-void cleanup_module(void) 
-{
-
-}
-
-#endif /* MODULE */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irlpt/irlpt_srvr.c linux.15p9/net/irda/irlpt/irlpt_srvr.c
--- linux.vanilla/net/irda/irlpt/irlpt_srvr.c	Sat Aug 14 02:26:54 1999
+++ linux.15p9/net/irda/irlpt/irlpt_srvr.c	Thu Jan  1 01:00:00 1970
@@ -1,530 +0,0 @@
-/*********************************************************************
- *
- * Filename:      irlpt.c
- * Version:       
- * Description:   
- * Status:        Experimental.
- * Author:        Thomas Davis, <ratbert@radiks.net>
- * Created at:    Sat Feb 21 18:54:38 1998
- * Modified at:   Sun Mar  8 23:44:19 1998
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * Sources:	  irlan.c
- *
- *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>,
- *			   Dag Brattli,  <dagb@cs.uit.no>
- *     All Rights Reserved.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     I, Thomas Davis, provide no warranty for any of this software.
- *     This material is provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/module.h>
-
-#include <asm/uaccess.h>
-#include <linux/miscdevice.h>
-#include <linux/proc_fs.h>
-
-#include <net/irda/irlap.h>
-#include <net/irda/irlmp.h>
-#include <net/irda/iriap.h>
-#include <net/irda/irias_object.h>
-#include <net/irda/timer.h>
-#include <net/irda/irda.h>
-#include <net/irda/irlpt_common.h>
-#include <net/irda/irlpt_server.h>
-#include <net/irda/irlpt_server_fsm.h>
-
-#ifdef CONFIG_PROC_FS
-static int irlpt_server_proc_read(char *buf, char **start, off_t offset, 
-				  int len, int unused);
-#endif /* CONFIG_PROC_FS */
-
-int irlpt_server_init(void);
-static void irlpt_server_disconnect_indication(void *instance, void *sap, 
-						LM_REASON reason,
-						struct sk_buff *skb);
-
-#if 0
-static void irlpt_server_connect_confirm(void *instance, void *sap, 
-					 struct qos_info *qos,  
-					 __u32 max_seg_size,
-					 __u8 max_header_size,
-					 struct sk_buff *skb);
-static void irlpt_server_connect_indication(void *instance, 
-					    void *sap, 
-					    struct qos_info *qos, 
-					    __u32 max_seg_size,
-					    __u8 max_header_size,
-					    struct sk_buff *skb);
-#endif
-
-static int irlpt_server_data_indication(void *instance, void *sap, 
-					struct sk_buff *skb);
-static void register_irlpt_server(void);
-static void deregister_irlpt_server(void);
-
-static __u32 skey; /* IrLMP service handle */
-
-int irlpt_server_lsap = LSAP_IRLPT;
-int irlpt_server_debug = 4;
-
-#if 0
-static char *rcsid = "$Id: irlpt_server.c,v 1.9 1998/10/22 12:02:22 dagb Exp $";
-#endif
-
-static char *version = "IrLPT server, v2 (Thomas Davis)";
-
-struct file_operations irlpt_fops = {
-	irlpt_seek,	/* seek */
-	irlpt_read,     /* read */   
-	irlpt_write,
-	NULL,		/* readdir */
-	NULL,           /* poll */
-	NULL,		/* ioctl */
-	NULL,		/* mmap */
-	irlpt_open,     /* open */
-	NULL,           /* flush */
-	irlpt_close,    /* release */
-	NULL,           /* fsync */
-	NULL,           /* fasync */
-	NULL,           /* check_media_change */
-	NULL,           /* revalidate */
-        NULL,           /* lock */
-};
-
-#ifdef CONFIG_PROC_FS
-
-/*
- * Function irlpt_server_proc_read (buf, start, offset, len, unused)
- *
- *
- *
- */
-static int irlpt_server_proc_read(char *buf, char **start, off_t offset, 
-				  int len, int unused)
-{
-	int index;
-
-	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
-
-	if (irlpt_server != NULL) {
-	        len = sprintf(buf, "%s\n\n", version);
-		len += sprintf(buf+len, "ifname: %s\n", irlpt_server->ifname);
-		len += sprintf(buf+len, "minor: %d\n", irlpt_server->ir_dev.minor);
-
-		switch (irlpt_server->servicetype) {
-		case IRLPT_UNKNOWN:
-			index = 0;
-			break;
-		case IRLPT_THREE_WIRE_RAW:
-			index = 1;
-			break;
-		case IRLPT_THREE_WIRE:
-			index = 2;
-			break;
-		case IRLPT_NINE_WIRE:
-			index = 3;
-			break;
-		case IRLPT_CENTRONICS:
-			index = 4;
-			break;
-		case IRLPT_SERVER_MODE:
-			index = 5;
-			break;
-		default:
-			index = 0;
-			break;
-		}
-
-		len += sprintf(buf+len, "servicetype: %s, porttype: %s\n",
-			       irlpt_service_type[index],
-			       irlpt_port_type[irlpt_server->porttype]);
-		len += sprintf(buf+len, "saddr: 0x%08x, daddr: 0x%08x\n", 
-			       irlpt_server->saddr, irlpt_server->daddr);
-		len += sprintf(buf+len, "slsap: 0x%08x, dlsap: 0x%08x\n", 
-			       irlpt_server->slsap_sel, 
-			       irlpt_server->dlsap_sel);
-		len += sprintf(buf+len, "retries: %d, count: %d\n", 
-			       irlpt_server->open_retries,
-			       irlpt_server->count);
-		len += sprintf(buf+len, "fsm state: %s, rx queue depth: %d\n", 
-			       irlpt_server_fsm_state[irlpt_server->state],
-			       skb_queue_len(&irlpt_server->rx_queue));
-		len += sprintf(buf+len, "\n");
-	}
-
-	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
-
-	return len;
-}
-
-extern struct proc_dir_entry *proc_irda;
-#endif /* CONFIG_PROC_FS */
-
-/*
- * Function irlpt_init (dev)
- *
- *   Initializes the irlpt control structure
- *
- */
-
-__initfunc(int irlpt_server_init(void))
-{
-	struct irmanager_event mgr_event;
-	__u16 hints;
-
-	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
-
-	printk( KERN_INFO "%s\n", version);
-
-	irlpt_server = (struct irlpt_cb *) kmalloc (sizeof(struct irlpt_cb), 
-						    GFP_KERNEL);
-
-	if ( irlpt_server == NULL) {
-		printk( KERN_WARNING "IrLPT server: Can't allocate" 
-			" irlpt_server control block!\n");
-		return -ENOMEM;
-	}
-	memset( irlpt_server, 0, sizeof(struct irlpt_cb));
-
-	sprintf(irlpt_server->ifname, "irlpt_server");
-	irlpt_server->ir_dev.minor = MISC_DYNAMIC_MINOR;
-	irlpt_server->ir_dev.name = irlpt_server->ifname;
-	irlpt_server->ir_dev.fops = &irlpt_fops;
-	misc_register(&irlpt_server->ir_dev);
-	irlpt_server->magic = IRLPT_MAGIC;
-	irlpt_server->in_use = TRUE;
-	irlpt_server->servicetype = IRLPT_THREE_WIRE_RAW;
-	irlpt_server->porttype = IRLPT_SERIAL;
-
-	skb_queue_head_init(&irlpt_server->rx_queue);
-
-	hints = irlmp_service_to_hint(S_PRINTER);
-	skey = irlmp_register_service(hints);
-	
-	register_irlpt_server();
-
-#ifdef CONFIG_PROC_FS
-	create_proc_entry("irlpt_server", 0, proc_irda)->get_info
-		= irlpt_server_proc_read;
-#endif /* CONFIG_PROC_FS */
-
-	mgr_event.event = EVENT_IRLPT_START;
-        sprintf(mgr_event.devname, "%s", irlpt_server->ifname);
-        irmanager_notify(&mgr_event);
-
-	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
-
-	return 0;
-}
-
-/*
- * Function irlpt_cleanup (void)
- *
- *
- *
- */
-static void irlpt_server_cleanup(void)
-{
-	struct irmanager_event mgr_event;
-	struct sk_buff *skb;
-
-	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
-
-	irlmp_unregister_service(skey);
-	deregister_irlpt_server();
-
-	while (( skb = skb_dequeue(&irlpt_server->rx_queue)) != NULL) {
-		DEBUG(irlpt_server_debug, __FUNCTION__ ": freeing SKB\n");
-                dev_kfree_skb( skb);
-	}
-
-	misc_deregister(&irlpt_server->ir_dev);
-
-	kfree(irlpt_server);
-
-#ifdef CONFIG_PROC_FS
-	remove_proc_entry("irlpt_server", proc_irda);
-#endif
-
-        mgr_event.event = EVENT_IRLPT_STOP;
-        sprintf( mgr_event.devname, "%s", irlpt_server->ifname);
-        irmanager_notify( &mgr_event);
- 
-	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
-}
-
-/*
- * Function irlpt_disconnect_indication (handle)
- *
- */
-static void irlpt_server_disconnect_indication( void *instance, 
-						void *sap, 
-						LM_REASON reason,
-						struct sk_buff *userdata)
-{
-#if 0
-	struct irlpt_info info;
-#endif
-	struct irlpt_cb *self;
-
-	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
-
-	self = ( struct irlpt_cb *) instance;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLPT_MAGIC, return;);
-
-#if 0
-	info.daddr = self->daddr;
-#endif
-
-	DEBUG( irlpt_server_debug, 
-	       __FUNCTION__ ": reason=%d (%s), dlsap_sel=%d\n",
-	       reason, irlpt_reasons[reason], self->dlsap_sel);
-
-	self->connected = IRLPT_DISCONNECTED;
-	self->eof = reason;
-
-        wake_up_interruptible(&self->read_wait);
-	wake_up_interruptible(&self->write_wait);
-	wake_up_interruptible(&self->ex_wait);
-
-	DEBUG( irlpt_server_debug, __FUNCTION__ ": rx queue length: %d\n",
-	       skb_queue_len(&irlpt_server->rx_queue));
-
-	irlpt_server_do_event( self, LMP_DISCONNECT, NULL, NULL);
-
-	deregister_irlpt_server();
-	register_irlpt_server();
-
-	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
-}
-
-/*
- * Function irlpt_connect_confirm (handle, qos, skb)
- *
- *    LSAP connection confirmed!
- */
-static void irlpt_server_connect_confirm(void *instance, 
-					 void *sap, 
-					 struct qos_info *qos,
-					 __u32 max_seg_size,
-					 __u8 max_header_size,
-					 struct sk_buff *skb)
-{
-	struct irlpt_cb *self;
-
-	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
-	self = ( struct irlpt_cb *) instance;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLPT_MAGIC, return;);
-
-	self->max_data_size = max_seg_size;
-	self->max_header_size = max_header_size;
-
-	self->connected = TRUE;
-
-	irlpt_server_do_event( self, LMP_CONNECT, NULL, NULL);
-
-	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
-}
-
-/*
- * Function irlpt_connect_indication (handle)
- *
- */
-static void irlpt_server_connect_indication(void *instance, 
-					    void *sap, 
-					    struct qos_info *qos, 
-					    __u32 max_seg_size,
-					    __u8 max_header_size,
-					    struct sk_buff *skb)
-{
-	struct irlpt_cb *self;
-	struct irlpt_info info;
-
-	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
-
-	self = ( struct irlpt_cb *) instance;
-
-	info.lsap  = (struct lsap_cb *) sap;
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLPT_MAGIC, return;);
-
-	self->max_data_size = max_seg_size;
-	self->max_header_size = max_header_size;
-
-	self->connected = IRLPT_CONNECTED;
-	self->eof = FALSE;
-
-	irlpt_server_do_event( self, LMP_CONNECT, NULL, &info);
-
-	if (skb)
-		dev_kfree_skb( skb);
-
-	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
-}
-
-/*
- * Function irlpt_server_data_indication (handle, skb)
- *
- *    This function gets the data that is received on the data channel
- *
- */
-static int irlpt_server_data_indication(void *instance, void *sap, 
-					struct sk_buff *skb) 
-{
-	struct irlpt_cb *self;
-
-	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
-
-	self = ( struct irlpt_cb *) instance;
-	     
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
-
-	ASSERT( skb != NULL, return -1;);
-
-	DEBUG( irlpt_server_debug, __FUNCTION__ ": len=%d\n", (int) skb->len);
-
-#if 0
-	dump_buffer(skb);
-#endif
-	
-	skb_queue_tail(&self->rx_queue, skb);
-        wake_up_interruptible(&self->read_wait);
-
-	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
-	
-	return 0;
-}
-
-/*
- * Function register_irlpt_server(void)
- *
- *    Register server support so we can accept incoming connections. We
- *    must register both a TSAP for control and data
- * 
- */
-static void register_irlpt_server(void)
-{
-	struct notify_t notify;
-	struct ias_object *obj;
-	
-	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
-
-	/*
-	 *  First register control TSAP
-	 */
-	if ( !irlpt_server || irlpt_server->magic != IRLPT_MAGIC) {
-		DEBUG( 0, __FUNCTION__ ": unable to obtain handle!\n");
-		return;
-	}
-
-	irda_notify_init(&notify);
-
-	notify.connect_confirm = irlpt_server_connect_confirm;
-	notify.connect_indication = irlpt_server_connect_indication;
-	notify.disconnect_indication = irlpt_server_disconnect_indication;
-	notify.data_indication = irlpt_server_data_indication;
-	notify.instance = irlpt_server;
-	strcpy(notify.name, "IrLPT server");
-
-	irlpt_server->lsap = irlmp_open_lsap( irlpt_server_lsap, &notify);
-
-	irlpt_server->connected = IRLPT_WAITING;
-	irlpt_server->service_LSAP = irlpt_server_lsap;
-	irlpt_server->slsap_sel = irlpt_server_lsap;
-
-	/* 
-	 *  Register with LM-IAS
-	 */
-
-	obj = irias_new_object("IrLPT", IAS_IRLPT_ID);
-	irias_add_integer_attrib(obj, "IrDA:IrLMP:LsapSel", irlpt_server_lsap);
-	irias_insert_object(obj);
-
-	DEBUG( irlpt_server_debug, __FUNCTION__ 
-	       ": Source LSAP sel=%d\n", irlpt_server->slsap_sel);
-	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
-}
-
-/*
- * Function register_irlpt_server(void)
- *
- *    Register server support so we can accept incoming connections. We
- *    must register both a TSAP for control and data
- * 
- */
-static void deregister_irlpt_server(void)
-{
-	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
-
-	irlpt_server->connected = IRLPT_DISCONNECTED;
-
-	/* 
-	 *  de-Register with LM-IAS
-	 */
-	irias_delete_object( "IrLPT");
-
-	DEBUG( irlpt_server_debug, 
-	       __FUNCTION__ ": Source LSAP sel=%d\n", irlpt_server->slsap_sel);
-	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
-}
-
-#ifdef MODULE
-
-MODULE_AUTHOR("Thomas Davis <ratbert@radiks.net>");
-MODULE_DESCRIPTION("The Linux IrDA/IrLPT server protocol");
-MODULE_PARM(irlpt_server_debug,"1i");
-MODULE_PARM(irlpt_server_fsm_debug, "1i");
-
-/*
- * Function init_module (void)
- *
- *    Initialize the IrLPT server module, this function is called by the
- *    modprobe(1) program.
- */
-int init_module(void)
-{
-	int ret;
-
-        DEBUG( irlpt_server_debug, "--> IrLPT server: init_module\n");
-
-        ret = irlpt_server_init();
-
-        DEBUG( irlpt_server_debug, "IrLPT server: init_module -->\n");
-
-        return ret;
-}
-
-/*
- * Function cleanup_module (void)
- *
- *    Remove the IrLPT server module, this function is called by the rmmod(1)
- *    program
- */
-void cleanup_module(void)
-{
-        DEBUG( irlpt_server_debug, "--> IrLPT server: cleanup_module\n");
-
-        /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
-
-        /* Free some memory */
-        irlpt_server_cleanup();
-
-        DEBUG( irlpt_server_debug, "IrLPT server: cleanup_module -->\n");
-}
-
-#endif /* MODULE */
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irlpt/irlpt_srvr_fsm.c linux.15p9/net/irda/irlpt/irlpt_srvr_fsm.c
--- linux.vanilla/net/irda/irlpt/irlpt_srvr_fsm.c	Sun Mar  7 23:26:44 1999
+++ linux.15p9/net/irda/irlpt/irlpt_srvr_fsm.c	Thu Jan  1 01:00:00 1970
@@ -1,187 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      irlpt_srvr_fsm.c
- * Version:       0.1
- * Sources:       irlan_event.c
- * 
- *     Copyright (c) 1997, Dag Brattli <dagb@cs.uit.no>, 
- *		All Rights Reserved.
- *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>, 
- *		All Rights Reserved.
- *     
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
- *     the License, or (at your option) any later version.
- *
- *     I, Thomas Davis, provide no warranty for any of this software. This 
- *     material is provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#include <net/irda/iriap.h>
-#include <net/irda/irlmp.h>
-#include <net/irda/irttp.h>
-#include <net/irda/irlpt_common.h>
-#include <net/irda/irlpt_server.h>
-#include <net/irda/irlpt_server_fsm.h>
-#include <net/irda/irda.h>
-
-static int irlpt_server_state_idle  ( struct irlpt_cb *self, 
-				      IRLPT_EVENT event,
-				      struct sk_buff *skb, 
-				      struct irlpt_info *info);
-static int irlpt_server_state_conn  ( struct irlpt_cb *self, 
-				      IRLPT_EVENT event, 
-				      struct sk_buff *skb, 
-				      struct irlpt_info *info);
-
-#if 0
-static char *rcsid = "$Id: irlpt_server_fsm.c,v 1.4 1998/10/05 05:46:45 ratbert Exp $";
-#endif
-
-int irlpt_server_fsm_debug = 4; /* don't change this! */
-
-static int (*irlpt_server_state[])( struct irlpt_cb *self, 
-				    IRLPT_EVENT event, 
-				    struct sk_buff *skb,
-				    struct irlpt_info *info) = 
-{ 
-	irlpt_server_state_idle,
-	irlpt_server_state_conn,
-};
-
-void irlpt_server_do_event( struct irlpt_cb *self, 
-			    IRLPT_EVENT event, 
-			    struct sk_buff *skb, 
-			    struct irlpt_info *info) 
-{
-	DEBUG( irlpt_server_fsm_debug, 
-	       __FUNCTION__ ": STATE = %s, EVENT = %s\n", 
-	       irlpt_server_fsm_state[self->state], irlpt_fsm_event[event]);
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLPT_MAGIC, return;);
-
-	(*irlpt_server_state[ self->state]) ( self, event, skb, info);
-
-	DEBUG( irlpt_server_fsm_debug, __FUNCTION__ " -->\n");
-}
-
-void irlpt_server_next_state( struct irlpt_cb *self, 
-			      IRLPT_CLIENT_STATE state) 
-{
-
-	DEBUG( irlpt_server_fsm_debug, __FUNCTION__ ": NEXT STATE = %s\n", 
-	       irlpt_server_fsm_state[state]);
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLPT_MAGIC, return;);
-
-	self->state = state;
-
-	DEBUG( irlpt_server_fsm_debug, __FUNCTION__ " -->\n");
-}
-
-/*
- * Function server_state_idle (event, skb, info)
- *
- *    IDLE, We are waiting for an indication that there is a provider
- *    available.
- */
-static int irlpt_server_state_idle( struct irlpt_cb *self, 
-				    IRLPT_EVENT event, 
-				    struct sk_buff *skb, 
-				    struct irlpt_info *info) 
-{
-	struct sk_buff *r_skb;
-
-	DEBUG( irlpt_server_fsm_debug, "--> " __FUNCTION__ ":\n");
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
-
-	switch( event) {
-	case LMP_CONNECT:
-		DEBUG( irlpt_server_fsm_debug, __FUNCTION__ 
-		       ": LM_CONNECT, remote lsap: 0x%08x\n",
-		       info->lsap->dlsap_sel);
-
-		self->dlsap_sel = info->lsap->dlsap_sel;
-		self->daddr = info->daddr;
-		self->saddr = info->saddr;
-
-		r_skb = dev_alloc_skb(64);
-		if (r_skb == NULL) { 
-			printk( KERN_INFO __FUNCTION__ 
-				": can't allocate sk_buff of length 64\n");
-			return 0;
-		}
-		skb_reserve( r_skb, LMP_MAX_HEADER);
-		irlmp_connect_response( self->lsap, r_skb);
-		irlpt_server_next_state( self, IRLPT_SERVER_CONN);
-		break;
-
-	default:
-		DEBUG( irlpt_server_fsm_debug, __FUNCTION__ 
-		       ": Unknown event %d (%s)\n", 
-		       event, irlpt_fsm_event[event]);
-		break;
-	}
-
-	if (skb) {
-		dev_kfree_skb( skb);
-	}
-
-	DEBUG( irlpt_server_fsm_debug, __FUNCTION__ " -->\n");
-
-	return 0;
-}
-
-/*
- * Function server_state_conn (event, skb, info)
- *
- *    CONN, We have connected to a provider but has not issued any
- *    commands yet.
- *
- */
-static int irlpt_server_state_conn( struct irlpt_cb *self, 
-				    IRLPT_EVENT event, 
-				    struct sk_buff *skb, 
-				    struct irlpt_info *info) 
-{
-	DEBUG( irlpt_server_fsm_debug, "--> " __FUNCTION__ ":\n");
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
-
-	switch( event) {
-	case LMP_DISCONNECT:
-	case LAP_DISCONNECT:
-		DEBUG( irlpt_server_fsm_debug, __FUNCTION__ 
-		       ": LMP_DISCONNECT/LAP_DISCONNECT\n");
-		irlpt_server_next_state( self, IRLPT_SERVER_IDLE);
-		break;
-
-	default:
-		DEBUG( irlpt_server_fsm_debug, __FUNCTION__ 
-		       ": Unknown event %d (%s)\n", 
-		       event, irlpt_fsm_event[event]);
-		break;
-	}
-
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-
-	DEBUG( irlpt_server_fsm_debug, __FUNCTION__ " -->\n");
-
-	return 0;
-}
-
-#if 0
-static void irlpt_server_print_event( IRLPT_EVENT event) 
-{
-	DEBUG( 0, "IRLPT_EVENT = %s\n", irlpt_fsm_event[event]);
-}
-#endif
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irmod.c linux.15p9/net/irda/irmod.c
--- linux.vanilla/net/irda/irmod.c	Tue Jan  4 21:19:03 2000
+++ linux.15p9/net/irda/irmod.c	Tue Jan 18 01:08:19 2000
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Dec 15 13:55:39 1997
- * Modified at:   Fri May 14 13:46:02 1999
+ * Modified at:   Mon Jan 17 11:21:56 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1997, 1999 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1997, 1999-2000 Dag Brattli, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -27,10 +27,10 @@
 
 #include <linux/init.h>
 #include <linux/poll.h>
-#include <asm/segment.h>
-
 #include <linux/proc_fs.h>
 
+#include <asm/segment.h>
+
 #include <net/irda/irda.h>
 #include <net/irda/irmod.h>
 #include <net/irda/irlap.h>
@@ -44,6 +44,7 @@
 #include <net/irda/irda_device.h>
 #include <net/irda/wrapper.h>
 #include <net/irda/timer.h>
+#include <net/irda/parameters.h>
 
 extern struct proc_dir_entry *proc_irda;
 
@@ -66,7 +67,7 @@
 extern int irlan_client_init(void);
 extern int irlan_server_init(void);
 extern int ircomm_init(void);
-extern int irvtd_init(void);
+extern int ircomm_tty_init(void);
 extern int irlpt_client_init(void);
 extern int irlpt_server_init(void);
 
@@ -122,8 +123,15 @@
 #ifdef CONFIG_PROC_FS
 EXPORT_SYMBOL(proc_irda);
 #endif
+EXPORT_SYMBOL(irda_param_insert);
+EXPORT_SYMBOL(irda_param_extract);
+EXPORT_SYMBOL(irda_param_extract_all);
+EXPORT_SYMBOL(irda_param_pack);
+EXPORT_SYMBOL(irda_param_unpack);
 
 /* IrIAP/IrIAS */
+EXPORT_SYMBOL(iriap_open);
+EXPORT_SYMBOL(iriap_close);
 EXPORT_SYMBOL(iriap_getvaluebyclass_request);
 EXPORT_SYMBOL(irias_object_change_attribute);
 EXPORT_SYMBOL(irias_add_integer_attrib);
@@ -132,6 +140,7 @@
 EXPORT_SYMBOL(irias_insert_object);
 EXPORT_SYMBOL(irias_new_object);
 EXPORT_SYMBOL(irias_delete_object);
+EXPORT_SYMBOL(irias_delete_value);
 EXPORT_SYMBOL(irias_find_object);
 EXPORT_SYMBOL(irias_find_attrib);
 EXPORT_SYMBOL(irias_new_integer_value);
@@ -167,42 +176,50 @@
 EXPORT_SYMBOL(hashbin_get_first);
 
 /* IrLAP */
+EXPORT_SYMBOL(irlap_open);
+EXPORT_SYMBOL(irlap_close);
 #ifdef CONFIG_IRDA_COMPRESSION
 EXPORT_SYMBOL(irda_unregister_compressor);
 EXPORT_SYMBOL(irda_register_compressor);
 #endif /* CONFIG_IRDA_COMPRESSION */
 EXPORT_SYMBOL(irda_init_max_qos_capabilies);
 EXPORT_SYMBOL(irda_qos_bits_to_value);
-EXPORT_SYMBOL(irda_device_open);
-EXPORT_SYMBOL(irda_device_close);
 EXPORT_SYMBOL(irda_device_setup);
 EXPORT_SYMBOL(irda_device_set_media_busy);
 EXPORT_SYMBOL(irda_device_txqueue_empty);
 
-EXPORT_SYMBOL(irda_device_init_dongle);
+EXPORT_SYMBOL(irda_device_dongle_init);
+EXPORT_SYMBOL(irda_device_dongle_cleanup);
 EXPORT_SYMBOL(irda_device_register_dongle);
 EXPORT_SYMBOL(irda_device_unregister_dongle);
+EXPORT_SYMBOL(irda_task_execute);
+EXPORT_SYMBOL(irda_task_kick);
+EXPORT_SYMBOL(irda_task_next_state);
+EXPORT_SYMBOL(irda_task_delete);
 
 EXPORT_SYMBOL(async_wrap_skb);
 EXPORT_SYMBOL(async_unwrap_char);
 EXPORT_SYMBOL(irda_start_timer);
-/* EXPORT_SYMBOL(irda_get_mtt); */
 EXPORT_SYMBOL(setup_dma);
+EXPORT_SYMBOL(infrared_mode);
 
 #ifdef CONFIG_IRTTY
 EXPORT_SYMBOL(irtty_set_dtr_rts);
 EXPORT_SYMBOL(irtty_register_dongle);
 EXPORT_SYMBOL(irtty_unregister_dongle);
+EXPORT_SYMBOL(irtty_set_packet_mode);
 #endif
 
-__initfunc(int irda_init(void))
+int __init irda_init(void)
 {
-        printk(KERN_INFO "IrDA (tm) Protocols for Linux-2.2 (Dag Brattli)\n");
-
+	MESSAGE("IrDA (tm) Protocols for Linux-2.2 (Dag Brattli)\n");
+	
  	irlmp_init();
 	irlap_init();
-	irda_device_init();
-
+	
+#ifdef MODULE
+	irda_device_init();	/* Called by init/main.c when non-modular */
+#endif
 	iriap_init();
  	irttp_init();
 	
@@ -212,12 +229,11 @@
 #ifdef CONFIG_SYSCTL
 	irda_sysctl_register();
 #endif
-
 	irda.dev.minor = MISC_DYNAMIC_MINOR;
 	irda.dev.name = "irda";
 	irda.dev.fops = &irda_fops;
 	
-	misc_register( &irda.dev);
+	misc_register(&irda.dev);
 
 	irda.in_use = FALSE;
 
@@ -229,15 +245,7 @@
 #endif
 #ifdef CONFIG_IRCOMM
 	ircomm_init();
-	irvtd_init();
-#endif
-
-#ifdef CONFIG_IRLPT_CLIENT
-	irlpt_client_init();
-#endif
-
-#ifdef CONFIG_IRLPT_SERVER
-	irlpt_server_init();
+	ircomm_tty_init();
 #endif
 
 #ifdef CONFIG_IRDA_COMPRESSION
@@ -252,7 +260,7 @@
 #ifdef MODULE
 void irda_cleanup(void)
 {
-	misc_deregister( &irda.dev);
+	misc_deregister(&irda.dev);
 
 #ifdef CONFIG_SYSCTL
 	irda_sysctl_unregister();
@@ -261,7 +269,6 @@
 #ifdef CONFIG_PROC_FS
 	irda_proc_unregister();
 #endif
-
 	/* Remove higher layers */
 	irttp_cleanup();
 	iriap_cleanup();
@@ -296,7 +303,7 @@
  *    Used for initializing the notify structure
  *
  */
-void irda_notify_init( struct notify_t *notify)
+void irda_notify_init(notify_t *notify)
 {
 	notify->data_indication = NULL;
 	notify->udata_indication = NULL;
@@ -305,7 +312,7 @@
 	notify->disconnect_indication = NULL;
 	notify->flow_indication = NULL;
 	notify->instance = NULL;
-	strncpy( notify->name, "Unknown", NOTIFY_MAX_NAME);
+	strncpy(notify->name, "Unknown", NOTIFY_MAX_NAME);
 }
 
 /*
@@ -322,10 +329,8 @@
 	struct irmanager_event event;
 
 	/* Make sure irmanager is running */
-	if ( !irda.in_use) {
-		printk( KERN_ERR "irmanager is not running!\n");
+	if (!irda.in_use)
 		return;
-	}
 
 	/* Make new todo event */
 	new = (struct irda_todo *) kmalloc( sizeof(struct irda_todo),
@@ -340,12 +345,12 @@
 	new->param = param;
 	
 	/* Queue todo */
-	enqueue_last( &irda.todo_queue, (QUEUE *) new);
+	enqueue_last(&irda.todo_queue, (queue_t *) new);
 
 	event.event = EVENT_NEED_PROCESS_CONTEXT;
 
 	/* Notify the user space manager */
-	irmanager_notify( &event);
+	irmanager_notify(&event);
 }
 
 /*
@@ -358,13 +363,11 @@
 {
 	struct irda_event *new;
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
-
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+	
 	/* Make sure irmanager is running */
-	if ( !irda.in_use) {
-		printk( KERN_ERR "irmanager is not running!\n");
+	if (!irda.in_use)
 		return;
-	}
 
 	/* Make new IrDA Event */
 	new = (struct irda_event *) kmalloc( sizeof(struct irda_event),
@@ -372,28 +375,29 @@
 	if ( new == NULL) {
 		return;	
 	}
-	memset( new, 0, sizeof( struct irda_event));
+	memset(new, 0, sizeof( struct irda_event));
 	new->event = *event;
 	
 	/* Queue event */
-	enqueue_last( &irda.event_queue, (QUEUE *) new);
+	enqueue_last(&irda.event_queue, (queue_t *) new);
 	
 	/* Wake up irmanager sleeping on read */
-	wake_up_interruptible( &irda.wait_queue);
+	wake_up_interruptible(&irda.wait_queue);
 }
 
 static int irda_open( struct inode * inode, struct file *file)
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG( 4, __FUNCTION__ "()\n");
 
-	if ( irda.in_use) {
-		DEBUG( 0, __FUNCTION__ "(), irmanager is already running!\n");
+	if (irda.in_use) {
+		IRDA_DEBUG(0, __FUNCTION__ 
+			   "(), irmanager is already running!\n");
 		return -1;
 	}
 	irda.in_use = TRUE;
 		
 	MOD_INC_USE_COUNT;
-
+	
 	return 0;
 }
 
@@ -403,62 +407,62 @@
  *    Ioctl, used by irmanager to ...
  *
  */
-static int irda_ioctl( struct inode *inode, struct file *filp, 
-		       unsigned int cmd, unsigned long arg)
+static int irda_ioctl(struct inode *inode, struct file *filp, 
+		      unsigned int cmd, unsigned long arg)
 {
 	struct irda_todo *todo;
 	int err = 0;
 	int size = _IOC_SIZE(cmd);
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	if ( _IOC_DIR(cmd) & _IOC_READ)
+	
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+	
+	if (_IOC_DIR(cmd) & _IOC_READ)
 		err = verify_area( VERIFY_WRITE, (void *) arg, size);
-	else if ( _IOC_DIR(cmd) & _IOC_WRITE)
+	else if (_IOC_DIR(cmd) & _IOC_WRITE)
 		err = verify_area( VERIFY_READ, (void *) arg, size);
-	if ( err)
+	if (err)
 		return err;
 	
-	switch( cmd) {
+	switch (cmd) {
 	case IRMGR_IOCTNPC:
 		/* Got process context! */
-		DEBUG( 4, __FUNCTION__ "(), got process context!\n");
-
-		while (( todo = (struct irda_todo *) dequeue_first( 
+		IRDA_DEBUG(4, __FUNCTION__ "(), got process context!\n");
+		
+		while ((todo = (struct irda_todo *) dequeue_first( 
 			&irda.todo_queue)) != NULL)
 		{
-			todo->callback( todo->self, todo->param);
+			todo->callback(todo->self, todo->param);
 
-			kfree( todo);
+			kfree(todo);
 		}
 		break;
 
 	default:
 		return -ENOIOCTLCMD;
 	}
-
+	
 	return 0;
 }
 
-static int irda_close( struct inode *inode, struct file *file)
+static int irda_close(struct inode *inode, struct file *file)
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	MOD_DEC_USE_COUNT;
-
+	
 	irda.in_use = FALSE;
 
 	return 0;
 }
 
-static ssize_t irda_read( struct file *file, char *buffer, size_t count, 
-			  loff_t *noidea)
+static ssize_t irda_read(struct file *file, char *buffer, size_t count, 
+			 loff_t *noidea)
 {
 	struct irda_event *event;
 	unsigned long flags;
 	int len;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	/* * Go to sleep and wait for event if there is no event to be read! */
 	save_flags( flags);
@@ -471,31 +475,33 @@
 	 *  Ensure proper reaction to signals, and screen out 
 	 *  blocked signals (page 112. linux device drivers)
 	 */
-	if ( signal_pending( current))
+	if (signal_pending( current))
 		return -ERESTARTSYS;
 
 	event = (struct irda_event *) dequeue_first( &irda.event_queue);
+	if (!event)
+		return 0;
 
 	len = sizeof(struct irmanager_event);
-	copy_to_user( buffer, &event->event, len);
+	copy_to_user(buffer, &event->event, len);
 
 	/* Finished with event */
-	kfree( event);
+	kfree(event);
 
 	return len;
 }
 
-static ssize_t irda_write( struct file *file, const char *buffer,
-			   size_t count, loff_t *noidea)
+static ssize_t irda_write(struct file *file, const char *buffer,
+			  size_t count, loff_t *noidea)
 {
-	DEBUG( 0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 	
 	return 0;
 }
 
-static u_int irda_poll( struct file *file, poll_table *wait)
+static u_int irda_poll(struct file *file, poll_table *wait)
 {
-	DEBUG( 0, __FUNCTION__ "(), Sorry not implemented yet!\n");
+	IRDA_DEBUG(0, __FUNCTION__ "(), Sorry not implemented yet!\n");
 
 	return 0;
 }
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irproc.c linux.15p9/net/irda/irproc.c
--- linux.vanilla/net/irda/irproc.c	Sat Aug 14 02:26:54 1999
+++ linux.15p9/net/irda/irproc.c	Tue Jan 18 01:08:19 2000
@@ -6,10 +6,11 @@
  * Status:        Experimental.
  * Author:        Thomas Davis, <ratbert@radiks.net>
  * Created at:    Sat Feb 21 21:33:24 1998
- * Modified at:   Fri May  7 08:06:49 1999
+ * Modified at:   Wed Jan  5 22:45:14 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     Copyright (c) 1998-1999, Thomas Davis, <ratbert@radiks.net>, 
+ *
+ *     Copyright (c) 1998-2000, Dag Brattli <dagb@cs.uit.no>
+ *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>, 
  *     All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
@@ -22,6 +23,9 @@
  *     
  ********************************************************************/
 
+#define __NO_VERSION__    /* irmod.c defines module_kernel_version */
+#include <linux/module.h>
+
 #include <linux/miscdevice.h>
 #include <linux/proc_fs.h>
 
@@ -30,8 +34,6 @@
 #include <net/irda/irlap.h>
 #include <net/irda/irlmp.h>
 
-extern int irda_device_proc_read(char *buf, char **start, off_t offset, 
-				 int len, int unused);
 extern int irlap_proc_read(char *buf, char **start, off_t offset, int len, 
 			   int unused);
 extern int irlmp_proc_read(char *buf, char **start, off_t offset, int len, 
@@ -42,18 +44,6 @@
 			   int unused);
 extern int discovery_proc_read(char *buf, char **start, off_t offset, int len, 
 			       int unused);
-static int proc_discovery_read(char *buf, char **start, off_t offset, int len,
-			       int unused);
-
-/* enum irda_directory_inos { */
-/* 	PROC_IRDA_LAP = 1, */
-/* 	PROC_IRDA_LMP, */
-/* 	PROC_IRDA_TTP, */
-/* 	PROC_IRDA_LPT, */
-/* 	PROC_IRDA_COMM, */
-/*  	PROC_IRDA_IRDA_DEVICE, */
-/* 	PROC_IRDA_IRIAS */
-/* }; */
 
 struct irda_entry {
 	char *name;
@@ -64,7 +54,6 @@
  
 static struct irda_entry dir[] = {
 	{"discovery",	discovery_proc_read},
-	{"irda_device",	irda_device_proc_read},
 	{"irttp",	irttp_proc_read},
 	{"irlmp",	irlmp_proc_read},
 	{"irlap",	irlap_proc_read},
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irqueue.c linux.15p9/net/irda/irqueue.c
--- linux.vanilla/net/irda/irqueue.c	Sat Aug 14 02:25:48 1999
+++ linux.15p9/net/irda/irqueue.c	Tue Jan 18 01:08:19 2000
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Jun  9 13:29:31 1998
- * Modified at:   Thu Mar 11 13:27:04 1999
+ * Modified at:   Sun Dec 12 13:48:22 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (C) 1998, Aage Kvalnes <aage@cs.uit.no>
+ *     Copyright (C) 1998-1999, Aage Kvalnes <aage@cs.uit.no>
  *     Copyright (C) 1998, Dag Brattli, 
  *     All Rights Reserved.
  *
@@ -36,7 +36,7 @@
 #include <net/irda/irqueue.h>
 #include <net/irda/irmod.h>
 
-static QUEUE *dequeue_general( QUEUE **queue, QUEUE* element);
+static queue_t *dequeue_general( queue_t **queue, queue_t* element);
 static __u32 hash( char* name);
 
 /*
@@ -50,8 +50,6 @@
 	hashbin_t* hashbin;
 	int i;
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
 	/*
 	 * Allocate new hashbin
 	 */
@@ -81,22 +79,22 @@
  */
 int hashbin_clear( hashbin_t* hashbin, FREE_FUNC free_func)
 {
-	QUEUE* queue;
+	queue_t* queue;
 	int i;
 	
-	ASSERT( hashbin != NULL, return -1;);
-	ASSERT( hashbin->magic == HB_MAGIC, return -1;);
+	ASSERT(hashbin != NULL, return -1;);
+	ASSERT(hashbin->magic == HB_MAGIC, return -1;);
 
 	/*
 	 * Free the entries in the hashbin
 	 */
-	for ( i = 0; i < HASHBIN_SIZE; i ++ ) {
-		queue = dequeue_first( (QUEUE**) &hashbin->hb_queue[ i]);
-		while( queue ) {
-			if ( free_func)
-				(*free_func)( queue );
+	for (i = 0; i < HASHBIN_SIZE; i ++ ) {
+		queue = dequeue_first( (queue_t**) &hashbin->hb_queue[i]);
+		while (queue) {
+			if (free_func)
+				(*free_func)(queue);
 			queue = dequeue_first( 
-				(QUEUE**) &hashbin->hb_queue[ i]);
+				(queue_t**) &hashbin->hb_queue[i]);
 		}
 	}
 	hashbin->hb_size = 0;
@@ -114,22 +112,23 @@
  */
 int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func)
 {
+	queue_t* queue;
 	int i;
-	QUEUE* queue;
 
-	DEBUG( 4, "hashbin_destroy()\n");
+	ASSERT(hashbin != NULL, return -1;);
+	ASSERT(hashbin->magic == HB_MAGIC, return -1;);
 	
 	/*
 	 *  Free the entries in the hashbin, TODO: use hashbin_clear when
 	 *  it has been shown to work
 	 */
-	for ( i = 0; i < HASHBIN_SIZE; i ++ ) {
-		queue = dequeue_first( (QUEUE**) &hashbin->hb_queue[ i ] );
-		while( queue ) {
-			if ( free_func)
-				(*free_func)( queue );
+	for (i = 0; i < HASHBIN_SIZE; i ++ ) {
+		queue = dequeue_first((queue_t**) &hashbin->hb_queue[i]);
+		while (queue ) {
+			if (free_func)
+				(*free_func)(queue);
 			queue = dequeue_first( 
-				(QUEUE**) &hashbin->hb_queue[ i ]);
+				(queue_t**) &hashbin->hb_queue[i]);
 		}
 	}
 	
@@ -137,7 +136,7 @@
 	 *  Free the hashbin structure
 	 */
 	hashbin->magic = ~HB_MAGIC;
-	kfree( hashbin );
+	kfree(hashbin);
 
 	return 0;
 }
@@ -148,28 +147,28 @@
  *    Lock the hashbin
  *
  */
-void hashbin_lock( hashbin_t* hashbin, __u32 hashv, char* name, 
-		   unsigned long flags)
+void hashbin_lock(hashbin_t* hashbin, __u32 hashv, char* name, 
+		  unsigned long flags)
 {
 	int bin;
 	
-	DEBUG( 0, "hashbin_lock\n");
+	IRDA_DEBUG(0, "hashbin_lock\n");
 
-	ASSERT( hashbin != NULL, return;);
-	ASSERT( hashbin->magic == HB_MAGIC, return;);
+	ASSERT(hashbin != NULL, return;);
+	ASSERT(hashbin->magic == HB_MAGIC, return;);
 
 	/*
 	 * Locate hashbin
 	 */
-	if ( name )
-		hashv = hash( name );
-	bin = GET_HASHBIN( hashv);
+	if (name)
+		hashv = hash(name);
+	bin = GET_HASHBIN(hashv);
 	
 	/* Synchronize */
 	if ( hashbin->hb_type & HB_GLOBAL )
-		spin_lock_irqsave( &hashbin->hb_mutex[ bin], flags);
+		spin_lock_irqsave(&hashbin->hb_mutex[ bin], flags);
 	else {
-		save_flags( flags);
+		save_flags(flags);
 		cli();
 	}
 }
@@ -185,7 +184,7 @@
 {
 	int bin;
 
-	DEBUG(0, "hashbin_unlock()\n");
+	IRDA_DEBUG(0, "hashbin_unlock()\n");
 
 	ASSERT(hashbin != NULL, return;);
 	ASSERT(hashbin->magic == HB_MAGIC, return;);
@@ -211,12 +210,12 @@
  *    Insert an entry into the hashbin
  *
  */
-void hashbin_insert( hashbin_t* hashbin, QUEUE* entry, __u32 hashv, char* name)
+void hashbin_insert(hashbin_t* hashbin, queue_t* entry, __u32 hashv, char* name)
 {
 	unsigned long flags = 0;
 	int bin;
 
-	DEBUG( 4, __FUNCTION__"()\n");
+	IRDA_DEBUG( 4, __FUNCTION__"()\n");
 
 	ASSERT( hashbin != NULL, return;);
 	ASSERT( hashbin->magic == HB_MAGIC, return;);
@@ -251,7 +250,7 @@
 	 */
 	if ( hashbin->hb_type & HB_SORTED) {
 	} else {
-		enqueue_first( (QUEUE**) &hashbin->hb_queue[ bin ],
+		enqueue_first( (queue_t**) &hashbin->hb_queue[ bin ],
 			       entry);
 	}
 	hashbin->hb_size++;
@@ -276,9 +275,9 @@
 {
 	int bin, found = FALSE;
 	unsigned long flags = 0;
-	QUEUE* entry;
+	queue_t* entry;
 
-	DEBUG( 4, "hashbin_find()\n");
+	IRDA_DEBUG( 4, "hashbin_find()\n");
 
 	ASSERT( hashbin != NULL, return NULL;);
 	ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
@@ -343,7 +342,7 @@
 void *hashbin_remove_first( hashbin_t *hashbin)
 {
 	unsigned long flags;
-	QUEUE *entry = NULL;
+	queue_t *entry = NULL;
 
 	save_flags(flags);
 	cli();
@@ -368,9 +367,9 @@
 {
 	int bin, found = FALSE;
 	unsigned long flags = 0;
-	QUEUE* entry;
+	queue_t* entry;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG( 4, __FUNCTION__ "()\n");
 
 	ASSERT( hashbin != NULL, return NULL;);
 	ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
@@ -422,8 +421,8 @@
 	 * If entry was found, dequeue it
 	 */
 	if ( found ) {
-		dequeue_general( (QUEUE**) &hashbin->hb_queue[ bin ],
-				 (QUEUE*) entry );
+		dequeue_general( (queue_t**) &hashbin->hb_queue[ bin ],
+				 (queue_t*) entry );
 		hashbin->hb_size--;
 
 		/*
@@ -458,9 +457,9 @@
  *    called before any calls to hashbin_get_next()!
  *
  */
-QUEUE *hashbin_get_first( hashbin_t* hashbin) 
+queue_t *hashbin_get_first( hashbin_t* hashbin) 
 {
-	QUEUE *entry;
+	queue_t *entry;
 	int i;
 
 	ASSERT( hashbin != NULL, return NULL;);
@@ -490,9 +489,9 @@
  *    NULL when all items have been traversed
  * 
  */
-QUEUE *hashbin_get_next( hashbin_t *hashbin)
+queue_t *hashbin_get_next( hashbin_t *hashbin)
 {
-	QUEUE* entry;
+	queue_t* entry;
 	int bin;
 	int i;
 
@@ -543,9 +542,9 @@
  *    Insert item into end of queue.
  *
  */
-static void __enqueue_last( QUEUE **queue, QUEUE* element)
+static void __enqueue_last( queue_t **queue, queue_t* element)
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG( 4, __FUNCTION__ "()\n");
 
 	/*
 	 * Check if queue is empty.
@@ -567,7 +566,7 @@
 	}	
 }
 
-inline void enqueue_last( QUEUE **queue, QUEUE* element)
+inline void enqueue_last( queue_t **queue, queue_t* element)
 {
 	unsigned long flags;
 	
@@ -585,10 +584,10 @@
  *    Insert item first in queue.
  *
  */
-void enqueue_first(QUEUE **queue, QUEUE* element)
+void enqueue_first(queue_t **queue, queue_t* element)
 {
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG( 4, __FUNCTION__ "()\n");
 
 	/*
 	 * Check if queue is empty.
@@ -617,9 +616,9 @@
  *    Insert a queue (list) into the start of the first queue
  *
  */
-void enqueue_queue( QUEUE** queue, QUEUE** list )
+void enqueue_queue( queue_t** queue, queue_t** list )
 {
-	QUEUE* tmp;
+	queue_t* tmp;
 	
 	/*
 	 * Check if queue is empty
@@ -644,9 +643,9 @@
  *
  */
 #if 0
-static void enqueue_second(QUEUE **queue, QUEUE* element)
+static void enqueue_second(queue_t **queue, queue_t* element)
 {
-	DEBUG( 0, "enqueue_second()\n");
+	IRDA_DEBUG( 0, "enqueue_second()\n");
 
 	/*
 	 * Check if queue is empty.
@@ -675,11 +674,11 @@
  *    Remove first entry in queue
  *
  */
-QUEUE *dequeue_first(QUEUE **queue)
+queue_t *dequeue_first(queue_t **queue)
 {
-	QUEUE *ret;
+	queue_t *ret;
 
-	DEBUG( 4, "dequeue_first()\n");
+	IRDA_DEBUG( 4, "dequeue_first()\n");
 	
 	/*
 	 * Set return value
@@ -716,11 +715,11 @@
  *
  *
  */
-static QUEUE *dequeue_general(QUEUE **queue, QUEUE* element)
+static queue_t *dequeue_general(queue_t **queue, queue_t* element)
 {
-	QUEUE *ret;
+	queue_t *ret;
 	
-	DEBUG( 4, "dequeue_general()\n");
+	IRDA_DEBUG( 4, "dequeue_general()\n");
 	
 	/*
 	 * Set return value
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irsysctl.c linux.15p9/net/irda/irsysctl.c
--- linux.vanilla/net/irda/irsysctl.c	Sat Aug 14 02:26:54 1999
+++ linux.15p9/net/irda/irsysctl.c	Tue Jan 18 01:08:19 2000
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun May 24 22:12:06 1998
- * Modified at:   Thu May  6 21:32:46 1999
+ * Modified at:   Fri Jun  4 02:50:15 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997, 1999 Dag Brattli, All Rights Reserved.
@@ -31,13 +31,15 @@
 #include <net/irda/irda.h>
 
 #define NET_IRDA 412 /* Random number */
-enum { DISCOVERY=1, DEVNAME, COMPRESSION, DEBUG, SLOTS, SLOT_TIMEOUT };
+enum { DISCOVERY=1, DEVNAME, COMPRESSION, DEBUG, SLOTS, DISCOVERY_TIMEOUT, 
+       SLOT_TIMEOUT };
 
-extern int sysctl_discovery;
-extern int sysctl_discovery_slots;
-extern int sysctl_slot_timeout;
-extern int sysctl_fast_poll_increase;
-int sysctl_compression = 0;
+extern int  sysctl_discovery;
+extern int  sysctl_discovery_slots;
+extern int  sysctl_discovery_timeout;
+extern int  sysctl_slot_timeout;
+extern int  sysctl_fast_poll_increase;
+int         sysctl_compression = 0;
 extern char sysctl_devname[];
 
 #ifdef CONFIG_IRDA_DEBUG
@@ -62,6 +64,8 @@
 #endif
 	{ SLOTS, "discovery_slots", &sysctl_discovery_slots,
 	  sizeof(int), 0644, NULL, &proc_dointvec },
+	{ DISCOVERY_TIMEOUT, "discovery_timeout", &sysctl_discovery_timeout,
+	  sizeof(int), 0644, NULL, &proc_dointvec },
 	{ SLOT_TIMEOUT, "slot_timeout", &sysctl_slot_timeout,
 	  sizeof(int), 0644, NULL, &proc_dointvec },
 	{ 0 }
@@ -89,9 +93,10 @@
  */
 int irda_sysctl_register(void)
 {
-	irda_table_header = register_sysctl_table( irda_root_table, 0);
-	if ( !irda_table_header)
+	irda_table_header = register_sysctl_table(irda_root_table, 0);
+	if (!irda_table_header)
 		return -ENOMEM;
+
 	return 0;
 }
 
@@ -103,7 +108,7 @@
  */
 void irda_sysctl_unregister(void) 
 {
-	unregister_sysctl_table( irda_table_header);
+	unregister_sysctl_table(irda_table_header);
 }
 
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/irttp.c linux.15p9/net/irda/irttp.c
--- linux.vanilla/net/irda/irttp.c	Sat Aug 14 02:26:54 1999
+++ linux.15p9/net/irda/irttp.c	Mon Feb  7 12:17:43 2000
@@ -3,13 +3,13 @@
  * Filename:      irttp.c
  * Version:       1.2
  * Description:   Tiny Transport Protocol (TTP) implementation
- * Status:        Experimental.
+ * Status:        Stable
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:31 1997
- * Modified at:   Mon May 31 10:29:56 1999
+ * Modified at:   Sun Jan 30 14:30:32 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
+ *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>, 
  *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
@@ -32,7 +32,9 @@
 
 #include <net/irda/irda.h>
 #include <net/irda/irmod.h>
+#include <net/irda/irlap.h>
 #include <net/irda/irlmp.h>
+#include <net/irda/parameters.h>
 #include <net/irda/irttp.h>
 
 static struct irttp_cb *irttp = NULL;
@@ -58,6 +60,16 @@
 static void irttp_fragment_skb(struct tsap_cb *self, struct sk_buff *skb);
 static void irttp_start_todo_timer(struct tsap_cb *self, int timeout);
 static struct sk_buff *irttp_reassemble_skb(struct tsap_cb *self);
+static int irttp_param_max_sdu_size(void *instance, irda_param_t *param, 
+				    int get);
+
+/* Information for parsing parameters in IrTTP */
+static pi_minor_info_t pi_minor_call_table[] = {
+	{ NULL, 0 },                                             /* 0x00 */
+	{ irttp_param_max_sdu_size, PV_INTEGER | PV_BIG_ENDIAN } /* 0x01 */
+};
+static pi_major_info_t pi_major_call_table[] = {{ pi_minor_call_table, 2 }};
+static pi_param_info_t param_info = { pi_major_call_table, 1, 0x0f, 4 };
 
 /*
  * Function irttp_init (void)
@@ -65,7 +77,7 @@
  *    Initialize the IrTTP layer. Called by module initialization code
  *
  */
-__initfunc(int irttp_init(void))
+int __init irttp_init(void)
 {
 	/* Initialize the irttp structure. */
 	if (irttp == NULL) {
@@ -79,7 +91,7 @@
 
 	irttp->tsaps = hashbin_new(HB_LOCAL);
 	if (!irttp->tsaps) {
-		printk(KERN_WARNING "IrDA: Can't allocate IrTTP hashbin!\n");
+		ERROR(__FUNCTION__ "(), can't allocate IrTTP hashbin!\n");
 		return -ENOMEM;
 	}
 	
@@ -118,22 +130,22 @@
  *
  *    Create TSAP connection endpoint,
  */
-struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, 
-				struct notify_t *notify) 
+struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify) 
 {
-	struct notify_t ttp_notify;
 	struct tsap_cb *self;
 	struct lsap_cb *lsap;
+	notify_t ttp_notify;
 
 	ASSERT(irttp != NULL, return NULL;);
 	ASSERT(irttp->magic == TTP_MAGIC, return NULL;);
 
 	self = kmalloc(sizeof(struct tsap_cb), GFP_ATOMIC);
 	if (self == NULL) {
-		DEBUG(0, __FUNCTION__ "(), unable to kmalloc!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), unable to kmalloc!\n");
 		return NULL;
 	}
 	memset(self, 0, sizeof(struct tsap_cb));
+	spin_lock_init(&self->lock);
 
 	init_timer(&self->todo_timer);
 
@@ -156,9 +168,9 @@
 	/*
 	 *  Create LSAP at IrLMP layer
 	 */
-	lsap = irlmp_open_lsap(stsap_sel, &ttp_notify);
+	lsap = irlmp_open_lsap(stsap_sel, &ttp_notify, 0);
 	if (lsap == NULL) {
-		printk(KERN_ERR "IrTTP, Unable to get LSAP!!\n");
+		WARNING(__FUNCTION__ "(), unable to allocate LSAP!!\n");
 		return NULL;
 	}
 	
@@ -168,12 +180,12 @@
 	 *  the stsap_sel we have might not be valid anymore
 	 */
 	self->stsap_sel = lsap->slsap_sel;
-	DEBUG(4, __FUNCTION__ "(), stsap_sel=%02x\n", self->stsap_sel);
+	IRDA_DEBUG(4, __FUNCTION__ "(), stsap_sel=%02x\n", self->stsap_sel);
 
 	self->notify = *notify;
 	self->lsap = lsap;
 
-	hashbin_insert(irttp->tsaps, (QUEUE *) self, (int) self, NULL);
+	hashbin_insert(irttp->tsaps, (queue_t *) self, (int) self, NULL);
 
 	if (credit > TTP_MAX_QUEUE)
 		self->initial_credit = TTP_MAX_QUEUE;
@@ -217,7 +229,7 @@
 {
 	struct tsap_cb *tsap;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
@@ -226,11 +238,11 @@
 	if (self->connected) {
 		/* Check if disconnect is not pending */
 		if (!self->disconnect_pend) {
-			DEBUG(0, __FUNCTION__ "(), TSAP still connected!\n");
+			IRDA_DEBUG(0, __FUNCTION__ "(), TSAP still connected!\n");
 			irttp_disconnect_request(self, NULL, P_NORMAL);
 		}
 		self->close_pend = TRUE;
-		irttp_start_todo_timer(self, 100);
+		irttp_start_todo_timer(self, 1*HZ);
 
 		return 0; /* Will be back! */
 	}
@@ -262,16 +274,16 @@
 	ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
 	ASSERT(skb != NULL, return -1;);
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	/* Check that nothing bad happens */
 	if ((skb->len == 0) || (!self->connected)) {
-		DEBUG(1, __FUNCTION__ "(), No data, or not connected\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), No data, or not connected\n");
 		return -1;
 	}
 	
 	if (skb->len > self->max_seg_size) {
-		DEBUG(1, __FUNCTION__ "(), UData is to large for IrLAP!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), UData is to large for IrLAP!\n");
 		return -1;
 	}
 		    
@@ -291,13 +303,9 @@
 {
 	__u8 *frame;
 
-	ASSERT(self != NULL, return -1;);
-	ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
-	ASSERT(skb != NULL, return -1;);
-
 	/* Check that nothing bad happens */
 	if ((skb->len == 0) || (!self->connected)) {
-		ERROR(__FUNCTION__ "(), No data, or not connected\n");
+		WARNING(__FUNCTION__ "(), No data, or not connected\n");
 		return -ENOTCONN;
 	}
 
@@ -316,7 +324,7 @@
 	 *  TxMaxSduSize 
 	 */
 	if ((self->tx_max_sdu_size != 0) && 
-	    (self->tx_max_sdu_size != SAR_UNBOUND) && 
+	    (self->tx_max_sdu_size != TTP_SAR_UNBOUND) && 
 	    (skb->len > self->tx_max_sdu_size))
 	{
 		ERROR(__FUNCTION__ "(), SAR enabled, "
@@ -355,7 +363,7 @@
 
 	/* Check if we can accept more data from client */
 	if ((!self->tx_sdu_busy) && 
-	    (skb_queue_len(&self->tx_queue) > HIGH_THRESHOLD)) {
+	    (skb_queue_len(&self->tx_queue) > TTP_HIGH_THRESHOLD)) {
 		
 		/* Tx queue filling up, so stop client */
 		self->tx_sdu_busy = TRUE;
@@ -375,25 +383,36 @@
 /*
  * Function irttp_run_tx_queue (self)
  *
- *    If possible, transmit a frame queued for transmission.
+ *    Transmit packets queued for transmission (if possible)
  *
  */
 static void irttp_run_tx_queue(struct tsap_cb *self) 
 {
-	struct sk_buff *skb = NULL;
+	struct sk_buff *skb;
 	unsigned long flags;
 	int n;
 
 	if (irda_lock(&self->tx_queue_lock) == FALSE)
 		return;
 
-	while ((self->send_credit > 0) && !skb_queue_empty(&self->tx_queue)) {
-		skb = skb_dequeue(&self->tx_queue);
-		ASSERT(skb != NULL, return;);
-		
-		/* Make room for TTP header */
-		ASSERT(skb_headroom(skb) >= TTP_HEADER, return;);
-				
+	/* Try to send out frames as long as we have credits */
+	while ((self->send_credit > 0) &&
+	       (skb = skb_dequeue(&self->tx_queue)))
+	{
+		/* 
+		 * Make sure we don't flood IrLAP with frames just because
+		 * the remote device has given us a lot of credits
+		 */
+		if (irlmp_get_lap_tx_queue_len(self->lsap) > LAP_MAX_QUEUE) {
+			/* Re-queue packet */
+			skb_queue_head(&self->tx_queue, skb);
+
+			/* Try later. Maybe IrLAP could notify us? */
+			irttp_start_todo_timer(self, MSECS_TO_JIFFIES(10));
+			
+			break;
+		}
+
 		/*
 		 *  Since we can transmit and receive frames concurrently, 
 		 *  the code below is a critical region and we must assure that
@@ -425,7 +444,7 @@
 
 		/* Check if we can accept more frames from client */
 		if ((self->tx_sdu_busy) && 
-		    (skb_queue_len(&self->tx_queue) < LOW_THRESHOLD)) 
+		    (skb_queue_len(&self->tx_queue) < TTP_LOW_THRESHOLD)) 
 		{
 			self->tx_sdu_busy = FALSE;
 			
@@ -435,9 +454,7 @@
 					FLOW_START);
 		}
 	}
-	
-	/* Reset lock */
-	self->tx_queue_lock = 0;
+	self->tx_queue_lock = 0; /* Reset lock */
 }
 
 /*
@@ -455,8 +472,8 @@
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);	
 
-	DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n", 
-	       self->send_credit, self->avail_credit, self->remote_credit);
+	IRDA_DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n", 
+		   self->send_credit, self->avail_credit, self->remote_credit);
 	
 	/* Give credit to peer */
 	tx_skb = dev_alloc_skb(64);
@@ -503,7 +520,7 @@
 {
 	struct tsap_cb *self;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	self = (struct tsap_cb *) instance;
 
@@ -512,16 +529,18 @@
 	ASSERT(skb != NULL, return -1;);
 
 	/* Just pass data to layer above */
-	if (self->notify.udata_indication) {
-		self->notify.udata_indication(self->notify.instance, self, skb);
-	}
+	if (self->notify.udata_indication)
+		self->notify.udata_indication(self->notify.instance, self,skb);
+	else
+		dev_kfree_skb(skb);
+
 	self->stats.rx_packets++;
 
 	return 0;
 }
 
 /*
- * Function irttp_data_indication (handle, skb)
+ * Function irttp_data_indication (instance, sap, skb)
  *
  *    Receive segment from IrLMP. 
  *
@@ -534,20 +553,15 @@
 
 	self = (struct tsap_cb *) instance;
 
-	ASSERT(self != NULL, return -1;);
-	ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
-
 	n = skb->data[0] & 0x7f;     /* Extract the credits */
 
 	self->stats.rx_packets++;
 
 	/* 
-	 *  Data or dataless frame? Dataless frames only contain the 
-	 *  TTP_HEADER
+	 *  Data or dataless packet? Dataless frames contains only the 
+	 *  TTP_HEADER. 
 	 */
-	if (skb->len == 1)
-		self->send_credit += n;	/* Dataless flowdata TTP-PDU */
-	else {
+	if (skb->len > 1) {
 		/* Deal with inbound credit */
 		self->send_credit += n;
 		self->remote_credit--;
@@ -557,7 +571,10 @@
 		 *  more bit, so the defragment routing knows what to do
 		 */
 		skb_queue_tail(&self->rx_queue, skb);
-	} 
+	} else {
+		self->send_credit += n;	/* Dataless flowdata TTP-PDU */
+		dev_kfree_skb(skb);
+	}
 
 	irttp_run_rx_queue(self);
 
@@ -565,18 +582,22 @@
 	 *  Give avay some credits to peer? 
 	 */
 	if ((skb_queue_empty(&self->tx_queue)) && 
-	    (self->remote_credit < LOW_THRESHOLD) && 
+	    (self->remote_credit < TTP_LOW_THRESHOLD) && 
 	    (self->avail_credit > 0)) 
 	{
 		/* Schedule to start immediately after this thread */
 		irttp_start_todo_timer(self, 0);
+		/*irttp_give_credit(self);*/
 	}
-
-	/* If peer has given us some credites and we didn't have anyone
-         * from before, the we need to shedule the tx queue? 
+	
+	/* 
+	 * If the peer device has given us some credits and we didn't have
+         * anyone from before, the we need to shedule the tx queue?  
 	 */
-	if (self->send_credit == n)
+	if (self->send_credit == n) {
+		/*irttp_run_tx_queue(self);*/
 		irttp_start_todo_timer(self, 0);
+	}
 	return 0;
 }
 
@@ -589,24 +610,24 @@
  */
 void irttp_flow_request(struct tsap_cb *self, LOCAL_FLOW flow)
 {
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(1, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 
 	switch (flow) {
 	case FLOW_STOP:
-		DEBUG(1, __FUNCTION__ "(), flow stop\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), flow stop\n");
 		self->rx_sdu_busy = TRUE;
 		break;
 	case FLOW_START:
-		DEBUG(1, __FUNCTION__ "(), flow start\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), flow start\n");
 		self->rx_sdu_busy = FALSE;
 		
 		irttp_run_rx_queue(self);
 		break;
 	default:
-		DEBUG(1, __FUNCTION__ "(), Unknown flow command!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown flow command!\n");
 	}
 }
 	
@@ -625,11 +646,14 @@
 	__u8 *frame;
 	__u8 n;
 	
-	DEBUG(4, __FUNCTION__ "(), max_sdu_size=%d\n", max_sdu_size); 
+	IRDA_DEBUG(4, __FUNCTION__ "(), max_sdu_size=%d\n", max_sdu_size); 
 	
-	ASSERT(self != NULL, return -1;);
-	ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+	ASSERT(self != NULL, return -EBADR;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return -EBADR;);
 
+	if (self->connected)
+		return -EISCONN;
+	
 	/* Any userdata supplied? */
 	if (userdata == NULL) {
 		skb = dev_alloc_skb(64);
@@ -705,17 +729,16 @@
  *
  */
 static void irttp_connect_confirm(void *instance, void *sap, 
-				  struct qos_info *qos,
-				  __u32 max_seg_size, __u8 max_header_size,
-				  struct sk_buff *skb) 
+				  struct qos_info *qos, __u32 max_seg_size,
+				  __u8 max_header_size, struct sk_buff *skb) 
 {
 	struct tsap_cb *self;
 	int parameters;
-	__u8 *frame;
-	__u8 plen, pi, pl;
+	int ret;
+	__u8 plen;
 	__u8 n;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	self = (struct tsap_cb *) instance;
 
@@ -723,7 +746,7 @@
 	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 	ASSERT(skb != NULL, return;);
 
-	self->max_seg_size = max_seg_size;
+	self->max_seg_size = max_seg_size - TTP_HEADER;
 	self->max_header_size = max_header_size + TTP_HEADER;
 
 	/*
@@ -731,63 +754,53 @@
 	 *  negotiated QoS for the link.
 	 */
 	if (qos) {
-		DEBUG(4, "IrTTP, Negotiated BAUD_RATE: %02x\n", 
+		IRDA_DEBUG(4, "IrTTP, Negotiated BAUD_RATE: %02x\n", 
 		       qos->baud_rate.bits);			
-		DEBUG(4, "IrTTP, Negotiated BAUD_RATE: %d bps.\n", 
+		IRDA_DEBUG(4, "IrTTP, Negotiated BAUD_RATE: %d bps.\n", 
 		       qos->baud_rate.value);
 	}
 
-	frame = skb->data;
-	n = frame[0] & 0x7f;
+	n = skb->data[0] & 0x7f;
 	
-	DEBUG(4, __FUNCTION__ "(), Initial send_credit=%d\n", n);
+	IRDA_DEBUG(4, __FUNCTION__ "(), Initial send_credit=%d\n", n);
 	
 	self->send_credit = n;
 	self->tx_max_sdu_size = 0;
 	self->connected = TRUE;
 
-	parameters = frame[0] & 0x80;	
+	parameters = skb->data[0] & 0x80;	
 
 	ASSERT(skb->len >= TTP_HEADER, return;);
 	skb_pull(skb, TTP_HEADER);
-		
+
 	if (parameters) {
-		plen = frame[1];
-		pi   = frame[2];
-		pl   = frame[3];
-
-		switch (pl) {
-		case 1:
-			self->tx_max_sdu_size = *(frame+4);
-			break;
-		case 2:
-			self->tx_max_sdu_size = 
-				be16_to_cpu(get_unaligned((__u16 *)(frame+4)));
-			break;
-		case 4:
-			self->tx_max_sdu_size = 
-				be32_to_cpu(get_unaligned((__u32 *)(frame+4)));
-			break;
-		default:
-			printk(KERN_ERR __FUNCTION__ 
-			       "() illegal value length for max_sdu_size!\n");
-			self->tx_max_sdu_size = 0;
-		};
+		plen = skb->data[0];
 
-		DEBUG(4, __FUNCTION__ "(), RxMaxSduSize=%d\n", 
-		      self->tx_max_sdu_size);
-		
+		ret = irda_param_extract_all(self, skb->data+1,
+					     IRDA_MIN(skb->len-1, plen), 
+					     &param_info);
+
+		/* Any errors in the parameter list? */
+		if (ret < 0) {
+			WARNING(__FUNCTION__ 
+				"(), error extracting parameters\n");
+			dev_kfree_skb(skb);
+
+			/* Do not accept this connection attempt */
+			return;
+		}
 		/* Remove parameters */
-		ASSERT(skb->len >= (plen+1), return;);
-		skb_pull(skb, plen+1);
+		skb_pull(skb, IRDA_MIN(skb->len, plen+1));
 	}
 	
-	DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n", 
+	IRDA_DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n", 
 	      self->send_credit, self->avail_credit, self->remote_credit);
 
+	IRDA_DEBUG(2, __FUNCTION__ "(), MaxSduSize=%d\n", self->tx_max_sdu_size);
+
 	if (self->notify.connect_confirm) {
 		self->notify.connect_confirm(self->notify.instance, self, qos,
-					     self->tx_max_sdu_size, 
+					     self->tx_max_sdu_size,
 					     self->max_header_size, skb);
 	}
 }
@@ -805,8 +818,8 @@
 	struct tsap_cb *self;
 	struct lsap_cb *lsap;
 	int parameters;
-	__u8 *frame;
-	__u8 plen, pi, pl;
+	int ret;
+	__u8 plen;
 	__u8 n;
 
 	self = (struct tsap_cb *) instance;
@@ -817,65 +830,51 @@
 
 	lsap = (struct lsap_cb *) sap;
 
-	self->max_seg_size = max_seg_size;
-
+	self->max_seg_size = max_seg_size - TTP_HEADER;;
 	self->max_header_size = max_header_size+TTP_HEADER;
 
-	DEBUG(4, __FUNCTION__ "(), TSAP sel=%02x\n", self->stsap_sel);
+	IRDA_DEBUG(4, __FUNCTION__ "(), TSAP sel=%02x\n", self->stsap_sel);
 
 	/* Need to update dtsap_sel if its equal to LSAP_ANY */
 	self->dtsap_sel = lsap->dlsap_sel;
 
-	frame = skb->data;
-	n = frame[0] & 0x7f;
+	n = skb->data[0] & 0x7f;
 
 	self->send_credit = n;
 	self->tx_max_sdu_size = 0;
 	
-	parameters = frame[0] & 0x80;
+	parameters = skb->data[0] & 0x80;
 
 	ASSERT(skb->len >= TTP_HEADER, return;);
 	skb_pull(skb, TTP_HEADER);
-		
+
 	if (parameters) {
-		DEBUG(3, __FUNCTION__ "(), Contains parameters!\n");
-		plen = frame[1];
-		pi   = frame[2];
-		pl   = frame[3];
-
-		switch (pl) {
-		case 1:
-			self->tx_max_sdu_size = frame[4];
-			break;
-		case 2:
-			self->tx_max_sdu_size = 
-				be16_to_cpu(get_unaligned((__u16 *)(frame+4)));
-			break;
-		case 4:
-			self->tx_max_sdu_size = 
-				be32_to_cpu(get_unaligned((__u32 *)(frame+4)));
-			break;
-		default:
-			printk(KERN_ERR __FUNCTION__ 
-			       "() illegal value length for max_sdu_size!\n");
-			self->tx_max_sdu_size = 0;
-		};
+		plen = skb->data[0];
 		
-		/* Remove parameters */
-		ASSERT(skb->len >= (plen+1), return;);
-		skb_pull(skb, plen+1);
+		ret = irda_param_extract_all(self, skb->data+1,
+					     IRDA_MIN(skb->len-1, plen), 
+					     &param_info);
+
+		/* Any errors in the parameter list? */
+		if (ret < 0) {
+			WARNING(__FUNCTION__ 
+				"(), error extracting parameters\n");
+			dev_kfree_skb(skb);
+			
+			/* Do not accept this connection attempt */
+			return;
+		}
 
-		DEBUG(3, __FUNCTION__ "(), MaxSduSize=%d\n", 
-		      self->tx_max_sdu_size);
+		/* Remove parameters */
+		skb_pull(skb, IRDA_MIN(skb->len, plen+1));
 	}
 
-	DEBUG(4, __FUNCTION__ "(), initial send_credit=%d\n", n);
-
 	if (self->notify.connect_indication) {
 		self->notify.connect_indication(self->notify.instance, self, 
-						qos, self->rx_max_sdu_size, 
+						qos, self->tx_max_sdu_size, 
 						self->max_header_size, skb);
-	}
+	} else
+		dev_kfree_skb(skb);
 }
 
 /*
@@ -885,24 +884,25 @@
  *    IrLMP!
  * 
  */
-void irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size, 
-			    struct sk_buff *userdata)
+int irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size, 
+			   struct sk_buff *userdata)
 {
 	struct sk_buff *skb;
 	__u8 *frame;
+	int ret;
 	__u8 n;
 
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
 
-	DEBUG(4, __FUNCTION__ "(), Source TSAP selector=%02x\n", 
-	      self->stsap_sel);
+	IRDA_DEBUG(4, __FUNCTION__ "(), Source TSAP selector=%02x\n", 
+		   self->stsap_sel);
 	
 	/* Any userdata supplied? */
 	if (userdata == NULL) {
 		skb = dev_alloc_skb(64);
 		if (!skb)
-			return;
+			return -ENOMEM;
 
 		/* Reserve space for MUX_CONTROL and LAP header */
 		skb_reserve(skb, TTP_MAX_HEADER);
@@ -912,7 +912,7 @@
 		 *  Check that the client has reserved enough space for 
 		 *  headers
 		 */
-		ASSERT(skb_headroom(skb) >= TTP_MAX_HEADER, return;);
+		ASSERT(skb_headroom(skb) >= TTP_MAX_HEADER, return -1;);
 	}
 	
 	self->avail_credit = 0;
@@ -935,13 +935,17 @@
 	/* SAR enabled? */
 	if (max_sdu_size > 0) {
 		ASSERT(skb_headroom(skb) >= (TTP_MAX_HEADER+TTP_SAR_HEADER), 
-		       return;);
+		       return -1;);
 		
 		/* Insert TTP header with SAR parameters */
 		frame = skb_push(skb, TTP_HEADER+TTP_SAR_HEADER);
 		
 		frame[0] = TTP_PARAMETERS | n;
 		frame[1] = 0x04; /* Length */
+
+		/* irda_param_insert(self, IRTTP_MAX_SDU_SIZE, frame+1,  */
+/* 				  TTP_SAR_HEADER, &param_info) */
+		
 		frame[2] = 0x01; /* MaxSduSize */
 		frame[3] = 0x02; /* Value length */
 
@@ -954,7 +958,9 @@
 		frame[0] = n & 0x7f;
 	}
 	 
-	irlmp_connect_response(self->lsap, skb);
+	ret = irlmp_connect_response(self->lsap, skb);
+
+	return ret;
 }
 
 /*
@@ -967,15 +973,15 @@
 {
 	struct tsap_cb *new;
 
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(1, __FUNCTION__ "()\n");
 
 	if (!hashbin_find(irttp->tsaps, (int) orig, NULL)) {
-		DEBUG(0, __FUNCTION__ "(), unable to find TSAP\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), unable to find TSAP\n");
 		return NULL;
 	}
 	new = kmalloc(sizeof(struct tsap_cb), GFP_ATOMIC);
 	if (!new) {
-		DEBUG(0, __FUNCTION__ "(), unable to kmalloc\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), unable to kmalloc\n");
 		return NULL;
 	}
 	/* Dup */
@@ -990,7 +996,7 @@
 	skb_queue_head_init(&new->tx_queue);
 	skb_queue_head_init(&new->rx_fragments);
 
-	hashbin_insert(irttp->tsaps, (QUEUE *) new, (int) new, NULL);
+	hashbin_insert(irttp->tsaps, (queue_t *) new, (int) new, NULL);
 
 	return new;
 }
@@ -1002,32 +1008,31 @@
  *    segments, if any, will be deallocated first
  *
  */
-void irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *userdata, 
-			      int priority)
+int irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *userdata, 
+			     int priority)
 {
 	struct sk_buff *skb;
+	int ret;
 
-	DEBUG(2, __FUNCTION__ "()\n");
-
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
 
 	/* Already disconnected? */
 	if (!self->connected) {
-		DEBUG(4, __FUNCTION__ "(), already disconnected!\n");
-		return;
+		IRDA_DEBUG(4, __FUNCTION__ "(), already disconnected!\n");
+		return -1;
 	}
 
 	/* Disconnect already pending? */
 	if (self->disconnect_pend) {
-		DEBUG(1, __FUNCTION__ "(), disconnect already pending\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), disconnect already pending\n");
 		if (userdata) {
 			dev_kfree_skb(userdata);
 		}
 
 		/* Try to make some progress */
 		irttp_run_rx_queue(self);
-		return;
+		return -1;
 	}
 
 	/*
@@ -1035,7 +1040,7 @@
 	 */
 	if (skb_queue_len(&self->tx_queue) > 0) {
 		if (priority == P_HIGH) {
-			DEBUG(1, __FUNCTION__  "High priority!!()\n" );
+			IRDA_DEBUG(1, __FUNCTION__  "High priority!!()\n" );
 			
 			/* 
 			 *  No need to send the queued data, if we are 
@@ -1057,18 +1062,18 @@
 
 			irttp_run_tx_queue(self);
 
-			irttp_start_todo_timer(self, 100);
-			return;
+			irttp_start_todo_timer(self, MSECS_TO_JIFFIES(1000));
+			return -1;
 		}
 	}
-	DEBUG(1, __FUNCTION__ "(), Disconnecting ...\n");
+	IRDA_DEBUG(1, __FUNCTION__ "(), Disconnecting ...\n");
 
 	self->connected = FALSE;
 	
 	if (!userdata) {
 		skb = dev_alloc_skb(64);
 		if (!skb)
-			return;
+			return -ENOMEM;
 		
 		/* 
 		 *  Reserve space for MUX and LAP header 
@@ -1077,7 +1082,9 @@
 		
 		userdata = skb;
 	}
-	irlmp_disconnect_request(self->lsap, userdata);
+	ret = irlmp_disconnect_request(self->lsap, userdata);
+
+	return ret;
 }
 
 /*
@@ -1087,11 +1094,11 @@
  *
  */
 void irttp_disconnect_indication(void *instance, void *sap, LM_REASON reason, 
-				 struct sk_buff *userdata) 
+				 struct sk_buff *skb) 
 {
 	struct tsap_cb *self;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	self = (struct tsap_cb *) instance;
 	
@@ -1100,11 +1107,22 @@
 	
 	self->connected = FALSE;
 	
-	if (!self->notify.disconnect_indication)
+	/* Check if client has already tried to close the TSAP */
+	if (self->close_pend) {
+		irttp_close_tsap(self);
 		return;
+	}
 
-	self->notify.disconnect_indication(self->notify.instance, self, reason,
-					   userdata);
+	/* No need to notify the client if has already tried to disconnect */
+	if (self->disconnect_pend)
+		return;
+	
+	if (self->notify.disconnect_indication)
+		self->notify.disconnect_indication(self->notify.instance, self,
+						   reason, skb);
+	else
+		if (skb)
+			dev_kfree_skb(skb);
 }
 
 /*
@@ -1118,6 +1136,12 @@
 {
 	int err;
 
+	/* Check if client has already tried to close the TSAP */
+	if (self->close_pend || self->disconnect_pend) {
+		dev_kfree_skb(skb);
+		return;
+	}
+
 	err = self->notify.data_indication(self->notify.instance, self, skb);
 
 	/* Usually the layer above will notify that it's input queue is
@@ -1126,7 +1150,7 @@
 	 * give an error back 
 	 */
 	if (err == -ENOMEM) {
-		DEBUG(0, __FUNCTION__ "() requeueing skb!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "() requeueing skb!\n");
 
 		/* Make sure we take a break */
 		self->rx_sdu_busy = TRUE;
@@ -1151,8 +1175,8 @@
 	struct sk_buff *skb;
 	int more = 0;
 
-	DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n", 
-	       self->send_credit, self->avail_credit, self->remote_credit);
+	IRDA_DEBUG(2, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n", 
+		   self->send_credit, self->avail_credit, self->remote_credit);
 
 	if (irda_lock(&self->rx_queue_lock) == FALSE)
 		return;
@@ -1177,7 +1201,7 @@
 		 * immediately. This can be requested by clients that
 		 * implements byte streams without any message boundaries
 		 */
-		if (self->rx_max_sdu_size == SAR_DISABLE) {
+		if (self->rx_max_sdu_size == TTP_SAR_DISABLE) {
 			irttp_do_data_indication(self, skb);
 			self->rx_sdu_size = 0;
 
@@ -1191,7 +1215,7 @@
 			 *  limits of the maximum size of the rx_sdu
 			 */
 			if (self->rx_sdu_size <= self->rx_max_sdu_size) {
-				DEBUG(4, __FUNCTION__ "(), queueing frag\n");
+				IRDA_DEBUG(4, __FUNCTION__ "(), queueing frag\n");
 				skb_queue_tail(&self->rx_fragments, skb);
 			} else {
 				/* Free the part of the SDU that is too big */
@@ -1203,7 +1227,7 @@
 		 *  This is the last fragment, so time to reassemble!
 		 */
 		if ((self->rx_sdu_size <= self->rx_max_sdu_size) ||
-		    (self->rx_max_sdu_size == SAR_UNBOUND)) 
+		    (self->rx_max_sdu_size == TTP_SAR_UNBOUND)) 
 		{
 			/* 
 			 * A little optimizing. Only queue the fragment if
@@ -1221,7 +1245,7 @@
 			/* Now we can deliver the reassembled skb */
 			irttp_do_data_indication(self, skb);
 		} else {
-			DEBUG(1, __FUNCTION__ "(), Truncated frame\n");
+			IRDA_DEBUG(1, __FUNCTION__ "(), Truncated frame\n");
 			
 			/* Free the part of the SDU that is too big */
 			dev_kfree_skb(skb);
@@ -1246,7 +1270,7 @@
 {
 	struct sk_buff* skb;
 	
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
@@ -1279,10 +1303,10 @@
       	ASSERT(self != NULL, return NULL;);
 	ASSERT(self->magic == TTP_TSAP_MAGIC, return NULL;);
 
-	DEBUG(4, __FUNCTION__ "(), self->rx_sdu_size=%d\n", 
-	      self->rx_sdu_size);
+	IRDA_DEBUG(2, __FUNCTION__ "(), self->rx_sdu_size=%d\n", 
+		   self->rx_sdu_size);
 
-	skb = dev_alloc_skb(self->rx_sdu_size);
+	skb = dev_alloc_skb(TTP_HEADER + self->rx_sdu_size);
 	if (!skb)
 		return NULL;
 
@@ -1302,11 +1326,12 @@
 		
 		dev_kfree_skb(frag);
 	}
-	DEBUG(4, __FUNCTION__ "(), frame len=%d\n", n);
-	/* Set the new length */
+	IRDA_DEBUG(2, __FUNCTION__ "(), frame len=%d\n", n);
 
-	DEBUG(4, __FUNCTION__ "(), rx_sdu_size=%d\n", self->rx_sdu_size);
+	IRDA_DEBUG(2, __FUNCTION__ "(), rx_sdu_size=%d\n", self->rx_sdu_size);
 	ASSERT(n <= self->rx_sdu_size, return NULL;);
+
+	/* Set the new length */
 	skb_trim(skb, n);
 
 	self->rx_sdu_size = 0;
@@ -1325,7 +1350,7 @@
 	struct sk_buff *frag;
 	__u8 *frame;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
@@ -1334,22 +1359,9 @@
 	/*
 	 *  Split frame into a number of segments
 	 */
-	while (skb->len > 0) {
-		/*
-		 *  Instead of making the last segment, we just
-		 *  queue what is left of the original skb
-		 */
-		if (skb->len < self->max_seg_size) {
-			DEBUG(4, __FUNCTION__ 
-			       "(), queuing last segment\n");
-
-			frame = skb_push(skb, TTP_HEADER);
-			frame[0] = 0x00; /* Clear more bit */
-			skb_queue_tail(&self->tx_queue, skb);
-			
-			return;
-		}
-		
+	while (skb->len > self->max_seg_size) {
+		IRDA_DEBUG(2, __FUNCTION__  "(), fragmenting ...\n");
+
 		/* Make new segment */
 		frag = dev_alloc_skb(self->max_seg_size+self->max_header_size);
 		if (!frag)
@@ -1357,19 +1369,55 @@
 
 		skb_reserve(frag, self->max_header_size);
 
-		/*
-		 *  Copy data from the original skb into this fragment. We
-		 *  first insert the TTP header with the more bit set
-		 */
-		frame = skb_put(frag, self->max_seg_size+TTP_HEADER);
+		/* Copy data from the original skb into this fragment. */
+		memcpy(skb_put(frag, self->max_seg_size), skb->data, 
+		       self->max_seg_size);
+
+		/* Insert TTP header, with the more bit set */
+		frame = skb_push(frag, TTP_HEADER);
 		frame[0] = TTP_MORE;
-		memcpy(frag->data+1, skb->data, self->max_seg_size);
 		
 		/* Hide the copied data from the original skb */
 		skb_pull(skb, self->max_seg_size);
-		
+
+		/* Queue fragment */
 		skb_queue_tail(&self->tx_queue, frag);
 	}
+	/* Queue what is left of the original skb */
+	IRDA_DEBUG(2, __FUNCTION__  "(), queuing last segment\n");
+	
+	frame = skb_push(skb, TTP_HEADER);
+	frame[0] = 0x00; /* Clear more bit */
+
+	/* Queue fragment */
+	skb_queue_tail(&self->tx_queue, skb);
+}
+
+/*
+ * Function irttp_param_max_sdu_size (self, param)
+ *
+ *    Handle the MaxSduSize parameter in the connect frames, this function
+ *    will be called both when this parameter needs to be inserted into, and
+ *    extracted from the connect frames
+ */
+static int irttp_param_max_sdu_size(void *instance, irda_param_t *param, 
+				    int get)
+{
+	struct tsap_cb *self;
+
+	self = (struct tsap_cb *) instance;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+
+	if (get)
+		param->pv.i = self->tx_max_sdu_size;
+	else
+		self->tx_max_sdu_size = param->pv.i;
+
+	IRDA_DEBUG(0, __FUNCTION__ "(), MaxSduSize=%d\n", param->pv.i);
+	
+	return 0;
 }
 
 /*
@@ -1382,18 +1430,15 @@
 {
 	struct tsap_cb *self = (struct tsap_cb *) data;
 
-	DEBUG(4, __FUNCTION__ "()\n");
-	
 	/* Check that we still exist */
-	if (!self || self->magic != TTP_TSAP_MAGIC) {
+	if (!self || self->magic != TTP_TSAP_MAGIC)
 		return;
-	}
-
+	
 	irttp_run_rx_queue(self);
 	irttp_run_tx_queue(self);
-
+		
 	/*  Give avay some credits to peer?  */
-	if ((self->remote_credit < LOW_THRESHOLD) && 
+	if ((self->remote_credit < TTP_LOW_THRESHOLD) && 
 	    (self->avail_credit > 0) && (skb_queue_empty(&self->tx_queue)))
 	{
 		irttp_give_credit(self);
@@ -1414,13 +1459,13 @@
 				irttp_disconnect_request(self, NULL, P_NORMAL);
 		} else {
 			/* Try again later */
-			irttp_start_todo_timer(self, 100);
+			irttp_start_todo_timer(self, 1*HZ);
 			
 			/* No reason to try and close now */
 			return;
 		}
 	}
-
+	
 	/* Check if it's closing time */
 	if (self->close_pend)
 		irttp_close_tsap(self);
@@ -1442,7 +1487,7 @@
 	self->todo_timer.data     = (unsigned long) self;
 	self->todo_timer.function = &irttp_todo_expired;
 	self->todo_timer.expires  = jiffies + timeout;
-	
+
 	add_timer(&self->todo_timer);
 }
 
@@ -1467,42 +1512,40 @@
 
 	self = (struct tsap_cb *) hashbin_get_first(irttp->tsaps);
 	while (self != NULL) {
-		if (!self || self->magic != TTP_TSAP_MAGIC) {
-			DEBUG(1, "irttp_proc_read: bad ptr self\n");
+		if (!self || self->magic != TTP_TSAP_MAGIC)
 			return len;
-		}
 
 		len += sprintf(buf+len, "TSAP %d, ", i++);
 		len += sprintf(buf+len, "stsap_sel: %02x, ", 
-				self->stsap_sel);
+			       self->stsap_sel);
 		len += sprintf(buf+len, "dtsap_sel: %02x\n", 
-				self->dtsap_sel);
+			       self->dtsap_sel);
 		len += sprintf(buf+len, "  connected: %s, ",
-				self->connected? "TRUE":"FALSE");
+			       self->connected? "TRUE":"FALSE");
 		len += sprintf(buf+len, "avail credit: %d, ",
-				self->avail_credit);
+			       self->avail_credit);
 		len += sprintf(buf+len, "remote credit: %d, ",
-				self->remote_credit);
+			       self->remote_credit);
 		len += sprintf(buf+len, "send credit: %d\n",
-				self->send_credit);
+			       self->send_credit);
 		len += sprintf(buf+len, "  tx packets: %d, ",
-				self->stats.tx_packets);
+			       self->stats.tx_packets);
 		len += sprintf(buf+len, "rx packets: %d, ",
-				self->stats.rx_packets);
+			       self->stats.rx_packets);
 		len += sprintf(buf+len, "tx_queue len: %d ", 
-				skb_queue_len(&self->tx_queue));
+			       skb_queue_len(&self->tx_queue));
 		len += sprintf(buf+len, "rx_queue len: %d\n", 
-				skb_queue_len(&self->rx_queue));
+			       skb_queue_len(&self->rx_queue));
 		len += sprintf(buf+len, "  tx_sdu_busy: %s, ",
-				self->tx_sdu_busy? "TRUE":"FALSE");
+			       self->tx_sdu_busy? "TRUE":"FALSE");
 		len += sprintf(buf+len, "rx_sdu_busy: %s\n",
-				self->rx_sdu_busy? "TRUE":"FALSE");
+			       self->rx_sdu_busy? "TRUE":"FALSE");
 		len += sprintf(buf+len, "  max_seg_size: %d, ",
-				self->max_seg_size);
+			       self->max_seg_size);
 		len += sprintf(buf+len, "tx_max_sdu_size: %d, ",
-				self->tx_max_sdu_size);
+			       self->tx_max_sdu_size);
 		len += sprintf(buf+len, "rx_max_sdu_size: %d\n",
-				self->rx_max_sdu_size);
+			       self->rx_max_sdu_size);
 
 		len += sprintf(buf+len, "  Used by (%s)\n", 
 				self->notify.name);
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/parameters.c linux.15p9/net/irda/parameters.c
--- linux.vanilla/net/irda/parameters.c	Thu Jan  1 01:00:00 1970
+++ linux.15p9/net/irda/parameters.c	Mon Feb  7 12:17:43 2000
@@ -0,0 +1,575 @@
+/*********************************************************************
+ *                
+ * Filename:      parameters.c
+ * Version:       1.0
+ * Description:   A more general way to handle (pi,pl,pv) parameters
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Mon Jun  7 10:25:11 1999
+ * Modified at:   Sun Jan 30 14:08:39 2000
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#include <asm/unaligned.h>
+#include <asm/byteorder.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/parameters.h>
+
+static int irda_extract_integer(void *self, __u8 *buf, int len, __u8 pi, 
+				PV_TYPE type, PI_HANDLER func);
+static int irda_extract_string(void *self, __u8 *buf, int len, __u8 pi, 
+			       PV_TYPE type, PI_HANDLER func);
+static int irda_extract_octseq(void *self, __u8 *buf, int len, __u8 pi, 
+			       PV_TYPE type, PI_HANDLER func);
+static int irda_extract_no_value(void *self, __u8 *buf, int len, __u8 pi, 
+				 PV_TYPE type, PI_HANDLER func);
+
+static int irda_insert_integer(void *self, __u8 *buf, int len, __u8 pi, 
+			       PV_TYPE type, PI_HANDLER func);
+static int irda_insert_no_value(void *self, __u8 *buf, int len, __u8 pi, 
+				PV_TYPE type, PI_HANDLER func);
+
+/* Parameter value call table. Must match PV_TYPE */
+static PV_HANDLER pv_extract_table[] = {
+	irda_extract_integer, /* Handler for any length integers */
+	irda_extract_integer, /* Handler for 8  bits integers */
+	irda_extract_integer, /* Handler for 16 bits integers */
+	irda_extract_string,  /* Handler for strings */
+	irda_extract_integer, /* Handler for 32 bits integers */
+	irda_extract_octseq,  /* Handler for octet sequences */
+	irda_extract_no_value /* Handler for no value parameters */
+};
+
+static PV_HANDLER pv_insert_table[] = {
+	irda_insert_integer, /* Handler for any length integers */
+	irda_insert_integer, /* Handler for 8  bits integers */
+	irda_insert_integer, /* Handler for 16 bits integers */
+	NULL,                /* Handler for strings */
+	irda_insert_integer, /* Handler for 32 bits integers */
+	NULL,                /* Handler for octet sequences */
+	irda_insert_no_value /* Handler for no value parameters */
+};
+
+/*
+ * Function irda_insert_no_value (self, buf, len, pi, type, func)
+ *
+ *    
+ *
+ */
+static int irda_insert_no_value(void *self, __u8 *buf, int len, __u8 pi, 
+				PV_TYPE type, PI_HANDLER func)
+{
+	irda_param_t p;
+	int ret;
+
+	p.pi = pi;
+	p.pl = 0;
+
+	/* Call handler for this parameter */
+	ret = (*func)(self, &p, PV_GET);
+
+	/* Extract values anyway, since handler may need them */
+	irda_param_pack(buf, "bb", p.pi, p.pl);
+
+	if (ret < 0)
+		return ret;
+	 
+	return 2; /* Inserted pl+2 bytes */
+}
+
+/*
+ * Function irda_extract_no_value (self, buf, len, type, func)
+ *
+ *    Extracts a parameter without a pv field (pl=0)
+ *
+ */
+static int irda_extract_no_value(void *self, __u8 *buf, int len, __u8 pi, 
+				 PV_TYPE type, PI_HANDLER func)
+{
+	irda_param_t p;
+	int ret;
+
+	/* Extract values anyway, since handler may need them */
+	irda_param_unpack(buf, "bb", &p.pi, &p.pl);
+
+	/* Call handler for this parameter */
+	ret = (*func)(self, &p, PV_PUT);
+
+	if (ret < 0)
+		return ret;
+	 
+	return 2; /* Extracted pl+2 bytes */
+}
+
+/*
+ * Function irda_insert_integer (self, buf, len, pi, type, func)
+ *
+ *    
+ *
+ */
+static int irda_insert_integer(void *self, __u8 *buf, int len, __u8 pi, 
+			       PV_TYPE type, PI_HANDLER func)
+{
+	irda_param_t p;
+	int n = 0;
+	int err;
+
+	p.pi = pi;             /* In case handler needs to know */
+	p.pl = type & PV_MASK; /* The integer type codes the lenght as well */
+	p.pv.i = 0;            /* Clear value */
+
+	/* Call handler for this parameter */
+	err = (*func)(self, &p, PV_GET);
+	if (err < 0)
+		return err; 
+
+	/* 
+	 * If parameter lenght is still 0, then (1) this is an any length 
+	 * integer, and (2) the handler function does not care which length
+	 * we choose to use, so we pick the one the gives the fewest bytes.
+	 */
+	if (p.pl == 0) {
+		if (p.pv.i < 0xff) {
+			IRDA_DEBUG(2, __FUNCTION__ "(), using 1 byte\n");
+			p.pl = 1;
+		} else if (p.pv.i < 0xffff) {
+			IRDA_DEBUG(2, __FUNCTION__ "(), using 2 bytes\n");
+			p.pl = 2;
+		} else {
+			IRDA_DEBUG(2, __FUNCTION__ "(), using 4 bytes\n");
+			p.pl = 4; /* Default length */
+		}
+	}
+	/* Check if buffer is long enough for insertion */
+	if (len < (2+p.pl)) {
+		WARNING(__FUNCTION__ "(), buffer to short for insertion!\n");
+		return -1;
+	}
+	IRDA_DEBUG(2, __FUNCTION__ "(), pi=%#x, pl=%d, pi=%d\n", p.pi, p.pl, p.pv.i);
+	switch (p.pl) {
+	case 1:
+		n += irda_param_pack(buf, "bbb", p.pi, p.pl, p.pv.b);
+		break;
+	case 2:
+		if (type & PV_BIG_ENDIAN)
+			cpu_to_be16s(&p.pv.s);
+		else
+			cpu_to_le16s(&p.pv.s);
+		n += irda_param_pack(buf, "bbs", p.pi, p.pl, p.pv.s);
+		break;
+	case 4:
+		if (type & PV_BIG_ENDIAN)
+			cpu_to_be32s(&p.pv.i);
+		else
+			cpu_to_le32s(&p.pv.i);
+		n += irda_param_pack(buf, "bbi", p.pi, p.pl, p.pv.i);
+
+		break;
+	default:
+		WARNING(__FUNCTION__ "() length %d not supported\n", p.pl);
+		/* Skip parameter */ 
+		return -1;
+	}
+
+	return p.pl+2; /* Inserted pl+2 bytes */
+}
+
+/*
+ * Function irda_extract integer (self, buf, len, pi, type, func)
+ *
+ *    Extract a possibly variable length integer from buffer, and call 
+ *    handler for processing of the parameter
+ */
+static int irda_extract_integer(void *self, __u8 *buf, int len, __u8 pi, 
+				PV_TYPE type, PI_HANDLER func)
+{
+	irda_param_t p;
+	int n = 0;
+	int err;
+
+	p.pi = pi;     /* In case handler needs to know */
+	p.pl = buf[1]; /* Extract lenght of value */
+	p.pv.i = 0;    /* Clear value */
+
+	/* Check if buffer is long enough for parsing */
+	if (len < (2+p.pl)) {
+		WARNING(__FUNCTION__ "(), buffer to short for parsing! "
+			"Need %d bytes, but len is only %d\n", p.pl, len);
+		return -1;
+	}
+
+	/* 
+	 * Check that the integer length is what we expect it to be. If the
+	 * handler want a 16 bits integer then a 32 bits is not good enough
+	 */
+	if (((type & PV_MASK) != PV_INTEGER) && ((type & PV_MASK) != p.pl)) {
+		ERROR(__FUNCTION__ "(), invalid parameter length! "
+		      "Expected %d bytes, but value had %d bytes!\n",
+		      type & PV_MASK, p.pl);
+		
+		/* Skip parameter */
+		return p.pl+2;
+	}
+
+	switch (p.pl) {
+	case 1:
+		n += irda_param_unpack(buf+2, "b", &p.pv.b);
+		break;
+	case 2:
+		n += irda_param_unpack(buf+2, "s", &p.pv.s);
+		if (type & PV_BIG_ENDIAN)
+			be16_to_cpus(&p.pv.s);
+		else
+			le16_to_cpus(&p.pv.s);
+		break;
+	case 4:
+		n += irda_param_unpack(buf+2, "i", &p.pv.i);
+		if (type & PV_BIG_ENDIAN)
+			be32_to_cpus(&p.pv.i);
+		else
+			le32_to_cpus(&p.pv.i);
+		break;
+	default:
+		WARNING(__FUNCTION__ "() length %d not supported\n", p.pl);
+
+		/* Skip parameter */ 
+		return p.pl+2;
+	}
+
+	/* Call handler for this parameter */
+	err = (*func)(self, &p, PV_PUT);
+	if (err < 0)
+		return err; 
+
+	return p.pl+2; /* Extracted pl+2 bytes */
+}
+
+/*
+ * Function irda_extract_string (self, buf, len, type, func)
+ *
+ *    
+ *
+ */
+static int irda_extract_string(void *self, __u8 *buf, int len, __u8 pi, 
+			       PV_TYPE type, PI_HANDLER func)
+{
+	char str[33];
+	irda_param_t p;
+	int err;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	p.pi = pi;     /* In case handler needs to know */
+	p.pl = buf[1]; /* Extract lenght of value */
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), pi=%#x, pl=%d\n", p.pi, p.pl);
+
+	/* Check if buffer is long enough for parsing */
+	if (len < (2+p.pl)) {
+		WARNING(__FUNCTION__ "(), buffer to short for parsing! "
+			"Need %d bytes, but len is only %d\n", p.pl, len);
+		return -1;
+	}
+
+	/* Should be safe to copy string like this since we have already 
+	 * checked that the buffer is long enough */
+	strncpy(str, buf+2, p.pl);
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), str=0x%02x 0x%02x\n", (__u8) str[0], 
+	      (__u8) str[1]);
+	
+	/* Null terminate string */
+	str[p.pl+1] = '\0';
+
+	p.pv.c = str; /* Handler will need to take a copy */
+
+	/* Call handler for this parameter */
+	err = (*func)(self, &p, PV_PUT);
+	if (err < 0)
+		return err; 
+
+	return p.pl+2; /* Extracted pl+2 bytes */
+}
+
+/*
+ * Function irda_extract_octseq (self, buf, len, type, func)
+ *
+ *    
+ *
+ */
+static int irda_extract_octseq(void *self, __u8 *buf, int len, __u8 pi,
+			       PV_TYPE type, PI_HANDLER func)
+{
+	irda_param_t p;
+
+	p.pi = pi;     /* In case handler needs to know */
+	p.pl = buf[1]; /* Extract lenght of value */
+
+	/* Check if buffer is long enough for parsing */
+	if (len < (2+p.pl)) {
+		WARNING(__FUNCTION__ "(), buffer to short for parsing! "
+			"Need %d bytes, but len is only %d\n", p.pl, len);
+		return -1;
+	}
+
+	IRDA_DEBUG(0, __FUNCTION__ "(), not impl\n");
+	
+	return p.pl+2; /* Extracted pl+2 bytes */
+}
+
+/*
+ * Function irda_param_pack (skb, fmt, ...)
+ *
+ *    Format:
+ *        'i' = 32 bits integer
+ *        's' = string
+ *
+ */
+int irda_param_pack(__u8 *buf, char *fmt, ...)
+{
+	irda_pv_t arg;
+	va_list args;
+	char *p;
+	int n = 0;
+	
+	va_start(args, fmt);
+
+	for (p = fmt; *p != '\0'; p++) {
+		switch (*p) {
+		case 'b':  /* 8 bits unsigned byte */
+			buf[n++] = va_arg(args, __u8);
+			break;
+		case 's':  /* 16 bits unsigned short */
+			arg.s = va_arg(args, __u16);
+			put_unaligned(arg.s, (__u16 *)(buf+n)); n+=2;
+			break;
+		case 'i':  /* 32 bits unsigned integer */
+			arg.i = va_arg(args, __u32);
+			put_unaligned(arg.i, (__u32 *)(buf+n)); n+=4;
+			break;
+		case 'c': /* \0 terminated string */
+			arg.c = va_arg(args, char *);
+			strcpy(buf+n, arg.c);
+			n += strlen(arg.c) + 1;
+			break;
+		default:
+			va_end(args);
+			return -1;
+		}
+		
+	}
+	va_end(args);
+
+	return 0;
+}
+
+/*
+ * Function irda_param_unpack (skb, fmt, ...)
+ *
+ *    
+ *
+ */
+int irda_param_unpack(__u8 *buf, char *fmt, ...)
+{
+	irda_pv_t arg;
+	va_list args;
+	char *p;
+	int n = 0;
+
+	va_start(args, fmt);
+
+	for (p = fmt; *p != '\0'; p++) {
+		switch (*p) {
+		case 'b':  /* 8 bits byte */
+			arg.bp = va_arg(args, __u8 *);
+			*arg.bp = buf[n++];
+			break;
+		case 's':  /* 16 bits short */
+			arg.sp = va_arg(args, __u16 *);
+			*arg.sp = get_unaligned((__u16 *)(buf+n)); n+=2;
+			break;
+		case 'i':  /* 32 bits unsigned integer */
+			arg.ip = va_arg(args, __u32 *);
+			*arg.ip = get_unaligned((__u32 *)(buf+n)); n+=4;
+			break;
+#if 0
+		case 'c':   /* \0 terminated string */
+			arg.c = va_arg(args, char *);
+			strcpy(arg.c, buf+n);
+			n += strlen(arg.c) + 1;
+			break;
+#endif
+		default:
+			va_end(args);
+			return -1;
+		}
+		
+	}
+	va_end(args);
+
+	return 0;
+}
+
+/*
+ * Function irda_param_insert (self, pi, buf, len, info)
+ *
+ *    Insert the specified parameter (pi) into buffer. Returns number of
+ *    bytes inserted
+ */
+int irda_param_insert(void *self, __u8 pi, __u8 *buf, int len, 
+		      pi_param_info_t *info)
+{
+	pi_minor_info_t *pi_minor_info;
+	__u8 pi_minor;
+	__u8 pi_major;
+	int type;
+	int ret = -1;
+	int n = 0;
+
+	ASSERT(buf != NULL, return ret;);
+	ASSERT(info != 0, return ret;);
+
+	pi_minor = pi & info->pi_mask;
+	pi_major = pi >> info->pi_major_offset;
+
+	/* Check if the identifier value (pi) is valid */
+	if ((pi_major > info->len-1) || 
+	    (pi_minor > info->tables[pi_major].len-1))
+	{
+		IRDA_DEBUG(0, __FUNCTION__ 
+		      "(), no handler for parameter=0x%02x\n", pi);
+		
+		/* Skip this parameter */
+		return -1;
+	}
+	
+	/* Lookup the info on how to parse this parameter */
+	pi_minor_info = &info->tables[pi_major].pi_minor_call_table[pi_minor];
+
+	/* Find expected data type for this parameter identifier (pi)*/
+	type = pi_minor_info->type;
+
+	/*  Check if handler has been implemented */
+	if (!pi_minor_info->func) {
+		MESSAGE(__FUNCTION__"(), no handler for pi=%#x\n", pi);
+		/* Skip this parameter */
+		return -1;
+	}
+	
+	/* Insert parameter value */
+	ret = (*pv_insert_table[type & PV_MASK])(self, buf+n, len, pi, type, 
+						 pi_minor_info->func);
+	return ret;
+}
+
+/*
+ * Function irda_param_extract_all (self, buf, len, info)
+ *
+ *    Parse all parameters. If len is correct, then everything should be
+ *    safe. Returns the number of bytes that was parsed
+ *
+ */
+int irda_param_extract(void *self, __u8 *buf, int len, pi_param_info_t *info)
+{
+	pi_minor_info_t *pi_minor_info;
+	__u8 pi_minor;
+	__u8 pi_major;
+	int type;
+	int ret = -1;
+	int n = 0;
+
+	ASSERT(buf != NULL, return ret;);
+	ASSERT(info != 0, return ret;);
+
+	pi_minor = buf[n] & info->pi_mask;
+	pi_major = buf[n] >> info->pi_major_offset;
+	
+	/* Check if the identifier value (pi) is valid */
+	if ((pi_major > info->len-1) || 
+	    (pi_minor > info->tables[pi_major].len-1))
+	{
+		IRDA_DEBUG(0, __FUNCTION__ "(), no handler for parameter=0x%02x\n",
+		      buf[0]);
+		
+		/* Skip this parameter */
+		n += (2 + buf[n+1]);
+		len -= (2 + buf[n+1]);
+
+		return 0;  /* Continue */
+	}
+
+	/* Lookup the info on how to parse this parameter */
+	pi_minor_info = &info->tables[pi_major].pi_minor_call_table[pi_minor];
+
+	/* Find expected data type for this parameter identifier (pi)*/
+	type = pi_minor_info->type;
+	
+	IRDA_DEBUG(3, __FUNCTION__ "(), pi=[%d,%d], type=%d\n",
+	      pi_major, pi_minor, type);
+	
+	/*  Check if handler has been implemented */
+	if (!pi_minor_info->func) {
+		MESSAGE(__FUNCTION__"(), no handler for pi=%#x\n", buf[n]);
+		/* Skip this parameter */
+		n += (2 + buf[n+1]);
+		len -= (2 + buf[n+1]);
+
+		return 0; /* Continue */
+	}
+
+	/* Parse parameter value */
+	ret = (*pv_extract_table[type & PV_MASK])(self, buf+n, len, buf[n],
+						  type, pi_minor_info->func);
+	return ret;
+}
+
+/*
+ * Function irda_param_extract_all (self, buf, len, info)
+ *
+ *    Parse all parameters. If len is correct, then everything should be
+ *    safe. Returns the number of bytes that was parsed
+ *
+ */
+int irda_param_extract_all(void *self, __u8 *buf, int len, 
+			   pi_param_info_t *info)
+{
+	int ret = -1;
+	int n = 0;
+
+	ASSERT(buf != NULL, return ret;);
+	ASSERT(info != 0, return ret;);
+
+	/*
+	 * Parse all parameters. Each parameter must be at least two bytes
+	 * long or else there is no point in trying to parse it
+	 */
+	while (len > 2) {
+		ret = irda_param_extract(self, buf+n, len, info);
+		if (ret < 0)
+			return ret;
+
+		n += ret;
+		len -= ret;
+	}
+	return n;
+}
+
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/qos.c linux.15p9/net/irda/qos.c
--- linux.vanilla/net/irda/qos.c	Sat Aug 14 02:26:54 1999
+++ linux.15p9/net/irda/qos.c	Mon Feb  7 12:17:43 2000
@@ -1,32 +1,39 @@
 /*********************************************************************
- *                
+ *                                
  * Filename:      qos.c
- * Version:       0.8
- * Description:   IrLAP QoS negotiation
- * Status:        Experimental.
+ * Version:       1.0
+ * Description:   IrLAP QoS parameter negotiation
+ * Status:        Stable
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Sep  9 00:00:26 1997
- * Modified at:   Mon May  3 21:15:08 1999
+ * Modified at:   Sun Jan 30 14:29:16 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
+ *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>, 
  *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
- *
- *     Neither Dag Brattli nor University of Tromsř admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
- *
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
  ********************************************************************/
 
 #include <linux/config.h>
 #include <asm/byteorder.h>
 
 #include <net/irda/irda.h>
+#include <net/irda/parameters.h>
 #include <net/irda/qos.h>
 #include <net/irda/irlap.h>
 #ifdef CONFIG_IRDA_COMPRESSION
@@ -36,17 +43,74 @@
 #define CI_BZIP2  27 /* Random pick */
 #endif
 
-int min_turn_time[] = { 10000, 5000, 1000, 500, 100, 50, 10, 0 };
-int baud_rates[] = { 2400, 9600, 19200, 38400, 57600, 115200, 576000, 1152000,
-		     4000000 };
-int data_size[]  = { 64, 128, 256, 512, 1024, 2048 };
-int add_bofs[]   = { 48, 24, 12, 5, 3, 2, 1, 0 };
-int max_turn_time[] = { 500, 250, 100, 50 };
-int link_disc_time[] = { 3, 8, 12, 16, 20, 25, 30, 40 };
+static int irlap_param_baud_rate(void *instance, irda_param_t *param, int get);
+static int irlap_param_link_disconnect(void *instance, irda_param_t *parm, 
+				       int get);
+static int irlap_param_max_turn_time(void *instance, irda_param_t *param, 
+				     int get);
+static int irlap_param_data_size(void *instance, irda_param_t *param, int get);
+static int irlap_param_window_size(void *instance, irda_param_t *param, 
+				   int get);
+static int irlap_param_additional_bofs(void *instance, irda_param_t *parm, 
+				       int get);
+static int irlap_param_min_turn_time(void *instance, irda_param_t *param, 
+				     int get);
+
+__u32 min_turn_times[]  = { 10000, 5000, 1000, 500, 100, 50, 10, 0 }; /* us */
+__u32 baud_rates[]      = { 2400, 9600, 19200, 38400, 57600, 115200, 576000, 
+			    1152000, 4000000, 16000000 };           /* bps */
+__u32 data_sizes[]      = { 64, 128, 256, 512, 1024, 2048 };        /* bytes */
+__u32 add_bofs[]        = { 48, 24, 12, 5, 3, 2, 1, 0 };            /* bytes */
+__u32 max_turn_times[]  = { 500, 250, 100, 50 };                    /* ms */
+__u32 link_disc_times[] = { 3, 8, 12, 16, 20, 25, 30, 40 };         /* secs */
 
 #ifdef CONFIG_IRDA_COMPRESSION
-int compression[] = { CI_BZIP2, CI_DEFLATE, CI_DEFLATE_DRAFT };
+__u32 compressions[] = { CI_BZIP2, CI_DEFLATE, CI_DEFLATE_DRAFT };
 #endif
+
+__u32 max_line_capacities[10][4] = {
+       /* 500 ms     250 ms  100 ms  50 ms (max turn time) */
+	{    100,      0,      0,     0 }, /*     2400 bps */
+	{    400,      0,      0,     0 }, /*     9600 bps */
+	{    800,      0,      0,     0 }, /*    19200 bps */
+	{   1600,      0,      0,     0 }, /*    38400 bps */
+	{   2360,      0,      0,     0 }, /*    57600 bps */
+	{   4800,   2400,    960,   480 }, /*   115200 bps */
+	{  28800,  11520,   5760,  2880 }, /*   576000 bps */
+	{  57600,  28800,  11520,  5760 }, /*  1152000 bps */
+	{ 200000, 100000,  40000, 20000 }, /*  4000000 bps */
+	{ 800000, 400000, 160000, 80000 }, /* 16000000 bps */
+};
+
+static pi_minor_info_t pi_minor_call_table_type_0[] = {
+	{ NULL, 0 },
+/* 01 */{ irlap_param_baud_rate,       PV_INTEGER | PV_LITTLE_ENDIAN },
+	{ NULL, 0 },
+	{ NULL, 0 },
+	{ NULL, 0 },
+	{ NULL, 0 },
+	{ NULL, 0 },
+	{ NULL, 0 },
+/* 08 */{ irlap_param_link_disconnect, PV_INT_8_BITS }
+};
+
+static pi_minor_info_t pi_minor_call_table_type_1[] = {
+	{ NULL, 0 },
+	{ NULL, 0 },
+/* 82 */{ irlap_param_max_turn_time,   PV_INT_8_BITS },
+/* 83 */{ irlap_param_data_size,       PV_INT_8_BITS },
+/* 84 */{ irlap_param_window_size,     PV_INT_8_BITS },
+/* 85 */{ irlap_param_additional_bofs, PV_INT_8_BITS },
+/* 86 */{ irlap_param_min_turn_time,   PV_INT_8_BITS },
+};
+
+static pi_major_info_t pi_major_call_table[] = {
+	{ pi_minor_call_table_type_0, 9 },
+	{ pi_minor_call_table_type_1, 7 },
+};
+
+static pi_param_info_t irlap_param_info = { pi_major_call_table, 2, 0x7f, 7 };
+
 /*
  * Function irda_qos_compute_intersection (qos, new)
  *
@@ -81,7 +145,7 @@
  *    set the maximum QoS possible and then "and in" their own limitations
  * 
  */
-void irda_init_max_qos_capabilies( struct qos_info *qos)
+void irda_init_max_qos_capabilies(struct qos_info *qos)
 {
 	/* 
 	 *  These are the maximum supported values as specified on pages
@@ -104,164 +168,117 @@
 }
 
 /*
+ * Function irlap_adjust_qos_settings (qos)
+ *
+ *     Adjust QoS settings in case some values are not possible to use because
+ *     of other settings
+ */
+void irlap_adjust_qos_settings(struct qos_info *qos)
+{
+	__u32 line_capacity;
+	int index;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	/* 
+	 * Not allowed to use a max turn time less than 500 ms if the baudrate
+	 * is less than 115200
+	 */
+	if ((qos->baud_rate.value < 115200) && 
+	    (qos->max_turn_time.value < 500))
+	{
+		IRDA_DEBUG(0, __FUNCTION__ 
+			   "(), adjusting max turn time from %d to 500 ms\n",
+			   qos->max_turn_time.value);
+		qos->max_turn_time.value = 500;
+	}
+	
+	/*
+	 * The data size must be adjusted according to the baud rate and max 
+	 * turn time
+	 */
+	index = value_index(qos->data_size.value, data_sizes);
+	line_capacity = irlap_max_line_capacity(qos->baud_rate.value, 
+						qos->max_turn_time.value);
+
+#ifdef CONFIG_IRDA_DYNAMIC_WINDOW
+	while ((qos->data_size.value > line_capacity) && (index > 0)) {
+		qos->data_size.value = data_sizes[index--];
+		IRDA_DEBUG(2, __FUNCTION__ 
+			   "(), redusing data size to %d\n",
+			   qos->data_size.value);
+	}
+#else /* Use method descibed in section 6.6.11 of IrLAP */
+	while (irlap_requested_line_capacity(qos) > line_capacity) {
+		ASSERT(index != 0, return;);
+
+		/* Must be able to send at least one frame */
+		if (qos->window_size.value > 1) {
+			qos->window_size.value--;
+			IRDA_DEBUG(2, __FUNCTION__ 
+				   "(), redusing window size to %d\n",
+				   qos->window_size.value);
+		} else if (index > 1) {
+			qos->data_size.value = data_sizes[index--];
+			IRDA_DEBUG(2, __FUNCTION__ 
+				   "(), redusing data size to %d\n",
+				   qos->data_size.value);
+		} else {
+			WARNING(__FUNCTION__ "(), nothing more we can do!\n");
+		}
+	}
+#endif CONFIG_IRDA_DYNAMIC_WINDOW
+}
+
+/*
  * Function irlap_negotiate (qos_device, qos_session, skb)
  *
  *    Negotiate QoS values, not really that much negotiation :-)
  *    We just set the QoS capabilities for the peer station
  *
  */
-void irda_qos_negotiate(struct qos_info *qos_rx, struct qos_info *qos_tx, 
-			struct sk_buff *skb) 
+int irlap_qos_negotiate(struct irlap_cb *self, struct sk_buff *skb) 
 {
-	int n=0;
+	int ret;
 #ifdef CONFIG_IRDA_COMPRESSION
 	int comp_seen = FALSE;
 #endif
-	__u8 length;
-	__u8 *frame;
-	__u8 final_byte;
-	__u8 code;
-	__u8 byte;
- 	__u16 final_word;
-	__u16_host_order word;
-
-	ASSERT( qos_tx != NULL, return;);
-	ASSERT( qos_rx != NULL, return;);
-	ASSERT( skb != NULL, return;);
-
-	frame = skb->data;
-
-	while( n < skb->len-2) {
-		code = frame[n++];
-		/* Length */
-		length = frame[n++];
-
-		/*  
-		 *  Get the value, since baud_rate may need two bytes, we
-		 *  Just use word size all the time
-		 */
-		switch( length) {
-		case 1:
-			byte = frame[n++];
-			word.word = byte; /* To make things a little easier */
-			break;
-		case 2:
-#ifdef __LITTLE_ENDIAN
-			word.byte[0] = frame[n++];
-			word.byte[1] = frame[n++];
-#else ifdef __BIG_ENDIAN
-			word.byte[1] = frame[n++];
-			word.byte[0] = frame[n++];
-#endif
-			byte = 0;
-			break;
-		default:
-			DEBUG( 0, __FUNCTION__ "Error\n");
-			word.word = byte = 0;
-			n += length;
-			
-			break;
-		}
-
-		switch(code) {
-		case PI_BAUD_RATE:
-			/* 
-			 *  Stations must agree on baud rate, so calculate
-                         *  intersection 
-			 */
-			DEBUG( 4, "Requested BAUD_RATE: 0x%04x\n", word.word);
-			final_word = word.word & qos_rx->baud_rate.bits;
-			DEBUG( 4, "Final BAUD_RATE: 0x%04x\n", final_word);
-			qos_tx->baud_rate.bits = final_word;
-			qos_rx->baud_rate.bits = final_word;
-			break;
-		case PI_MAX_TURN_TIME:
-			/*
-			 *  Negotiated independently for each station
-			 */
-			DEBUG(4, __FUNCTION__ "(), MAX_TURN_TIME: %02x\n", 
-			      byte);
-			qos_tx->max_turn_time.bits = byte;
-			break;
-		case PI_DATA_SIZE:
-			/*
-			 *  Negotiated independently for each station
-			 */
-			DEBUG( 4, "DATA_SIZE: %02x\n", byte);
-			qos_tx->data_size.bits = byte;
-			break;
-		case PI_WINDOW_SIZE:
-			/*
-			 *  Negotiated independently for each station
-			 */
-			qos_tx->window_size.bits = byte;
-			break;
-		case PI_ADD_BOFS:
-			/*
-			 *  Negotiated independently for each station
-			 */
-			DEBUG( 4, "ADD_BOFS: %02x\n", byte);
-			qos_tx->additional_bofs.bits = byte;	
-			break;
-		case PI_MIN_TURN_TIME:
-			DEBUG( 4, "MIN_TURN_TIME: %02x\n", byte);
-			qos_tx->min_turn_time.bits = byte;
-			break;
-		case PI_LINK_DISC:
-			/*  
-			 *  Stations must agree on link disconnect/threshold 
-			 *  time.
-			 */
-			DEBUG( 4, "LINK_DISC: %02x\n", byte);
-			
-			final_byte = byte & qos_rx->link_disc_time.bits;
-			DEBUG( 4, "Final LINK_DISC: %02x\n", final_byte);
-			qos_tx->link_disc_time.bits = final_byte;
-			qos_rx->link_disc_time.bits = final_byte;
-			break;
-#ifdef CONFIG_IRDA_COMPRESSION
-		case PI_COMPRESSION:
-			final_byte = byte & qos_rx->compression.bits;
-			qos_rx->compression.bits = byte;
-			qos_tx->compression.bits = byte;
-			comp_seen = TRUE;
-			break;
-#endif
-		default:
-			DEBUG( 0, __FUNCTION__ "(), Unknown value\n");
-			break;
-		}
-	}
+	ret = irda_param_extract_all(self, skb->data, skb->len, 
+				     &irlap_param_info);
+	
 #ifdef CONFIG_IRDA_COMPRESSION
-	if ( !comp_seen) {
-		DEBUG( 4, __FUNCTION__ "(), Compression not seen!\n");
-		qos_tx->compression.bits = 0x00;
-		qos_rx->compression.bits = 0x00;
+	if (!comp_seen) {
+		IRDA_DEBUG( 4, __FUNCTION__ "(), Compression not seen!\n");
+		self->qos_tx.compression.bits = 0x00;
+		self->qos_rx.compression.bits = 0x00;
 	}
 #endif
+
 	/* Convert the negotiated bits to values */
-	irda_qos_bits_to_value( qos_tx);
-	irda_qos_bits_to_value( qos_rx);
-		
-	DEBUG( 4, "Setting BAUD_RATE to %d bps.\n", 
-	       qos_tx->baud_rate.value);
-	DEBUG( 4, "Setting DATA_SIZE to %d bytes\n",
-	       qos_tx->data_size.value);
-	DEBUG( 4, "Setting WINDOW_SIZE to %d\n", 
-	       qos_tx->window_size.value);
-	DEBUG( 4, "Setting XBOFS to %d\n", 
-	       qos_tx->additional_bofs.value);
-	DEBUG( 4, "Setting MAX_TURN_TIME to %d ms.\n",
-	       qos_tx->max_turn_time.value);
-	DEBUG( 4, "Setting MIN_TURN_TIME to %d usecs.\n",
-	       qos_tx->min_turn_time.value);
-	DEBUG( 4, "Setting LINK_DISC to %d secs.\n", 
-	       qos_tx->link_disc_time.value);
+	irda_qos_bits_to_value(&self->qos_tx);
+	irda_qos_bits_to_value(&self->qos_rx);
+
+	irlap_adjust_qos_settings(&self->qos_tx);
+
+	IRDA_DEBUG(2, "Setting BAUD_RATE to %d bps.\n", 
+		   self->qos_tx.baud_rate.value);
+	IRDA_DEBUG(2, "Setting DATA_SIZE to %d bytes\n",
+		   self->qos_tx.data_size.value);
+	IRDA_DEBUG(2, "Setting WINDOW_SIZE to %d\n", 
+		   self->qos_tx.window_size.value);
+	IRDA_DEBUG(2, "Setting XBOFS to %d\n", 
+		   self->qos_tx.additional_bofs.value);
+	IRDA_DEBUG(2, "Setting MAX_TURN_TIME to %d ms.\n",
+		   self->qos_tx.max_turn_time.value);
+	IRDA_DEBUG(2, "Setting MIN_TURN_TIME to %d usecs.\n",
+		   self->qos_tx.min_turn_time.value);
+	IRDA_DEBUG(2, "Setting LINK_DISC to %d secs.\n", 
+		   self->qos_tx.link_disc_time.value);
 #ifdef CONFIG_IRDA_COMPRESSION
-	DEBUG( 4, "Setting COMPRESSION to %d\n", 
-	       qos_tx->compression.value);
-#endif
-	
+	IRDA_DEBUG(2, "Setting COMPRESSION to %d\n", 
+		   self->qos_tx.compression.value);
+#endif	
+	return ret;
 }
 
 /*
@@ -270,100 +287,303 @@
  *    Insert QoS negotiaion pararameters into frame
  *
  */
-int irda_insert_qos_negotiation_params(struct qos_info *qos, __u8 *frame)
+int irlap_insert_qos_negotiation_params(struct irlap_cb *self, 
+					struct sk_buff *skb)
 {
-	int n;
-	__u16_host_order word;
+	int ret;
 
-	ASSERT( qos != NULL, return 0;);
-	ASSERT( frame != NULL, return 0;);
+	/* Insert data rate */
+	ret = irda_param_insert(self, PI_BAUD_RATE, skb->tail, 
+				skb_tailroom(skb), &irlap_param_info);
+	if (ret < 0)
+		return ret;
+	skb_put(skb, ret);
+
+	/* Insert max turnaround time */
+	ret = irda_param_insert(self, PI_MAX_TURN_TIME, skb->tail, 
+				skb_tailroom(skb), &irlap_param_info);
+	if (ret < 0)
+		return ret;
+	skb_put(skb, ret);
+
+	/* Insert data size */
+	ret = irda_param_insert(self, PI_DATA_SIZE, skb->tail, 
+				skb_tailroom(skb), &irlap_param_info);
+	if (ret < 0)
+		return ret;
+	skb_put(skb, ret);
+
+	/* Insert window size */
+	ret = irda_param_insert(self, PI_WINDOW_SIZE, skb->tail, 
+				skb_tailroom(skb), &irlap_param_info);
+	if (ret < 0)
+		return ret;
+	skb_put(skb, ret);
+
+	/* Insert additional BOFs */
+	ret = irda_param_insert(self, PI_ADD_BOFS, skb->tail, 
+				skb_tailroom(skb), &irlap_param_info);
+	if (ret < 0)
+		return ret;
+	skb_put(skb, ret);
+
+	/* Insert minimum turnaround time */
+	ret = irda_param_insert(self, PI_MIN_TURN_TIME, skb->tail, 
+				skb_tailroom(skb), &irlap_param_info);
+	if (ret < 0)
+		return ret;
+	skb_put(skb, ret);
+
+	/* Insert link disconnect/threshold time */
+	ret = irda_param_insert(self, PI_LINK_DISC, skb->tail, 
+				skb_tailroom(skb), &irlap_param_info);
+	if (ret < 0)
+		return ret;
+	skb_put(skb, ret);
+
+	return 0;
+}
 
-	n = 0;
+/*
+ * Function irlap_param_baud_rate (instance, param, get)
+ *
+ *    Negotiate data-rate
+ *
+ */
+static int irlap_param_baud_rate(void *instance, irda_param_t *param, int get)
+{
+	__u16 final;
 
-	/* Set baud rate */
-	if (qos->baud_rate.bits < 256) {
-		frame[n++] = PI_BAUD_RATE;
-		frame[n++] = 0x01;   /* length 1 */
-		frame[n++] = qos->baud_rate.bits;
+	struct irlap_cb *self = (struct irlap_cb *) instance;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LAP_MAGIC, return -1;);
+
+	if (get) {
+		param->pv.i = self->qos_rx.baud_rate.bits;
+		IRDA_DEBUG(2, __FUNCTION__ "(), baud rate = 0x%02x\n", 
+			   param->pv.i);		
 	} else {
-		frame[n++] = PI_BAUD_RATE;
-		frame[n++] = 0x02;   /* length 2 */
-		
 		/* 
-		 *  qos->baud_rate.bits is in host byte order, so make sure
-		 *  we transmit it in little endian format 
+		 *  Stations must agree on baud rate, so calculate
+		 *  intersection 
 		 */
-		word.word = qos->baud_rate.bits;
-#ifdef __LITTLE_ENDIAN
-		frame[n++] = word.byte[0]; /* LSB */
-		frame[n++] = word.byte[1]; /* MSB */
-#else ifdef __BIG_ENDIAN
-		frame[n++] = word.byte[1]; /* LSB */
-		frame[n++] = word.byte[0]; /* MSB */
-#endif
+		IRDA_DEBUG(2, "Requested BAUD_RATE: 0x%04x\n", param->pv.s);
+		final = param->pv.s & self->qos_rx.baud_rate.bits;
+
+		IRDA_DEBUG(2, "Final BAUD_RATE: 0x%04x\n", final);
+		self->qos_tx.baud_rate.bits = final;
+		self->qos_rx.baud_rate.bits = final;
 	}
 
-	/* Set Maximum Turn Around Time */
-	frame[n++] = PI_MAX_TURN_TIME;
-	frame[n++] = 0x01;   /* length 1 */
-	frame[n++] = qos->max_turn_time.bits;
-	
-	/* Set data size */
-	frame[n++] = PI_DATA_SIZE;
-	frame[n++] = 0x01;   /* length 1 */
-	frame[n++] = qos->data_size.bits;
-
-	/* Set window size */
-	frame[n++] = PI_WINDOW_SIZE;
-	frame[n++] = 0x01;   /* length 1 */
-	frame[n++] = qos->window_size.bits;
-
-	/* Set additional BOFs */
-	frame[n++] = PI_ADD_BOFS;
-	frame[n++] = 0x01;   /* length 1 */
-	frame[n++] = qos->additional_bofs.bits;
-
-	/* Set minimum turn around time */
-	frame[n++] = PI_MIN_TURN_TIME;
-	frame[n++] = 0x01;   /* length 1 */
-	frame[n++] = qos->min_turn_time.bits;
-
-	/* Set Link Disconnect/Threshold Time */
-	frame[n++] = PI_LINK_DISC;
-	frame[n++] = 0x01;   /* length 1 */
-	frame[n++] = qos->link_disc_time.bits;
-#ifdef CONFIG_IRDA_COMPRESSION
-	/* Set compression bits*/
-	if ( qos->compression.bits) {
-		DEBUG( 4, __FUNCTION__ "(), inserting compresion bits\n");
-		frame[n++] = PI_COMPRESSION;
-		frame[n++] = 0x01;   /* length 1 */
-		frame[n++] = qos->compression.bits;
+	return 0;
+}
+
+/*
+ * Function irlap_param_link_disconnect (instance, param, get)
+ *
+ *    Negotiate link disconnect/threshold time. 
+ *
+ */
+static int irlap_param_link_disconnect(void *instance, irda_param_t *param, 
+				       int get)
+{
+	__u16 final;
+	
+	struct irlap_cb *self = (struct irlap_cb *) instance;
+	
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LAP_MAGIC, return -1;);
+	
+	if (get)
+		param->pv.b = self->qos_rx.link_disc_time.bits;
+	else {
+		/*  
+		 *  Stations must agree on link disconnect/threshold 
+		 *  time.
+		 */
+		IRDA_DEBUG(2, "LINK_DISC: %02x\n", param->pv.b);
+		final = param->pv.b & self->qos_rx.link_disc_time.bits;
+
+		IRDA_DEBUG(2, "Final LINK_DISC: %02x\n", final);
+		self->qos_tx.link_disc_time.bits = final;
+		self->qos_rx.link_disc_time.bits = final;
 	}
-#endif
-	return n;
+	return 0;
 }
 
-int byte_value( __u8 byte, int *array) 
+/*
+ * Function irlap_param_max_turn_time (instance, param, get)
+ *
+ *    Negotiate the maximum turnaround time. This is a type 1 parameter and
+ *    will be negotiated independently for each station
+ *
+ */
+static int irlap_param_max_turn_time(void *instance, irda_param_t *param, 
+				     int get)
 {
-	int index;
+	struct irlap_cb *self = (struct irlap_cb *) instance;
+	
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LAP_MAGIC, return -1;);
+	
+	if (get)
+		param->pv.b = self->qos_rx.max_turn_time.bits;
+	else
+		self->qos_tx.max_turn_time.bits = param->pv.b;
+
+	return 0;
+}
+
+/*
+ * Function irlap_param_data_size (instance, param, get)
+ *
+ *    Negotiate the data size. This is a type 1 parameter and
+ *    will be negotiated independently for each station
+ *
+ */
+static int irlap_param_data_size(void *instance, irda_param_t *param, int get)
+{
+	struct irlap_cb *self = (struct irlap_cb *) instance;
+	
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LAP_MAGIC, return -1;);
+	
+	if (get)
+		param->pv.b = self->qos_rx.data_size.bits;
+	else
+		self->qos_tx.data_size.bits = param->pv.b;
 
-	ASSERT( array != NULL, return -1;);
+	return 0;
+}
+
+/*
+ * Function irlap_param_window_size (instance, param, get)
+ *
+ *    Negotiate the window size. This is a type 1 parameter and
+ *    will be negotiated independently for each station
+ *
+ */
+static int irlap_param_window_size(void *instance, irda_param_t *param, 
+				   int get)
+{
+	struct irlap_cb *self = (struct irlap_cb *) instance;
+	
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LAP_MAGIC, return -1;);
+	
+	if (get)
+		param->pv.b = self->qos_rx.window_size.bits;
+	else
+		self->qos_tx.window_size.bits = param->pv.b;
 
-	index = msb_index( byte);
-	return index_value( index, array);
+	return 0;
 }
 
+/*
+ * Function irlap_param_additional_bofs (instance, param, get)
+ *
+ *    Negotiate additional BOF characters. This is a type 1 parameter and
+ *    will be negotiated independently for each station.
+ */
+static int irlap_param_additional_bofs(void *instance, irda_param_t *param, int get)
+{
+	struct irlap_cb *self = (struct irlap_cb *) instance;
+	
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LAP_MAGIC, return -1;);
+	
+	if (get)
+		param->pv.b = self->qos_rx.additional_bofs.bits;
+	else
+		self->qos_tx.additional_bofs.bits = param->pv.b;
 
-/* __u8 value_byte( int value, int *array) */
-/* { */
-/* 	int index; */
-/* 	__u8 byte; */
+	return 0;
+}
 
-/* 	index = value_index( value, array); */
+/*
+ * Function irlap_param_min_turn_time (instance, param, get)
+ *
+ *    Negotiate the minimum turn around time. This is a type 1 parameter and
+ *    will be negotiated independently for each station
+ */
+static int irlap_param_min_turn_time(void *instance, irda_param_t *param, 
+				     int get)
+{
+	struct irlap_cb *self = (struct irlap_cb *) instance;
+	
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LAP_MAGIC, return -1;);
+	
+	if (get)
+		param->pv.b = self->qos_rx.min_turn_time.bits;
+	else
+		self->qos_tx.min_turn_time.bits = param->pv.b;
 
-/* 	byte =  */
-/* } */
+	return 0;
+}
+
+/*
+ * Function irlap_max_line_capacity (speed, max_turn_time, min_turn_time)
+ *
+ *    Calculate the maximum line capacity
+ *
+ */
+__u32 irlap_max_line_capacity(__u32 speed, __u32 max_turn_time)
+{
+	__u32 line_capacity;
+	int i,j;
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), speed=%d, max_turn_time=%d\n",
+		   speed, max_turn_time);
+
+	i = value_index(speed, baud_rates);
+	j = value_index(max_turn_time, max_turn_times);
+
+	ASSERT(((i >=0) && (i <=10)), return 0;);
+	ASSERT(((j >=0) && (j <=4)), return 0;);
+
+	line_capacity = max_line_capacities[i][j];
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), line capacity=%d bytes\n", 
+		   line_capacity);
+	
+	return line_capacity;
+}
+
+__u32 irlap_requested_line_capacity(struct qos_info *qos)
+{	__u32 line_capacity;
+	
+	line_capacity = qos->window_size.value * 
+		(qos->data_size.value + 6 + qos->additional_bofs.value) +
+		irlap_min_turn_time_in_bytes(qos->baud_rate.value, 
+					     qos->min_turn_time.value);
+	
+	IRDA_DEBUG(2, __FUNCTION__ "(), requested line capacity=%d\n",
+		   line_capacity);
+	
+	return line_capacity;			       		  
+}
+
+__u32 irlap_min_turn_time_in_bytes(__u32 speed, __u32 min_turn_time)
+{
+	__u32 bytes;
+	
+	bytes = speed * min_turn_time / 10000000;
+	
+	return bytes;
+}
+
+__u32 byte_value(__u8 byte, __u32 *array) 
+{
+	int index;
+
+	ASSERT(array != NULL, return -1;);
+
+	index = msb_index(byte);
+
+	return index_value(index, array);
+}
 
 /*
  * Function msb_index (word)
@@ -371,18 +591,18 @@
  *    Returns index to most significant bit (MSB) in word
  *
  */
-int msb_index ( __u16 word) 
+int msb_index (__u16 word) 
 {
 	__u16 msb = 0x8000;
 	int index = 15;   /* Current MSB */
 	
-	while( msb) {
-		if ( word & msb)
+	while (msb) {
+		if (word & msb)
 			break;   /* Found it! */
 		msb >>=1;
 		index--;
 	}
-
+	
 	return index;
 }
 
@@ -391,12 +611,12 @@
  *
  *    Returns the index to the value in the specified array
  */
-int value_index( int value, int *array) 
+int value_index(__u32 value, __u32 *array) 
 {
 	int i;
 	
-	for( i=0;i<8;i++)
-		if ( array[i] == value)
+	for (i=0;i<8;i++)
+		if (array[i] == value)
 			break;
 	return i;
 }
@@ -407,44 +627,50 @@
  *    Returns value to index in array, easy!
  *
  */
-int index_value( int index, int *array) 
+__u32 index_value(int index, __u32 *array) 
 {
 	return array[index];
 }
 
-void irda_qos_bits_to_value( struct qos_info *qos)
+void irda_qos_bits_to_value(struct qos_info *qos)
 {
 	int index;
 
-	ASSERT( qos != NULL, return;);
+	ASSERT(qos != NULL, return;);
 	
-	index = msb_index( qos->baud_rate.bits);
+	index = msb_index(qos->baud_rate.bits);
 	qos->baud_rate.value = baud_rates[index];
 
-	index = msb_index( qos->data_size.bits);
-	qos->data_size.value = data_size[index];
+	index = msb_index(qos->data_size.bits);
+	qos->data_size.value = data_sizes[index];
 
-	index = msb_index( qos->window_size.bits);
+	index = msb_index(qos->window_size.bits);
 	qos->window_size.value = index+1;
 
-	index = msb_index( qos->min_turn_time.bits);
-	qos->min_turn_time.value = min_turn_time[index];
+	index = msb_index(qos->min_turn_time.bits);
+	qos->min_turn_time.value = min_turn_times[index];
 	
-	index = msb_index( qos->max_turn_time.bits);
-	qos->max_turn_time.value = max_turn_time[index];
+	index = msb_index(qos->max_turn_time.bits);
+	qos->max_turn_time.value = max_turn_times[index];
 
-	index = msb_index( qos->link_disc_time.bits);
-	qos->link_disc_time.value = link_disc_time[index];
+	index = msb_index(qos->link_disc_time.bits);
+	qos->link_disc_time.value = link_disc_times[index];
 	
-	index = msb_index( qos->additional_bofs.bits);
+	index = msb_index(qos->additional_bofs.bits);
 	qos->additional_bofs.value = add_bofs[index];
 
 #ifdef CONFIG_IRDA_COMPRESSION
-	index = msb_index( qos->compression.bits);
-	if ( index >= 0)
-		qos->compression.value = compression[index];
+	index = msb_index(qos->compression.bits);
+	if (index >= 0)
+		qos->compression.value = compressions[index];
 	else 
 		qos->compression.value = 0;
 #endif
 }
+
+
+
+
+
+
 
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/timer.c linux.15p9/net/irda/timer.c
--- linux.vanilla/net/irda/timer.c	Sun Mar  7 23:26:44 1999
+++ linux.15p9/net/irda/timer.c	Tue Jan 18 01:08:19 2000
@@ -6,10 +6,11 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Aug 16 00:59:29 1997
- * Modified at:   Thu Feb  4 10:49:38 1999
+ * Modified at:   Wed Dec  8 12:50:34 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>, 
+ *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -31,84 +32,88 @@
 #include <net/irda/irlap.h>
 #include <net/irda/irlmp_event.h>
 
-static void irlap_slot_timer_expired( unsigned long data);
-static void irlap_query_timer_expired( unsigned long data);
-static void irlap_final_timer_expired( unsigned long data);
-static void irlap_wd_timer_expired( unsigned long data);
-static void irlap_backoff_timer_expired( unsigned long data);
+static void irlap_slot_timer_expired(void* data);
+static void irlap_query_timer_expired(void* data);
+static void irlap_final_timer_expired(void* data);
+static void irlap_wd_timer_expired(void* data);
+static void irlap_backoff_timer_expired(void* data);
 
-static void irda_device_media_busy_expired( unsigned long data); 
+static void irlap_media_busy_expired(void* data); 
 /*
  * Function irda_start_timer (timer, timeout)
  *
  *    Start an IrDA timer
  *
  */
-void irda_start_timer( struct timer_list *ptimer, int timeout, int data,
-		       TIMER_CALLBACK callback) 
+void irda_start_timer(struct timer_list *ptimer, int timeout, void *data,
+		      TIMER_CALLBACK callback) 
 {
-	del_timer( ptimer);
+	del_timer(ptimer);
  
 	ptimer->data = (unsigned long) data;
-	ptimer->function = callback;
+
+	/* 
+	 * For most architectures void * is the same as unsigned long, but
+	 * at least we try to use void * as long as possible. Since the 
+	 * timer functions use unsigned long, we cast the function here
+	 */
+	ptimer->function = (void (*)(unsigned long)) callback;
 	ptimer->expires = jiffies + timeout;
 	
-	add_timer( ptimer);
+	add_timer(ptimer);
 }
 
-inline void irlap_start_slot_timer( struct irlap_cb *self, int timeout)
+void irlap_start_slot_timer(struct irlap_cb *self, int timeout)
 {
-	irda_start_timer( &self->slot_timer, timeout, (unsigned long) self, 
-			  irlap_slot_timer_expired);
+	irda_start_timer(&self->slot_timer, timeout, (void *) self, 
+			 irlap_slot_timer_expired);
 }
 
-inline void irlap_start_query_timer( struct irlap_cb *self, int timeout)
+void irlap_start_query_timer(struct irlap_cb *self, int timeout)
 {
-	irda_start_timer( &self->query_timer, timeout, (unsigned long) self, 
+	irda_start_timer( &self->query_timer, timeout, (void *) self, 
 			  irlap_query_timer_expired);
 }
 
-inline void irlap_start_final_timer( struct irlap_cb *self, int timeout)
+void irlap_start_final_timer(struct irlap_cb *self, int timeout)
 {
-	irda_start_timer( &self->final_timer, timeout,  (unsigned long) self, 
-			  irlap_final_timer_expired);
+	irda_start_timer(&self->final_timer, timeout, (void *) self, 
+			 irlap_final_timer_expired);
 }
 
-inline void irlap_start_wd_timer( struct irlap_cb *self, int timeout)
+void irlap_start_wd_timer(struct irlap_cb *self, int timeout)
 {
-	irda_start_timer( &self->wd_timer, timeout, (unsigned long) self, 
-			  irlap_wd_timer_expired);
+	irda_start_timer(&self->wd_timer, timeout, (void *) self, 
+			 irlap_wd_timer_expired);
 }
 
-inline void irlap_start_backoff_timer( struct irlap_cb *self, int timeout)
+void irlap_start_backoff_timer(struct irlap_cb *self, int timeout)
 {
-	irda_start_timer( &self->backoff_timer, timeout, (unsigned long) self, 
-			  irlap_backoff_timer_expired);
+	irda_start_timer(&self->backoff_timer, timeout, (void *) self, 
+			 irlap_backoff_timer_expired);
 }
 
-inline void irda_device_start_mbusy_timer( struct irda_device *self) 
+void irlap_start_mbusy_timer(struct irlap_cb *self)
 {
-	irda_start_timer( &self->media_busy_timer, MEDIABUSY_TIMEOUT, 
-			  (unsigned long) self, 
-			  irda_device_media_busy_expired);
-	
+	irda_start_timer(&self->media_busy_timer, MEDIABUSY_TIMEOUT, 
+			 (void *) self, irlap_media_busy_expired);
 }
 
-inline void irlmp_start_watchdog_timer( struct lsap_cb *self, int timeout) 
+void irlmp_start_watchdog_timer(struct lsap_cb *self, int timeout) 
 {
-	irda_start_timer( &self->watchdog_timer, timeout, (unsigned long) self,
-			  irlmp_watchdog_timer_expired);
+	irda_start_timer(&self->watchdog_timer, timeout, (void *) self,
+			 irlmp_watchdog_timer_expired);
 }
 
-inline void irlmp_start_discovery_timer(struct irlmp_cb *self, int timeout) 
+void irlmp_start_discovery_timer(struct irlmp_cb *self, int timeout) 
 {
-	irda_start_timer(&self->discovery_timer, timeout, (unsigned long) self,
+	irda_start_timer(&self->discovery_timer, timeout, (void *) self,
 			 irlmp_discovery_timer_expired);
 }
 
-inline void irlmp_start_idle_timer(struct lap_cb *self, int timeout) 
+void irlmp_start_idle_timer(struct lap_cb *self, int timeout) 
 {
-	irda_start_timer(&self->idle_timer, timeout, (unsigned long) self,
+	irda_start_timer(&self->idle_timer, timeout, (void *) self,
 			 irlmp_idle_timer_expired);
 }
 
@@ -118,16 +123,14 @@
  *    IrLAP slot timer has expired
  *
  */
-static void irlap_slot_timer_expired( unsigned long data)
+static void irlap_slot_timer_expired(void *data)
 {
 	struct irlap_cb *self = (struct irlap_cb *) data;
 
-	DEBUG( 4, "Slot timer expired!\n");
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
 
-	irlap_do_event( self, SLOT_TIMER_EXPIRED, NULL, NULL);
+	irlap_do_event(self, SLOT_TIMER_EXPIRED, NULL, NULL);
 } 
 
 /*
@@ -136,16 +139,14 @@
  *    IrLAP query timer has expired
  *
  */
-static void irlap_query_timer_expired( unsigned long data)
+static void irlap_query_timer_expired(void *data)
 {
 	struct irlap_cb *self = (struct irlap_cb *) data;
 
-	DEBUG( 4, "Query timer expired!\n");
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LAP_MAGIC, return;);
-
-	irlap_do_event( self, QUERY_TIMER_EXPIRED, NULL, NULL);
+	irlap_do_event(self, QUERY_TIMER_EXPIRED, NULL, NULL);
 } 
 
 /*
@@ -154,16 +155,14 @@
  *    
  *
  */
-static void irlap_final_timer_expired( unsigned long data)
+static void irlap_final_timer_expired(void *data)
 {
 	struct irlap_cb *self = (struct irlap_cb *) data;
 
-	DEBUG( 4, "Final timer expired!\n");
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
 
-	irlap_do_event( self, FINAL_TIMER_EXPIRED, NULL, NULL);
+	irlap_do_event(self, FINAL_TIMER_EXPIRED, NULL, NULL);
 }
 
 /*
@@ -172,16 +171,14 @@
  *    
  *
  */
-static void irlap_wd_timer_expired( unsigned long data)
+static void irlap_wd_timer_expired(void *data)
 {
 	struct irlap_cb *self = (struct irlap_cb *) data;
 	
-	DEBUG( 4, "WD timer expired!\n");
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
 	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LAP_MAGIC, return;);
-	
-	irlap_do_event( self, WD_TIMER_EXPIRED, NULL, NULL);
+	irlap_do_event(self, WD_TIMER_EXPIRED, NULL, NULL);
 }
 
 /*
@@ -190,16 +187,14 @@
  *    
  *
  */
-static void irlap_backoff_timer_expired( unsigned long data)
+static void irlap_backoff_timer_expired(void *data)
 {
 	struct irlap_cb *self = (struct irlap_cb *) data;
 	
-	DEBUG( 0, "Backoff timer expired!\n");
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
 	
-	irlap_do_event( self, BACKOFF_TIMER_EXPIRED, NULL, NULL);
+	irlap_do_event(self, BACKOFF_TIMER_EXPIRED, NULL, NULL);
 }
 
 
@@ -208,14 +203,15 @@
  *
  *    
  */
-void irda_device_media_busy_expired( unsigned long data) 
+void irlap_media_busy_expired(void* data)
 {
-	struct irda_device *self = ( struct irda_device *) data;
+	struct irlap_cb *self = (struct irlap_cb *) data;
 
-	DEBUG( 4, "Mediabusy timer expired!\n");
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRDA_DEVICE_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+
+	irda_device_set_media_busy(self->netdev, FALSE);
 
-	irda_device_set_media_busy( self, FALSE);
+	/* Send any pending Ultra frames if any */
+	if (!skb_queue_empty(&self->txq_ultra))
+		irlap_do_event(self, SEND_UI_FRAME, NULL, NULL);
 }
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/irda/wrapper.c linux.15p9/net/irda/wrapper.c
--- linux.vanilla/net/irda/wrapper.c	Sat Aug 14 02:26:54 1999
+++ linux.15p9/net/irda/wrapper.c	Tue Jan 18 01:08:19 2000
@@ -3,13 +3,15 @@
  * Filename:      wrapper.c
  * Version:       1.2
  * Description:   IrDA SIR async wrapper layer
- * Status:        Experimental.
+ * Status:        Stable
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Fri May 28 20:30:24 1999
+ * Modified at:   Sat Jan 15 13:32:27 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * Modified at:   Fri May 28  3:11 CST 1999
+ * Modified by:   Horst von Brand <vonbrand@sleipnir.valparaiso.cl>
  * 
- *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
+ *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>, 
  *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
@@ -24,6 +26,7 @@
  ********************************************************************/
 
 #include <linux/skbuff.h>
+#include <linux/string.h>
 #include <asm/byteorder.h>
 
 #include <net/irda/irda.h>
@@ -36,12 +39,21 @@
 
 static inline int stuff_byte(__u8 byte, __u8 *buf);
 
-static void state_outside_frame(struct irda_device *idev, __u8 byte);
-static void state_begin_frame(struct irda_device *idev, __u8 byte);
-static void state_link_escape(struct irda_device *idev, __u8 byte);
-static void state_inside_frame(struct irda_device *idev, __u8 byte);
+static void state_outside_frame(struct device *dev, 
+				struct net_device_stats *stats, 
+				iobuff_t *rx_buff, __u8 byte);
+static void state_begin_frame(struct device *dev, 
+			      struct net_device_stats *stats, 
+			      iobuff_t *rx_buff, __u8 byte);
+static void state_link_escape(struct device *dev, 
+			      struct net_device_stats *stats, 
+			      iobuff_t *rx_buff, __u8 byte);
+static void state_inside_frame(struct device *dev, 
+			       struct net_device_stats *stats, 
+			       iobuff_t *rx_buff, __u8 byte);
 
-static void (*state[])(struct irda_device *idev, __u8 byte) = 
+static void (*state[])(struct device *dev, struct net_device_stats *stats, 
+		       iobuff_t *rx_buff, __u8 byte) = 
 { 
 	state_outside_frame,
 	state_begin_frame,
@@ -50,16 +62,16 @@
 };
 
 /*
- * Function async_wrap (skb, *tx_buff)
+ * Function async_wrap (skb, *tx_buff, buffsize)
  *
  *    Makes a new buffer with wrapping and stuffing, should check that 
  *    we don't get tx buffer overflow.
  */
 int async_wrap_skb(struct sk_buff *skb, __u8 *tx_buff, int buffsize)
 {
+	int xbofs;
  	int i;
 	int n;
-	int xbofs;
 	union {
 		__u16 value;
 		__u8 bytes[2];
@@ -69,21 +81,28 @@
 	fcs.value = INIT_FCS;
 	n = 0;
 
-	if (skb->len > 2048) {
-		DEBUG(0, __FUNCTION__ "Warning size=%d of sk_buff to big!\n", 
-		      (int) skb->len);
-		return 0;
-	}
-	
 	/*
 	 *  Send  XBOF's for required min. turn time and for the negotiated
 	 *  additional XBOFS
 	 */
-	if (((struct irlap_skb_cb *)(skb->cb))->magic != LAP_MAGIC) {
-		DEBUG(1, __FUNCTION__ "(), wrong magic in skb!\n");
+	if (((struct irda_skb_cb *)(skb->cb))->magic != LAP_MAGIC) {
+		/* 
+		 * This will happen for all frames sent from user-space.
+		 * Nothing to worry about, but we set the default number of 
+		 * BOF's
+		 */
+		IRDA_DEBUG(1, __FUNCTION__ "(), wrong magic in skb!\n");
 		xbofs = 10;
 	} else
-		xbofs = ((struct irlap_skb_cb *)(skb->cb))->xbofs;
+		xbofs = ((struct irda_skb_cb *)(skb->cb))->xbofs;
+
+	IRDA_DEBUG(4, __FUNCTION__ "(), xbofs=%d\n", xbofs);
+
+	/* Check that we never use more than 115 + 48 xbofs */
+	if (xbofs > 163) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), too many xbofs (%d)\n", xbofs);
+		xbofs = 163;
+	}
 
 	memset(tx_buff+n, XBOF, xbofs);
 	n += xbofs;
@@ -119,40 +138,6 @@
 }
 
 /*
- * Function async_bump (idev)
- *
- *    Got a frame, make a copy of it, and pass it up the stack!
- *
- */
-static inline void async_bump(struct irda_device *idev, __u8 *buf, int len)
-{
-       	struct sk_buff *skb;
-
-	skb = dev_alloc_skb(len+1);
-	if (!skb)  {
-		idev->stats.rx_dropped++;
-		return;
-	}
-
-	/*  Align IP header to 20 bytes */
-	skb_reserve(skb, 1);
-	
-        /* Copy data without CRC */
-	memcpy(skb_put(skb, len-2), buf, len-2); 
-	
-	/* 
-	 *  Feed it to IrLAP layer 
-	 */
-	skb->dev = &idev->netdev;
-	skb->mac.raw  = skb->data;
-	skb->protocol = htons(ETH_P_IRDA);
-
-	netif_rx(skb);
-	idev->stats.rx_packets++;
-	idev->stats.rx_bytes += skb->len;	
-}
-
-/*
  * Function stuff_byte (byte, buf)
  *
  *    Byte stuff one single byte and put the result in buffer pointed to by
@@ -179,36 +164,75 @@
 }
 
 /*
- * Function async_unwrap (skb)
+ * Function async_bump (buf, len, stats)
+ *
+ *    Got a frame, make a copy of it, and pass it up the stack! We can try
+ *    to inline it since it's only called from state_inside_frame
+ */
+inline void async_bump(struct device *dev, struct net_device_stats *stats,
+		       __u8 *buf, int len)
+{
+       	struct sk_buff *skb;
+
+	skb = dev_alloc_skb(len+1);
+	if (!skb)  {
+		stats->rx_dropped++;
+		return;
+	}
+
+	/* Align IP header to 20 bytes */
+	skb_reserve(skb, 1);
+	
+        /* Copy data without CRC */
+	memcpy(skb_put(skb, len-2), buf, len-2); 
+	
+	/* Feed it to IrLAP layer */
+	skb->dev = dev;
+	skb->mac.raw  = skb->data;
+	skb->protocol = htons(ETH_P_IRDA);
+
+	netif_rx(skb);
+
+	stats->rx_packets++;
+	stats->rx_bytes += len;	
+}
+
+/*
+ * Function async_unwrap_char (dev, rx_buff, byte)
  *
  *    Parse and de-stuff frame received from the IrDA-port
  *
  */
-inline void async_unwrap_char(struct irda_device *idev, __u8 byte)
+inline void async_unwrap_char(struct device *dev, 
+			      struct net_device_stats *stats, 
+			      iobuff_t *rx_buff, __u8 byte)
 {
-	(*state[idev->rx_buff.state]) (idev, byte);
+	(*state[rx_buff->state])(dev, stats, rx_buff, byte);
 }
 	 
 /*
- * Function state_outside_frame (idev, byte)
+ * Function state_outside_frame (dev, rx_buff, byte)
  *
- *    
+ *    Not receiving any frame (or just bogus data)
  *
  */
-static void state_outside_frame(struct irda_device *idev, __u8 byte)
+static void state_outside_frame(struct device *dev, 
+				struct net_device_stats *stats, 
+				iobuff_t *rx_buff, __u8 byte)
 {
 	switch (byte) {
 	case BOF:
-		idev->rx_buff.state = BEGIN_FRAME;
-		idev->rx_buff.in_frame = TRUE;
+		rx_buff->state = BEGIN_FRAME;
+		rx_buff->in_frame = TRUE;
 		break;
 	case XBOF:
 		/* idev->xbofs++; */
 		break;
 	case EOF:
-		irda_device_set_media_busy( idev, TRUE);
+		irda_device_set_media_busy(dev, TRUE);
 		break;
 	default:
+		irda_device_set_media_busy(dev, TRUE);
 		break;
 	}
 }
@@ -219,58 +243,58 @@
  *    Begin of frame detected
  *
  */
-static void state_begin_frame(struct irda_device *idev, __u8 byte)
+static void state_begin_frame(struct device *dev, 
+			      struct net_device_stats *stats, 
+			      iobuff_t *rx_buff, __u8 byte)
 {
+	/* Time to initialize receive buffer */
+	rx_buff->data = rx_buff->head;
+	rx_buff->len = 0;
+	rx_buff->fcs = INIT_FCS;
+
 	switch (byte) {
 	case BOF:
 		/* Continue */
 		break;
 	case CE:
 		/* Stuffed byte */
-		idev->rx_buff.state = LINK_ESCAPE;
-
-		/* Time to initialize receive buffer */
-		idev->rx_buff.data = idev->rx_buff.head;
-		idev->rx_buff.len = 0;
+		rx_buff->state = LINK_ESCAPE;
 		break;
 	case EOF:
 		/* Abort frame */
-		idev->rx_buff.state = OUTSIDE_FRAME;
-		
-		idev->stats.rx_errors++;
-		idev->stats.rx_frame_errors++;
+		rx_buff->state = OUTSIDE_FRAME;
+		IRDA_DEBUG(1, __FUNCTION__ "(), abort frame\n");
+		stats->rx_errors++;
+		stats->rx_frame_errors++;
 		break;
-	default:	
-		/* Time to initialize receive buffer */
-		idev->rx_buff.data = idev->rx_buff.head;
-		idev->rx_buff.len = 0;
-
-		idev->rx_buff.data[idev->rx_buff.len++] = byte;
-		
-		idev->rx_buff.fcs = irda_fcs(INIT_FCS, byte);
-		idev->rx_buff.state = INSIDE_FRAME;
+	default:
+		rx_buff->data[rx_buff->len++] = byte;
+		rx_buff->fcs = irda_fcs(rx_buff->fcs, byte);
+		rx_buff->state = INSIDE_FRAME;
 		break;
 	}
 }
 
 /*
- * Function state_link_escape (idev, byte)
+ * Function state_link_escape (dev, byte)
  *
- *    
+ *    Found link escape character
  *
  */
-static void state_link_escape(struct irda_device *idev, __u8 byte)
+static void state_link_escape(struct device *dev, 
+			      struct net_device_stats *stats, 
+			      iobuff_t *rx_buff, __u8 byte)
 {
 	switch (byte) {
 	case BOF: /* New frame? */
-		idev->rx_buff.state = BEGIN_FRAME;
-		irda_device_set_media_busy(idev, TRUE);
+		rx_buff->state = BEGIN_FRAME;
+		irda_device_set_media_busy(dev, TRUE);
 		break;
 	case CE:
-		DEBUG(4, "WARNING: State not defined\n");
+		WARNING(__FUNCTION__ "(), state not defined\n");
 		break;
 	case EOF: /* Abort frame */
-		idev->rx_buff.state = OUTSIDE_FRAME;
+		rx_buff->state = OUTSIDE_FRAME;
 		break;
 	default:
 		/* 
@@ -278,59 +302,65 @@
 		 *  following CE, IrLAP p.114 
 		 */
 		byte ^= IRDA_TRANS;
-		if (idev->rx_buff.len < idev->rx_buff.truesize)  {
-			idev->rx_buff.data[idev->rx_buff.len++] = byte;
-			idev->rx_buff.fcs = irda_fcs(idev->rx_buff.fcs, byte);
-			idev->rx_buff.state = INSIDE_FRAME;
+		if (rx_buff->len < rx_buff->truesize)  {
+			rx_buff->data[rx_buff->len++] = byte;
+			rx_buff->fcs = irda_fcs(rx_buff->fcs, byte);
+			rx_buff->state = INSIDE_FRAME;
 		} else {
-			DEBUG(1, __FUNCTION__ 
-			      "(), Rx buffer overflow, aborting\n");
-			idev->rx_buff.state = OUTSIDE_FRAME;
+			IRDA_DEBUG(1, __FUNCTION__ "(), rx buffer overflow\n");
+			rx_buff->state = OUTSIDE_FRAME;
 		}
 		break;
 	}
 }
 
 /*
- * Function state_inside_frame (idev, byte)
+ * Function state_inside_frame (dev, byte)
  *
  *    Handle bytes received within a frame
  *
  */
-static void state_inside_frame(struct irda_device *idev, __u8 byte)
+static void state_inside_frame(struct device *dev, 
+			       struct net_device_stats *stats,
+			       iobuff_t *rx_buff, __u8 byte)
 {
+	int ret = 0; 
+
 	switch (byte) {
 	case BOF: /* New frame? */
-		idev->rx_buff.state = BEGIN_FRAME;
-		irda_device_set_media_busy(idev, TRUE);
+		rx_buff->state = BEGIN_FRAME;
+		irda_device_set_media_busy(dev, TRUE);
 		break;
 	case CE: /* Stuffed char */
-		idev->rx_buff.state = LINK_ESCAPE;
+		rx_buff->state = LINK_ESCAPE;
 		break;
 	case EOF: /* End of frame */
-		idev->rx_buff.state = OUTSIDE_FRAME;
-		idev->rx_buff.in_frame = FALSE;
+		rx_buff->state = OUTSIDE_FRAME;
+		rx_buff->in_frame = FALSE;
 		
-		/* Test FCS and deliver frame if it's good */
-		if (idev->rx_buff.fcs == GOOD_FCS) {
-			async_bump(idev, idev->rx_buff.data, 
-				   idev->rx_buff.len);
+		/* Test FCS and signal success if the frame is good */
+		if (rx_buff->fcs == GOOD_FCS) {
+			/* Deliver frame */
+			async_bump(dev, stats, rx_buff->data, rx_buff->len);
+			ret = TRUE;
+			break;
 		} else {
 			/* Wrong CRC, discard frame!  */
-			irda_device_set_media_busy(idev, TRUE); 
-			
-			idev->stats.rx_errors++;
-			idev->stats.rx_crc_errors++;
+			irda_device_set_media_busy(dev, TRUE); 
+
+			IRDA_DEBUG(1, __FUNCTION__ "(), crc error\n");
+			stats->rx_errors++;
+			stats->rx_crc_errors++;
 		}			
 		break;
 	default: /* Must be the next byte of the frame */
-		if (idev->rx_buff.len < idev->rx_buff.truesize)  {
-			idev->rx_buff.data[idev->rx_buff.len++] = byte;
-			idev->rx_buff.fcs = irda_fcs(idev->rx_buff.fcs, byte);
+		if (rx_buff->len < rx_buff->truesize)  {
+			rx_buff->data[rx_buff->len++] = byte;
+			rx_buff->fcs = irda_fcs(rx_buff->fcs, byte);
 		} else {
-			DEBUG(1, __FUNCTION__ 
+			IRDA_DEBUG(1, __FUNCTION__ 
 			      "(), Rx buffer overflow, aborting\n");
-			idev->rx_buff.state = OUTSIDE_FRAME;
+			rx_buff->state = OUTSIDE_FRAME;
 		}
 		break;
 	}
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/packet/af_packet.c linux.15p9/net/packet/af_packet.c
--- linux.vanilla/net/packet/af_packet.c	Tue Jan  4 21:19:03 2000
+++ linux.15p9/net/packet/af_packet.c	Fri Jan 14 16:02:48 2000
@@ -5,7 +5,7 @@
  *
  *		PACKET - implements raw packet sockets.
  *
- * Version:	$Id: af_packet.c,v 1.19 1999/03/21 05:23:03 davem Exp $
+ * Version:	$Id: af_packet.c,v 1.19.2.1 1999/12/04 05:45:02 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/sunrpc/sched.c linux.15p9/net/sunrpc/sched.c
--- linux.vanilla/net/sunrpc/sched.c	Sat Aug 14 02:26:22 1999
+++ linux.15p9/net/sunrpc/sched.c	Mon Feb  7 12:27:35 2000
@@ -413,18 +413,15 @@
 		}
 
 		/*
-		 * No handler for next step means exit.
-		 */
-		if (!task->tk_action)
-			break;
-
-		/*
 		 * Perform the next FSM step.
 		 * tk_action may be NULL when the task has been killed
 		 * by someone else.
 		 */
-		if (RPC_IS_RUNNING(task) && task->tk_action)
+		if (RPC_IS_RUNNING(task)) {
+			if (!task->tk_action)
+				break;
 			task->tk_action(task);
+		}
 
 		/*
 		 * Check whether task is sleeping.
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/wanrouter/wanmain.c linux.15p9/net/wanrouter/wanmain.c
--- linux.vanilla/net/wanrouter/wanmain.c	Tue Jan  4 21:19:03 2000
+++ linux.15p9/net/wanrouter/wanmain.c	Sun Jan 16 19:28:19 2000
@@ -118,6 +118,7 @@
 {
 	int err;
 	extern void wanpipe_init(void);
+	extern void wanpipe_init2(void);
 
 	printk(KERN_INFO "%s v%u.%u %s\n",
 		fullname, ROUTER_VERSION, ROUTER_RELEASE, copyright);
@@ -132,6 +133,7 @@
 
 #ifdef CONFIG_VENDOR_SANGOMA
 	wanpipe_init();
+	wanpipe_init2();
 #endif	
  
 	return err;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/net/x25/x25_link.c linux.15p9/net/x25/x25_link.c
--- linux.vanilla/net/x25/x25_link.c	Mon Jul 27 07:35:58 1998
+++ linux.15p9/net/x25/x25_link.c	Wed Feb 16 18:22:05 2000
@@ -74,6 +74,11 @@
 	del_timer(&neigh->t20timer);
 }
 
+static int x25_t20timer_pending(struct x25_neigh *neigh)
+{
+	return timer_pending(&neigh->t20timer);
+}
+
 /*
  *	This handles all restart and diagnostic frames.
  */
@@ -84,8 +89,9 @@
 	switch (frametype) {
 		case X25_RESTART_REQUEST:
 			x25_stop_t20timer(neigh);
+			if (!x25_t20timer_pending(neigh))
+				x25_transmit_restart_confirmation(neigh);
 			neigh->state = X25_LINK_STATE_3;
-			x25_transmit_restart_confirmation(neigh);
 			break;
 
 		case X25_RESTART_CONFIRMATION:
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/scripts/Menuconfig linux.15p9/scripts/Menuconfig
--- linux.vanilla/scripts/Menuconfig	Tue Jan  4 21:19:03 2000
+++ linux.15p9/scripts/Menuconfig	Tue Jan 18 01:05:12 2000
@@ -1220,7 +1220,7 @@
 
 DIALOG="./scripts/lxdialog/lxdialog"
 
-kernel_version="${VERSION}.${PATCHLEVEL}.${SUBLEVEL}"
+kernel_version="${VERSION}.${PATCHLEVEL}.${SUBLEVEL}${EXTRAVERSION}"
 
 backtitle="Linux Kernel v$kernel_version Configuration"
 
