diff -u --recursive --new-file v2.2.2/linux/CREDITS linux/CREDITS
--- v2.2.2/linux/CREDITS	Tue Feb 23 15:21:31 1999
+++ linux/CREDITS	Sun Mar  7 16:15:39 1999
@@ -1061,6 +1061,14 @@
 S: L3R 8B2
 S: Canada
 
+N: Russell Kroll
+E: rkroll@exploits.org
+W: http://www.exploits.org/
+D: V4L Aztech radio card driver, mods to Aimslab driver
+S: Post Office Box 49458
+S: Colorado Springs, Colorado 80949-9458
+S: USA
+
 N: Gero Kuhlmann
 E: gero@gkminix.han.de
 D: mounting root via NFS
@@ -2003,6 +2011,14 @@
 S: Chudenicka 8
 S: 10200 Prague 10, Hostivar
 S: Czech Republic
+
+N: James R. Van Zandt
+E: jrv@vanzandt.mv.com
+P: 1024/E298966D F0 37 4F FD E5 7E C5 E6  F1 A0 1E 22 6F 46 DA 0C
+D: Author and maintainer of the Double Talk speech synthesizer driver
+S: 27 Spencer Drive
+S: Nashua, New Hampshire 03062
+S: USA
 
 N: Andrew Veliath
 E: andrewtv@usa.net
diff -u --recursive --new-file v2.2.2/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.2.2/linux/Documentation/Configure.help	Tue Feb 23 15:21:31 1999
+++ linux/Documentation/Configure.help	Mon Mar  8 10:14:35 1999
@@ -1089,25 +1089,6 @@
   recommended to read the NET-3-HOWTO, available via FTP (user:
   anonymous) from ftp://metalab.unc.edu/pub/Linux/docs/HOWTO.
 
-Network aliasing
-CONFIG_NET_ALIAS
-  If you say Y here, you will be able to set multiple network
-  addresses on the same low-level network device driver. This is
-  typically used for services that act differently based on the
-  address they listen on (e.g. "multihosting" or "virtual domains" or
-  "virtual hosting services" on the web server apache and the ftp
-  server wuftpd -- read the Virtual-Services-HOWTO, available via FTP
-  (user: anonymous) from ftp://metalab.unc.edu/pub/Linux/docs/HOWTO)
-  or for connecting to different logical networks through the same
-  physical interface (most commonly an Ethernet networking card). See
-  Documentation/networking/alias.txt for more info.
-
-  This is the generic part, later when configuring network protocol
-  options you will be asked for protocol-specific aliasing support,
-  and you will have to say Y to at least one of them, most likely to
-  "IP: aliasing support". If you need this feature (for any protocol,
-  like IP) say Y; if unsure, say N.
-
 Socket filtering
 CONFIG_FILTER
   The Linux Socket Filter is derived from the Berkeley Packet Filter.
@@ -2099,7 +2080,7 @@
 CONFIG_PNP_PARPORT
   Some IEEE-1284 conforming parallel-port devices can identify
   themselves when requested. Say Y to enable this feature, or M to
-  compile it as a module (parport_ieee1284.o). If in doubt, say N.
+  compile it as a module (parport_probe.o). If in doubt, say N.
 
 Enable loadable module support
 CONFIG_MODULES
@@ -2735,20 +2716,6 @@
   enabled. Those programs that would benefit from disabling this
   facility can do it on a per connection basis themselves.
 
-IP: Drop source routed frames
-CONFIG_IP_NOSR
-  Usually, the originator of an IP frame (packet) specifies only the
-  destination, and the hosts along the way do the routing, i.e. they
-  decide how to forward the frame. However, there is a feature of the
-  IP protocol that allows to specify the full route for a given frame
-  already at its origin. A frame with such a fully specified route is
-  called "source routed". The question now is whether we should honour
-  these route requests when such frames arrive, or if we should drop
-  all those frames instead. Honouring them can introduce security
-  problems (and is rarely a useful feature), and hence it is
-  recommended that you say Y here unless you really know what you're
-  doing.
-
 IP: Allow large windows (not recommended if <16 MB of memory)
 CONFIG_SKB_LARGE
   On high speed, long distance networks the performance limit on
@@ -4203,6 +4170,17 @@
   say M here and read Documentation/modules.txt. The module will be
   called initio.o
 
+Initio 91XXU(W) SCSI support
+CONFIG_SCSI_INITIO
+  This is support for the Initio 91XXU(W) SCSI host adapter.
+  Please read the SCSI-HOWTO, available via FTP (user: anonymous) at
+  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.
+
+  If you want to compile this as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read Documentation/modules.txt. The module will be
+  called initio.o
+
 PAS16 SCSI support
 CONFIG_SCSI_PAS16
   This is support for a SCSI host adapter. It is explained in section
@@ -4216,6 +4194,17 @@
   The module will be called pas16.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
 
+Initio INI-A100U2W SCSI support
+CONFIG_SCSI_INIA100
+  This is support for the Initio INI-A100U2W SCSI host adapter.
+  Please read the SCSI-HOWTO, available via FTP (user: anonymous) at
+  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.
+
+  If you want to compile this as a module ( = code which can be 
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read Documentation/modules.txt. The module will be
+  called a100u2w.o
+
 PCI2000 support
 CONFIG_SCSI_PCI2000
   This is support for the PCI2000I EIDE interface card which acts as a
@@ -4408,6 +4397,23 @@
   say M here and read Documentation/modules.txt. The module will be
   called NCR53c406.o.
 
+Symbios Logic sym53c416 support
+CONFIG_SCSI_SYM53C416
+  This is support for the sym53c416 SCSI host adapter. This is the
+  SCSI adapter that comes with some hp scanners. This driver requires that
+  the sym53c416 is configured first using some sort of pnp configuration
+  program (e.g. isapnp) or by a PnP aware BIOS. If you are using isapnp then
+  you need to compile it as a module and then load it using insmod after
+  isapnp has run. The parameters of the configured card(s) should be passed
+  to the driver. The format is:
+
+    insmod sym53c416 sym53c416=<base>,<irq> [sym53c416_1=<base>,<irq>]
+
+  There is support for up to four adapters. If you want to compile this
+  driver as a module ( = code which can be inserted in and removed from
+  the running kernel whenever you want), say M here and read
+  Documentation/modules.txt.
+
 Tekram DC390(T) and Am53/79C974 (PCscsi) SCSI support
 CONFIG_SCSI_DC390T
   This driver supports PCI SCSI host adapters based on the Am53C974A
@@ -8485,6 +8491,15 @@
   This driver does not exist at this point, so you might as well 
   say N.
 
+Double Talk PC internal speech card support
+CONFIG_DTLK
+  This driver is for the DoubleTalk PC, a speech synthesizer
+  manufactured by RC Systems (http://www.rcsys.com/).  It is also
+  called the `internal DoubleTalk'.  If you want to compile this as a
+  module ( = code which can be inserted in and removed from the
+  running kernel whenever you want), say M here and read
+  Documentation/modules.txt. The module will be called dtlk.o.
+
 Advanced Power Management
 CONFIG_APM
   APM is a BIOS specification for saving power using several different
@@ -8924,6 +8939,20 @@
   here (the module will be called sound.o) if you haven't found a
   driver for your sound card above, then pick your driver from the
   list below.
+
+Persistent DMA buffers
+CONFIG_SOUND_DMAP
+  Linux can often have problems allocating DMA buffers for ISA cards on
+  machines with more than 16MB of RAM. This is because ISA DMA buffers
+  must exist below the 16MB boundry and it is quite possible that we
+  can't find a large enough free block in this region after the machine
+  has been running for any amount of time. If you say Y here the DMA
+  buffers (64Kb) will be allocated at boot time and kept until the
+  shutdown. This option is only usefull if you say Y to OSS sound
+  modules. If you say M to OSS sound modules then you can just pass to
+  the sound.o module a "dmabuf=1" command-line argument.
+
+  Say Y unless you have 16MB or less RAM or a PCI sound card.
  
 Support for Aztech Sound Galaxy (non-PnP) cards
 CONFIG_SOUND_SGALAXY
@@ -10503,6 +10532,44 @@
 CONFIG_RADIO_SF16FMI_PORT
   Enter the I/O port of your SF16FMI radio card.
 
+Typhoon Radio
+CONFIG_RADIO_TYPHOON
+  Choose Y here if you have one of these FM radio cards, and then fill
+  in the port address and the frequency used for muting below.
+
+  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
+  http://roadrunner.swansea.uk.linux.org/v4l.shtml; to browse the WWW,
+  you need to have access to a machine on the Internet that has a 
+  program like lynx or netscape.
+
+  If you want to compile this driver as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read Documentation/modules.txt. The module will be
+  called radio-typhoon.o
+
+Support for /proc/radio-typhoon
+CONFIG_RADIO_TYPHOON_PROC_FS
+  Say Y here if you want the typhoon radio card driver to write
+  status information (frequency, volume, muted, mute frequency,
+  base address) to /proc/radio-typhoon. The file can be viewed with
+  your favorite pager (i.e. use "more /proc/radio-typhoon" or "less
+  /proc/radio-typhoon" or simply "cat /proc/radio-typhoon").
+
+Typhoon I/O port (0x316 or 0x336)
+CONFIG_RADIO_TYPHOON_PORT
+  Enter the I/O port of your Typhoon or EcoRadio radio card.
+
+Typhoon frequency set when muting the device (kHz)
+CONFIG_RADIO_TYPHOON_MUTEFREQ
+  Enter the frequency used for muting the radio. The device is never
+  completely silent. If the volume is just turned down, you can still
+  hear silent voices and music. For that reason, the frequency of the
+  radio device is set to the frequency you can enter here whenever
+  the device is muted. There should be no local radio station at that
+  frequency.
+
 Zoltrix Radio
 CONFIG_RADIO_ZOLTRIX
   Choose Y here if you have one of these FM radio cards, and then fill
@@ -10748,24 +10815,10 @@
   Documentation/modules.txt. IrLAN emulates an Ethernet and makes it
   possible to put up a wireless LAN using infrared beams.
 
-IrLAN Client Protocol 
-CONFIG_IRLAN_CLIENT
-  Say Y here if you want to build support for the IrLAN client
-  protocol. If you want to compile it as a module, say M here and read
-  Documentation/modules.txt. The IrLAN client protocol can be used to
-  talk with infrared access points like the HP NetbeamIR, or the ESI
-  JetEye NET. You can also connect to another Linux machine running
-  the IrLAN server protocol for ad-hoc networking!
-
-IrLAN Server Protocol 
-CONFIG_IRLAN_SERVER
-  Say Y here if you want to build support for infrared LAN access. If
-  you want to compile it as a module, say M here and read
-  Documentation/modules.txt. The IrLAN server protocol makes it
-  possible to set up a wireless LAN with a machine running the IrLAN
-  client protocol. Notice that the IrLAN server protocol currently
-  only emulates an access point and does not implement the ad-hoc
-  specification of IrLAN, but this will not be noticeable by the user.
+  The IrLAN protocol can be used to talk with infrared access points 
+  like the HP NetbeamIR, or the ESI JetEye NET. You can also connect 
+  to another Linux machine running the IrLAN protocol for ac-hoc 
+  networking!
 
 IrOBEX Protocol
 CONFIG_IROBEX
@@ -10877,6 +10930,15 @@
   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.
+
+Greenwich GIrBIL dongle
+CONFIG_GIRBIL_DONGLE
+  Say Y here if you want to build support for the Greenwich GIrBIL
+  dongle. If you want to compile it as a module, say M here and read
+  Documentation/modules.txt. The Greenwich dongle attaches to the
+  normal 9-pin serial port connector, and can currently only be used
+  by IrTTY. To activate support for Greenwich dongles you will have to
+  insert "irattach -d girbil" in the /etc/irda/drivers script.
 
 VME (Motorola and BVM) support
 CONFIG_VME
diff -u --recursive --new-file v2.2.2/linux/Documentation/filesystems/fat_cvf.txt linux/Documentation/filesystems/fat_cvf.txt
--- v2.2.2/linux/Documentation/filesystems/fat_cvf.txt	Wed Jun 24 22:54:02 1998
+++ linux/Documentation/filesystems/fat_cvf.txt	Sun Feb 28 09:47:37 1999
@@ -1,4 +1,4 @@
-This is the main documentation for the CVF-FAT filesystem extension.  31DEC1997
+This is the main documentation for the CVF-FAT filesystem extension.  18Nov1998
 
 
 Table of Contents:
@@ -37,14 +37,9 @@
   CVF filesystems cannot do bmap. It's impossible in principle. Thus
   all actions that require bmap do not work (swapping, writable mmapping).
   Read-only mmapping works because the FAT driver has a hack for this
-  situation :) Well, with some tricks writable mmapping could work,
-  (proof: they did under old dmsdos), but..... (hint: readpage/writepage
-  interface functions) ...... but the FAT driver has to support them 
-  first without bmap :-)
-
-  We'll see. If someone points me to an application that needs this, I
-  might be persuaded to implement it :). CVF-FAT is already prepared
-  for using readpage.
+  situation :) Well, writable mmapping should now work using the readpage
+  interface function which has been hacked into the FAT driver just for 
+  CVF-FAT :)
   
 - attention, DOSEmu users 
 
@@ -66,11 +61,28 @@
 
   cvf_format=xxx
     Forces the driver to use the CVF module "xxx" instead of auto-detection.
-    This is only necessary if the CVF format is not recognized correctly
+    Without this option, the CVF-FAT interface asks all currently loaded
+    CVF modules whether they recognize the CVF. Therefore, this option is
+    only necessary if the CVF format is not recognized correctly
     because of bugs or incompatibilities in the CVF modules. (It skips
     the detect_cvf call.) "xxx" may be the text "none" (without the quotes)
     to inhibit using any of the loaded CVF modules, just in case a CVF
-    module insists on mounting plain FAT filesystems by misunderstanding :)
+    module insists on mounting plain FAT filesystems by misunderstanding.
+    "xxx" may also be the text "autoload", which has a special meaning for
+    a module loader, but does not skip auto-detection.
+
+    If the kernel supports kmod, the cvf_format=xxx option also controls
+    on-demand CVF module loading. Without this option, nothing is loaded
+    on demand. With cvf_format=xxx, a module "xxx" is requested automatically
+    before mounting the compressed filesystem (unless "xxx" is "none"). In 
+    case there is a difference between the CVF format name and the module 
+    name, setup aliases in your modules configuration. If the string "xxx" 
+    is "autoload", a non-existent module "cvf_autoload" is requested which 
+    can be used together with a special modules configuration (alias and 
+    pre-install statements) in order to load more than one CVF module, let 
+    them detect automatically which kind of CVF is to be mounted, and only 
+    keep the "right" module in memory. For examples please refer to the 
+    dmsdos documentation (ftp and http addresses see below).
 
   cvf_options=yyy
     Option string passed to the CVF module. I.e. only the "yyy" is passed
@@ -80,8 +92,8 @@
     misinterpretation by the FAT driver, which would recognize the text 
     after a comma as a FAT driver option and might get confused or print 
     strange error messages. The documentation for the CVF module should 
-    offer a different separation symbol, for example the dot ".", which
-    is only valid inside the string "yyy".
+    offer a different separation symbol, for example the dot "." or the
+    plus sign "+", which is only valid inside the string "yyy".
 
 
 4. Description of the CVF-FAT interface
@@ -120,11 +132,11 @@
       is set, mmap is set to generic_file_mmap and readpage is caught
       and redirected to the cvf_readpage function. If it is not set,
       readpage is set to generic_readpage and mmap is caught and redirected
-      to cvf_mmap.
+      to cvf_mmap. (If you want writable mmap use the readpage interface.)
   - detect_cvf:
       A function that is called to decide whether the filesystem is a CVF of
       the type the module supports. The detect_cvf function must return 0
-      for "NO, I DON'T KNOW THIS GARBAGE" or anything !=0 for "YES, THIS IS
+      for "NO, I DON'T KNOW THIS GARBAGE" or anything >0 for "YES, THIS IS
       THE KIND OF CVF I SUPPORT". The function must maintain the module
       usage counters for safety, i.e. do MOD_INC_USE_COUNT at the beginning
       and MOD_DEC_USE_COUNT at the end. The function *must not* assume that
@@ -180,11 +192,19 @@
   that has not been previously registered. The code uses the version id
   to distinguish the modules, so be sure to keep it unique.
 
-5. CVS Modules
+5. CVF Modules
 ------------------------------------------------------------------------------
 
 Refer to the dmsdos module (the successor of the dmsdos filesystem) for a
 sample implementation.  It can currently be found at
 
-  ftp://fb9nt.uni-duisburg.de/pub/linux/dmsdos
+  ftp://fb9nt.uni-duisburg.de/pub/linux/dmsdos/dmsdos-x.y.z.tgz
+  ftp://sunsite.unc.edu/pub/Linux/system/Filesystems/dosfs/dmsdos-x.y.z.tgz
+  ftp://ftp.uni-stuttgart.de/pub/systems/linux/local/system/dmsdos-x.y.z.tgz
+
+(where x.y.z is to be replaced with the actual version number). Full
+documentation about dmsdos is included in the dmsdos package, but can also
+be found at
 
+  http://fb9nt.uni-duisburg.de/mitarbeiter/gockel/software/dmsdos/index.html
+  http://www.yk.rim.or.jp/~takafumi/dmsdos/index.html (in Japanese).
diff -u --recursive --new-file v2.2.2/linux/Documentation/sound/CMI8330 linux/Documentation/sound/CMI8330
--- v2.2.2/linux/Documentation/sound/CMI8330	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/sound/CMI8330	Sun Mar  7 15:22:06 1999
@@ -0,0 +1,86 @@
+How to enable CMI 8330 soundchip on Linux
+------------------------------------------
+Stefan Laudat <Stefan.Laudat@asit.ro>
+
+Hello folks, 
+	
+	The CMI8330 soundchip is a very small chip found on many recent 
+	motherboards. In order to use it you just have to use a proper 
+        isapnp.conf and a little bit of patience. 
+	
+	Of course you will have to compile kernel sound support as module, 
+        as shown below:
+
+CONFIG_SOUND=m
+CONFIG_SOUND_OSS=m
+CONFIG_SOUND_SB=m
+CONFIG_SOUND_ADLIB=m
+CONFIG_SOUND_MPU401=m
+# Just for fun :)
+CONFIG_SOUND_MSS=m
+
+	The /etc/isapnp.conf file will be:
+
+<snip below>
+
+(READPORT 0x0203)
+(ISOLATE PRESERVE)
+(IDENTIFY *)
+(VERBOSITY 2)
+(CONFLICT (IO FATAL)(IRQ FATAL)(DMA FATAL)(MEM FATAL)) # or WARNING
+(VERIFYLD N)
+# WSS 
+
+(CONFIGURE CMI0001/16777472 (LD 0
+(IO 0 (SIZE 8) (BASE 0x0530))
+(IO 1 (SIZE 8) (BASE 0x0388))
+(INT 0 (IRQ 5 (MODE +E)))
+(DMA 0 (CHANNEL 0))
+(NAME "CMI0001/16777472[0]{CMI8330/C3D Audio Adapter}")
+(ACT Y)
+))
+
+# Control device ? 
+
+(CONFIGURE CMI0001/16777472 (LD 1
+(IO 0 (SIZE 2) (BASE 0x0330))
+(INT 0 (IRQ 11 (MODE +E)))
+(NAME "CMI0001/16777472[1]{CMI8330/C3D Audio Adapter}")
+(ACT Y)
+))
+
+# Joystick
+
+(CONFIGURE CMI0001/16777472 (LD 2
+(IO 0 (SIZE 8) (BASE 0x0200))
+(NAME "CMI0001/16777472[2]{CMI8330/C3D Audio Adapter}")
+(ACT Y)
+))
+
+#  SB... 
+(CONFIGURE CMI0001/16777472 (LD 3
+(IO 0 (SIZE 16) (BASE 0x0220))
+(INT 0 (IRQ 7 (MODE +E)))
+(DMA 0 (CHANNEL 1))
+(DMA 1 (CHANNEL 5))
+(NAME "CMI0001/16777472[3]{CMI8330/C3D Audio Adapter}")
+(ACT Y)
+))
+
+
+(WAITFORKEY)
+
+<end of snip>
+
+	The module sequence is trivial:
+
+/sbin/modprobe sound
+# You need to load the ad1848 module first. That matters, otherwise the 
+# chip falls into soundblaster compatibility and you won't get it back out
+/sbin/insmod ad1848 io=0x530 dma=0 irq=5 soundpro=1
+/sbin/insmod uart401
+/sbin/insmod sb io=0x220 irq=5 dma=1 dma16=-1
+/sbin/insmod mpu401 io=0x330
+/sbin/insmod opl3 io=0x388
+
+	The soundchip is now fully initialized. Enjoy it.
diff -u --recursive --new-file v2.2.2/linux/Documentation/sound/VIBRA16 linux/Documentation/sound/VIBRA16
--- v2.2.2/linux/Documentation/sound/VIBRA16	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/sound/VIBRA16	Sun Mar  7 15:22:06 1999
@@ -0,0 +1,80 @@
+Sound Blaster 16X Vibra addendum
+--------------------------------
+by Marius Ilioaea <mariusi@protv.ro>
+   Stefan Laudat  <stefan@asit.ro>
+
+Sat Mar 6 23:55:27 EET 1999
+
+			Hello again,
+	
+	Playing with a SB Vibra 16x soundcard we found it very difficult
+to setup because the kernel reported a lot of DMA errors and wouldn't
+simply play any sound.
+	A good starting point is that the vibra16x chip full-duplex facility
+is neither still exploited by the sb driver found in the linux kernel 
+(tried it with a 2.2.2-ac7), nor in the commercial OSS package (it reports
+it as half-duplex soundcard). Oh, I almost forgot, the RedHat sndconfig
+failed detecting it ;)
+	So, the big problem still remains, because the sb module wants a
+8-bit and a 16-bit dma, which we could not allocate for vibra... it supports
+only two 8-bit dma channels, the second one will be passed to the module
+as a 16 bit channel, the kernel will yield about that but everything will
+be okay, trust us. 
+	The only inconvenient you may find is that you will have
+some sound playing jitters if you have HDD dma support enabled - but this
+will happen with almost all soundcards...
+
+	A fully working isapnp.conf is just here:
+
+<snip here>
+
+(READPORT 0x0203)
+(ISOLATE PRESERVE)
+(IDENTIFY *)
+(VERBOSITY 2)
+(CONFLICT (IO FATAL)(IRQ FATAL)(DMA FATAL)(MEM FATAL)) # or WARNING
+# SB 16 and OPL3 devices
+(CONFIGURE CTL00f0/-1 (LD 0
+(INT 0 (IRQ 5 (MODE +E)))
+(DMA 0 (CHANNEL 1))
+(DMA 1 (CHANNEL 3))
+(IO 0 (SIZE 16) (BASE 0x0220))
+(IO 2 (SIZE 4) (BASE 0x0388))
+(NAME "CTL00f0/-1[0]{Audio               }")
+(ACT Y)
+))
+
+# Joystick device - only if you need it :-/
+
+(CONFIGURE CTL00f0/-1 (LD 1
+(IO 0 (SIZE 1) (BASE 0x0200))
+(NAME "CTL00f0/-1[1]{Game                }")
+(ACT Y)
+))
+(WAITFORKEY)
+
+<end of snipping>
+
+	So, after a good kernel modules compilation and a 'depmod -a kernel_ver'
+you may want to:
+
+modprobe sb io=0x220 irq=5 dma=1 dma16=3
+
+	Or, take the hard way:
+
+insmod souncore
+insmod sound
+insmod uart401
+insmod sb io=0x220 irq=5 dma=1 dma16=3
+# do you need MIDI?
+insmod opl3=0x388
+
+	Just in case, the kernel sound support should be:
+
+CONFIG_SOUND=m
+CONFIG_SOUND_OSS=m
+CONFIG_SOUND_SB=m
+	
+	Enjoy your new noisy Linux box! ;)
+	
+
diff -u --recursive --new-file v2.2.2/linux/MAINTAINERS linux/MAINTAINERS
--- v2.2.2/linux/MAINTAINERS	Tue Feb 23 15:21:32 1999
+++ linux/MAINTAINERS	Sun Mar  7 16:15:39 1999
@@ -246,6 +246,12 @@
 L:	linux-kernel@vger.rutgers.edu
 S:	Maintained
 
+DOUBLETALK DRIVER
+P:	James R. Van Zandt
+M:	jrv@vanzandt.mv.com
+L:	blinux-list@redhat.com
+S:	Maintained
+
 EATA-DMA SCSI DRIVER
 P:	Michael Neuffer
 M:	mike@i-Connect.Net
@@ -324,7 +330,7 @@
 M:	arobinso@nyx.net
 L:	linux-kernel@vger.rutgers.edu
 W:	http://www.nyx.net/~arobinso
-S:	Maintainted
+S:	Maintained
 
 HFS FILESYSTEM
 P:      Adrian Sun
@@ -522,7 +528,7 @@
 
 NETWORKING [IPv4/IPv6]
 P:	David S. Miller
-M:	davem@dm.cobaltmicro.com
+M:	davem@redhat.com
 P:	Andi Kleen
 M:	ak@muc.de
 P:	Alexey Kuznetsov
@@ -678,9 +684,18 @@
 S:	Supported
 
 SPARC:
+P:	David S. Miller
+M:	davem@dm.cobaltmicro.com
 P:	Eddie C. Dost
 M:	ecd@skynet.be
+P:	Jakub Jelinek
+M:	jj@sunsite.ms.mff.cuni.cz
+P:	Anton Blanchard
+M:	anton@jubilex.progsoc.uts.edu.au
 L:	sparclinux@vger.rutgers.edu
+L:	ultralinux@vger.rutgers.edu
+W:	http://ultra.linux.cz
+W:	http://www.geog.ubc.ca/s_linux.html
 S:	Maintained
 
 SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER
diff -u --recursive --new-file v2.2.2/linux/Makefile linux/Makefile
--- v2.2.2/linux/Makefile	Tue Feb 23 15:21:32 1999
+++ linux/Makefile	Wed Feb 24 16:30:59 1999
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 2
-SUBLEVEL = 2
+SUBLEVEL = 3
 EXTRAVERSION =
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
diff -u --recursive --new-file v2.2.2/linux/arch/alpha/boot/main.c linux/arch/alpha/boot/main.c
--- v2.2.2/linux/arch/alpha/boot/main.c	Sun Aug  4 03:37:59 1996
+++ linux/arch/alpha/boot/main.c	Thu Feb 25 10:46:51 1999
@@ -22,61 +22,27 @@
 extern int vsprintf(char *, const char *, va_list);
 extern unsigned long switch_to_osf_pal(unsigned long nr,
 	struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa,
-	unsigned long vptb, unsigned long *kstk);
-
-int printk(const char * fmt, ...)
-{
-	va_list args;
-	int i, j, written, remaining, num_nl;
-	static char buf[1024];
-	char * str;
-
-	va_start(args, fmt);
-	i = vsprintf(buf, fmt, args);
-	va_end(args);
-
-	/* expand \n into \r\n: */
-
-	num_nl = 0;
-	for (j = 0; j < i; ++j) {
-	    if (buf[j] == '\n')
-	    	++num_nl;
-	}
-	remaining = i + num_nl;
-	for (j = i - 1; j >= 0; --j) {
-	    buf[j + num_nl] = buf[j];
-	    if (buf[j] == '\n') {
-	    	--num_nl;
-		buf[j + num_nl] = '\r';
-	    }
-	}
-
-	str = buf;
-	do {
-	    written = puts(str, remaining);
-	    remaining -= written;
-	    str += written;
-	} while (remaining > 0);
-	return i;
-}
-
-#define hwrpb (*INIT_HWRPB)
+	unsigned long *vptb);
+struct hwrpb_struct *hwrpb = INIT_HWRPB;
+static struct pcb_struct pcb_va[1];
 
 /*
  * Find a physical address of a virtual object..
  *
  * This is easy using the virtual page table address.
  */
-struct pcb_struct * find_pa(unsigned long *vptb, struct pcb_struct * pcb)
+
+static inline void *
+find_pa(unsigned long *vptb, void *ptr)
 {
-	unsigned long address = (unsigned long) pcb;
+	unsigned long address = (unsigned long) ptr;
 	unsigned long result;
 
 	result = vptb[address >> 13];
 	result >>= 32;
 	result <<= 13;
 	result |= address & 0x1fff;
-	return (struct pcb_struct *) result;
+	return (void *) result;
 }	
 
 /*
@@ -88,30 +54,19 @@
  * code has the L1 page table identity-map itself in the second PTE
  * in the L1 page table. Thus the L1-page is virtually addressable
  * itself (through three levels) at virtual address 0x200802000.
- *
- * As we don't want it there anyway, we also move the L1 self-map
- * up as high as we can, so that the last entry in the L1 page table
- * maps the page tables.
- *
- * As a result, the OSF/1 pal-code will instead use a virtual page table
- * map located at 0xffffffe00000000.
  */
-#define pcb_va ((struct pcb_struct *) 0x20000000)
-#define old_vptb (0x0000000200000000UL)
-#define new_vptb (0xfffffffe00000000UL)
-void pal_init(void)
+
+#define VPTB	((unsigned long *) 0x200000000)
+#define L1	((unsigned long *) 0x200802000)
+
+void
+pal_init(void)
 {
-	unsigned long i, rev, sum;
-	unsigned long *L1, *l;
+	unsigned long i, rev;
 	struct percpu_struct * percpu;
 	struct pcb_struct * pcb_pa;
 
-	/* Find the level 1 page table and duplicate it in high memory */
-	L1 = (unsigned long *) 0x200802000UL; /* (1<<33 | 1<<23 | 1<<13) */
-	L1[1023] = L1[1];
-
-	percpu = (struct percpu_struct *) (hwrpb.processor_offset + (unsigned long) &hwrpb),
-		
+	/* Create the dummy PCB.  */
 	pcb_va->ksp = 0;
 	pcb_va->usp = 0;
 	pcb_va->ptbr = L1[1] >> 32;
@@ -119,39 +74,32 @@
 	pcb_va->pcc = 0;
 	pcb_va->unique = 0;
 	pcb_va->flags = 1;
-	pcb_pa = find_pa((unsigned long *) old_vptb, pcb_va);
-	printk("Switching to OSF PAL-code .. ");
+	pcb_va->res1 = 0;
+	pcb_va->res2 = 0;
+	pcb_pa = find_pa(VPTB, pcb_va);
+
 	/*
 	 * a0 = 2 (OSF)
-	 * a1 = return address, but we give the asm the virtual addr of the PCB
+	 * a1 = return address, but we give the asm the vaddr of the PCB
 	 * a2 = physical addr of PCB
 	 * a3 = new virtual page table pointer
-	 * a4 = KSP (but we give it 0, asm sets it)
+	 * a4 = KSP (but the asm sets it)
 	 */
-	i = switch_to_osf_pal(
-		2,
-		pcb_va,
-		pcb_pa,
-		new_vptb,
-		0);
+	srm_printk("Switching to OSF PAL-code .. ");
+
+	i = switch_to_osf_pal(2, pcb_va, pcb_pa, VPTB);
 	if (i) {
-		printk("failed, code %ld\n", i);
+		srm_printk("failed, code %ld\n", i);
 		halt();
 	}
+
+	percpu = (struct percpu_struct *)
+		(INIT_HWRPB->processor_offset + (unsigned long) INIT_HWRPB);
 	rev = percpu->pal_revision = percpu->palcode_avail[2];
 
-	hwrpb.vptb = new_vptb;
+	srm_printk("Ok (rev %lx)\n", rev);
 
-	/* update checksum: */
-	sum = 0;
-	for (l = (unsigned long *) &hwrpb; l < (unsigned long *) &hwrpb.chksum; ++l)
-		sum += *l;
-	hwrpb.chksum = sum;
-
-	printk("Ok (rev %lx)\n", rev);
-	/* remove the old virtual page-table mapping */
-	L1[1] = 0;
-	flush_tlb_all();
+	tbia(); /* do it directly in case we are SMP */
 }
 
 static inline long openboot(void)
@@ -159,15 +107,15 @@
 	char bootdev[256];
 	long result;
 
-	result = dispatch(CCB_GET_ENV, ENV_BOOTED_DEV, bootdev, 255);
+	result = srm_dispatch(CCB_GET_ENV, ENV_BOOTED_DEV, bootdev, 255);
 	if (result < 0)
 		return result;
-	return dispatch(CCB_OPEN, bootdev, result & 255);
+	return srm_dispatch(CCB_OPEN, bootdev, result & 255);
 }
 
 static inline long close(long dev)
 {
-	return dispatch(CCB_CLOSE, dev);
+	return srm_dispatch(CCB_CLOSE, dev);
 }
 
 static inline long load(long dev, unsigned long addr, unsigned long count)
@@ -176,15 +124,15 @@
 	extern char _end;
 	long result, boot_size = &_end - (char *) BOOT_ADDR;
 
-	result = dispatch(CCB_GET_ENV, ENV_BOOTED_FILE, bootfile, 255);
+	result = srm_dispatch(CCB_GET_ENV, ENV_BOOTED_FILE, bootfile, 255);
 	if (result < 0)
 		return result;
 	result &= 255;
 	bootfile[result] = '\0';
 	if (result)
-		printk("Boot file specification (%s) not implemented\n",
+		srm_printk("Boot file specification (%s) not implemented\n",
 		       bootfile);
-	return dispatch(CCB_READ, dev, count, addr, boot_size/512 + 1);
+	return srm_dispatch(CCB_READ, dev, count, addr, boot_size/512 + 1);
 }
 
 /*
@@ -208,27 +156,27 @@
 	int nbytes;
 	char envval[256];
 
-	printk("Linux/AXP bootloader for Linux " UTS_RELEASE "\n");
-	if (hwrpb.pagesize != 8192) {
-		printk("Expected 8kB pages, got %ldkB\n", hwrpb.pagesize >> 10);
+	srm_printk("Linux/AXP bootloader for Linux " UTS_RELEASE "\n");
+	if (INIT_HWRPB->pagesize != 8192) {
+		srm_printk("Expected 8kB pages, got %ldkB\n", INIT_HWRPB->pagesize >> 10);
 		return;
 	}
 	pal_init();
 	dev = openboot();
 	if (dev < 0) {
-		printk("Unable to open boot device: %016lx\n", dev);
+		srm_printk("Unable to open boot device: %016lx\n", dev);
 		return;
 	}
 	dev &= 0xffffffff;
-	printk("Loading vmlinux ...");
+	srm_printk("Loading vmlinux ...");
 	i = load(dev, START_ADDR, KERNEL_SIZE);
 	close(dev);
 	if (i != KERNEL_SIZE) {
-		printk("Failed (%lx)\n", i);
+		srm_printk("Failed (%lx)\n", i);
 		return;
 	}
 
-	nbytes = dispatch(CCB_GET_ENV, ENV_BOOTED_OSFLAGS,
+	nbytes = srm_dispatch(CCB_GET_ENV, ENV_BOOTED_OSFLAGS,
 			  envval, sizeof(envval));
 	if (nbytes < 0) {
 		nbytes = 0;
@@ -236,7 +184,7 @@
 	envval[nbytes] = '\0';
 	strcpy((char*)ZERO_PAGE, envval);
 
-	printk(" Ok\nNow booting the kernel\n");
+	srm_printk(" Ok\nNow booting the kernel\n");
 	runkernel();
 	for (i = 0 ; i < 0x100000000 ; i++)
 		/* nothing */;
diff -u --recursive --new-file v2.2.2/linux/arch/alpha/defconfig linux/arch/alpha/defconfig
--- v2.2.2/linux/arch/alpha/defconfig	Mon Dec 28 15:00:52 1998
+++ linux/arch/alpha/defconfig	Thu Feb 25 10:46:46 1999
@@ -91,7 +91,6 @@
 # CONFIG_PACKET is not set
 # CONFIG_NETLINK is not set
 # CONFIG_FIREWALL is not set
-# CONFIG_NET_ALIAS is not set
 # CONFIG_FILTER is not set
 CONFIG_UNIX=y
 CONFIG_INET=y
diff -u --recursive --new-file v2.2.2/linux/arch/arm/defconfig linux/arch/arm/defconfig
--- v2.2.2/linux/arch/arm/defconfig	Thu Aug  6 14:06:28 1998
+++ linux/arch/arm/defconfig	Thu Feb 25 10:46:46 1999
@@ -80,7 +80,6 @@
 # CONFIG_PACKET is not set
 # CONFIG_NETLINK is not set
 # CONFIG_FIREWALL is not set
-# CONFIG_NET_ALIAS is not set
 # CONFIG_FILTER is not set
 CONFIG_UNIX=y
 CONFIG_INET=y
diff -u --recursive --new-file v2.2.2/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.2.2/linux/arch/i386/defconfig	Tue Feb 23 15:21:32 1999
+++ linux/arch/i386/defconfig	Sun Mar  7 20:38:44 1999
@@ -104,7 +104,6 @@
 CONFIG_PACKET=y
 # CONFIG_NETLINK is not set
 # CONFIG_FIREWALL is not set
-# CONFIG_NET_ALIAS is not set
 # CONFIG_FILTER is not set
 CONFIG_UNIX=y
 CONFIG_INET=y
@@ -121,7 +120,6 @@
 # (it is safe to leave these untouched)
 #
 # CONFIG_INET_RARP is not set
-CONFIG_IP_NOSR=y
 CONFIG_SKB_LARGE=y
 
 #
@@ -172,7 +170,9 @@
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_GENERIC_NCR5380 is not set
 # CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_NCR53C7xx is not set
 CONFIG_SCSI_NCR53C8XX=y
 CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=4
@@ -186,6 +186,7 @@
 # CONFIG_SCSI_PSI240I is not set
 # CONFIG_SCSI_QLOGIC_FAS is not set
 # CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_SEAGATE is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_T128 is not set
@@ -281,6 +282,7 @@
 # Joystick support
 #
 # CONFIG_JOYSTICK is not set
+# CONFIG_DTLK is not set
 
 #
 # Ftape, the floppy tape device driver
diff -u --recursive --new-file v2.2.2/linux/arch/i386/kernel/bios32.c linux/arch/i386/kernel/bios32.c
--- v2.2.2/linux/arch/i386/kernel/bios32.c	Wed Jan 20 23:14:04 1999
+++ linux/arch/i386/kernel/bios32.c	Mon Mar  8 11:08:02 1999
@@ -14,7 +14,7 @@
  *	Hannover, Germany
  *	hm@ix.de
  *
- * Copyright 1997, 1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ * Copyright 1997--1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
  *
  * For more information, please consult the following manuals (look at
  * http://www.pcisig.com/ for how to get them):
@@ -71,6 +71,10 @@
  *	a large gallery of common hardware bug workarounds (watch the comments)
  *	-- the PCI specs themselves are sane, but most implementors should be
  *	hit hard with \hammer scaled \magstep5. [mj]
+ *
+ * Jan 23, 1999 : More improvements to peer host bridge logic. i450NX fixup. [mj]
+ *
+ * Feb 8,  1999 : Added UM8886BF I/O address fixup. [mj]
  */
 
 #include <linux/config.h>
@@ -171,6 +175,7 @@
 #define PCI_NO_SORT 0x100
 #define PCI_BIOS_SORT 0x200
 #define PCI_NO_CHECKS 0x400
+#define PCI_NO_PEER_FIXUP 0x800
 
 static unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2;
 
@@ -521,6 +526,8 @@
 	unsigned short segment;
 } pci_indirect = { 0, __KERNEL_CS };
 
+static int pci_bios_present;
+
 __initfunc(static int check_pcibios(void))
 {
 	u32 signature, eax, ebx, ecx;
@@ -803,7 +810,7 @@
  * which used BIOS ordering, we are bound to do this...
  */
 
-__initfunc(void pcibios_sort(void))
+static void __init pcibios_sort(void)
 {
 	struct pci_dev *dev = pci_devices;
 	struct pci_dev **last = &pci_devices;
@@ -856,7 +863,7 @@
 
 static int pci_last_io_addr __initdata = 0x5800;
 
-__initfunc(void pcibios_fixup_io_addr(struct pci_dev *dev, int idx))
+static void __init pcibios_fixup_io_addr(struct pci_dev *dev, int idx)
 {
 	unsigned short cmd;
 	unsigned int reg = PCI_BASE_ADDRESS_0 + 4*idx;
@@ -868,13 +875,16 @@
 		printk("PCI: Unassigned I/O space for %02x:%02x\n", bus, devfn);
 		return;
 	}
-	if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && idx < 4) {
+	if (((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && idx < 4) ||
+	     (dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) {
 		/*
 		 * In case the BIOS didn't assign an address 0--3 to an IDE
 		 * controller, we don't try to fix it as it means "use default
 		 * addresses" at least with several broken chips and the IDE
 		 * driver needs the original settings to recognize which devices
 		 * correspond to the primary controller.
+		 *
+		 * We don't assign VGA I/O ranges as well.
 		 */
 		return;
 	}
@@ -914,7 +924,7 @@
  * expected to be unique) and remove the ghost devices.
  */
 
-__initfunc(void pcibios_fixup_ghosts(struct pci_bus *b))
+static void __init pcibios_fixup_ghosts(struct pci_bus *b)
 {
 	struct pci_dev *d, *e, **z;
 	int mirror = PCI_DEVFN(16,0);
@@ -954,12 +964,17 @@
  * the reality doesn't pass this test and the bus number is usually
  * set by BIOS to the first free value.
  */
-__initfunc(void pcibios_fixup_peer_bridges(void))
+static void __init pcibios_fixup_peer_bridges(void)
 {
 	struct pci_bus *b = &pci_root;
 	int i, n, cnt=-1;
 	struct pci_dev *d;
 
+#ifdef CONFIG_VISWS
+	pci_scan_peer_bridge(1);
+	return;
+#endif
+
 #ifdef CONFIG_PCI_DIRECT
 	/*
 	 * Don't search for peer host bridges if we use config type 2
@@ -969,6 +984,7 @@
 	if (access_pci == &pci_direct_conf2)
 		return;
 #endif
+
 	for(d=b->devices; d; d=d->sibling)
 		if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST)
 			cnt++;
@@ -979,6 +995,20 @@
 		for(i=0; i<256; i += 8)
 			if (!pcibios_read_config_word(n, i, PCI_VENDOR_ID, &l) &&
 			    l != 0x0000 && l != 0xffff) {
+#ifdef CONFIG_PCI_BIOS
+				if (pci_bios_present) {
+					int succ, idx = 0;
+					u8 bios_bus, bios_dfn;
+					u16 d;
+					pcibios_read_config_word(n, i, PCI_DEVICE_ID, &d);
+					DBG("BIOS test for %02x:%02x (%04x:%04x)\n", n, i, l, d);
+					while ((succ = pci_bios_find_device(l, d, idx, &bios_bus, &bios_dfn)) &&
+					       (bios_bus != n || bios_dfn != i))
+						idx++;
+					if (!succ)
+						break;
+				}
+#endif
 				DBG("Found device at %02x:%02x\n", n, i);
 				found++;
 				if (!pcibios_read_config_word(n, i, PCI_CLASS_DEVICE, &l) &&
@@ -989,13 +1019,7 @@
 			break;
 		if (found) {
 			printk("PCI: Discovered primary peer bus %02x\n", n);
-			b = kmalloc(sizeof(*b), GFP_KERNEL);
-			memset(b, 0, sizeof(*b));
-			b->next = pci_root.next;
-			pci_root.next = b;
-			b->number = b->secondary = n;
-			b->subordinate = 0xff;
-			b->subordinate = pci_scan_bus(b);
+			b = pci_scan_peer_bridge(n);
 			n = b->subordinate;
 		}
 		n++;
@@ -1003,11 +1027,75 @@
 }
 
 /*
+ * Exceptions for specific devices. Usually work-arounds for fatal design flaws.
+ */
+
+static void __init pci_fixup_i450nx(struct pci_dev *d)
+{
+	/*
+	 * i450NX -- Find and scan all secondary buses on all PXB's.
+	 */
+	int pxb, reg;
+	u8 busno, suba, subb;
+	reg = 0xd0;
+	for(pxb=0; pxb<2; pxb++) {
+		pci_read_config_byte(d, reg++, &busno);
+		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_probe |= PCI_NO_PEER_FIXUP;
+}
+
+static void __init pci_fixup_umc_ide(struct pci_dev *d)
+{
+	/*
+	 * UM8886BF IDE controller sets region type bits incorrectly,
+	 * therefore they look like memory despite of them being I/O.
+	 */
+	int i;
+
+	for(i=0; i<4; i++)
+		d->base_address[i] |= PCI_BASE_ADDRESS_SPACE_IO;
+}
+
+struct dev_ex {
+	u16 vendor, device;
+	void (*handler)(struct pci_dev *);
+	char *comment;
+};
+
+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_UMC,		PCI_DEVICE_ID_UMC_UM8886BF,	pci_fixup_umc_ide,	"Working around UM8886BF bugs" }
+};
+
+static void __init pcibios_scan_buglist(struct pci_bus *b)
+{
+	struct pci_dev *d;
+	int i;
+
+	for(d=b->devices; d; d=d->sibling)
+		for(i=0; i<sizeof(dev_ex_table)/sizeof(dev_ex_table[0]); i++) {
+			struct dev_ex *e = &dev_ex_table[i];
+			if (e->vendor == d->vendor && e->device == d->device) {
+				printk("PCI: %02x:%02x [%04x/%04x]: %s\n",
+					b->number, d->devfn, d->vendor, d->device, e->comment);
+				e->handler(d);
+			}
+		}
+}
+
+/*
  * Fix base addresses, I/O and memory enables and IRQ's (mostly work-arounds
  * for buggy PCI BIOS'es :-[).
  */
 
-__initfunc(void pcibios_fixup_devices(void))
+static void __init pcibios_fixup_devices(void)
 {
 	struct pci_dev *dev;
 	int i, has_io, has_mem;
@@ -1099,7 +1187,8 @@
 
 __initfunc(void pcibios_fixup(void))
 {
-	pcibios_fixup_peer_bridges();
+	if (!(pci_probe & PCI_NO_PEER_FIXUP))
+		pcibios_fixup_peer_bridges();
 	pcibios_fixup_devices();
 
 #ifdef CONFIG_PCI_BIOS
@@ -1111,6 +1200,7 @@
 __initfunc(void pcibios_fixup_bus(struct pci_bus *b))
 {
 	pcibios_fixup_ghosts(b);
+	pcibios_scan_buglist(b);
 }
 
 /*
@@ -1126,8 +1216,10 @@
 	struct pci_access *dir = NULL;
 
 #ifdef CONFIG_PCI_BIOS
-	if ((pci_probe & PCI_PROBE_BIOS) && ((bios = pci_find_bios())))
+	if ((pci_probe & PCI_PROBE_BIOS) && ((bios = pci_find_bios()))) {
 		pci_probe |= PCI_BIOS_SORT;
+		pci_bios_present = 1;
+	}
 #endif
 #ifdef CONFIG_PCI_DIRECT
 	if (pci_probe & (PCI_PROBE_CONF1 | PCI_PROBE_CONF2))
@@ -1139,10 +1231,6 @@
 		access_pci = bios;
 }
 
-#if !defined(CONFIG_PCI_BIOS) && !defined(CONFIG_PCI_DIRECT)
-#error PCI configured with neither PCI BIOS or PCI direct access support.
-#endif
-
 __initfunc(char *pcibios_setup(char *str))
 {
 	if (!strcmp(str, "off")) {
@@ -1178,5 +1266,9 @@
 		return NULL;
 	}
 #endif
+	else if (!strcmp(str, "nopeer")) {
+		pci_probe |= PCI_NO_PEER_FIXUP;
+		return NULL;
+	}
 	return str;
 }
diff -u --recursive --new-file v2.2.2/linux/arch/i386/kernel/time.c linux/arch/i386/kernel/time.c
--- v2.2.2/linux/arch/i386/kernel/time.c	Wed Jan 20 23:14:04 1999
+++ linux/arch/i386/kernel/time.c	Mon Mar  8 11:38:51 1999
@@ -30,19 +30,6 @@
  *	serialize accesses to xtime/lost_ticks).
  */
 
-/* What about the "updated NTP code" stuff in 2.0 time.c? It's not in
- * 2.1, perhaps it should be ported, too.
- *
- * What about the BUGGY_NEPTUN_TIMER stuff in do_slow_gettimeoffset()?
- * Whatever it fixes, is it also fixed in the new code from the Jumbo
- * patch, so that that code can be used instead?
- *
- * The CPU Hz should probably be displayed in check_bugs() together
- * with the CPU vendor and type. Perhaps even only in MHz, though that
- * takes away some of the fun of the new code :)
- *
- * - Michael Krause */
-
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -556,70 +543,72 @@
  * device.
  */
 
+#define CALIBRATE_LATCH	(5 * LATCH)
+#define CALIBRATE_TIME	(5 * 1000020/HZ)
+
 __initfunc(static unsigned long calibrate_tsc(void))
 {
-       unsigned long retval;
+       /* Set the Gate high, disable speaker */
+	outb((inb(0x61) & ~0x02) | 0x01, 0x61);
 
-       __asm__( /* set the Gate high, program CTC channel 2 for mode 0
-		 * (interrupt on terminal count mode), binary count, 
-		 * load 5 * LATCH count, (LSB and MSB)
-		 * to begin countdown, read the TSC and busy wait.
-		 * BTW LATCH is calculated in timex.h from the HZ value
-		 */
+	/*
+	 * Now let's take care of CTC channel 2
+	 *
+	 * Set the Gate high, program CTC channel 2 for mode 0,
+	 * (interrupt on terminal count mode), binary count,
+	 * load 5 * LATCH count, (LSB and MSB) to begin countdown.
+	 */
+	outb(0xb0, 0x43);			/* binary, mode 0, LSB/MSB, Ch 2 */
+	outb(CALIBRATE_LATCH & 0xff, 0x42);	/* LSB of count */
+	outb(CALIBRATE_LATCH >> 8, 0x42);	/* MSB of count */
 
-	       /* Set the Gate high, disable speaker */
-	       "inb  $0x61, %%al\n\t" /* Read port */
-	       "andb $0xfd, %%al\n\t" /* Turn off speaker Data */
-	       "orb  $0x01, %%al\n\t" /* Set Gate high */
-	       "outb %%al, $0x61\n\t" /* Write port */
-
-	       /* Now let's take care of CTC channel 2 */
-	       "movb $0xb0, %%al\n\t" /* binary, mode 0, LSB/MSB, ch 2*/
-	       "outb %%al, $0x43\n\t" /* Write to CTC command port */
-	       "movl %1, %%eax\n\t"
-	       "outb %%al, $0x42\n\t" /* LSB of count */
-	       "shrl $8, %%eax\n\t"
-	       "outb %%al, $0x42\n\t" /* MSB of count */
-
-               /* Read the TSC; counting has just started */
-               "rdtsc\n\t"
-               /* Move the value for safe-keeping. */
-               "movl %%eax, %%ebx\n\t"
-               "movl %%edx, %%ecx\n\t"
-
-	       /* Busy wait. Only 50 ms wasted at boot time. */
-               "0: inb $0x61, %%al\n\t" /* Read Speaker Output Port */
-	       "testb $0x20, %%al\n\t" /* Check CTC channel 2 output (bit 5) */
-               "jz 0b\n\t"
-
-               /* And read the TSC.  5 jiffies (50.00077ms) have elapsed. */
-               "rdtsc\n\t"
-
-               /* Great.  So far so good.  Store last TSC reading in
-                * last_tsc_low (only 32 lsb bits needed) */
-               "movl %%eax, last_tsc_low\n\t"
-               /* And now calculate the difference between the readings. */
-               "subl %%ebx, %%eax\n\t"
-               "sbbl %%ecx, %%edx\n\t" /* 64-bit subtract */
-	       /* but probably edx = 0 at this point (see below). */
-               /* Now we have 5 * (TSC counts per jiffy) in eax.  We want
-                * to calculate TSC->microsecond conversion factor. */
-
-               /* Note that edx (high 32-bits of difference) will now be 
-                * zero iff CPU clock speed is less than 85 GHz.  Moore's
-                * law says that this is likely to be true for the next
-                * 12 years or so.  You will have to change this code to
-                * do a real 64-by-64 divide before that time's up. */
-               "movl %%eax, %%ecx\n\t"
-               "xorl %%eax, %%eax\n\t"
-               "movl %2, %%edx\n\t"
-               "divl %%ecx\n\t" /* eax= 2^32 / (1 * TSC counts per microsecond) */
-	       /* Return eax for the use of fast_gettimeoffset */
-               "movl %%eax, %0\n\t"
-               : "=r" (retval)
-               : "r" (5 * LATCH), "r" (5 * 1000020/HZ)
-               : /* we clobber: */ "ax", "bx", "cx", "dx", "cc", "memory");
-       return retval;
+	{
+		unsigned long startlow, starthigh;
+		unsigned long endlow, endhigh;
+		unsigned long count;
+
+		__asm__ __volatile__("rdtsc":"=a" (startlow),"=d" (starthigh));
+		count = 0;
+		do {
+			count++;
+		} while ((inb(0x61) & 0x20) == 0);
+		__asm__ __volatile__("rdtsc":"=a" (endlow),"=d" (endhigh));
+
+		last_tsc_low = endlow;
+
+		/* Error: ECTCNEVERSET */
+		if (count <= 1)
+			goto bad_ctc;
+
+		/* 64-bit subtract - gcc just messes up with long longs */
+		__asm__("subl %2,%0\n\t"
+			"sbbl %3,%1"
+			:"=a" (endlow), "=d" (endhigh)
+			:"g" (startlow), "g" (starthigh),
+			 "0" (endlow), "1" (endhigh));
+
+		/* Error: ECPUTOOFAST */
+		if (endhigh)
+			goto bad_ctc;
+
+		/* Error: ECPUTOOSLOW */
+		if (endlow <= CALIBRATE_TIME)
+			goto bad_ctc;
+
+		__asm__("divl %2"
+			:"=a" (endlow), "=d" (endhigh)
+			:"r" (endlow), "0" (0), "1" (CALIBRATE_TIME));
+
+		return endlow;
+	}
+
+	/*
+	 * The CTC wasn't reliable: we got a hit on the very first read,
+	 * or the CPU was so fast/slow that the quotient wouldn't fit in
+	 * 32 bits..
+	 */
+bad_ctc:
+	return 0;
 }
 
 __initfunc(void time_init(void))
@@ -655,23 +644,26 @@
  	dodgy_tsc();
  	
 	if (boot_cpu_data.x86_capability & X86_FEATURE_TSC) {
+		unsigned long tsc_quotient = calibrate_tsc();
+		if (tsc_quotient) {
+			fast_gettimeoffset_quotient = tsc_quotient;
+			use_tsc = 1;
 #ifndef do_gettimeoffset
-		do_gettimeoffset = do_fast_gettimeoffset;
+			do_gettimeoffset = do_fast_gettimeoffset;
 #endif
-		do_get_fast_time = do_gettimeofday;
-		use_tsc = 1;
-		fast_gettimeoffset_quotient = calibrate_tsc();
-		
-		/* report CPU clock rate in Hz.
-		 * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) =
-		 * clock/second. Our precision is about 100 ppm.
-		 */
-		{	unsigned long eax=0, edx=1000000;
-			__asm__("divl %2"
-	       		:"=a" (cpu_hz), "=d" (edx)
-               		:"r" (fast_gettimeoffset_quotient),
-                	"0" (eax), "1" (edx));
-			printk("Detected %ld Hz processor.\n", cpu_hz);
+			do_get_fast_time = do_gettimeofday;
+
+			/* report CPU clock rate in Hz.
+			 * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) =
+			 * clock/second. Our precision is about 100 ppm.
+			 */
+			{	unsigned long eax=0, edx=1000000;
+				__asm__("divl %2"
+		       		:"=a" (cpu_hz), "=d" (edx)
+        	       		:"r" (tsc_quotient),
+	                	"0" (eax), "1" (edx));
+				printk("Detected %ld Hz processor.\n", cpu_hz);
+			}
 		}
 	}
 
diff -u --recursive --new-file v2.2.2/linux/arch/m68k/defconfig linux/arch/m68k/defconfig
--- v2.2.2/linux/arch/m68k/defconfig	Wed Jan 20 23:14:04 1999
+++ linux/arch/m68k/defconfig	Thu Feb 25 10:46:46 1999
@@ -78,7 +78,6 @@
 CONFIG_PACKET=y
 # CONFIG_NETLINK is not set
 # CONFIG_FIREWALL is not set
-# CONFIG_NET_ALIAS is not set
 # CONFIG_FILTER is not set
 CONFIG_UNIX=y
 CONFIG_INET=y
diff -u --recursive --new-file v2.2.2/linux/arch/mips/defconfig linux/arch/mips/defconfig
--- v2.2.2/linux/arch/mips/defconfig	Fri Oct 23 22:01:19 1998
+++ linux/arch/mips/defconfig	Thu Feb 25 10:46:47 1999
@@ -90,7 +90,6 @@
 # CONFIG_PACKET is not set
 # CONFIG_NETLINK is not set
 # CONFIG_FIREWALL is not set
-# CONFIG_NET_ALIAS is not set
 # CONFIG_FILTER is not set
 CONFIG_UNIX=y
 CONFIG_INET=y
diff -u --recursive --new-file v2.2.2/linux/arch/ppc/apus_defconfig linux/arch/ppc/apus_defconfig
--- v2.2.2/linux/arch/ppc/apus_defconfig	Mon Dec 28 15:00:52 1998
+++ linux/arch/ppc/apus_defconfig	Thu Feb 25 10:46:47 1999
@@ -100,7 +100,6 @@
 # CONFIG_RTNETLINK is not set
 # CONFIG_NETLINK_DEV is not set
 # CONFIG_FIREWALL is not set
-CONFIG_NET_ALIAS=y
 # CONFIG_FILTER is not set
 CONFIG_UNIX=y
 CONFIG_INET=y
diff -u --recursive --new-file v2.2.2/linux/arch/ppc/chrp_defconfig linux/arch/ppc/chrp_defconfig
--- v2.2.2/linux/arch/ppc/chrp_defconfig	Mon Dec 28 15:00:52 1998
+++ linux/arch/ppc/chrp_defconfig	Thu Feb 25 10:46:47 1999
@@ -85,7 +85,6 @@
 # CONFIG_PACKET is not set
 # CONFIG_NETLINK is not set
 # CONFIG_FIREWALL is not set
-CONFIG_NET_ALIAS=y
 # CONFIG_FILTER is not set
 CONFIG_UNIX=y
 CONFIG_INET=y
diff -u --recursive --new-file v2.2.2/linux/arch/ppc/common_defconfig linux/arch/ppc/common_defconfig
--- v2.2.2/linux/arch/ppc/common_defconfig	Fri Jan  8 22:36:02 1999
+++ linux/arch/ppc/common_defconfig	Thu Feb 25 10:46:47 1999
@@ -87,7 +87,6 @@
 # CONFIG_PACKET is not set
 # CONFIG_NETLINK is not set
 # CONFIG_FIREWALL is not set
-# CONFIG_NET_ALIAS is not set
 # CONFIG_FILTER is not set
 CONFIG_UNIX=y
 CONFIG_INET=y
diff -u --recursive --new-file v2.2.2/linux/arch/ppc/defconfig linux/arch/ppc/defconfig
--- v2.2.2/linux/arch/ppc/defconfig	Thu Jan  7 15:11:36 1999
+++ linux/arch/ppc/defconfig	Thu Feb 25 10:46:47 1999
@@ -102,7 +102,6 @@
 # CONFIG_RTNETLINK is not set
 # CONFIG_NETLINK_DEV is not set
 # CONFIG_FIREWALL is not set
-CONFIG_NET_ALIAS=y
 # CONFIG_FILTER is not set
 CONFIG_UNIX=y
 CONFIG_INET=y
diff -u --recursive --new-file v2.2.2/linux/arch/ppc/mbx_defconfig linux/arch/ppc/mbx_defconfig
--- v2.2.2/linux/arch/ppc/mbx_defconfig	Mon Dec 28 15:00:52 1998
+++ linux/arch/ppc/mbx_defconfig	Thu Feb 25 10:46:47 1999
@@ -75,7 +75,6 @@
 # CONFIG_PACKET is not set
 # CONFIG_NETLINK is not set
 # CONFIG_FIREWALL is not set
-# CONFIG_NET_ALIAS is not set
 # CONFIG_FILTER is not set
 CONFIG_UNIX=y
 CONFIG_INET=y
diff -u --recursive --new-file v2.2.2/linux/arch/ppc/pmac_defconfig linux/arch/ppc/pmac_defconfig
--- v2.2.2/linux/arch/ppc/pmac_defconfig	Thu Jan  7 15:11:36 1999
+++ linux/arch/ppc/pmac_defconfig	Thu Feb 25 10:46:47 1999
@@ -102,7 +102,6 @@
 # CONFIG_RTNETLINK is not set
 # CONFIG_NETLINK_DEV is not set
 # CONFIG_FIREWALL is not set
-CONFIG_NET_ALIAS=y
 # CONFIG_FILTER is not set
 CONFIG_UNIX=y
 CONFIG_INET=y
diff -u --recursive --new-file v2.2.2/linux/arch/ppc/prep_defconfig linux/arch/ppc/prep_defconfig
--- v2.2.2/linux/arch/ppc/prep_defconfig	Mon Dec 28 15:00:52 1998
+++ linux/arch/ppc/prep_defconfig	Thu Feb 25 10:46:47 1999
@@ -84,7 +84,6 @@
 # CONFIG_PACKET is not set
 # CONFIG_NETLINK is not set
 # CONFIG_FIREWALL is not set
-# CONFIG_NET_ALIAS is not set
 # CONFIG_FILTER is not set
 CONFIG_UNIX=y
 CONFIG_INET=y
diff -u --recursive --new-file v2.2.2/linux/arch/sparc/defconfig linux/arch/sparc/defconfig
--- v2.2.2/linux/arch/sparc/defconfig	Tue Dec 22 14:16:54 1998
+++ linux/arch/sparc/defconfig	Thu Feb 25 10:46:47 1999
@@ -101,7 +101,6 @@
 CONFIG_PACKET=y
 # CONFIG_NETLINK is not set
 # CONFIG_FIREWALL is not set
-# CONFIG_NET_ALIAS is not set
 # CONFIG_FILTER is not set
 CONFIG_UNIX=y
 CONFIG_INET=y
diff -u --recursive --new-file v2.2.2/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- v2.2.2/linux/arch/sparc64/defconfig	Tue Dec 22 14:16:54 1998
+++ linux/arch/sparc64/defconfig	Thu Feb 25 10:46:47 1999
@@ -128,7 +128,6 @@
 CONFIG_PACKET=y
 # CONFIG_NETLINK is not set
 # CONFIG_FIREWALL is not set
-# CONFIG_NET_ALIAS is not set
 # CONFIG_FILTER is not set
 CONFIG_UNIX=y
 CONFIG_INET=y
diff -u --recursive --new-file v2.2.2/linux/drivers/block/genhd.c linux/drivers/block/genhd.c
--- v2.2.2/linux/drivers/block/genhd.c	Tue Feb 23 15:21:32 1999
+++ linux/drivers/block/genhd.c	Wed Feb 24 16:27:53 1999
@@ -879,7 +879,7 @@
 	res = 0;
 
 	for (blk = 0; blk < RDB_ALLOCATION_LIMIT; blk++) {
-		if(!(bh = bread(dev,blk,get_ptable_blocksize(dev)))) {
+		if(!(bh = bread(dev,blk,512))) {
 			printk("Dev %s: unable to read RDB block %d\n",
 			       kdevname(dev),blk);
 			goto rdb_done;
@@ -896,7 +896,7 @@
 			blk = htonl(rdb->rdb_PartitionList);
 			brelse(bh);
 			for (part = 1; blk > 0 && part <= 16; part++) {
-				if (!(bh = bread(dev,blk, get_ptable_blocksize(dev)))) {
+				if (!(bh = bread(dev,blk, 512))) {
 					printk("Dev %s: unable to read partition block %d\n",
 						       kdevname(dev),blk);
 					goto rdb_done;
diff -u --recursive --new-file v2.2.2/linux/drivers/block/hd.c linux/drivers/block/hd.c
--- v2.2.2/linux/drivers/block/hd.c	Tue Jan 19 11:32:51 1999
+++ linux/drivers/block/hd.c	Wed Feb 24 16:27:53 1999
@@ -744,11 +744,12 @@
 		
 	*/
 
-		if ((cmos_disks = CMOS_READ(0x12)) & 0xf0)
+		if ((cmos_disks = CMOS_READ(0x12)) & 0xf0) {
 			if (cmos_disks & 0x0f)
 				NR_HD = 2;
 			else
 				NR_HD = 1;
+		}
 	}
 #endif /* __i386__ */
 	for (drive=0 ; drive < NR_HD ; drive++) {
diff -u --recursive --new-file v2.2.2/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v2.2.2/linux/drivers/block/ide.c	Tue Jan 19 11:32:51 1999
+++ linux/drivers/block/ide.c	Wed Feb 24 16:27:54 1999
@@ -2068,6 +2068,12 @@
 				(unsigned long *) &loc->start)) return -EFAULT;
 			return 0;
 		}
+		case BLKSSZGET:
+			/* Block size of media */
+			return put_user(blksize_size[HWIF(drive)->major]
+						    [minor&PARTN_MASK],
+						    (int *)arg);
+		
 		case BLKFLSBUF:
 			if (!capable(CAP_SYS_ADMIN)) return -EACCES;
 			fsync_dev(inode->i_rdev);
diff -u --recursive --new-file v2.2.2/linux/drivers/block/nbd.c linux/drivers/block/nbd.c
--- v2.2.2/linux/drivers/block/nbd.c	Tue Dec 22 14:16:55 1998
+++ linux/drivers/block/nbd.c	Mon Mar  8 13:05:11 1999
@@ -17,6 +17,7 @@
  * 97-4-11 Making protocol independent of endianity etc.
  * 97-9-13 Cosmetic changes
  * 98-5-13 Attempt to make 64-bit-clean on 64-bit machines
+ * 99-1-11 Attempt to make 64-bit-clean on 32-bit machines <ankry@mif.pg.gda.pl>
  *
  * possible FIXME: make set_sock / set_blksize / set_size / do_it one syscall
  * why not: would need verify_area and friends, would share yet another 
@@ -45,8 +46,9 @@
 #define LO_MAGIC 0x68797548
 
 static int nbd_blksizes[MAX_NBD];
+static int nbd_blksize_bits[MAX_NBD];
 static int nbd_sizes[MAX_NBD];
-static int nbd_bytesizes[MAX_NBD];
+static u64 nbd_bytesizes[MAX_NBD];
 
 static struct nbd_device nbd_dev[MAX_NBD];
 
@@ -149,7 +151,7 @@
 	DEBUG("NBD: sending control, ");
 	request.magic = htonl(NBD_REQUEST_MAGIC);
 	request.type = htonl(req->cmd);
-	request.from = cpu_to_be64( (u64) req->sector * (u64) 512);
+	request.from = cpu_to_be64( (u64) req->sector << 9);
 	request.len = htonl(req->current_nr_sectors << 9);
 	memcpy(request.handle, &req, sizeof(req));
 
@@ -340,7 +342,7 @@
 		     unsigned int cmd, unsigned long arg)
 {
 	struct nbd_device *lo;
-	int dev, error;
+	int dev, error, temp;
 
 	/* Anyone capable of this syscall can do *real bad* things */
 
@@ -355,6 +357,7 @@
 	lo = &nbd_dev[dev];
 	switch (cmd) {
 	case NBD_CLEAR_SOCK:
+		nbd_clear_que(lo);
 		if (lo->head || lo->tail) {
 			printk(KERN_ERR "nbd: Some requests are in progress -> can not turn off.\n");
 			return -EBUSY;
@@ -380,14 +383,25 @@
 		}
 		return error;
 	case NBD_SET_BLKSIZE:
-		if ((arg & 511) || (arg > PAGE_SIZE))
+		if ((arg & (arg-1)) || (arg < 512) || (arg > PAGE_SIZE))
 			return -EINVAL;
 		nbd_blksizes[dev] = arg;
-		nbd_sizes[dev] = arg/nbd_blksizes[dev];
+		temp = arg >> 9;
+		nbd_blksize_bits[dev] = 9;
+		while (temp > 1) {
+			nbd_blksize_bits[dev]++;
+			temp >>= 1;
+		}
+		nbd_sizes[dev] = nbd_bytesizes[dev] >> nbd_blksize_bits[dev];
+		nbd_bytesizes[dev] = nbd_sizes[dev] << nbd_blksize_bits[dev];
 		return 0;
 	case NBD_SET_SIZE:
-		nbd_bytesizes[dev] = arg;
-		nbd_sizes[dev] = arg/nbd_blksizes[dev];
+		nbd_sizes[dev] = arg >> nbd_blksize_bits[dev];
+		nbd_bytesizes[dev] = nbd_sizes[dev] << nbd_blksize_bits[dev];
+		return 0;
+	case NBD_SET_SIZE_BLOCKS:
+		nbd_sizes[dev] = arg;
+		nbd_bytesizes[dev] = arg << nbd_blksize_bits[dev];
 		return 0;
 	case NBD_DO_IT:
 		if (!lo->file)
@@ -404,7 +418,7 @@
 		return 0;
 #endif
 	case BLKGETSIZE:
-		return put_user(nbd_bytesizes[dev]/512, (long *) arg);
+		return put_user(nbd_bytesizes[dev] << 9, (long *) arg);
 	}
 	return -EINVAL;
 }
@@ -420,6 +434,7 @@
 	if (dev >= MAX_NBD)
 		return -ENODEV;
 	fsync_dev(inode->i_rdev);
+	invalidate_buffers(inode->i_rdev);
 	lo = &nbd_dev[dev];
 	if (lo->refcnt <= 0)
 		printk(KERN_ALERT "nbd_release: refcount(%d) <= 0\n", lo->refcnt);
@@ -478,8 +493,9 @@
 		nbd_dev[i].magic = LO_MAGIC;
 		nbd_dev[i].flags = 0;
 		nbd_blksizes[i] = 1024;
-		nbd_bytesizes[i] = 0x7fffffff;
-		nbd_sizes[i] = nbd_bytesizes[i]/nbd_blksizes[i];
+		nbd_blksize_bits[i] = 10;
+		nbd_bytesizes[i] = 0x7ffffc00; /* 2GB */
+		nbd_sizes[i] = nbd_bytesizes[i] >> nbd_blksize_bits[i];
 	}
 	return 0;
 }
diff -u --recursive --new-file v2.2.2/linux/drivers/block/rd.c linux/drivers/block/rd.c
--- v2.2.2/linux/drivers/block/rd.c	Wed Aug 26 11:37:35 1998
+++ linux/drivers/block/rd.c	Wed Feb 24 16:27:54 1999
@@ -170,14 +170,12 @@
 			break;
          	case BLKGETSIZE:   /* Return device size */
 			if (!arg)  return -EINVAL;
-			err = verify_area(VERIFY_WRITE, (long *) arg,
-					  sizeof(long));
-			if (err)
-				return err;
-			put_user(rd_length[MINOR(inode->i_rdev)] / 512, 
+			return put_user(rd_length[MINOR(inode->i_rdev)] / 512, 
 				 (long *) arg);
-			return 0;
-			
+		case BLKSSZGET:
+			/* Block size of media */
+			return put_user(rd_blocksizes[MINOR(inode->i_rdev)],
+						    (int *)arg);
 		default:
 			break;
 	};
diff -u --recursive --new-file v2.2.2/linux/drivers/char/Config.in linux/drivers/char/Config.in
--- v2.2.2/linux/drivers/char/Config.in	Mon Dec 28 15:00:52 1998
+++ linux/drivers/char/Config.in	Sun Mar  7 16:15:39 1999
@@ -139,6 +139,16 @@
   if [ "$CONFIG_RADIO_SF16FMI" = "y" ]; then
     hex '  SF16FMI I/O port (0x284 or 0x384)' CONFIG_RADIO_SF16FMI_PORT 284
   fi
+  dep_tristate 'Typhoon Radio (a.k.a. EcoRadio)' CONFIG_RADIO_TYPHOON $CONFIG_VIDEO_DEV
+  if [ "$CONFIG_PROC_FS" = "y" ]; then
+      if [ "$CONFIG_RADIO_TYPHOON" != "n" ]; then
+	bool '  Support for /proc/radio-typhoon' CONFIG_RADIO_TYPHOON_PROC_FS
+      fi
+  fi
+  if [ "$CONFIG_RADIO_TYPHOON" = "y" ]; then
+    hex '  Typhoon I/O port (0x316 or 0x336)' CONFIG_RADIO_TYPHOON_PORT 316
+    int '  Typhoon frequency set when muting the device (kHz)' CONFIG_RADIO_TYPHOON_MUTEFREQ 87500
+  fi
   dep_tristate 'Zoltrix Radio' CONFIG_RADIO_ZOLTRIX $CONFIG_VIDEO_DEV
   if [ "$CONFIG_RADIO_ZOLTRIX" = "y" ]; then
     hex '  ZOLTRIX I/O port (0x20c or 0x30c)' CONFIG_RADIO_ZOLTRIX_PORT 20c
@@ -155,6 +165,8 @@
   source drivers/char/joystick/Config.in
 fi
 endmenu
+
+tristate 'Double Talk PC internal speech card support' CONFIG_DTLK
 
 mainmenu_option next_comment
 comment 'Ftape, the floppy tape device driver'
diff -u --recursive --new-file v2.2.2/linux/drivers/char/Makefile linux/drivers/char/Makefile
--- v2.2.2/linux/drivers/char/Makefile	Mon Dec 28 15:00:52 1998
+++ linux/drivers/char/Makefile	Sun Mar  7 16:15:39 1999
@@ -176,6 +176,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_DTLK),y)
+L_OBJS += dtlk.o
+else
+  ifeq ($(CONFIG_DTLK),m)
+  M_OBJS += dtlk.o
+  endif
+endif
+
 ifeq ($(CONFIG_MS_BUSMOUSE),y)
 L_OBJS += msbusmouse.o
 else
@@ -361,6 +369,14 @@
 else
   ifeq ($(CONFIG_RADIO_RTRACK2),m)
   M_OBJS += radio-rtrack2.o
+  endif
+endif                                             
+
+ifeq ($(CONFIG_RADIO_TYPHOON),y)
+L_OBJS += radio-typhoon.o
+else
+  ifeq ($(CONFIG_RADIO_TYPHOON),m)
+  M_OBJS += radio-typhoon.o
   endif
 endif                                             
 
diff -u --recursive --new-file v2.2.2/linux/drivers/char/bttv.c linux/drivers/char/bttv.c
--- v2.2.2/linux/drivers/char/bttv.c	Tue Feb 23 15:21:33 1999
+++ linux/drivers/char/bttv.c	Mon Mar  8 10:14:40 1999
@@ -1558,12 +1558,33 @@
 static void bttv_close(struct video_device *dev)
 {
 	struct bttv *btv=(struct bttv *)dev;
-  
+	
 	btv->user--;
 	audio(btv, AUDIO_INTERN);
 	btv->cap&=~3;
 	bt848_set_risc_jmps(btv);
 
+	/*
+	 *	A word of warning. At this point the chip
+	 *	is still capturing because its FIFO hasn't emptied
+	 *	and the DMA control operations are posted PCI 
+	 *	operations.
+	 */
+
+	btread(BT848_I2C); 	/* This fixes the PCI posting delay */
+	
+	/*
+	 *	This is sucky but right now I can't find a good way to
+	 *	be sure its safe to free the buffer. We wait 5-6 fields
+	 *	which is more than sufficient to be sure.
+	 */
+	 
+	current->state = TASK_UNINTERRUPTIBLE;
+	schedule_timeout(HZ/10);	/* Wait 1/10th of a second */
+	
+	/*
+	 *	We have allowed it to drain.
+	 */
 	if(btv->fbuffer)
 		rvfree((void *) btv->fbuffer, 2*BTTV_MAX_FBUF);
 	btv->fbuffer=0;
@@ -3037,7 +3058,7 @@
 	btv->risc_jmp[12]=BT848_RISC_JUMP;
 	btv->risc_jmp[13]=virt_to_bus(btv->risc_jmp);
 
-	/* enable cpaturing and DMA */
+	/* enable capturing */
 	btaor(flags, ~0x0f, BT848_CAP_CTL);
 	if (flags&0x0f)
 		bt848_dma(btv, 3);
@@ -3242,7 +3263,7 @@
 		if (astat&BT848_INT_SCERR) {
 			IDEBUG(printk ("bttv%d: IRQ_SCERR\n", btv->nr));
 			bt848_dma(btv, 0);
-			bt848_dma(btv, 1);
+			bt848_dma(btv, 3);
 			wake_up_interruptible(&btv->vbiq);
 			wake_up_interruptible(&btv->capq);
 
diff -u --recursive --new-file v2.2.2/linux/drivers/char/console.c linux/drivers/char/console.c
--- v2.2.2/linux/drivers/char/console.c	Wed Jan 20 23:14:05 1999
+++ linux/drivers/char/console.c	Thu Feb 25 10:02:12 1999
@@ -203,7 +203,14 @@
 
 static inline unsigned short *screenpos(int currcons, int offset, int viewed)
 {
-	unsigned short *p = (unsigned short *)(visible_origin + offset);
+	unsigned short *p;
+	
+	if (!viewed)
+		p = (unsigned short *)(origin + offset);
+	else if (!sw->con_screen_pos)
+		p = (unsigned short *)(visible_origin + offset);
+	else
+		p = sw->con_screen_pos(vc_cons[currcons].d, offset);
 	return p;
 }
 
@@ -253,16 +260,16 @@
 	unsigned int xx, yy, offset;
 	u16 *p;
 
-	if (start < origin) {
-		count -= origin - start;
-		start = origin;
-	}
-	if (count <= 0)
-		return;
-	offset = (start - origin) / 2;
-	xx = offset % video_num_columns;
-	yy = offset / video_num_columns;
 	p = (u16 *) start;
+	if (!sw->con_getxy) {
+		offset = (start - origin) / 2;
+		xx = offset % video_num_columns;
+		yy = offset / video_num_columns;
+	} else {
+		int nxx, nyy;
+		start = sw->con_getxy(vc_cons[currcons].d, start, &nxx, &nyy);
+		xx = nxx; yy = nyy;
+	}
 	for(;;) {
 		u16 attrib = scr_readw(p) & 0xff00;
 		int startx = xx;
@@ -285,6 +292,10 @@
 			break;
 		xx = 0;
 		yy++;
+		if (sw->con_getxy) {
+			p = (u16 *)start;
+			start = sw->con_getxy(vc_cons[currcons].d, start, NULL, NULL);
+		}
 	}
 #endif
 }
@@ -2778,7 +2789,7 @@
 	set_cursor(currcons);
 }
 
-u16 vcs_scr_readw(int currcons, u16 *org)
+u16 vcs_scr_readw(int currcons, const u16 *org)
 {
 	if ((unsigned long)org == pos && softcursor_original != -1)
 		return softcursor_original;
diff -u --recursive --new-file v2.2.2/linux/drivers/char/dtlk.c linux/drivers/char/dtlk.c
--- v2.2.2/linux/drivers/char/dtlk.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/dtlk.c	Sun Mar  7 16:15:39 1999
@@ -0,0 +1,722 @@
+/*                                              -*- linux-c -*-
+ * dtlk.c - DoubleTalk PC driver for Linux kernel 2.0.29
+ * 
+ * $Id: dtlk.c,v 1.19 1999/02/28 12:13:13 jrv Exp jrv $
+ *
+ * Original author: Chris Pallotta <chris@allmedia.com>
+ * Current maintainer: Jim Van Zandt <jrv@vanzandt.mv.com>
+ */
+
+/* This driver is for the DoubleTalk PC, a speech synthesizer
+   manufactured by RC Systems (http://www.rcsys.com/).  It was written
+   based on documentation in their User's Manual file and Developer's
+   Tools disk.
+
+   The DoubleTalk PC contains four voice synthesizers: text-to-speech
+   (TTS), linear predictive coding (LPC), PCM/ADPCM, and CVSD.  It
+   also has a tone generator.  Output data for LPC are written to the
+   LPC port, and output data for the other modes are written to the
+   TTS port.
+
+   Two kinds of data can be read from the DoubleTalk: status
+   information (in response to the "\001?" interrogation command) is
+   read from the TTS port, and index markers (which mark the progress
+   of the speech) are read from the LPC port.  Not all models of the
+   DoubleTalk PC implement index markers.  Both the TTS and LPC ports
+   can also display status flags.
+
+   The DoubleTalk PC generates no interrupts.
+
+   These characteristics are mapped into the Unix stream I/O model as
+   follows:
+
+   "write" sends bytes to the TTS port.  It is the responsibility of
+   the user program to switch modes among TTS, PCM/ADPCM, and CVSD.
+   This driver was written for use with the text-to-speech
+   synthesizer.  If LPC output is needed some day, other minor device
+   numbers can be used to select among output modes.
+
+   "read" gets index markers from the LPC port.  If the device does
+   not implement index markers, the read will fail with error EINVAL.
+
+   Status information is available using the DTLK_INTERROGATE ioctl.
+
+ */
+
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+
+#ifdef MODULE
+#include <linux/module.h>
+#include <linux/version.h>
+#else
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#endif
+
+#define KERNEL
+#include <linux/config.h>
+
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/mm.h>		/* for verify_area */
+#include <linux/errno.h>	/* for -EBUSY */
+#include <linux/ioport.h>	/* for check_region, request_region */
+#include <linux/delay.h>	/* for loops_per_sec */
+#include <asm/segment.h>	/* for put_user_byte */
+#include <asm/io.h>		/* for inb_p, outb_p, inb, outb, etc. */
+#include <asm/uaccess.h>	/* for get_user, etc. */
+#include <linux/wait.h>		/* for wait_queue */
+#include <linux/init.h>		/* for __init */
+#include <linux/poll.h>		/* for POLLIN, etc. */
+#include <linux/dtlk.h>		/* local header file for DoubleTalk values */
+
+#ifdef TRACING
+#define TRACE_TEXT(str) printk(str);
+#define TRACE_RET printk(")")
+#else				/* !TRACING */
+#define TRACE_TEXT(str) ((void) 0)
+#define TRACE_RET ((void) 0)
+#endif				/* TRACING */
+
+
+static int dtlk_major;
+static int dtlk_port_lpc;
+static int dtlk_port_tts;
+static int dtlk_busy;
+static int dtlk_timer_active;
+static int dtlk_has_indexing;
+static unsigned int dtlk_portlist[] =
+{0x25e, 0x29e, 0x2de, 0x31e, 0x35e, 0x39e, 0};
+static struct wait_queue *dtlk_process_list = NULL;
+static struct timer_list dtlk_timer;
+
+/* prototypes for file_operations struct */
+static ssize_t dtlk_read(struct file *, char *,
+			 size_t nbytes, loff_t * ppos);
+static ssize_t dtlk_write(struct file *, const char *,
+			  size_t nbytes, loff_t * ppos);
+static unsigned int dtlk_poll(struct file *, poll_table *);
+static int dtlk_open(struct inode *, struct file *);
+static int dtlk_release(struct inode *, struct file *);
+static int dtlk_ioctl(struct inode *inode, struct file *file,
+		      unsigned int cmd, unsigned long arg);
+
+static struct file_operations dtlk_fops =
+{
+	NULL,			/* lseek */
+	dtlk_read,
+	dtlk_write,
+	NULL,			/* readdir */
+	dtlk_poll,
+	dtlk_ioctl,
+	NULL,			/* mmap */
+	dtlk_open,
+	NULL,			/* flush */
+	dtlk_release,
+	NULL,			/* fsync */
+	NULL,			/* fasync */
+	NULL,			/* check_media_change */
+	NULL,			/* revalidate */
+	NULL			/* lock */
+};
+
+/* local prototypes */
+static void dtlk_delay(int ms);
+static int dtlk_dev_probe(void);
+static struct dtlk_settings *dtlk_interrogate(void);
+static int dtlk_readable(void);
+static char dtlk_read_lpc(void);
+static char dtlk_read_tts(void);
+static void dtlk_stop_timer(void);
+static int dtlk_writeable(void);
+static char dtlk_write_bytes(const char *buf, int n);
+static char dtlk_write_tts(char);
+/*
+   static void dtlk_handle_error(char, char, unsigned int);
+   static char dtlk_write_byte(unsigned int, const char*);
+ */
+static void dtlk_timer_tick(unsigned long data);
+
+static ssize_t dtlk_read(struct file *file, char *buf,
+			 size_t count, loff_t * ppos)
+{
+	unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+	char ch;
+	int retval, i = 0, retries;
+
+	/* Can't seek (pread) on the DoubleTalk.  */
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+
+	TRACE_TEXT("(dtlk_read");
+	/*  printk("DoubleTalk PC - dtlk_read()\n"); */
+
+	if (minor != DTLK_MINOR || !dtlk_has_indexing)
+		return -EINVAL;
+
+	for (retries = 0; retries < loops_per_sec / 10; retries++) {
+		while (i < count && dtlk_readable()) {
+			ch = dtlk_read_lpc();
+			/*        printk("dtlk_read() reads 0x%02x\n", ch); */
+			if ((retval = put_user(ch, buf++)))
+				return retval;
+			i++;
+		}
+		if (i)
+			return i;
+		if (file->f_flags & O_NONBLOCK)
+			break;
+		dtlk_delay(10);
+	}
+	if (retries == loops_per_sec)
+		printk(KERN_ERR "dtlk_read times out\n");
+	TRACE_RET;
+	return -EAGAIN;
+}
+
+static ssize_t dtlk_write(struct file *file, const char *buf,
+			  size_t count, loff_t * ppos)
+{
+	int i = 0, retries = 0, err, ch;
+
+	TRACE_TEXT("(dtlk_write");
+#ifdef TRACING
+	printk(" \"");
+	{
+		int i, ch;
+		for (i = 0; i < count; i++) {
+			err = get_user(ch, buf + i);
+			if (' ' <= ch && ch <= '~')
+				printk("%c", ch);
+			else
+				printk("\\%03o", ch);
+		}
+		printk("\"");
+	}
+#endif
+
+	/* Can't seek (pwrite) on the DoubleTalk.  */
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+
+	if (MINOR(file->f_dentry->d_inode->i_rdev) != DTLK_MINOR)
+		return -EINVAL;
+
+	while (1) {
+		while (i < count && (err = get_user(ch, buf)) == 0 &&
+		       (ch == DTLK_CLEAR || dtlk_writeable())) {
+			dtlk_write_tts(ch);
+			buf++;
+			i++;
+			if (i % 5 == 0)
+				/* We yield our time until scheduled
+				   again.  This reduces the transfer
+				   rate to 500 bytes/sec, but that's
+				   still enough to keep up with the
+				   speech synthesizer. */
+				dtlk_delay(1);
+			else {
+				/* the RDY bit goes zero 2-3 usec
+				   after writing, and goes 1 again
+				   180-190 usec later.  Here, we wait
+				   up to 250 usec for the RDY bit to
+				   go nonzero. */
+				for (retries = 0;
+				     retries < loops_per_sec / 4000;
+				     retries++)
+					if (inb_p(dtlk_port_tts) &
+					    TTS_WRITABLE)
+						break;
+			}
+			retries = 0;
+		}
+		if (i == count)
+			return i;
+		if (file->f_flags & O_NONBLOCK)
+			break;
+
+		dtlk_delay(1);
+
+		if (++retries > 10 * HZ) { /* wait no more than 10 sec
+					      from last write */
+			printk("dtlk: write timeout.  "
+			       "inb_p(dtlk_port_tts) = 0x%02x\n",
+			       inb_p(dtlk_port_tts));
+			TRACE_RET;
+			return -EBUSY;
+		}
+	}
+	TRACE_RET;
+	return -EAGAIN;
+}
+
+static unsigned int dtlk_poll(struct file *file, poll_table * wait)
+{
+	int mask = 0;
+	TRACE_TEXT(" dtlk_poll");
+	/*
+	   static long int j;
+	   printk(".");
+	   printk("<%ld>", jiffies-j);
+	   j=jiffies;
+	 */
+	poll_wait(file, &dtlk_process_list, wait);
+
+	if (dtlk_has_indexing && dtlk_readable()) {
+		dtlk_stop_timer();
+		mask = POLLIN | POLLRDNORM;
+	}
+	if (dtlk_writeable()) {
+		dtlk_stop_timer();
+		mask |= POLLOUT | POLLWRNORM;
+	}
+	/* there are no exception conditions */
+
+	if (mask == 0 && !dtlk_timer_active) {
+		/* not ready just yet.  There won't be any interrupts,
+		   so we set a timer instead. */
+		dtlk_timer_active = 1;
+		dtlk_timer.expires = jiffies + HZ / 100;
+		add_timer(&dtlk_timer);
+	}
+	return 0;
+}
+
+static void dtlk_stop_timer()
+{
+	if (dtlk_timer_active) {
+		dtlk_timer_active = 0;
+		del_timer(&dtlk_timer);
+	}
+}
+
+static void dtlk_timer_tick(unsigned long data)
+{
+
+	wake_up_interruptible(&dtlk_process_list);
+
+	if (dtlk_timer_active) {
+		del_timer(&dtlk_timer);
+		dtlk_timer.expires = jiffies + HZ / 100;
+		add_timer(&dtlk_timer);
+	}
+}
+
+static int dtlk_ioctl(struct inode *inode,
+		      struct file *file,
+		      unsigned int cmd,
+		      unsigned long arg)
+{
+	struct dtlk_settings *sp;
+	int err;
+	char portval;
+	TRACE_TEXT(" dtlk_ioctl");
+
+	switch (cmd) {
+
+	case DTLK_INTERROGATE:
+		sp = dtlk_interrogate();
+		err = copy_to_user((char *) arg, (char *) sp,
+				   sizeof(struct dtlk_settings));
+		if (err)
+			return -EINVAL;
+		return 0;
+
+	case DTLK_STATUS:
+		portval = inb_p(dtlk_port_tts);
+		return put_user(portval, (char *) arg);
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static int dtlk_open(struct inode *inode, struct file *file)
+{
+	MOD_INC_USE_COUNT;
+	TRACE_TEXT("(dtlk_open");
+
+	switch (MINOR(inode->i_rdev)) {
+	case DTLK_MINOR:
+		if (dtlk_busy)
+			return -EBUSY;
+		return 0;
+
+	default:
+		return -ENXIO;
+	}
+}
+
+static int dtlk_release(struct inode *inode, struct file *file)
+{
+	MOD_DEC_USE_COUNT;
+	TRACE_TEXT("(dtlk_release");
+
+	switch (MINOR(inode->i_rdev)) {
+	case DTLK_MINOR:
+		break;
+
+	default:
+		break;
+	}
+	TRACE_RET;
+
+	dtlk_stop_timer();
+
+	return 0;
+}
+
+int __init dtlk_init(void)
+{
+	dtlk_port_lpc = 0;
+	dtlk_port_tts = 0;
+	dtlk_busy = 0;
+	dtlk_timer_active = 0;
+	dtlk_major = register_chrdev(0, "dtlk", &dtlk_fops);
+	if (dtlk_major == 0) {
+		printk(KERN_ERR "DoubleTalk PC - cannot register device\n");
+		return 0;
+	}
+	if (dtlk_dev_probe() == 0)
+		printk(", MAJOR %d\n", dtlk_major);
+
+	init_timer(&dtlk_timer);
+	dtlk_timer.function = dtlk_timer_tick;
+	dtlk_process_list = NULL;
+
+	return 0;
+}
+
+#ifdef MODULE
+int init_module(void)
+{
+	return dtlk_init();
+}
+
+void cleanup_module(void)
+{
+	dtlk_write_bytes("goodbye", 8);
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(5 * HZ / 10);		/* nap 0.50 sec but
+						   could be awakened
+						   earlier by
+						   signals... */
+
+	dtlk_write_tts(DTLK_CLEAR);
+	unregister_chrdev(dtlk_major, "dtlk");
+	release_region(dtlk_port_lpc, DTLK_IO_EXTENT);
+}
+
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+/* sleep for ms milliseconds */
+static void dtlk_delay(int ms)
+{
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout((ms * HZ + 1000 - HZ) / 1000);
+	current->state = TASK_RUNNING;
+}
+
+static int dtlk_readable(void)
+{
+	TRACE_TEXT(" dtlk_readable");
+	return inb_p(dtlk_port_lpc) != 0x7f;
+}
+
+static int dtlk_writeable(void)
+{
+	/* TRACE_TEXT(" dtlk_writeable"); */
+#ifdef TRACING
+	printk(" dtlk_writeable(%02x)", inb_p(dtlk_port_tts));
+#endif
+	return inb_p(dtlk_port_tts) & TTS_WRITABLE;
+}
+
+static int __init dtlk_dev_probe(void)
+{
+	unsigned int testval = 0;
+	int i = 0;
+	struct dtlk_settings *sp;
+
+	if (dtlk_port_lpc | dtlk_port_tts)
+		return -EBUSY;
+
+	for (i = 0; dtlk_portlist[i]; i++) {
+#if 0
+		printk("DoubleTalk PC - Port %03x = %04x\n",
+		       dtlk_portlist[i], (testval = inw_p(dtlk_portlist[i])));
+#endif
+
+		if (check_region(dtlk_portlist[i], DTLK_IO_EXTENT))
+			continue;
+		testval = inw_p(dtlk_portlist[i]);
+		if ((testval &= 0xfbff) == 0x107f) {
+			request_region(dtlk_portlist[i], DTLK_IO_EXTENT, 
+				       "dtlk");
+			dtlk_port_lpc = dtlk_portlist[i];
+			dtlk_port_tts = dtlk_port_lpc + 1;
+
+			sp = dtlk_interrogate();
+			printk("DoubleTalk PC at %03x-%03x, "
+			       "ROM version %s, serial number %u",
+			       dtlk_portlist[i], dtlk_portlist[i] +
+			       DTLK_IO_EXTENT - 1,
+			       sp->rom_version, sp->serial_number);
+
+                        /* put LPC port into known state, so
+			   dtlk_readable() gives valid result */
+			outb_p(0xff, dtlk_port_lpc); 
+
+                        /* INIT string and index marker */
+			dtlk_write_bytes("\036\1@\0\0012I\r", 8);
+			/* posting an index takes 18 msec.  Here, we
+			   wait up to 100 msec to see whether it
+			   appears. */
+			dtlk_delay(100);
+			dtlk_has_indexing = dtlk_readable();
+
+#ifdef INSCOPE
+			{
+/* This macro records ten samples read from the LPC port, for later display */
+#define LOOK					\
+for (i = 0; i < 10; i++)			\
+  {						\
+    buffer[b++] = inb_p(dtlk_port_lpc);		\
+    __delay(loops_per_sec/1000000);             \
+  }
+				char buffer[1000];
+				int b = 0, i, j;
+
+				LOOK
+				    outb_p(0xff, dtlk_port_lpc);
+				buffer[b++] = 0;
+				LOOK
+				    dtlk_write_bytes("\0012I\r", 4);
+				buffer[b++] = 0;
+				__delay(50 * loops_per_sec / 1000);
+				outb_p(0xff, dtlk_port_lpc);
+				buffer[b++] = 0;
+				LOOK
+
+				    printk("\n");
+				for (j = 0; j < b; j++)
+					printk(" %02x", buffer[j]);
+				printk("\n");
+			}
+#endif				/* INSCOPE */
+
+#ifdef OUTSCOPE
+			{
+/* This macro records ten samples read from the TTS port, for later display */
+#define LOOK					\
+for (i = 0; i < 10; i++)			\
+  {						\
+    buffer[b++] = inb_p(dtlk_port_tts);		\
+    __delay(loops_per_sec/1000000);  /* 1 us */ \
+  }
+				char buffer[1000];
+				int b = 0, i, j;
+
+				__delay(loops_per_sec / 100);	/* 10 ms */
+				LOOK
+				    outb_p(0x03, dtlk_port_tts);
+				buffer[b++] = 0;
+				LOOK
+				    LOOK
+
+				    printk("\n");
+				for (j = 0; j < b; j++)
+					printk(" %02x", buffer[j]);
+				printk("\n");
+			}
+#endif				/* OUTSCOPE */
+
+			dtlk_write_bytes("Double Talk found", 18);
+
+			return 0;
+		}
+	}
+
+	printk(KERN_INFO "\nDoubleTalk PC - not found\n");
+	return -ENODEV;
+}
+
+/*
+   static void dtlk_handle_error(char op, char rc, unsigned int minor)
+   {
+   printk(KERN_INFO"\nDoubleTalk PC - MINOR: %d, OPCODE: %d, ERROR: %d\n", 
+   minor, op, rc);
+   return;
+   }
+ */
+
+/* interrogate the DoubleTalk PC and return its settings */
+static struct dtlk_settings *dtlk_interrogate(void)
+{
+	unsigned char *t;
+	static char buf[sizeof(struct dtlk_settings) + 1];
+	int total, i;
+	static struct dtlk_settings status;
+	TRACE_TEXT("(dtlk_interrogate");
+	dtlk_write_bytes("\030\001?", 3);
+	for (total = 0, i = 0; i < 50; i++) {
+		buf[total] = dtlk_read_tts();
+		if (total > 2 && buf[total] == 0x7f)
+			break;
+		if (total < sizeof(struct dtlk_settings))
+			 total++;
+	}
+	/*
+	   if (i==50) printk("interrogate() read overrun\n");
+	   for (i=0; i<sizeof(buf); i++)
+	   printk(" %02x", buf[i]);
+	   printk("\n");
+	 */
+	t = buf;
+	status.serial_number = t[0] + t[1] * 256; /* serial number is
+						     little endian */
+	t += 2;
+
+	i = 0;
+	while (*t != '\r') {
+		status.rom_version[i] = *t;
+		if (i < sizeof(status.rom_version) - 1)
+			i++;
+		t++;
+	}
+	status.rom_version[i] = 0;
+	t++;
+
+	status.mode = *t++;
+	status.punc_level = *t++;
+	status.formant_freq = *t++;
+	status.pitch = *t++;
+	status.speed = *t++;
+	status.volume = *t++;
+	status.tone = *t++;
+	status.expression = *t++;
+	status.ext_dict_loaded = *t++;
+	status.ext_dict_status = *t++;
+	status.free_ram = *t++;
+	status.articulation = *t++;
+	status.reverb = *t++;
+	status.eob = *t++;
+	status.has_indexing = dtlk_has_indexing;
+	TRACE_RET;
+	return &status;
+}
+
+static char dtlk_read_tts(void)
+{
+	int portval, retries = 0;
+	char ch;
+	TRACE_TEXT("(dtlk_read_tts");
+
+	/* verify DT is ready, read char, wait for ACK */
+	do {
+		portval = inb_p(dtlk_port_tts);
+	} while ((portval & TTS_READABLE) == 0 && retries++ < DTLK_MAX_RETRIES);
+	if (retries == DTLK_MAX_RETRIES)
+		printk(KERN_ERR "dtlk_read_tts() timeout\n");
+
+	ch = inb_p(dtlk_port_tts);	/* input from TTS port */
+	ch &= 0x7f;
+	outb_p(ch, dtlk_port_tts);
+
+	retries = 0;
+	do {
+		portval = inb_p(dtlk_port_tts);
+	} while ((portval & TTS_READABLE) != 0 && retries++ < DTLK_MAX_RETRIES);
+	if (retries == DTLK_MAX_RETRIES)
+		printk(KERN_ERR "dtlk_read_tts() timeout\n");
+
+	TRACE_RET;
+	return ch;
+}
+
+static char dtlk_read_lpc(void)
+{
+	int retries = 0;
+	char ch;
+	TRACE_TEXT("(dtlk_read_lpc");
+
+	/* no need to test -- this is only called when the port is readable */
+
+	ch = inb_p(dtlk_port_lpc);	/* input from LPC port */
+
+	outb_p(0xff, dtlk_port_lpc);
+
+	/* acknowledging a read takes 3-4
+	   usec.  Here, we wait up to 20 usec
+	   for the acknowledgement */
+	retries = (loops_per_sec * 20) / 1000000;
+	while (inb_p(dtlk_port_lpc) != 0x7f && --retries > 0);
+	if (retries == 0)
+		printk(KERN_ERR "dtlk_read_lpc() timeout\n");
+
+	TRACE_RET;
+	return ch;
+}
+
+#ifdef NEVER
+static char dtlk_write_byte(unsigned int minor, const char *buf)
+{
+	char ch;
+	int err;
+	/* TRACE_TEXT("(dtlk_write_byte"); */
+	err = get_user(ch, buf);
+	/* printk("  dtlk_write_byte(%d, 0x%02x)", minor, (int)ch); */
+
+	ch = dtlk_write_tts(ch);
+	/* 
+	   TRACE_RET; */
+	return ch;
+}
+#endif				/* NEVER */
+
+/* write n bytes to tts port */
+static char dtlk_write_bytes(const char *buf, int n)
+{
+	char val = 0;
+	/*  printk("dtlk_write_bytes(\"%-*s\", %d)\n", n, buf, n); */
+	TRACE_TEXT("(dtlk_write_bytes");
+	while (n-- > 0)
+		val = dtlk_write_tts(*buf++);
+	TRACE_RET;
+	return val;
+}
+
+static char dtlk_write_tts(char ch)
+{
+	int retries = 0;
+#ifdef TRACING
+	printk("  dtlk_write_tts(");
+	if (' ' <= ch && ch <= '~')
+		printk("'%c'", ch);
+	else
+		printk("0x%02x", ch);
+#endif
+	if (ch != DTLK_CLEAR)	/* no flow control for CLEAR command */
+		while ((inb_p(dtlk_port_tts) & TTS_WRITABLE) == 0 &&
+		       retries++ < DTLK_MAX_RETRIES)	/* DT ready? */
+			;
+	if (retries == DTLK_MAX_RETRIES)
+		printk(KERN_ERR "dtlk_write_tts() timeout\n");
+
+	outb_p(ch, dtlk_port_tts);	/* output to TTS port */
+	/* the RDY bit goes zero 2-3 usec after writing, and goes
+	   1 again 180-190 usec later.  Here, we wait up to 10
+	   usec for the RDY bit to go zero. */
+	for (retries = 0; retries < loops_per_sec / 100000; retries++)
+		if ((inb_p(dtlk_port_tts) & TTS_WRITABLE) == 0)
+			break;
+
+#ifdef TRACING
+	printk(")\n");
+#endif
+	return 0;
+}
diff -u --recursive --new-file v2.2.2/linux/drivers/char/ftape/zftape/zftape-init.c linux/drivers/char/ftape/zftape/zftape-init.c
--- v2.2.2/linux/drivers/char/ftape/zftape/zftape-init.c	Wed Aug 26 11:37:37 1998
+++ linux/drivers/char/ftape/zftape/zftape-init.c	Sun Mar  7 10:42:26 1999
@@ -280,8 +280,6 @@
 		static struct vm_operations_struct dummy = { NULL, };
 		vma->vm_ops = &dummy;
 #endif
-		vma->vm_file = filep;
-		filep->f_count++;
 	}
 	current->blocked = old_sigmask; /* restore mask */
 	TRACE_EXIT result;
diff -u --recursive --new-file v2.2.2/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- v2.2.2/linux/drivers/char/mem.c	Mon Jan 25 17:44:34 1999
+++ linux/drivers/char/mem.c	Sun Mar  7 10:36:47 1999
@@ -178,8 +178,6 @@
 	if (remap_page_range(vma->vm_start, offset, vma->vm_end-vma->vm_start,
 			     vma->vm_page_prot))
 		return -EAGAIN;
-	vma->vm_file = file;
-	file->f_count++;
 	return 0;
 }
 
diff -u --recursive --new-file v2.2.2/linux/drivers/char/misc.c linux/drivers/char/misc.c
--- v2.2.2/linux/drivers/char/misc.c	Tue Jan 19 11:32:51 1999
+++ linux/drivers/char/misc.c	Sun Mar  7 16:15:39 1999
@@ -231,6 +231,9 @@
 #ifdef CONFIG_SOFT_WATCHDOG
 	watchdog_init();
 #endif
+#ifdef CONFIG_DTLK
+	dtlk_init();
+#endif
 #ifdef CONFIG_APM
 	apm_bios_init();
 #endif
diff -u --recursive --new-file v2.2.2/linux/drivers/char/radio-aimslab.c linux/drivers/char/radio-aimslab.c
--- v2.2.2/linux/drivers/char/radio-aimslab.c	Wed Jan 13 15:00:41 1999
+++ linux/drivers/char/radio-aimslab.c	Sun Mar  7 15:22:06 1999
@@ -3,6 +3,11 @@
  * Coverted to new API by Alan Cox <Alan.Cox@linux.org>
  * Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org>
  *
+ * History:
+ * 1999-02-24	Russell Kroll <rkroll@exploits.org>
+ * 		Fine tuning/VIDEO_TUNER_LOW
+ *		Frequency range expanded to start at 87 MHz
+ *
  * TODO: Allow for more than one of these foolish entities :-)
  *
  * Notes on the hardware (reverse engineered from other peoples'
@@ -156,14 +161,11 @@
 
 	/* adapted from radio-aztech.c */
 
-	/* We want to compute x * 100 / 16 without overflow 
-	 * So we compute x*6 + (x/100)*25 to give x*6.25
-	 */
-	 
-	freq = freq * 6 + freq/4;	/* massage the data a little	*/
-	freq += 1070;			/* IF = 10.7 MHz 		*/
-	freq /= 5;			/* ref = 25 kHz			*/
+	/* now uses VIDEO_TUNER_LOW for fine tuning */
 
+	freq += 171200;			/* Add 10.7 MHz IF 		*/
+	freq /= 800;			/* Convert to 50 kHz units	*/
+	 
 	send_0_byte (io, dev);		/*  0: LSB of frequency		*/
 
 	for (i = 0; i < 13; i++)	/*   : frequency bits (1-13)	*/
@@ -229,9 +231,9 @@
 				return -EFAULT;
 			if(v.tuner)	/* Only 1 tuner */ 
 				return -EINVAL;
-			v.rangelow=(88*16);
-			v.rangehigh=(108*16);
-			v.flags=0;
+			v.rangelow=(87*16000);
+			v.rangehigh=(108*16000);
+			v.flags=VIDEO_TUNER_LOW;
 			v.mode=VIDEO_MODE_AUTO;
 			v.signal=0xFFFF*rt_getsigstr(rt);
 			if(copy_to_user(arg,&v, sizeof(v)))
diff -u --recursive --new-file v2.2.2/linux/drivers/char/radio-aztech.c linux/drivers/char/radio-aztech.c
--- v2.2.2/linux/drivers/char/radio-aztech.c	Wed Aug 26 11:37:37 1998
+++ linux/drivers/char/radio-aztech.c	Sun Mar  7 15:22:06 1999
@@ -1,9 +1,7 @@
-/* aztech.c - Aztech radio card driver for Linux 2.1 by Russell Kroll
+/* radio-aztech.c - Aztech radio card driver for Linux 2.2 
  *
- * Heavily modified to support the new 2.1 radio card interfaces by
- * Russell Kroll (rkroll@exploits.org)
- *
- * Based on code by
+ * Adapted to support the Video for Linux API by 
+ * Russell Kroll <rkroll@exploits.org>.  Based on original tuner code by:
  *
  * Quay Ly
  * Donald Song
@@ -14,6 +12,11 @@
  * The basis for this code may be found at http://bigbang.vtc.vsc.edu/fmradio/
  * along with more information on the card itself.
  *
+ * History:
+ * 1999-02-24	Russell Kroll <rkroll@exploits.org>
+ *		Fine tuning/VIDEO_TUNER_LOW
+ * 		Range expanded to 87-108 MHz (from 87.9-107.8)
+ *
  * Notable changes from the original source:
  * - includes stripped down to the essentials
  * - for loops used as delays replaced with udelay()
@@ -113,11 +116,8 @@
 {
 	int  i;
 
-	/*  6.25 *  */
-	frequency = frequency*6 + frequency/4;	/* massage data a bit */
-  
-	frequency += 1070;		/* tuning needs 24 data bits  */
-	frequency /= 5;
+	frequency += 171200;		/* Add 10.7 MHz IF		*/
+	frequency /= 800;		/* Convert to 50 kHz units	*/
 					
 	send_0_byte (dev);		/*  0: LSB of frequency       */
 
@@ -179,9 +179,9 @@
 				return -EFAULT;
 			if(v.tuner)	/* Only 1 tuner */ 
 				return -EINVAL;
-			v.rangelow=(879*16)/10;
-			v.rangehigh=(1078*16)/10;
-			v.flags=0;
+			v.rangelow=(87*16000);
+			v.rangehigh=(108*16000);
+			v.flags=VIDEO_TUNER_LOW;
 			v.mode=VIDEO_MODE_AUTO;
 			v.signal=0xFFFF*az_getsigstr(az);
 			if(az_getstereo(az))
@@ -292,7 +292,7 @@
 		return -EINVAL;
 		
 	request_region(io, 2, "aztech");
-	printk(KERN_INFO "Aztech radio card driver v0.40/19980422 rkroll@exploits.org\n");
+	printk(KERN_INFO "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n");
 	/* mute card - prevents noisy bootups */
 	outb (0, io);
 	return 0;
diff -u --recursive --new-file v2.2.2/linux/drivers/char/radio-typhoon.c linux/drivers/char/radio-typhoon.c
--- v2.2.2/linux/drivers/char/radio-typhoon.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/radio-typhoon.c	Wed Feb 24 16:27:53 1999
@@ -0,0 +1,428 @@
+/* Typhoon Radio Card driver for radio support
+ * (c) 1999 Dr. Henrik Seidel <Henrik.Seidel@gmx.de>
+ *
+ * Card manufacturer:
+ * http://194.18.155.92/idc/prod2.idc?nr=50753&lang=e
+ *
+ * Notes on the hardware
+ *
+ * This card has two output sockets, one for speakers and one for line.
+ * The speaker output has volume control, but only in four discrete
+ * steps. The line output has neither volume control nor mute.
+ *
+ * The card has auto-stereo according to its manual, although it all
+ * sounds mono to me (even with the Win/DOS drivers). Maybe it's my
+ * antenna - I really don't know for sure.
+ *
+ * Frequency control is done digitally.
+ *
+ * Volume control is done digitally, but there are only four different
+ * possible values. So you should better always turn the volume up and
+ * use line control. I got the best results by connecting line output
+ * to the sound card microphone input. For such a configuration the
+ * volume control has no effect, since volume control only influences
+ * the speaker output.
+ *
+ * There is no explicit mute/unmute. So I set the radio frequency to a
+ * value where I do expect just noise and turn the speaker volume down.
+ * The frequency change is necessary since the card never seems to be
+ * completely silent.
+ */
+
+#include <linux/module.h>	/* Modules                        */
+#include <linux/init.h>		/* Initdata                       */
+#include <linux/ioport.h>	/* check_region, request_region   */
+#include <linux/proc_fs.h>	/* radio card status report	  */
+#include <asm/io.h>		/* outb, outb_p                   */
+#include <asm/uaccess.h>	/* copy to/from user              */
+#include <linux/videodev.h>	/* kernel radio structs           */
+#include <linux/config.h>	/* CONFIG_RADIO_TYPHOON_*         */
+
+#define BANNER "Typhoon Radio Card driver v0.1\n"
+
+#ifndef CONFIG_RADIO_TYPHOON_PORT
+#define CONFIG_RADIO_TYPHOON_PORT -1
+#endif
+
+#ifndef CONFIG_RADIO_TYPHOON_MUTEFREQ
+#define CONFIG_RADIO_TYPHOON_MUTEFREQ 0
+#endif
+
+struct typhoon_device {
+	int users;
+	int iobase;
+	int curvol;
+	int muted;
+	unsigned long curfreq;
+	unsigned long mutefreq;
+};
+
+static void typhoon_setvol_generic(struct typhoon_device *dev, int vol);
+static int typhoon_setfreq_generic(struct typhoon_device *dev,
+				   unsigned long frequency);
+static int typhoon_setfreq(struct typhoon_device *dev, unsigned long frequency);
+static void typhoon_mute(struct typhoon_device *dev);
+static void typhoon_unmute(struct typhoon_device *dev);
+static int typhoon_setvol(struct typhoon_device *dev, int vol);
+static int typhoon_ioctl(struct video_device *dev, unsigned int cmd, void *arg);
+static int typhoon_open(struct video_device *dev, int flags);
+static void typhoon_close(struct video_device *dev);
+#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
+static int typhoon_read_proc(char *buf, char **start, off_t offset, int len,
+	                     int unused);
+#endif
+#ifdef MODULE
+int init_module(void);
+void cleanup_module(void);
+int typhoon_init(struct video_init *v);
+#else
+int typhoon_init(struct video_init *v) __init;
+#endif
+
+static void typhoon_setvol_generic(struct typhoon_device *dev, int vol)
+{
+	vol >>= 14;				/* Map 16 bit to 2 bit */
+	vol &= 3;
+	outb_p(vol / 2, dev->iobase);		/* Set the volume, high bit. */
+	outb_p(vol % 2, dev->iobase + 2);	/* Set the volume, low bit. */
+}
+
+static int typhoon_setfreq_generic(struct typhoon_device *dev,
+				   unsigned long frequency)
+{
+	unsigned long outval;
+	unsigned long x;
+
+	/*
+	 * The frequency transfer curve is not linear. The best fit I could
+	 * get is
+	 *
+	 * outval = -155 + exp((f + 15.55) * 0.057))
+	 *
+	 * where frequency f is in MHz. Since we don't have exp in the kernel,
+	 * I approximate this function by a third order polynomial.
+	 *
+	 */
+
+	x = frequency / 160;
+	outval = (x * x + 2500) / 5000;
+	outval = (outval * x + 5000) / 10000;
+	outval -= (10 * x * x + 10433) / 20866;
+	outval += 4 * x - 11505;
+
+	outb_p((outval >> 8) & 0x01, dev->iobase + 4);
+	outb_p(outval >> 9, dev->iobase + 6);
+	outb_p(outval & 0xff, dev->iobase + 8);
+
+	return 0;
+}
+
+static int typhoon_setfreq(struct typhoon_device *dev, unsigned long frequency)
+{
+	typhoon_setfreq_generic(dev, frequency);
+	dev->curfreq = frequency;
+	return 0;
+}
+
+static void typhoon_mute(struct typhoon_device *dev)
+{
+	if (dev->muted == 1)
+		return;
+	typhoon_setvol_generic(dev, 0);
+	typhoon_setfreq_generic(dev, dev->mutefreq);
+	dev->muted = 1;
+}
+
+static void typhoon_unmute(struct typhoon_device *dev)
+{
+	if (dev->muted == 0)
+		return;
+	typhoon_setfreq_generic(dev, dev->curfreq);
+	typhoon_setvol_generic(dev, dev->curvol);
+	dev->muted = 0;
+}
+
+static int typhoon_setvol(struct typhoon_device *dev, int vol)
+{
+	if (dev->muted && vol != 0) {	/* user is unmuting the card */
+		dev->curvol = vol;
+		typhoon_unmute(dev);
+		return 0;
+	}
+	if (vol == dev->curvol)		/* requested volume == current */
+		return 0;
+
+	if (vol == 0) {			/* volume == 0 means mute the card */
+		typhoon_mute(dev);
+		dev->curvol = vol;
+		return 0;
+	}
+	typhoon_setvol_generic(dev, vol);
+	dev->curvol = vol;
+	return 0;
+}
+
+
+static int typhoon_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
+{
+	struct typhoon_device *typhoon = dev->priv;
+
+	switch (cmd) {
+	case VIDIOCGCAP:
+		{
+			struct video_capability v;
+			v.type = VID_TYPE_TUNER;
+			v.channels = 1;
+			v.audios = 1;
+			/* No we don't do pictures */
+			v.maxwidth = 0;
+			v.maxheight = 0;
+			v.minwidth = 0;
+			v.minheight = 0;
+			strcpy(v.name, "Typhoon Radio");
+			if (copy_to_user(arg, &v, sizeof(v)))
+				return -EFAULT;
+			return 0;
+		}
+	case VIDIOCGTUNER:
+		{
+			struct video_tuner v;
+			if (copy_from_user(&v, arg, sizeof(v)) != 0)
+				return -EFAULT;
+			if (v.tuner)	/* Only 1 tuner */
+				return -EINVAL;
+			v.rangelow = 875 * 1600;
+			v.rangehigh = 1080 * 1600;
+			v.flags = VIDEO_TUNER_LOW;
+			v.mode = VIDEO_MODE_AUTO;
+			v.signal = 0;	/* We can't get the signal strength */
+			if (copy_to_user(arg, &v, sizeof(v)))
+				return -EFAULT;
+			return 0;
+		}
+	case VIDIOCSTUNER:
+		{
+			struct video_tuner v;
+			if (copy_from_user(&v, arg, sizeof(v)))
+				return -EFAULT;
+			if (v.tuner != 0)
+				return -EINVAL;
+			/* Only 1 tuner so no setting needed ! */
+			return 0;
+		}
+	case VIDIOCGFREQ:
+		if (copy_to_user(arg, &typhoon->curfreq,
+				 sizeof(typhoon->curfreq)))
+			return -EFAULT;
+		return 0;
+	case VIDIOCSFREQ:
+		if (copy_from_user(&typhoon->curfreq, arg,
+				   sizeof(typhoon->curfreq)))
+			return -EFAULT;
+		typhoon_setfreq(typhoon, typhoon->curfreq);
+		return 0;
+	case VIDIOCGAUDIO:
+		{
+			struct video_audio v;
+			memset(&v, 0, sizeof(v));
+			v.flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME;
+			v.mode |= VIDEO_SOUND_MONO;
+			v.volume = typhoon->curvol;
+			v.step = 1 << 14;
+			strcpy(v.name, "Typhoon Radio");
+			if (copy_to_user(arg, &v, sizeof(v)))
+				return -EFAULT;
+			return 0;
+		}
+	case VIDIOCSAUDIO:
+		{
+			struct video_audio v;
+			if (copy_from_user(&v, arg, sizeof(v)))
+				return -EFAULT;
+			if (v.audio)
+				return -EINVAL;
+
+			if (v.flags & VIDEO_AUDIO_MUTE)
+				typhoon_mute(typhoon);
+			else
+				typhoon_unmute(typhoon);
+
+			if (v.flags & VIDEO_AUDIO_VOLUME)
+				typhoon_setvol(typhoon, v.volume);
+
+			return 0;
+		}
+	default:
+		return -ENOIOCTLCMD;
+	}
+}
+
+static int typhoon_open(struct video_device *dev, int flags)
+{
+	struct typhoon_device *typhoon = dev->priv;
+	if (typhoon->users)
+		return -EBUSY;
+	typhoon->users++;
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static void typhoon_close(struct video_device *dev)
+{
+	struct typhoon_device *typhoon = dev->priv;
+	typhoon->users--;
+	MOD_DEC_USE_COUNT;
+}
+
+static struct typhoon_device typhoon_unit =
+{
+	0,				/* users */
+	CONFIG_RADIO_TYPHOON_PORT,	/* iobase */
+	0,				/* curvol */
+	0,				/* muted */
+	CONFIG_RADIO_TYPHOON_MUTEFREQ,	/* curfreq */
+	CONFIG_RADIO_TYPHOON_MUTEFREQ	/* mutefreq */
+};
+
+static struct video_device typhoon_radio =
+{
+	"Typhoon Radio",
+	VID_TYPE_TUNER,
+	VID_HARDWARE_TYPHOON,
+	typhoon_open,
+	typhoon_close,
+	NULL,			/* Can't read  (no capture ability) */
+	NULL,			/* Can't write */
+	NULL,			/* Can't poll */
+	typhoon_ioctl,
+	NULL,
+	NULL
+};
+
+#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
+
+static int typhoon_read_proc(char *buf, char **start, off_t offset, int len,
+	              int unused)
+{
+	#ifdef MODULE
+	    #define MODULEPROCSTRING "Driver loaded as a module"
+	#else
+	    #define MODULEPROCSTRING "Driver compiled into kernel"
+	#endif
+
+        #define LIMIT (PAGE_SIZE - 80)
+
+	len = 0;
+	len += sprintf(buf + len, BANNER);
+	if (len > LIMIT) return len;
+	len += sprintf(buf + len, "Load type: " MODULEPROCSTRING "\n\n");
+	if (len > LIMIT) return len;
+	len += sprintf(buf + len, "frequency = %lu kHz\n",
+		typhoon_unit.curfreq >> 4);
+	if (len > LIMIT) return len;
+	len += sprintf(buf + len, "volume = %d\n", typhoon_unit.curvol);
+	if (len > LIMIT) return len;
+	len += sprintf(buf + len, "mute = %s\n", typhoon_unit.muted ?
+		"on" : "off");
+	if (len > LIMIT) return len;
+	len += sprintf(buf + len, "iobase = 0x%x\n", typhoon_unit.iobase);
+	if (len > LIMIT) return len;
+	len += sprintf(buf + len, "mute frequency = %lu kHz\n",
+		typhoon_unit.mutefreq >> 4);
+	return len;
+}
+
+static struct proc_dir_entry typhoon_proc_entry = {
+	0,			/* low_ino: inode is dynamic */
+	13, "radio-typhoon",	/* length of name and name */
+	S_IFREG | S_IRUGO,	/* mode */
+	1, 0, 0,		/* nlinks, owner, group */
+	0,			/* size -- not used */
+	NULL,			/* operations -- use default */
+	&typhoon_read_proc,	/* function used to read data */
+	/* nothing more */
+};
+
+#endif /* CONFIG_RADIO_TYPHOON_PROC_FS */
+
+int typhoon_init(struct video_init *v)
+{
+	printk(KERN_INFO BANNER);
+	if (check_region(typhoon_unit.iobase, 8)) {
+		printk(KERN_ERR "radio-typhoon: port 0x%x already in use\n",
+		       typhoon_unit.iobase);
+		return -EBUSY;
+	}
+
+	typhoon_radio.priv = &typhoon_unit;
+	if (video_register_device(&typhoon_radio, VFL_TYPE_RADIO) == -1)
+		return -EINVAL;
+
+	request_region(typhoon_unit.iobase, 8, "typhoon");
+	printk(KERN_INFO "radio-typhoon: port 0x%x.\n", typhoon_unit.iobase);
+	printk(KERN_INFO "radio-typhoon: mute frequency is %lu kHz.\n",
+	       typhoon_unit.mutefreq);
+	typhoon_unit.mutefreq <<= 4;
+
+	/* mute card - prevents noisy bootups */
+	typhoon_mute(&typhoon_unit);
+
+#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
+	
+	if (proc_register(&proc_root, &typhoon_proc_entry))
+	    	printk(KERN_ERR "radio-typhoon: registering /proc/radio-typhoon failed\n");
+
+#endif
+
+	return 0;
+}
+
+#ifdef MODULE
+
+MODULE_AUTHOR("Dr. Henrik Seidel");
+MODULE_DESCRIPTION("A driver for the Typhoon radio card (a.k.a. EcoRadio).");
+MODULE_PARM(io, "i");
+MODULE_PARM_DESC(io, "I/O address of the Typhoon card (0x316 or 0x336)");
+MODULE_PARM(mutefreq, "i");
+MODULE_PARM_DESC(mutefreq, "Frequency used when muting the card (in kHz)");
+
+EXPORT_NO_SYMBOLS;
+
+static int io = -1;
+static unsigned long mutefreq = 0;
+
+int init_module(void)
+{
+	if (io == -1) {
+		printk(KERN_ERR "radio-typhoon: You must set an I/O address with io=0x316 or io=0x336\n");
+		return -EINVAL;
+	}
+	typhoon_unit.iobase = io;
+
+	if (mutefreq < 87000 || mutefreq > 108500) {
+		printk(KERN_ERR "radio-typhoon: You must set a frequency (in kHz) used when muting the card,\n");
+		printk(KERN_ERR "radio-typhoon: e.g. with \"mutefreq=87500\" (87000 <= mutefreq <= 108500)\n");
+		return -EINVAL;
+	}
+	typhoon_unit.mutefreq = mutefreq;
+
+	return typhoon_init(NULL);
+}
+
+void cleanup_module(void)
+{
+
+#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
+
+	if (proc_unregister(&proc_root, typhoon_proc_entry.low_ino))
+	    	printk(KERN_ERR "radio-typhoon: unregistering /proc/radio-typhoon failed\n");
+
+#endif
+
+	video_unregister_device(&typhoon_radio);
+	release_region(io, 8);
+}
+
+#endif
+
+
diff -u --recursive --new-file v2.2.2/linux/drivers/char/radio-zoltrix.c linux/drivers/char/radio-zoltrix.c
--- v2.2.2/linux/drivers/char/radio-zoltrix.c	Fri Jan  8 22:36:05 1999
+++ linux/drivers/char/radio-zoltrix.c	Wed Feb 24 16:27:53 1999
@@ -11,7 +11,8 @@
  *  at a low frequency, and it is not possible (at least I have not found)
  *  to get fine volume control over the low volume range.
  *
- *  Some code derived from code by Frans Brinkman
+ *  Some code derived from code by Romolo Manfredini
+ *				   romolo@bicnet.it
  *
  * 1999-01-05 - (C. van Schaik)
  *	      - Changed tuning to 1/160Mhz accuracy
@@ -285,10 +286,10 @@
 			if (v.flags & VIDEO_AUDIO_MUTE)
 				zol_mute(zol);
 			else
+			{
 				zol_unmute(zol);
-
-			if (v.flags & VIDEO_AUDIO_VOLUME)
 				zol_setvol(zol, v.volume / 4096);
+			}
 
 			if (v.mode & VIDEO_SOUND_STEREO)
 			{
diff -u --recursive --new-file v2.2.2/linux/drivers/char/vc_screen.c linux/drivers/char/vc_screen.c
--- v2.2.2/linux/drivers/char/vc_screen.c	Wed Aug 26 11:37:37 1998
+++ linux/drivers/char/vc_screen.c	Thu Feb 25 10:02:12 1999
@@ -89,6 +89,7 @@
 	long p = *ppos;
 	long viewed, attr, size, read;
 	char *buf0;
+	int col, maxcol;
 	unsigned short *org = NULL;
 
 	attr = (currcons & 128);
@@ -111,10 +112,19 @@
 		count = size - p;
 
 	buf0 = buf;
+	maxcol = video_num_columns;
 	if (!attr) {
 		org = screen_pos(currcons, p, viewed);
-		while (count-- > 0)
+		col = p % maxcol;
+		p += maxcol - col;
+		while (count-- > 0) {
 			put_user(vcs_scr_readw(currcons, org++) & 0xff, buf++);
+			if (++col == maxcol) {
+				org = screen_pos(currcons, p, viewed);
+				col = 0;
+				p += maxcol;
+			}
+		}
 	} else {
 		if (p < HEADER_SIZE) {
 			char header[HEADER_SIZE];
@@ -124,20 +134,35 @@
 			while (p < HEADER_SIZE && count > 0)
 			    { count--; put_user(header[p++], buf++); }
 		}
+		p -= HEADER_SIZE;
+		col = (p/2) % maxcol;
 		if (count > 0) {
-		    p -= HEADER_SIZE;
-		    org = screen_pos(currcons, p/2, viewed);
-		    if ((p & 1) && count > 0)
+			org = screen_pos(currcons, p/2, viewed);
+			if ((p & 1) && count > 0) {
+				count--;   
 #ifdef __BIG_ENDIAN
-			    { count--; put_user(vcs_scr_readw(currcons, org++) & 0xff, buf++); }
+				put_user(vcs_scr_readw(currcons, org++) & 0xff, buf++);
 #else
-			    { count--; put_user(vcs_scr_readw(currcons, org++) >> 8, buf++); }
+				put_user(vcs_scr_readw(currcons, org++) >> 8, buf++);
 #endif
+				p++;
+				if (++col == maxcol) {
+					org = screen_pos(currcons, p/2, viewed);
+					col = 0;
+				}
+			}
+			p /= 2;
+			p += maxcol - col;
 		}
 		while (count > 1) {
 			put_user(vcs_scr_readw(currcons, org++), (unsigned short *) buf);
 			buf += 2;
 			count -= 2;
+			if (++col == maxcol) {
+				org = screen_pos(currcons, p, viewed);
+				col = 0;
+				p += maxcol;
+			}
 		}
 		if (count > 0)
 #ifdef __BIG_ENDIAN
@@ -159,6 +184,7 @@
 	long p = *ppos;
 	long viewed, attr, size, written;
 	const char *buf0;
+	int col, maxcol;
 	u16 *org0 = NULL, *org = NULL;
 
 	attr = (currcons & 128);
@@ -181,14 +207,22 @@
 		count = size - p;
 
 	buf0 = buf;
+	maxcol = video_num_columns;
 	if (!attr) {
 		org0 = org = screen_pos(currcons, p, viewed);
+		col = p % maxcol;
+		p += maxcol - col;
 		while (count > 0) {
 			unsigned char c;
 			count--;
 			get_user(c, (const unsigned char*)buf++);
 			vcs_scr_writew(currcons, (vcs_scr_readw(currcons, org) & 0xff00) | c, org);
 			org++;
+			if (++col == maxcol) {
+				org = screen_pos(currcons, p, viewed);
+				col = 0;
+				p += maxcol;
+			}
 		}
 	} else {
 		if (p < HEADER_SIZE) {
@@ -199,8 +233,9 @@
 			if (!viewed)
 				putconsxy(currcons, header+2);
 		}
+		p -= HEADER_SIZE;
+		col = (p/2) % maxcol;
 		if (count > 0) {
-			p -= HEADER_SIZE;
 			org0 = org = screen_pos(currcons, p/2, viewed);
 			if ((p & 1) && count > 0) {
 			    char c;
@@ -214,7 +249,14 @@
 				     (vcs_scr_readw(currcons, org) & 0xff), org);
 #endif
 				org++;
+				p++;
+				if (++col == maxcol) {
+					org = screen_pos(currcons, p/2, viewed);
+					col = 0;
+				}
 			}
+			p /= 2;
+			p += maxcol - col;
 		}
 		while (count > 1) {
 			unsigned short w;
@@ -222,6 +264,11 @@
 			vcs_scr_writew(currcons, w, org++);
 			buf += 2;
 			count -= 2;
+			if (++col == maxcol) {
+				org = screen_pos(currcons, p, viewed);
+				col = 0;
+				p += maxcol;
+			}
 		}
 		if (count > 0) {
 			unsigned char c;
diff -u --recursive --new-file v2.2.2/linux/drivers/char/videodev.c linux/drivers/char/videodev.c
--- v2.2.2/linux/drivers/char/videodev.c	Wed Jan 20 23:14:05 1999
+++ linux/drivers/char/videodev.c	Wed Feb 24 16:27:53 1999
@@ -72,6 +72,9 @@
 #ifdef CONFIG_RADIO_GEMTEK
 extern int gemtek_init(struct video_init *);
 #endif
+#ifdef CONFIG_RADIO_TYPHOON
+extern int typhoon_init(struct video_init *);
+#endif
 #ifdef CONFIG_VIDEO_PMS
 extern int init_pms_cards(struct video_init *);
 #endif
@@ -101,7 +104,7 @@
 #endif	
 #ifdef CONFIG_RADIO_RTRACK
 	{"RTrack", rtrack_init}, 
-#endif	
+#endif 
 #ifdef CONFIG_RADIO_SF16FMI
 	{"SF16FMI", fmi_init}, 
 #endif	
@@ -110,6 +113,9 @@
 #endif
 #ifdef CONFIG_RADIO_GEMTEK
 	{"GemTek", gemtek_init},
+#endif
+#ifdef CONFIG_RADIO_TYPHOON
+	{"radio-typhoon", typhoon_init},
 #endif
 	{"end", NULL}
 };
diff -u --recursive --new-file v2.2.2/linux/drivers/net/8390.c linux/drivers/net/8390.c
--- v2.2.2/linux/drivers/net/8390.c	Fri Jan  8 22:36:06 1999
+++ linux/drivers/net/8390.c	Wed Feb 24 16:27:53 1999
@@ -165,8 +165,10 @@
       
       	spin_lock_irqsave(&ei_local->page_lock, flags);
 	NS8390_init(dev, 1);
-      	spin_unlock_irqrestore(&ei_local->page_lock, flags);
+	/* Set the flag before we drop the lock, That way the IRQ arrives
+	   after its set and we get no silly warnings */
 	dev->start = 1;
+      	spin_unlock_irqrestore(&ei_local->page_lock, flags);
 	ei_local->irqlock = 0;
 	return 0;
 }
diff -u --recursive --new-file v2.2.2/linux/drivers/net/Makefile linux/drivers/net/Makefile
--- v2.2.2/linux/drivers/net/Makefile	Tue Jan 19 11:32:51 1999
+++ linux/drivers/net/Makefile	Sun Mar  7 15:25:24 1999
@@ -1046,6 +1046,7 @@
 
 ifeq ($(CONFIG_IRDA),y)
 SUB_DIRS += irda
+MOD_IN_SUB_DIRS += irda
 else
   ifeq ($(CONFIG_IRDA),m)
   MOD_SUB_DIRS += irda
diff -u --recursive --new-file v2.2.2/linux/drivers/net/a2065.c linux/drivers/net/a2065.c
--- v2.2.2/linux/drivers/net/a2065.c	Mon Oct  5 13:13:39 1998
+++ linux/drivers/net/a2065.c	Thu Feb 25 10:02:13 1999
@@ -767,6 +767,8 @@
 			dev->priv = kmalloc(sizeof(struct
 						   lance_private),
 					    GFP_KERNEL);
+			if (dev->priv == NULL)  
+				return -ENOMEM;
 			priv = (struct lance_private *)dev->priv;
 			memset(priv, 0, sizeof(struct lance_private));
 
diff -u --recursive --new-file v2.2.2/linux/drivers/net/ariadne.c linux/drivers/net/ariadne.c
--- v2.2.2/linux/drivers/net/ariadne.c	Thu Sep 17 17:53:36 1998
+++ linux/drivers/net/ariadne.c	Thu Feb 25 10:02:13 1999
@@ -171,6 +171,8 @@
 	    init_etherdev(dev, 0);
 
 	    dev->priv = kmalloc(sizeof(struct ariadne_private), GFP_KERNEL);
+	    if (dev->priv == NULL)
+		return -ENOMEM;
 	    priv = (struct ariadne_private *)dev->priv;
 	    memset(priv, 0, sizeof(struct ariadne_private));
 
diff -u --recursive --new-file v2.2.2/linux/drivers/net/cosa.c linux/drivers/net/cosa.c
--- v2.2.2/linux/drivers/net/cosa.c	Mon Dec 28 15:00:52 1998
+++ linux/drivers/net/cosa.c	Sun Mar  7 15:47:46 1999
@@ -1,4 +1,4 @@
-/* $Id: cosa.c,v 1.11 1998/12/24 23:44:23 kas Exp $ */
+/* $Id: cosa.c,v 1.21 1999/02/06 19:49:18 kas Exp $ */
 
 /*
  *  Copyright (C) 1995-1997  Jan "Yenya" Kasprzak <kas@fi.muni.cz>
@@ -27,7 +27,7 @@
  * Masaryk University (http://www.ics.muni.cz/). The hardware is
  * developed by Jiri Novotny <novotny@ics.muni.cz>. More information
  * and the photo of both cards is available at
- * http://www.kozakmartin.cz/cosa.html. The card documentation, firmwares
+ * http://www.pavoucek.cz/cosa.html. The card documentation, firmwares
  * and other goods can be downloaded from ftp://ftp.ics.muni.cz/pub/cosa/.
  * For Linux-specific utilities, see below in the "Software info" section.
  * If you want to order the card, contact Jiri Novotny.
@@ -141,11 +141,13 @@
 	unsigned int datareg, statusreg;	/* I/O ports */
 	unsigned short irq, dma;	/* IRQ and DMA number */
 	unsigned short startaddr;	/* Firmware start address */
+	unsigned short busmaster;	/* Use busmastering? */
 	int nchannels;			/* # of channels on this card */
 	int driver_status;		/* For communicating with firware */
 	int firmware_status;		/* Downloaded, reseted, etc. */
 	int rxbitmap, txbitmap;		/* Bitmap of channels who are willing to send/receive data */
 	int rxtx;			/* RX or TX in progress? */
+	int enabled;
 	int usage;				/* usage count */
 	int txchan, txsize, rxsize;
 	struct channel_data *rxchan;
@@ -331,9 +333,8 @@
 static int get_wait_data(struct cosa_data *cosa);
 static int put_wait_data(struct cosa_data *cosa, int data);
 static int puthexnumber(struct cosa_data *cosa, int number);
-static void put_driver_status_common(struct cosa_data *cosa, int nolock);
-#define put_driver_status(x) put_driver_status_common((x), 0)
-#define put_driver_status_nolock(x) put_driver_status_common((x), 1)
+static void put_driver_status(struct cosa_data *cosa);
+static void put_driver_status_nolock(struct cosa_data *cosa);
 
 /* Interrupt handling */
 static void cosa_interrupt(int irq, void *cosa, struct pt_regs *regs);
@@ -357,7 +358,7 @@
 #endif
 {
 	int i;
-	printk(KERN_INFO "cosa v1.03 (c) 1997-8 Jan Kasprzak <kas@fi.muni.cz>\n");
+	printk(KERN_INFO "cosa v1.04 (c) 1997-8 Jan Kasprzak <kas@fi.muni.cz>\n");
 #ifdef __SMP__
 	printk(KERN_INFO "cosa: SMP found. Please mail any success/failure reports to the author.\n");
 #endif
@@ -630,9 +631,14 @@
 	if (dev->tbusy) { 
 		if (time_before(jiffies, dev->trans_start+2*HZ))
 			return 1;	/* Two seconds timeout */
+		if (test_bit(RXBIT, &chan->cosa->rxtx)) {
+			chan->stats.rx_errors++;
+			chan->stats.rx_missed_errors++;
+		} else {
+			chan->stats.tx_errors++;
+			chan->stats.tx_aborted_errors++;
+		}
 		cosa_kick(chan->cosa);
-		chan->stats.tx_errors++;
-		chan->stats.tx_aborted_errors++;
 		if (chan->tx_skb) {
 			dev_kfree_skb(chan->tx_skb);
 			chan->tx_skb = 0;
@@ -659,6 +665,14 @@
 	d->tbusy = 1;
 	cosa_disable_rx(chan);
 	spin_lock_irqsave(&chan->cosa->lock, flags);
+	if (chan->rx_skb) {
+		kfree_skb(chan->rx_skb);
+		chan->rx_skb = 0;
+	}
+	if (chan->tx_skb) {
+		kfree_skb(chan->tx_skb);
+		chan->tx_skb = 0;
+	}
 	chan->usage=0;
 	chan->cosa->usage--;
 	MOD_DEC_USE_COUNT;
@@ -1128,6 +1142,17 @@
 		return nr_cards;
 	case COSAIONRCHANS:
 		return cosa->nchannels;
+	case COSAIOBMSET:
+		if (!suser())
+			return -EACCES;
+		if (is_8bit(cosa))
+			return -EINVAL;
+		if (arg != COSA_BM_OFF && arg != COSA_BM_ON)
+			return -EINVAL;
+		cosa->busmaster = arg;
+		return 0;
+	case COSAIOBMGET:
+		return cosa->busmaster;
 	}
 	return -ENOIOCTLCMD;
 }
@@ -1208,37 +1233,67 @@
 	return 0;
 }
 
-static void put_driver_status_common(struct cosa_data *cosa, int nolock)
+static void put_driver_status(struct cosa_data *cosa)
 {
 	unsigned flags=0;
 	int status;
 
-	if (!nolock)
-		spin_lock_irqsave(&cosa->lock, flags);
+	spin_lock_irqsave(&cosa->lock, flags);
 
 	status = (cosa->rxbitmap ? DRIVER_RX_READY : 0)
 		| (cosa->txbitmap ? DRIVER_TX_READY : 0)
 		| (cosa->txbitmap? ~(cosa->txbitmap<<DRIVER_TXMAP_SHIFT)
 			&DRIVER_TXMAP_MASK : 0);
-	if (!cosa->rxtx || nolock) {
-#ifdef DEBUG_IO
-		debug_data_cmd(cosa, status);
-#endif
-		cosa_putdata8(cosa, status);
+	if (!cosa->rxtx) {
 		if (cosa->rxbitmap|cosa->txbitmap) {
-			cosa_putstatus(cosa, SR_RX_INT_ENA);
+			if (!cosa->enabled) {
+				cosa_putstatus(cosa, SR_RX_INT_ENA);
 #ifdef DEBUG_IO
-			debug_status_out(cosa, SR_RX_INT_ENA);
+				debug_status_out(cosa, SR_RX_INT_ENA);
 #endif
-		} else {
+				cosa->enabled = 1;
+			}
+		} else if (cosa->enabled) {
+			cosa->enabled = 0;
 			cosa_putstatus(cosa, 0);
 #ifdef DEBUG_IO
 			debug_status_out(cosa, 0);
 #endif
 		}
+		cosa_putdata8(cosa, status);
+#ifdef DEBUG_IO
+		debug_data_cmd(cosa, status);
+#endif
 	}
-	if (!nolock)
-		spin_unlock_irqrestore(&cosa->lock, flags);
+	spin_unlock_irqrestore(&cosa->lock, flags);
+}
+
+static void put_driver_status_nolock(struct cosa_data *cosa)
+{
+	int status;
+
+	status = (cosa->rxbitmap ? DRIVER_RX_READY : 0)
+		| (cosa->txbitmap ? DRIVER_TX_READY : 0)
+		| (cosa->txbitmap? ~(cosa->txbitmap<<DRIVER_TXMAP_SHIFT)
+			&DRIVER_TXMAP_MASK : 0);
+
+	if (cosa->rxbitmap|cosa->txbitmap) {
+		cosa_putstatus(cosa, SR_RX_INT_ENA);
+#ifdef DEBUG_IO
+		debug_status_out(cosa, SR_RX_INT_ENA);
+#endif
+		cosa->enabled = 1;
+	} else {
+		cosa_putstatus(cosa, 0);
+#ifdef DEBUG_IO
+		debug_status_out(cosa, 0);
+#endif
+		cosa->enabled = 0;
+	}
+	cosa_putdata8(cosa, status);
+#ifdef DEBUG_IO
+	debug_data_cmd(cosa, status);
+#endif
 }
 
 /*
@@ -1249,9 +1304,14 @@
 static void cosa_kick(struct cosa_data *cosa)
 {
 	unsigned flags, flags1;
+	char *s = "Unknown";
 
-	printk(KERN_INFO "%s: DMA timeout - restarting.\n", cosa->name);
+	if (test_bit(RXBIT, &cosa->rxtx))
+		s = "RX";
+	if (test_bit(TXBIT, &cosa->rxtx))
+		s = "TX";
 
+	printk(KERN_INFO "%s: %s DMA timeout - restarting.\n", cosa->name, s); 
 	spin_lock_irqsave(&cosa->lock, flags);
 	cosa->rxtx = 0;
 
@@ -1261,6 +1321,13 @@
 	release_dma_lock(flags1);
 
 	/* FIXME: Anything else? */
+	udelay(100);
+	cosa_putstatus(cosa, 0);
+	udelay(100);
+	(void) cosa_getdata8(cosa);
+	udelay(100);
+	cosa_putdata8(cosa, 0);
+	udelay(100);
 	put_driver_status_nolock(cosa);
 	spin_unlock_irqrestore(&cosa->lock, flags);
 }
@@ -1556,6 +1623,10 @@
  * COSA status byte. I have moved the rx/tx/eot interrupt handling into
  * separate functions to make it more readable. These functions are inline,
  * so there should be no overhead of function call.
+ * 
+ * In the COSA bus-master mode, we need to tell the card the address of a
+ * buffer. Unfortunately, COSA may be too slow for us, so we must busy-wait.
+ * It's time to use the bottom half :-(
  */
 
 /*
@@ -1606,13 +1677,13 @@
 
 	if (is_8bit(cosa)) {
 		if (!test_bit(IRQBIT, &cosa->rxtx)) {
+			cosa_putstatus(cosa, SR_TX_INT_ENA);
 			cosa_putdata8(cosa, ((cosa->txchan << 5) & 0xe0)|
 				((cosa->txsize >> 8) & 0x1f));
-			cosa_putstatus(cosa, SR_TX_INT_ENA);
 #ifdef DEBUG_IO
+			debug_status_out(cosa, SR_TX_INT_ENA);
 			debug_data_out(cosa, ((cosa->txchan << 5) & 0xe0)|
                                 ((cosa->txsize >> 8) & 0x1f));
-			debug_status_out(cosa, SR_TX_INT_ENA);
 			debug_data_in(cosa, cosa_getdata8(cosa));
 #else
 			cosa_getdata8(cosa);
@@ -1630,27 +1701,57 @@
 #endif
 		}
 	} else {
+		cosa_putstatus(cosa, SR_TX_INT_ENA);
 		cosa_putdata16(cosa, ((cosa->txchan<<13) & 0xe000)
 			| (cosa->txsize & 0x1fff));
-		cosa_getdata16(cosa);
 #ifdef DEBUG_IO
-		debug_status_out(cosa, ((cosa->txchan<<13) & 0xe000)
+		debug_status_out(cosa, SR_TX_INT_ENA);
+		debug_data_out(cosa, ((cosa->txchan<<13) & 0xe000)
                         | (cosa->txsize & 0x1fff));
-		debug_data_in(cosa, cosa_getdata16(cosa));
+		debug_data_in(cosa, cosa_getdata8(cosa));
+		debug_status_out(cosa, 0);
 #else
-		cosa_getdata16(cosa);
+		cosa_getdata8(cosa);
 #endif
+		cosa_putstatus(cosa, 0);
 	}
 
-	/* start the DMA */
-	flags1 = claim_dma_lock();
-	disable_dma(cosa->dma);
-	clear_dma_ff(cosa->dma);
-	set_dma_mode(cosa->dma, DMA_MODE_WRITE);
-	set_dma_addr(cosa->dma, virt_to_bus(cosa->txbuf));
-	set_dma_count(cosa->dma, cosa->txsize);
-	enable_dma(cosa->dma);
-	release_dma_lock(flags1);
+	if (cosa->busmaster) {
+		unsigned long addr = virt_to_bus(cosa->txbuf);
+		int count=0;
+		printk(KERN_INFO "busmaster IRQ\n");
+		while (!(cosa_getstatus(cosa)&SR_TX_RDY)) {
+			count++;
+			udelay(10);
+			if (count > 1000) break;
+		}
+		printk(KERN_INFO "status %x\n", cosa_getstatus(cosa));
+		printk(KERN_INFO "ready after %d loops\n", count);
+		cosa_putdata16(cosa, (addr >> 16)&0xffff);
+
+		count = 0;
+		while (!(cosa_getstatus(cosa)&SR_TX_RDY)) {
+			count++;
+			if (count > 1000) break;
+			udelay(10);
+		}
+		printk(KERN_INFO "ready after %d loops\n", count);
+		cosa_putdata16(cosa, addr &0xffff);
+		flags1 = claim_dma_lock();
+		set_dma_mode(cosa->dma, DMA_MODE_CASCADE);
+		enable_dma(cosa->dma);
+		release_dma_lock(flags1);
+	} else {
+		/* start the DMA */
+		flags1 = claim_dma_lock();
+		disable_dma(cosa->dma);
+		clear_dma_ff(cosa->dma);
+		set_dma_mode(cosa->dma, DMA_MODE_WRITE);
+		set_dma_addr(cosa->dma, virt_to_bus(cosa->txbuf));
+		set_dma_count(cosa->dma, cosa->txsize);
+		enable_dma(cosa->dma);
+		release_dma_lock(flags1);
+	}
 	cosa_putstatus(cosa, SR_TX_DMA_ENA|SR_USR_INT_ENA);
 #ifdef DEBUG_IO
 	debug_status_out(cosa, SR_TX_DMA_ENA|SR_USR_INT_ENA);
@@ -1671,21 +1772,16 @@
 	if (is_8bit(cosa)) {
 		if (!test_bit(IRQBIT, &cosa->rxtx)) {
 			set_bit(IRQBIT, &cosa->rxtx);
-			cosa_putstatus(cosa, 0);
 			cosa->rxsize = cosa_getdata8(cosa) <<8;
 #ifdef DEBUG_IO
-			debug_status_out(cosa, 0);
 			debug_data_in(cosa, cosa->rxsize >> 8);
 #endif
-			put_driver_status_nolock(cosa);
 			spin_unlock_irqrestore(&cosa->lock, flags);
 			return;
 		} else {
 			clear_bit(IRQBIT, &cosa->rxtx);
-			cosa_putstatus(cosa, 0);
 			cosa->rxsize |= cosa_getdata8(cosa) & 0xff;
 #ifdef DEBUG_IO
-			debug_status_out(cosa, 0);
 			debug_data_in(cosa, cosa->rxsize & 0xff);
 #endif
 #if 0
@@ -1695,12 +1791,8 @@
 		}
 	} else {
 		cosa->rxsize = cosa_getdata16(cosa);
-		cosa_putstatus(cosa, 0);
-		cosa_putdata8(cosa, DRIVER_RX_READY);
 #ifdef DEBUG_IO
 		debug_data_in(cosa, cosa->rxsize);
-		debug_status_out(cosa, 0);
-		debug_cmd_out(cosa, DRIVER_RX_READY);
 #endif
 #if 0
 		printk(KERN_INFO "cosa%d: receive rxsize = (0x%04x).\n",
@@ -1725,10 +1817,7 @@
 reject:		/* Reject the packet */
 		printk(KERN_INFO "cosa%d: rejecting packet on channel %d\n",
 			cosa->num, cosa->rxchan->num);
-		/* FIXME: This works for COSA only (not SRP) */
-		cosa->rxtx = 0;
-		put_driver_status(cosa);
-		return;
+		cosa->rxbuf = cosa->bouncebuf;
 	}
 
 	/* start the DMA */
@@ -1746,8 +1835,12 @@
 	release_dma_lock(flags);
 	spin_lock_irqsave(&cosa->lock, flags);
 	cosa_putstatus(cosa, SR_RX_DMA_ENA|SR_USR_INT_ENA);
+	if (!is_8bit(cosa) && (status & SR_TX_RDY))
+		cosa_putdata8(cosa, DRIVER_RX_READY);
 #ifdef DEBUG_IO
 	debug_status_out(cosa, SR_RX_DMA_ENA|SR_USR_INT_ENA);
+	if (!is_8bit(cosa) && (status & SR_TX_RDY))
+		debug_data_cmd(cosa, DRIVER_RX_READY);
 #endif
 	spin_unlock_irqrestore(&cosa->lock, flags);
 }
@@ -1756,11 +1849,12 @@
 {
 	unsigned long flags, flags1;
 	spin_lock_irqsave(&cosa->lock, flags);
+	flags1 = claim_dma_lock();
+	disable_dma(cosa->dma);
+	clear_dma_ff(cosa->dma);
+	release_dma_lock(flags1);
 	if (test_bit(TXBIT, &cosa->rxtx)) {
 		struct channel_data *chan = cosa->chan+cosa->txchan;
-#ifdef DEBUG_IRQS
-		printk(KERN_INFO "cosa%d: end of transfer.\n", cosa->num);
-#endif
 		if (chan->tx_done)
 			if (chan->tx_done(chan, cosa->txsize))
 				clear_bit(chan->num, &cosa->txbitmap);
@@ -1775,6 +1869,9 @@
 		printk("\n");
 	}
 #endif
+		/* Packet for unknown channel? */
+		if (cosa->rxbuf == cosa->bouncebuf)
+			goto out;
 		if (!cosa_dma_able(cosa->rxchan, cosa->rxbuf, cosa->rxsize))
 			memcpy(cosa->rxbuf, cosa->bouncebuf, cosa->rxsize);
 		if (cosa->rxchan->rx_done)
@@ -1786,12 +1883,11 @@
 	}
 	/*
 	 * Clear the RXBIT, TXBIT and IRQBIT (the latest should be
-	 * cleared anyway).
+	 * cleared anyway). We should do it as soon as possible
+	 * so that we can tell the COSA we are done and to give it a time
+	 * for recovery.
 	 */
-	flags1 = claim_dma_lock();
-	disable_dma(cosa->dma);
-	clear_dma_ff(cosa->dma);
-	release_dma_lock(flags1);
+out:
 	cosa->rxtx = 0;
 	put_driver_status_nolock(cosa);
 	spin_unlock_irqrestore(&cosa->lock, flags);
@@ -1799,7 +1895,7 @@
 
 static void cosa_interrupt(int irq, void *cosa_, struct pt_regs *regs)
 {
-	int status;
+	unsigned status;
 	int count = 0;
 	struct cosa_data *cosa = cosa_;
 again:
diff -u --recursive --new-file v2.2.2/linux/drivers/net/cosa.h linux/drivers/net/cosa.h
--- v2.2.2/linux/drivers/net/cosa.h	Mon Dec 28 15:00:52 1998
+++ linux/drivers/net/cosa.h	Sun Mar  7 15:47:46 1999
@@ -1,4 +1,4 @@
-/* $Id: cosa.h,v 1.5 1998/12/24 12:40:18 kas Exp $ */
+/* $Id: cosa.h,v 1.6 1999/01/06 14:02:44 kas Exp $ */
 
 /*
  *  Copyright (C) 1995-1997  Jan "Yenya" Kasprzak <kas@fi.muni.cz>
@@ -98,5 +98,14 @@
 
 /* Get the number of channels on this card */
 #define COSAIONRCHANS	_IO('C',0xf8)
+
+/* Set the driver for the bus-master operations */
+#define COSAIOBMSET	_IOW('C', 0xf9, sizeof(unsigned short))
+
+#define COSA_BM_OFF	0	/* Bus-mastering off - use ISA DMA (default) */
+#define COSA_BM_ON	1	/* Bus-mastering on - faster but untested */
+
+/* Gets the busmaster status */
+#define COSAIOBMGET	_IO('C', 0xfa)
 
 #endif /* !COSA_H__ */
diff -u --recursive --new-file v2.2.2/linux/drivers/net/irda/Config.in linux/drivers/net/irda/Config.in
--- v2.2.2/linux/drivers/net/irda/Config.in	Wed Jan 20 23:14:05 1999
+++ linux/drivers/net/irda/Config.in	Sun Mar  7 15:26:43 1999
@@ -9,6 +9,7 @@
     dep_tristate '   ESI JetEye PC dongle' CONFIG_ESI_DONGLE $CONFIG_IRTTY_SIR
     dep_tristate '   ACTiSYS IR-220L and IR220L+ dongle' CONFIG_ACTISYS_DONGLE $CONFIG_IRTTY_SIR
     dep_tristate '   Tekram IrMate 210B dongle' CONFIG_TEKRAM_DONGLE $CONFIG_IRTTY_SIR
+    dep_tristate '   Greenwich GIrBIL dongle' CONFIG_GIRBIL_DONGLE $CONFIG_IRTTY_SIR
   fi
 fi
 dep_tristate '  NSC PC87108' CONFIG_NSC_FIR  $CONFIG_IRDA
diff -u --recursive --new-file v2.2.2/linux/drivers/net/irda/Makefile linux/drivers/net/irda/Makefile
--- v2.2.2/linux/drivers/net/irda/Makefile	Wed Jan 20 23:14:05 1999
+++ linux/drivers/net/irda/Makefile	Sun Mar  7 15:26:43 1999
@@ -68,6 +68,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_GIRBIL_DONGLE),y)
+L_OBJS += girbil.o
+else
+  ifeq ($(CONFIG_GIRBIL_DONGLE),m)
+  M_OBJS += girbil.o
+  endif
+endif
+
 include $(TOPDIR)/Rules.make
 
 clean:
diff -u --recursive --new-file v2.2.2/linux/drivers/net/irda/actisys.c linux/drivers/net/irda/actisys.c
--- v2.2.2/linux/drivers/net/irda/actisys.c	Wed Jan 20 23:14:05 1999
+++ linux/drivers/net/irda/actisys.c	Sun Mar  7 15:26:43 1999
@@ -1,13 +1,13 @@
 /*********************************************************************
  *                
  * Filename:      actisys.c
- * Version:       0.4
+ * Version:       0.5
  * Description:   Implementation for the ACTiSYS IR-220L and IR-220L+ 
  *                dongles
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Wed Oct 21 20:02:35 1998
- * Modified at:   Mon Jan 18 11:30:25 1999
+ * Modified at:   Tue Feb  9 15:38:16 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -70,9 +70,10 @@
 
 static void actisys_open( struct irda_device *idev, int type)
 {
-	strcat( idev->name, " <-> actisys");
+	strcat(idev->description, " <-> actisys");
 
         idev->io.dongle_id = type;
+	idev->flags |= IFF_DONGLE;
 
 	MOD_INC_USE_COUNT;
 }
@@ -85,24 +86,20 @@
 /*
  * Function actisys_change_speed (tty, baud)
  *
- *    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 be compatible with the new IR-220L+, we have to reset the dongle 
- *    first since its not possible cycle around anymore and still be 
- *    compatible with both dongles :-(
+ *    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.  
  */
 static void actisys_change_speed( struct irda_device *idev, int baudrate)
 {
         struct irtty_cb *self;
         struct tty_struct *tty;
-        int arg;
         struct termios old_termios;
 	int cflag;
         int current_baudrate;
         int index = 0;
-	mm_segment_t fs;
 	
-	DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 
 	ASSERT( idev != NULL, return;);
 	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -115,10 +112,10 @@
 	current_baudrate = idev->qos.baud_rate.value;
 
 	/* Find the correct baudrate index for the currently used baudrate */
-	while ( current_baudrate != baud_rates[index])
+	while (current_baudrate != baud_rates[index])
 		index++;
 
-        DEBUG( 0, __FUNCTION__ "(), index=%d\n", index);
+        DEBUG( 4, __FUNCTION__ "(), index=%d\n", index);
 
 	if ( !self->tty)
 		return;
@@ -127,38 +124,18 @@
 
 	/* Cycle through avaiable baudrates until we reach the correct one */
         while ( current_baudrate != baudrate) {	
-                DEBUG( 0, __FUNCTION__ "(), current baudrate = %d\n",
+                DEBUG( 4, __FUNCTION__ "(), current baudrate = %d\n",
                        baud_rates[index]);
-		DEBUG( 0, __FUNCTION__ "(), Clearing RTS\n");
 		
 		/* Set DTR, clear RTS */
-		arg = TIOCM_DTR|TIOCM_OUT2;
-		
-		fs = get_fs();
-		set_fs( get_ds());
-		
-		if ( tty->driver.ioctl( tty, NULL, TIOCMSET, 
-					(unsigned long) &arg)) { 
-			DEBUG( 0, __FUNCTION__ 
-			       "Error clearing RTS!\n");
-		}
-		set_fs(fs);
+		irtty_set_dtr_rts(tty, TRUE, FALSE);
 		
 		/* Wait at a few ms */
 		current->state = TASK_INTERRUPTIBLE;
 		schedule_timeout(2);
 
 		/* Set DTR, Set RTS */
-                arg = TIOCM_DTR | TIOCM_RTS |TIOCM_OUT2;
-
-		fs = get_fs();
-		set_fs( get_ds());
-		
-		if ( tty->driver.ioctl( tty, NULL, TIOCMSET, 
-					(unsigned long) &arg)) { 
-			DEBUG( 0, __FUNCTION__  "Error setting RTS!\n");
-		}
-		set_fs(fs);
+		irtty_set_dtr_rts(tty, TRUE, TRUE);
 		
 		/* Wait at a few ms again */
 		current->state = TASK_INTERRUPTIBLE;
@@ -172,8 +149,8 @@
 
                 current_baudrate = baud_rates[index];
         }
-	DEBUG( 0, __FUNCTION__ "(), current baudrate = %d\n", 
-                  baud_rates[index]);
+	DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n", 
+	      baud_rates[index]);
 
 	/* Now change the speed of the serial port */
 	old_termios = *(tty->termios);
@@ -200,9 +177,8 @@
 		break;
 	}
 
+	/* Change speed of serial port */
 	tty->termios->c_cflag = cflag;
-
-	DEBUG( 0, __FUNCTION__ "(), Setting the speed of the serial port\n");
 	tty->driver.set_termios( tty, &old_termios);
 }
 
@@ -219,10 +195,6 @@
 {
 	struct irtty_cb *self;
         struct tty_struct *tty;
-        int arg = 0;
-	mm_segment_t fs;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
 
 	ASSERT( idev != NULL, return;);
 	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -236,36 +208,16 @@
 	if ( !tty)
 		return;
 
-	DEBUG( 0, __FUNCTION__ "(), Clearing DTR\n");
-	arg = TIOCM_RTS | TIOCM_OUT2;
-
-	fs = get_fs();
-	set_fs( get_ds());
-	
-	if ( tty->driver.ioctl( tty, NULL, TIOCMSET, 
-				(unsigned long) &arg)) 
-	{ 
-		DEBUG( 0, __FUNCTION__"(), ioctl error!\n");
-	}
-	set_fs(fs);
+	/* Clear DTR */
+	irtty_set_dtr_rts(tty, FALSE, TRUE);
 
 	/* Sleep 10-20 ms*/
 	current->state = TASK_INTERRUPTIBLE;
 	schedule_timeout(2);
 	
-	DEBUG( 0, __FUNCTION__ "(), Setting DTR\n");
-	arg = TIOCM_RTS | TIOCM_DTR | TIOCM_OUT2;
-	
-	fs = get_fs();
-	set_fs( get_ds());
+	/* Go back to normal mode */
+	irtty_set_dtr_rts(tty, TRUE, TRUE);
 	
-	if ( tty->driver.ioctl( tty, NULL, TIOCMSET, 
-				(unsigned long) &arg)) 
-	{ 
-		DEBUG( 0, __FUNCTION__"(), ioctl error!\n");
-	}
-	set_fs(fs);
-
 	idev->qos.baud_rate.value = 9600;
 }
 
@@ -287,6 +239,9 @@
 }
 
 #ifdef MODULE
+
+MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
+MODULE_DESCRIPTION("ACTiSYS IR-220L and IR-220L+ dongle driver");	
 		
 /*
  * Function init_module (void)
diff -u --recursive --new-file v2.2.2/linux/drivers/net/irda/esi.c linux/drivers/net/irda/esi.c
--- v2.2.2/linux/drivers/net/irda/esi.c	Wed Jan 20 23:14:05 1999
+++ linux/drivers/net/irda/esi.c	Sun Mar  7 15:26:43 1999
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      esi.c
- * Version:       1.1
- * Description:   Driver for the Extended Systems JetEye PC
+ * Version:       1.2
+ * Description:   Driver for the Extended Systems JetEye PC dongle
  * Status:        Experimental.
  * Author:        Thomas Davis, <ratbert@radiks.net>
  * Created at:    Sat Feb 21 18:54:38 1998
- * Modified at:   Mon Jan 18 11:30:32 1999
+ * Modified at:   Tue Feb  9 15:36:47 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:	  esi.c
  *
@@ -71,6 +71,7 @@
 	strcat( idev->description, " <-> esi");
 
 	idev->io.dongle_id = type;
+	idev->flags |= IFF_DONGLE;
 
 	MOD_INC_USE_COUNT;
 }
@@ -90,10 +91,9 @@
 {
 	struct irtty_cb *self;
 	struct tty_struct *tty;
-	int arg = TIOCM_OUT2;
+	int dtr, rts;
         struct termios old_termios;
 	int cflag;
-	mm_segment_t fs;
 	
 	ASSERT( idev != NULL, return;);
 	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -116,37 +116,25 @@
 	switch (baud) {
 	case 19200:
 		cflag |= B19200;
-		arg |= TIOCM_DTR;
+		dtr = TRUE;
+		rts = FALSE;
 		break;
 	case 115200:
 		cflag |= B115200;
-		arg |= TIOCM_RTS | TIOCM_DTR;
+		dtr = rts = TRUE;
 		break;
 	case 9600:
 	default:
 		cflag |= B9600;
-		arg |= TIOCM_RTS;
+		dtr = FALSE;
+		rts = TRUE;
 		break;
 	}
-		
+	/* Change speed of serial driver */
 	tty->termios->c_cflag = cflag;
 	tty->driver.set_termios( tty, &old_termios);
 
-	/*
-	 *  The ioctl function, or actually set_modem_info in serial.c
-	 *  expects a pointer to the argument in user space. To hack us
-	 *  around this we use the set_fs function to fool the routines 
-	 *  that check if they are called from user space. We also need 
-	 *  to send a pointer to the argument so get_user() gets happy. 
-	 *  DB.
-	 */
-	fs = get_fs();
-	set_fs( get_ds());
-
-	if ( tty->driver.ioctl( tty, NULL, TIOCMSET, (unsigned long) &arg)) { 
-		DEBUG( 0, __FUNCTION__ "(), error setting ESI speed!\n");
-	}
-	set_fs(fs);
+	irtty_set_dtr_rts(tty, dtr, rts);
 }
 
 static void esi_reset( struct irda_device *idev, int unused)
diff -u --recursive --new-file v2.2.2/linux/drivers/net/irda/girbil.c linux/drivers/net/irda/girbil.c
--- v2.2.2/linux/drivers/net/irda/girbil.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/irda/girbil.c	Sun Mar  7 15:26:43 1999
@@ -0,0 +1,276 @@
+/*********************************************************************
+ *                
+ * Filename:      girbil.c
+ * Version:       1.0
+ * 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 Feb  9 15:36:36 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.
+ *  
+ *     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.
+ *     
+ ********************************************************************/
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/tty.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/ioctls.h>
+#include <asm/segment.h>
+#include <asm/uaccess.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 girbil_reset(struct irda_device *dev, int unused);
+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);
+
+/* Control register 1 */
+#define GIRBIL_TXEN    0x01 /* Enable transmitter */
+#define GIRBIL_RXEN    0x02 /* Enable receiver */
+#define GIRBIL_ECAN    0x04 /* Cancel self emmited data */
+#define GIRBIL_ECHO    0x08 /* Echo control characters */
+
+/* LED Current Register (0x2) */
+#define GIRBIL_HIGH    0x20
+#define GIRBIL_MEDIUM  0x21
+#define GIRBIL_LOW     0x22
+
+/* Baud register (0x3) */
+#define GIRBIL_2400    0x30
+#define GIRBIL_4800    0x31	
+#define GIRBIL_9600    0x32
+#define GIRBIL_19200   0x33
+#define GIRBIL_38400   0x34	
+#define GIRBIL_57600   0x35	
+#define GIRBIL_115200  0x36
+
+/* Mode register (0x4) */
+#define GIRBIL_IRDA    0x40
+#define GIRBIL_ASK     0x41
+
+/* Control register 2 (0x5) */
+#define GIRBIL_LOAD    0x51 /* Load the new baud rate value */
+
+static struct dongle dongle = {
+	GIRBIL_DONGLE,
+	girbil_open,
+	girbil_close,
+	girbil_reset,
+	girbil_change_speed,
+	girbil_init_qos,
+};
+
+__initfunc(void girbil_init(void))
+{
+	irtty_register_dongle(&dongle);
+}
+
+void girbil_cleanup(void)
+{
+	irtty_unregister_dongle(&dongle);
+}
+
+static void girbil_open(struct irda_device *idev, int type)
+{
+	strcat( idev->description, " <-> girbil");
+
+	idev->io.dongle_id = type;
+	idev->flags |= IFF_DONGLE;
+	
+	MOD_INC_USE_COUNT;
+}
+
+static void girbil_close(struct irda_device *dev)
+{
+	MOD_DEC_USE_COUNT;
+}
+
+/*
+ * Function girbil_change_speed (dev, speed)
+ *
+ *    Set the speed for the Girbil type dongle. Warning, this 
+ *    function must be called with a process context!
+ *
+ */
+static void girbil_change_speed(struct irda_device *idev, int speed)
+{
+	struct irtty_cb *self;
+	struct tty_struct *tty;
+	struct termios old_termios;
+	int cflag;
+	__u8 control[2];
+	
+	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;);
+	
+	if (!self->tty)
+		return;
+
+	tty = self->tty;
+	
+	old_termios = *(tty->termios);
+	cflag = tty->termios->c_cflag;
+
+	cflag &= ~CBAUD;
+
+	switch (speed) {
+	case 9600:
+	default:
+		cflag |= B9600;
+		control[0] = GIRBIL_9600;
+		break;
+	case 19200:
+		cflag |= B19200;
+		control[0] = GIRBIL_19200;
+		break;
+	case 34800:
+		cflag |= B38400;
+		control[0] = GIRBIL_38400;
+		break;
+	case 57600:
+		cflag |= B57600;
+		control[0] = GIRBIL_57600;
+		break;
+	case 115200:
+		cflag |= B115200;
+		control[0] = GIRBIL_115200;
+		break;
+	}
+	control[1] = GIRBIL_LOAD;
+
+	/* Set DTR and Clear RTS to enter command mode */
+	irtty_set_dtr_rts(tty, FALSE, TRUE);
+
+	/* Write control bytes */
+	if (tty->driver.write)
+		tty->driver.write(self->tty, 0, control, 2);
+
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(2);
+	
+	/* Go back to normal mode */
+	irtty_set_dtr_rts(tty, TRUE, TRUE);
+
+	/* Now change the speed of the serial port */
+	tty->termios->c_cflag = cflag;
+	tty->driver.set_termios(tty, &old_termios);	
+}
+
+/*
+ * Function girbil_reset (driver)
+ *
+ *      This function resets the girbil dongle. Warning, this function 
+ *      must be called with a process context!! 
+ *
+ *      Algorithm:
+ *    	  0. set RTS, and wait at least 5 ms 
+ *        1. clear RTS 
+ */
+void girbil_reset(struct irda_device *idev, int unused)
+{
+	struct irtty_cb *self;
+	struct tty_struct *tty;
+	__u8 control = GIRBIL_TXEN | GIRBIL_RXEN /* | GIRBIL_ECAN */;
+
+	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;);
+
+	tty = self->tty;
+	if (!tty)
+		return;
+
+	/* Reset dongle */
+	irtty_set_dtr_rts(tty, TRUE, FALSE);
+
+	/* Sleep at least 5 ms */
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(2);
+	
+	/* Set DTR and clear RTS to enter command mode */
+	irtty_set_dtr_rts(tty, FALSE, TRUE);
+
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(2);
+
+	/* Write control byte */
+	if (tty->driver.write)
+		tty->driver.write(self->tty, 0, &control, 1);
+
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(2);
+
+	/* Go back to normal mode */
+	irtty_set_dtr_rts(tty, TRUE, TRUE);
+}
+
+/*
+ * 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 &= 0xfe; /* All except 0 ms */
+}
+
+#ifdef MODULE
+
+MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
+MODULE_DESCRIPTION("Greenwich GIrBIL dongle driver");
+	
+/*
+ * Function init_module (void)
+ *
+ *    Initialize Girbil module
+ *
+ */
+int init_module(void)
+{
+	girbil_init();
+	return(0);
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ *    Cleanup Girbil module
+ *
+ */
+void cleanup_module(void)
+{
+        girbil_cleanup();
+}
+
+#endif /* MODULE */
diff -u --recursive --new-file v2.2.2/linux/drivers/net/irda/irport.c linux/drivers/net/irda/irport.c
--- v2.2.2/linux/drivers/net/irda/irport.c	Mon Jan 25 17:44:34 1999
+++ linux/drivers/net/irda/irport.c	Sun Mar  7 15:26:43 1999
@@ -96,7 +96,7 @@
 #ifdef MODULE
 static void irport_cleanup(void)
 {
-	int i;
+/* 	int i; */
 
         DEBUG( 4, __FUNCTION__ "()\n");
 
@@ -303,7 +303,6 @@
 int irport_hard_xmit( struct sk_buff *skb, struct device *dev)
 {
 	struct irda_device *idev;
-	int xbofs;
 	int actual;
 
 	DEBUG( 4, __FUNCTION__ "()\n");
diff -u --recursive --new-file v2.2.2/linux/drivers/net/irda/irtty.c linux/drivers/net/irda/irtty.c
--- v2.2.2/linux/drivers/net/irda/irtty.c	Wed Jan 20 23:14:05 1999
+++ linux/drivers/net/irda/irtty.c	Sun Mar  7 15:26:43 1999
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irtty.c
- * Version:       1.0
+ * Version:       1.1
  * Description:   IrDA line discipline implementation
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Dec  9 21:18:38 1997
- * Modified at:   Mon Jan 18 15:32:03 1999
+ * Modified at:   Tue Feb  9 13:08:25 1999
  * 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>
@@ -206,6 +206,7 @@
 	self->idev.qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
 		IR_115200;
 	self->idev.qos.min_turn_time.bits = 0x03;
+	self->idev.flags = IFF_SIR | IFF_PIO;
 	irda_qos_bits_to_value( &self->idev.qos);
 
 	/* Specify which buffer allocation policy we need */
@@ -272,8 +273,6 @@
 		kfree( self);
 
  	MOD_DEC_USE_COUNT;
-
-	DEBUG( 4, "IrTTY: close() -->\n");
 }
 
 /* 
@@ -289,6 +288,8 @@
 	struct irtty_cb *self;
 	int cflag;
 
+	DEBUG(4,__FUNCTION__ "(), <%ld>\n", jiffies); 
+
 	ASSERT( idev != NULL, return;);
 	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
 
@@ -360,10 +361,15 @@
 		DEBUG( 0, __FUNCTION__ "(), Tekram dongle!\n");
 		request_module( "tekram");
 		break;
-	case ACTISYS_DONGLE:
+	case ACTISYS_DONGLE:     /* FALLTHROUGH */
+	case ACTISYS_PLUS_DONGLE:
 		DEBUG( 0, __FUNCTION__ "(), ACTiSYS dongle!\n");
 		request_module( "actisys");
 		break;
+	case GIRBIL_DONGLE:
+		DEBUG( 0, __FUNCTION__ "(), GIrBIL dongle!\n");
+		request_module( "girbil");
+		break;
 	default:
 		DEBUG( 0, __FUNCTION__ "(), Unknown dongle type!\n");
 		return;
@@ -373,8 +379,7 @@
 
 	node = hashbin_find( dongles, type, NULL);
 	if ( !node) {
-		DEBUG( 0, __FUNCTION__ 
-		       "(), Unable to find requested dongle\n");
+		DEBUG(0, __FUNCTION__ "(), Unable to find requested dongle\n");
 		return;
 	}
 	self->dongle_q = node;
@@ -401,8 +406,7 @@
  *     The Swiss army knife of system calls :-)
  *
  */
-static int irtty_ioctl( struct tty_struct *tty, void *file, int cmd, 
-			void *arg) 
+static int irtty_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
 {
 	struct irtty_cb *self;
 	int err = 0;
@@ -444,8 +448,8 @@
  *    been received, which can now be decapsulated and delivered for
  *    further processing 
  */
-static void irtty_receive_buf( struct tty_struct *tty, const unsigned 
-			       char *cp, char *fp, int count) 
+static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
+			      char *fp, int count) 
 {
 	struct irtty_cb *self = (struct irtty_cb *) tty->disc_data;
 
@@ -464,11 +468,8 @@
  			cp++;
  			continue;
  		}
-		/*
-		 *  Unwrap and destuff one byte
-		 */
+		/* Unwrap and destuff one byte */
 		async_unwrap_char( &self->idev, *cp++);
-		/* self->rx_over_errors++; */
 	}
 }
 
@@ -478,7 +479,7 @@
  *    Transmit skb
  *
  */
-static int irtty_hard_xmit( struct sk_buff *skb, struct device *dev)
+static int irtty_hard_xmit(struct sk_buff *skb, struct device *dev)
 {
 	struct irtty_cb *self;
 	struct irda_device *idev;
@@ -487,43 +488,40 @@
 	ASSERT( dev != NULL, return 0;);
 	ASSERT( skb != NULL, return 0;);
 
-	if ( dev->tbusy) {
-		DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n");
-		
-		return -EBUSY;
-	}
-
 	idev = (struct irda_device *) dev->priv;
 
-	ASSERT( idev != NULL, return 0;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+	ASSERT(idev != NULL, return 0;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
 	
 	self = (struct irtty_cb *) idev->priv;
 
-	ASSERT( self != NULL, return 0;);
-	ASSERT( self->magic == IRTTY_MAGIC, return 0;);
+	ASSERT(self != NULL, return 0;);
+	ASSERT(self->magic == IRTTY_MAGIC, return 0;);
 
 	/* Lock transmit buffer */
-	if ( irda_lock( (void *) &dev->tbusy) == FALSE)
-		return 0;
+	if (irda_lock((void *) &dev->tbusy) == FALSE)
+		return -EBUSY;
 
         /*  
 	 *  Transfer 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); 
+        idev->tx_buff.len = async_wrap_skb(skb, idev->tx_buff.data, 
+					   idev->tx_buff.truesize); 
 
 	self->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
 
 	dev->trans_start = jiffies;
 
 	if ( self->tty->driver.write)
-		actual = self->tty->driver.write( self->tty, 0, 
-						  idev->tx_buff.data, 
-						  idev->tx_buff.len);
+		actual = self->tty->driver.write(self->tty, 0, 
+						 idev->tx_buff.data, 
+						 idev->tx_buff.len);
 
 	idev->tx_buff.offset = actual;
 	idev->tx_buff.head = idev->tx_buff.data + 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
@@ -535,8 +533,7 @@
  		irda_unlock( &self->tbusy);
  	}
 #endif
-
-	dev_kfree_skb( skb);
+	dev_kfree_skb(skb);
 
 	return 0;
 }
@@ -587,8 +584,6 @@
 		tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
 
 		idev->netdev.tbusy = 0; /* Unlock */
-		idev->stats.tx_packets++;
-		idev->stats.tx_bytes += idev->tx_buff.len;
 
 		/* Tell network layer that we want more frames */
 		mark_bh( NET_BH);
@@ -602,8 +597,6 @@
 	actual = tty->driver.write( tty, 0, idev->tx_buff.head, count);
 	idev->tx_buff.offset += actual;
 	idev->tx_buff.head += actual;
-
-	DEBUG( 4, "actual=%d, sent %d\n", actual, count);
 }
 
 /*
@@ -648,8 +641,7 @@
         }
 	
 	/* Make new IrDA dongle */
-        new = (struct dongle_q *) kmalloc (sizeof (struct dongle_q), 
-					      GFP_KERNEL);
+        new = (struct dongle_q *)kmalloc(sizeof(struct dongle_q), GFP_KERNEL);
         if (new == NULL) {
                 return 1;
 		
@@ -675,6 +667,35 @@
 	kfree( node);
 }
 
+
+void irtty_set_dtr_rts(struct tty_struct *tty, int dtr, int rts)
+{
+	mm_segment_t fs;
+	int arg = TIOCM_OUT2;
+
+	if (rts)
+		arg |= TIOCM_RTS;
+	if (dtr)
+		arg |= TIOCM_DTR;
+
+	/*
+	 *  The ioctl() function, or actually set_modem_info() in serial.c
+	 *  expects a pointer to the argument in user space. To hack us
+	 *  around this, we use the set_fs() function to fool the routines 
+	 *  that check if they are called from user space. We also need 
+	 *  to send a pointer to the argument so get_user() gets happy. DB.
+	 */
+
+	fs = get_fs();
+	set_fs(get_ds());
+	
+	if (tty->driver.ioctl(tty, NULL, TIOCMSET, (unsigned long) &arg)) { 
+		DEBUG(0, __FUNCTION__ "(), error!\n");
+	}
+	set_fs(fs);
+}
+
+
 static int irtty_net_init( struct device *dev)
 {
 	/* Set up to be a normal IrDA network device driver */
@@ -714,6 +735,9 @@
 }
 
 #ifdef MODULE
+
+MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
+MODULE_DESCRIPTION("IrDA TTY device driver");
 
 /*
  * Function init_module (void)
diff -u --recursive --new-file v2.2.2/linux/drivers/net/irda/pc87108.c linux/drivers/net/irda/pc87108.c
--- v2.2.2/linux/drivers/net/irda/pc87108.c	Wed Jan 20 23:14:05 1999
+++ linux/drivers/net/irda/pc87108.c	Sun Mar  7 15:26:43 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Nov  7 21:43:15 1998
- * Modified at:   Mon Dec 28 08:46:16 1998
+ * Modified at:   Tue Feb  9 13:29:40 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>
@@ -50,7 +50,6 @@
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/malloc.h>
-#include <linux/delay.h>
 #include <linux/init.h>
 
 #include <asm/io.h>
@@ -100,7 +99,9 @@
 /* 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); 
@@ -221,6 +222,8 @@
 	idev->qos.min_turn_time.bits = 0x07;
 	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;
@@ -250,6 +253,7 @@
 	return 0;
 }
 
+#ifdef MODULE
 /*
  * Function pc87108_close (idev)
  *
@@ -276,6 +280,7 @@
 
 	return 0;
 }
+#endif /* MODULE */
 
 /*
  * Function pc87108_probe (iobase, board_addr, irq, dma)
@@ -720,12 +725,6 @@
 	iobase = idev->io.iobase;
 
 	DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
-
-	if ( dev->tbusy) {
-		DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n");
-			
-		return -EBUSY;
-	}
 	
 	/* Lock transmit buffer */
 	if ( irda_lock( (void *) &dev->tbusy) == FALSE)
diff -u --recursive --new-file v2.2.2/linux/drivers/net/irda/tekram.c linux/drivers/net/irda/tekram.c
--- v2.2.2/linux/drivers/net/irda/tekram.c	Wed Jan 20 23:14:05 1999
+++ linux/drivers/net/irda/tekram.c	Sun Mar  7 15:26:43 1999
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      tekram.c
- * Version:       0.4
+ * Version:       0.5
  * Description:   Implementation of the Tekram IrMate IR-210B dongle
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Wed Oct 21 20:02:35 1998
- * Modified at:   Mon Jan 18 11:30:38 1999
+ * Modified at:   Tue Feb  9 15:36:55 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -63,9 +63,12 @@
 	irtty_unregister_dongle( &dongle);
 }
 
-static void tekram_open( struct irda_device *dev, int type)
+static void tekram_open( struct irda_device *idev, int type)
 {
-	strcat( dev->name, " <-> tekram");
+	strcat(idev->description, " <-> tekram");
+
+	idev->io.dongle_id = type;
+	idev->flags |= IFF_DONGLE;
 	
 	MOD_INC_USE_COUNT;
 }
@@ -96,11 +99,8 @@
 	struct irtty_cb *self;
 	struct tty_struct *tty;
 	struct termios old_termios;
-	int arg = 0;
 	int cflag;
 	__u8 byte;
-	int actual;
-	mm_segment_t fs;
 	
 	DEBUG( 4, __FUNCTION__ "()\n");
 
@@ -147,44 +147,22 @@
 	}
 
 	/* Set DTR, Clear RTS */
-	DEBUG( 0, __FUNCTION__ "(), Setting DTR, Clearing RTS\n");
-	arg = TIOCM_DTR | TIOCM_OUT2;
-	
-	fs = get_fs();
-	set_fs( get_ds());
-	
-	if ( tty->driver.ioctl( tty, NULL, TIOCMSET, 
-                                (unsigned long) &arg)) { 
-		DEBUG( 0, "error setting Tekram speed!\n");
-	}
-	set_fs(fs);
+	irtty_set_dtr_rts(tty, TRUE, FALSE);
 	
 	/* Wait at least 7us */
 	udelay( 7);
 
-	DEBUG( 0, __FUNCTION__ "(), Writing control byte\n");
 	/* Write control byte */
 	if ( tty->driver.write)
-		actual = tty->driver.write( self->tty, 0, &byte, 1);
+		tty->driver.write( self->tty, 0, &byte, 1);
 	
 	/* Wait at least 100 ms */
 	current->state = TASK_INTERRUPTIBLE;
 	schedule_timeout( 10);
         
 	/* Set DTR, Set RTS */
-	DEBUG( 0, __FUNCTION__ "(), Setting DTR, Setting RTS\n");
-	arg = TIOCM_DTR | TIOCM_RTS | TIOCM_OUT2;
-	
-	fs = get_fs();
-	set_fs( get_ds());
-	
-	if ( tty->driver.ioctl( tty, NULL, TIOCMSET, 
-				(unsigned long) &arg)) { 
-		DEBUG( 0, "error setting Tekram speed!\n");
-	}
-	set_fs(fs);
+	irtty_set_dtr_rts(tty, TRUE, TRUE);
 
-	DEBUG( 0, __FUNCTION__ "(), Setting new speed on serial port\n");
 	/* Now change the speed of the serial port */
 	tty->termios->c_cflag = cflag;
 	tty->driver.set_termios( tty, &old_termios);	
@@ -208,8 +186,6 @@
 {
 	struct irtty_cb *self;
 	struct tty_struct *tty;
-	int arg = 0;
-	mm_segment_t fs;
 
 	DEBUG( 4, __FUNCTION__ "()\n");
 
@@ -225,51 +201,22 @@
 	if ( !tty)
 		return;
 
-	DEBUG( 0, __FUNCTION__ "(), Power off dongle\n");
-	arg = TIOCM_RTS | TIOCM_DTR | TIOCM_OUT2;
-	
-	fs = get_fs();
-	set_fs( get_ds());
-	
-	if ( tty->driver.ioctl( tty, NULL, TIOCMSET, 
-				(unsigned long) &arg)) 
-	{ 
-		DEBUG(0, "error setting ESI speed!\n");
-	}
-	set_fs(fs);
+	/* Power off dongle */
+	irtty_set_dtr_rts(tty, FALSE, FALSE);
 
 	/* Sleep 50 ms */
 	current->state = TASK_INTERRUPTIBLE;
 	schedule_timeout(5);
-	
-	DEBUG( 0, __FUNCTION__ "(), Set DTR, clear RTS\n");
-	/* Set DTR, clear RTS */
-	arg = TIOCM_DTR | TIOCM_OUT2;
-	
-	fs = get_fs();
-	set_fs( get_ds());
-	
-	if ( tty->driver.ioctl( tty, NULL, TIOCMSET, 
-				(unsigned long) &arg)) { 
-		DEBUG( 0, "Error setting Tekram speed!\n");
-	}
-	set_fs(fs);
+
+	/* Clear DTR, Set RTS */
+	irtty_set_dtr_rts(tty, FALSE, TRUE); 
 
 	/* Should sleep 1 ms, but 10-20 should not do any harm */
 	current->state = TASK_INTERRUPTIBLE;
 	schedule_timeout(2);
 
-	DEBUG( 0, __FUNCTION__ "(), STATE3\n");
-	/* Clear DTR, clear RTS */
-	arg = TIOCM_OUT2;
-
-	fs = get_fs();
-	set_fs( get_ds());
-	
-	if ( tty->driver.ioctl( tty, NULL, TIOCMSET, (unsigned long) &arg)) { 
-		DEBUG( 0, "error setting Tekram speed!\n");
-	}
-	set_fs(fs);
+	/* Set DTR, Set RTS */
+	irtty_set_dtr_rts(tty, TRUE, TRUE);
 	
 	/* Finished! */
 }
@@ -287,6 +234,9 @@
 }
 
 #ifdef MODULE
+
+MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
+MODULE_DESCRIPTION("Tekram IrMate IR-210B dongle driver");
 		
 /*
  * Function init_module (void)
@@ -311,4 +261,4 @@
         tekram_cleanup();
 }
 
-#endif
+#endif /* MODULE */
diff -u --recursive --new-file v2.2.2/linux/drivers/net/irda/uircc.c linux/drivers/net/irda/uircc.c
--- v2.2.2/linux/drivers/net/irda/uircc.c	Mon Jan 25 17:44:34 1999
+++ linux/drivers/net/irda/uircc.c	Sun Mar  7 15:26:43 1999
@@ -7,7 +7,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Dec 26 10:59:03 1998
- * Modified at:   Tue Jan 19 23:54:04 1999
+ * Modified at:   Tue Feb  9 13:30:41 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -196,6 +196,8 @@
 
 	idev->qos.min_turn_time.bits = 0x07;
 	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;
@@ -271,9 +273,11 @@
 static int uircc_probe( int iobase, int iobase2, int irq, int dma) 
 {
 	int version;
+#if 0
 	int probe_irq=0;
 	unsigned long mask;
 	int i;
+#endif
 	
 	DEBUG( 0, __FUNCTION__ "()\n");
 
@@ -442,20 +446,12 @@
 	DEBUG(0, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
 
 	/* Use irport for SIR speeds */
-	if ( idev->io.baudrate <= 115200) {
-		return irport_hard_xmit( skb, dev);
-	}
-
-	if ( dev->tbusy) {
-		__u8 sr3;
-
-		DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n");
-			
-		return -EBUSY;
+	if (idev->io.baudrate <= 115200) {
+		return irport_hard_xmit(skb, dev);
 	}
 	
 	/* Lock transmit buffer */
-	if ( irda_lock( (void *) &dev->tbusy) == FALSE)
+	if (irda_lock((void *) &dev->tbusy) == FALSE)
 		return -EBUSY;
 
 	memcpy( idev->tx_buff.data, skb->data, skb->len);
diff -u --recursive --new-file v2.2.2/linux/drivers/net/irda/w83977af_ir.c linux/drivers/net/irda/w83977af_ir.c
--- v2.2.2/linux/drivers/net/irda/w83977af_ir.c	Tue Dec 22 14:16:55 1998
+++ linux/drivers/net/irda/w83977af_ir.c	Sun Mar  7 15:26:43 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Paul VanderSpek
  * Created at:    Wed Nov  4 11:46:16 1998
- * Modified at:   Mon Dec 14 21:51:53 1998
+ * Modified at:   Tue Feb  9 13:30:35 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Corel Computer Corp.
@@ -204,6 +204,8 @@
 	/* The HP HDLS-1100 needs 1 ms according to the specs */
 	idev->qos.min_turn_time.bits = 0x03; /* 1ms and more */
 	irda_qos_bits_to_value( &idev->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;
@@ -468,12 +470,6 @@
 	iobase = idev->io.iobase;
 
 	DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
-
-	if ( dev->tbusy) {
-		DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n");
-
-		return -EBUSY;
-	}
 	
 	/* Lock transmit buffer */
 	if ( irda_lock( (void *) &dev->tbusy) == FALSE)
diff -u --recursive --new-file v2.2.2/linux/drivers/net/ne.c linux/drivers/net/ne.c
--- v2.2.2/linux/drivers/net/ne.c	Tue Dec 22 14:16:55 1998
+++ linux/drivers/net/ne.c	Sun Mar  7 15:47:46 1999
@@ -105,6 +105,7 @@
     {"ET-100","ET-200", {0x00, 0x45, 0x54}}, /* YANG and YA clone */
     {"COMPEX","COMPEX16",{0x00,0x80,0x48}}, /* Broken ISA Compex cards */
     {"E-LAN100", "E-LAN200", {0x00, 0x00, 0x5d}}, /* Broken ne1000 clones */
+    {"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */    
     {0,}
 };
 #endif
diff -u --recursive --new-file v2.2.2/linux/drivers/net/plip.c linux/drivers/net/plip.c
--- v2.2.2/linux/drivers/net/plip.c	Thu Jan  7 15:11:37 1999
+++ linux/drivers/net/plip.c	Sun Mar  7 15:47:46 1999
@@ -1217,7 +1217,7 @@
 plip_searchfor(int list[], int a)
 {
 	int i;
-	for (i = 0; i < 3 && list[i] != -1; i++) {
+	for (i = 0; i < PLIP_MAX && list[i] != -1; i++) {
 		if (list[i] == a) return 1;
 	}
 	return 0;
@@ -1240,7 +1240,7 @@
 	/* If the user feeds parameters, use them */
 	while (pb) {
 		if ((parport[0] == -1 && (!timid || !pb->devices)) || 
-		    plip_searchfor(parport, i)) {
+		    plip_searchfor(parport, pb->number)) {
 			if (i == PLIP_MAX) {
 				printk(KERN_ERR "plip: too many devices\n");
 				break;
diff -u --recursive --new-file v2.2.2/linux/drivers/net/shaper.c linux/drivers/net/shaper.c
--- v2.2.2/linux/drivers/net/shaper.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/net/shaper.c	Wed Feb 24 16:27:53 1999
@@ -53,6 +53,13 @@
  *		This will be fixed in BETA4
  */
  
+/*
+ * bh_atomic() SMP races fixes and rewritten the locking code to be SMP safe
+ * and irq-mask friendly. NOTE: we can't use start_bh_atomic() in kick_shaper()
+ * because it's going to be recalled from an irq handler, and synchronize_bh()
+ * is a nono if called from irq context.
+ *						1999  Andrea Arcangeli
+ */
  
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -83,21 +90,17 @@
  
 static int shaper_lock(struct shaper *sh)
 {
-	unsigned long flags;
-	save_flags(flags);
-	cli();
 	/*
-	 *	Lock in an interrupt may fail
+	 *	Lock in an interrupt must fail
 	 */
-	if(sh->locked && in_interrupt())
+	while (test_and_set_bit(0, &sh->locked))
 	{
-		restore_flags(flags);
-		return 0;
+		if (!in_interrupt())
+			sleep_on(&sh->wait_queue);
+		else
+			return 0;
+			
 	}
-	while(sh->locked)
-		sleep_on(&sh->wait_queue);
-	sh->locked=1;
-	restore_flags(flags);
 	return 1;
 }
 
@@ -105,7 +108,7 @@
 
 static void shaper_unlock(struct shaper *sh)
 {
-	sh->locked=0;
+	clear_bit(0, &sh->locked);
 	wake_up(&sh->wait_queue);
 	shaper_kick(sh);
 }
@@ -240,7 +243,6 @@
  		dev_kfree_skb(ptr);
  	}
  	shaper_unlock(shaper);
- 	shaper_kick(shaper);
  	return 0;
 }
 
@@ -285,24 +287,16 @@
 static void shaper_kick(struct shaper *shaper)
 {
 	struct sk_buff *skb;
-	unsigned long flags;
 	
-	save_flags(flags);
-	cli();
-
-	del_timer(&shaper->timer);
-
 	/*
 	 *	Shaper unlock will kick
 	 */
 	 
-	if(shaper->locked)
-	{	
+	if (test_and_set_bit(0, &shaper->locked))
+	{
 		if(sh_debug)
 			printk("Shaper locked.\n");
-		shaper->timer.expires=jiffies+1;
-		add_timer(&shaper->timer);
-		restore_flags(flags);
+		mod_timer(&shaper->timer, jiffies);
 		return;
 	}
 
@@ -320,7 +314,7 @@
 		 
 		if(sh_debug)
 			printk("Clock = %d, jiffies = %ld\n", skb->shapeclock, jiffies);
-		if(skb->shapeclock - jiffies <= SHAPER_BURST)
+		if(time_before_eq(skb->shapeclock - jiffies, SHAPER_BURST))
 		{
 			/*
 			 *	Pull the frame and get interrupts back on.
@@ -329,8 +323,6 @@
 			skb_unlink(skb);
 			if (shaper->recovery < skb->shapeclock + skb->shapelen)
 				shaper->recovery = skb->shapeclock + skb->shapelen;
-			restore_flags(flags);
-
 			/*
 			 *	Pass on to the physical target device via
 			 *	our low level packet thrower.
@@ -338,7 +330,6 @@
 			
 			skb->shapepend=0;
 			shaper_queue_xmit(shaper, skb);	/* Fire */
-			cli();
 		}
 		else
 			break;
@@ -349,17 +340,9 @@
 	 */
 	 
 	if(skb!=NULL)
-	{
-		del_timer(&shaper->timer);
-		shaper->timer.expires=skb->shapeclock;
-		add_timer(&shaper->timer);
-	}
-		
-	/*
-	 *	Interrupts on, mission complete
-	 */
-		
-	restore_flags(flags);
+		mod_timer(&shaper->timer, skb->shapeclock);
+
+	clear_bit(0, &shaper->locked);
 }
 
 
@@ -370,8 +353,14 @@
 static void shaper_flush(struct shaper *shaper)
 {
 	struct sk_buff *skb;
+ 	if(!shaper_lock(shaper))
+	{
+		printk(KERN_ERR "shaper: shaper_flush() called by an irq!\n");
+ 		return;
+	}
 	while((skb=skb_dequeue(&shaper->sendq))!=NULL)
 		dev_kfree_skb(skb);
+	shaper_unlock(shaper);
 }
 
 /*
@@ -405,7 +394,9 @@
 {
 	struct shaper *shaper=dev->priv;
 	shaper_flush(shaper);
+	start_bh_atomic();
 	del_timer(&shaper->timer);
+	end_bh_atomic();
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
diff -u --recursive --new-file v2.2.2/linux/drivers/net/sk_g16.c linux/drivers/net/sk_g16.c
--- v2.2.2/linux/drivers/net/sk_g16.c	Tue Jul 28 14:21:08 1998
+++ linux/drivers/net/sk_g16.c	Sun Mar  7 15:47:46 1999
@@ -733,7 +733,7 @@
     SK_print_pos(dev, "POS registers after ROM, RAM config");
 #endif
 
-    board = (SK_RAM *) rom_addr; 
+    board = (SK_RAM *) bus_to_virt(rom_addr);
 
     /* Read in station address */
     for (i = 0, j = 0; i < ETH_ALEN; i++, j+=2)
diff -u --recursive --new-file v2.2.2/linux/drivers/net/smc-ultra.c linux/drivers/net/smc-ultra.c
--- v2.2.2/linux/drivers/net/smc-ultra.c	Tue Feb 23 15:21:33 1999
+++ linux/drivers/net/smc-ultra.c	Wed Feb 24 16:27:54 1999
@@ -2,7 +2,7 @@
 /*
 	This is a driver for the SMC Ultra and SMC EtherEZ ISA ethercards.
 
-	Written 1993-1996 by Donald Becker.
+	Written 1993-1998 by Donald Becker.
 
 	Copyright 1993 United States Government as represented by the
 	Director, National Security Agency.
@@ -14,7 +14,7 @@
 	Center of Excellence in Space Data and Information Sciences
 		Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
 
-	This driver uses the cards in the 8390-compatible, shared memory mode.
+	This driver uses the cards in the 8390-compatible mode.
 	Most of the run-time complexity is handled by the generic code in
 	8390.c.  The code in this file is responsible for
 
@@ -27,6 +27,8 @@
 
 		ultra_block_input()		Routines for reading and writing blocks of
 		ultra_block_output()	packet buffer memory.
+		ultra_pio_input()
+		ultra_pio_output()
 
 	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
@@ -34,7 +36,7 @@
 
 	This driver now supports the programmed-I/O (PIO) data transfer mode of
 	the EtherEZ. It does not use the non-8390-compatible "Altego" mode.
-	That support (if available) is smc-ez.c.
+	That support (if available) is in smc-ez.c.
 
 	Changelog:
 
@@ -44,8 +46,7 @@
 */
 
 static const char *version =
-	"smc-ultra.c:v2.00 6/6/96 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
-
+	"smc-ultra.c:v2.02 2/3/98 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
 
 #include <linux/module.h>
 
@@ -75,13 +76,13 @@
 static void ultra_block_input(struct device *dev, int count,
 						  struct sk_buff *skb, int ring_offset);
 static void ultra_block_output(struct device *dev, int count,
-							const unsigned char *buf, int start_page);
+							const unsigned char *buf, const int start_page);
 static void ultra_pio_get_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
 						int ring_page);
 static void ultra_pio_input(struct device *dev, int count,
 						  struct sk_buff *skb, int ring_offset);
 static void ultra_pio_output(struct device *dev, int count,
-							const unsigned char *buf, int start_page);
+							 const unsigned char *buf, const int start_page);
 static int ultra_close_card(struct device *dev);
 
 
@@ -155,11 +156,8 @@
 	if (load_8390_module("smc-ultra.c"))
 		return -ENOSYS;
 
-	/* We should have a "dev" from Space.c or the static module table. */
-	if (dev == NULL) {
-		printk("smc-ultra.c: Passed a NULL device.\n");
+	if (dev == NULL)
 		dev = init_etherdev(0, 0);
-	}
 
 	if (ei_debug  &&  version_printed++ == 0)
 		printk(version);
@@ -255,12 +253,19 @@
 ultra_open(struct device *dev)
 {
 	int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
+	unsigned char irq2reg[] = {0, 0, 0x04, 0x08, 0, 0x0C, 0, 0x40,
+							   0, 0x04, 0x44, 0x48, 0, 0, 0, 0x4C, };
 
 	if (request_irq(dev->irq, ei_interrupt, 0, ei_status.name, dev))
 		return -EAGAIN;
 
 	outb(0x00, ioaddr);	/* Disable shared memory for safety. */
 	outb(0x80, ioaddr + 5);
+	/* Set the IRQ line. */
+	outb(inb(ioaddr + 4) | 0x80, ioaddr + 4);
+	outb((inb(ioaddr + 13) & ~0x4C) | irq2reg[dev->irq], ioaddr + 13);
+	outb(inb(ioaddr + 4) & 0x7f, ioaddr + 4);
+
 	if (ei_status.block_input == &ultra_pio_input) {
 		outb(0x11, ioaddr + 6);		/* Enable interrupts and PIO. */
 		outb(0x01, ioaddr + 0x19);  	/* Enable ring read auto-wrap. */
@@ -358,7 +363,7 @@
    byte-sequentially to IOPA, with no intervening I/O operations, and the
    data is read or written to the IOPD data port.
    The only potential complication is that the address register is shared
-   must be always be rewritten between each read/write direction change.
+   and must be always be rewritten between each read/write direction change.
    This is no problem for us, as the 8390 code ensures that we are single
    threaded. */
 static void ultra_pio_get_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
@@ -379,20 +384,17 @@
 	/* For now set the address again, although it should already be correct. */
 	outb(ring_offset, ioaddr + IOPA);	/* Set the address, LSB first. */
 	outb(ring_offset >> 8, ioaddr + IOPA);
+	/* We know skbuffs are padded to at least word alignment. */
 	insw(ioaddr + IOPD, buf, (count+1)>>1);
-#ifdef notdef
-	/* We don't need this -- skbuffs are padded to at least word alignment. */
-	if (count & 0x01) {
-		buf[count-1] = inb(ioaddr + IOPD);
-#endif
 }
 
 static void ultra_pio_output(struct device *dev, int count,
-							const unsigned char *buf, int start_page)
+							const unsigned char *buf, const int start_page)
 {
 	int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
 	outb(0x00, ioaddr + IOPA);	/* Set the address, LSB first. */
 	outb(start_page, ioaddr + IOPA);
+	/* An extra odd byte is OK here as well. */
 	outsw(ioaddr + IOPD, buf, (count+1)>>1);
 }
 
@@ -461,15 +463,12 @@
 		}
 		if (register_netdev(dev) != 0) {
 			printk(KERN_WARNING "smc-ultra.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;
-			}
+			if (found != 0) return 0;	/* Got at least one. */
 			return -ENXIO;
 		}
 		found++;
 	}
-	lock_8390_module();
+
 	return 0;
 }
 
@@ -481,15 +480,14 @@
 	for (this_dev = 0; this_dev < MAX_ULTRA_CARDS; this_dev++) {
 		struct device *dev = &dev_ultra[this_dev];
 		if (dev->priv != NULL) {
+			/* NB: ultra_close_card() does free_irq + irq2dev */
 			int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET;
-			void *priv = dev->priv;
-			/* NB: ultra_close_card() does free_irq */
+			kfree(dev->priv);
+			dev->priv = NULL;
 			release_region(ioaddr, ULTRA_IO_EXTENT);
 			unregister_netdev(dev);
-			kfree(priv);
 		}
 	}
-	unlock_8390_module();
 }
 #endif /* MODULE */
 
@@ -500,6 +498,7 @@
  *  version-control: t
  *  kept-new-versions: 5
  *  c-indent-level: 4
+ *  c-basic-offset: 4
  *  tab-width: 4
  * End:
  */
diff -u --recursive --new-file v2.2.2/linux/drivers/pci/pci.c linux/drivers/pci/pci.c
--- v2.2.2/linux/drivers/pci/pci.c	Wed Jan 20 23:14:05 1999
+++ linux/drivers/pci/pci.c	Sun Mar  7 15:19:55 1999
@@ -1,12 +1,12 @@
 /*
- *	$Id: pci.c,v 1.90 1998/09/05 12:39:39 mj Exp $
+ *	$Id: pci.c,v 1.91 1999/01/21 13:34:01 davem Exp $
  *
  *	PCI Bus Services, see include/linux/pci.h for further explanation.
  *
  *	Copyright 1993 -- 1997 Drew Eckhardt, Frederic Potter,
  *	David Mosberger-Tang
  *
- *	Copyright 1997 -- 1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ *	Copyright 1997 -- 1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
  */
 
 #include <linux/config.h>
@@ -28,9 +28,6 @@
 #endif
 
 struct pci_bus pci_root;
-#ifdef CONFIG_VISWS
-struct pci_bus pci_other;
-#endif
 struct pci_dev *pci_devices = NULL;
 static struct pci_dev **pci_last_dev_p = &pci_devices;
 static int pci_reverse __initdata = 0;
@@ -371,6 +368,18 @@
 	return max;
 }
 
+struct pci_bus * __init pci_scan_peer_bridge(int bus)
+{
+	struct pci_bus *b;
+
+	b = kmalloc(sizeof(*b), GFP_KERNEL);
+	memset(b, 0, sizeof(*b));
+	b->next = pci_root.next;
+	pci_root.next = b;
+	b->number = b->secondary = bus;
+	b->subordinate = pci_scan_bus(b);
+	return b;
+}
 
 __initfunc(void pci_init(void))
 {
@@ -385,11 +394,6 @@
 
 	memset(&pci_root, 0, sizeof(pci_root));
 	pci_root.subordinate = pci_scan_bus(&pci_root);
-#ifdef CONFIG_VISWS
-	pci_other.number = 1; /* XXX unless bridge(s) on pci_root */
-	pci_other.subordinate = pci_scan_bus(&pci_other);
-	pci_root.next = &pci_other;
-#endif
 
 	/* give BIOS a chance to apply platform specific fixes: */
 	pcibios_fixup();
@@ -402,7 +406,6 @@
 	pci_proc_init();
 #endif
 }
-
 
 __initfunc(void pci_setup (char *str, int *ints))
 {
diff -u --recursive --new-file v2.2.2/linux/drivers/sbus/char/flash.c linux/drivers/sbus/char/flash.c
--- v2.2.2/linux/drivers/sbus/char/flash.c	Mon Oct  5 13:13:40 1998
+++ linux/drivers/sbus/char/flash.c	Sun Mar  7 10:43:29 1999
@@ -72,8 +72,6 @@
 	if (remap_page_range(vma->vm_start, addr, size, vma->vm_page_prot))
 		return -EAGAIN;
 		
-	vma->vm_file = file;
-	file->f_count++;
 	return 0;
 }
 
diff -u --recursive --new-file v2.2.2/linux/drivers/sbus/char/vfc_dev.c linux/drivers/sbus/char/vfc_dev.c
--- v2.2.2/linux/drivers/sbus/char/vfc_dev.c	Sun Nov  8 14:03:01 1998
+++ linux/drivers/sbus/char/vfc_dev.c	Sun Mar  7 10:43:40 1999
@@ -582,8 +582,6 @@
 	if(ret)
 		return -EAGAIN;
 
-	vma->vm_file = file;
-	file->f_count++;
 	return 0;
 }
 
diff -u --recursive --new-file v2.2.2/linux/drivers/scsi/ChangeLog.ncr53c8xx linux/drivers/scsi/ChangeLog.ncr53c8xx
--- v2.2.2/linux/drivers/scsi/ChangeLog.ncr53c8xx	Tue Jan 19 11:32:51 1999
+++ linux/drivers/scsi/ChangeLog.ncr53c8xx	Sun Mar  7 10:13:22 1999
@@ -1,4 +1,26 @@
-Sat Jan 16  17:30 1998 Gerard Roudier (groudier@club-internet.fr)
+Sat Mar 6  11:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.1h
+	- Fix some oooold bug that hangs the bus if a device rejects a 
+	  negotiation. Btw, the corresponding stuff also needed some cleanup 
+	  and thus the change is a bit larger than it could have been.
+	- Still some typo that made compilation fail for 64 bit (trivial fix).
+
+Sun Feb  14:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.1g
+	- Deal correctly with 64 bit PCI address registers on Linux 2.2.
+	  Pointed out by Leonard Zubkoff.
+	- Allow to tune request_irq() flags from the boot command line using 
+	  ncr53c8xx=irqm:??, as follows:
+	  a) If bit 0x10 is set in irqm, SA_SHIRQ flag is not used.
+	  b) If bit 0x20 is set in irqm, SA_INTERRUPT flag is not used.
+	  By default the driver uses both SA_SHIRQ and SA_INTERRUPT.
+	  Option 'ncr53c8xx=irqm:0x20' may be used when an IRQ is shared by 
+	  a 53C8XX adapter and a network board.
+	- Tiny mispelling fixed (ABORT instead of ABRT). Was fortunately 
+	  harmless.
+	- Negotiate SYNC data transfers with CCS devices.
+
+Sat Jan 16  17:30 1999 Gerard Roudier (groudier@club-internet.fr)
 	* revision 3.1f
 	- Some PCI fix-ups not needed any more for PPC (from Cort).
 	- Cache line size set to 16 DWORDS for Sparc   (from DSM).
diff -u --recursive --new-file v2.2.2/linux/drivers/scsi/Config.in linux/drivers/scsi/Config.in
--- v2.2.2/linux/drivers/scsi/Config.in	Mon Jan  4 15:08:17 1999
+++ linux/drivers/scsi/Config.in	Wed Feb 24 16:27:54 1999
@@ -66,6 +66,7 @@
 fi
 if [ "$CONFIG_PCI" = "y" ]; then
   dep_tristate 'Initio 9100U(W) support' CONFIG_SCSI_INITIO $CONFIG_SCSI
+  dep_tristate 'Initio INI-A100U2W support' CONFIG_SCSI_INIA100 $CONFIG_SCSI
 fi
 if [ "$CONFIG_PARPORT" != "n" ]; then
   dep_tristate 'IOMEGA parallel port (ppa - older drives)' CONFIG_SCSI_PPA $CONFIG_SCSI $CONFIG_PARPORT
@@ -76,6 +77,7 @@
   fi
 fi
 dep_tristate 'NCR53c406a SCSI support' CONFIG_SCSI_NCR53C406A $CONFIG_SCSI
+dep_tristate 'symbios 53c416 SCSI support' CONFIG_SCSI_SYM53C416 $CONFIG_SCSI
 if [ "$CONFIG_PCI" = "y" ]; then
   dep_tristate 'NCR53c7,8xx SCSI support'  CONFIG_SCSI_NCR53C7xx $CONFIG_SCSI
   if [ "$CONFIG_SCSI_NCR53C7xx" != "n" ]; then
@@ -117,7 +119,7 @@
 dep_tristate 'Qlogic FAS SCSI support' CONFIG_SCSI_QLOGIC_FAS $CONFIG_SCSI
 if [ "$CONFIG_PCI" = "y" ]; then
   dep_tristate 'Qlogic ISP SCSI support' CONFIG_SCSI_QLOGIC_ISP $CONFIG_SCSI
-# dep_tristate 'Qlogic ISP FC SCSI support' CONFIG_SCSI_QLOGIC_FC $CONFIG_SCSI
+  dep_tristate 'Qlogic ISP FC SCSI support' CONFIG_SCSI_QLOGIC_FC $CONFIG_SCSI
 fi
 dep_tristate 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE $CONFIG_SCSI
 if [ "$CONFIG_PCI" = "y" ]; then
diff -u --recursive --new-file v2.2.2/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile
--- v2.2.2/linux/drivers/scsi/Makefile	Mon Jan  4 15:08:17 1999
+++ linux/drivers/scsi/Makefile	Wed Feb 24 16:27:54 1999
@@ -298,6 +298,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_SCSI_INIA100),y)
+L_OBJS += a100u2w.o
+else
+  ifeq ($(CONFIG_SCSI_INIA100),m)
+  M_OBJS += a100u2w.o
+  endif
+endif
+
 ifeq ($(CONFIG_SCSI_QLOGIC_FC),y)
 L_OBJS += qlogicfc.o 
 else
@@ -576,6 +584,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_SCSI_SYM53C416),y)
+L_OBJS += sym53c416.o
+else
+  ifeq ($(CONFIG_SCSI_SYM53C416),m)
+  M_OBJS += sym53c416.o
+  endif
+endif
+
 ifeq ($(CONFIG_BLK_DEV_IDESCSI),y)
 L_OBJS += ide-scsi.o
 else
@@ -616,6 +632,9 @@
 	$(CC) $(CFLAGS) -c i91uscsi.c -o i91uscsi.o
 	$(LD) -r -o initio.o ini9100u.o i91uscsi.o
 	rm -f ini9100u.o i91uscsi.o
+
+a100u2w.o: inia100.o i60uscsi.o
+	$(LD) -r -o a100u2w.o inia100.o i60uscsi.o
 
 megaraid.o: megaraid.c
 	$(CC) $(CFLAGS) -c megaraid.c
diff -u --recursive --new-file v2.2.2/linux/drivers/scsi/README.ncr53c8xx linux/drivers/scsi/README.ncr53c8xx
--- v2.2.2/linux/drivers/scsi/README.ncr53c8xx	Fri Jan  8 22:36:09 1999
+++ linux/drivers/scsi/README.ncr53c8xx	Sun Mar  7 10:13:23 1999
@@ -4,7 +4,7 @@
 21 Rue Carnot
 95170 DEUIL LA BARRE - FRANCE
 
-22 November 1998
+14 February 1999
 ===============================================================================
 
 1.  Introduction
@@ -39,6 +39,7 @@
       14.2 Device names change when another controller is added
       14.3 Using only 8 bit devices with a WIDE SCSI controller.
       14.4 Possible data corruption during a Memory Write and Invalidate
+      14.5 IRQ sharing problems
 15. SCSI problem troubleshooting
 16. Synchonous transfer negotiation tables
       16.1 Synchronous timings for 53C875 and 53C860 Ultra-SCSI controllers
@@ -669,6 +670,10 @@
     irqm:0	always open drain
     irqm:1	same as initial settings (assumed BIOS settings)
     irqm:2	always totem pole
+    irqm:0x10	driver will not use SA_SHIRQ flag when requesting irq
+    irqm:0x20	driver will not use SA_INTERRUPT flag when requesting irq
+
+    (Bits 0x10 and 0x20 can be combined with hardware irq mode option)
 
 Reverse probe
     revprob:n   probe chip ids from the PCI configuration in this order:
@@ -1027,7 +1032,25 @@
 may only be needed under Linux when a scatter/gather list is not used and 
 when the SCSI DATA IN phase is reentered after a phase mismatch.
 
- 
+14.5 IRQ sharing problems
+
+When an IRQ is shared by devices that are handled by different drivers, it 
+may happen that one driver complains about the request of the IRQ having 
+failed. This may be due to one driver having requested the IRQ using the 
+SA_INTERRUPT flag but some other having requested the same IRQ without this 
+flag, or to one driver not having requested the IRQ with the SA_SHIRQ flag.
+
+By default, the ncr53c8xx driver requests IRQs with both the SA_INTERRUPT 
+and the SA_SHIRQ flag, but you can disable use of SA_INTERRUPT flags from 
+the boot command line by using the following option:
+
+                      ncr53c8xx=irqm:0x20
+
+If this does not fix the problem, then you may want to check how all other 
+drivers are requesting the IRQ and report the problem. Note that if at least 
+a single driver does not request the IRQ with the SA_SHIRQ flag (share IRQ), 
+then the request of the IRQ obviously will not succeed for all the drivers.
+
 15. SCSI problem troubleshooting
 
 Most SCSI problems are due to a non conformant SCSI bus or to buggy
diff -u --recursive --new-file v2.2.2/linux/drivers/scsi/README.st linux/drivers/scsi/README.st
--- v2.2.2/linux/drivers/scsi/README.st	Wed Sep  9 14:51:08 1998
+++ linux/drivers/scsi/README.st	Sun Mar  7 15:20:26 1999
@@ -2,7 +2,7 @@
 The driver is currently maintained by Kai M{kisara (email
 Kai.Makisara@metla.fi)
 
-Last modified: Sun Sep  6 10:03:47 1998 by makisara@home
+Last modified: Sun Jan 17 10:57:41 1999 by makisara@home
 
 
 BASICS
@@ -60,10 +60,19 @@
 alternative is to make a small script that uses mt to set the defaults
 tailored to the system.
 
-
 The driver supports fixed and variable block size (within buffer
 limits). Both the auto-rewind (minor equals device number) and
 non-rewind devices (minor is 128 + device number) are implemented.
+
+In variable block mode, the byte count in write() determines the size
+of the physical block on tape. When reading, the drive reads the next
+tape block and returns to the user the data if the read() byte count
+is at least the block size. Otherwise the data is truncated.
+
+In fixed block mode, the data transfer between the drive and the
+driver is in multiples of the block size. The write() byte count must
+be a multiple of the block size. This is not required when reading but
+may be advisable for portability.
 
 Support is provided for changing the tape partition and partitioning
 of the tape with one or two partitions. By default support for
diff -u --recursive --new-file v2.2.2/linux/drivers/scsi/atp870u.c linux/drivers/scsi/atp870u.c
--- v2.2.2/linux/drivers/scsi/atp870u.c	Tue Feb 23 15:21:33 1999
+++ linux/drivers/scsi/atp870u.c	Wed Feb 24 16:27:54 1999
@@ -1684,7 +1684,7 @@
     struct Scsi_Host * shpnt = NULL;
     int count = 0;
     static unsigned short devid[7]={0x8002,0x8010,0x8020,0x8030,0x8040,0x8050,0};
-	static struct pci_dev *pdev = NULL;
+    static struct pci_dev *pdev = NULL, *acard_pdev[3];
 
     printk("aec671x_detect: \n");
     if (!pci_present())
@@ -1729,6 +1729,7 @@
        chip_ver[2]=0;
 	   
        /* To avoid messing with the things below...  */
+       acard_pdev[2] = pdev;
        pci_device_fn[2] =  pdev->devfn;
        pci_bus[2] = pdev->bus->number;
 
@@ -1746,15 +1747,18 @@
        }
        if ( pci_device_fn[2] < pci_device_fn[0] )
        {
+	  acard_pdev[1]=acard_pdev[0];
 	  pci_bus[1]=pci_bus[0];
 	  pci_device_fn[1]=pci_device_fn[0];
 	  chip_ver[1]=chip_ver[0];
+	  acard_pdev[0]=acard_pdev[2];
 	  pci_bus[0]=pci_bus[2];
 	  pci_device_fn[0]=pci_device_fn[2];
 	  chip_ver[0]=chip_ver[2];
        }
        else if ( pci_device_fn[2] < pci_device_fn[1] )
        {
+	  acard_pdev[1]=acard_pdev[2];
 	  pci_bus[1]=pci_bus[2];
 	  pci_device_fn[1]=pci_device_fn[2];
 	  chip_ver[1]=chip_ver[2];
@@ -1774,6 +1778,7 @@
        return count;
     }
 
+    pdev = acard_pdev[h];
     pdev->devfn = pci_device_fn[h];
     pdev->bus->number = pci_bus[h];
 
diff -u --recursive --new-file v2.2.2/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c
--- v2.2.2/linux/drivers/scsi/hosts.c	Tue Jan 19 11:32:51 1999
+++ linux/drivers/scsi/hosts.c	Wed Feb 24 16:27:54 1999
@@ -223,6 +223,10 @@
 #include "NCR53c406a.h"
 #endif
 
+#ifdef CONFIG_SCSI_SYM53C416 
+#include "sym53c416.h" 
+#endif
+
 #ifdef CONFIG_SCSI_DC390T
 #include "dc390.h"
 #endif
@@ -283,6 +287,10 @@
 #include "ini9100u.h"
 #endif
 
+#ifdef CONFIG_SCSI_INIA100
+#include "inia100.h"
+#endif
+
 #ifdef CONFIG_SCSI_DEBUG
 #include "scsi_debug.h"
 #endif
@@ -452,7 +460,7 @@
 #ifdef CONFIG_SCSI_AIC7XXX
     AIC7XXX,
 #endif
-#ifdef CONFIG_FD_MCS
+#ifdef CONFIG_SCSI_FD_MCS
    FD_MCS,
 #endif
 #ifdef CONFIG_SCSI_FUTURE_DOMAIN
@@ -467,6 +475,9 @@
 #ifdef CONFIG_SCSI_NCR53C406A	/* 53C406A should come before QLOGIC */
     NCR53c406a,
 #endif
+#ifdef CONFIG_SCSI_SYM53C416 
+    SYM53C416, 
+#endif
 #ifdef CONFIG_SCSI_QLOGIC_FAS
     QLOGICFAS,
 #endif
@@ -532,6 +543,9 @@
 #endif
 #ifdef CONFIG_SCSI_INITIO
     INI9100U,
+#endif
+#ifdef CONFIG_SCSI_INIA100
+    INIA100,
 #endif
 #ifdef CONFIG_SCSI_QLOGICPTI
     QLOGICPTI,
diff -u --recursive --new-file v2.2.2/linux/drivers/scsi/i60uscsi.c linux/drivers/scsi/i60uscsi.c
--- v2.2.2/linux/drivers/scsi/i60uscsi.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/i60uscsi.c	Wed Feb 24 16:27:54 1999
@@ -0,0 +1,956 @@
+/**************************************************************************
+ * Initio A100 device driver for Linux.
+ *
+ * Copyright (c) 1994-1998 Initio Corporation
+ * 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, 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
+ * 2. Redistributions 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.
+ *
+ * Where this Software is combined with software released under the terms of 
+ * the GNU Public License ("GPL") and the terms of the GPL would require the 
+ * combined work to also be released under the terms of the GPL, the terms
+ * and conditions of this License will apply in addition to those of the
+ * GPL with the exception of any terms or conditions of this License that
+ * conflict with, or are expressly prohibited by, the GPL.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ *
+ *************************************************************************
+ *
+ * module: i60uscsi.c 
+ * DESCRIPTION:
+ * 	This is the Linux low-level SCSI driver for Initio INIA100 SCSI host
+ * adapters
+ *
+ * 07/02/98 hl	- v.91n Initial drivers.
+ * 09/14/98 hl - v1.01 Support new Kernel.
+ * 09/22/98 hl - v1.01a Support reset.
+ * 09/24/98 hl - v1.01b Fixed reset.
+ * 10/05/98 hl - v1.02 split the source code and release.
+ * 12/19/98 bv - v1.02a Use spinlocks for 2.1.95 and up
+ **************************************************************************/
+
+#ifndef CVT_LINUX_VERSION
+#define CVT_LINUX_VERSION(V,P,S)        (V * 65536 + P * 256 + S)
+#endif
+
+#include <linux/sched.h>
+#include <asm/io.h>
+#include "i60uscsi.h"
+
+
+/* ---- INTERNAL FUNCTIONS ---- */
+static UCHAR waitChipReady(ORC_HCS * hcsp);
+static UCHAR waitFWReady(ORC_HCS * hcsp);
+static UCHAR waitFWReady(ORC_HCS * hcsp);
+static UCHAR waitSCSIRSTdone(ORC_HCS * hcsp);
+static UCHAR waitHDOoff(ORC_HCS * hcsp);
+static UCHAR waitHDIset(ORC_HCS * hcsp, UCHAR * pData);
+static unsigned short get_FW_version(ORC_HCS * hcsp);
+static UCHAR set_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char value);
+static UCHAR get_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char *pDataIn);
+static int se2_rd_all(ORC_HCS * hcsp);
+static void se2_update_all(ORC_HCS * hcsp);	/* setup default pattern        */
+static void read_eeprom(ORC_HCS * hcsp);
+static UCHAR load_FW(ORC_HCS * hcsp);
+static void setup_SCBs(ORC_HCS * hcsp);
+static void initAFlag(ORC_HCS * hcsp);
+ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp);
+
+/* ---- EXTERNAL FUNCTIONS ---- */
+extern void inia100SCBPost(BYTE * pHcb, BYTE * pScb);
+
+/* ---- INTERNAL VARIABLES ---- */
+ORC_HCS orc_hcs[MAX_SUPPORTED_ADAPTERS];
+static INIA100_ADPT_STRUCT inia100_adpt[MAX_SUPPORTED_ADAPTERS];
+/* set by inia100_setup according to the command line */
+int orc_num_scb;
+
+NVRAM nvram, *nvramp = &nvram;
+static UCHAR dftNvRam[64] =
+{
+/*----------header -------------*/
+	0x01,			/* 0x00: Sub System Vendor ID 0 */
+	0x11,			/* 0x01: Sub System Vendor ID 1 */
+	0x60,			/* 0x02: Sub System ID 0        */
+	0x10,			/* 0x03: Sub System ID 1        */
+	0x00,			/* 0x04: SubClass               */
+	0x01,			/* 0x05: Vendor ID 0            */
+	0x11,			/* 0x06: Vendor ID 1            */
+	0x60,			/* 0x07: Device ID 0            */
+	0x10,			/* 0x08: Device ID 1            */
+	0x00,			/* 0x09: Reserved               */
+	0x00,			/* 0x0A: Reserved               */
+	0x01,			/* 0x0B: Revision of Data Structure     */
+				/* -- Host Adapter Structure --- */
+	0x01,			/* 0x0C: Number Of SCSI Channel */
+	0x01,			/* 0x0D: BIOS Configuration 1   */
+	0x00,			/* 0x0E: BIOS Configuration 2   */
+	0x00,			/* 0x0F: BIOS Configuration 3   */
+				/* --- SCSI Channel 0 Configuration --- */
+	0x07,			/* 0x10: H/A ID                 */
+	0x83,			/* 0x11: Channel Configuration  */
+	0x20,			/* 0x12: MAX TAG per target     */
+	0x0A,			/* 0x13: SCSI Reset Recovering time     */
+	0x00,			/* 0x14: Channel Configuration4 */
+	0x00,			/* 0x15: Channel Configuration5 */
+				/* SCSI Channel 0 Target Configuration  */
+				/* 0x16-0x25                    */
+	0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
+	0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
+				/* --- SCSI Channel 1 Configuration --- */
+	0x07,			/* 0x26: H/A ID                 */
+	0x83,			/* 0x27: Channel Configuration  */
+	0x20,			/* 0x28: MAX TAG per target     */
+	0x0A,			/* 0x29: SCSI Reset Recovering time     */
+	0x00,			/* 0x2A: Channel Configuration4 */
+	0x00,			/* 0x2B: Channel Configuration5 */
+				/* SCSI Channel 1 Target Configuration  */
+				/* 0x2C-0x3B                    */
+	0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
+	0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
+	0x00,			/* 0x3C: Reserved               */
+	0x00,			/* 0x3D: Reserved               */
+	0x00,			/* 0x3E: Reserved               */
+	0x00			/* 0x3F: Checksum               */
+};
+
+
+/***************************************************************************/
+static void waitForPause(unsigned amount)
+{
+	ULONG the_time = jiffies + amount;	/* 0.01 seconds per jiffy */
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	while (time_before_eq(jiffies, the_time));
+#else
+	while (jiffies < the_time);
+#endif
+}
+
+/***************************************************************************/
+UCHAR waitChipReady(ORC_HCS * hcsp)
+{
+	int i;
+
+	for (i = 0; i < 2000; i++) {	/* Wait 1 second for report timeout     */
+		if (ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & HOSTSTOP)	/* Wait HOSTSTOP set */
+			return (TRUE);
+		waitForPause(5);	/* wait 500ms before try again  */
+	}
+	return (FALSE);
+}
+
+/***************************************************************************/
+UCHAR waitFWReady(ORC_HCS * hcsp)
+{
+	int i;
+
+	for (i = 0; i < 2000; i++) {	/* Wait 1 second for report timeout     */
+		if (ORC_RD(hcsp->HCS_Base, ORC_HSTUS) & RREADY)		/* Wait READY set */
+			return (TRUE);
+		waitForPause(5);	/* wait 500ms before try again  */
+	}
+	return (FALSE);
+}
+
+/***************************************************************************/
+UCHAR waitSCSIRSTdone(ORC_HCS * hcsp)
+{
+	int i;
+
+	for (i = 0; i < 2000; i++) {	/* Wait 1 second for report timeout     */
+		if (!(ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & SCSIRST))	/* Wait SCSIRST done */
+			return (TRUE);
+		waitForPause(5);	/* wait 500ms before try again  */
+	}
+	return (FALSE);
+}
+
+/***************************************************************************/
+UCHAR waitHDOoff(ORC_HCS * hcsp)
+{
+	int i;
+
+	for (i = 0; i < 2000; i++) {	/* Wait 1 second for report timeout     */
+		if (!(ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & HDO))		/* Wait HDO off */
+			return (TRUE);
+		waitForPause(5);	/* wait 500ms before try again  */
+	}
+	return (FALSE);
+}
+
+/***************************************************************************/
+UCHAR waitHDIset(ORC_HCS * hcsp, UCHAR * pData)
+{
+	int i;
+
+	for (i = 0; i < 2000; i++) {	/* Wait 1 second for report timeout     */
+		if ((*pData = ORC_RD(hcsp->HCS_Base, ORC_HSTUS)) & HDI)
+			return (TRUE);	/* Wait HDI set */
+		waitForPause(5);	/* wait 500ms before try again  */
+	}
+	return (FALSE);
+}
+
+/***************************************************************************/
+unsigned short get_FW_version(ORC_HCS * hcsp)
+{
+	UCHAR bData;
+	union {
+		unsigned short sVersion;
+		unsigned char cVersion[2];
+	} Version;
+
+	ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_VERSION);
+	ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
+	if (waitHDOoff(hcsp) == FALSE)	/* Wait HDO off   */
+		return (FALSE);
+
+	if (waitHDIset(hcsp, &bData) == FALSE)	/* Wait HDI set   */
+		return (FALSE);
+	Version.cVersion[0] = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
+	ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData);	/* Clear HDI            */
+
+	if (waitHDIset(hcsp, &bData) == FALSE)	/* Wait HDI set   */
+		return (FALSE);
+	Version.cVersion[1] = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
+	ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData);	/* Clear HDI            */
+
+	return (Version.sVersion);
+}
+
+/***************************************************************************/
+UCHAR set_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char value)
+{
+	ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_SET_NVM);	/* Write command */
+	ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
+	if (waitHDOoff(hcsp) == FALSE)	/* Wait HDO off   */
+		return (FALSE);
+
+	ORC_WR(hcsp->HCS_Base + ORC_HDATA, address);	/* Write address */
+	ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
+	if (waitHDOoff(hcsp) == FALSE)	/* Wait HDO off   */
+		return (FALSE);
+
+	ORC_WR(hcsp->HCS_Base + ORC_HDATA, value);	/* Write value  */
+	ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
+	if (waitHDOoff(hcsp) == FALSE)	/* Wait HDO off   */
+		return (FALSE);
+
+	return (TRUE);
+}
+
+/***************************************************************************/
+UCHAR get_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char *pDataIn)
+{
+	unsigned char bData;
+
+	ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_GET_NVM);	/* Write command */
+	ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
+	if (waitHDOoff(hcsp) == FALSE)	/* Wait HDO off   */
+		return (FALSE);
+
+	ORC_WR(hcsp->HCS_Base + ORC_HDATA, address);	/* Write address */
+	ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
+	if (waitHDOoff(hcsp) == FALSE)	/* Wait HDO off   */
+		return (FALSE);
+
+	if (waitHDIset(hcsp, &bData) == FALSE)	/* Wait HDI set   */
+		return (FALSE);
+	*pDataIn = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
+	ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData);	/* Clear HDI    */
+
+	return (TRUE);
+}
+
+/***************************************************************************/
+void orc_exec_scb(ORC_HCS * hcsp, ORC_SCB * scbp)
+{
+	scbp->SCB_Status = SCB_POST;
+	ORC_WR(hcsp->HCS_Base + ORC_PQUEUE, scbp->SCB_ScbIdx);
+	return;
+}
+
+
+/***********************************************************************
+ Read SCSI H/A configuration parameters from serial EEPROM
+************************************************************************/
+int se2_rd_all(ORC_HCS * hcsp)
+{
+	int i;
+	UCHAR *np, chksum = 0;
+
+	np = (UCHAR *) nvramp;
+	for (i = 0; i < 64; i++, np++) {	/* <01> */
+		if (get_NVRAM(hcsp, (unsigned char) i, np) == FALSE)
+			return -1;
+//      *np++ = get_NVRAM(hcsp, (unsigned char ) i);
+	}
+
+/*------ Is ckecksum ok ? ------*/
+	np = (UCHAR *) nvramp;
+	for (i = 0; i < 63; i++)
+		chksum += *np++;
+
+	if (nvramp->CheckSum != (UCHAR) chksum)
+		return -1;
+	return 1;
+}
+
+/************************************************************************
+ Update SCSI H/A configuration parameters from serial EEPROM
+*************************************************************************/
+void se2_update_all(ORC_HCS * hcsp)
+{				/* setup default pattern  */
+	int i;
+	UCHAR *np, *np1, chksum = 0;
+
+	/* Calculate checksum first   */
+	np = (UCHAR *) dftNvRam;
+	for (i = 0; i < 63; i++)
+		chksum += *np++;
+	*np = chksum;
+
+	np = (UCHAR *) dftNvRam;
+	np1 = (UCHAR *) nvramp;
+	for (i = 0; i < 64; i++, np++, np1++) {
+		if (*np != *np1) {
+			set_NVRAM(hcsp, (unsigned char) i, *np);
+		}
+	}
+	return;
+}
+
+/*************************************************************************
+ Function name  : read_eeprom
+**************************************************************************/
+void read_eeprom(ORC_HCS * hcsp)
+{
+	if (se2_rd_all(hcsp) != 1) {
+		se2_update_all(hcsp);	/* setup default pattern        */
+		se2_rd_all(hcsp);	/* load again                   */
+	}
+}
+
+
+/***************************************************************************/
+UCHAR load_FW(ORC_HCS * hcsp)
+{
+	U32 dData;
+	USHORT wBIOSAddress;
+	USHORT i;
+	UCHAR *pData, bData;
+
+
+	bData = ORC_RD(hcsp->HCS_Base, ORC_GCFG);
+	ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData | EEPRG);	/* Enable EEPROM programming */
+	ORC_WR(hcsp->HCS_Base + ORC_EBIOSADR2, 0x00);
+	ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x00);
+	if (ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA) != 0x55) {
+		ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData);	/* Disable EEPROM programming */
+		return (FALSE);
+	}
+	ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x01);
+	if (ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA) != 0xAA) {
+		ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData);	/* Disable EEPROM programming */
+		return (FALSE);
+	}
+	ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST | DOWNLOAD);	/* Enable SRAM programming */
+	pData = (UCHAR *) & dData;
+	dData = 0;		/* Initial FW address to 0 */
+	ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x10);
+	*pData = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);		/* Read from BIOS */
+	ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x11);
+	*(pData + 1) = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);	/* Read from BIOS */
+	ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x12);
+	*(pData + 2) = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);	/* Read from BIOS */
+	ORC_WR(hcsp->HCS_Base + ORC_EBIOSADR2, *(pData + 2));
+	ORC_WRLONG(hcsp->HCS_Base + ORC_FWBASEADR, dData);	/* Write FW address */
+
+	wBIOSAddress = (USHORT) dData;	/* FW code locate at BIOS address + ? */
+	for (i = 0, pData = (UCHAR *) & dData;	/* Download the code    */
+	     i < 0x1000;	/* Firmware code size = 4K      */
+	     i++, wBIOSAddress++) {
+		ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, wBIOSAddress);
+		*pData++ = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);	/* Read from BIOS */
+		if ((i % 4) == 3) {
+			ORC_WRLONG(hcsp->HCS_Base + ORC_RISCRAM, dData);	/* Write every 4 bytes */
+			pData = (UCHAR *) & dData;
+		}
+	}
+
+	ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST | DOWNLOAD);	/* Reset program count 0 */
+	wBIOSAddress -= 0x1000;	/* Reset the BIOS adddress      */
+	for (i = 0, pData = (UCHAR *) & dData;	/* Check the code       */
+	     i < 0x1000;	/* Firmware code size = 4K      */
+	     i++, wBIOSAddress++) {
+		ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, wBIOSAddress);
+		*pData++ = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);	/* Read from BIOS */
+		if ((i % 4) == 3) {
+			if (ORC_RDLONG(hcsp->HCS_Base, ORC_RISCRAM) != dData) {
+				ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST);	/* Reset program to 0 */
+				ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData);	/*Disable EEPROM programming */
+				return (FALSE);
+			}
+			pData = (UCHAR *) & dData;
+		}
+	}
+	ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST);	/* Reset program to 0   */
+	ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData);	/* Disable EEPROM programming */
+	return (TRUE);
+}
+
+/***************************************************************************/
+void setup_SCBs(ORC_HCS * hcsp)
+{
+	ORC_SCB *pVirScb;
+	int i;
+	UCHAR j;
+	ESCB *pVirEscb;
+	PVOID pPhysEscb;
+	PVOID tPhysEscb;
+
+	j = 0;
+	pVirScb = NULL;
+	tPhysEscb = (PVOID) NULL;
+	pPhysEscb = (PVOID) NULL;
+	/* Setup SCB HCS_Base and SCB Size registers */
+	ORC_WR(hcsp->HCS_Base + ORC_SCBSIZE, orc_num_scb);	/* Total number of SCBs */
+	/* SCB HCS_Base address 0      */
+	ORC_WRLONG(hcsp->HCS_Base + ORC_SCBBASE0, hcsp->HCS_physScbArray);
+	/* SCB HCS_Base address 1      */
+	ORC_WRLONG(hcsp->HCS_Base + ORC_SCBBASE1, hcsp->HCS_physScbArray);
+
+	/* setup scatter list address with one buffer */
+	pVirScb = (ORC_SCB *) hcsp->HCS_virScbArray;
+	pVirEscb = (ESCB *) hcsp->HCS_virEscbArray;
+
+	for (i = 0; i < orc_num_scb; i++) {
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+		pPhysEscb = (PVOID) ((ULONG) hcsp->HCS_virEscbArray + (sizeof(ESCB) * i));
+		pVirScb->SCB_SGPAddr = (U32) VIRT_TO_BUS(pPhysEscb);
+		pVirScb->SCB_SensePAddr = (U32) VIRT_TO_BUS(pPhysEscb);
+#else
+		pPhysEscb = (PVOID) (hcsp->HCS_physEscbArray + (sizeof(ESCB) * i));
+		pVirScb->SCB_SGPAddr = (U32) pPhysEscb;
+		pVirScb->SCB_SensePAddr = (U32) pPhysEscb;
+#endif
+		pVirScb->SCB_EScb = pVirEscb;
+		pVirScb->SCB_ScbIdx = i;
+		pVirScb++;
+		pVirEscb++;
+	}
+
+	return;
+}
+
+/***************************************************************************/
+static void initAFlag(ORC_HCS * hcsp)
+{
+	UCHAR i, j;
+
+	for (i = 0; i < MAX_CHANNELS; i++) {
+		for (j = 0; j < 8; j++) {
+			hcsp->BitAllocFlag[i][j] = 0xffffffff;
+		}
+	}
+}
+
+/***************************************************************************/
+int init_orchid(ORC_HCS * hcsp)
+{
+	UBYTE *readBytep;
+	USHORT revision;
+	UCHAR i;
+
+	initAFlag(hcsp);
+	ORC_WR(hcsp->HCS_Base + ORC_GIMSK, 0xFF);	/* Disable all interrupt        */
+	if (ORC_RD(hcsp->HCS_Base, ORC_HSTUS) & RREADY) {	/* Orchid is ready              */
+		revision = get_FW_version(hcsp);
+		if (revision == 0xFFFF) {
+			ORC_WR(hcsp->HCS_Base + ORC_HCTRL, DEVRST);	/* Reset Host Adapter   */
+			if (waitChipReady(hcsp) == FALSE)
+				return (-1);
+			load_FW(hcsp);	/* Download FW                  */
+			setup_SCBs(hcsp);	/* Setup SCB HCS_Base and SCB Size registers */
+			ORC_WR(hcsp->HCS_Base + ORC_HCTRL, 0);	/* clear HOSTSTOP       */
+			if (waitFWReady(hcsp) == FALSE)
+				return (-1);
+			/* Wait for firmware ready     */
+		} else {
+			setup_SCBs(hcsp);	/* Setup SCB HCS_Base and SCB Size registers */
+		}
+	} else {		/* Orchid is not Ready          */
+		ORC_WR(hcsp->HCS_Base + ORC_HCTRL, DEVRST);	/* Reset Host Adapter   */
+		if (waitChipReady(hcsp) == FALSE)
+			return (-1);
+		load_FW(hcsp);	/* Download FW                  */
+		setup_SCBs(hcsp);	/* Setup SCB HCS_Base and SCB Size registers */
+		ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);	/* Do Hardware Reset &  */
+
+		/*     clear HOSTSTOP  */
+		if (waitFWReady(hcsp) == FALSE)		/* Wait for firmware ready      */
+			return (-1);
+	}
+
+/*------------- get serial EEProm settting -------*/
+
+	read_eeprom(hcsp);
+
+	if (nvramp->Revision != 1)
+		return (-1);
+
+	hcsp->HCS_SCSI_ID = nvramp->SCSI0Id;
+	hcsp->HCS_BIOS = nvramp->BIOSConfig1;
+	hcsp->HCS_MaxTar = MAX_TARGETS;
+	readBytep = (UCHAR *) & (nvramp->Target00Config);
+	for (i = 0; i < 16; readBytep++, i++) {
+		hcsp->TargetFlag[i] = *readBytep;
+		hcsp->MaximumTags[i] = orc_num_scb;
+	}			/* for                          */
+
+	if (nvramp->SCSI0Config & NCC_BUSRESET) {	/* Reset SCSI bus               */
+		hcsp->HCS_Flags |= HCF_SCSI_RESET;
+	}
+	ORC_WR(hcsp->HCS_Base + ORC_GIMSK, 0xFB);	/* enable RP FIFO interrupt     */
+	return (0);
+}
+
+/*****************************************************************************
+ Function name  : orc_reset_scsi_bus
+ Description    : Reset registers, reset a hanging bus and
+                  kill active and disconnected commands for target w/o soft reset
+ Input          : pHCB  -       Pointer to host adapter structure
+ Output         : None.
+ Return         : pSRB  -       Pointer to SCSI request block.
+*****************************************************************************/
+int orc_reset_scsi_bus(ORC_HCS * pHCB)
+{				/* I need Host Control Block Information */
+	ULONG flags;
+
+#if 0
+	printk("inia100: enter inia100_reset\n");
+#endif
+
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+	save_flags(flags);
+	cli();
+#else
+	spin_lock_irqsave(&(pHCB->BitAllocFlagLock), flags);
+#endif
+
+	initAFlag(pHCB);
+	/* reset scsi bus */
+	ORC_WR(pHCB->HCS_Base + ORC_HCTRL, SCSIRST);
+	if (waitSCSIRSTdone(pHCB) == FALSE) {
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+		restore_flags(flags);
+#else
+		spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
+#endif
+		return (SCSI_RESET_ERROR);
+	} else {
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+		restore_flags(flags);
+#else
+		spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
+#endif
+		return (SCSI_RESET_SUCCESS);
+	}
+}
+
+/*****************************************************************************
+ Function name  : orc_device_reset
+ Description    : Reset registers, reset a hanging bus and
+                  kill active and disconnected commands for target w/o soft reset
+ Input          : pHCB  -       Pointer to host adapter structure
+ Output         : None.
+ Return         : pSRB  -       Pointer to SCSI request block.
+*****************************************************************************/
+int orc_device_reset(ORC_HCS * pHCB, ULONG SCpnt, unsigned int target, unsigned int ResetFlags)
+{				/* I need Host Control Block Information */
+	ORC_SCB *pScb;
+	ESCB *pVirEscb;
+	ORC_SCB *pVirScb;
+	UCHAR i;
+	ULONG flags;
+
+#if 0
+	printk("inia100: enter inia100_reset\n");
+#endif
+
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+	save_flags(flags);
+	cli();
+#else
+	spin_lock_irqsave(&(pHCB->BitAllocFlagLock), flags);
+#endif
+	pScb = (ORC_SCB *) NULL;
+	pVirEscb = (ESCB *) NULL;
+
+	/* setup scatter list address with one buffer */
+	pVirScb = (ORC_SCB *) pHCB->HCS_virScbArray;
+
+	initAFlag(pHCB);
+	/* device reset */
+	for (i = 0; i < orc_num_scb; i++) {
+		pVirEscb = pVirScb->SCB_EScb;
+		if ((pVirScb->SCB_Status) && (pVirEscb->SCB_Srb == (unsigned char *) SCpnt))
+			break;
+		pVirScb++;
+	}
+
+	if (i == orc_num_scb) {
+		printk("Unable to Reset - No SCB Found\n");
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+		restore_flags(flags);
+#else
+		spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
+#endif
+		return (SCSI_RESET_NOT_RUNNING);
+	}
+	if ((pScb = orc_alloc_scb(pHCB)) == NULL) {
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+		restore_flags(flags);
+#else
+		spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
+#endif
+		return (SCSI_RESET_NOT_RUNNING);
+	}
+	pScb->SCB_Opcode = ORC_BUSDEVRST;
+	pScb->SCB_Target = target;
+	pScb->SCB_HaStat = 0;
+	pScb->SCB_TaStat = 0;
+	pScb->SCB_Status = 0x0;
+	pScb->SCB_Link = 0xFF;
+	pScb->SCB_Reserved0 = 0;
+	pScb->SCB_Reserved1 = 0;
+	pScb->SCB_XferLen = 0;
+	pScb->SCB_SGLen = 0;
+
+	pVirEscb->SCB_Srb = 0;
+	if (ResetFlags & SCSI_RESET_SYNCHRONOUS) {
+		pVirEscb->SCB_Srb = (unsigned char *) SCpnt;
+	}
+	orc_exec_scb(pHCB, pScb);	/* Start execute SCB            */
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+	restore_flags(flags);
+#else
+	spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
+#endif
+	return SCSI_RESET_PENDING;
+}
+
+
+/***************************************************************************/
+ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp)
+{
+	ORC_SCB *pTmpScb;
+	UCHAR Ch;
+	ULONG idx;
+	UCHAR index;
+	UCHAR i;
+	ULONG flags;
+
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+	save_flags(flags);
+	cli();
+#else
+	spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags);
+#endif
+	Ch = hcsp->HCS_Index;
+	for (i = 0; i < 8; i++) {
+		for (index = 0; index < 32; index++) {
+			if ((hcsp->BitAllocFlag[Ch][i] >> index) & 0x01) {
+				hcsp->BitAllocFlag[Ch][i] &= ~(1 << index);
+				break;
+			}
+		}
+		idx = index + 32 * i;
+		pTmpScb = (PVOID) ((ULONG) hcsp->HCS_virScbArray + (idx * sizeof(ORC_SCB)));
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+		restore_flags(flags);
+#else
+		spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
+#endif
+		return (pTmpScb);
+	}
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+	restore_flags(flags);
+#else
+	spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
+#endif
+	return (NULL);
+}
+
+
+/***************************************************************************/
+void orc_release_scb(ORC_HCS * hcsp, ORC_SCB * scbp)
+{
+	ULONG flags;
+	UCHAR Index;
+	UCHAR i;
+	UCHAR Ch;
+
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+	save_flags(flags);
+	cli();
+#else
+	spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags);
+#endif
+	Ch = hcsp->HCS_Index;
+	Index = scbp->SCB_ScbIdx;
+	i = Index / 32;
+	Index %= 32;
+	hcsp->BitAllocFlag[Ch][i] |= (1 << Index);
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+	restore_flags(flags);
+#else
+	spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
+#endif
+}
+
+
+/*****************************************************************************
+ Function name	: Addinia100_into_Adapter_table
+ Description	: This function will scan PCI bus to get all Orchid card
+ Input		: None.
+ Output		: None.
+ Return		: SUCCESSFUL	- Successful scan
+ ohterwise	- No drives founded
+*****************************************************************************/
+int Addinia100_into_Adapter_table(WORD wBIOS, WORD wBASE, BYTE bInterrupt,
+				  BYTE bBus, BYTE bDevice)
+{
+	unsigned int i, j;
+
+	for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) {
+		if (inia100_adpt[i].ADPT_BIOS < wBIOS)
+			continue;
+		if (inia100_adpt[i].ADPT_BIOS == wBIOS) {
+			if (inia100_adpt[i].ADPT_BASE == wBASE)
+				if (inia100_adpt[i].ADPT_Bus != 0xFF)
+					return (FAILURE);
+				else if (inia100_adpt[i].ADPT_BASE < wBASE)
+					continue;
+		}
+		for (j = MAX_SUPPORTED_ADAPTERS - 1; j > i; j--) {
+			inia100_adpt[j].ADPT_BASE = inia100_adpt[j - 1].ADPT_BASE;
+			inia100_adpt[j].ADPT_INTR = inia100_adpt[j - 1].ADPT_INTR;
+			inia100_adpt[j].ADPT_BIOS = inia100_adpt[j - 1].ADPT_BIOS;
+			inia100_adpt[j].ADPT_Bus = inia100_adpt[j - 1].ADPT_Bus;
+			inia100_adpt[j].ADPT_Device = inia100_adpt[j - 1].ADPT_Device;
+		}
+		inia100_adpt[i].ADPT_BASE = wBASE;
+		inia100_adpt[i].ADPT_INTR = bInterrupt;
+		inia100_adpt[i].ADPT_BIOS = wBIOS;
+		inia100_adpt[i].ADPT_Bus = bBus;
+		inia100_adpt[i].ADPT_Device = bDevice;
+		return (SUCCESSFUL);
+	}
+	return (FAILURE);
+}
+
+
+/*****************************************************************************
+ Function name	: init_inia100Adapter_table
+ Description	: This function will scan PCI bus to get all Orchid card
+ Input		: None.
+ Output		: None.
+ Return		: SUCCESSFUL	- Successful scan
+ ohterwise	- No drives founded
+*****************************************************************************/
+void init_inia100Adapter_table(void)
+{
+	int i;
+
+	for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) {	/* Initialize adapter structure */
+		inia100_adpt[i].ADPT_BIOS = 0xffff;
+		inia100_adpt[i].ADPT_BASE = 0xffff;
+		inia100_adpt[i].ADPT_INTR = 0xff;
+		inia100_adpt[i].ADPT_Bus = 0xff;
+		inia100_adpt[i].ADPT_Device = 0xff;
+	}
+}
+
+/*****************************************************************************
+ Function name  : get_orcPCIConfig
+ Description    : 
+ Input          : pHCB  -       Pointer to host adapter structure
+ Output         : None.
+ Return         : pSRB  -       Pointer to SCSI request block.
+*****************************************************************************/
+void get_orcPCIConfig(ORC_HCS * pCurHcb, int ch_idx)
+{
+	pCurHcb->HCS_Base = inia100_adpt[ch_idx].ADPT_BASE;	/* Supply base address  */
+	pCurHcb->HCS_BIOS = inia100_adpt[ch_idx].ADPT_BIOS;	/* Supply BIOS address  */
+	pCurHcb->HCS_Intr = inia100_adpt[ch_idx].ADPT_INTR;	/* Supply interrupt line */
+	return;
+}
+
+
+/*****************************************************************************
+ Function name  : abort_SCB
+ Description    : Abort a queued command.
+	                 (commands that are on the bus can't be aborted easily)
+ Input          : pHCB  -       Pointer to host adapter structure
+ Output         : None.
+ Return         : pSRB  -       Pointer to SCSI request block.
+*****************************************************************************/
+int abort_SCB(ORC_HCS * hcsp, ORC_SCB * pScb)
+{
+	unsigned char bData, bStatus;
+
+	ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_ABORT_SCB);	/* Write command */
+	ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
+	if (waitHDOoff(hcsp) == FALSE)	/* Wait HDO off   */
+		return (FALSE);
+
+	ORC_WR(hcsp->HCS_Base + ORC_HDATA, pScb->SCB_ScbIdx);	/* Write address */
+	ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
+	if (waitHDOoff(hcsp) == FALSE)	/* Wait HDO off   */
+		return (FALSE);
+
+	if (waitHDIset(hcsp, &bData) == FALSE)	/* Wait HDI set   */
+		return (FALSE);
+	bStatus = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
+	ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData);	/* Clear HDI    */
+
+	if (bStatus == 1)	/* 0 - Successfully               */
+		return (FALSE);	/* 1 - Fail                     */
+	return (TRUE);
+}
+
+/*****************************************************************************
+ Function name  : inia100_abort
+ Description    : Abort a queued command.
+	                 (commands that are on the bus can't be aborted easily)
+ Input          : pHCB  -       Pointer to host adapter structure
+ Output         : None.
+ Return         : pSRB  -       Pointer to SCSI request block.
+*****************************************************************************/
+int orc_abort_srb(ORC_HCS * hcsp, ULONG SCpnt)
+{
+	ESCB *pVirEscb;
+	ORC_SCB *pVirScb;
+	UCHAR i;
+	ULONG flags;
+
+#if 0
+	printk("inia100: abort SRB \n");
+#endif
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+	save_flags(flags);
+	cli();
+#else
+	spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags);
+#endif
+
+	pVirScb = (ORC_SCB *) hcsp->HCS_virScbArray;
+
+	for (i = 0; i < orc_num_scb; i++, pVirScb++) {
+		pVirEscb = pVirScb->SCB_EScb;
+		if ((pVirScb->SCB_Status) && (pVirEscb->SCB_Srb == (unsigned char *) SCpnt)) {
+			if (pVirScb->SCB_TagMsg == 0) {
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+				restore_flags(flags);
+#else
+				spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
+#endif
+				return (SCSI_ABORT_BUSY);
+			} else {
+				if (abort_SCB(hcsp, pVirScb)) {
+					pVirEscb->SCB_Srb = NULL;
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+					restore_flags(flags);
+#else
+					spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
+#endif
+					return (SCSI_ABORT_SUCCESS);
+				} else {
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+					restore_flags(flags);
+#else
+					spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
+#endif
+					return (SCSI_ABORT_NOT_RUNNING);
+				}
+			}
+		}
+	}
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+	restore_flags(flags);
+#else
+	spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
+#endif
+	return (SCSI_ABORT_NOT_RUNNING);
+}
+
+/***********************************************************************
+ Routine Description:
+	  This is the interrupt service routine for the Orchid SCSI adapter.
+	  It reads the interrupt register to determine if the adapter is indeed
+	  the source of the interrupt and clears the interrupt at the device.
+ Arguments:
+	  HwDeviceExtension - HBA miniport driver's adapter data storage
+ Return Value:
+***********************************************************************/
+void orc_interrupt(
+			  ORC_HCS * hcsp
+)
+{
+	BYTE bScbIdx;
+	ORC_SCB *pScb;
+
+	if (ORC_RD(hcsp->HCS_Base, ORC_RQUEUECNT) == 0) {
+		return;		// (FALSE);
+
+	}
+	do {
+		bScbIdx = ORC_RD(hcsp->HCS_Base, ORC_RQUEUE);
+
+		pScb = (ORC_SCB *) ((ULONG) hcsp->HCS_virScbArray + (ULONG) (sizeof(ORC_SCB) * bScbIdx));
+		pScb->SCB_Status = 0x0;
+
+		inia100SCBPost((BYTE *) hcsp, (BYTE *) pScb);
+	} while (ORC_RD(hcsp->HCS_Base, ORC_RQUEUECNT));
+	return;			//(TRUE);
+
+}				/* End of I1060Interrupt() */
diff -u --recursive --new-file v2.2.2/linux/drivers/scsi/i60uscsi.h linux/drivers/scsi/i60uscsi.h
--- v2.2.2/linux/drivers/scsi/i60uscsi.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/i60uscsi.h	Wed Feb 24 16:27:54 1999
@@ -0,0 +1,574 @@
+/**************************************************************************
+ * Initio A100 device driver for Linux.
+ *
+ * Copyright (c) 1994-1998 Initio Corporation
+ * 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, 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
+ * 2. Redistributions 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.
+ *
+ * Where this Software is combined with software released under the terms of 
+ * the GNU Public License ("GPL") and the terms of the GPL would require the 
+ * combined work to also be released under the terms of the GPL, the terms
+ * and conditions of this License will apply in addition to those of the
+ * GPL with the exception of any terms or conditions of this License that
+ * conflict with, or are expressly prohibited by, the GPL.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ *
+ **************************************************************************
+ *
+ * Module: inia100.h
+ * Description: INI-A100U2W LINUX device driver header
+ * Revision History:
+ *	06/18/98 HL, Initial Version 1.02
+ *	12/19/98 bv, v1.02a Use spinlocks for 2.1.95 and up.
+ **************************************************************************/
+
+#include <linux/config.h>
+
+#define ULONG   unsigned long
+#define PVOID   void *
+#define USHORT  unsigned short
+#define UCHAR   unsigned char
+#define BYTE    unsigned char
+#define WORD    unsigned short
+#define DWORD   unsigned long
+#define UBYTE   unsigned char
+#define UWORD   unsigned short
+#define UDWORD  unsigned long
+#ifdef ALPHA
+#define U32     unsigned int
+#else
+#define U32     unsigned long
+#endif
+
+#ifndef NULL
+#define NULL     0		/* zero          */
+#endif
+#ifndef TRUE
+#define TRUE     (1)		/* boolean true  */
+#endif
+#ifndef FALSE
+#define FALSE    (0)		/* boolean false */
+#endif
+#ifndef FAILURE
+#define FAILURE  (-1)
+#endif
+#if 1
+#define ORC_MAXQUEUE		245
+#else
+#define ORC_MAXQUEUE		25
+#endif
+
+#define TOTAL_SG_ENTRY		32
+#define MAX_TARGETS		16
+#define IMAX_CDB			15
+#define SENSE_SIZE		14
+#define MAX_SUPPORTED_ADAPTERS  4
+#define SUCCESSFUL              0x00
+
+#define I920_DEVICE_ID	0x0002	/* Initio's inic-950 product ID   */
+
+/************************************************************************/
+/*              Scatter-Gather Element Structure                        */
+/************************************************************************/
+typedef struct ORC_SG_Struc {
+	U32 SG_Ptr;		/* Data Pointer */
+	U32 SG_Len;		/* Data Length */
+} ORC_SG;
+
+typedef struct inia100_Adpt_Struc {
+	UWORD ADPT_BIOS;	/* 0 */
+	UWORD ADPT_BASE;	/* 1 */
+	UBYTE ADPT_Bus;		/* 2 */
+	UBYTE ADPT_Device;	/* 3 */
+	UBYTE ADPT_INTR;	/* 4 */
+} INIA100_ADPT_STRUCT;
+
+
+/* SCSI related definition                                              */
+#define DISC_NOT_ALLOW          0x80	/* Disconnect is not allowed    */
+#define DISC_ALLOW              0xC0	/* Disconnect is allowed        */
+
+
+#define ORC_OFFSET_SCB			16
+#define ORC_MAX_SCBS		    250
+#define MAX_CHANNELS       2
+#define MAX_ESCB_ELE				64
+#define TCF_DRV_255_63     0x0400
+
+/********************************************************/
+/*      Orchid Configuration Register Set               */
+/********************************************************/
+#define ORC_PVID	0x00	/* Vendor ID                      */
+#define ORC_VENDOR_ID	0x1101	/* Orchid vendor ID               */
+#define ORC_PDID        0x02	/* Device ID                    */
+#define ORC_DEVICE_ID	0x1060	/* Orchid device ID               */
+#define ORC_COMMAND	0x04	/* Command                        */
+#define BUSMS		0x04	/* BUS MASTER Enable              */
+#define IOSPA		0x01	/* IO Space Enable                */
+#define ORC_STATUS	0x06	/* Status register                */
+#define ORC_REVISION	0x08	/* Revision number                */
+#define ORC_BASE	0x10	/* Base address                   */
+#define ORC_BIOS	0x50	/* Expansion ROM base address     */
+#define ORC_INT_NUM	0x3C	/* Interrupt line         */
+#define ORC_INT_PIN	0x3D	/* Interrupt pin          */
+
+
+/********************************************************/
+/*      Orchid Host Command Set                         */
+/********************************************************/
+#define ORC_CMD_NOP		0x00	/* Host command - NOP             */
+#define ORC_CMD_VERSION		0x01	/* Host command - Get F/W version */
+#define ORC_CMD_ECHO		0x02	/* Host command - ECHO            */
+#define ORC_CMD_SET_NVM		0x03	/* Host command - Set NVRAM       */
+#define ORC_CMD_GET_NVM		0x04	/* Host command - Get NVRAM       */
+#define ORC_CMD_GET_BUS_STATUS	0x05	/* Host command - Get SCSI bus status */
+#define ORC_CMD_ABORT_SCB	0x06	/* Host command - Abort SCB       */
+#define ORC_CMD_ISSUE_SCB	0x07	/* Host command - Issue SCB       */
+
+/********************************************************/
+/*              Orchid Register Set                     */
+/********************************************************/
+#define ORC_GINTS	0xA0	/* Global Interrupt Status        */
+#define QINT		0x04	/* Reply Queue Interrupt  */
+#define ORC_GIMSK	0xA1	/* Global Interrupt MASK  */
+#define MQINT		0x04	/* Mask Reply Queue Interrupt     */
+#define	ORC_GCFG	0xA2	/* Global Configure               */
+#define EEPRG		0x01	/* Enable EEPROM programming */
+#define	ORC_GSTAT	0xA3	/* Global status          */
+#define WIDEBUS		0x10	/* Wide SCSI Devices connected    */
+#define ORC_HDATA	0xA4	/* Host Data                      */
+#define ORC_HCTRL	0xA5	/* Host Control                   */
+#define SCSIRST		0x80	/* SCSI bus reset         */
+#define HDO			0x40	/* Host data out          */
+#define HOSTSTOP		0x02	/* Host stop RISC engine  */
+#define DEVRST		0x01	/* Device reset                   */
+#define ORC_HSTUS	0xA6	/* Host Status                    */
+#define HDI			0x02	/* Host data in                   */
+#define RREADY		0x01	/* RISC engine is ready to receive */
+#define	ORC_NVRAM	0xA7	/* Nvram port address             */
+#define SE2CS		0x008
+#define SE2CLK		0x004
+#define SE2DO		0x002
+#define SE2DI		0x001
+#define ORC_PQUEUE	0xA8	/* Posting queue FIFO             */
+#define ORC_PQCNT	0xA9	/* Posting queue FIFO Cnt */
+#define ORC_RQUEUE	0xAA	/* Reply queue FIFO               */
+#define ORC_RQUEUECNT	0xAB	/* Reply queue FIFO Cnt           */
+#define	ORC_FWBASEADR	0xAC	/* Firmware base address  */
+
+#define	ORC_EBIOSADR0 0xB0	/* External Bios address */
+#define	ORC_EBIOSADR1 0xB1	/* External Bios address */
+#define	ORC_EBIOSADR2 0xB2	/* External Bios address */
+#define	ORC_EBIOSDATA 0xB3	/* External Bios address */
+
+#define	ORC_SCBSIZE	0xB7	/* SCB size register              */
+#define	ORC_SCBBASE0	0xB8	/* SCB base address 0             */
+#define	ORC_SCBBASE1	0xBC	/* SCB base address 1             */
+
+#define	ORC_RISCCTL	0xE0	/* RISC Control                   */
+#define PRGMRST		0x002
+#define DOWNLOAD		0x001
+#define	ORC_PRGMCTR0	0xE2	/* RISC program counter           */
+#define	ORC_PRGMCTR1	0xE3	/* RISC program counter           */
+#define	ORC_RISCRAM	0xEC	/* RISC RAM data port 4 bytes     */
+
+typedef struct orc_extended_scb {	/* Extended SCB                 */
+	ORC_SG ESCB_SGList[TOTAL_SG_ENTRY];	/*0 Start of SG list              */
+	unsigned char *SCB_Srb;	/*50 SRB Pointer */
+//         Scsi_Cmnd    *SCB_Srb;       /*50 SRB Pointer */
+} ESCB;
+
+/***********************************************************************
+		SCSI Control Block
+************************************************************************/
+typedef struct orc_scb {	/* Scsi_Ctrl_Blk                */
+	UBYTE SCB_Opcode;	/*00 SCB command code&residual  */
+	UBYTE SCB_Flags;	/*01 SCB Flags                  */
+	UBYTE SCB_Target;	/*02 Target Id                  */
+	UBYTE SCB_Lun;		/*03 Lun                        */
+	U32 SCB_Reserved0;	/*04 Reserved for ORCHID must 0 */
+	U32 SCB_XferLen;	/*08 Data Transfer Length       */
+	U32 SCB_Reserved1;	/*0C Reserved for ORCHID must 0 */
+	U32 SCB_SGLen;		/*10 SG list # * 8              */
+	U32 SCB_SGPAddr;	/*14 SG List Buf physical Addr  */
+	U32 SCB_SGPAddrHigh;	/*18 SG Buffer high physical Addr */
+	UBYTE SCB_HaStat;	/*1C Host Status                */
+	UBYTE SCB_TaStat;	/*1D Target Status              */
+	UBYTE SCB_Status;	/*1E SCB status                 */
+	UBYTE SCB_Link;		/*1F Link pointer, default 0xFF */
+	UBYTE SCB_SenseLen;	/*20 Sense Allocation Length    */
+	UBYTE SCB_CDBLen;	/*21 CDB Length                 */
+	UBYTE SCB_Ident;	/*22 Identify                   */
+	UBYTE SCB_TagMsg;	/*23 Tag Message                */
+	UBYTE SCB_CDB[IMAX_CDB];	/*24 SCSI CDBs                  */
+	UBYTE SCB_ScbIdx;	/*3C Index for this ORCSCB      */
+	U32 SCB_SensePAddr;	/*34 Sense Buffer physical Addr */
+
+	ESCB *SCB_EScb;		/*38 Extended SCB Pointer       */
+#ifndef ALPHA
+	UBYTE SCB_Reserved2[4];	/*3E Reserved for Driver use    */
+#endif
+} ORC_SCB;
+
+/* Opcodes of ORCSCB_Opcode */
+#define ORC_EXECSCSI	0x00	/* SCSI initiator command with residual */
+#define ORC_BUSDEVRST	0x01	/* SCSI Bus Device Reset  */
+
+/* Status of ORCSCB_Status */
+#define SCB_COMPLETE	0x00	/* SCB request completed  */
+#define SCB_POST	0x01	/* SCB is posted by the HOST      */
+
+/* Bit Definition for ORCSCB_Flags */
+#define SCF_DISINT	0x01	/* Disable HOST interrupt */
+#define SCF_DIR		0x18	/* Direction bits         */
+#define SCF_NO_DCHK	0x00	/* Direction determined by SCSI   */
+#define SCF_DIN		0x08	/* From Target to Initiator       */
+#define SCF_DOUT	0x10	/* From Initiator to Target       */
+#define SCF_NO_XF	0x18	/* No data transfer               */
+#define SCF_POLL   0x40
+
+/* Error Codes for ORCSCB_HaStat */
+#define HOST_SEL_TOUT	0x11
+#define HOST_DO_DU	0x12
+#define HOST_BUS_FREE	0x13
+#define HOST_BAD_PHAS	0x14
+#define HOST_INV_CMD	0x16
+#define HOST_SCSI_RST	0x1B
+#define HOST_DEV_RST	0x1C
+
+
+/* Error Codes for ORCSCB_TaStat */
+#define TARGET_CHK_COND	0x02
+#define TARGET_BUSY	0x08
+#define TARGET_TAG_FULL	0x28
+
+
+/* Queue tag msg: Simple_quque_tag, Head_of_queue_tag, Ordered_queue_tag */
+#define MSG_STAG	0x20
+#define MSG_HTAG	0x21
+#define MSG_OTAG	0x22
+
+#define MSG_IGNOREWIDE	0x23
+
+#define MSG_IDENT	0x80
+#define MSG_DISC	0x40	/* Disconnect allowed             */
+
+
+/* SCSI MESSAGE */
+#define	MSG_EXTEND	0x01
+#define	MSG_SDP		0x02
+#define	MSG_ABORT	0x06
+#define	MSG_REJ		0x07
+#define	MSG_NOP		0x08
+#define	MSG_PARITY	0x09
+#define	MSG_DEVRST	0x0C
+#define	MSG_STAG	0x20
+
+/***********************************************************************
+		Target Device Control Structure
+**********************************************************************/
+
+typedef struct ORC_Tar_Ctrl_Struc {
+	UBYTE TCS_DrvDASD;	/* 6 */
+	UBYTE TCS_DrvSCSI;	/* 7 */
+	UBYTE TCS_DrvHead;	/* 8 */
+	UWORD TCS_DrvFlags;	/* 4 */
+	UBYTE TCS_DrvSector;	/* 7 */
+} ORC_TCS, *PORC_TCS;
+
+/* Bit Definition for TCF_DrvFlags */
+#define	TCS_DF_NODASD_SUPT	0x20	/* Suppress OS/2 DASD Mgr support */
+#define	TCS_DF_NOSCSI_SUPT	0x40	/* Suppress OS/2 SCSI Mgr support */
+
+
+/***********************************************************************
+              Host Adapter Control Structure
+************************************************************************/
+typedef struct ORC_Ha_Ctrl_Struc {
+	USHORT HCS_Base;	/* 00 */
+	UBYTE HCS_Index;	/* 02 */
+	UBYTE HCS_Intr;		/* 04 */
+	UBYTE HCS_SCSI_ID;	/* 06    H/A SCSI ID */
+	UBYTE HCS_BIOS;		/* 07    BIOS configuration */
+
+	UBYTE HCS_Flags;	/* 0B */
+	UBYTE HCS_HAConfig1;	/* 1B    SCSI0MAXTags */
+	UBYTE HCS_MaxTar;	/* 1B    SCSI0MAXTags */
+
+	USHORT HCS_Units;	/* Number of units this adapter  */
+	USHORT HCS_AFlags;	/* Adapter info. defined flags   */
+	ULONG HCS_Timeout;	/* Adapter timeout value   */
+	PVOID HCS_virScbArray;	/* 28 Virtual Pointer to SCB array     */
+	U32 HCS_physScbArray;	/* Scb Physical address */
+	PVOID HCS_virEscbArray;	/* Virtual pointer to ESCB Scatter list */
+	U32 HCS_physEscbArray;	/* scatter list Physical address */
+	UBYTE TargetFlag[16];	/* 30  target configuration, TCF_EN_TAG */
+	UBYTE MaximumTags[16];	/* 40  ORC_MAX_SCBS */
+	UBYTE ActiveTags[16][16];	/* 50 */
+	ORC_TCS HCS_Tcs[16];	/* 28 */
+	U32 BitAllocFlag[MAX_CHANNELS][8];	/* Max STB is 256, So 256/32 */
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spinlock_t BitAllocFlagLock;
+#endif
+	ULONG pSRB_head;
+	ULONG pSRB_tail;
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spinlock_t pSRB_lock;
+#endif
+} ORC_HCS;
+
+/* Bit Definition for HCS_Flags */
+
+#define HCF_SCSI_RESET	0x01	/* SCSI BUS RESET         */
+#define HCF_PARITY    	0x02	/* parity card                    */
+#define HCF_LVDS     	0x10	/* parity card                    */
+
+/* Bit Definition for TargetFlag */
+
+#define TCF_EN_255	    0x08
+#define TCF_EN_TAG	    0x10
+#define TCF_BUSY	      0x20
+#define TCF_DISCONNECT	0x40
+#define TCF_SPIN_UP	  0x80
+
+/* Bit Definition for HCS_AFlags */
+#define	HCS_AF_IGNORE		0x01	/* Adapter ignore         */
+#define	HCS_AF_DISABLE_RESET	0x10	/* Adapter disable reset  */
+#define	HCS_AF_DISABLE_ADPT	0x80	/* Adapter disable                */
+
+
+/*---------------------------------------*/
+/* TimeOut for RESET to complete (30s)   */
+/*                                       */
+/* After a RESET the drive is checked    */
+/* every 200ms.                          */
+/*---------------------------------------*/
+#define DELAYED_RESET_MAX       (30*1000L)
+#define DELAYED_RESET_INTERVAL  200L
+
+/*----------------------------------------------*/
+/* TimeOut for IRQ from last interrupt (5s)     */
+/*----------------------------------------------*/
+#define IRQ_TIMEOUT_INTERVAL    (5*1000L)
+
+/*----------------------------------------------*/
+/* Retry Delay interval (200ms)                 */
+/*----------------------------------------------*/
+#define DELAYED_RETRY_INTERVAL  200L
+
+#define	INQUIRY_SIZE		36
+#define	CAPACITY_SIZE		8
+#define	DEFAULT_SENSE_LEN	14
+
+#define	DEVICE_NOT_FOUND	0x86
+
+/*----------------------------------------------*/
+/* Definition for PCI device                    */
+/*----------------------------------------------*/
+#define	MAX_PCI_DEVICES	21
+#define	MAX_PCI_BUSES	8
+
+typedef struct Adpt_Struc {
+	USHORT ADPT_BIOS;	/* 0 */
+	UBYTE ADPT_BASE;	/* 1 */
+	UBYTE ADPT_Bus;		/* 2 */
+	UBYTE ADPT_Device;	/* 3 */
+	UBYTE ADPT_Reserved[3];
+} JACS, *PJACS;
+
+typedef struct _NVRAM {
+/*----------header ---------------*/
+	UCHAR SubVendorID0;	/* 00 - Sub Vendor ID           */
+	UCHAR SubVendorID1;	/* 00 - Sub Vendor ID           */
+	UCHAR SubSysID0;	/* 02 - Sub System ID           */
+	UCHAR SubSysID1;	/* 02 - Sub System ID           */
+	UCHAR SubClass;		/* 04 - Sub Class               */
+	UCHAR VendorID0;	/* 05 - Vendor ID               */
+	UCHAR VendorID1;	/* 05 - Vendor ID               */
+	UCHAR DeviceID0;	/* 07 - Device ID               */
+	UCHAR DeviceID1;	/* 07 - Device ID               */
+	UCHAR Reserved0[2];	/* 09 - Reserved                */
+	UCHAR Revision;		/* 0B - Revision of data structure */
+	/* ----Host Adapter Structure ---- */
+	UCHAR NumOfCh;		/* 0C - Number of SCSI channel  */
+	UCHAR BIOSConfig1;	/* 0D - BIOS configuration 1    */
+	UCHAR BIOSConfig2;	/* 0E - BIOS boot channel&target ID */
+	UCHAR BIOSConfig3;	/* 0F - BIOS configuration 3    */
+	/* ----SCSI channel Structure ---- */
+	/* from "CTRL-I SCSI Host Adapter SetUp menu "  */
+	UCHAR SCSI0Id;		/* 10 - Channel 0 SCSI ID       */
+	UCHAR SCSI0Config;	/* 11 - Channel 0 SCSI configuration */
+	UCHAR SCSI0MaxTags;	/* 12 - Channel 0 Maximum tags  */
+	UCHAR SCSI0ResetTime;	/* 13 - Channel 0 Reset recovering time */
+	UCHAR ReservedforChannel0[2];	/* 14 - Reserved                */
+
+	/* ----SCSI target Structure ----  */
+	/* from "CTRL-I SCSI device SetUp menu "                        */
+	UCHAR Target00Config;	/* 16 - Channel 0 Target 0 config */
+	UCHAR Target01Config;	/* 17 - Channel 0 Target 1 config */
+	UCHAR Target02Config;	/* 18 - Channel 0 Target 2 config */
+	UCHAR Target03Config;	/* 19 - Channel 0 Target 3 config */
+	UCHAR Target04Config;	/* 1A - Channel 0 Target 4 config */
+	UCHAR Target05Config;	/* 1B - Channel 0 Target 5 config */
+	UCHAR Target06Config;	/* 1C - Channel 0 Target 6 config */
+	UCHAR Target07Config;	/* 1D - Channel 0 Target 7 config */
+	UCHAR Target08Config;	/* 1E - Channel 0 Target 8 config */
+	UCHAR Target09Config;	/* 1F - Channel 0 Target 9 config */
+	UCHAR Target0AConfig;	/* 20 - Channel 0 Target A config */
+	UCHAR Target0BConfig;	/* 21 - Channel 0 Target B config */
+	UCHAR Target0CConfig;	/* 22 - Channel 0 Target C config */
+	UCHAR Target0DConfig;	/* 23 - Channel 0 Target D config */
+	UCHAR Target0EConfig;	/* 24 - Channel 0 Target E config */
+	UCHAR Target0FConfig;	/* 25 - Channel 0 Target F config */
+
+	UCHAR SCSI1Id;		/* 26 - Channel 1 SCSI ID       */
+	UCHAR SCSI1Config;	/* 27 - Channel 1 SCSI configuration */
+	UCHAR SCSI1MaxTags;	/* 28 - Channel 1 Maximum tags  */
+	UCHAR SCSI1ResetTime;	/* 29 - Channel 1 Reset recovering time */
+	UCHAR ReservedforChannel1[2];	/* 2A - Reserved                */
+
+	/* ----SCSI target Structure ----  */
+	/* from "CTRL-I SCSI device SetUp menu "                                          */
+	UCHAR Target10Config;	/* 2C - Channel 1 Target 0 config */
+	UCHAR Target11Config;	/* 2D - Channel 1 Target 1 config */
+	UCHAR Target12Config;	/* 2E - Channel 1 Target 2 config */
+	UCHAR Target13Config;	/* 2F - Channel 1 Target 3 config */
+	UCHAR Target14Config;	/* 30 - Channel 1 Target 4 config */
+	UCHAR Target15Config;	/* 31 - Channel 1 Target 5 config */
+	UCHAR Target16Config;	/* 32 - Channel 1 Target 6 config */
+	UCHAR Target17Config;	/* 33 - Channel 1 Target 7 config */
+	UCHAR Target18Config;	/* 34 - Channel 1 Target 8 config */
+	UCHAR Target19Config;	/* 35 - Channel 1 Target 9 config */
+	UCHAR Target1AConfig;	/* 36 - Channel 1 Target A config */
+	UCHAR Target1BConfig;	/* 37 - Channel 1 Target B config */
+	UCHAR Target1CConfig;	/* 38 - Channel 1 Target C config */
+	UCHAR Target1DConfig;	/* 39 - Channel 1 Target D config */
+	UCHAR Target1EConfig;	/* 3A - Channel 1 Target E config */
+	UCHAR Target1FConfig;	/* 3B - Channel 1 Target F config */
+	UCHAR reserved[3];	/* 3C - Reserved                */
+	/* ---------- CheckSum ----------       */
+	UCHAR CheckSum;		/* 3F - Checksum of NVRam       */
+} NVRAM, *PNVRAM;
+
+/* Bios Configuration for nvram->BIOSConfig1                            */
+#define NBC_BIOSENABLE	0x01	/* BIOS enable                    */
+#define NBC_CDROM	0x02	/* Support bootable CDROM */
+#define NBC_REMOVABLE	0x04	/* Support removable drive        */
+
+/* Bios Configuration for nvram->BIOSConfig2                            */
+#define	NBB_TARGET_MASK	0x0F	/* Boot SCSI target ID number     */
+#define	NBB_CHANL_MASK	0xF0	/* Boot SCSI channel number       */
+
+/* Bit definition for nvram->SCSIConfig                                 */
+#define NCC_BUSRESET	0x01	/* Reset SCSI bus at power up     */
+#define NCC_PARITYCHK	0x02	/* SCSI parity enable             */
+#define NCC_LVDS	0x10	/* Enable LVDS                    */
+#define NCC_ACTTERM1	0x20	/* Enable active terminator 1     */
+#define NCC_ACTTERM2	0x40	/* Enable active terminator 2     */
+#define NCC_AUTOTERM	0x80	/* Enable auto termination        */
+
+/* Bit definition for nvram->TargetxConfig                              */
+#define	NTC_PERIOD	0x07	/* Maximum Sync. Speed            */
+#define NTC_1GIGA	0x08	/* 255 head / 63 sectors (64/32) */
+#define NTC_NO_SYNC	0x10	/* NO SYNC. NEGO          */
+#define NTC_NO_WIDESYNC	0x20	/* NO WIDE SYNC. NEGO             */
+#define	NTC_DISC_ENABLE	0x40	/* Enable SCSI disconnect */
+#define NTC_SPINUP	0x80	/* Start disk drive               */
+
+/* Default NVRam values                                                 */
+#define NBC_DEFAULT	(NBC_ENABLE)
+#define NCC_DEFAULT	(NCC_BUSRESET | NCC_AUTOTERM | NCC_PARITYCHK)
+#define NCC_MAX_TAGS	0x20	/* Maximum tags per target        */
+#define	NCC_RESET_TIME	0x0A	/* SCSI RESET recovering time     */
+#define NTC_DEFAULT	(NTC_1GIGA | NTC_NO_WIDESYNC | NTC_DISC_ENABLE)
+
+typedef union {			/* Union define for mechanism 1   */
+	struct {
+		unsigned char RegNum;
+		unsigned char FcnNum:3;
+		unsigned char DeviceNum:5;
+		unsigned char BusNum;
+		unsigned char Reserved:7;
+		unsigned char Enable:1;
+	} sConfigAdr;
+	unsigned long lConfigAdr;
+} CONFIG_ADR;
+
+typedef union {			/* Union define for mechanism 2   */
+	struct {
+		unsigned char RegNum;
+		unsigned char DeviceNum;
+		unsigned short Reserved;
+	} sHostAdr;
+	unsigned long lHostAdr;
+} HOST_ADR;
+
+#define ORC_RD(x,y)             (UCHAR)(inb(  (int)((ULONG)((ULONG)x+(UCHAR)y)) ))
+#define ORC_RDLONG(x,y)         (long)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) ))
+
+#define ORC_WR(     adr,data)   outb( (UCHAR)(data), (int)(adr))
+#define ORC_WRSHORT(adr,data)   outw( (UWORD)(data), (int)(adr))
+#define ORC_WRLONG( adr,data)   outl( (ULONG)(data), (int)(adr))
+
+
+#define SCSI_ABORT_SNOOZE 0
+#define SCSI_ABORT_SUCCESS 1
+#define SCSI_ABORT_PENDING 2
+#define SCSI_ABORT_BUSY 3
+#define SCSI_ABORT_NOT_RUNNING 4
+#define SCSI_ABORT_ERROR 5
+
+#define SCSI_RESET_SNOOZE 0
+#define SCSI_RESET_PUNT 1
+#define SCSI_RESET_SUCCESS 2
+#define SCSI_RESET_PENDING 3
+#define SCSI_RESET_WAKEUP 4
+#define SCSI_RESET_NOT_RUNNING 5
+#define SCSI_RESET_ERROR 6
+
+#define SCSI_RESET_SYNCHRONOUS		0x01
+#define SCSI_RESET_ASYNCHRONOUS		0x02
+#define SCSI_RESET_SUGGEST_BUS_RESET	0x04
+#define SCSI_RESET_SUGGEST_HOST_RESET	0x08
+
+#define SCSI_RESET_BUS_RESET 0x100
+#define SCSI_RESET_HOST_RESET 0x200
+#define SCSI_RESET_ACTION   0xff
diff -u --recursive --new-file v2.2.2/linux/drivers/scsi/inia100.c linux/drivers/scsi/inia100.c
--- v2.2.2/linux/drivers/scsi/inia100.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/inia100.c	Wed Feb 24 16:27:54 1999
@@ -0,0 +1,952 @@
+/**************************************************************************
+ * Initio A100 device driver for Linux.
+ *
+ * Copyright (c) 1994-1998 Initio Corporation
+ * 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, 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
+ * 2. Redistributions 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.
+ *
+ * Where this Software is combined with software released under the terms of 
+ * the GNU Public License ("GPL") and the terms of the GPL would require the 
+ * combined work to also be released under the terms of the GPL, the terms
+ * and conditions of this License will apply in addition to those of the
+ * GPL with the exception of any terms or conditions of this License that
+ * conflict with, or are expressly prohibited by, the GPL.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ *
+ **************************************************************************
+ * 
+ * module: inia100.c
+ * DESCRIPTION:
+ * 	This is the Linux low-level SCSI driver for Initio INIA100 SCSI host
+ * 	adapters
+ * 09/24/98 hl - v1.02 initial production release.
+ * 12/19/98 bv - v1.02a Use spinlocks for 2.1.95 and up.
+ **************************************************************************/
+
+#define CVT_LINUX_VERSION(V,P,S)        (V * 65536 + P * 256 + S)
+
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+
+#ifdef MODULE
+#include <linux/module.h>
+#endif
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+#include <stdarg.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#if LINUX_VERSION_CODE <= CVT_LINUX_VERSION(2,1,92)
+#include <linux/bios32.h>
+#endif
+#include <linux/pci.h>
+#include <linux/proc_fs.h>
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,23)
+#include <linux/init.h>
+#endif
+#include <linux/blk.h>
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+#include <asm/spinlock.h>
+#endif
+#include "sd.h"
+#include "scsi.h"
+#include "hosts.h"
+#include "inia100.h"
+#include <linux/stat.h>
+#include <linux/malloc.h>
+
+
+#else
+
+#include <linux/kernel.h>
+#include <linux/head.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include "../block/blk.h"
+#include "scsi.h"
+#include "sd.h"
+#include "hosts.h"
+#include <linux/malloc.h>
+#include "inia100.h"
+#endif
+
+#ifdef MODULE
+Scsi_Host_Template driver_template = INIA100;
+#include "scsi_module.c"
+#endif
+
+#define ORC_RDWORD(x,y)         (short)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) ))
+
+char *inia100_Copyright = "Copyright (C) 1998-99";
+char *inia100_InitioName = "by Initio Corporation";
+char *inia100_ProductName = "INI-A100U2W";
+char *inia100_Version = "v1.02a";
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+struct proc_dir_entry proc_scsi_inia100 =
+{
+	PROC_SCSI_INIA100, 7, "INIA100",
+	S_IFDIR | S_IRUGO | S_IXUGO, 2,
+	0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+#endif
+
+/* set by inia100_setup according to the command line */
+static int setup_called = 0;
+static int orc_num_ch = MAX_SUPPORTED_ADAPTERS;		/* Maximum 4 adapters           */
+
+/* ---- INTERNAL VARIABLES ---- */
+#define NUMBER(arr)     (sizeof(arr) / sizeof(arr[0]))
+static char *setup_str = (char *) NULL;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+static void inia100_intr0(int irq, void *dev_id, struct pt_regs *);
+static void inia100_intr1(int irq, void *dev_id, struct pt_regs *);
+static void inia100_intr2(int irq, void *dev_id, struct pt_regs *);
+static void inia100_intr3(int irq, void *dev_id, struct pt_regs *);
+static void inia100_intr4(int irq, void *dev_id, struct pt_regs *);
+static void inia100_intr5(int irq, void *dev_id, struct pt_regs *);
+static void inia100_intr6(int irq, void *dev_id, struct pt_regs *);
+static void inia100_intr7(int irq, void *dev_id, struct pt_regs *);
+#else
+static void inia100_intr0(int irq, struct pt_regs *);
+static void inia100_intr1(int irq, struct pt_regs *);
+static void inia100_intr2(int irq, struct pt_regs *);
+static void inia100_intr3(int irq, struct pt_regs *);
+static void inia100_intr4(int irq, struct pt_regs *);
+static void inia100_intr5(int irq, struct pt_regs *);
+static void inia100_intr6(int irq, struct pt_regs *);
+static void inia100_intr7(int irq, struct pt_regs *);
+#endif
+
+static void inia100_panic(char *msg);
+void inia100SCBPost(BYTE * pHcb, BYTE * pScb);
+
+/* ---- EXTERNAL VARIABLES ---- */
+extern int Addinia100_into_Adapter_table(WORD, WORD, BYTE, BYTE, BYTE);
+extern void init_inia100Adapter_table(void);
+extern ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp);
+extern void orc_exec_scb(ORC_HCS * hcsp, ORC_SCB * scbp);
+extern void orc_release_scb(ORC_HCS * hcsp, ORC_SCB * scbp);
+extern void orc_interrupt(ORC_HCS * hcsp);
+extern int orc_device_reset(ORC_HCS * pHCB, ULONG SCpnt, unsigned int target, unsigned int ResetFlags);
+extern int orc_reset_scsi_bus(ORC_HCS * pHCB);
+extern int abort_SCB(ORC_HCS * hcsp, ORC_SCB * pScb);
+extern int orc_abort_srb(ORC_HCS * hcsp, ULONG SCpnt);
+extern void get_orcPCIConfig(ORC_HCS * pCurHcb, int ch_idx);
+extern int init_orchid(ORC_HCS * hcsp);
+
+extern int orc_num_scb;
+extern ORC_HCS orc_hcs[];
+
+/*****************************************************************************
+ Function name  : inia100AppendSRBToQueue
+ Description    : This function will push current request into save list
+ Input          : pSRB  -       Pointer to SCSI request block.
+		  pHCB  -       Pointer to host adapter structure
+ Output         : None.
+ Return         : None.
+*****************************************************************************/
+static void inia100AppendSRBToQueue(ORC_HCS * pHCB, Scsi_Cmnd * pSRB)
+{
+	ULONG flags;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_lock_irqsave(&(pHCB->pSRB_lock), flags);
+#else
+	save_flags(flags);
+	cli();
+#endif
+
+	pSRB->next = NULL;	/* Pointer to next */
+	if (pHCB->pSRB_head == NULL)
+		pHCB->pSRB_head = pSRB;
+	else
+		pHCB->pSRB_tail->next = pSRB;	/* Pointer to next */
+	pHCB->pSRB_tail = pSRB;
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_unlock_irqrestore(&(pHCB->pSRB_lock), flags);
+#else
+	restore_flags(flags);
+#endif
+	return;
+}
+
+/*****************************************************************************
+ Function name  : inia100PopSRBFromQueue
+ Description    : This function will pop current request from save list
+ Input          : pHCB  -       Pointer to host adapter structure
+ Output         : None.
+ Return         : pSRB  -       Pointer to SCSI request block.
+*****************************************************************************/
+static Scsi_Cmnd *inia100PopSRBFromQueue(ORC_HCS * pHCB)
+{
+	Scsi_Cmnd *pSRB;
+	ULONG flags;
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_lock_irqsave(&(pHCB->pSRB_lock), flags);
+#else
+	save_flags(flags);
+	cli();
+#endif
+
+	if ((pSRB = (Scsi_Cmnd *) pHCB->pSRB_head) != NULL) {
+		pHCB->pSRB_head = pHCB->pSRB_head->next;
+		pSRB->next = NULL;
+	}
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_unlock_irqrestore(&(pHCB->pSRB_lock), flags);
+#else
+	restore_flags(flags);
+#endif
+	return (pSRB);
+}
+
+/*****************************************************************************
+ Function name  : inia100_setup
+ Description    : 
+ Input          : pHCB  -       Pointer to host adapter structure
+ Output         : None.
+ Return         : pSRB  -       Pointer to SCSI request block.
+*****************************************************************************/
+void inia100_setup(char *str, int *ints)
+{
+	if (setup_called)
+		inia100_panic("inia100: inia100_setup called twice.\n");
+
+	setup_called = ints[0];
+	setup_str = str;
+}
+
+/*****************************************************************************
+ Function name	: orc_ReturnNumberOfAdapters
+ Description	: This function will scan PCI bus to get all Orchid card
+ Input		: None.
+ Output		: None.
+ Return		: SUCCESSFUL	- Successful scan
+		  ohterwise	- No drives founded
+*****************************************************************************/
+int orc_ReturnNumberOfAdapters(void)
+{
+	unsigned int i, iAdapters;
+
+	iAdapters = 0;
+	/*
+	 * PCI-bus probe.
+	 */
+	if (pcibios_present()) {
+		struct {
+			unsigned short vendor_id;
+			unsigned short device_id;
+		} const inia100_pci_devices[] =
+		{
+			{ORC_VENDOR_ID, I920_DEVICE_ID},
+			{ORC_VENDOR_ID, ORC_DEVICE_ID}
+		};
+
+		unsigned int dRegValue;
+		unsigned short command;
+		WORD wBIOS, wBASE;
+		BYTE bPCIBusNum, bInterrupt, bPCIDeviceNum;
+
+#ifdef MMAPIO
+		unsigned long page_offset, base;
+#endif
+
+#if LINUX_VERSION_CODE > CVT_LINUX_VERSION(2,1,92)
+		struct pci_dev *pdev = NULL;
+#else
+		int index;
+		unsigned char pci_bus, pci_devfn;
+#endif
+
+		bPCIBusNum = 0;
+		bPCIDeviceNum = 0;
+		init_inia100Adapter_table();
+		for (i = 0; i < NUMBER(inia100_pci_devices); i++) {
+#if LINUX_VERSION_CODE > CVT_LINUX_VERSION(2,1,92)
+			pdev = NULL;
+			while ((pdev = pci_find_device(inia100_pci_devices[i].vendor_id,
+					inia100_pci_devices[i].device_id,
+						       pdev)))
+#else
+			index = 0;
+			while (!(pcibios_find_device(inia100_pci_devices[i].vendor_id,
+					inia100_pci_devices[i].device_id,
+					 index++, &pci_bus, &pci_devfn)))
+#endif
+			{
+				if (iAdapters >= MAX_SUPPORTED_ADAPTERS)
+					break;	/* Never greater than maximum   */
+
+				if (i == 0) {
+					/*
+					   printk("inia100: The RAID controller is not supported by\n");
+					   printk("inia100:         this driver, we are ignoring it.\n");
+					 */
+				} else {
+					/*
+					 * Read sundry information from PCI BIOS.
+					 */
+#if LINUX_VERSION_CODE > CVT_LINUX_VERSION(2,1,92)
+					bPCIBusNum = pdev->bus->number;
+					bPCIDeviceNum = pdev->devfn;
+					dRegValue = pdev->base_address[0];
+					if (dRegValue == -1) {	/* Check return code            */
+						printk("\n\rinia100: orchid read configuration error.\n");
+						return (0);	/* Read configuration space error  */
+					}
+					/* <02> read from base address + 0x50 offset to get the wBIOS balue. */
+					wBASE = (WORD) dRegValue;
+
+					/* Now read the interrupt line  */
+					dRegValue = pdev->irq;
+					bInterrupt = dRegValue & 0xFF;	/* Assign interrupt line      */
+					pci_read_config_word(pdev, PCI_COMMAND, &command);
+					pci_write_config_word(pdev, PCI_COMMAND,
+							      command | PCI_COMMAND_MASTER | PCI_COMMAND_IO);
+
+#else
+					bPCIBusNum = pci_bus;
+					bPCIDeviceNum = pci_devfn;
+					pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_0,
+							     &dRegValue);
+					if (dRegValue == -1) {	/* Check return code            */
+						printk("\n\rinia100: Orchid read configuration error.\n");
+						return (0);	/* Read configuration space error  */
+					}
+					/* <02> read from base address + 0x50 offset to get the wBIOS balue. */
+					wBASE = (WORD) dRegValue;
+
+					/* Now read the interrupt line  */
+					pcibios_read_config_dword(pci_bus, pci_devfn, PCI_INTERRUPT_LINE,
+							     &dRegValue);
+					bInterrupt = dRegValue & 0xFF;	/* Assign interrupt line      */
+					pcibios_read_config_word(pci_bus, pci_devfn, PCI_COMMAND, &command);
+					pcibios_write_config_word(pci_bus, pci_devfn, PCI_COMMAND,
+								  command | PCI_COMMAND_MASTER | PCI_COMMAND_IO);
+#endif
+					wBASE &= PCI_BASE_ADDRESS_IO_MASK;
+					wBIOS = ORC_RDWORD(wBASE, 0x50);
+
+#ifdef MMAPIO
+					base = wBASE & PAGE_MASK;
+					page_offset = wBASE - base;
+
+					/*
+					 * replace the next line with this one if you are using 2.1.x:
+					 * temp_p->maddr = ioremap(base, page_offset + 256);
+					 */
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,0)
+					wBASE = ioremap(base, page_offset + 256);
+#else
+					wBASE = (WORD) vremap(base, page_offset + 256);
+#endif
+					if (wBASE) {
+						wBASE += page_offset;
+					}
+#endif
+
+					if (Addinia100_into_Adapter_table(wBIOS, wBASE, bInterrupt, bPCIBusNum,
+					    bPCIDeviceNum) == SUCCESSFUL)
+						iAdapters++;
+				}
+			}	/* while(pdev=....) */
+		}		/* for PCI_DEVICES */
+	}			/* PCI BIOS present */
+	return (iAdapters);
+}
+
+/*****************************************************************************
+ Function name  : inia100_detect
+ Description    : 
+ Input          : pHCB  -       Pointer to host adapter structure
+ Output         : None.
+ Return         : pSRB  -       Pointer to SCSI request block.
+*****************************************************************************/
+int inia100_detect(Scsi_Host_Template * tpnt)
+{
+	ORC_HCS *pHCB;
+	struct Scsi_Host *hreg;
+	U32 sz;
+	U32 i;			/* 01/14/98                     */
+	int ok = 0, iAdapters;
+	ULONG dBiosAdr;
+	BYTE *pbBiosAdr;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+	tpnt->proc_dir = &proc_scsi_inia100;
+#endif
+	if (setup_called) {
+		/* Setup by inia100_setup          */
+		printk("inia100: processing commandline: ");
+	}
+	/* Get total number of adapters in the motherboard */
+	iAdapters = orc_ReturnNumberOfAdapters();
+
+	/* printk("inia100: Total Initio Adapters = %d\n", iAdapters); */
+	if (iAdapters == 0)	/* If no orc founded, return */
+		return (0);
+
+	orc_num_ch = (iAdapters > orc_num_ch) ? orc_num_ch : iAdapters;
+	orc_num_scb = ORC_MAXQUEUE;
+
+	/* clear the memory needed for HCS */
+	i = orc_num_ch * sizeof(ORC_HCS);
+	memset((unsigned char *) &orc_hcs[0], 0, i);	/* Initialize orc_hcs 0   */
+
+#if 0
+	printk("orc_num_scb= %x orc_num_ch= %x hcsize= %x scbsize= %x escbsize= %x\n",
+	       orc_num_scb, orc_num_ch, sizeof(ORC_HCS), sizeof(ORC_SCB), sizeof(ESCB));
+#endif
+
+	for (i = 0, pHCB = &orc_hcs[0];		/* Get pointer for control block */
+	     i < orc_num_ch;
+	     i++, pHCB++) {
+
+		pHCB->pSRB_head = NULL;		/* Initial SRB save queue       */
+		pHCB->pSRB_tail = NULL;		/* Initial SRB save queue       */
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+		pHCB->pSRB_lock = SPIN_LOCK_UNLOCKED; /* SRB save queue lock */
+#endif
+		/* Get total memory needed for SCB */
+		sz = orc_num_scb * sizeof(ORC_SCB);
+		if ((pHCB->HCS_virScbArray = (PVOID) kmalloc(sz, GFP_ATOMIC | GFP_DMA)) == NULL) {
+			printk("inia100: SCB memory allocation error\n");
+			return (0);
+		}
+		memset((unsigned char *) pHCB->HCS_virScbArray, 0, sz);
+		pHCB->HCS_physScbArray = (U32) VIRT_TO_BUS(pHCB->HCS_virScbArray);
+
+		/* Get total memory needed for ESCB */
+		sz = orc_num_scb * sizeof(ESCB);
+		if ((pHCB->HCS_virEscbArray = (PVOID) kmalloc(sz, GFP_ATOMIC | GFP_DMA)) == NULL) {
+			printk("inia100: ESCB memory allocation error\n");
+			return (0);
+		}
+		memset((unsigned char *) pHCB->HCS_virEscbArray, 0, sz);
+		pHCB->HCS_physEscbArray = (U32) VIRT_TO_BUS(pHCB->HCS_virEscbArray);
+
+		request_region(pHCB->HCS_Base, 0x100, "inia100");	/* Register */
+		get_orcPCIConfig(pHCB, i);
+
+		dBiosAdr = pHCB->HCS_BIOS;
+		dBiosAdr = (dBiosAdr << 4);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+		pbBiosAdr = phys_to_virt(dBiosAdr);
+#endif
+
+		if (init_orchid(pHCB)) {	/* Initial orchid chip    */
+			printk("inia100: initial orchid fail!!\n");
+			return (0);
+		}
+		hreg = scsi_register(tpnt, sizeof(ORC_HCS));
+		if (hreg == NULL) {
+			printk("Invalid scsi_register pointer.\n");
+		}
+		hreg->io_port = pHCB->HCS_Base;
+		hreg->n_io_port = 0xff;
+		hreg->can_queue = orc_num_scb;	/* 03/05/98                   */
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+		hreg->unique_id = pHCB->HCS_Base;
+		hreg->max_id = pHCB->HCS_MaxTar;
+#endif
+
+		hreg->max_lun = 32;	/* 10/21/97                     */
+/*
+   hreg->max_lun = 8;
+   hreg->max_channel = 1;
+ */
+		hreg->irq = pHCB->HCS_Intr;
+		hreg->this_id = pHCB->HCS_SCSI_ID;	/* Assign HCS index           */
+		hreg->base = (UCHAR *) pHCB;
+
+#if 1
+		hreg->sg_tablesize = TOTAL_SG_ENTRY;	/* Maximun support is 32 */
+#else
+		hreg->sg_tablesize = SG_NONE;	/* No SG                        */
+#endif
+
+		/* Initial orc chip           */
+		switch (i) {
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+		case 0:
+			ok = request_irq(pHCB->HCS_Intr, inia100_intr0, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL);
+			break;
+		case 1:
+			ok = request_irq(pHCB->HCS_Intr, inia100_intr1, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL);
+			break;
+		case 2:
+			ok = request_irq(pHCB->HCS_Intr, inia100_intr2, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL);
+			break;
+		case 3:
+			ok = request_irq(pHCB->HCS_Intr, inia100_intr3, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL);
+			break;
+		case 4:
+			ok = request_irq(pHCB->HCS_Intr, inia100_intr4, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL);
+			break;
+		case 5:
+			ok = request_irq(pHCB->HCS_Intr, inia100_intr5, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL);
+			break;
+		case 6:
+			ok = request_irq(pHCB->HCS_Intr, inia100_intr6, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL);
+			break;
+		case 7:
+			ok = request_irq(pHCB->HCS_Intr, inia100_intr7, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL);
+			break;
+		default:
+			inia100_panic("inia100: Too many host adapters\n");
+			break;
+		}
+
+		if (ok < 0) {
+			if (ok == -EINVAL) {
+				printk("inia100: bad IRQ %d.\n", pHCB->HCS_Intr);
+				printk("         Contact author.\n");
+			} else {
+				if (ok == -EBUSY)
+					printk("inia100: IRQ %d already in use. Configure another.\n", pHCB->HCS_Intr);
+				else {
+					printk("\ninia100: Unexpected error code on requesting IRQ %d.\n",
+					       pHCB->HCS_Intr);
+					printk("         Contact author.\n");
+				}
+			}
+			inia100_panic("inia100: driver needs an IRQ.\n");
+		}
+#endif
+	}
+
+	tpnt->this_id = -1;
+	tpnt->can_queue = 1;
+	return 1;
+}
+
+/*****************************************************************************
+ Function name  : inia100BuildSCB
+ Description    : 
+ Input          : pHCB  -       Pointer to host adapter structure
+ Output         : None.
+ Return         : pSRB  -       Pointer to SCSI request block.
+*****************************************************************************/
+static void inia100BuildSCB(ORC_HCS * pHCB, ORC_SCB * pSCB, Scsi_Cmnd * SCpnt)
+{				/* Create corresponding SCB     */
+	struct scatterlist *pSrbSG;
+	ORC_SG *pSG;		/* Pointer to SG list           */
+	int i;
+	U32 TotalLen;
+	ESCB *pEScb;
+
+	pEScb = pSCB->SCB_EScb;
+	pEScb->SCB_Srb = SCpnt;
+	pSG = NULL;
+
+	pSCB->SCB_Opcode = ORC_EXECSCSI;
+	pSCB->SCB_Flags = SCF_NO_DCHK;	/* Clear done bit               */
+	pSCB->SCB_Target = SCpnt->target;
+	pSCB->SCB_Lun = SCpnt->lun;
+	pSCB->SCB_Reserved0 = 0;
+	pSCB->SCB_Reserved1 = 0;
+	pSCB->SCB_SGLen = 0;
+
+	if ((pSCB->SCB_XferLen = (U32) SCpnt->request_bufflen)) {
+		pSG = (ORC_SG *) & pEScb->ESCB_SGList[0];
+		if (SCpnt->use_sg) {
+			TotalLen = 0;
+			pSCB->SCB_SGLen = (U32) (SCpnt->use_sg * 8);
+			pSrbSG = (struct scatterlist *) SCpnt->request_buffer;
+			for (i = 0; i < SCpnt->use_sg; i++, pSG++, pSrbSG++) {
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+				pSG->SG_Ptr = (U32) (VIRT_TO_BUS(pSrbSG->address));
+#else
+				pSG->SG_Ptr = (U32) pSrbSG->address;
+#endif
+				pSG->SG_Len = (U32) pSrbSG->length;
+				TotalLen += (U32) pSrbSG->length;
+			}
+		} else {	/* Non SG                       */
+			pSCB->SCB_SGLen = 0x8;
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+			pSG->SG_Ptr = (U32) (VIRT_TO_BUS(SCpnt->request_buffer));
+#else
+			pSG->SG_PTR = (U32) SCpnt->request_buffer;
+#endif
+			pSG->SG_Len = (U32) SCpnt->request_bufflen;
+		}
+	}
+	pSCB->SCB_SGPAddr = (U32) pSCB->SCB_SensePAddr;
+	pSCB->SCB_HaStat = 0;
+	pSCB->SCB_TaStat = 0;
+	pSCB->SCB_Link = 0xFF;
+	pSCB->SCB_SenseLen = SENSE_SIZE;
+	pSCB->SCB_CDBLen = SCpnt->cmd_len;
+	if (pSCB->SCB_CDBLen >= IMAX_CDB) {
+		printk("max cdb length= %x\b", SCpnt->cmd_len);
+		pSCB->SCB_CDBLen = IMAX_CDB;
+	}
+	pSCB->SCB_Ident = SCpnt->lun | DISC_ALLOW;
+	if (SCpnt->device->tagged_supported) {	/* Tag Support                  */
+		pSCB->SCB_TagMsg = SIMPLE_QUEUE_TAG;	/* Do simple tag only   */
+	} else {
+		pSCB->SCB_TagMsg = 0;	/* No tag support               */
+	}
+	memcpy(&pSCB->SCB_CDB[0], &SCpnt->cmnd, pSCB->SCB_CDBLen);
+	return;
+}
+
+/*****************************************************************************
+ Function name  : inia100_queue
+ Description    : Queue a command and setup interrupts for a free bus.
+ Input          : pHCB  -       Pointer to host adapter structure
+ Output         : None.
+ Return         : pSRB  -       Pointer to SCSI request block.
+*****************************************************************************/
+int inia100_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
+{
+	register ORC_SCB *pSCB;
+	ORC_HCS *pHCB;		/* Point to Host adapter control block */
+
+	if (SCpnt->lun > 16) {
+		SCpnt->result = (DID_TIME_OUT << 16);
+		done(SCpnt);	/* Notify system DONE           */
+		return (0);
+	}
+	pHCB = (ORC_HCS *) SCpnt->host->base;
+	SCpnt->scsi_done = done;
+	/* Get free SCSI control block  */
+	if ((pSCB = orc_alloc_scb(pHCB)) == NULL) {
+		inia100AppendSRBToQueue(pHCB, SCpnt);	/* Buffer this request  */
+		/* printk("inia100_entry: can't allocate SCB\n"); */
+		return (0);
+	}
+	inia100BuildSCB(pHCB, pSCB, SCpnt);
+	orc_exec_scb(pHCB, pSCB);	/* Start execute SCB            */
+
+	return (0);
+}
+
+/*****************************************************************************
+ Function name  : inia100_command
+ Description    : We only support command in interrupt-driven fashion
+ Input          : pHCB  -       Pointer to host adapter structure
+ Output         : None.
+ Return         : pSRB  -       Pointer to SCSI request block.
+*****************************************************************************/
+int inia100_command(Scsi_Cmnd * SCpnt)
+{
+	printk("inia100: interrupt driven driver; use inia100_queue()\n");
+	return -1;
+}
+
+/*****************************************************************************
+ Function name  : inia100_abort
+ Description    : Abort a queued command.
+	                 (commands that are on the bus can't be aborted easily)
+ Input          : pHCB  -       Pointer to host adapter structure
+ Output         : None.
+ Return         : pSRB  -       Pointer to SCSI request block.
+*****************************************************************************/
+int inia100_abort(Scsi_Cmnd * SCpnt)
+{
+	ORC_HCS *hcsp;
+
+	hcsp = (ORC_HCS *) SCpnt->host->base;
+	return orc_abort_srb(hcsp, (ULONG) SCpnt);
+}
+
+/*****************************************************************************
+ Function name  : inia100_reset
+ Description    : Reset registers, reset a hanging bus and
+                  kill active and disconnected commands for target w/o soft reset
+ Input          : pHCB  -       Pointer to host adapter structure
+ Output         : None.
+ Return         : pSRB  -       Pointer to SCSI request block.
+*****************************************************************************/
+int inia100_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
+{				/* I need Host Control Block Information */
+	ORC_HCS *pHCB;
+	pHCB = (ORC_HCS *) SCpnt->host->base;
+
+	if (reset_flags & (SCSI_RESET_SUGGEST_BUS_RESET | SCSI_RESET_SUGGEST_HOST_RESET))
+		return orc_reset_scsi_bus(pHCB);
+	else
+		return orc_device_reset(pHCB, (ULONG) SCpnt, SCpnt->target, reset_flags);
+
+}
+
+/*****************************************************************************
+ Function name  : inia100SCBPost
+ Description    : This is callback routine be called when orc finish one
+			SCSI command.
+ Input          : pHCB  -       Pointer to host adapter control block.
+		  pSCB  -       Pointer to SCSI control block.
+ Output         : None.
+ Return         : None.
+*****************************************************************************/
+void inia100SCBPost(BYTE * pHcb, BYTE * pScb)
+{
+	Scsi_Cmnd *pSRB;	/* Pointer to SCSI request block */
+	ORC_HCS *pHCB;
+	ORC_SCB *pSCB;
+	ESCB *pEScb;
+
+	pHCB = (ORC_HCS *) pHcb;
+	pSCB = (ORC_SCB *) pScb;
+	pEScb = pSCB->SCB_EScb;
+	if ((pSRB = (Scsi_Cmnd *) pEScb->SCB_Srb) == 0) {
+		printk("inia100SCBPost: SRB pointer is empty\n");
+		orc_release_scb(pHCB, pSCB);	/* Release SCB for current channel */
+		return;
+	}
+	pEScb->SCB_Srb = NULL;
+
+	switch (pSCB->SCB_HaStat) {
+	case 0x0:
+	case 0xa:		/* Linked command complete without error and linked normally */
+	case 0xb:		/* Linked command complete without error interrupt generated */
+		pSCB->SCB_HaStat = 0;
+		break;
+
+	case 0x11:		/* Selection time out-The initiator selection or target
+				   reselection was not complete within the SCSI Time out period */
+		pSCB->SCB_HaStat = DID_TIME_OUT;
+		break;
+
+	case 0x14:		/* Target bus phase sequence failure-An invalid bus phase or bus
+				   phase sequence was requested by the target. The host adapter
+				   will generate a SCSI Reset Condition, notifying the host with
+				   a SCRD interrupt */
+		pSCB->SCB_HaStat = DID_RESET;
+		break;
+
+	case 0x1a:		/* SCB Aborted. 07/21/98 */
+		pSCB->SCB_HaStat = DID_ABORT;
+		break;
+
+	case 0x12:		/* Data overrun/underrun-The target attempted to transfer more data
+				   than was allocated by the Data Length field or the sum of the
+				   Scatter / Gather Data Length fields. */
+	case 0x13:		/* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */
+	case 0x16:		/* Invalid CCB Operation Code-The first byte of the CCB was invalid. */
+
+	default:
+		printk("inia100: %x %x\n", pSCB->SCB_HaStat, pSCB->SCB_TaStat);
+		pSCB->SCB_HaStat = DID_ERROR;	/* Couldn't find any better */
+		break;
+	}
+
+	if (pSCB->SCB_TaStat == 2) {	/* Check condition              */
+		memcpy((unsigned char *) &pSRB->sense_buffer[0],
+		   (unsigned char *) &pEScb->ESCB_SGList[0], SENSE_SIZE);
+	}
+	pSRB->result = pSCB->SCB_TaStat | (pSCB->SCB_HaStat << 16);
+	pSRB->scsi_done(pSRB);	/* Notify system DONE           */
+
+	/* Find the next pending SRB    */
+	if ((pSRB = inia100PopSRBFromQueue(pHCB)) != NULL) {	/* Assume resend will success   */
+		/* Reuse old SCB                */
+		inia100BuildSCB(pHCB, pSCB, pSRB);	/* Create corresponding SCB     */
+		orc_exec_scb(pHCB, pSCB);	/* Start execute SCB            */
+	} else {		/* No Pending SRB               */
+		orc_release_scb(pHCB, pSCB);	/* Release SCB for current channel */
+	}
+	return;
+}
+
+/*****************************************************************************
+ Function name  : inia100_biosparam
+ Description    : Return the "logical geometry"
+ Input          : pHCB  -       Pointer to host adapter structure
+ Output         : None.
+ Return         : pSRB  -       Pointer to SCSI request block.
+*****************************************************************************/
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+int inia100_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array)
+#else
+int inia100_biosparam(Scsi_Disk * disk, int dev, int *info_array)
+#endif
+{
+	ORC_HCS *pHcb;		/* Point to Host adapter control block */
+	ORC_TCS *pTcb;
+
+	pHcb = (ORC_HCS *) disk->device->host->base;
+	pTcb = &pHcb->HCS_Tcs[disk->device->id];
+
+	if (pTcb->TCS_DrvHead) {
+		info_array[0] = pTcb->TCS_DrvHead;
+		info_array[1] = pTcb->TCS_DrvSector;
+		info_array[2] = disk->capacity / pTcb->TCS_DrvHead / pTcb->TCS_DrvSector;
+	} else {
+		if (pTcb->TCS_DrvFlags & TCF_DRV_255_63) {
+			info_array[0] = 255;
+			info_array[1] = 63;
+			info_array[2] = disk->capacity / 255 / 63;
+		} else {
+			info_array[0] = 64;
+			info_array[1] = 32;
+			info_array[2] = disk->capacity >> 11;
+		}
+	}
+	return 0;
+}
+
+
+static void subIntr(ORC_HCS * pHCB, int irqno)
+{
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	unsigned long flags;
+
+	spin_lock_irqsave(&io_request_lock, flags);
+#endif
+
+	if (pHCB->HCS_Intr != irqno) {
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+		spin_unlock_irqrestore(&io_request_lock, flags);
+#endif
+		return;
+	}
+	orc_interrupt(pHCB);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_unlock_irqrestore(&io_request_lock, flags);
+#endif
+}
+
+/*
+ * Interrupts handler (main routine of the driver)
+ */
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+static void inia100_intr0(int irqno, void *dev_id, struct pt_regs *regs)
+#else
+static void inia100_intr0(int irqno, struct pt_regs *regs)
+#endif
+{
+	subIntr(&orc_hcs[0], irqno);
+}
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+static void inia100_intr1(int irqno, void *dev_id, struct pt_regs *regs)
+#else
+static void inia100_intr1(int irqno, struct pt_regs *regs)
+#endif
+{
+	subIntr(&orc_hcs[1], irqno);
+}
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+static void inia100_intr2(int irqno, void *dev_id, struct pt_regs *regs)
+#else
+static void inia100_intr2(int irqno, struct pt_regs *regs)
+#endif
+{
+	subIntr(&orc_hcs[2], irqno);
+}
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+static void inia100_intr3(int irqno, void *dev_id, struct pt_regs *regs)
+#else
+static void inia100_intr3(int irqno, struct pt_regs *regs)
+#endif
+{
+	subIntr(&orc_hcs[3], irqno);
+}
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+static void inia100_intr4(int irqno, void *dev_id, struct pt_regs *regs)
+#else
+static void inia100_intr4(int irqno, struct pt_regs *regs)
+#endif
+{
+	subIntr(&orc_hcs[4], irqno);
+}
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+static void inia100_intr5(int irqno, void *dev_id, struct pt_regs *regs)
+#else
+static void inia100_intr5(int irqno, struct pt_regs *regs)
+#endif
+{
+	subIntr(&orc_hcs[5], irqno);
+}
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+static void inia100_intr6(int irqno, void *dev_id, struct pt_regs *regs)
+#else
+static void inia100_intr6(int irqno, struct pt_regs *regs)
+#endif
+{
+	subIntr(&orc_hcs[6], irqno);
+}
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+static void inia100_intr7(int irqno, void *dev_id, struct pt_regs *regs)
+#else
+static void inia100_intr7(int irqno, struct pt_regs *regs)
+#endif
+{
+	subIntr(&orc_hcs[7], irqno);
+}
+
+/* 
+ * Dump the current driver status and panic...
+ */
+static void inia100_panic(char *msg)
+{
+	printk("\ninia100_panic: %s\n", msg);
+	panic("inia100 panic");
+}
+
+/*#include "inia100scsi.c" */
diff -u --recursive --new-file v2.2.2/linux/drivers/scsi/inia100.h linux/drivers/scsi/inia100.h
--- v2.2.2/linux/drivers/scsi/inia100.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/inia100.h	Mon Mar  8 15:52:43 1999
@@ -0,0 +1,503 @@
+/**************************************************************************
+ * Initio A100 device driver for Linux.
+ *
+ * Copyright (c) 1994-1998 Initio Corporation
+ * 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, 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
+ * 2. Redistributions 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.
+ *
+ * Where this Software is combined with software released under the terms of 
+ * the GNU Public License ("GPL") and the terms of the GPL would require the 
+ * combined work to also be released under the terms of the GPL, the terms
+ * and conditions of this License will apply in addition to those of the
+ * GPL with the exception of any terms or conditions of this License that
+ * conflict with, or are expressly prohibited by, the GPL.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ *
+ **************************************************************************
+ *
+ * Module: inia100.h
+ * Description: INI-A100U2W LINUX device driver header
+ * Revision History:
+ *	06/18/98 HL, Initial production Version 1.02
+ *	12/19/98 bv, Use spinlocks for 2.1.95 and up
+ ****************************************************************************/
+
+#ifndef	CVT_LINUX_VERSION
+#define	CVT_LINUX_VERSION(V,P,S)	(((V) * 65536) + ((P) * 256) + (S))
+#endif
+
+#ifndef	LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+
+#include "sd.h"
+
+extern int inia100_detect(Scsi_Host_Template *);
+extern int inia100_command(Scsi_Cmnd *);
+extern int inia100_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
+extern int inia100_abort(Scsi_Cmnd *);
+extern int inia100_reset(Scsi_Cmnd *, unsigned int);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1, 3, 0)
+extern int inia100_biosparam(Scsi_Disk *, kdev_t, int *);	/*for linux v2.0 */
+extern struct proc_dir_entry proc_scsi_inia100;
+#else
+extern int inia100_biosparam(Disk *, int, int *);	/*for linux v1.13 */
+#endif
+
+#define inia100_REVID "Initio INI-A100U2W SCSI device driver; Revision: 1.02a"
+
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(1, 3, 0)
+#define INIA100	{ \
+		NULL, \
+		NULL, \
+		inia100_REVID, \
+		inia100_detect, \
+		NULL, \
+		NULL, \
+		inia100_command, \
+		inia100_queue, \
+		inia100_abort, \
+		inia100_reset, \
+		NULL, \
+		inia100_biosparam, \
+		1, \
+7, \
+SG_ALL, \
+1, \
+0, \
+0, \
+ENABLE_CLUSTERING \
+}
+
+#else
+
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2, 1, 75)
+#define INIA100	{ \
+		NULL, \
+		NULL, \
+		&proc_scsi_inia100, \
+		NULL, \
+		inia100_REVID, \
+		inia100_detect, \
+		NULL, \
+		NULL, \
+		inia100_command, \
+		inia100_queue, \
+		inia100_abort, \
+		inia100_reset, \
+		NULL, \
+		inia100_biosparam, \
+		1, \
+		7, \
+		0, \
+		1, \
+		0, \
+		0, \
+		ENABLE_CLUSTERING \
+}
+#else				/* Version >= 2.1.75 */
+#define INIA100	{ \
+	next:		NULL,						\
+	module:		NULL,						\
+	proc_dir:	&proc_scsi_inia100, \
+	proc_info:	NULL,				\
+	name:		inia100_REVID, \
+	detect:		inia100_detect, \
+	release:	NULL, \
+	info:		NULL,					\
+	command:	inia100_command, \
+	queuecommand:	inia100_queue, \
+ 	eh_strategy_handler: NULL, \
+ 	eh_abort_handler: NULL, \
+ 	eh_device_reset_handler: NULL, \
+ 	eh_bus_reset_handler: NULL, \
+ 	eh_host_reset_handler: NULL, \
+	abort:		inia100_abort, \
+	reset:		inia100_reset, \
+	slave_attach:	NULL, \
+	bios_param:	inia100_biosparam, \
+	can_queue:	1, \
+	this_id:	1, \
+	sg_tablesize:	SG_ALL, \
+	cmd_per_lun: 	1, \
+	present:	0, \
+	unchecked_isa_dma: 0, \
+	use_clustering:	ENABLE_CLUSTERING, \
+ use_new_eh_code: 0 \
+}
+#endif
+#endif
+
+#define VIRT_TO_BUS(i)  (unsigned int) virt_to_bus((void *)(i))
+#define ULONG   unsigned long
+#define PVOID   void *
+#define USHORT  unsigned short
+#define UCHAR   unsigned char
+#define BYTE    unsigned char
+#define WORD    unsigned short
+#define DWORD   unsigned long
+#define UBYTE   unsigned char
+#define UWORD   unsigned short
+#define UDWORD  unsigned long
+#ifdef ALPHA
+#define U32     unsigned int
+#else
+#define U32     unsigned long
+#endif
+
+#ifndef NULL
+#define NULL     0		/* zero          */
+#endif
+#ifndef TRUE
+#define TRUE     (1)		/* boolean true  */
+#endif
+#ifndef FALSE
+#define FALSE    (0)		/* boolean false */
+#endif
+#ifndef FAILURE
+#define FAILURE  (-1)
+#endif
+#if 1
+#define ORC_MAXQUEUE		245
+#else
+#define ORC_MAXQUEUE		25
+#endif
+
+#define TOTAL_SG_ENTRY		32
+#define MAX_TARGETS		16
+#define IMAX_CDB			15
+#define SENSE_SIZE		14
+#define MAX_SUPPORTED_ADAPTERS  4
+#define SUCCESSFUL              0x00
+
+#define I920_DEVICE_ID	0x0002	/* Initio's inic-950 product ID   */
+
+/************************************************************************/
+/*              Scatter-Gather Element Structure                        */
+/************************************************************************/
+typedef struct ORC_SG_Struc {
+	U32 SG_Ptr;		/* Data Pointer */
+	U32 SG_Len;		/* Data Length */
+} ORC_SG;
+
+
+/* SCSI related definition                                              */
+#define DISC_NOT_ALLOW          0x80	/* Disconnect is not allowed    */
+#define DISC_ALLOW              0xC0	/* Disconnect is allowed        */
+
+
+#define ORC_OFFSET_SCB			16
+#define ORC_MAX_SCBS		    250
+#define MAX_CHANNELS       2
+#define MAX_ESCB_ELE				64
+#define TCF_DRV_255_63     0x0400
+
+/********************************************************/
+/*      Orchid Configuration Register Set               */
+/********************************************************/
+#define ORC_PVID	0x00	/* Vendor ID                      */
+#define ORC_VENDOR_ID	0x1101	/* Orchid vendor ID               */
+#define ORC_PDID        0x02	/* Device ID                    */
+#define ORC_DEVICE_ID	0x1060	/* Orchid device ID               */
+#define ORC_COMMAND	0x04	/* Command                        */
+#define BUSMS		0x04	/* BUS MASTER Enable              */
+#define IOSPA		0x01	/* IO Space Enable                */
+#define ORC_STATUS	0x06	/* Status register                */
+#define ORC_REVISION	0x08	/* Revision number                */
+#define ORC_BASE	0x10	/* Base address                   */
+#define ORC_BIOS	0x50	/* Expansion ROM base address     */
+#define ORC_INT_NUM	0x3C	/* Interrupt line         */
+#define ORC_INT_PIN	0x3D	/* Interrupt pin          */
+
+/********************************************************/
+/*      Orchid Host Command Set                         */
+/********************************************************/
+#define ORC_CMD_NOP		0x00	/* Host command - NOP             */
+#define ORC_CMD_VERSION		0x01	/* Host command - Get F/W version */
+#define ORC_CMD_ECHO		0x02	/* Host command - ECHO            */
+#define ORC_CMD_SET_NVM		0x03	/* Host command - Set NVRAM       */
+#define ORC_CMD_GET_NVM		0x04	/* Host command - Get NVRAM       */
+#define ORC_CMD_GET_BUS_STATUS	0x05	/* Host command - Get SCSI bus status */
+#define ORC_CMD_ABORT_SCB	0x06	/* Host command - Abort SCB       */
+#define ORC_CMD_ISSUE_SCB	0x07	/* Host command - Issue SCB       */
+
+/********************************************************/
+/*              Orchid Register Set                     */
+/********************************************************/
+#define ORC_GINTS	0xA0	/* Global Interrupt Status        */
+#define QINT		0x04	/* Reply Queue Interrupt  */
+#define ORC_GIMSK	0xA1	/* Global Interrupt MASK  */
+#define MQINT		0x04	/* Mask Reply Queue Interrupt     */
+#define	ORC_GCFG	0xA2	/* Global Configure               */
+#define EEPRG		0x01	/* Enable EEPROM programming */
+#define	ORC_GSTAT	0xA3	/* Global status          */
+#define WIDEBUS		0x10	/* Wide SCSI Devices connected    */
+#define ORC_HDATA	0xA4	/* Host Data                      */
+#define ORC_HCTRL	0xA5	/* Host Control                   */
+#define SCSIRST		0x80	/* SCSI bus reset         */
+#define HDO			0x40	/* Host data out          */
+#define HOSTSTOP		0x02	/* Host stop RISC engine  */
+#define DEVRST		0x01	/* Device reset                   */
+#define ORC_HSTUS	0xA6	/* Host Status                    */
+#define HDI			0x02	/* Host data in                   */
+#define RREADY		0x01	/* RISC engine is ready to receive */
+#define	ORC_NVRAM	0xA7	/* Nvram port address             */
+#define SE2CS		0x008
+#define SE2CLK		0x004
+#define SE2DO		0x002
+#define SE2DI		0x001
+#define ORC_PQUEUE	0xA8	/* Posting queue FIFO             */
+#define ORC_PQCNT	0xA9	/* Posting queue FIFO Cnt */
+#define ORC_RQUEUE	0xAA	/* Reply queue FIFO               */
+#define ORC_RQUEUECNT	0xAB	/* Reply queue FIFO Cnt           */
+#define	ORC_FWBASEADR	0xAC	/* Firmware base address  */
+
+#define	ORC_EBIOSADR0 0xB0	/* External Bios address */
+#define	ORC_EBIOSADR1 0xB1	/* External Bios address */
+#define	ORC_EBIOSADR2 0xB2	/* External Bios address */
+#define	ORC_EBIOSDATA 0xB3	/* External Bios address */
+
+#define	ORC_SCBSIZE	0xB7	/* SCB size register              */
+#define	ORC_SCBBASE0	0xB8	/* SCB base address 0             */
+#define	ORC_SCBBASE1	0xBC	/* SCB base address 1             */
+
+#define	ORC_RISCCTL	0xE0	/* RISC Control                   */
+#define PRGMRST		0x002
+#define DOWNLOAD		0x001
+#define	ORC_PRGMCTR0	0xE2	/* RISC program counter           */
+#define	ORC_PRGMCTR1	0xE3	/* RISC program counter           */
+#define	ORC_RISCRAM	0xEC	/* RISC RAM data port 4 bytes     */
+
+typedef struct orc_extended_scb {	/* Extended SCB                 */
+	ORC_SG ESCB_SGList[TOTAL_SG_ENTRY];	/*0 Start of SG list              */
+	Scsi_Cmnd *SCB_Srb;	/*50 SRB Pointer */
+} ESCB;
+
+/***********************************************************************
+		SCSI Control Block
+************************************************************************/
+typedef struct orc_scb {	/* Scsi_Ctrl_Blk                */
+	UBYTE SCB_Opcode;	/*00 SCB command code&residual  */
+	UBYTE SCB_Flags;	/*01 SCB Flags                  */
+	UBYTE SCB_Target;	/*02 Target Id                  */
+	UBYTE SCB_Lun;		/*03 Lun                        */
+	U32 SCB_Reserved0;	/*04 Reserved for ORCHID must 0 */
+	U32 SCB_XferLen;	/*08 Data Transfer Length       */
+	U32 SCB_Reserved1;	/*0C Reserved for ORCHID must 0 */
+	U32 SCB_SGLen;		/*10 SG list # * 8              */
+	U32 SCB_SGPAddr;	/*14 SG List Buf physical Addr  */
+	U32 SCB_SGPAddrHigh;	/*18 SG Buffer high physical Addr */
+	UBYTE SCB_HaStat;	/*1C Host Status                */
+	UBYTE SCB_TaStat;	/*1D Target Status              */
+	UBYTE SCB_Status;	/*1E SCB status                 */
+	UBYTE SCB_Link;		/*1F Link pointer, default 0xFF */
+	UBYTE SCB_SenseLen;	/*20 Sense Allocation Length    */
+	UBYTE SCB_CDBLen;	/*21 CDB Length                 */
+	UBYTE SCB_Ident;	/*22 Identify                   */
+	UBYTE SCB_TagMsg;	/*23 Tag Message                */
+	UBYTE SCB_CDB[IMAX_CDB];	/*24 SCSI CDBs                  */
+	UBYTE SCB_ScbIdx;	/*3C Index for this ORCSCB      */
+	U32 SCB_SensePAddr;	/*34 Sense Buffer physical Addr */
+
+	ESCB *SCB_EScb;		/*38 Extended SCB Pointer       */
+#ifndef ALPHA
+	UBYTE SCB_Reserved2[4];	/*3E Reserved for Driver use    */
+#endif
+} ORC_SCB;
+
+/* Opcodes of ORCSCB_Opcode */
+#define ORC_EXECSCSI	0x00	/* SCSI initiator command with residual */
+#define ORC_BUSDEVRST	0x01	/* SCSI Bus Device Reset  */
+
+/* Status of ORCSCB_Status */
+#define SCB_COMPLETE	0x00	/* SCB request completed  */
+#define SCB_POST	0x01	/* SCB is posted by the HOST      */
+
+/* Bit Definition for ORCSCB_Flags */
+#define SCF_DISINT	0x01	/* Disable HOST interrupt */
+#define SCF_DIR		0x18	/* Direction bits         */
+#define SCF_NO_DCHK	0x00	/* Direction determined by SCSI   */
+#define SCF_DIN		0x08	/* From Target to Initiator       */
+#define SCF_DOUT	0x10	/* From Initiator to Target       */
+#define SCF_NO_XF	0x18	/* No data transfer               */
+#define SCF_POLL   0x40
+
+/* Error Codes for ORCSCB_HaStat */
+#define HOST_SEL_TOUT	0x11
+#define HOST_DO_DU	0x12
+#define HOST_BUS_FREE	0x13
+#define HOST_BAD_PHAS	0x14
+#define HOST_INV_CMD	0x16
+#define HOST_SCSI_RST	0x1B
+#define HOST_DEV_RST	0x1C
+
+
+/* Error Codes for ORCSCB_TaStat */
+#define TARGET_CHK_COND	0x02
+#define TARGET_BUSY	0x08
+#define TARGET_TAG_FULL	0x28
+
+
+/* Queue tag msg: Simple_quque_tag, Head_of_queue_tag, Ordered_queue_tag */
+#define MSG_STAG	0x20
+#define MSG_HTAG	0x21
+#define MSG_OTAG	0x22
+
+#define MSG_IGNOREWIDE	0x23
+
+#define MSG_IDENT	0x80
+#define MSG_DISC	0x40	/* Disconnect allowed             */
+
+
+/* SCSI MESSAGE */
+#define	MSG_EXTEND	0x01
+#define	MSG_SDP		0x02
+#define	MSG_ABORT	0x06
+#define	MSG_REJ		0x07
+#define	MSG_NOP		0x08
+#define	MSG_PARITY	0x09
+#define	MSG_DEVRST	0x0C
+#define	MSG_STAG	0x20
+
+/***********************************************************************
+		Target Device Control Structure
+**********************************************************************/
+
+typedef struct ORC_Tar_Ctrl_Struc {
+	UBYTE TCS_DrvDASD;	/* 6 */
+	UBYTE TCS_DrvSCSI;	/* 7 */
+	UBYTE TCS_DrvHead;	/* 8 */
+	UWORD TCS_DrvFlags;	/* 4 */
+	UBYTE TCS_DrvSector;	/* 7 */
+} ORC_TCS, *PORC_TCS;
+
+/* Bit Definition for TCF_DrvFlags */
+#define	TCS_DF_NODASD_SUPT	0x20	/* Suppress OS/2 DASD Mgr support */
+#define	TCS_DF_NOSCSI_SUPT	0x40	/* Suppress OS/2 SCSI Mgr support */
+
+
+/***********************************************************************
+              Host Adapter Control Structure
+************************************************************************/
+typedef struct ORC_Ha_Ctrl_Struc {
+	USHORT HCS_Base;	/* 00 */
+	UBYTE HCS_Index;	/* 02 */
+	UBYTE HCS_Intr;		/* 04 */
+	UBYTE HCS_SCSI_ID;	/* 06    H/A SCSI ID */
+	UBYTE HCS_BIOS;		/* 07    BIOS configuration */
+
+	UBYTE HCS_Flags;	/* 0B */
+	UBYTE HCS_HAConfig1;	/* 1B    SCSI0MAXTags */
+	UBYTE HCS_MaxTar;	/* 1B    SCSI0MAXTags */
+
+	USHORT HCS_Units;	/* Number of units this adapter  */
+	USHORT HCS_AFlags;	/* Adapter info. defined flags   */
+	ULONG HCS_Timeout;	/* Adapter timeout value   */
+	PVOID HCS_virScbArray;	/* 28 Virtual Pointer to SCB array     */
+	U32 HCS_physScbArray;	/* Scb Physical address */
+	PVOID HCS_virEscbArray;	/* Virtual pointer to ESCB Scatter list */
+	U32 HCS_physEscbArray;	/* scatter list Physical address */
+	UBYTE TargetFlag[16];	/* 30  target configuration, TCF_EN_TAG */
+	UBYTE MaximumTags[16];	/* 40  ORC_MAX_SCBS */
+	UBYTE ActiveTags[16][16];	/* 50 */
+	ORC_TCS HCS_Tcs[16];	/* 28 */
+	U32 BitAllocFlag[MAX_CHANNELS][8];	/* Max STB is 256, So 256/32 */
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spinlock_t BitAllocFlagLock;
+#endif
+	Scsi_Cmnd *pSRB_head;
+	Scsi_Cmnd *pSRB_tail;
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spinlock_t pSRB_lock;
+#endif
+} ORC_HCS;
+
+/* Bit Definition for HCS_Flags */
+
+#define HCF_SCSI_RESET	0x01	/* SCSI BUS RESET         */
+#define HCF_PARITY    	0x02	/* parity card                    */
+#define HCF_LVDS     	0x10	/* parity card                    */
+
+/* Bit Definition for TargetFlag */
+
+#define TCF_EN_255	    0x08
+#define TCF_EN_TAG	    0x10
+#define TCF_BUSY	      0x20
+#define TCF_DISCONNECT	0x40
+#define TCF_SPIN_UP	  0x80
+
+/* Bit Definition for HCS_AFlags */
+#define	HCS_AF_IGNORE		0x01	/* Adapter ignore         */
+#define	HCS_AF_DISABLE_RESET	0x10	/* Adapter disable reset  */
+#define	HCS_AF_DISABLE_ADPT	0x80	/* Adapter disable                */
+
+
+/*---------------------------------------*/
+/* TimeOut for RESET to complete (30s)   */
+/*                                       */
+/* After a RESET the drive is checked    */
+/* every 200ms.                          */
+/*---------------------------------------*/
+#define DELAYED_RESET_MAX       (30*1000L)
+#define DELAYED_RESET_INTERVAL  200L
+
+/*----------------------------------------------*/
+/* TimeOut for IRQ from last interrupt (5s)     */
+/*----------------------------------------------*/
+#define IRQ_TIMEOUT_INTERVAL    (5*1000L)
+
+/*----------------------------------------------*/
+/* Retry Delay interval (200ms)                 */
+/*----------------------------------------------*/
+#define DELAYED_RETRY_INTERVAL  200L
+
+#define	INQUIRY_SIZE		36
+#define	CAPACITY_SIZE		8
+#define	DEFAULT_SENSE_LEN	14
+
+#define	DEVICE_NOT_FOUND	0x86
+
+/*----------------------------------------------*/
+/* Definition for PCI device                    */
+/*----------------------------------------------*/
+#define	MAX_PCI_DEVICES	21
+#define	MAX_PCI_BUSES	8
diff -u --recursive --new-file v2.2.2/linux/drivers/scsi/megaraid.c linux/drivers/scsi/megaraid.c
--- v2.2.2/linux/drivers/scsi/megaraid.c	Wed Jan 13 15:00:42 1999
+++ linux/drivers/scsi/megaraid.c	Wed Feb 24 16:27:54 1999
@@ -1,24 +1,27 @@
 /*===================================================================
  *
  *                    Linux MegaRAID device driver
- * 
+ *
  * Copyright 1998 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.
+ *              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 : 0.92
+ * Version : 0.96
  * 
  * Description: Linux device driver for AMI MegaRAID controller
  *
+ * Supported controllers: MegaRAID 418, 428, 438, 466, 762
+ * 
+ * Maintainer: Jeff L Jones <jeffreyj@ami.com>
+ *
  * History:
  *
  * Version 0.90:
- *     Works and has been tested with the MegaRAID 428 controller, and
- *     the MegaRAID 438 controller.  Probably works with the 466 also,
- *     but not tested.
+ *     Original source contributed by Dell; integrated it into the kernel and
+ *     cleaned up some things.  Added support for 438/466 controllers.
  *
  * Version 0.91:
  *     Aligned mailbox area on 16-byte boundry.
@@ -35,31 +38,51 @@
  *     Removed setting of SA_INTERRUPT flag when requesting Irq.
  *
  * Version 0.92ac:
- *	Small changes to the comments/formatting. Plus a couple of
- *	added notes. Returned to the authors. No actual code changes
- *	save printk levels.
- *	8 Oct 98	Alan Cox <alan.cox@linux.org>
+ *      Small changes to the comments/formatting. Plus a couple of
+ *      added notes. Returned to the authors. No actual code changes
+ *      save printk levels.
+ *      8 Oct 98        Alan Cox <alan.cox@linux.org>
  *
  *     Merged with 2.1.131 source tree.
- *     12 Dec 98       K. Baranowski <kgb@knm.org.pl>
+ *     12 Dec 98       K. Baranowski <kgb@knm.org.pl>                          
+ *
+ * Version 0.93:
+ *     Added support for vendor specific ioctl commands (0x80+xxh)
+ *     Changed some fields in MEGARAID struct to better values.
+ *     Added signature check for Rp controllers under 2.0 kernels
+ *     Changed busy-wait loop to be time-based
+ *     Fixed SMP race condition in isr
+ *     Added kfree (sgList) on release
+ *     Added #include linux/version.h to megaraid.h for hosts.h
+ *     Changed max_id to represent max logical drives instead of targets.
+ *
+ * Version 0.94:
+ *     Got rid of some excess locking/unlocking
+ *     Fixed slight memory corruption problem while memcpy'ing into mailbox
+ *     Changed logical drives to be reported as luns rather than targets
+ *     Changed max_id to 16 since it is now max targets/chan again.
+ *     Improved ioctl interface for upcoming megamgr
+ *
+ * Version 0.95:
+ *     Fixed problem of queueing multiple commands to adapter;
+ *       still has some strange problems on some setups, so still
+ *       defaults to single.  To enable parallel commands change
+ *       #define MULTI_IO in megaraid.h
+ *     Changed kmalloc allocation to be done in beginning.
+ *     Got rid of C++ style comments
+ *
+ * Version 0.96:
+ *     762 fully supported.
  *
  * BUGS:
- *     Tested with 2.1.90, but unfortunately there is a bug in pci.c which
- *     fails to detect our controller.  Does work with 2.1.118--don't know
- *     which kernel in between it was fixed in.
- *     With SMP enabled under 2.1.118 with more than one processor, gets an
- *     error message "scsi_end_request: buffer-list destroyed" under heavy
- *     IO, but doesn't seem to affect operation, or data integrity.  The
- *     message doesn't occur without SMP enabled, or with one proccessor with
- *     SMP enabled, or under any combination under 2.0 kernels.
+ *     Some older 2.1 kernels (eg. 2.1.90) have a bug in pci.c that
+ *     fails to detect the controller as a pci device on the system.
  *
  *===================================================================*/
-#define QISR 1
 
 #define CRLFSTR "\n"
 
-#define MULTIQ 1
-
+#include <linux/config.h>
 #include <linux/version.h>
 
 #ifdef MODULE
@@ -68,10 +91,8 @@
 #if LINUX_VERSION_CODE >= 0x20100
 char kernel_version[] = UTS_RELEASE;
 
-/* originally ported by Dell Corporation; updated, released, and maintained by
-   American Megatrends */
-MODULE_AUTHOR("American Megatrends Inc."); 
-MODULE_DESCRIPTION("AMI MegaRAID driver");    
+MODULE_AUTHOR ("American Megatrends Inc.");
+MODULE_DESCRIPTION ("AMI MegaRAID driver");
 #endif
 #endif
 
@@ -93,6 +114,7 @@
 #include <linux/sched.h>
 #include <linux/stat.h>
 #include <linux/malloc.h>	/* for kmalloc() */
+#include <linux/config.h>	/* for CONFIG_PCI */
 #if LINUX_VERSION_CODE < 0x20100
 #include <linux/bios32.h>
 #else
@@ -112,14 +134,18 @@
  *
  *                          #Defines
  *
- *================================================================*/
+ *================================================================
+ */
 
 #if LINUX_VERSION_CODE < 0x020100
 #define ioremap vremap
 #define iounmap vfree
 
 /* simulate spin locks */
-typedef struct {volatile char lock;} spinlock_t;
+typedef struct {
+  volatile char lock;
+} spinlock_t;
+
 #define spin_lock_init(x) { (x)->lock = 0;}
 #define spin_lock_irqsave(x,flags) { while ((x)->lock) barrier();\
                                         (x)->lock=1; save_flags(flags);\
@@ -143,7 +169,15 @@
   (*node) = obj; \
   (*node)->##next = NULL; \
   spin_unlock_irqrestore(&mega_lock,cpuflag);\
-};
+}
+
+/* a non-locking version (if we already have the lock) */
+#define ENQUEUE_NL(obj,type,list,next) \
+{ type **node; \
+  for(node=&(list); *node; node=(type **)&(*node)->##next); \
+  (*node) = obj; \
+  (*node)->##next = NULL; \
+}
 
 #define DEQUEUE(obj,type,list,next) \
 { long cpuflag; \
@@ -154,125 +188,124 @@
   spin_unlock_irqrestore(&mega_lock,cpuflag);\
 };
 
-u_long RDINDOOR(mega_host_config *megaCfg)
+u_long RDINDOOR (mega_host_config * megaCfg)
 {
-  return readl(megaCfg->base + 0x20);
+  return readl (megaCfg->base + 0x20);
 }
 
-void WRINDOOR(mega_host_config *megaCfg, u_long value)
+void WRINDOOR (mega_host_config * megaCfg, u_long value)
 {
-  writel(value,megaCfg->base+0x20);
+  writel (value, megaCfg->base + 0x20);
 }
 
-u_long RDOUTDOOR(mega_host_config *megaCfg)
+u_long RDOUTDOOR (mega_host_config * megaCfg)
 {
-  return readl(megaCfg->base+0x2C);
+  return readl (megaCfg->base + 0x2C);
 }
 
-void WROUTDOOR(mega_host_config *megaCfg, u_long value)
+void WROUTDOOR (mega_host_config * megaCfg, u_long value)
 {
-  writel(value,megaCfg->base+0x2C);
+  writel (value, megaCfg->base + 0x2C);
 }
 
 /*================================================================
  *
  *                    Function prototypes
  *
- *================================================================*/
-static int  MegaIssueCmd(mega_host_config *megaCfg,
-			 u_char *mboxData,
-			 mega_scb *scb,
+ *================================================================
+ */
+static int MegaIssueCmd (mega_host_config * megaCfg,
+			 u_char * mboxData,
+			 mega_scb * scb,
 			 int intr);
-static int  build_sglist(mega_host_config *megaCfg, mega_scb *scb, 
-			 u_long *buffer, u_long *length);
+static int build_sglist (mega_host_config * megaCfg, mega_scb * scb,
+			 u_long * buffer, u_long * length);
 
-static void mega_runque(void *);
-static void mega_rundoneq(void);
-static void mega_cmd_done(mega_host_config *,mega_scb *, int);
+static void mega_runque (void *);
+static void mega_rundoneq (void);
+static void mega_cmd_done (mega_host_config *, mega_scb *, int);
+static mega_scb *mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt);
+static inline void freeSgList(mega_host_config *megaCfg);
 
 /* set SERDEBUG to 1 to enable serial debugging */
 #define SERDEBUG 0
 #if SERDEBUG
-static void ser_init(void);
-static void ser_puts(char *str);
-static void ser_putc(char c);
-static int  ser_printk(const char *fmt, ...);
+static void ser_init (void);
+static void ser_puts (char *str);
+static void ser_putc (char c);
+static int ser_printk (const char *fmt,...);
 #endif
 
 /*================================================================
  *
  *                    Global variables
  *
- *================================================================*/
-static int               numCtlrs = 0;
-static mega_host_config *megaCtlrs[4] = { 0 };
-
-/* Change this to 0 if you want to see the raw drives */
-static int use_raid   = 1;
+ *================================================================
+ */
+static int numCtlrs = 0;
+static mega_host_config *megaCtlrs[12] = {0};
 
 /* Queue of pending/completed SCBs */
-static mega_scb  *qPending   = NULL;
+static mega_scb *qPending = NULL;
 static Scsi_Cmnd *qCompleted = NULL;
 
 volatile static spinlock_t mega_lock;
-static struct tq_struct runq = {0,0,mega_runque,NULL};
+static struct tq_struct runq = {0, 0, mega_runque, NULL};
 
-struct proc_dir_entry proc_scsi_megaraid = {
+struct proc_dir_entry proc_scsi_megaraid =
+{
   PROC_SCSI_MEGARAID, 8, "megaraid",
   S_IFDIR | S_IRUGO | S_IXUGO, 2
 };
 
 #if SERDEBUG
-static char strbuf[MAX_SERBUF+1];
+static char strbuf[MAX_SERBUF + 1];
 
-static void ser_init()
+static void ser_init ()
 {
-    unsigned port=COM_BASE;
+  unsigned port = COM_BASE;
 
-    outb(0x80,port+3);
-    outb(0,port+1);
-    /* 9600 Baud, if 19200: outb(6,port) */
-    outb(12, port);
-    outb(3,port+3);
-    outb(0,port+1);
+  outb (0x80, port + 3);
+  outb (0, port + 1);
+  /* 9600 Baud, if 19200: outb(6,port) */
+  outb (12, port);
+  outb (3, port + 3);
+  outb (0, port + 1);
 }
 
-static void ser_puts(char *str)
+static void ser_puts (char *str)
 {
-    char *ptr;
+  char *ptr;
 
-    ser_init();
-    for (ptr=str;*ptr;++ptr)
-        ser_putc(*ptr);
+  ser_init ();
+  for (ptr = str; *ptr; ++ptr)
+    ser_putc (*ptr);
 }
 
-static void ser_putc(char c)
+static void ser_putc (char c)
 {
-    unsigned port=COM_BASE;
+  unsigned port = COM_BASE;
 
-    while ((inb(port+5) & 0x20)==0);
-    outb(c,port);
-    if (c==0x0a)
-    {
-        while ((inb(port+5) & 0x20)==0);
-        outb(0x0d,port);
-    }
+  while ((inb (port + 5) & 0x20) == 0);
+  outb (c, port);
+  if (c == 0x0a) {
+    while ((inb (port + 5) & 0x20) == 0);
+    outb (0x0d, port);
+  }
 }
 
-static int ser_printk(const char *fmt, ...)
+static int ser_printk (const char *fmt,...)
 {
-    va_list args;
-    int i;
-    long flags;
+  va_list args;
+  int i;
+  long flags;
 
-    spin_lock_irqsave(mega_lock,flags);
-    va_start(args,fmt);
-    i = vsprintf(strbuf,fmt,args);
-    ser_puts(strbuf);
-    va_end(args);
-    spin_unlock_irqrestore(&mega_lock,flags);
+  va_start (args, fmt);
+  i = vsprintf (strbuf, fmt, args);
+  ser_puts (strbuf);
+  va_end (args);
 
-    return i;
+  return i;
 }
 
 #define TRACE(a)    { ser_printk a;}
@@ -281,14 +314,14 @@
 #define TRACE(A)
 #endif
 
-void callDone(Scsi_Cmnd *SCpnt)
+void callDone (Scsi_Cmnd * SCpnt)
 {
   if (SCpnt->result) {
-    TRACE(("*** %.08lx %.02x <%d.%d.%d> = %x\n", SCpnt->serial_number, 
-	   SCpnt->cmnd[0], SCpnt->channel, SCpnt->target, SCpnt->lun, 
-	   SCpnt->result));
+    TRACE (("*** %.08lx %.02x <%d.%d.%d> = %x\n", SCpnt->serial_number,
+	    SCpnt->cmnd[0], SCpnt->channel, SCpnt->target, SCpnt->lun,
+	    SCpnt->result));
   }
-  SCpnt->scsi_done(SCpnt);
+  SCpnt->scsi_done (SCpnt);
 }
 
 /*-------------------------------------------------------------------------
@@ -299,96 +332,95 @@
 
 /*================================================
  * Initialize SCB structures
- *================================================*/
-static void initSCB(mega_host_config *megaCfg)
+ *================================================
+ */
+static int initSCB (mega_host_config * megaCfg)
 {
   int idx;
 
-  for(idx=0; idx<megaCfg->max_cmds; idx++) {
-    megaCfg->scbList[idx].idx    = -1;
-    megaCfg->scbList[idx].flag   = 0;
-    megaCfg->scbList[idx].sgList = NULL;
-    megaCfg->scbList[idx].SCpnt  = NULL;
+  for (idx = 0; idx < megaCfg->max_cmds; idx++) {
+    megaCfg->scbList[idx].idx = -1;
+    megaCfg->scbList[idx].flag = 0;
+    megaCfg->scbList[idx].sgList = kmalloc(sizeof(mega_sglist) * MAX_SGLIST,
+				GFP_ATOMIC | GFP_DMA);
+    if (megaCfg->scbList[idx].sgList == NULL) {
+        printk(KERN_WARNING "Can't allocate sglist for id %d\n",idx);
+        freeSgList(megaCfg);
+        return -1;
+    }
+    megaCfg->scbList[idx].SCpnt = NULL;
   }
+  return 0;
 }
 
 /*===========================
  * Allocate a SCB structure
- *===========================*/
-static mega_scb *allocateSCB(mega_host_config *megaCfg,Scsi_Cmnd *SCpnt)
+ *===========================
+ */
+static mega_scb * allocateSCB (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
 {
-  int        idx;
-  long       flags;
+  int idx;
+  long flags;
 
-  spin_lock_irqsave(&mega_lock,flags);
-  for(idx=0; idx<megaCfg->max_cmds; idx++) {
+  spin_lock_irqsave (&mega_lock, flags);
+  for (idx = 0; idx < megaCfg->max_cmds; idx++) {
     if (megaCfg->scbList[idx].idx < 0) {
 
-      /* Set Index and SCB pointer */ 
-      megaCfg->scbList[idx].flag  = 0;
-      megaCfg->scbList[idx].idx   = idx;
+      /* Set Index and SCB pointer */
+      megaCfg->scbList[idx].idx = idx;
+      spin_unlock_irqrestore (&mega_lock, flags);
+      megaCfg->scbList[idx].flag = 0;
       megaCfg->scbList[idx].SCpnt = SCpnt;
-      megaCfg->scbList[idx].next  = NULL;
-      spin_unlock_irqrestore(&mega_lock,flags);
-
-      if (megaCfg->scbList[idx].sgList == NULL) {
-	megaCfg->scbList[idx].sgList =
-                  kmalloc(sizeof(mega_sglist)*MAX_SGLIST,GFP_ATOMIC|GFP_DMA);
-      }
+      megaCfg->scbList[idx].next = NULL;
 
       return &megaCfg->scbList[idx];
     }
   }
-  spin_unlock_irqrestore(&mega_lock,flags);
+  spin_unlock_irqrestore (&mega_lock, flags);
+
+  printk (KERN_WARNING "Megaraid: Could not allocate free SCB!!!\n");
 
-  printk(KERN_WARNING "Megaraid: Could not allocate free SCB!!!\n");
-  
   return NULL;
 }
 
 /*=======================
  * Free a SCB structure
- *=======================*/
-static void freeSCB(mega_scb *scb)
+ *=======================
+ */
+static void freeSCB (mega_scb * scb)
 {
-  long flags;
-
-  spin_lock_irqsave(&mega_lock,flags);
-  scb->flag  = 0;
-  scb->idx   = -1;
-  scb->next  = NULL;
+  scb->flag = 0;
+  scb->next = NULL;
   scb->SCpnt = NULL;
-  spin_unlock_irqrestore(&mega_lock,flags);
+    scb->idx = -1;
 }
 
 /* Run through the list of completed requests */
-static void mega_rundoneq()
+static void mega_rundoneq ()
 {
   mega_host_config *megaCfg;
-  Scsi_Cmnd        *SCpnt;
-  long              islogical;
+  Scsi_Cmnd *SCpnt;
+  char islogical;
+
+  while (1) {
+    DEQUEUE (SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+    if (SCpnt == NULL)
+      return;
+
+    megaCfg = (mega_host_config *) SCpnt->host->hostdata;
 
-  while(1) {
-    DEQUEUE(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
-    if (SCpnt == NULL) return;
-
-    megaCfg = (mega_host_config *)SCpnt->host->hostdata;
-
-    /* Check if we're allowing access to RAID drives or physical
-     *  if use_raid == 1 and this wasn't a disk on the max channel or
-     *  if use_raid == 0 and this was a disk on the max channel
-     *  then fail.
-     */
-    islogical = (SCpnt->channel == megaCfg->host->max_channel) ? 1 : 0;
+    islogical = (SCpnt->channel == megaCfg->host->max_channel &&
+                 SCpnt->target == 0);
     if (SCpnt->cmnd[0] == INQUIRY &&
-	((((u_char*)SCpnt->request_buffer)[0] & 0x1F) == TYPE_DISK) &&
-	(islogical != use_raid)) {
-       SCpnt->result = 0xF0;
+	((((u_char *) SCpnt->request_buffer)[0] & 0x1F) == TYPE_DISK) &&
+	!islogical) {
+      SCpnt->result = 0xF0;
     }
 
     /* Convert result to error */
-    switch(SCpnt->result) {
-    case 0x00: case 0x02:
+    switch (SCpnt->result) {
+    case 0x00:
+    case 0x02:
       SCpnt->result |= (DID_OK << 16);
       break;
     case 0x8:
@@ -400,16 +432,16 @@
     }
 
     /* Callback */
-    callDone(SCpnt);
+    callDone (SCpnt);
   }
 }
 
 /* Add command to the list of completed requests */
-static void mega_cmd_done(mega_host_config *megaCfg,mega_scb *pScb, int status)
+static void mega_cmd_done (mega_host_config * megaCfg, mega_scb * pScb, int status)
 {
   pScb->SCpnt->result = status;
-  ENQUEUE(pScb->SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
-  freeSCB(pScb);
+  ENQUEUE (pScb->SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+  freeSCB (pScb);
 }
 
 /*----------------------------------------------------
@@ -417,42 +449,45 @@
  *
  * Run as a scheduled task 
  *----------------------------------------------------*/
-static void mega_runque(void *dummy)
+static void mega_runque (void *dummy)
 {
   mega_host_config *megaCfg;
-  mega_scb         *pScb;
-  long              flags;
+  mega_scb *pScb;
+  long flags;
 
   /* Take care of any completed requests */
-  mega_rundoneq();
+  mega_rundoneq ();
 
-  DEQUEUE(pScb,mega_scb,qPending,next);
+  DEQUEUE (pScb, mega_scb, qPending, next);
 
   if (pScb) {
-    megaCfg = (mega_host_config *)pScb->SCpnt->host->hostdata;
+    if (pScb->SCpnt) {
+        TRACE(("NULL SCpnt for idx %d!\n",pScb->idx));
+    }
+    megaCfg = (mega_host_config *) pScb->SCpnt->host->hostdata;
 
-    if (megaCfg->mbox->busy || megaCfg->flag & (IN_ISR|PENDING)) {
-      TRACE(("%.08lx %.02x <%d.%d.%d> intr%d busy%d isr%d pending%d\n",
-	     pScb->SCpnt->serial_number,
-	     pScb->SCpnt->cmnd[0],
-	     pScb->SCpnt->channel,
-	     pScb->SCpnt->target,
-	     pScb->SCpnt->lun,
-	     intr_count,
-	     megaCfg->mbox->busy,
-	     (megaCfg->flag & IN_ISR)  ? 1 : 0,
-	     (megaCfg->flag & PENDING) ? 1 : 0));
+    if (megaCfg->mbox->busy || megaCfg->flag & (IN_ISR | PENDING)) {
+      TRACE (("%.08lx %.02x <%d.%d.%d> busy%d isr%d pending%d\n",
+	      pScb->SCpnt->serial_number,
+	      pScb->SCpnt->cmnd[0],
+	      pScb->SCpnt->channel,
+	      pScb->SCpnt->target,
+	      pScb->SCpnt->lun,
+	      megaCfg->mbox->busy,
+	      (megaCfg->flag & IN_ISR) ? 1 : 0,
+	      (megaCfg->flag & PENDING) ? 1 : 0));
     }
 
-    if (MegaIssueCmd(megaCfg, pScb->mboxData, pScb, 1)) {
+    if (MegaIssueCmd (megaCfg, pScb->mboxData, pScb, 1)) {
       /* We're BUSY... come back later */
-      spin_lock_irqsave(&mega_lock,flags);
+      spin_lock_irqsave (&mega_lock, flags);
       pScb->next = qPending;
-      qPending   = pScb;
-      spin_unlock_irqrestore(&mega_lock,flags);
+      qPending = pScb;
+      spin_unlock_irqrestore (&mega_lock, flags);
 
-      if (!(megaCfg->flag & PENDING)) { /* If PENDING, irq will schedule task */
-          queue_task(&runq, &tq_scheduler);
+      if (!(megaCfg->flag & PENDING)) {
+	/* If PENDING, irq will schedule task */
+	queue_task (&runq, &tq_scheduler);
       }
     }
   }
@@ -466,17 +501,22 @@
  * If NULL is returned, the scsi_done function MUST have been called
  *
  *-------------------------------------------------------------------*/
-static mega_scb *mega_build_cmd(mega_host_config *megaCfg, Scsi_Cmnd *SCpnt)
+static mega_scb * mega_build_cmd (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
 {
-  mega_scb      *pScb;
-  mega_mailbox  *mbox;
+  mega_scb *pScb;
+  mega_mailbox *mbox;
   mega_passthru *pthru;
-  long           seg;
+  long seg;
+  char islogical;
+
+  if (SCpnt->cmnd[0] & 0x80)	/* ioctl from megamgr */
+    return mega_ioctl (megaCfg, SCpnt);
 
-  /* We don't support multi-luns */
-  if (SCpnt->lun != 0) {
+  islogical = (SCpnt->channel == megaCfg->host->max_channel && SCpnt->target == 0);
+
+  if (!islogical && SCpnt->lun != 0) {
     SCpnt->result = (DID_BAD_TARGET << 16);
-    callDone(SCpnt);
+    callDone (SCpnt);
     return NULL;
   }
 
@@ -485,45 +525,46 @@
    *               Logical drive commands
    *
    *-----------------------------------------------------*/
-  if (SCpnt->channel == megaCfg->host->max_channel) {
-    switch(SCpnt->cmnd[0]) {
+  if (islogical) {
+    switch (SCpnt->cmnd[0]) {
     case TEST_UNIT_READY:
-      memset(SCpnt->request_buffer, 0, SCpnt->request_bufflen);
+      memset (SCpnt->request_buffer, 0, SCpnt->request_bufflen);
       SCpnt->result = (DID_OK << 16);
-      callDone(SCpnt);
+      callDone (SCpnt);
       return NULL;
 
     case MODE_SENSE:
-      memset(SCpnt->request_buffer, 0, SCpnt->cmnd[4]);
+      memset (SCpnt->request_buffer, 0, SCpnt->cmnd[4]);
       SCpnt->result = (DID_OK << 16);
-      callDone(SCpnt);
+      callDone (SCpnt);
       return NULL;
 
     case READ_CAPACITY:
     case INQUIRY:
       /* Allocate a SCB and initialize passthru */
-      if ((pScb = allocateSCB(megaCfg,SCpnt)) == NULL) {
+      if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
 	SCpnt->result = (DID_ERROR << 16);
-	callDone(SCpnt);
+	callDone (SCpnt);
 	return NULL;
       }
       pthru = &pScb->pthru;
-      mbox  = (mega_mailbox *)&pScb->mboxData;
+      mbox = (mega_mailbox *) & pScb->mboxData;
 
-      memset(mbox,  0, sizeof(pScb->mboxData));
-      memset(pthru, 0, sizeof(mega_passthru));
-      pthru->timeout      = 0;
-      pthru->ars          = 0;
-      pthru->islogical    = 1;
-      pthru->logdrv       = SCpnt->target;
-      pthru->cdblen       = SCpnt->cmd_len;
-      pthru->dataxferaddr = virt_to_bus(SCpnt->request_buffer);
-      pthru->dataxferlen  = SCpnt->request_bufflen;
-      memcpy(pthru->cdb, SCpnt->cmnd, SCpnt->cmd_len);
+      memset (mbox, 0, sizeof (pScb->mboxData));
+      memset (pthru, 0, sizeof (mega_passthru));
+      pthru->timeout = 0;
+      pthru->ars = 1;
+      pthru->reqsenselen = 14;
+      pthru->islogical = 1;
+      pthru->logdrv = SCpnt->lun;
+      pthru->cdblen = SCpnt->cmd_len;
+      pthru->dataxferaddr = virt_to_bus (SCpnt->request_buffer);
+      pthru->dataxferlen = SCpnt->request_bufflen;
+      memcpy (pthru->cdb, SCpnt->cmnd, SCpnt->cmd_len);
 
       /* Initialize mailbox area */
-      mbox->cmd      = MEGA_MBOXCMD_PASSTHRU;
-      mbox->xferaddr = virt_to_bus(pthru);
+      mbox->cmd = MEGA_MBOXCMD_PASSTHRU;
+      mbox->xferaddr = virt_to_bus (pthru);
 
       return pScb;
 
@@ -532,51 +573,51 @@
     case READ_10:
     case WRITE_10:
       /* Allocate a SCB and initialize mailbox */
-      if ((pScb = allocateSCB(megaCfg,SCpnt)) == NULL) {
+      if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
 	SCpnt->result = (DID_ERROR << 16);
-	callDone(SCpnt);
+	callDone (SCpnt);
 	return NULL;
       }
-      mbox = (mega_mailbox *)&pScb->mboxData;
+      mbox = (mega_mailbox *) & pScb->mboxData;
 
-      memset(mbox, 0, sizeof(pScb->mboxData));
-      mbox->logdrv = SCpnt->target;
-      mbox->cmd    = (*SCpnt->cmnd == READ_6 || *SCpnt->cmnd == READ_10) ?
+      memset (mbox, 0, sizeof (pScb->mboxData));
+      mbox->logdrv = SCpnt->lun;
+      mbox->cmd = (*SCpnt->cmnd == READ_6 || *SCpnt->cmnd == READ_10) ?
 	MEGA_MBOXCMD_LREAD : MEGA_MBOXCMD_LWRITE;
-      
+
       /* 6-byte */
       if (*SCpnt->cmnd == READ_6 || *SCpnt->cmnd == WRITE_6) {
-	mbox->numsectors = 
-	  (u_long)SCpnt->cmnd[4];
-	mbox->lba = 
-	  ((u_long)SCpnt->cmnd[1] << 16) |
-	  ((u_long)SCpnt->cmnd[2] << 8) |
-	  (u_long)SCpnt->cmnd[3];
+	mbox->numsectors =
+	  (u_long) SCpnt->cmnd[4];
+	mbox->lba =
+	  ((u_long) SCpnt->cmnd[1] << 16) |
+	  ((u_long) SCpnt->cmnd[2] << 8) |
+	  (u_long) SCpnt->cmnd[3];
 	mbox->lba &= 0x1FFFFF;
       }
-      
+
       /* 10-byte */
       if (*SCpnt->cmnd == READ_10 || *SCpnt->cmnd == WRITE_10) {
-	mbox->numsectors = 
-	  (u_long)SCpnt->cmnd[8] |
-	  ((u_long)SCpnt->cmnd[7] << 8);
+	mbox->numsectors =
+	  (u_long) SCpnt->cmnd[8] |
+	  ((u_long) SCpnt->cmnd[7] << 8);
 	mbox->lba =
-	  ((u_long)SCpnt->cmnd[2] << 24) |
-	  ((u_long)SCpnt->cmnd[3] << 16) |
-	  ((u_long)SCpnt->cmnd[4] << 8) |
-	  (u_long)SCpnt->cmnd[5];
+	  ((u_long) SCpnt->cmnd[2] << 24) |
+	  ((u_long) SCpnt->cmnd[3] << 16) |
+	  ((u_long) SCpnt->cmnd[4] << 8) |
+	  (u_long) SCpnt->cmnd[5];
       }
-      
+
       /* Calculate Scatter-Gather info */
-      mbox->numsgelements = build_sglist(megaCfg, pScb, 
-					 (u_long*)&mbox->xferaddr,
-					 (u_long*)&seg);
+      mbox->numsgelements = build_sglist (megaCfg, pScb,
+					  (u_long *) & mbox->xferaddr,
+					  (u_long *) & seg);
 
       return pScb;
-      
+
     default:
       SCpnt->result = (DID_BAD_TARGET << 16);
-      callDone(SCpnt);
+      callDone (SCpnt);
       return NULL;
     }
   }
@@ -587,31 +628,32 @@
    *-----------------------------------------------------*/
   else {
     /* Allocate a SCB and initialize passthru */
-    if ((pScb = allocateSCB(megaCfg,SCpnt)) == NULL) {
+    if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
       SCpnt->result = (DID_ERROR << 16);
-      callDone(SCpnt);
+      callDone (SCpnt);
       return NULL;
     }
     pthru = &pScb->pthru;
-    mbox  = (mega_mailbox *)pScb->mboxData;
-    
-    memset(mbox,  0, sizeof(pScb->mboxData));
-    memset(pthru, 0, sizeof(mega_passthru));
-    pthru->timeout   = 0;
-    pthru->ars       = 0;
+    mbox = (mega_mailbox *) pScb->mboxData;
+
+    memset (mbox, 0, sizeof (pScb->mboxData));
+    memset (pthru, 0, sizeof (mega_passthru));
+    pthru->timeout = 0;
+    pthru->ars = 1;
+    pthru->reqsenselen = 14;
     pthru->islogical = 0;
-    pthru->channel   = SCpnt->channel;
-    pthru->target    = SCpnt->target;
-    pthru->cdblen    = SCpnt->cmd_len;
-    memcpy(pthru->cdb, SCpnt->cmnd, SCpnt->cmd_len);
-   
-    pthru->numsgelements = build_sglist(megaCfg, pScb,
-					(u_long *)&pthru->dataxferaddr,
-					(u_long *)&pthru->dataxferlen);
-    
+    pthru->channel = SCpnt->channel;
+    pthru->target = SCpnt->target;
+    pthru->cdblen = SCpnt->cmd_len;
+    memcpy (pthru->cdb, SCpnt->cmnd, SCpnt->cmd_len);
+
+    pthru->numsgelements = build_sglist (megaCfg, pScb,
+					 (u_long *) & pthru->dataxferaddr,
+					 (u_long *) & pthru->dataxferlen);
+
     /* Initialize mailbox */
-    mbox->cmd      = MEGA_MBOXCMD_PASSTHRU;
-    mbox->xferaddr = virt_to_bus(pthru);
+    mbox->cmd = MEGA_MBOXCMD_PASSTHRU;
+    mbox->xferaddr = virt_to_bus (pthru);
 
     return pScb;
   }
@@ -619,88 +661,183 @@
 }
 
 /*--------------------------------------------------------------------
+ * build RAID commands for controller, passed down through ioctl()
+ *--------------------------------------------------------------------*/
+static mega_scb * mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
+{
+  mega_scb *pScb;
+  mega_ioctl_mbox *mbox;
+  mega_mailbox *mailbox;
+  mega_passthru *pthru;
+  long seg;
+  unsigned char *data = (unsigned char *)SCpnt->request_buffer;
+  int i;
+
+  if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
+    SCpnt->result = (DID_ERROR << 16);
+    callDone (SCpnt);
+    return NULL;
+  }
+
+#if 0
+  printk("\nBUF: ");
+  for (i=0;i<18;i++) {
+     printk(" %x",data[i]);
+  }
+  printk("......\n");
+#endif
+
+  mbox = (mega_ioctl_mbox *) & pScb->mboxData;
+  mailbox = (mega_mailbox *) & pScb->mboxData;
+  memset (mailbox, 0, sizeof (pScb->mboxData));
+
+  if (data[0] == 0x03) {	/* passthrough command */
+    unsigned char cdblen = data[2];
+
+    pthru = &pScb->pthru;
+    memset (pthru, 0, sizeof (mega_passthru));
+    pthru->islogical = (data[cdblen+3] & 0x80) ? 1:0;
+    pthru->timeout = data[cdblen+3] & 0x07;
+    pthru->reqsenselen = 14;
+    pthru->ars = (data[cdblen+3] & 0x08) ? 1:0;
+    pthru->logdrv = data[cdblen+4];
+    pthru->channel = data[cdblen+5];
+    pthru->target = data[cdblen+6];
+    pthru->cdblen = cdblen;
+    memcpy (pthru->cdb, &data[3], cdblen);
+
+    mailbox->cmd = MEGA_MBOXCMD_PASSTHRU;
+    mailbox->xferaddr = virt_to_bus (pthru);
+
+
+    pthru->numsgelements = build_sglist (megaCfg, pScb,
+					 (u_long *) & pthru->dataxferaddr,
+					 (u_long *) & pthru->dataxferlen);
+
+    for (i=0;i<(SCpnt->request_bufflen-cdblen-7);i++) {
+       data[i] = data[i+cdblen+7];
+    }
+
+    return pScb;
+  }
+  /* else normal (nonpassthru) command */
+
+  mbox->cmd = data[0];
+  mbox->channel = data[1];
+  mbox->param = data[2];
+  mbox->pad[0] = data[3];
+  mbox->logdrv = data[4];
+
+  mbox->numsgelements = build_sglist (megaCfg, pScb,
+				      (u_long *) & mbox->xferaddr,
+				      (u_long *) & seg);
+
+  for (i=0;i<(SCpnt->request_bufflen-6);i++) {
+     data[i] = data[i+6];
+  }
+
+  return (pScb);
+}
+
+
+/*--------------------------------------------------------------------
  * Interrupt service routine
  *--------------------------------------------------------------------*/
-static void megaraid_isr(int irq, void *devp, struct pt_regs *regs)
+static void megaraid_isr (int irq, void *devp, struct pt_regs *regs)
 {
-  mega_host_config *megaCfg;
-  u_char            byte, idx, sIdx;
-  u_long            dword;
-  mega_mailbox     *mbox;
-  mega_scb         *pScb;
-  long              flags;
-  int               qCnt, qStatus;
+  mega_host_config    *megaCfg;
+  u_char byte, idx, sIdx;
+  u_long dword;
+  mega_mailbox *mbox;
+  mega_scb *pScb;
+  long flags;
+  int qCnt, qStatus;
 
-  megaCfg = (mega_host_config *)devp;
-  mbox    = (mega_mailbox *)megaCfg->mbox;
+  megaCfg = (mega_host_config *) devp;
+  mbox = (mega_mailbox *) megaCfg->mbox;
 
   if (megaCfg->host->irq == irq) {
-    spin_lock_irqsave(&mega_lock,flags);
+
+#if LINUX_VERSION_CODE >= 0x20100
+    spin_lock_irqsave (&io_request_lock, flags);
+#endif
+
+    spin_lock_irqsave (&mega_lock, flags);
 
     if (megaCfg->flag & IN_ISR) {
-      TRACE(("ISR called reentrantly!!\n"));
+      TRACE (("ISR called reentrantly!!\n"));
     }
 
     megaCfg->flag |= IN_ISR;
 
     /* Check if a valid interrupt is pending */
     if (megaCfg->flag & BOARD_QUARTZ) {
-        dword = RDOUTDOOR(megaCfg);
-        if (dword != 0x10001234) {
-            /* Spurious interrupt */
-            megaCfg->flag &= ~IN_ISR;
-            spin_unlock_irqrestore(&mega_lock,flags);
-            return;
-        }
-        WROUTDOOR(megaCfg,dword);
-    } else {
-        byte = READ_PORT(megaCfg->host->io_port, INTR_PORT);
-        if ((byte & VALID_INTR_BYTE) == 0) {
-          /* Spurious interrupt */
-          megaCfg->flag &= ~IN_ISR;
-          spin_unlock_irqrestore(&mega_lock,flags);
-          return;
-        }
-        WRITE_PORT(megaCfg->host->io_port, INTR_PORT, byte);
+      dword = RDOUTDOOR (megaCfg);
+      if (dword != 0x10001234) {
+	/* Spurious interrupt */
+	megaCfg->flag &= ~IN_ISR;
+	spin_unlock_irqrestore (&mega_lock, flags);
+#if LINUX_VERSION_CODE >= 0x20100
+        spin_unlock_irqrestore (&io_request_lock, flags);
+#endif
+	return;
+      }
+      WROUTDOOR (megaCfg, dword);
     }
-    
-    qCnt    = mbox->numstatus;
+    else {
+      byte = READ_PORT (megaCfg->host->io_port, INTR_PORT);
+      if ((byte & VALID_INTR_BYTE) == 0) {
+	/* Spurious interrupt */
+	megaCfg->flag &= ~IN_ISR;
+	spin_unlock_irqrestore (&mega_lock, flags);
+#if LINUX_VERSION_CODE >= 0x20100
+        spin_unlock_irqrestore (&io_request_lock, flags);
+#endif
+	return;
+      }
+      WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte);
+    }
+
+    qCnt = mbox->numstatus;
     qStatus = mbox->status;
 
-    if (qCnt > 1) {TRACE(("ISR: Received %d status\n", qCnt))
-        printk(KERN_DEBUG "Got numstatus = %d\n",qCnt);
+    if (qCnt > 1) {
+      TRACE (("ISR: Received %d status\n", qCnt))
+	printk (KERN_DEBUG "Got numstatus = %d\n", qCnt);
     }
-    
-    for(idx=0; idx<qCnt; idx++) {
+
+    for (idx = 0; idx < qCnt; idx++) {
       sIdx = mbox->completed[idx];
       if (sIdx > 0) {
-	pScb = &megaCfg->scbList[sIdx-1];
-        spin_unlock_irqrestore(&mega_lock,flags); /* locks within cmd_done */
-	mega_cmd_done(megaCfg,&megaCfg->scbList[sIdx-1], qStatus);
-        spin_lock_irqsave(&mega_lock,flags);
+	pScb = &megaCfg->scbList[sIdx - 1];
+        /* FVF: let's try to avoid un/locking for no good reason */
+        pScb->SCpnt->result = qStatus;
+        ENQUEUE_NL (pScb->SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+        freeSCB (pScb);
       }
     }
     if (megaCfg->flag & BOARD_QUARTZ) {
-        WRINDOOR(megaCfg,virt_to_bus(megaCfg->mbox)|0x2);
-        while (RDINDOOR(megaCfg) & 0x02);
-    } else {
-        CLEAR_INTR(megaCfg->host->io_port);
+      WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x2);
+      while (RDINDOOR (megaCfg) & 0x02);
+    }
+    else {
+      CLEAR_INTR (megaCfg->host->io_port);
     }
 
     megaCfg->flag &= ~IN_ISR;
     megaCfg->flag &= ~PENDING;
 
-    spin_unlock_irqrestore(&mega_lock,flags);
+    spin_unlock_irqrestore (&mega_lock, flags);
+    mega_runque (NULL);
 
-    spin_lock_irqsave(&io_request_lock, flags);
-    mega_runque(NULL);
-    spin_unlock_irqrestore(&io_request_lock,flags);              
+#if LINUX_VERSION_CODE >= 0x20100
+    spin_unlock_irqrestore (&io_request_lock, flags);
+#endif
 
 #if 0
     /* Queue as a delayed ISR routine */
-    queue_task_irq_off(&runq, &tq_immediate);
-    mark_bh(IMMEDIATE_BH);
-    spin_unlock_irqrestore(&mega_lock,flags);
+    queue_task_irq_off (&runq, &tq_immediate);
+    mark_bh (IMMEDIATE_BH);
 #endif
 
   }
@@ -709,15 +846,17 @@
 /*==================================================*/
 /* Wait until the controller's mailbox is available */
 /*==================================================*/
-static int busyWaitMbox(mega_host_config *megaCfg)
+static int busyWaitMbox (mega_host_config * megaCfg)
 {
-  mega_mailbox *mbox = (mega_mailbox *)megaCfg->mbox;
-  long          counter;
+  mega_mailbox *mbox = (mega_mailbox *) megaCfg->mbox;
+  long counter;
 
-  for(counter=0; counter<0xFFFFFF; counter++) {
-    if (!mbox->busy) return 0;
+  for (counter = 0; counter < 10000; counter++) {
+    udelay (100);
+    if (!mbox->busy)
+      return 0;
   }
-  return -1;
+  return -1;			/* give up after 1 second */
 }
 
 /*=====================================================
@@ -728,92 +867,105 @@
  *   u_char *mboxData - Mailbox area, 16 bytes
  *   mega_scb *pScb   - SCB posting (or NULL if N/A)
  *   int intr         - if 1, interrupt, 0 is blocking
- *=====================================================*/
-static int MegaIssueCmd(mega_host_config *megaCfg,
-			u_char *mboxData,
-			mega_scb *pScb,
-			int intr)
-{
-  mega_mailbox *mbox = (mega_mailbox *)megaCfg->mbox;
-  long          flags;
-  u_char        byte;
-  u_long        cmdDone;
-
-  mboxData[0x1] = (pScb ? pScb->idx+1 : 0x00);  /* Set cmdid */
-  mboxData[0xF] = 1;                            /* Set busy */
-
-  /* one bad report of problem when issuing a command while pending.
-   * Wasn't able to duplicate, but it doesn't really affect performance
-   * anyway, so don't allow command while PENDING
-   */
+ *=====================================================
+ */
+static int MegaIssueCmd (mega_host_config * megaCfg,
+	      u_char * mboxData,
+	      mega_scb * pScb,
+	      int intr)
+{
+  mega_mailbox *mbox = (mega_mailbox *) megaCfg->mbox;
+  long flags;
+  u_char byte;
+  u_long cmdDone;
+
+  mboxData[0x1] = (pScb ? pScb->idx + 1 : 0x00);	/* Set cmdid */
+  mboxData[0xF] = 1;		/* Set busy */
+
+  spin_lock_irqsave(&mega_lock,flags);
+
+#if !MULTI_IO
   if (megaCfg->flag & PENDING) {
-    return -1;
+     spin_unlock_irqrestore(&mega_lock,flags);
+     return -1;
   }
+#endif
 
   /* Wait until mailbox is free */
-  if (busyWaitMbox(megaCfg)) {
+  if (busyWaitMbox (megaCfg)) {
     if (pScb) {
-      TRACE(("Mailbox busy %.08lx <%d.%d.%d>\n", pScb->SCpnt->serial_number,
-	     pScb->SCpnt->channel, pScb->SCpnt->target, pScb->SCpnt->lun));
+      TRACE (("Mailbox busy %.08lx <%d.%d.%d>\n", pScb->SCpnt->serial_number,
+	      pScb->SCpnt->channel, pScb->SCpnt->target, pScb->SCpnt->lun));
+    } else {
+	TRACE(("pScb NULL in MegaIssueCmd!\n"));
     }
+    spin_unlock_irqrestore(&mega_lock,flags);
     return -1;
   }
 
   /* Copy mailbox data into host structure */
-  spin_lock_irqsave(&mega_lock,flags);
-  memset(mbox, 0, sizeof(mega_mailbox));
-  memcpy(mbox, mboxData, 16);
-  spin_unlock_irqrestore(&mega_lock,flags);
+  memset (mbox, 0, 16);
+  memcpy (mbox, mboxData, 16);
 
   /* Kick IO */
   megaCfg->flag |= PENDING;
   if (intr) {
     /* Issue interrupt (non-blocking) command */
     if (megaCfg->flag & BOARD_QUARTZ) {
-        mbox->mraid_poll = 0; 
-        mbox->mraid_ack = 0; 
-        WRINDOOR(megaCfg, virt_to_bus(megaCfg->mbox) | 0x1);
-    } else {
-        ENABLE_INTR(megaCfg->host->io_port);
-        ISSUE_COMMAND(megaCfg->host->io_port);
+      mbox->mraid_poll = 0;
+      mbox->mraid_ack = 0;
+      WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x1);
     }
+    else {
+      ENABLE_INTR (megaCfg->host->io_port);
+      ISSUE_COMMAND (megaCfg->host->io_port);
+    }
+    spin_unlock_irqrestore(&mega_lock,flags);
   }
-  else {      /* Issue non-ISR (blocking) command */
+  else {			/* Issue non-ISR (blocking) command */
 
     if (megaCfg->flag & BOARD_QUARTZ) {
 
-      mbox->mraid_poll = 0; 
-      mbox->mraid_ack = 0; 
-      WRINDOOR(megaCfg, virt_to_bus(megaCfg->mbox) | 0x1);
+      mbox->mraid_poll = 0;
+      mbox->mraid_ack = 0;
+      WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x1);
 
-      while((cmdDone=RDOUTDOOR(megaCfg)) != 0x10001234);
-      WROUTDOOR(megaCfg, cmdDone);
+      while ((cmdDone = RDOUTDOOR (megaCfg)) != 0x10001234);
+      WROUTDOOR (megaCfg, cmdDone);
 
+      spin_unlock_irqrestore(&mega_lock,flags);
       if (pScb) {
-	mega_cmd_done(megaCfg,pScb, mbox->status);
-	mega_rundoneq();
+	mega_cmd_done (megaCfg, pScb, mbox->status);
+	mega_rundoneq ();
       }
 
-      WRINDOOR(megaCfg,virt_to_bus(megaCfg->mbox) | 0x2);
-      while(RDINDOOR(megaCfg) & 0x2);
+      WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x2);
+      while (RDINDOOR (megaCfg) & 0x2);
 
       megaCfg->flag &= ~PENDING;
+
     }
     else {
-      DISABLE_INTR(megaCfg->host->io_port);
-      ISSUE_COMMAND(megaCfg->host->io_port);
-      
-      while(!((byte=READ_PORT(megaCfg->host->io_port,INTR_PORT))&INTR_VALID));
-      WRITE_PORT(megaCfg->host->io_port, INTR_PORT, byte);
-      
-      ENABLE_INTR(megaCfg->host->io_port);
-      CLEAR_INTR(megaCfg->host->io_port);
-      
+      DISABLE_INTR (megaCfg->host->io_port);
+      ISSUE_COMMAND (megaCfg->host->io_port);
+
+      while (!((byte = READ_PORT (megaCfg->host->io_port, INTR_PORT)) & INTR_VALID));
+      WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte);
+
+
+      ENABLE_INTR (megaCfg->host->io_port);
+      CLEAR_INTR (megaCfg->host->io_port);
+      megaCfg->flag &= ~PENDING;
+      spin_unlock_irqrestore(&mega_lock,flags);
+
       if (pScb) {
-	mega_cmd_done(megaCfg,pScb, mbox->status);
-	mega_rundoneq();
+	mega_cmd_done (megaCfg, pScb, mbox->status);
+	mega_rundoneq ();
       }
-      megaCfg->flag &= ~PENDING;
+      else {
+	TRACE (("Error: NULL pScb!\n"));
+      }
+
     }
   }
 
@@ -823,42 +975,42 @@
 /*-------------------------------------------------------------------
  * Copies data to SGLIST
  *-------------------------------------------------------------------*/
-static int build_sglist(mega_host_config *megaCfg, mega_scb *scb, 
-			u_long *buffer, u_long *length)
+static int build_sglist (mega_host_config * megaCfg, mega_scb * scb,
+	      u_long * buffer, u_long * length)
 {
   struct scatterlist *sgList;
   int idx;
 
   /* Scatter-gather not used */
   if (scb->SCpnt->use_sg == 0) {
-    *buffer = virt_to_bus(scb->SCpnt->request_buffer);
-    *length = (u_long)scb->SCpnt->request_bufflen;
+    *buffer = virt_to_bus (scb->SCpnt->request_buffer);
+    *length = (u_long) scb->SCpnt->request_bufflen;
     return 0;
   }
 
-  sgList = (struct scatterlist *)scb->SCpnt->buffer;
+  sgList = (struct scatterlist *) scb->SCpnt->request_buffer;
   if (scb->SCpnt->use_sg == 1) {
-    *buffer = virt_to_bus(sgList[0].address);
-    *length = (u_long)sgList[0].length;
+    *buffer = virt_to_bus (sgList[0].address);
+    *length = (u_long) sgList[0].length;
     return 0;
   }
 
   /* Copy Scatter-Gather list info into controller structure */
-  for(idx=0; idx<scb->SCpnt->use_sg; idx++) {
-    scb->sgList[idx].address = virt_to_bus(sgList[idx].address);
-    scb->sgList[idx].length  = (u_long)sgList[idx].length;
+  for (idx = 0; idx < scb->SCpnt->use_sg; idx++) {
+    scb->sgList[idx].address = virt_to_bus (sgList[idx].address);
+    scb->sgList[idx].length = (u_long) sgList[idx].length;
   }
-  
+
   /* Reset pointer and length fields */
-  *buffer = virt_to_bus(scb->sgList);
+  *buffer = virt_to_bus (scb->sgList);
   *length = 0;
 
   /* Return count of SG requests */
   return scb->SCpnt->use_sg;
 }
-    
+
 /*--------------------------------------------------------------------
- * Initializes the address of the controller's mailbox register
+ * Initializes the adress of the controller's mailbox register
  *  The mailbox register is used to issue commands to the card.
  *  Format of the mailbox area:
  *   00 01 command
@@ -873,25 +1025,25 @@
  *   10 01 numstatus byte
  *   11 01 status byte
  *--------------------------------------------------------------------*/
-static int mega_register_mailbox(mega_host_config *megaCfg, u_long paddr)
+static int mega_register_mailbox (mega_host_config * megaCfg, u_long paddr)
 {
   /* align on 16-byte boundry */
   megaCfg->mbox = &megaCfg->mailbox;
-  megaCfg->mbox = (mega_mailbox *) ((((ulong)megaCfg->mbox) + 16)&0xfffffff0);
-  paddr = (paddr+16)&0xfffffff0;
+  megaCfg->mbox = (mega_mailbox *) ((((ulong) megaCfg->mbox) + 16) & 0xfffffff0);
+  paddr = (paddr + 16) & 0xfffffff0;
 
   /* Register mailbox area with the firmware */
   if (megaCfg->flag & BOARD_QUARTZ) {
   }
   else {
-    WRITE_PORT(megaCfg->host->io_port, MBOX_PORT0, paddr         & 0xFF);
-    WRITE_PORT(megaCfg->host->io_port, MBOX_PORT1, (paddr >>  8) & 0xFF);
-    WRITE_PORT(megaCfg->host->io_port, MBOX_PORT2, (paddr >> 16) & 0xFF);
-    WRITE_PORT(megaCfg->host->io_port, MBOX_PORT3, (paddr >> 24) & 0xFF);
-    WRITE_PORT(megaCfg->host->io_port, ENABLE_MBOX_REGION, ENABLE_MBOX_BYTE);
-    
-    CLEAR_INTR(megaCfg->host->io_port);
-    ENABLE_INTR(megaCfg->host->io_port);
+    WRITE_PORT (megaCfg->host->io_port, MBOX_PORT0, paddr & 0xFF);
+    WRITE_PORT (megaCfg->host->io_port, MBOX_PORT1, (paddr >> 8) & 0xFF);
+    WRITE_PORT (megaCfg->host->io_port, MBOX_PORT2, (paddr >> 16) & 0xFF);
+    WRITE_PORT (megaCfg->host->io_port, MBOX_PORT3, (paddr >> 24) & 0xFF);
+    WRITE_PORT (megaCfg->host->io_port, ENABLE_MBOX_REGION, ENABLE_MBOX_BYTE);
+
+    CLEAR_INTR (megaCfg->host->io_port);
+    ENABLE_INTR (megaCfg->host->io_port);
   }
   return 0;
 }
@@ -899,77 +1051,79 @@
 /*-------------------------------------------------------------------
  * Issue an adapter info query to the controller
  *-------------------------------------------------------------------*/
-static int mega_i_query_adapter(mega_host_config *megaCfg)
+static int mega_i_query_adapter (mega_host_config * megaCfg)
 {
   mega_RAIDINQ *adapterInfo;
   mega_mailbox *mbox;
-  u_char        mboxData[16];
-  u_long        paddr;
+  u_char mboxData[16];
+  u_long paddr;
 
-  spin_lock_init(&mega_lock);
+  spin_lock_init (&mega_lock);
   /* Initialize adapter inquiry */
-  paddr = virt_to_bus(megaCfg->mega_buffer);
-  mbox  = (mega_mailbox *)mboxData;
+  paddr = virt_to_bus (megaCfg->mega_buffer);
+  mbox = (mega_mailbox *) mboxData;
 
-  memset((void *)megaCfg->mega_buffer, 0, sizeof(megaCfg->mega_buffer));
-  memset(mbox, 0, 16);
+  memset ((void *) megaCfg->mega_buffer, 0, sizeof (megaCfg->mega_buffer));
+  memset (mbox, 0, 16);
 
   /* Initialize mailbox registers */
-  mbox->cmd      = MEGA_MBOXCMD_ADAPTERINQ;
+  mbox->cmd = MEGA_MBOXCMD_ADAPTERINQ;
   mbox->xferaddr = paddr;
 
   /* Issue a blocking command to the card */
-  MegaIssueCmd(megaCfg, mboxData, NULL, 0);
-  
+  MegaIssueCmd (megaCfg, mboxData, NULL, 0);
+
   /* Initialize host/local structures with Adapter info */
-  adapterInfo = (mega_RAIDINQ *)megaCfg->mega_buffer;
+  adapterInfo = (mega_RAIDINQ *) megaCfg->mega_buffer;
   megaCfg->host->max_channel = adapterInfo->AdpInfo.ChanPresent;
-  megaCfg->host->max_id      = adapterInfo->AdpInfo.MaxTargPerChan;
-  megaCfg->numldrv           = adapterInfo->LogdrvInfo.NumLDrv;
+/*  megaCfg->host->max_id = adapterInfo->AdpInfo.MaxTargPerChan; */
+  megaCfg->host->max_id = 16; /* max targets/chan */
+  megaCfg->numldrv = adapterInfo->LogdrvInfo.NumLDrv;
 
 #if 0
-  printk(KERN_DEBUG "---- Logical drive info ----\n");
-  for(i=0; i<megaCfg->numldrv; i++) {
-    printk(KERN_DEBUG "%d: size: %ld prop: %x state: %x\n",i,
-	   adapterInfo->LogdrvInfo.LDrvSize[i],
-	   adapterInfo->LogdrvInfo.LDrvProp[i],
-	   adapterInfo->LogdrvInfo.LDrvState[i]);
-  }
-  printk(KERN_DEBUG "---- Physical drive info ----\n");
-  for(i=0; i<MAX_PHYSICAL_DRIVES; i++) {
-    if (i && !(i % 8)) printk("\n");
-    printk("%d: %x   ", i, adapterInfo->PhysdrvInfo.PDrvState[i]);
+  printk ("KERN_DEBUG ---- Logical drive info ----\n");
+  for (i = 0; i < megaCfg->numldrv; i++) {
+    printk ("%d: size: %ld prop: %x state: %x\n", i,
+	    adapterInfo->LogdrvInfo.LDrvSize[i],
+	    adapterInfo->LogdrvInfo.LDrvProp[i],
+	    adapterInfo->LogdrvInfo.LDrvState[i]);
+  }
+  printk (KERN_DEBUG "---- Physical drive info ----\n");
+  for (i = 0; i < MAX_PHYSICAL_DRIVES; i++) {
+    if (i && !(i % 8))
+      printk ("\n");
+    printk ("%d: %x   ", i, adapterInfo->PhysdrvInfo.PDrvState[i]);
   }
-  printk("\n");
+  printk ("\n");
 #endif
 
   megaCfg->max_cmds = adapterInfo->AdpInfo.MaxConcCmds;
 
-#ifdef HP            /* use HP firmware and bios version encoding */
-      sprintf(megaCfg->fwVer,"%c%d%d.%d%d",
-          adapterInfo->AdpInfo.FwVer[2],
-          adapterInfo->AdpInfo.FwVer[1] >> 8,
-          adapterInfo->AdpInfo.FwVer[1] & 0x0f,
-          adapterInfo->AdpInfo.FwVer[2] >> 8,
-          adapterInfo->AdpInfo.FwVer[2] & 0x0f);
-      sprintf(megaCfg->biosVer,"%c%d%d.%d%d",
-          adapterInfo->AdpInfo.BiosVer[2],
-          adapterInfo->AdpInfo.BiosVer[1] >> 8,
-          adapterInfo->AdpInfo.BiosVer[1] & 0x0f,
-          adapterInfo->AdpInfo.BiosVer[2] >> 8,
-          adapterInfo->AdpInfo.BiosVer[2] & 0x0f);
+#ifdef HP			/* use HP firmware and bios version encoding */
+  sprintf (megaCfg->fwVer, "%c%d%d.%d%d",
+	   adapterInfo->AdpInfo.FwVer[2],
+	   adapterInfo->AdpInfo.FwVer[1] >> 8,
+	   adapterInfo->AdpInfo.FwVer[1] & 0x0f,
+	   adapterInfo->AdpInfo.FwVer[2] >> 8,
+	   adapterInfo->AdpInfo.FwVer[2] & 0x0f);
+  sprintf (megaCfg->biosVer, "%c%d%d.%d%d",
+	   adapterInfo->AdpInfo.BiosVer[2],
+	   adapterInfo->AdpInfo.BiosVer[1] >> 8,
+	   adapterInfo->AdpInfo.BiosVer[1] & 0x0f,
+	   adapterInfo->AdpInfo.BiosVer[2] >> 8,
+	   adapterInfo->AdpInfo.BiosVer[2] & 0x0f);
 #else
-      memcpy(megaCfg->fwVer, adapterInfo->AdpInfo.FwVer, 4);
-      megaCfg->fwVer[4] = 0;
+  memcpy (megaCfg->fwVer, adapterInfo->AdpInfo.FwVer, 4);
+  megaCfg->fwVer[4] = 0;
 
-      memcpy(megaCfg->biosVer, adapterInfo->AdpInfo.BiosVer, 4);
-      megaCfg->biosVer[4] = 0;
+  memcpy (megaCfg->biosVer, adapterInfo->AdpInfo.BiosVer, 4);
+  megaCfg->biosVer[4] = 0;
 #endif
 
-  printk(KERN_INFO "megaraid: [%s:%s] detected %d logical drives" CRLFSTR,
-	 megaCfg->fwVer,
-	 megaCfg->biosVer,
-	 megaCfg->numldrv);
+  printk (KERN_INFO "megaraid: [%s:%s] detected %d logical drives" CRLFSTR,
+	  megaCfg->fwVer,
+	  megaCfg->biosVer,
+	  megaCfg->numldrv);
   return 0;
 }
 
@@ -982,47 +1136,65 @@
 /*----------------------------------------------------------
  * Returns data to be displayed in /proc/scsi/megaraid/X
  *----------------------------------------------------------*/
-int megaraid_proc_info(char *buffer, char **start, off_t offset,
-		       int length, int inode, int inout)
+int megaraid_proc_info (char *buffer, char **start, off_t offset,
+		    int length, int inode, int inout)
 {
   *start = buffer;
   return 0;
 }
 
-int findCard(Scsi_Host_Template *pHostTmpl, 
-	     u_short pciVendor, u_short pciDev,
-	     long flag)
+int findCard (Scsi_Host_Template * pHostTmpl,
+	  u_short pciVendor, u_short pciDev,
+	  long flag)
 {
   mega_host_config *megaCfg;
   struct Scsi_Host *host;
-  u_char            pciBus, pciDevFun, megaIrq;
-  u_long            megaBase;
-  u_short           pciIdx = 0;
+  u_char pciBus, pciDevFun, megaIrq;
+  u_long megaBase;
+  u_short pciIdx = 0;
+  u_short numFound = 0;
 
 #if LINUX_VERSION_CODE < 0x20100
-  while(!pcibios_find_device(pciVendor, pciDev, pciIdx,&pciBus,&pciDevFun)) {
+  while (!pcibios_find_device (pciVendor, pciDev, pciIdx, &pciBus, &pciDevFun)) {
+#if 0
+    if (flag & BOARD_QUARTZ) {
+      u_int magic;
+      pcibios_read_config_dword (pciBus, pciDevFun,
+				 PCI_CONF_AMISIG,
+				 &magic);
+      if (magic != AMI_SIGNATURE) {
+        pciIdx++;
+	continue;		/* not an AMI board */
+      }
+    }
+#endif
+
+#if 0
+    } /* keep auto-indenters happy */
+#endif
+
 #else
-  struct pci_dev   *pdev=pci_devices;
+  struct pci_dev *pdev = pci_devices;
 
-  while((pdev = pci_find_device(pciVendor, pciDev, pdev))) {
+  while ((pdev = pci_find_device (pciVendor, pciDev, pdev))) {
     pciBus = pdev->bus->number;
     pciDevFun = pdev->devfn;
 #endif
-    printk(KERN_INFO "megaraid: found 0x%4.04x:0x%4.04x:idx %d:bus %d:slot %d:fun %d\n",
-	   pciVendor, 
-	   pciDev, 
-	   pciIdx, pciBus, 
-	   PCI_SLOT(pciDevFun), 
-	   PCI_FUNC(pciDevFun));
-    
+    printk (KERN_INFO "megaraid: found 0x%4.04x:0x%4.04x:idx %d:bus %d:slot %d:fun %d\n",
+	    pciVendor,
+	    pciDev,
+	    pciIdx, pciBus,
+	    PCI_SLOT (pciDevFun),
+	    PCI_FUNC (pciDevFun));
+
     /* Read the base port and IRQ from PCI */
 #if LINUX_VERSION_CODE < 0x20100
-    pcibios_read_config_dword(pciBus, pciDevFun,
-			     PCI_BASE_ADDRESS_0,
-			     (u_int *)&megaBase);
-    pcibios_read_config_byte(pciBus, pciDevFun,			       
-			     PCI_INTERRUPT_LINE,
-			     &megaIrq);
+    pcibios_read_config_dword (pciBus, pciDevFun,
+			       PCI_BASE_ADDRESS_0,
+			       (u_int *) & megaBase);
+    pcibios_read_config_byte (pciBus, pciDevFun,
+			      PCI_INTERRUPT_LINE,
+			      &megaIrq);
 #else
     megaBase = pdev->base_address[0];
     megaIrq = pdev->irq;
@@ -1031,7 +1203,7 @@
 
     if (flag & BOARD_QUARTZ) {
       megaBase &= PCI_BASE_ADDRESS_MEM_MASK;
-      megaBase = (long) ioremap(megaBase,128);
+      megaBase = (long) ioremap (megaBase, 128);
     }
     else {
       megaBase &= PCI_BASE_ADDRESS_IO_MASK;
@@ -1039,72 +1211,75 @@
     }
 
     /* Initialize SCSI Host structure */
-    host    = scsi_register(pHostTmpl, sizeof(mega_host_config));
-    megaCfg = (mega_host_config *)host->hostdata;
-    memset(megaCfg, 0, sizeof(mega_host_config));
-
-    printk(KERN_INFO " scsi%d: Found a MegaRAID controller at 0x%x, IRQ: %d" CRLFSTR, 
-	   host->host_no, (u_int)megaBase, megaIrq);
-    
+    host = scsi_register (pHostTmpl, sizeof (mega_host_config));
+    megaCfg = (mega_host_config *) host->hostdata;
+    memset (megaCfg, 0, sizeof (mega_host_config));
+
+    printk (KERN_INFO " scsi%d: Found a MegaRAID controller at 0x%x, IRQ: %d" CRLFSTR,
+	    host->host_no, (u_int) megaBase, megaIrq);
+
     /* Copy resource info into structure */
-    megaCfg->flag            = flag;
-    megaCfg->host            = host;
-    megaCfg->base            = megaBase;
-    megaCfg->host->irq       = megaIrq;
-    megaCfg->host->io_port   = megaBase;
+    megaCfg->flag = flag;
+    megaCfg->host = host;
+    megaCfg->base = megaBase;
+    megaCfg->host->irq = megaIrq;
+    megaCfg->host->io_port = megaBase;
     megaCfg->host->n_io_port = 16;
     megaCfg->host->unique_id = (pciBus << 8) | pciDevFun;
-    megaCtlrs[numCtlrs++]    = megaCfg;
+    megaCtlrs[numCtlrs++] = megaCfg;
 
     if (flag != BOARD_QUARTZ) {
       /* Request our IO Range */
-      if (check_region(megaBase, 16)) {
-	printk(KERN_WARNING "megaraid: Couldn't register I/O range!" CRLFSTR);
-	scsi_unregister(host);
+      if (check_region (megaBase, 16)) {
+	printk (KERN_WARNING "megaraid: Couldn't register I/O range!" CRLFSTR);
+	scsi_unregister (host);
 	continue;
       }
-      request_region(megaBase, 16, "megaraid");
+      request_region (megaBase, 16, "megaraid");
     }
 
     /* Request our IRQ */
-    if (request_irq(megaIrq, megaraid_isr, SA_SHIRQ, 
-		    "megaraid", megaCfg)) {
-      printk(KERN_WARNING "megaraid: Couldn't register IRQ %d!" CRLFSTR,
-	     megaIrq);
-      scsi_unregister(host);
+    if (request_irq (megaIrq, megaraid_isr, SA_SHIRQ,
+		     "megaraid", megaCfg)) {
+      printk (KERN_WARNING "megaraid: Couldn't register IRQ %d!" CRLFSTR,
+	      megaIrq);
+      scsi_unregister (host);
       continue;
     }
 
-    mega_register_mailbox(megaCfg, virt_to_bus((void*)&megaCfg->mailbox));
-    mega_i_query_adapter(megaCfg);
+    mega_register_mailbox (megaCfg, virt_to_bus ((void *) &megaCfg->mailbox));
+    mega_i_query_adapter (megaCfg);
 
     /* Initialize SCBs */
-    initSCB(megaCfg);
+    if (initSCB (megaCfg)) {
+	scsi_unregister (host);
+	continue;
+    }
 
+    numFound++;
   }
-  return pciIdx;
+  return numFound;
 }
 
 /*---------------------------------------------------------
  * Detects if a megaraid controller exists in this system
  *---------------------------------------------------------*/
-int megaraid_detect(Scsi_Host_Template *pHostTmpl)
+int megaraid_detect (Scsi_Host_Template * pHostTmpl)
 {
   int count = 0;
 
   pHostTmpl->proc_dir = &proc_scsi_megaraid;
 
 #if LINUX_VERSION_CODE < 0x20100
-  if (!pcibios_present()) 
-    {
-      printk(KERN_WARNING "megaraid: PCI bios not present." CRLFSTR);
-      return 0;
-    }
+  if (!pcibios_present ()) {
+    printk (KERN_WARNING "megaraid: PCI bios not present." CRLFSTR);
+    return 0;
+  }
 #endif
 
-  count += findCard(pHostTmpl, 0x101E, 0x9010, 0);
-  count += findCard(pHostTmpl, 0x101E, 0x9060, 0);
-  count += findCard(pHostTmpl, 0x8086, 0x1960, BOARD_QUARTZ);
+  count += findCard (pHostTmpl, 0x101E, 0x9010, 0);
+  count += findCard (pHostTmpl, 0x101E, 0x9060, 0);
+  count += findCard (pHostTmpl, 0x8086, 0x1960, BOARD_QUARTZ);
 
   return count;
 }
@@ -1112,54 +1287,67 @@
 /*---------------------------------------------------------------------
  * Release the controller's resources
  *---------------------------------------------------------------------*/
-int megaraid_release(struct Scsi_Host *pSHost)
+int megaraid_release (struct Scsi_Host *pSHost)
 {
   mega_host_config *megaCfg;
-  mega_mailbox         *mbox;
-  u_char                mboxData[16];
+  mega_mailbox *mbox;
+  u_char mboxData[16];
 
-  megaCfg = (mega_host_config*)pSHost->hostdata;
-  mbox    = (mega_mailbox *)mboxData;
+  megaCfg = (mega_host_config *) pSHost->hostdata;
+  mbox = (mega_mailbox *) mboxData;
 
   /* Flush cache to disk */
-  memset(mbox, 0, 16);
+  memset (mbox, 0, 16);
   mboxData[0] = 0xA;
 
   /* Issue a blocking (interrupts disabled) command to the card */
-  MegaIssueCmd(megaCfg, mboxData, NULL, 0);
+  MegaIssueCmd (megaCfg, mboxData, NULL, 0);
 
-  schedule();
+  schedule ();
 
   /* Free our resources */
   if (megaCfg->flag & BOARD_QUARTZ) {
-      iounmap((void *)megaCfg->base);
-  } else {
-      release_region(megaCfg->host->io_port, 16);
-  }
-  free_irq(megaCfg->host->irq, megaCfg); /* Must be freed first, otherwise
-                                            extra interrupt is generated */
-  scsi_unregister(pSHost);
+    iounmap ((void *) megaCfg->base);
+  }
+  else {
+    release_region (megaCfg->host->io_port, 16);
+  }
+  free_irq (megaCfg->host->irq, megaCfg);	/* Must be freed first, otherwise
+
+						   extra interrupt is generated */
+  freeSgList(megaCfg);
+  scsi_unregister (pSHost);
 
   return 0;
 }
 
+static inline void freeSgList(mega_host_config *megaCfg)
+{
+  int i;
+
+  for (i = 0; i < megaCfg->max_cmds; i++) {
+    if (megaCfg->scbList[i].sgList)
+      kfree (megaCfg->scbList[i].sgList);	/* free sgList */
+  }
+}
+
 /*----------------------------------------------
  * Get information about the card/driver 
  *----------------------------------------------*/
-const char *megaraid_info(struct Scsi_Host *pSHost)
+const char * megaraid_info (struct Scsi_Host *pSHost)
 {
-  static char           buffer[512];
-  mega_host_config  *megaCfg;
-  mega_RAIDINQ          *adapterInfo;
+  static char buffer[512];
+  mega_host_config *megaCfg;
+  mega_RAIDINQ *adapterInfo;
 
-  megaCfg     = (mega_host_config *)pSHost->hostdata;
-  adapterInfo = (mega_RAIDINQ *)megaCfg->mega_buffer;
+  megaCfg = (mega_host_config *) pSHost->hostdata;
+  adapterInfo = (mega_RAIDINQ *) megaCfg->mega_buffer;
 
-  sprintf(buffer, "AMI MegaRAID %s %d commands %d targs %d chans",
-	  megaCfg->fwVer,
-	  adapterInfo->AdpInfo.MaxConcCmds,
-	  megaCfg->host->max_id,
-	  megaCfg->host->max_channel);
+  sprintf (buffer, "AMI MegaRAID %s %d commands %d targs %d chans",
+	   megaCfg->fwVer,
+	   adapterInfo->AdpInfo.MaxConcCmds,
+	   megaCfg->host->max_id,
+	   megaCfg->host->max_channel);
   return buffer;
 }
 
@@ -1178,29 +1366,29 @@
  *   10 01 numstatus byte
  *   11 01 status byte 
  *-----------------------------------------------------------------*/
-int megaraid_queue(Scsi_Cmnd *SCpnt, void (*pktComp)(Scsi_Cmnd *))
+int megaraid_queue (Scsi_Cmnd * SCpnt, void (*pktComp) (Scsi_Cmnd *))
 {
   mega_host_config *megaCfg;
-  mega_scb         *pScb;
+  mega_scb *pScb;
 
-  megaCfg = (mega_host_config *)SCpnt->host->hostdata;
+  megaCfg = (mega_host_config *) SCpnt->host->hostdata;
 
   if (!(megaCfg->flag & (1L << SCpnt->channel))) {
-    printk(KERN_INFO "scsi%d: scanning channel %c for devices.\n",
-	   megaCfg->host->host_no,
-	   SCpnt->channel + 'A');
+    printk (KERN_INFO "scsi%d: scanning channel %c for devices.\n",
+	    megaCfg->host->host_no,
+	    SCpnt->channel + 'A');
     megaCfg->flag |= (1L << SCpnt->channel);
   }
 
   SCpnt->scsi_done = pktComp;
 
   /* Allocate and build a SCB request */
-  if ((pScb = mega_build_cmd(megaCfg, SCpnt)) != NULL) {
+  if ((pScb = mega_build_cmd (megaCfg, SCpnt)) != NULL) {
     /* Add SCB to the head of the pending queue */
-    ENQUEUE(pScb, mega_scb, qPending, next);
+    ENQUEUE (pScb, mega_scb, qPending, next);
 
     /* Issue the command to the card */
-      mega_runque(NULL);
+    mega_runque (NULL);
   }
 
   return 0;
@@ -1208,37 +1396,44 @@
 
 /*----------------------------------------------------------------------
  * Issue a blocking command to the controller
- *
- * Note - this isnt 2.0.x SMP safe
  *----------------------------------------------------------------------*/
-volatile static int internal_done_flag    = 0;
+volatile static int internal_done_flag = 0;
 volatile static int internal_done_errcode = 0;
 
-static void internal_done(Scsi_Cmnd *SCpnt)
+static void internal_done (Scsi_Cmnd * SCpnt)
 {
   internal_done_errcode = SCpnt->result;
   internal_done_flag++;
 }
 
 /*
- *	This seems dangerous in an SMP environment because 
- *	while spinning on internal_done_flag in 2.0.x SMP
- *	no IRQ's will be taken, including those that might
- *	be needed to clear this.
- *
- *	I think this should be using a wait queue ?
- *				-- AC
+ *      This seems dangerous in an SMP environment because
+ *      while spinning on internal_done_flag in 2.0.x SMP
+ *      no IRQ's will be taken, including those that might
+ *      be needed to clear this.
+ *
+ *      I think this should be using a wait queue ?
+ *                              -- AC
+ */      
+
+/*
+ *      I'll probably fix this in the next version, but
+ *      megaraid_command() will never get called since can_queue is set,
+ *      except maybe in a *really* old kernel in which case it's very
+ *      unlikely they'd be using SMP anyway.  Really this function is
+ *      just here for completeness.
+ *                              - JLJ
  */
- 
-int megaraid_command(Scsi_Cmnd *SCpnt)
+
+int megaraid_command (Scsi_Cmnd * SCpnt)
 {
   internal_done_flag = 0;
 
   /* Queue command, and wait until it has completed */
-  megaraid_queue(SCpnt, internal_done);
+  megaraid_queue (SCpnt, internal_done);
 
-  while(!internal_done_flag)
-    barrier();
+  while (!internal_done_flag)
+    barrier ();
 
   return internal_done_errcode;
 }
@@ -1246,67 +1441,67 @@
 /*---------------------------------------------------------------------
  * Abort a previous SCSI request
  *---------------------------------------------------------------------*/
-int megaraid_abort(Scsi_Cmnd *SCpnt)
+int megaraid_abort (Scsi_Cmnd * SCpnt)
 {
   mega_host_config *megaCfg;
-  int       idx;
-  long      flags;
+  int idx;
+  long flags;
 
-  spin_lock_irqsave(&mega_lock,flags);
+  spin_lock_irqsave (&mega_lock, flags);
 
-  megaCfg = (mega_host_config *)SCpnt->host->hostdata;
+  megaCfg = (mega_host_config *) SCpnt->host->hostdata;
 
-  TRACE(("ABORT!!! %.08lx %.02x <%d.%d.%d>\n",
-	 SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target, 
-	 SCpnt->lun));
+  TRACE (("ABORT!!! %.08lx %.02x <%d.%d.%d>\n",
+	SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
+	  SCpnt->lun));
   /*
    * Walk list of SCBs for any that are still outstanding
    */
-  for(idx=0; idx<megaCfg->max_cmds; idx++) {
+  for (idx = 0; idx < megaCfg->max_cmds; idx++) {
     if (megaCfg->scbList[idx].idx >= 0) {
       if (megaCfg->scbList[idx].SCpnt == SCpnt) {
-	freeSCB(&megaCfg->scbList[idx]);
+	freeSCB (&megaCfg->scbList[idx]);
 
-	SCpnt->result = (DID_RESET << 16) | (SUGGEST_RETRY<<24);
-	callDone(SCpnt);
+	SCpnt->result = (DID_RESET << 16) | (SUGGEST_RETRY << 24);
+	callDone (SCpnt);
       }
     }
   }
-  spin_unlock_irqrestore(&mega_lock,flags);
+  spin_unlock_irqrestore (&mega_lock, flags);
   return SCSI_ABORT_SNOOZE;
 }
 
 /*---------------------------------------------------------------------
  * Reset a previous SCSI request
  *---------------------------------------------------------------------*/
-int megaraid_reset(Scsi_Cmnd *SCpnt, unsigned int rstflags)
+int megaraid_reset (Scsi_Cmnd * SCpnt, unsigned int rstflags)
 {
   mega_host_config *megaCfg;
-  int       idx;
-  long      flags;
+  int idx;
+  long flags;
 
-  spin_lock_irqsave(&mega_lock,flags);
+  spin_lock_irqsave (&mega_lock, flags);
 
-  megaCfg = (mega_host_config *)SCpnt->host->hostdata;
+  megaCfg = (mega_host_config *) SCpnt->host->hostdata;
 
-  TRACE(("RESET: %.08lx %.02x <%d.%d.%d>\n",
-	 SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target, 
-	 SCpnt->lun));
+  TRACE (("RESET: %.08lx %.02x <%d.%d.%d>\n",
+	SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
+	  SCpnt->lun));
 
   /*
    * Walk list of SCBs for any that are still outstanding
    */
-  for(idx=0; idx<megaCfg->max_cmds; idx++) {
+  for (idx = 0; idx < megaCfg->max_cmds; idx++) {
     if (megaCfg->scbList[idx].idx >= 0) {
       SCpnt = megaCfg->scbList[idx].SCpnt;
-      freeSCB(&megaCfg->scbList[idx]);
-      SCpnt->result = (DID_RESET << 16) | (SUGGEST_RETRY<<24);
-      callDone(SCpnt);
+      freeSCB (&megaCfg->scbList[idx]);
+      SCpnt->result = (DID_RESET << 16) | (SUGGEST_RETRY << 24);
+      callDone (SCpnt);
     }
   }
-  spin_unlock_irqrestore(&mega_lock,flags);
+  spin_unlock_irqrestore (&mega_lock, flags);
   return SCSI_RESET_PUNT;
-} 
+}
 
 /*-------------------------------------------------------------
  * Return the disk geometry for a particular disk
@@ -1318,23 +1513,23 @@
  *     geom[1] = sectors
  *     geom[2] = cylinders
  *-------------------------------------------------------------*/
-int megaraid_biosparam(Disk *disk, kdev_t dev, int *geom)
+int megaraid_biosparam (Disk * disk, kdev_t dev, int *geom)
 {
-  int                   heads, sectors, cylinders;
+  int heads, sectors, cylinders;
   mega_host_config *megaCfg;
 
   /* Get pointer to host config structure */
-  megaCfg = (mega_host_config *)disk->device->host->hostdata;
+  megaCfg = (mega_host_config *) disk->device->host->hostdata;
 
   /* Default heads (64) & sectors (32) */
-  heads     = 64;
-  sectors   = 32;
+  heads = 64;
+  sectors = 32;
   cylinders = disk->capacity / (heads * sectors);
 
   /* Handle extended translation size for logical drives > 1Gb */
   if (disk->capacity >= 0x200000) {
-    heads     = 255;
-    sectors   = 63;
+    heads = 255;
+    sectors = 63;
     cylinders = disk->capacity / (heads * sectors);
   }
 
diff -u --recursive --new-file v2.2.2/linux/drivers/scsi/megaraid.h linux/drivers/scsi/megaraid.h
--- v2.2.2/linux/drivers/scsi/megaraid.h	Mon Jan 25 17:44:34 1999
+++ linux/drivers/scsi/megaraid.h	Mon Mar  8 15:52:17 1999
@@ -1,7 +1,12 @@
 #ifndef __MEGARAID_H__
 #define __MEGARAID_H__
 
+#ifndef LINUX_VERSION_CODE
 #include <linux/version.h>
+#endif
+
+#define MULTI_IO 0    /* change to 1 for fully parallel I/O to adapter */
+                      /* works on some systems, not on others yet */
 
 #define IN_ISR                  0x80000000L
 #define NO_INTR                 0x40000000L
@@ -20,7 +25,7 @@
 
 #define MEGA_CMD_TIMEOUT        10
 
-#define MAX_SGLIST              20
+#define MAX_SGLIST              17
 #define MAX_COMMANDS            254
 
 #define MAX_LOGICAL_DRIVES      8
@@ -56,7 +61,7 @@
 #define I_TOGGLE_PORT      0x01
 #define INTR_PORT          0x0a
 
-#define MAILBOX_SIZE       70
+#define MAILBOX_SIZE       (sizeof(mega_mailbox)-16)
 #define MBOX_BUSY_PORT     0x00
 #define MBOX_PORT0         0x04
 #define MBOX_PORT1         0x05
@@ -96,6 +101,8 @@
 
 #define PCI_CONF_BASE_ADDR_OFFSET  0x10
 #define PCI_CONF_IRQ_OFFSET        0x3c
+#define PCI_CONF_AMISIG            0xa0
+#define AMI_SIGNATURE              0x11223344
 
 #if LINUX_VERSION_CODE < 0x20100
 #define MEGARAID \
@@ -113,14 +120,14 @@
     megaraid_reset,                     /* Reset Command Function    */\
     NULL,                               /* Slave Attach Function     */\
     megaraid_biosparam,                 /* Disk BIOS Parameters      */\
-    1,                                  /* # of cmds that can be\
+    254,                                /* # of cmds that can be\
                                            outstanding at any time */\
     7,                                  /* HBA Target ID             */\
     MAX_SGLIST,                         /* Scatter/Gather Table Size */\
-    1,                                  /* SCSI Commands per LUN     */\
+    64,                                 /* SCSI Commands per LUN     */\
     0,                                  /* Present                   */\
     0,                                  /* Default Unchecked ISA DMA */\
-    ENABLE_CLUSTERING }                 /* Enable Clustering         */
+    ENABLE_CLUSTERING }		/* Enable Clustering         */
 #else
 #define MEGARAID \
   {\
@@ -134,10 +141,10 @@
     abort:            megaraid_abort,          /* Abort Command Function    */\
     reset:            megaraid_reset,          /* Reset Command Function    */\
     bios_param:       megaraid_biosparam,      /* Disk BIOS Parameters      */\
-    can_queue:        255,                     /* Can Queue                 */\
+    can_queue:        1 /* MAX_COMMANDS */,            /* Can Queue                 */\
     this_id:          7,                       /* HBA Target ID             */\
     sg_tablesize:     MAX_SGLIST,              /* Scatter/Gather Table Size */\
-    cmd_per_lun:      1,                       /* SCSI Commands per LUN     */\
+    cmd_per_lun:      64,                      /* SCSI Commands per LUN     */\
     present:          0,                       /* Present                   */\
     unchecked_isa_dma:0,                       /* Default Unchecked ISA DMA */\
     use_clustering:   ENABLE_CLUSTERING       /* Enable Clustering         */\
@@ -145,140 +152,150 @@
 #endif
 
 /* Structures */
-typedef struct _mega_ADP_INFO
-{
-  u_char    MaxConcCmds;
-  u_char    RbldRate;
-  u_char    MaxTargPerChan;
-  u_char    ChanPresent;
-  u_char    FwVer[4];
-  u_short   AgeOfFlash;
-  u_char    ChipSet;
-  u_char    DRAMSize;
-  u_char    CacheFlushInterval;
-  u_char    BiosVer[4];
-  u_char    resvd[7];
+typedef struct _mega_ADP_INFO {
+    u_char MaxConcCmds;
+    u_char RbldRate;
+    u_char MaxTargPerChan;
+    u_char ChanPresent;
+    u_char FwVer[4];
+    u_short AgeOfFlash;
+    u_char ChipSet;
+    u_char DRAMSize;
+    u_char CacheFlushInterval;
+    u_char BiosVer[4];
+    u_char resvd[7];
 } mega_ADP_INFO;
 
-typedef struct _mega_LDRV_INFO
-{
-  u_char   NumLDrv;
-  u_char   resvd[3];
-  u_long   LDrvSize[MAX_LOGICAL_DRIVES];
-  u_char   LDrvProp[MAX_LOGICAL_DRIVES];
-  u_char   LDrvState[MAX_LOGICAL_DRIVES];
+typedef struct _mega_LDRV_INFO {
+    u_char NumLDrv;
+    u_char resvd[3];
+    u_long LDrvSize[MAX_LOGICAL_DRIVES];
+    u_char LDrvProp[MAX_LOGICAL_DRIVES];
+    u_char LDrvState[MAX_LOGICAL_DRIVES];
 } mega_LDRV_INFO;
 
-typedef struct _mega_PDRV_INFO
-{
-  u_char   PDrvState[MAX_PHYSICAL_DRIVES];
-  u_char   resvd;
+typedef struct _mega_PDRV_INFO {
+    u_char PDrvState[MAX_PHYSICAL_DRIVES];
+    u_char resvd;
 } mega_PDRV_INFO;
 
 // RAID inquiry: Mailbox command 0x5
-typedef struct _mega_RAIDINQ
-{
-  mega_ADP_INFO    AdpInfo;
-  mega_LDRV_INFO   LogdrvInfo;
-  mega_PDRV_INFO   PhysdrvInfo;
+typedef struct _mega_RAIDINQ {
+    mega_ADP_INFO AdpInfo;
+    mega_LDRV_INFO LogdrvInfo;
+    mega_PDRV_INFO PhysdrvInfo;
 } mega_RAIDINQ;
 
 // Passthrough command: Mailbox command 0x3
-typedef struct mega_passthru
-{
-  u_char            timeout:3;              /* 0=6sec/1=60sec/2=10min/3=3hrs */
-  u_char            ars:1;
-  u_char            reserved:3;
-  u_char            islogical:1;
-  u_char            logdrv;                 /* if islogical == 1 */
-  u_char            channel;                /* if islogical == 0 */
-  u_char            target;                 /* if islogical == 0 */
-  u_char            queuetag;               /* unused */
-  u_char            queueaction;            /* unused */
-  u_char            cdb[MAX_CDB_LEN];
-  u_char            cdblen;
-  u_char            reqsenselen;
-  u_char            reqsensearea[MAX_REQ_SENSE_LEN];
-  u_char            numsgelements;
-  u_char            scsistatus;
-  u_long            dataxferaddr;
-  u_long            dataxferlen;
+typedef struct mega_passthru {
+    u_char timeout:3;		/* 0=6sec/1=60sec/2=10min/3=3hrs */
+    u_char ars:1;
+    u_char reserved:3;
+    u_char islogical:1;
+    u_char logdrv;		/* if islogical == 1 */
+    u_char channel;		/* if islogical == 0 */
+    u_char target;		/* if islogical == 0 */
+    u_char queuetag;		/* unused */
+    u_char queueaction;		/* unused */
+    u_char cdb[MAX_CDB_LEN];
+    u_char cdblen;
+    u_char reqsenselen;
+    u_char reqsensearea[MAX_REQ_SENSE_LEN];
+    u_char numsgelements;
+    u_char scsistatus;
+    u_long dataxferaddr;
+    u_long dataxferlen;
 } mega_passthru;
 
-typedef struct _mega_mailbox
-{
-  /* 0x0 */ u_char    cmd;
-  /* 0x1 */ u_char    cmdid;
-  /* 0x2 */ u_short   numsectors;
-  /* 0x4 */ u_long    lba;
-  /* 0x8 */ u_long    xferaddr;
-  /* 0xC */ u_char    logdrv;
-  /* 0xD */ u_char    numsgelements;
-  /* 0xE */ u_char    resvd;
-  /* 0xF */ u_char    busy;
-  /* 0x10*/ u_char    numstatus;
-  /* 0x11*/ u_char    status;
-  /* 0x12*/ u_char    completed[46];
-            u_char    mraid_poll;
-            u_char    mraid_ack;
-            u_char    pad[16];
+typedef struct _mega_mailbox {
+    /* 0x0 */ u_char cmd;
+    /* 0x1 */ u_char cmdid;
+    /* 0x2 */ u_short numsectors;
+    /* 0x4 */ u_long lba;
+    /* 0x8 */ u_long xferaddr;
+    /* 0xC */ u_char logdrv;
+    /* 0xD */ u_char numsgelements;
+    /* 0xE */ u_char resvd;
+    /* 0xF */ u_char busy;
+    /* 0x10 */ u_char numstatus;
+    /* 0x11 */ u_char status;
+    /* 0x12 */ u_char completed[46];
+    u_char mraid_poll;
+    u_char mraid_ack;
+    u_char pad[16];
 } mega_mailbox;
 
-typedef struct _mega_sglist
-{
-  u_long     address;
-  u_long     length;
+typedef struct _mega_ioctl_mbox {
+    /* 0x0 */ u_char cmd;
+    /* 0x1 */ u_char cmdid;
+    /* 0x2 */ u_char channel;
+    /* 0x3 */ u_char param;
+    /* 0x4 */ u_char pad[4];
+    /* 0x8 */ u_long xferaddr;
+    /* 0xC */ u_char logdrv;
+    /* 0xD */ u_char numsgelements;
+    /* 0xE */ u_char resvd;
+    /* 0xF */ u_char busy;
+    /* 0x10 */ u_char numstatus;
+    /* 0x11 */ u_char status;
+    /* 0x12 */ u_char completed[46];
+    u_char mraid_poll;
+    u_char mraid_ack;
+    u_char malign[16];
+} mega_ioctl_mbox;
+
+typedef struct _mega_sglist {
+    u_long address;
+    u_long length;
 } mega_sglist;
 
 /* Queued command data */
 typedef struct _mega_scb mega_scb;
 
-struct _mega_scb
-{
-  int             idx;
-  u_long          flag;
-  Scsi_Cmnd      *SCpnt;
-  u_char          mboxData[16];
-  mega_passthru   pthru;
-  mega_sglist    *sgList;
-  mega_scb       *next;
+struct _mega_scb {
+    int idx;
+    u_long flag;
+    Scsi_Cmnd *SCpnt;
+    u_char mboxData[16];
+    mega_passthru pthru;
+    mega_sglist *sgList;
+    mega_scb *next;
 };
 
 /* Per-controller data */
-typedef struct _mega_host_config
-{
-  u_char               numldrv;
-  u_long               flag;
-  u_long               base;
-
-  struct tq_struct     megaTq;
-
-  /* Host adapter parameters */
-  u_char               fwVer[7];
-  u_char               biosVer[7];
-
-  struct Scsi_Host     *host;
-
-  /* The following must be DMA-able!! */
-  volatile mega_mailbox *mbox;
-  volatile mega_mailbox mailbox;
-  volatile u_char       mega_buffer[2*1024L];
+typedef struct _mega_host_config {
+    u_char numldrv;
+    u_long flag;
+    u_long base;
+
+    struct tq_struct megaTq;
+
+    /* Host adapter parameters */
+    u_char fwVer[7];
+    u_char biosVer[7];
+
+    struct Scsi_Host *host;
+
+    /* The following must be DMA-able!! */
+    volatile mega_mailbox *mbox;
+    volatile mega_mailbox mailbox;
+    volatile u_char mega_buffer[2 * 1024L];
 
-  u_char                max_cmds;
-  mega_scb              scbList[MAX_COMMANDS];
+    u_char max_cmds;
+    mega_scb scbList[MAX_COMMANDS];
 } mega_host_config;
 
 extern struct proc_dir_entry proc_scsi_megaraid;
 
-const char *megaraid_info( struct Scsi_Host * );
-int        megaraid_detect( Scsi_Host_Template * );
-int        megaraid_release(struct Scsi_Host *);
-int        megaraid_command( Scsi_Cmnd * );
-int        megaraid_abort( Scsi_Cmnd * );
-int        megaraid_reset( Scsi_Cmnd *, unsigned int); 
-int        megaraid_queue( Scsi_Cmnd *, void (*done)(Scsi_Cmnd *) );
-int        megaraid_biosparam( Disk *, kdev_t, int * );
-int        megaraid_proc_info( char *buffer, char **start, off_t offset,
-			       int length, int hostno, int inout );
+const char *megaraid_info(struct Scsi_Host *);
+int megaraid_detect(Scsi_Host_Template *);
+int megaraid_release(struct Scsi_Host *);
+int megaraid_command(Scsi_Cmnd *);
+int megaraid_abort(Scsi_Cmnd *);
+int megaraid_reset(Scsi_Cmnd *, unsigned int);
+int megaraid_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
+int megaraid_biosparam(Disk *, kdev_t, int *);
+int megaraid_proc_info(char *buffer, char **start, off_t offset,
+		       int length, int hostno, int inout);
 
 #endif
diff -u --recursive --new-file v2.2.2/linux/drivers/scsi/ncr53c8xx.c linux/drivers/scsi/ncr53c8xx.c
--- v2.2.2/linux/drivers/scsi/ncr53c8xx.c	Tue Feb 23 15:21:33 1999
+++ linux/drivers/scsi/ncr53c8xx.c	Sun Mar  7 10:13:23 1999
@@ -73,7 +73,7 @@
 */
 
 /*
-**	January 16 1998, version 3.1f
+**	March 6 1999, version 3.1h
 **
 **	Supported SCSI-II features:
 **	    Synchronous negotiation
@@ -2081,6 +2081,7 @@
 	ncrcmd  msg_ext_3	[ 10];
 	ncrcmd	msg_sdtr	[ 14];
 	ncrcmd	send_sdtr	[  7];
+	ncrcmd	nego_bad_phase	[  4];
 	ncrcmd	msg_out_abort	[ 10];
 	ncrcmd  hdata_in	[MAX_SCATTERH * 4];
 	ncrcmd  hdata_in2	[  2];
@@ -3185,16 +3186,15 @@
 	/*
 	**	If a negotiation was in progress,
 	**	negotiation failed.
+	**	Otherwise, let the C code print 
+	**	some message.
 	*/
 	SCR_FROM_REG (HS_REG),
 		0,
-	SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)),
-		SIR_NEGO_FAILED,
-	/*
-	**	else make host log this message
-	*/
 	SCR_INT ^ IFFALSE (DATA (HS_NEGOTIATE)),
 		SIR_REJECT_RECEIVED,
+	SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)),
+		SIR_NEGO_FAILED,
 	SCR_JUMP,
 		PADDR (clrack),
 
@@ -3304,10 +3304,9 @@
 		0,
 	SCR_CLR (SCR_ACK),
 		0,
+	SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)),
+		PADDRH (nego_bad_phase),
 
-/* CHECK THE SOURCE FOR 'send_wdtr' IF YOU INTEND TO CHANGE SOMETHING HERE */
-	SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)),
-		SIR_NEGO_PROTO,
 }/*-------------------------< SEND_WDTR >----------------*/,{
 	/*
 	**	Send the M_X_WIDE_REQ
@@ -3360,10 +3359,9 @@
 		0,
 	SCR_CLR (SCR_ACK),
 		0,
+	SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)),
+		PADDRH (nego_bad_phase),
 
-/* CHECK THE SOURCE FOR 'send_sdtr' IF YOU INTEND TO CHANGE SOMETHING HERE */
-	SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)),
-		SIR_NEGO_PROTO,
 }/*-------------------------< SEND_SDTR >-------------*/,{
 	/*
 	**	Send the M_X_SYNC_REQ
@@ -3376,6 +3374,12 @@
 	SCR_JUMP,
 		PADDR (msg_out_done),
 
+}/*-------------------------< NEGO_BAD_PHASE >------------*/,{
+	SCR_INT,
+		SIR_NEGO_PROTO,
+	SCR_JUMP,
+		PADDR (dispatch),
+
 }/*-------------------------< MSG_OUT_ABORT >-------------*/,{
 	/*
 	**	After ABORT message,
@@ -4274,7 +4278,7 @@
 	/*
 	**	Set irq mode.
 	*/
-	switch(driver_setup.irqm) {
+	switch(driver_setup.irqm & 3) {
 	case 2:
 		np->rv_dcntl	|= IRQM;
 		break;
@@ -4665,21 +4669,11 @@
 	/*
 	**	Install the interrupt handler.
 	*/
-#ifdef	SCSI_NCR_SHARE_IRQ
-#define	NCR_SA_INTERRUPT_FLAGS (SA_INTERRUPT | SA_SHIRQ)
-	if (bootverbose > 1)
-#ifdef __sparc__
-		printk(KERN_INFO "%s: requesting shared irq %s (dev_id=0x%lx)\n",
-		        ncr_name(np), __irq_itoa(device->slot.irq), (u_long) np);
-#else
-		printk(KERN_INFO "%s: requesting shared irq %d (dev_id=0x%lx)\n",
-		        ncr_name(np), device->slot.irq, (u_long) np);
-#endif
-#else
-#define	NCR_SA_INTERRUPT_FLAGS SA_INTERRUPT
-#endif
+
 	if (request_irq(device->slot.irq, ncr53c8xx_intr,
-			NCR_SA_INTERRUPT_FLAGS, "ncr53c8xx", np)) {
+			((driver_setup.irqm & 0x10) ? 0 : SA_SHIRQ) |
+			((driver_setup.irqm & 0x20) ? 0 : SA_INTERRUPT),
+			"ncr53c8xx", np)) {
 #ifdef __sparc__
 		printk(KERN_ERR "%s: request irq %s failure\n",
 			ncr_name(np), __irq_itoa(device->slot.irq));
@@ -4689,6 +4683,7 @@
 #endif
 		goto attach_error;
 	}
+
 	np->irq = device->slot.irq;
 
 	/*
@@ -4956,9 +4951,8 @@
 				nego = NS_SYNC;
 			} else {
 				tp->period  =0xffff;
-				tp->sval = 0xe0;
 				PRINT_TARGET(np, cmd->target);
-				printk ("SYNC transfers not supported.\n");
+				printk ("device did not report SYNC.\n");
 			};
 		};
 
@@ -5824,7 +5818,7 @@
 		**	announced capabilities (we need the 1rst 7 bytes).
 		*/
 		if (cmd->cmnd[0] == 0x12 && !(cmd->cmnd[1] & 0x3) &&
-		    cmd->cmnd[4] >= 7) {
+		    cmd->cmnd[4] >= 7 && !cmd->use_sg) {
 			ncr_setup_lcb (np, cmd->target, cmd->lun,
 				       (char *) cmd->request_buffer);
 		}
@@ -7051,7 +7045,7 @@
 	OUTONB (nc_ctest3, CLF);
 
 	if ((sist & (SGE)) ||
-		(dstat & (MDPE|BF|ABORT|IID))) {
+		(dstat & (MDPE|BF|ABRT|IID))) {
 		ncr_start_reset(np);
 		return;
 	};
@@ -7528,7 +7522,7 @@
 		}
 		else if	(dsp == NCB_SCRIPTH_PHYS (np, send_wdtr) ||
 			 dsp == NCB_SCRIPTH_PHYS (np, send_sdtr)) {
-			nxtdsp = dsp - 8; /* Should raise SIR_NEGO_PROTO */
+			nxtdsp = NCB_SCRIPTH_PHYS (np, nego_bad_phase);
 		}
 		break;
 #if 0
@@ -7882,9 +7876,7 @@
 		np->msgin [0] = M_NOOP;
 		np->msgout[0] = M_NOOP;
 		cp->nego_status = 0;
-		OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, dispatch));
-		return;
-/*		break;	*/
+		break;
 
 	case SIR_NEGO_SYNC:
 		/*
@@ -8657,10 +8649,15 @@
 	**	Evaluate trustable target/unit capabilities.
 	**	We only believe device version >= SCSI-2 that 
 	**	use appropriate response data format (2).
+	**	But it seems that some CCS devices also 
+	**	support SYNC and I donnot want to frustrate 
+	**	anybody. ;-)
 	*/
 	inq_byte7 = 0;
-	if ((inq_data[2] & 0x7) >= 2 && (inq_data[3] & 0xf) == 2)
+	if	((inq_data[2] & 0x7) >= 2 && (inq_data[3] & 0xf) == 2)
 		inq_byte7 = inq_data[7];
+	else if ((inq_data[2] & 0x7) == 1 && (inq_data[3] & 0xf) == 1)
+		inq_byte7 = INQ7_SYNC;
 
 	/*
 	**	Throw away announced LUN capabilities if we are told 
@@ -9586,6 +9583,50 @@
 }
 
 /*
+**   Generically read a base address from the PCI configuration space.
+**   Return the offset immediately after the base address that has 
+**   been read. Btw, we blindly assume that the high 32 bits of 64 bit 
+**   base addresses are set to zero on 32 bit architectures.
+**
+*/
+#if LINUX_VERSION_CODE <= LinuxVersionCode(2,1,92)
+__initfunc(
+static int 
+pci_read_base_address(u_char bus, u_char device_fn, int offset, u_long *base)
+)
+{
+	u_int32 tmp;
+
+	pcibios_read_config_dword(bus, device_fn, offset, &tmp);
+	*base = tmp;
+	offset += sizeof(u_int32);
+	if ((tmp & 0x7) == 0x4) {
+#if BITS_PER_LONG > 32
+		pcibios_read_config_dword(bus, device_fn, offset, &tmp);
+		*base |= (((u_long)tmp) << 32);
+#endif
+		offset += sizeof(u_int32);
+	}
+	return offset;
+}
+#else	/* LINUX_VERSION_CODE > LinuxVersionCode(2,1,92) */
+__initfunc(
+static int 
+pci_get_base_address(struct pci_dev *pdev, int index, u_long *base)
+)
+{
+	*base = pdev->base_address[index++];
+	if ((*base & 0x7) == 0x4) {
+#if BITS_PER_LONG > 32
+		*base |= (((u_long)pdev->base_address[index]) << 32);
+#endif
+		++index;
+	}
+	return index;
+}
+#endif
+
+/*
 **   Read and check the PCI configuration for any detected NCR 
 **   boards and save data for attaching after all boards have 
 **   been detected.
@@ -9601,61 +9642,46 @@
 	uchar revision;
 #if LINUX_VERSION_CODE > LinuxVersionCode(2,1,92)
 	struct pci_dev *pdev;
-	ulong base, base_2, io_port; 
 	uint irq;
 #else
 	uchar irq;
-	uint base, base_2, io_port; 
 #endif
+	ulong base, base_2, io_port; 
 	int i;
-
 #ifdef SCSI_NCR_NVRAM_SUPPORT
 	ncr_nvram *nvram = device->nvram;
 #endif
 	ncr_chip *chip;
 
 	/*
-	 * Read info from the PCI config space.
-	 * pcibios_read_config_xxx() functions are assumed to be used for 
-	 * successfully detected PCI devices.
-	 * Expecting error conditions from them is just paranoia,
-	 * thus void cast.
-	 */
-	(void) pcibios_read_config_word(bus, device_fn,
-					PCI_VENDOR_ID, &vendor_id);
-	(void) pcibios_read_config_word(bus, device_fn,
-					PCI_DEVICE_ID, &device_id);
-	(void) pcibios_read_config_word(bus, device_fn,
-					PCI_COMMAND, &command);
+	**    Read info from the PCI config space.
+	**    pcibios_read_config_xxx() functions are assumed to be used for 
+	**    successfully detected PCI devices.
+	*/
 #if LINUX_VERSION_CODE > LinuxVersionCode(2,1,92)
 	pdev = pci_find_slot(bus, device_fn);
-	io_port = pdev->base_address[0];
-	base = pdev->base_address[1];
-	base_2 = pdev->base_address[2];
+	vendor_id = pdev->vendor;
+	device_id = pdev->device;
 	irq = pdev->irq;
-	if ((base & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64)
-		base_2 = pdev->base_address[3];
+	i =	0;
+	i =	pci_get_base_address(pdev, i, &io_port);
+	i =	pci_get_base_address(pdev, i, &base);
+	(void)	pci_get_base_address(pdev, i, &base_2);
 #else
-	(void) pcibios_read_config_dword(bus, device_fn,
-					PCI_BASE_ADDRESS_0, &io_port);	
-	(void) pcibios_read_config_dword(bus, device_fn,
-					PCI_BASE_ADDRESS_1, &base);
-	(void) pcibios_read_config_dword(bus, device_fn,
-					PCI_BASE_ADDRESS_2, &base_2);
-
-	/* Handle 64bit base addresses for 53C896. */
-	if ((base & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64)
-		(void) pcibios_read_config_dword(bus, device_fn,
-						 PCI_BASE_ADDRESS_3, &base_2);
-	(void) pcibios_read_config_byte(bus, device_fn,
-					PCI_INTERRUPT_LINE, &irq);
-#endif
-	(void) pcibios_read_config_byte(bus, device_fn,
-					PCI_CLASS_REVISION,&revision);	
-	(void) pcibios_read_config_byte(bus, device_fn,
-					PCI_CACHE_LINE_SIZE, &cache_line_size);
-	(void) pcibios_read_config_byte(bus, device_fn,
-					PCI_LATENCY_TIMER, &latency_timer);
+	pcibios_read_config_word(bus, device_fn, PCI_VENDOR_ID, &vendor_id);
+	pcibios_read_config_word(bus, device_fn, PCI_DEVICE_ID, &device_id);
+	pcibios_read_config_byte(bus, device_fn, PCI_INTERRUPT_LINE, &irq);
+	i =	PCI_BASE_ADDRESS_0;
+	i =	pci_read_base_address(bus, device_fn, i, &io_port);
+	i =	pci_read_base_address(bus, device_fn, i, &base);
+	(void)	pci_read_base_address(bus, device_fn, i, &base_2);
+#endif
+	pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command);
+	pcibios_read_config_byte(bus, device_fn, PCI_CLASS_REVISION, &revision);
+	pcibios_read_config_byte(bus, device_fn, PCI_CACHE_LINE_SIZE,
+				 &cache_line_size);
+	pcibios_read_config_byte(bus, device_fn, PCI_LATENCY_TIMER,
+				 &latency_timer);
 
 	/*
 	 *	Check if the chip is supported
diff -u --recursive --new-file v2.2.2/linux/drivers/scsi/ncr53c8xx.h linux/drivers/scsi/ncr53c8xx.h
--- v2.2.2/linux/drivers/scsi/ncr53c8xx.h	Tue Jan 19 11:32:51 1999
+++ linux/drivers/scsi/ncr53c8xx.h	Mon Mar  8 15:52:15 1999
@@ -45,7 +45,7 @@
 /*
 **	Name and revision of the driver
 */
-#define SCSI_NCR_DRIVER_NAME		"ncr53c8xx - revision 3.1f"
+#define SCSI_NCR_DRIVER_NAME		"ncr53c8xx - revision 3.1h"
 
 /*
 **	Check supported Linux versions
@@ -69,7 +69,6 @@
 **	These options are not tunable from 'make config'
 */
 #define	SCSI_NCR_PROC_INFO_SUPPORT
-#define SCSI_NCR_SHARE_IRQ
 
 /*
 **	If you want a driver as small as possible, donnot define the 
diff -u --recursive --new-file v2.2.2/linux/drivers/scsi/qlogicfc.c linux/drivers/scsi/qlogicfc.c
--- v2.2.2/linux/drivers/scsi/qlogicfc.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/qlogicfc.c	Wed Feb 24 16:27:54 1999
@@ -0,0 +1,1937 @@
+/*
+ * QLogic ISP2100 SCSI-FCP
+ * Written by Erik H. Moe, ehm@cris.com
+ * Copyright 1995, Erik H. Moe
+ *
+ * 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.
+ */
+
+/* Renamed and updated to 1.3.x by Michael Griffith <grif@cs.ucr.edu> */
+
+/* This is a version of the isp1020 driver which was modified by
+ * Chris Loveland <cwl@iol.unh.edu> to support the isp2100
+ */
+
+/*
+ * $Date: 1995/09/22 02:23:15 $
+ * $Revision: 0.5 $
+ *
+ * $Log: isp1020.c,v $
+ * Revision 0.5  1995/09/22  02:23:15  root
+ * do auto request sense
+ *
+ * Revision 0.4  1995/08/07  04:44:33  root
+ * supply firmware with driver.
+ * numerous bug fixes/general cleanup of code.
+ *
+ * Revision 0.3  1995/07/16  16:15:39  root
+ * added reset/abort code.
+ *
+ * Revision 0.2  1995/06/29  03:14:19  root
+ * fixed biosparam.
+ * added queue protocol.
+ *
+ * Revision 0.1  1995/06/25  01:55:45  root
+ * Initial release.
+ *
+ */
+
+#include <linux/blk.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/unistd.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/spinlock.h>
+
+#include "sd.h"
+#include "hosts.h"
+#include "qlogicfc.h"
+
+/* Configuration section **************************************************** */
+
+/* Set the following macro to 1 to reload the ISP2100's firmware.  This is
+   version 1.13 of the firmware. */
+
+#define RELOAD_FIRMWARE		1
+
+#define USE_NVRAM_DEFAULTS      1
+
+
+/* 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 ISP2100_FABRIC          0
+
+/*  Macros used for debugging */
+/*
+#define DEBUG_ISP2100		1
+#define DEBUG_ISP2100_INT	1
+#define DEBUG_ISP2100_INTR	1
+#define DEBUG_ISP2100_SETUP	1
+
+#define DEBUG_ISP2100_FABRIC    1
+*/
+/* #define TRACE_ISP             1 */
+
+
+#define DEFAULT_LOOP_COUNT	10000000
+
+/* End Configuration section ************************************************ */
+
+#include <linux/module.h>
+
+#if TRACE_ISP
+
+#define TRACE_BUF_LEN	(32*1024)
+
+struct {
+	u_long next;
+	struct {
+		u_long time;
+		u_int index;
+		u_int addr;
+		u_char *name;
+	} buf[TRACE_BUF_LEN];
+} trace;
+
+#define TRACE(w, i, a)						\
+{								\
+	unsigned long flags;					\
+								\
+	save_flags(flags);					\
+	cli();							\
+	trace.buf[trace.next].name  = (w);			\
+	trace.buf[trace.next].time  = jiffies;			\
+	trace.buf[trace.next].index = (i);			\
+	trace.buf[trace.next].addr  = (long) (a);		\
+	trace.next = (trace.next + 1) & (TRACE_BUF_LEN - 1);	\
+	restore_flags(flags);					\
+}
+
+#else
+#define TRACE(w, i, a)
+#endif
+
+#if DEBUG_ISP2100_FABRIC
+#define DEBUG_FABRIC(x)	x
+#else
+#define DEBUG_FABRIC(x)
+#endif				/* DEBUG_ISP2100_FABRIC */
+
+
+#if DEBUG_ISP2100
+#define ENTER(x)	printk("isp2100 : entering %s()\n", x);
+#define LEAVE(x)	printk("isp2100 : leaving %s()\n", x);
+#define DEBUG(x)	x
+#else
+#define ENTER(x)
+#define LEAVE(x)
+#define DEBUG(x)
+#endif				/* DEBUG_ISP2100 */
+
+#if DEBUG_ISP2100_INTR
+#define ENTER_INTR(x)	printk("isp2100 : entering %s()\n", x);
+#define LEAVE_INTR(x)	printk("isp2100 : leaving %s()\n", x);
+#define DEBUG_INTR(x)	x
+#else
+#define ENTER_INTR(x)
+#define LEAVE_INTR(x)
+#define DEBUG_INTR(x)
+#endif				/* DEBUG ISP2100_INTR */
+
+
+#if defined(__i386__)
+#define virt_to_bus_low32(x)   virt_to_bus(x)
+#define virt_to_bus_high32(x)  0x0
+#define bus_to_virt_low32(x)   bus_to_virt(x)
+#define bus_to_virt_high32(x)  0x0
+#elif defined(__alpha__)
+#define virt_to_bus_low32(x)   ((u32) (0xffffffff & virt_to_bus(x)))
+#define virt_to_bus_high32(x)  ((u32) (0xffffffff & (virt_to_bus(x)>>32)))
+#define bus_to_virt_low32(x)   ((u32) (0xffffffff & bus_to_virt(x)))
+#define bus_to_virt_high32(x)  ((u32) (0xffffffff & (bus_to_virt(x)>>32)))
+#endif
+
+#define ISP2100_REV_ID	1
+#define ISP2100_REV_ID3        3
+
+#define MAX_TARGETS	16
+#define MAX_LUNS	8
+
+/* host configuration and control registers */
+#define HOST_HCCR	0xc0	/* host command and control */
+
+/* pci bus interface registers */
+#define FLASH_BIOS_ADDR	0x00
+#define FLASH_BIOS_DATA	0x02
+#define ISP_CTRL_STATUS	0x06	/* configuration register #1 */
+#define PCI_INTER_CTL	0x08	/* pci interupt control */
+#define PCI_INTER_STS	0x0a	/* pci interupt status */
+#define PCI_SEMAPHORE	0x0c	/* pci semaphore */
+#define PCI_NVRAM	0x0e	/* pci nvram interface */
+
+/* mailbox registers */
+#define MBOX0		0x10	/* mailbox 0 */
+#define MBOX1		0x12	/* mailbox 1 */
+#define MBOX2		0x14	/* mailbox 2 */
+#define MBOX3		0x16	/* mailbox 3 */
+#define MBOX4		0x18	/* mailbox 4 */
+#define MBOX5		0x1a	/* mailbox 5 */
+#define MBOX6		0x1c	/* mailbox 6 */
+#define MBOX7		0x1e	/* mailbox 7 */
+
+/* mailbox command complete status codes */
+#define MBOX_COMMAND_COMPLETE		0x4000
+#define INVALID_COMMAND			0x4001
+#define HOST_INTERFACE_ERROR		0x4002
+#define TEST_FAILED			0x4003
+#define COMMAND_ERROR			0x4005
+#define COMMAND_PARAM_ERROR		0x4006
+#define PORT_ID_USED                    0x4007
+#define LOOP_ID_USED                    0x4008
+#define ALL_IDS_USED                    0x4009
+
+/* async event status codes */
+#define RESET_DETECTED  		0x8001
+#define SYSTEM_ERROR			0x8002
+#define REQUEST_TRANSFER_ERROR		0x8003
+#define RESPONSE_TRANSFER_ERROR		0x8004
+#define REQUEST_QUEUE_WAKEUP		0x8005
+#define LIP_OCCURED                     0x8010
+#define LOOP_UP                         0x8011
+#define LOOP_DOWN                       0x8012
+#define LIP_RECEIVED                    0x8013
+#define PORT_DB_CHANGED                 0x8014
+#define CHANGE_NOTIFICATION             0x8015
+#define SCSI_COMMAND_COMPLETE           0x8020
+
+struct Entry_header {
+	u_char entry_type;
+	u_char entry_cnt;
+	u_char sys_def_1;
+	u_char flags;
+};
+
+/* entry header type commands */
+#define ENTRY_COMMAND		0x19
+#define ENTRY_CONTINUATION	0x0a
+#define ENTRY_STATUS		0x03
+#define ENTRY_MARKER		0x04
+
+/* entry header flag definitions */
+#define EFLAG_BUSY		2
+#define EFLAG_BAD_HEADER	4
+#define EFLAG_BAD_PAYLOAD	8
+
+struct dataseg {
+	u_int d_base_lo;
+	u_int d_base_high;
+	u_int d_count;
+};
+
+struct Command_Entry {
+	struct Entry_header hdr;
+	u_int handle;
+	u_char target_lun;
+	u_char target_id;
+	u_short rsvd1;
+	u_short control_flags;
+	u_short rsvd2;
+	u_short time_out;
+	u_short segment_cnt;
+	u_char cdb[16];
+	u_int total_byte_cnt;
+	struct dataseg dataseg[2];
+};
+
+/* command entry control flag definitions */
+#define CFLAG_NODISC		0x01
+#define CFLAG_HEAD_TAG		0x02
+#define CFLAG_ORDERED_TAG	0x04
+#define CFLAG_SIMPLE_TAG	0x08
+#define CFLAG_TAR_RTN		0x10
+#define CFLAG_READ		0x20
+#define CFLAG_WRITE		0x40
+
+struct Ext_Command_Entry {
+	struct Entry_header hdr;
+	u_int handle;
+	u_char target_lun;
+	u_char target_id;
+	u_short cdb_length;
+	u_short control_flags;
+	u_short rsvd;
+	u_short time_out;
+	u_short segment_cnt;
+	u_char cdb[44];
+};
+
+struct Continuation_Entry {
+	struct Entry_header hdr;
+	struct dataseg dataseg[5];
+};
+
+struct Marker_Entry {
+	struct Entry_header hdr;
+	u_int reserved;
+	u_char target_lun;
+	u_char target_id;
+	u_char modifier;
+	u_char rsvd;
+	u_char rsvds[52];
+};
+
+/* marker entry modifier definitions */
+#define SYNC_DEVICE	0
+#define SYNC_TARGET	1
+#define SYNC_ALL	2
+
+struct Status_Entry {
+	struct Entry_header hdr;
+	u_int handle;
+	u_short scsi_status;
+	u_short completion_status;
+	u_short state_flags;
+	u_short status_flags;
+	u_short res_info_len;
+	u_short req_sense_len;
+	u_int residual;
+	u_char res_info[8];
+	u_char req_sense_data[32];
+};
+
+/* status entry completion status definitions */
+#define CS_COMPLETE			0x0000
+#define CS_INCOMPLETE			0x0001
+#define CS_DMA_ERROR			0x0002
+#define CS_TRANSPORT_ERROR		0x0003
+#define CS_RESET_OCCURRED		0x0004
+#define CS_ABORTED			0x0005
+#define CS_TIMEOUT			0x0006
+#define CS_DATA_OVERRUN			0x0007
+#define CS_ABORT_MSG_FAILED		0x000e
+#define CS_REJECT_MSG_FAILED		0x000f
+#define CS_DATA_UNDERRUN		0x0015
+#define CS_PORT_UNAVAILABLE             0x0028
+#define CS_PORT_LOGGED_OUT              0x0029
+#define CS_PORT_CONFIG_CHANGED		0x002a
+
+/* status entry state flag definitions */
+#define SF_SENT_CDB			0x0400
+#define SF_TRANSFERRED_DATA		0x0800
+#define SF_GOT_STATUS			0x1000
+
+/* status entry status flag definitions */
+#define STF_BUS_RESET			0x0008
+#define STF_DEVICE_RESET		0x0010
+#define STF_ABORTED			0x0020
+#define STF_TIMEOUT			0x0040
+
+/* interupt control commands */
+#define ISP_EN_INT			0x8000
+#define ISP_EN_RISC			0x0008
+
+/* host control commands */
+#define HCCR_NOP			0x0000
+#define HCCR_RESET			0x1000
+#define HCCR_PAUSE			0x2000
+#define HCCR_RELEASE			0x3000
+#define HCCR_SINGLE_STEP		0x4000
+#define HCCR_SET_HOST_INTR		0x5000
+#define HCCR_CLEAR_HOST_INTR		0x6000
+#define HCCR_CLEAR_RISC_INTR		0x7000
+#define HCCR_BP_ENABLE			0x8000
+#define HCCR_BIOS_DISABLE		0x9000
+#define HCCR_TEST_MODE			0xf000
+
+#define RISC_BUSY			0x0004
+
+/* mailbox commands */
+#define MBOX_NO_OP			0x0000
+#define MBOX_LOAD_RAM			0x0001
+#define MBOX_EXEC_FIRMWARE		0x0002
+#define MBOX_DUMP_RAM			0x0003
+#define MBOX_WRITE_RAM_WORD		0x0004
+#define MBOX_READ_RAM_WORD		0x0005
+#define MBOX_MAILBOX_REG_TEST		0x0006
+#define MBOX_VERIFY_CHECKSUM		0x0007
+#define MBOX_ABOUT_FIRMWARE		0x0008
+#define MBOX_LOAD_RISC_RAM              0x0009
+#define MBOX_DUMP_RISC_RAM              0x000a
+#define MBOX_CHECK_FIRMWARE		0x000e
+#define MBOX_INIT_REQ_QUEUE		0x0010
+#define MBOX_INIT_RES_QUEUE		0x0011
+#define MBOX_EXECUTE_IOCB		0x0012
+#define MBOX_WAKE_UP			0x0013
+#define MBOX_STOP_FIRMWARE		0x0014
+#define MBOX_ABORT_IOCB			0x0015
+#define MBOX_ABORT_DEVICE		0x0016
+#define MBOX_ABORT_TARGET		0x0017
+#define MBOX_BUS_RESET			0x0018
+#define MBOX_STOP_QUEUE			0x0019
+#define MBOX_START_QUEUE		0x001a
+#define MBOX_SINGLE_STEP_QUEUE		0x001b
+#define MBOX_ABORT_QUEUE		0x001c
+#define MBOX_GET_DEV_QUEUE_STATUS	0x001d
+#define MBOX_GET_FIRMWARE_STATUS	0x001f
+#define MBOX_GET_INIT_SCSI_ID		0x0020
+#define MBOX_GET_RETRY_COUNT		0x0022
+#define MBOX_GET_TARGET_PARAMS		0x0028
+#define MBOX_GET_DEV_QUEUE_PARAMS	0x0029
+#define MBOX_SET_RETRY_COUNT		0x0032
+#define MBOX_SET_TARGET_PARAMS		0x0038
+#define MBOX_SET_DEV_QUEUE_PARAMS	0x0039
+#define MBOX_EXECUTE_IOCB64             0x0054
+#define MBOX_INIT_FIRMWARE              0x0060
+#define MBOX_GET_INIT_CB                0x0061
+#define MBOX_INIT_LIP			0x0062
+#define MBOX_GET_POS_MAP                0x0063
+#define MBOX_GET_PORT_DB                0x0064
+#define MBOX_CLEAR_ACA                  0x0065
+#define MBOX_TARGET_RESET               0x0066
+#define MBOX_CLEAR_TASK_SET             0x0067
+#define MBOX_ABORT_TASK_SET             0x0068
+#define MBOX_GET_FIRMWARE_STATE         0x0069
+#define MBOX_GET_PORT_NAME              0x006a
+#define MBOX_SEND_SNS                   0x006e
+#define MBOX_PORT_LOGIN                 0x006f
+#define MBOX_SEND_CHANGE_REQUEST        0x0070
+#define MBOX_PORT_LOGOUT                0x0071
+
+#include "qlogicfc_asm.c"
+
+/* Each element in mbox_param is an 8 bit bitmap where each bit indicates
+   if that mbox should be copied as input.  For example 0x2 would mean
+   only copy mbox1. */
+
+const u_char mbox_param[] =
+{
+	0x01,			/* MBOX_NO_OP */
+	0x1f,			/* MBOX_LOAD_RAM */
+	0x03,			/* MBOX_EXEC_FIRMWARE */
+	0x1f,			/* MBOX_DUMP_RAM */
+	0x07,			/* MBOX_WRITE_RAM_WORD */
+	0x03,			/* MBOX_READ_RAM_WORD */
+	0xff,			/* MBOX_MAILBOX_REG_TEST */
+	0x03,			/* MBOX_VERIFY_CHECKSUM */
+	0x01,			/* MBOX_ABOUT_FIRMWARE */
+	0xff,			/* MBOX_LOAD_RISC_RAM */
+	0xff,			/* MBOX_DUMP_RISC_RAM */
+	0x00,			/* 0x000b */
+	0x00,			/* 0x000c */
+	0x00,			/* 0x000d */
+	0x01,			/* MBOX_CHECK_FIRMWARE */
+	0x00,			/* 0x000f */
+	0x1f,			/* MBOX_INIT_REQ_QUEUE */
+	0x2f,			/* MBOX_INIT_RES_QUEUE */
+	0x0f,			/* MBOX_EXECUTE_IOCB */
+	0x03,			/* MBOX_WAKE_UP */
+	0x01,			/* MBOX_STOP_FIRMWARE */
+	0x0f,			/* MBOX_ABORT_IOCB */
+	0x03,			/* MBOX_ABORT_DEVICE */
+	0x07,			/* MBOX_ABORT_TARGET */
+	0x03,			/* MBOX_BUS_RESET */
+	0x03,			/* MBOX_STOP_QUEUE */
+	0x03,			/* MBOX_START_QUEUE */
+	0x03,			/* MBOX_SINGLE_STEP_QUEUE */
+	0x03,			/* MBOX_ABORT_QUEUE */
+	0x03,			/* MBOX_GET_DEV_QUEUE_STATUS */
+	0x00,			/* 0x001e */
+	0x01,			/* MBOX_GET_FIRMWARE_STATUS */
+	0x01,			/* MBOX_GET_INIT_SCSI_ID */
+	0x00,			/* 0x0021 */
+	0x01,			/* MBOX_GET_RETRY_COUNT */
+	0x00,			/* 0x0023 */
+	0x00,			/* 0x0024 */
+	0x00,			/* 0x0025 */
+	0x00,			/* 0x0026 */
+	0x00,			/* 0x0027 */
+	0x03,			/* MBOX_GET_TARGET_PARAMS */
+	0x03,			/* MBOX_GET_DEV_QUEUE_PARAMS */
+	0x00,			/* 0x002a */
+	0x00,			/* 0x002b */
+	0x00,			/* 0x002c */
+	0x00,			/* 0x002d */
+	0x00,			/* 0x002e */
+	0x00,			/* 0x002f */
+	0x00,			/* 0x0030 */
+	0x00,			/* 0x0031 */
+	0x07,			/* MBOX_SET_RETRY_COUNT */
+	0x00,			/* 0x0033 */
+	0x00,			/* 0x0034 */
+	0x00,			/* 0x0035 */
+	0x00,			/* 0x0036 */
+	0x00,			/* 0x0037 */
+	0x0f,			/* MBOX_SET_TARGET_PARAMS */
+	0x0f,			/* MBOX_SET_DEV_QUEUE_PARAMS */
+	0x00,			/* 0x003a */
+	0x00,			/* 0x003b */
+	0x00,			/* 0x003c */
+	0x00,			/* 0x003d */
+	0x00,			/* 0x003e */
+	0x00,			/* 0x003f */
+	0x00,			/* 0x0040 */
+	0x00,			/* 0x0041 */
+	0x00,			/* 0x0042 */
+	0x00,			/* 0x0043 */
+	0x00,			/* 0x0044 */
+	0x00,			/* 0x0045 */
+	0x00,			/* 0x0046 */
+	0x00,			/* 0x0047 */
+	0x00,			/* 0x0048 */
+	0x00,			/* 0x0049 */
+	0x00,			/* 0x004a */
+	0x00,			/* 0x004b */
+	0x00,			/* 0x004c */
+	0x00,			/* 0x004d */
+	0x00,			/* 0x004e */
+	0x00,			/* 0x004f */
+	0x00,			/* 0x0050 */
+	0x00,			/* 0x0051 */
+	0x00,			/* 0x0052 */
+	0x00,			/* 0x0053 */
+	0xcf,			/* MBOX_EXECUTE_IOCB64 */
+	0x00,			/* 0x0055 */
+	0x00,			/* 0x0056 */
+	0x00,			/* 0x0057 */
+	0x00,			/* 0x0058 */
+	0x00,			/* 0x0059 */
+	0x00,			/* 0x005a */
+	0x00,			/* 0x005b */
+	0x00,			/* 0x005c */
+	0x00,			/* 0x005d */
+	0x00,			/* 0x005e */
+	0x00,			/* 0x005f */
+	0xff,			/* MBOX_INIT_FIRMWARE */
+	0xcd,			/* MBOX_GET_INIT_CB */
+	0x01,			/* MBOX_INIT_LIP */
+	0xcd,			/* MBOX_GET_POS_MAP */
+	0xcf,			/* MBOX_GET_PORT_DB */
+	0x03,			/* MBOX_CLEAR_ACA */
+	0x03,			/* MBOX_TARGET_RESET */
+	0x03,			/* MBOX_CLEAR_TASK_SET */
+	0x03,			/* MBOX_ABORT_TASK_SET */
+	0x01,			/* MBOX_GET_FIRMWARE_STATE */
+	0x03,			/* MBOX_GET_PORT_NAME */
+	0x00,			/* 0x006b */
+	0x00,			/* 0x006c */
+	0x00,			/* 0x006d */
+	0xcf,			/* MBOX_SEND_SNS */
+	0x0f,			/* MBOX_PORT_LOGIN */
+	0x03,			/* MBOX_SEND_CHANGE_REQUEST */
+	0x03,			/* MBOX_PORT_LOGOUT */
+};
+
+#define MAX_MBOX_COMMAND	(sizeof(mbox_param)/sizeof(u_short))
+
+
+struct id_name_map {
+	u64 wwn;
+	u_char loop_id;
+};
+
+struct sns_cb {
+	u_short len;
+	u_short res1;
+	u_int response_low;
+	u_int response_high;
+	u_short sub_len;
+	u_short res2;
+	u_short data[22];
+};
+
+/* address of instance of this struct is passed to adapter to initialize things
+ */
+struct init_cb {
+	u_char version;
+	u_char reseverd1[1];
+	u_short firm_opts;
+	u_short max_frame_len;
+	u_short max_iocb;
+	u_short exec_throttle;
+	u_char retry_cnt;
+	u_char retry_delay;
+	u_short node_name[4];
+	u_short hard_addr;
+	u_char reserved2[10];
+	u_short req_queue_out;
+	u_short res_queue_in;
+	u_short req_queue_len;
+	u_short res_queue_len;
+	u_int req_queue_addr_lo;
+	u_int req_queue_addr_high;
+	u_int res_queue_addr_lo;
+	u_int res_queue_addr_high;
+};
+
+/*
+ * The result queue can be quite a bit smaller since continuation entries
+ * do not show up there:
+ */
+#define RES_QUEUE_LEN		((QLOGICFC_REQ_QUEUE_LEN + 1) / 8 - 1)
+#define QUEUE_ENTRY_LEN		64
+
+#if ISP2100_FABRIC
+#define QLOGICFC_MAX_ID    0xff
+#else
+#define QLOGICFC_MAX_ID    0x80
+#endif
+
+struct isp2100_hostdata {
+	u_char revision;
+	struct pci_dev *pci_dev;
+	/* result and request queues (shared with isp2100): */
+	u_int req_in_ptr;	/* index of next request slot */
+	u_int res_out_ptr;	/* index of next result slot */
+
+	/* 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];
+	struct init_cb control_block;
+	int loop_up;
+	unsigned long int tag_ages[126];
+	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];
+	u_char mbox_done;
+	u64 wwn;
+	u_int port_id;
+	u_char queued;
+};
+
+
+/* queue length's _must_ be power of two: */
+#define QUEUE_DEPTH(in, out, ql)	((in - out) & (ql))
+#define REQ_QUEUE_DEPTH(in, out)	QUEUE_DEPTH(in, out, 		     \
+						    QLOGICFC_REQ_QUEUE_LEN)
+#define RES_QUEUE_DEPTH(in, out)	QUEUE_DEPTH(in, out, RES_QUEUE_LEN)
+
+static void isp2100_enable_irqs(struct Scsi_Host *);
+static void isp2100_disable_irqs(struct Scsi_Host *);
+static int isp2100_init(struct Scsi_Host *);
+static int isp2100_reset_hardware(struct Scsi_Host *);
+static int isp2100_mbox_command(struct Scsi_Host *, u_short[]);
+static int isp2100_return_status(struct Status_Entry *);
+static void isp2100_intr_handler(int, void *, struct pt_regs *);
+static void do_isp2100_intr_handler(int, void *, struct pt_regs *);
+static int isp2100_make_portdb(struct Scsi_Host *);
+
+#if ISP2100_FABRIC
+static int isp2100_init_fabric(struct Scsi_Host *, struct id_name_map *, int);
+#endif
+
+#if USE_NVRAM_DEFAULTS
+static int isp2100_get_nvram_defaults(struct Scsi_Host *, struct init_cb *);
+static u_short isp2100_read_nvram_word(struct Scsi_Host *, u_short);
+#endif
+
+#if DEBUG_ISP2100
+static void isp2100_print_scsi_cmd(Scsi_Cmnd *);
+#endif
+
+#if DEBUG_ISP2100_INTR
+static void isp2100_print_status_entry(struct Status_Entry *);
+#endif
+
+static struct proc_dir_entry proc_scsi_isp2100 =
+{
+	PROC_SCSI_QLOGICFC, 7, "isp2100",
+	S_IFDIR | S_IRUGO | S_IXUGO, 2
+};
+
+
+static inline void isp2100_enable_irqs(struct Scsi_Host *host)
+{
+	outw(ISP_EN_INT | ISP_EN_RISC, host->io_port + PCI_INTER_CTL);
+}
+
+
+static inline void isp2100_disable_irqs(struct Scsi_Host *host)
+{
+	outw(0x0, host->io_port + PCI_INTER_CTL);
+}
+
+
+int isp2100_detect(Scsi_Host_Template * tmpt)
+{
+	int hosts = 0;
+	int wait_time;
+	struct Scsi_Host *host = NULL;
+	struct isp2100_hostdata *hostdata;
+	struct pci_dev *pdev = NULL;
+
+	ENTER("isp2100_detect");
+
+	tmpt->proc_dir = &proc_scsi_isp2100;
+
+	if (pci_present() == 0) {
+		printk("qlogicfc : PCI not present\n");
+		return 0;
+	}
+	while ((pdev = pci_find_device(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100, pdev))) {
+
+		host = scsi_register(tmpt, sizeof(struct isp2100_hostdata));
+		host->max_id = QLOGICFC_MAX_ID + 1;
+		host->hostt->use_new_eh_code = 1;
+		hostdata = (struct isp2100_hostdata *) host->hostdata;
+
+		memset(hostdata, 0, sizeof(struct isp2100_hostdata));
+		hostdata->pci_dev = pdev;
+
+		hostdata->queued = 0;
+		/* set up the control block */
+		hostdata->control_block.version = 0x0f;
+		hostdata->control_block.firm_opts = 0x010c;
+		hostdata->control_block.max_frame_len = 2048;
+		hostdata->control_block.max_iocb = 256;
+		hostdata->control_block.exec_throttle = 8;
+		hostdata->control_block.retry_delay = 5;
+		hostdata->control_block.retry_cnt = 0;
+		hostdata->control_block.node_name[0] = 0x0020;
+		hostdata->control_block.node_name[1] = 0xE000;
+		hostdata->control_block.node_name[2] = 0x008B;
+		hostdata->control_block.node_name[3] = 0x0000;
+		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->loop_up = 0;
+
+		if (isp2100_init(host) || isp2100_reset_hardware(host)) {
+			scsi_unregister(host);
+			continue;
+		}
+		host->this_id = tmpt->this_id;
+
+		if (request_irq(host->irq, do_isp2100_intr_handler, SA_INTERRUPT | SA_SHIRQ, "qlogicfc", host)) {
+			printk("qlogicfc : interrupt %d already in use\n",
+			       host->irq);
+			scsi_unregister(host);
+			continue;
+		}
+		if (check_region(host->io_port, 0xff)) {
+			printk("qlogicfc : i/o region 0x%lx-0x%lx already "
+			       "in use\n",
+			       host->io_port, host->io_port + 0xff);
+			free_irq(host->irq, host);
+			scsi_unregister(host);
+			continue;
+		}
+		request_region(host->io_port, 0xff, "qlogicfc");
+
+		outw(0x0, host->io_port + PCI_SEMAPHORE);
+		outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
+		isp2100_enable_irqs(host);
+		/* wait for the loop to come up */
+		for (wait_time = jiffies + 20 * HZ; wait_time > jiffies && hostdata->loop_up == 0;)
+			barrier();
+
+		if (hostdata->loop_up == 0) {
+			printk("qlogicfc: loop is not up\n");
+			release_region(host->io_port, 0xff);
+			free_irq(host->irq, host);
+			scsi_unregister(host);
+			continue;
+		}
+		hosts++;
+	}
+
+
+	/* this busy loop should not be needed but the isp2100 seems to need 
+	   some time before recognizing it is attached to a fabric */
+
+#if ISP2100_FABRIC
+	for (wait_time = jiffies + 5 * HZ; wait_time > jiffies;)
+		barrier();
+#endif
+
+	LEAVE("isp2100_detect");
+
+	return hosts;
+}
+
+
+static int isp2100_make_portdb(struct Scsi_Host *host)
+{
+
+	short param[8];
+	int i, j;
+	struct id_name_map temp[QLOGICFC_MAX_ID + 1];
+	struct isp2100_hostdata *hostdata;
+
+	isp2100_disable_irqs(host);
+
+	memset(temp, 0, sizeof(temp));
+	hostdata = (struct isp2100_hostdata *) host->hostdata;
+
+#if ISP2100_FABRIC
+	for (i = 0x81; i < QLOGICFC_MAX_ID; i++) {
+		param[0] = MBOX_PORT_LOGOUT;
+		param[1] = i << 8;
+		param[2] = 0;
+		param[3] = 0;
+
+		isp2100_mbox_command(host, param);
+
+		if (param[0] != MBOX_COMMAND_COMPLETE) {
+			printk("logout failed %x  %x\n", i, param[0]);
+		}
+	}
+#endif
+
+
+	param[0] = MBOX_GET_INIT_SCSI_ID;
+
+	isp2100_mbox_command(host, param);
+
+	if (param[0] == MBOX_COMMAND_COMPLETE) {
+		host->this_id = param[1];
+		hostdata->port_id = ((u_int) param[3]) << 16;
+		hostdata->port_id |= param[2];
+	}
+
+	for (i = 0, j = 0; i <= QLOGICFC_MAX_ID; i++) {
+	        temp[i].loop_id = host->this_id;
+
+		param[0] = MBOX_GET_PORT_NAME;
+		param[1] = (i << 8) & 0xff00;
+
+		isp2100_mbox_command(host, param);
+
+		if (param[0] == MBOX_COMMAND_COMPLETE) {
+			temp[j].loop_id = i;
+			temp[j].wwn = ((u64) (param[2] & 0xff)) << 56;
+			temp[j].wwn |= ((u64) ((param[2] >> 8) & 0xff)) << 48;
+			temp[j].wwn |= ((u64) (param[3] & 0xff)) << 40;
+			temp[j].wwn |= ((u64) ((param[3] >> 8) & 0xff)) << 32;
+			temp[j].wwn |= ((u64) (param[6] & 0xff)) << 24;
+			temp[j].wwn |= ((u64) ((param[6] >> 8) & 0xff)) << 16;
+			temp[j].wwn |= ((u64) (param[7] & 0xff)) << 8;
+			temp[j].wwn |= ((u64) ((param[7] >> 8) & 0xff));
+
+			j++;
+
+		}
+	}
+
+
+#if ISP2100_FABRIC
+	isp2100_init_fabric(host, temp, j);
+#endif
+
+	for (i = 0; i <= QLOGICFC_MAX_ID; i++) {
+		if (temp[i].wwn != hostdata->port_db[i].wwn) {
+			for (j = 0; j <= QLOGICFC_MAX_ID; j++) {
+				if (temp[j].wwn == hostdata->port_db[i].wwn) {
+					hostdata->port_db[i].loop_id = temp[j].loop_id;
+					break;
+				}
+			}
+			if (j == QLOGICFC_MAX_ID + 1)
+				hostdata->port_db[i].loop_id = host->this_id;
+
+			for (j = 0; j <= QLOGICFC_MAX_ID; j++) {
+				if (hostdata->port_db[j].wwn == temp[i].wwn || !hostdata->port_db[j].wwn) {
+					break;
+				}
+			}
+			if (j == QLOGICFC_MAX_ID + 1)
+				printk("qlogicfc.c: Too many scsi devices, no more room in port map.\n");
+			if (!hostdata->port_db[j].wwn) {
+				hostdata->port_db[j].loop_id = temp[i].loop_id;
+				hostdata->port_db[j].wwn = temp[i].wwn;
+			}
+		} else
+			hostdata->port_db[i].loop_id = temp[i].loop_id;
+
+	}
+
+	isp2100_enable_irqs(host);
+
+	return 0;
+}
+
+
+#if ISP2100_FABRIC
+
+int isp2100_init_fabric(struct Scsi_Host *host, struct id_name_map *port_db, int j)
+{
+
+	u_short param[8];
+	u64 wwn;
+	int done = 0;
+	u_short loop_id = 0x81;
+	u_short scsi_id = j;
+	u_int port_id;
+	struct sns_cb req;
+	u_char sns_response[608];
+	struct isp2100_hostdata *hostdata;
+
+	hostdata = (struct isp2100_hostdata *) host->hostdata;
+
+	DEBUG_FABRIC(printk("qlogicfc.c: Checking for a fabric.\n"));
+	param[0] = MBOX_GET_PORT_NAME;
+	param[1] = 0x7E00;
+
+	isp2100_mbox_command(host, param);
+
+	if (param[0] != MBOX_COMMAND_COMPLETE) {
+		DEBUG_FABRIC(printk("fabric check result %x\n", param[0]));
+		return 0;
+	}
+	printk("qlogicfc.c: Fabric found.\n");
+
+
+	port_id = hostdata->port_id;
+	while (!done) {
+		memset(&req, 0, sizeof(req));
+
+		req.len = 304;
+		req.response_low = virt_to_bus_low32(sns_response);
+		req.response_high = virt_to_bus_high32(sns_response);
+		req.sub_len = 6;
+		req.data[0] = 0x0100;
+		req.data[4] = (u_short) (port_id & 0xffff);
+		req.data[5] = (u_short) (port_id >> 16 & 0xffff);
+
+		param[0] = MBOX_SEND_SNS;
+		param[1] = 14;
+		param[2] = virt_to_bus_low32(&req) >> 16;
+		param[3] = virt_to_bus_low32(&req);
+		param[6] = virt_to_bus_high32(&req) >> 16;
+		param[7] = virt_to_bus_high32(&req);
+
+		isp2100_mbox_command(host, param);
+
+		if (param[0] == MBOX_COMMAND_COMPLETE) {
+			DEBUG_FABRIC(printk("found node %02x%02x%02x%02x%02x%02x%02x%02x ", sns_response[20], sns_response[21], sns_response[22], sns_response[23], sns_response[24], sns_response[25], sns_response[26], sns_response[27]));
+			DEBUG_FABRIC(printk("  port id: %02x%02x%02x\n", sns_response[17], sns_response[18], sns_response[19]));
+			port_id = ((u_int) sns_response[17]) << 16;
+			port_id |= ((u_int) sns_response[18]) << 8;
+			port_id |= ((u_int) sns_response[19]);
+			wwn = ((u64) sns_response[20]) << 56;
+			wwn |= ((u64) sns_response[21]) << 48;
+			wwn |= ((u64) sns_response[22]) << 40;
+			wwn |= ((u64) sns_response[23]) << 32;
+			wwn |= ((u64) sns_response[24]) << 24;
+			wwn |= ((u64) sns_response[25]) << 16;
+			wwn |= ((u64) sns_response[26]) << 8;
+			wwn |= ((u64) sns_response[27]);
+			if (hostdata->port_id >> 8 != port_id >> 8) {
+				DEBUG_FABRIC(printk("adding a fabric port: %x\n", port_id));
+				param[0] = MBOX_PORT_LOGIN;
+				param[1] = loop_id << 8;
+				param[2] = (u_short) (port_id >> 16);
+				param[3] = (u_short) (port_id);
+
+				isp2100_mbox_command(host, param);
+
+				if (param[0] == MBOX_COMMAND_COMPLETE) {
+					port_db[scsi_id].wwn = wwn;
+					port_db[scsi_id].loop_id = loop_id;
+					loop_id++;
+					scsi_id++;
+				} else {
+					printk("qlogicfc.c: Error performing port login %x\n", param[0]);
+					DEBUG_FABRIC(printk("loop_id: %x\n", loop_id));
+				}
+
+			}
+			if (hostdata->port_id == port_id)
+				done = 1;
+		} else {
+			printk("qlogicfc.c: Get All Next failed %x.\n", param[0]);
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+#endif				/* ISP2100_FABRIC */
+
+
+int isp2100_release(struct Scsi_Host *host)
+{
+	struct isp2100_hostdata *hostdata;
+
+	ENTER("isp2100_release");
+
+	hostdata = (struct isp2100_hostdata *) host->hostdata;
+
+	outw(0x0, host->io_port + PCI_INTER_CTL);
+	free_irq(host->irq, host);
+
+	release_region(host->io_port, 0xff);
+
+	LEAVE("isp2100_release");
+
+	return 0;
+}
+
+
+const char *isp2100_info(struct Scsi_Host *host)
+{
+	static char buf[80];
+	struct isp2100_hostdata *hostdata;
+	ENTER("isp2100_info");
+
+	hostdata = (struct isp2100_hostdata *) host->hostdata;
+	sprintf(buf,
+		"QLogic ISP2100 SCSI on PCI bus %02x device %02x irq %d base 0x%lx",
+		hostdata->pci_dev->bus->number, hostdata->pci_dev->devfn, host->irq,
+		host->io_port);
+
+
+	LEAVE("isp2100_info");
+
+	return buf;
+}
+
+
+/*
+ * The middle SCSI layer ensures that queuecommand never gets invoked
+ * concurrently with itself or the interrupt handler (though the
+ * interrupt handler may call this routine as part of
+ * request-completion handling).
+ */
+int isp2100_queuecommand(Scsi_Cmnd * Cmnd, void (*done) (Scsi_Cmnd *))
+{
+	int i, sg_count, n, num_free;
+	u_int in_ptr, out_ptr;
+	struct dataseg *ds;
+	struct scatterlist *sg;
+	struct Command_Entry *cmd;
+	struct Continuation_Entry *cont;
+	struct Scsi_Host *host;
+	struct isp2100_hostdata *hostdata;
+
+	ENTER("isp2100_queuecommand");
+
+	host = Cmnd->host;
+	hostdata = (struct isp2100_hostdata *) host->hostdata;
+	Cmnd->scsi_done = done;
+
+	DEBUG(isp2100_print_scsi_cmd(Cmnd));
+
+	if (hostdata->loop_up == 2) {
+		hostdata->loop_up = 1;
+		isp2100_make_portdb(host);
+		for (i = 0; hostdata->port_db[i].wwn != 0; i++) {
+			DEBUG(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));
+		}
+	}
+	if (hostdata->loop_up == -1) {
+		printk("qlogicfc.c: The firmware is dead, just return.\n");
+		host->max_id = 0;
+		return 0;
+	}
+	out_ptr = inw(host->io_port + MBOX4);
+	in_ptr = hostdata->req_in_ptr;
+
+	DEBUG(printk("qlogicfc : request queue depth %d\n",
+		     REQ_QUEUE_DEPTH(in_ptr, out_ptr)));
+
+	cmd = (struct Command_Entry *) &hostdata->req[in_ptr][0];
+	in_ptr = (in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN;
+	if (in_ptr == out_ptr) {
+		DEBUG(printk("qlogicfc : request queue overflow\n"));
+		return 1;
+	}
+	if (hostdata->send_marker) {
+		struct Marker_Entry *marker;
+
+		TRACE("queue marker", in_ptr, 0);
+
+		DEBUG(printk("qlogicfc : adding marker entry\n"));
+		marker = (struct Marker_Entry *) cmd;
+		memset(marker, 0, sizeof(struct Marker_Entry));
+
+		marker->hdr.entry_type = ENTRY_MARKER;
+		marker->hdr.entry_cnt = 1;
+		marker->modifier = SYNC_ALL;
+
+		hostdata->send_marker = 0;
+
+		if (((in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN) == out_ptr) {
+			outw(in_ptr, host->io_port + MBOX4);
+			hostdata->req_in_ptr = in_ptr;
+			DEBUG(printk("qlogicfc : request queue overflow\n"));
+			return 1;
+		}
+		cmd = (struct Command_Entry *) &hostdata->req[in_ptr][0];
+		in_ptr = (in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN;
+	}
+	TRACE("queue command", in_ptr, Cmnd);
+
+	memset(cmd, 0, sizeof(struct Command_Entry));
+
+	/* find a free handle mapping slot */
+	for (i = in_ptr; i != (in_ptr - 1) && hostdata->handle_ptrs[i]; i = ((i + 1) % (QLOGICFC_REQ_QUEUE_LEN + 1)));
+
+	if (!hostdata->handle_ptrs[i]) {
+		cmd->handle = i;
+		hostdata->handle_ptrs[i] = Cmnd;
+		hostdata->handle_serials[i] = Cmnd->serial_number;
+	} else
+		printk("qlogicfc: no handle slots, this should not happen.\n");
+
+	cmd->hdr.entry_type = ENTRY_COMMAND;
+	cmd->hdr.entry_cnt = 1;
+	cmd->target_lun = Cmnd->lun;
+	cmd->target_id = hostdata->port_db[Cmnd->target].loop_id;
+	cmd->total_byte_cnt = (u_int) Cmnd->request_bufflen;
+	cmd->time_out = SCSI_TIMEOUT / HZ;
+
+	memcpy(cmd->cdb, Cmnd->cmnd, Cmnd->cmd_len);
+
+	if (Cmnd->use_sg) {
+		cmd->segment_cnt = sg_count = Cmnd->use_sg;
+		sg = (struct scatterlist *) Cmnd->request_buffer;
+		ds = cmd->dataseg;
+		/* fill in first two sg entries: */
+		n = sg_count;
+		if (n > 2)
+			n = 2;
+		for (i = 0; i < n; i++) {
+			ds[i].d_base_lo = virt_to_bus_low32(sg->address);
+			ds[i].d_base_high = virt_to_bus_high32(sg->address);
+			ds[i].d_count = sg->length;
+			++sg;
+		}
+		sg_count -= 2;
+
+		while (sg_count > 0) {
+			++cmd->hdr.entry_cnt;
+			cont = (struct Continuation_Entry *)
+			    &hostdata->req[in_ptr][0];
+			memset(cont, 0, sizeof(struct Continuation_Entry));
+			in_ptr = (in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN;
+			if (in_ptr == out_ptr) {
+				DEBUG(printk("isp2100: unexpected request queue overflow\n"));
+				return 1;
+			}
+			TRACE("queue continuation", in_ptr, 0);
+			cont->hdr.entry_type = ENTRY_CONTINUATION;
+			ds = cont->dataseg;
+			n = sg_count;
+			if (n > 5)
+				n = 5;
+			for (i = 0; i < n; ++i) {
+				ds[i].d_base_lo = virt_to_bus_low32(sg->address);
+				ds[i].d_base_high = virt_to_bus_high32(sg->address);
+				ds[i].d_count = sg->length;
+				++sg;
+			}
+			sg_count -= n;
+		}
+	} else {
+		cmd->dataseg[0].d_base_lo = virt_to_bus_low32(Cmnd->request_buffer);
+		cmd->dataseg[0].d_base_high = virt_to_bus_high32(Cmnd->request_buffer);
+		cmd->dataseg[0].d_count =
+		    (u_int) Cmnd->request_bufflen;
+		cmd->segment_cnt = 1;
+	}
+
+	switch (Cmnd->cmnd[0]) {
+	case WRITE_10:
+	case WRITE_6:
+	case WRITE_BUFFER:
+		cmd->control_flags = CFLAG_WRITE;
+		break;
+	case REQUEST_SENSE:
+		/* scsi.c expects sense info in a different buffer */
+		cmd->dataseg[0].d_base_lo = virt_to_bus_low32(Cmnd->sense_buffer);
+		cmd->dataseg[0].d_base_high = virt_to_bus_high32(Cmnd->sense_buffer);
+		cmd->segment_cnt = 1;
+		cmd->control_flags = CFLAG_READ;
+		break;
+	default:
+		cmd->control_flags = CFLAG_READ;
+		break;
+	}
+
+
+	if (Cmnd->device->tagged_supported) {
+		switch (Cmnd->tag) {
+		case SIMPLE_QUEUE_TAG:
+			cmd->control_flags |= CFLAG_SIMPLE_TAG;
+			break;
+		case HEAD_OF_QUEUE_TAG:
+			cmd->control_flags |= CFLAG_HEAD_TAG;
+			break;
+		case ORDERED_QUEUE_TAG:
+			cmd->control_flags |= CFLAG_ORDERED_TAG;
+			break;
+		default:
+			if ((jiffies - hostdata->tag_ages[Cmnd->target]) > (5 * HZ)) {
+				cmd->control_flags |= CFLAG_ORDERED_TAG;
+				hostdata->tag_ages[Cmnd->target] = jiffies;
+			} else
+				cmd->control_flags |= CFLAG_SIMPLE_TAG;
+		}
+	}
+	outw(in_ptr, host->io_port + MBOX4);
+	hostdata->req_in_ptr = in_ptr;
+
+	hostdata->queued++;
+
+	num_free = QLOGICFC_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr);
+	num_free = num_free - 2;
+	host->can_queue = hostdata->queued + num_free;
+	if (host->can_queue > QLOGICFC_REQ_QUEUE_LEN)
+		host->can_queue = QLOGICFC_REQ_QUEUE_LEN;
+	host->sg_tablesize = QLOGICFC_MAX_SG(num_free);
+
+	/* this is really gross */
+	if (host->can_queue < host->host_busy){
+	        if (host->can_queue+2 < host->host_busy) 
+		  printk("qlogicfc.c crosses its fingers.\n");
+		host->can_queue = host->host_busy;
+	}
+
+	LEAVE("isp2100_queuecommand");
+
+	return 0;
+}
+
+
+#define ASYNC_EVENT_INTERRUPT	0x01
+
+
+void do_isp2100_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&io_request_lock, flags);
+	isp2100_intr_handler(irq, dev_id, regs);
+	spin_unlock_irqrestore(&io_request_lock, flags);
+}
+
+void isp2100_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	Scsi_Cmnd *Cmnd;
+	struct Status_Entry *sts;
+	struct Scsi_Host *host = dev_id;
+	struct isp2100_hostdata *hostdata;
+	u_int in_ptr, out_ptr, handle, num_free;
+	u_short status;
+
+	ENTER_INTR("isp2100_intr_handler");
+
+	hostdata = (struct isp2100_hostdata *) host->hostdata;
+
+	DEBUG_INTR(printk("qlogicfc : interrupt on line %d\n", irq));
+
+	if (!(inw(host->io_port + PCI_INTER_STS) & 0x08)) {
+		/* spurious interrupts can happen legally */
+		DEBUG_INTR(printk("qlogicfc: got spurious interrupt\n"));
+		return;
+	}
+	in_ptr = inw(host->io_port + MBOX5);
+	out_ptr = hostdata->res_out_ptr;
+
+	if ((inw(host->io_port + PCI_SEMAPHORE) & ASYNC_EVENT_INTERRUPT)) {
+		status = inw(host->io_port + MBOX0);
+
+		DEBUG_INTR(printk("qlogicfc : mbox completion status: %x\n",
+				  status));
+
+		switch (status) {
+		case LOOP_UP:
+			hostdata->loop_up = 2;
+			break;
+		case LOOP_DOWN:
+			hostdata->loop_up = 0;
+			break;
+		case LIP_OCCURED:
+		case CHANGE_NOTIFICATION:
+		case PORT_DB_CHANGED:
+		case LIP_RECEIVED:
+			if (hostdata->loop_up == 1)
+				hostdata->loop_up = 2;
+			break;
+		case SYSTEM_ERROR:
+			printk("The firmware just choked.\n");
+			hostdata->loop_up = -1;
+			break;
+		case SCSI_COMMAND_COMPLETE:
+			handle = inw(host->io_port + MBOX1) | (inw(host->io_port + MBOX2) << 16);
+			Cmnd = hostdata->handle_ptrs[handle];
+			hostdata->handle_ptrs[handle] = NULL;
+			hostdata->handle_serials[handle] = 0;
+			hostdata->queued--;
+			if (Cmnd != NULL) {
+				Cmnd->result = 0x0;
+				(*Cmnd->scsi_done) (Cmnd);
+			} else
+				printk("qlogicfc.c: got a null value out of handle_ptrs, this sucks\n");
+			break;
+		case MBOX_COMMAND_COMPLETE:
+		case INVALID_COMMAND:
+		case HOST_INTERFACE_ERROR:
+		case TEST_FAILED:
+		case COMMAND_ERROR:
+		case COMMAND_PARAM_ERROR:
+		case PORT_ID_USED:
+		case LOOP_ID_USED:
+		case ALL_IDS_USED:
+			hostdata->mbox_done = 1;
+			outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
+			return;
+		default:
+			printk("qlogicfc: got an unknown status? %x\n", status);
+		}
+		outw(0x0, host->io_port + PCI_SEMAPHORE);
+	} else {
+		DEBUG_INTR(printk("qlogicfc : response queue update\n"));
+		DEBUG_INTR(printk("qlogicfc : response queue depth %d\n", RES_QUEUE_DEPTH(in_ptr, out_ptr)));
+
+		while (out_ptr != in_ptr) {
+			sts = (struct Status_Entry *) &hostdata->res[out_ptr][0];
+			out_ptr = (out_ptr + 1) & RES_QUEUE_LEN;
+			Cmnd = hostdata->handle_ptrs[sts->handle];
+
+			hostdata->handle_ptrs[sts->handle] = NULL;
+
+			if (hostdata->handle_serials[sts->handle] != Cmnd->serial_number) {
+				hostdata->queued--;
+				hostdata->handle_serials[sts->handle] = 0;
+				outw(out_ptr, host->io_port + MBOX5);
+				continue;
+			}
+			hostdata->handle_serials[sts->handle] = 0;
+
+			TRACE("done", out_ptr, Cmnd);
+			DEBUG_INTR(isp2100_print_status_entry(sts));
+			if (sts->hdr.entry_type == ENTRY_STATUS) {
+				Cmnd->result = isp2100_return_status(sts);
+			} else {
+				outw(out_ptr, host->io_port + MBOX5);
+				continue;
+			}
+
+			if (sts->completion_status == CS_RESET_OCCURRED
+			    || sts->completion_status == CS_ABORTED
+			    || (sts->status_flags & STF_BUS_RESET))
+				hostdata->send_marker = 1;
+
+			if (sts->scsi_status & 0x0200)
+				memcpy(Cmnd->sense_buffer, sts->req_sense_data,
+				       sizeof(Cmnd->sense_buffer));
+
+			outw(out_ptr, host->io_port + MBOX5);
+
+			hostdata->queued--;
+			if (Cmnd->scsi_done != NULL) {
+				(*Cmnd->scsi_done) (Cmnd);
+			} else
+				printk("Ouch, scsi done is NULL\n");
+		}
+		hostdata->res_out_ptr = out_ptr;
+	}
+
+
+	out_ptr = inw(host->io_port + MBOX4);
+	in_ptr = hostdata->req_in_ptr;
+
+	num_free = QLOGICFC_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr);
+	num_free = num_free-2;
+	host->can_queue = hostdata->queued + num_free;
+	if (host->can_queue > QLOGICFC_REQ_QUEUE_LEN)
+		host->can_queue = QLOGICFC_REQ_QUEUE_LEN;
+	host->sg_tablesize = QLOGICFC_MAX_SG(num_free);
+
+	if (host->can_queue < host->host_busy){
+	        if (host->can_queue+2 < host->host_busy) 
+		        DEBUG(printk("qlogicfc crosses its fingers.\n"));
+		host->can_queue = host->host_busy;
+	}
+
+	outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
+	LEAVE_INTR("isp2100_intr_handler");
+}
+
+
+static int isp2100_return_status(struct Status_Entry *sts)
+{
+	int host_status = DID_ERROR;
+#if DEBUG_ISP2100_INTR
+	static char *reason[] =
+	{
+		"DID_OK",
+		"DID_NO_CONNECT",
+		"DID_BUS_BUSY",
+		"DID_TIME_OUT",
+		"DID_BAD_TARGET",
+		"DID_ABORT",
+		"DID_PARITY",
+		"DID_ERROR",
+		"DID_RESET",
+		"DID_BAD_INTR"
+	};
+#endif				/* DEBUG_ISP2100_INTR */
+
+	ENTER("isp2100_return_status");
+
+	DEBUG(printk("qlogicfc : completion status = 0x%04x\n",
+		     sts->completion_status));
+
+	switch (sts->completion_status) {
+	case CS_COMPLETE:
+		host_status = DID_OK;
+		break;
+	case CS_INCOMPLETE:
+		if (!(sts->state_flags & SF_SENT_CDB))
+			host_status = DID_ERROR;
+		else if (!(sts->state_flags & SF_TRANSFERRED_DATA))
+			host_status = DID_ERROR;
+		else if (!(sts->state_flags & SF_GOT_STATUS))
+			host_status = DID_ERROR;
+		break;
+	case CS_DMA_ERROR:
+	case CS_TRANSPORT_ERROR:
+		host_status = DID_ERROR;
+		break;
+	case CS_RESET_OCCURRED:
+		host_status = DID_RESET;
+		break;
+	case CS_ABORTED:
+		host_status = DID_ABORT;
+		break;
+	case CS_TIMEOUT:
+		host_status = DID_TIME_OUT;
+		break;
+	case CS_DATA_OVERRUN:
+	case CS_ABORT_MSG_FAILED:
+		host_status = DID_ERROR;
+		break;
+	case CS_DATA_UNDERRUN:
+		host_status = DID_OK;
+		break;
+	case CS_PORT_UNAVAILABLE:
+	case CS_PORT_LOGGED_OUT:
+	case CS_PORT_CONFIG_CHANGED:
+		host_status = DID_BAD_TARGET;
+		break;
+	default:
+		printk("qlogicfc : unknown completion status 0x%04x\n",
+		       sts->completion_status);
+		host_status = DID_ERROR;
+		break;
+	}
+
+	DEBUG_INTR(printk("qlogicfc : host status (%s) scsi status %x\n",
+			  reason[host_status], sts->scsi_status));
+
+	LEAVE("isp2100_return_status");
+
+	return (sts->scsi_status & STATUS_MASK) | (host_status << 16);
+}
+
+
+int isp2100_abort(Scsi_Cmnd * Cmnd)
+{
+	u_short param[8];
+	int i;
+	struct Scsi_Host *host;
+	struct isp2100_hostdata *hostdata;
+	int return_status = SCSI_ABORT_SUCCESS;
+
+	ENTER("isp2100_abort");
+
+	host = Cmnd->host;
+	hostdata = (struct isp2100_hostdata *) host->hostdata;
+
+	for (i = 0; i < QLOGICFC_REQ_QUEUE_LEN; i++)
+		if (hostdata->handle_ptrs[i] == Cmnd)
+			break;
+
+	if (i == QLOGICFC_REQ_QUEUE_LEN)
+		return SCSI_ABORT_ERROR;
+
+	isp2100_disable_irqs(host);
+
+	param[0] = MBOX_ABORT_IOCB;
+	param[1] = (((u_short) Cmnd->target) << 8) | Cmnd->lun;
+	param[2] = i >> 16;
+	param[3] = i & 0xffff;
+
+	isp2100_mbox_command(host, param);
+
+	if (param[0] != MBOX_COMMAND_COMPLETE) {
+		printk("qlogicfc : scsi abort failure: %x\n", param[0]);
+		if (param[0] == 0x4005)
+			Cmnd->result = DID_ERROR << 16;
+		if (param[0] == 0x4006)
+			Cmnd->result = DID_BAD_TARGET << 16;
+		(*Cmnd->scsi_done) (Cmnd);
+		return_status = SCSI_ABORT_ERROR;
+	}
+	isp2100_enable_irqs(host);
+
+	LEAVE("isp2100_abort");
+
+	return return_status;
+}
+
+
+int isp2100_reset(Scsi_Cmnd * Cmnd, unsigned int reset_flags)
+{
+	u_short param[8];
+	struct Scsi_Host *host;
+	struct isp2100_hostdata *hostdata;
+	int return_status = SCSI_RESET_SUCCESS;
+
+	ENTER("isp2100_reset");
+
+	host = Cmnd->host;
+	hostdata = (struct isp2100_hostdata *) host->hostdata;
+	param[0] = MBOX_BUS_RESET;
+	param[1] = 3;
+
+	isp2100_disable_irqs(host);
+
+	isp2100_mbox_command(host, param);
+
+	if (param[0] != MBOX_COMMAND_COMPLETE) {
+		printk("qlogicfc : scsi bus reset failure: %x\n", param[0]);
+		return_status = SCSI_RESET_ERROR;
+	}
+	isp2100_enable_irqs(host);
+
+	LEAVE("isp2100_reset");
+
+	return return_status;;
+}
+
+
+int isp2100_biosparam(Disk * disk, kdev_t n, int ip[])
+{
+	int size = disk->capacity;
+
+	ENTER("isp2100_biosparam");
+
+	ip[0] = 64;
+	ip[1] = 32;
+	ip[2] = size >> 11;
+	if (ip[2] > 1024) {
+		ip[0] = 255;
+		ip[1] = 63;
+		ip[2] = size / (ip[0] * ip[1]);
+		if (ip[2] > 1023)
+			ip[2] = 1023;
+	}
+	LEAVE("isp2100_biosparam");
+
+	return 0;
+}
+
+
+static int isp2100_reset_hardware(struct Scsi_Host *host)
+{
+	u_short param[8];
+	struct isp2100_hostdata *hostdata;
+	int loop_count;
+
+	ENTER("isp2100_reset_hardware");
+
+	outw(0x01, host->io_port + ISP_CTRL_STATUS);
+	outw(HCCR_RESET, host->io_port + HOST_HCCR);
+	outw(HCCR_RELEASE, host->io_port + HOST_HCCR);
+	outw(HCCR_BIOS_DISABLE, host->io_port + HOST_HCCR);
+
+	loop_count = DEFAULT_LOOP_COUNT;
+	while (--loop_count && inw(host->io_port + HOST_HCCR) == RISC_BUSY)
+		barrier();
+	if (!loop_count)
+		printk("qlogicfc: reset_hardware loop timeout\n");
+
+
+
+#if DEBUG_ISP2100
+	printk("qlogicfc : mbox 0 0x%04x \n", inw(host->io_port + MBOX0));
+	printk("qlogicfc : mbox 1 0x%04x \n", inw(host->io_port + MBOX1));
+	printk("qlogicfc : mbox 2 0x%04x \n", inw(host->io_port + MBOX2));
+	printk("qlogicfc : mbox 3 0x%04x \n", inw(host->io_port + MBOX3));
+	printk("qlogicfc : mbox 4 0x%04x \n", inw(host->io_port + MBOX4));
+	printk("qlogicfc : mbox 5 0x%04x \n", inw(host->io_port + MBOX5));
+	printk("qlogicfc : mbox 6 0x%04x \n", inw(host->io_port + MBOX6));
+	printk("qlogicfc : mbox 7 0x%04x \n", inw(host->io_port + MBOX7));
+#endif				/* DEBUG_ISP2100 */
+
+	DEBUG(printk("qlogicfc : verifying checksum\n"));
+
+#if RELOAD_FIRMWARE
+	{
+		int i;
+		for (i = 0; i < risc_code_length01; i++) {
+			param[0] = MBOX_WRITE_RAM_WORD;
+			param[1] = risc_code_addr01 + i;
+			param[2] = risc_code01[i];
+
+			isp2100_mbox_command(host, param);
+
+			if (param[0] != MBOX_COMMAND_COMPLETE) {
+				printk("qlogicfc : firmware load failure\n");
+				return 1;
+			}
+		}
+	}
+#endif				/* RELOAD_FIRMWARE */
+
+	param[0] = MBOX_VERIFY_CHECKSUM;
+	param[1] = risc_code_addr01;
+
+	isp2100_mbox_command(host, param);
+
+	if (param[0] != MBOX_COMMAND_COMPLETE) {
+		printk("qlogicfc : ram checksum failure\n");
+		return 1;
+	}
+	DEBUG(printk("qlogicfc : executing firmware\n"));
+
+	param[0] = MBOX_EXEC_FIRMWARE;
+	param[1] = risc_code_addr01;
+
+	isp2100_mbox_command(host, param);
+
+	param[0] = MBOX_ABOUT_FIRMWARE;
+
+	isp2100_mbox_command(host, param);
+
+	if (param[0] != MBOX_COMMAND_COMPLETE) {
+		printk("qlogicfc : about firmware failure\n");
+		return 1;
+	}
+	DEBUG(printk("qlogicfc : firmware major revision %d\n", param[1]));
+	DEBUG(printk("qlogicfc : firmware minor revision %d\n", param[2]));
+
+	hostdata = (struct isp2100_hostdata *) host->hostdata;
+
+#ifdef USE_NVRAM_DEFAULTS
+
+	if (isp2100_get_nvram_defaults(host, &hostdata->control_block) != 0) {
+		printk("qlogicfc: Could not read from NVRAM\n");
+	}
+#endif
+
+	hostdata->wwn = (u64) (hostdata->control_block.node_name[0]) << 56;
+	hostdata->wwn |= (u64) (hostdata->control_block.node_name[0] & 0xff00) << 48;
+	hostdata->wwn |= (u64) (hostdata->control_block.node_name[1] & 0xff00) << 24;
+	hostdata->wwn |= (u64) (hostdata->control_block.node_name[1] & 0x00ff) << 48;
+	hostdata->wwn |= (u64) (hostdata->control_block.node_name[2] & 0x00ff) << 24;
+	hostdata->wwn |= (u64) (hostdata->control_block.node_name[2] & 0xff00) << 8;
+	hostdata->wwn |= (u64) (hostdata->control_block.node_name[3] & 0x00ff) << 8;
+	hostdata->wwn |= (u64) (hostdata->control_block.node_name[3] & 0xff00) >> 8;
+
+	param[0] = MBOX_INIT_FIRMWARE;
+	param[2] = (u_short) (virt_to_bus_low32(&hostdata->control_block) >> 16);
+	param[3] = (u_short) (virt_to_bus_low32(&hostdata->control_block) & 0xffff);
+	param[4] = 0;
+	param[5] = 0;
+	param[6] = (u_short) (virt_to_bus_high32(&hostdata->control_block) >> 16);
+	param[7] = (u_short) (virt_to_bus_high32(&hostdata->control_block) & 0xffff);
+	isp2100_mbox_command(host, param);
+	if (param[0] != MBOX_COMMAND_COMPLETE) {
+		printk("qlogicfc.c: Ouch 0x%04x\n", param[0]);
+		return 1;
+	}
+	param[0] = MBOX_GET_FIRMWARE_STATE;
+	isp2100_mbox_command(host, param);
+	if (param[0] != MBOX_COMMAND_COMPLETE) {
+		printk("qlogicfc.c: 0x%04x\n", param[0]);
+		return 1;
+	}
+
+	LEAVE("isp2100_reset_hardware");
+
+	return 0;
+}
+
+#ifdef USE_NVRAM_DEFAULTS
+
+static int isp2100_get_nvram_defaults(struct Scsi_Host *host, struct init_cb *control_block)
+{
+
+	u_short value;
+	if (isp2100_read_nvram_word(host, 0) != 0x5349)
+		return 1;
+
+	control_block->max_frame_len = isp2100_read_nvram_word(host, 5);
+	control_block->max_iocb = isp2100_read_nvram_word(host, 6);
+	control_block->exec_throttle = isp2100_read_nvram_word(host, 7);
+	value = isp2100_read_nvram_word(host, 8);
+	control_block->node_name[0] = isp2100_read_nvram_word(host, 9);
+	control_block->node_name[1] = isp2100_read_nvram_word(host, 10);
+	control_block->node_name[2] = isp2100_read_nvram_word(host, 11);
+	control_block->node_name[3] = isp2100_read_nvram_word(host, 12);
+	control_block->hard_addr = isp2100_read_nvram_word(host, 13);
+
+	return 0;
+
+}
+
+#endif
+
+static int isp2100_init(struct Scsi_Host *sh)
+{
+	u_int io_base;
+	struct isp2100_hostdata *hostdata;
+	u_char revision;
+	u_int irq;
+	u_short command;
+	struct pci_dev *pdev;
+
+
+	ENTER("isp2100_init");
+
+	hostdata = (struct isp2100_hostdata *) sh->hostdata;
+	pdev = hostdata->pci_dev;
+
+	if (pci_read_config_word(pdev, PCI_COMMAND, &command)
+	  || pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision)) {
+		printk("qlogicfc : error reading PCI configuration\n");
+		return 1;
+	}
+	io_base = pdev->base_address[0];
+	irq = pdev->irq;
+
+
+
+	if (pdev->vendor != PCI_VENDOR_ID_QLOGIC) {
+		printk("qlogicfc : 0x%04x is not QLogic vendor ID\n",
+		       pdev->vendor);
+		return 1;
+	}
+	if (pdev->device != PCI_DEVICE_ID_QLOGIC_ISP2100) {
+		printk("qlogicfc : 0x%04x does not match ISP2100 device id\n",
+		       pdev->device);
+		return 1;
+	}
+	if (command & PCI_COMMAND_IO && (io_base & 3) == 1)
+		io_base &= PCI_BASE_ADDRESS_IO_MASK;
+	else {
+		printk("qlogicfc : i/o mapping is disabled\n");
+		return 1;
+	}
+
+	if (!(command & PCI_COMMAND_MASTER)) {
+		printk("qlogicfc : bus mastering is disabled\n");
+		return 1;
+	}
+	if (revision != ISP2100_REV_ID && revision != ISP2100_REV_ID3)
+		printk("qlogicfc : new isp2100 revision ID (%d)\n", revision);
+
+
+	hostdata->revision = revision;
+
+	sh->irq = irq;
+	sh->io_port = io_base;
+
+	LEAVE("isp2100_init");
+
+	return 0;
+}
+
+#if USE_NVRAM_DEFAULTS
+
+#define NVRAM_DELAY() udelay(10)	/* 10 microsecond delay */
+
+
+u_short isp2100_read_nvram_word(struct Scsi_Host * host, u_short byte)
+{
+	int i;
+	u_short value, output, input;
+
+	outw(0x2, host->io_port + PCI_NVRAM);
+	NVRAM_DELAY();
+	outw(0x3, host->io_port + PCI_NVRAM);
+	NVRAM_DELAY();
+
+	byte &= 0xff;
+	byte |= 0x0600;
+	for (i = 10; i >= 0; i--) {
+		output = ((byte >> i) & 0x1) ? 0x4 : 0x0;
+		outw(output | 0x2, host->io_port + PCI_NVRAM);
+		NVRAM_DELAY();
+		outw(output | 0x3, host->io_port + PCI_NVRAM);
+		NVRAM_DELAY();
+		outw(output | 0x2, host->io_port + PCI_NVRAM);
+		NVRAM_DELAY();
+	}
+
+	for (i = 0xf, value = 0; i >= 0; i--) {
+		value <<= 1;
+		outw(0x3, host->io_port + PCI_NVRAM);
+		NVRAM_DELAY();
+		input = inw(host->io_port + PCI_NVRAM);
+		NVRAM_DELAY();
+		outw(0x2, host->io_port + PCI_NVRAM);
+		NVRAM_DELAY();
+		if (input & 0x8)
+			value |= 1;
+	}
+
+	outw(0x0, host->io_port + PCI_NVRAM);
+	NVRAM_DELAY();
+
+	return value;
+}
+
+
+#endif				/* USE_NVRAM_DEFAULTS */
+
+
+
+/*
+ * currently, this is only called during initialization or abort/reset,
+ * at which times interrupts are disabled, so polling is OK, I guess...
+ */
+static int isp2100_mbox_command(struct Scsi_Host *host, u_short param[])
+{
+	int loop_count;
+	struct isp2100_hostdata *hostdata = (struct isp2100_hostdata *) host->hostdata;
+
+	if (mbox_param[param[0]] == 0)
+		return 1;
+
+	loop_count = DEFAULT_LOOP_COUNT;
+	while (--loop_count && inw(host->io_port + HOST_HCCR) & 0x0080)
+		barrier();
+	if (!loop_count) {
+		printk("qlogicfc: mbox_command loop timeout #1\n");
+		param[0] = 0x4006;
+		return 1;
+	}
+	hostdata->mbox_done = 0;
+
+	if (mbox_param[param[0]] == 0)
+		printk("qlogicfc: invalid mbox command\n");
+
+	if (mbox_param[param[0]] & 0x80)
+		outw(param[7], host->io_port + MBOX7);
+	if (mbox_param[param[0]] & 0x40)
+		outw(param[6], host->io_port + MBOX6);
+	if (mbox_param[param[0]] & 0x20)
+		outw(param[5], host->io_port + MBOX5);
+	if (mbox_param[param[0]] & 0x10)
+		outw(param[4], host->io_port + MBOX4);
+	if (mbox_param[param[0]] & 0x08)
+		outw(param[3], host->io_port + MBOX3);
+	if (mbox_param[param[0]] & 0x04)
+		outw(param[2], host->io_port + MBOX2);
+	if (mbox_param[param[0]] & 0x02)
+		outw(param[1], host->io_port + MBOX1);
+	if (mbox_param[param[0]] & 0x01)
+		outw(param[0], host->io_port + MBOX0);
+
+
+	outw(HCCR_SET_HOST_INTR, host->io_port + HOST_HCCR);
+
+	while (1) {
+		loop_count = DEFAULT_LOOP_COUNT;
+		while (--loop_count && !(inw(host->io_port + PCI_INTER_STS) & 0x08)) {
+			barrier();
+		}
+
+		if (!loop_count) {
+			printk("qlogicfc: mbox_command loop timeout #2\n");
+			break;
+		}
+		isp2100_intr_handler(host->irq, host, NULL);
+
+		if (hostdata->mbox_done == 1)
+			break;
+
+	}
+
+	loop_count = DEFAULT_LOOP_COUNT;
+	while (--loop_count && inw(host->io_port + MBOX0) == 0x04) {
+		barrier();
+	}
+	if (!loop_count)
+		printk("qlogicfc: mbox_command loop timeout #3\n");
+
+	param[7] = inw(host->io_port + MBOX7);
+	param[6] = inw(host->io_port + MBOX6);
+	param[5] = inw(host->io_port + MBOX5);
+	param[4] = inw(host->io_port + MBOX4);
+	param[3] = inw(host->io_port + MBOX3);
+	param[2] = inw(host->io_port + MBOX2);
+	param[1] = inw(host->io_port + MBOX1);
+	param[0] = inw(host->io_port + MBOX0);
+
+
+	outw(0x0, host->io_port + PCI_SEMAPHORE);
+
+	if (inw(host->io_port + HOST_HCCR) & 0x0080) {
+		printk("mbox op is still pending\n");
+	}
+	return 0;
+}
+
+
+#if DEBUG_ISP2100_INTR
+
+void isp2100_print_status_entry(struct Status_Entry *status)
+{
+	printk("qlogicfc : entry count = 0x%02x, type = 0x%02x, flags = 0x%02x\n",
+	status->hdr.entry_cnt, status->hdr.entry_type, status->hdr.flags);
+	printk("qlogicfc : scsi status = 0x%04x, completion status = 0x%04x\n",
+	       status->scsi_status, status->completion_status);
+	printk("qlogicfc : state flags = 0x%04x, status flags = 0x%04x\n",
+	       status->state_flags, status->status_flags);
+	printk("qlogicfc : response info length = 0x%04x, request sense length = 0x%04x\n",
+	       status->res_info_len, status->req_sense_len);
+	printk("qlogicfc : residual transfer length = 0x%08x, response = 0x%02x\n", status->residual, status->res_info[3]);
+
+}
+
+#endif				/* DEBUG_ISP2100_INTR */
+
+
+#if DEBUG_ISP2100
+
+void isp2100_print_scsi_cmd(Scsi_Cmnd * cmd)
+{
+	int i;
+
+	printk("qlogicfc : target = 0x%02x, lun = 0x%02x, cmd_len = 0x%02x\n",
+	       cmd->target, cmd->lun, cmd->cmd_len);
+	printk("qlogicfc : command = ");
+	for (i = 0; i < cmd->cmd_len; i++)
+		printk("0x%02x ", cmd->cmnd[i]);
+	printk("\n");
+}
+
+#endif				/* DEBUG_ISP2100 */
+
+
+#ifdef MODULE
+
+Scsi_Host_Template driver_template = QLOGICFC;
+
+#include "scsi_module.c"
+
+#endif
diff -u --recursive --new-file v2.2.2/linux/drivers/scsi/qlogicfc.h linux/drivers/scsi/qlogicfc.h
--- v2.2.2/linux/drivers/scsi/qlogicfc.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/qlogicfc.h	Wed Feb 24 16:27:54 1999
@@ -0,0 +1,102 @@
+/*
+ * QLogic ISP2100 SCSI-FCP
+ * 
+ * Written by Erik H. Moe, ehm@cris.com
+ * Copyright 1995, Erik H. Moe
+ *
+ * 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.
+ */
+
+/* Renamed and updated to 1.3.x by Michael Griffith <grif@cs.ucr.edu> */
+
+/* This is a version of the isp1020 driver which was modified by
+ * Chris Loveland <cwl@iol.unh.edu> to support the isp2100
+ */
+
+
+/*
+ * $Date: 1995/09/22 02:32:56 $
+ * $Revision: 0.5 $
+ *
+ * $Log: isp1020.h,v $
+ * Revision 0.5  1995/09/22  02:32:56  root
+ * do auto request sense
+ *
+ * Revision 0.4  1995/08/07  04:48:28  root
+ * supply firmware with driver.
+ * numerous bug fixes/general cleanup of code.
+ *
+ * Revision 0.3  1995/07/16  16:17:16  root
+ * added reset/abort code.
+ *
+ * Revision 0.2  1995/06/29  03:19:43  root
+ * fixed biosparam.
+ * added queue protocol.
+ *
+ * Revision 0.1  1995/06/25  01:56:13  root
+ * Initial release.
+ *
+ */
+
+#ifndef _QLOGICFC_H
+#define _QLOGICFC_H
+
+/*
+ * With the qlogic interface, every queue slot can hold a SCSI
+ * command with up to 2 scatter/gather entries.  If we need more
+ * than 2 entries, continuation entries can be used that hold
+ * another 5 entries each.  Unlike for other drivers, this means
+ * that the maximum number of scatter/gather entries we can
+ * support at any given time is a function of the number of queue
+ * slots available.  That is, host->can_queue and host->sg_tablesize
+ * are dynamic and _not_ independent.  This all works fine because
+ * requests are queued serially and the scatter/gather limit is
+ * determined for each queue request anew.
+ */
+#define QLOGICFC_REQ_QUEUE_LEN	63	/* must be power of two - 1 */
+#define QLOGICFC_MAX_SG(ql)	(2 + (((ql) > 0) ? 5*((ql) - 1) : 0))
+#define QLOGICFC_CMD_PER_LUN    8
+
+int isp2100_detect(Scsi_Host_Template *);
+int isp2100_release(struct Scsi_Host *);
+const char * isp2100_info(struct Scsi_Host *);
+int isp2100_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
+int isp2100_abort(Scsi_Cmnd *);
+int isp2100_reset(Scsi_Cmnd *, unsigned int);
+int isp2100_biosparam(Disk *, kdev_t, int[]);
+
+#ifndef NULL
+#define NULL (0)
+#endif
+
+extern struct proc_dir_entry proc_scsi_isp2100;
+
+#define QLOGICFC {							   \
+        detect:                 isp2100_detect,                            \
+        release:                isp2100_release,                           \
+        info:                   isp2100_info,                              \
+        queuecommand:           isp2100_queuecommand,                      \
+        abort:                  isp2100_abort,                             \
+        reset:                  isp2100_reset,                             \
+        bios_param:             isp2100_biosparam,                         \
+        can_queue:              QLOGICFC_REQ_QUEUE_LEN,                    \
+        this_id:                -1,                                        \
+        sg_tablesize:           QLOGICFC_MAX_SG(QLOGICFC_REQ_QUEUE_LEN),   \
+        cmd_per_lun:            QLOGICFC_CMD_PER_LUN,                      \
+        present:                0,                                         \
+        unchecked_isa_dma:      0,                                         \
+        use_clustering:         DISABLE_CLUSTERING                         \
+}
+
+#endif /* _QLOGICFC_H */
+
+
+
diff -u --recursive --new-file v2.2.2/linux/drivers/scsi/qlogicfc_asm.c linux/drivers/scsi/qlogicfc_asm.c
--- v2.2.2/linux/drivers/scsi/qlogicfc_asm.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/qlogicfc_asm.c	Wed Feb 24 16:27:54 1999
@@ -0,0 +1,2985 @@
+/************************************************************************
+ *									*
+ * 	 --- ISP2100 Fabric Initiator/Target Firmware ---               *
+ *									*
+ *									*
+ *									*
+ ************************************************************************
+ */
+/*
+ *	Firmware Version 1.13.00 (18:06 May 04, 1998)
+ */
+
+unsigned short risc_code_version = 1*1024+13;
+
+unsigned char firmware_version[] = {1,13,0};
+
+unsigned short risc_code_addr01 = 0x1000 ;
+
+unsigned short risc_code01[] = { 
+	0x0078, 0x1029, 0x0000, 0x5c95, 0x0000, 0x2043, 0x4f50, 0x5952,
+	0x4947, 0x4854, 0x2031, 0x3939, 0x3620, 0x514c, 0x4f47, 0x4943,
+	0x2043, 0x4f52, 0x504f, 0x5241, 0x5449, 0x4f4e, 0x2049, 0x5350,
+	0x3231, 0x3030, 0x2046, 0x6972, 0x6d77, 0x6172, 0x6520, 0x2056,
+	0x6572, 0x7369, 0x6f6e, 0x2030, 0x312e, 0x3133, 0x2020, 0x2020,
+	0x2400, 0x20c1, 0x0021, 0x20a1, 0x6c95, 0x2009, 0x0000, 0x20a9,
+	0x076b, 0x41a4, 0x3400, 0x20c9, 0x71ff, 0x2091, 0x2000, 0x2059,
+	0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x1e36, 0x2051, 0x6d00,
+	0x2a70, 0x705b, 0x8c00, 0x705f, 0xffff, 0x7057, 0x8bf9, 0x7063,
+	0x0300, 0x1078, 0x1264, 0x20a1, 0x7400, 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, 0x122b, 0x1078, 0x134e, 0x1078, 0x14d3, 0x1078, 0x17d7,
+	0x1078, 0x324a, 0x1078, 0x54fc, 0x1078, 0x12d9, 0x1078, 0x2191,
+	0x1078, 0x3875, 0x1078, 0x3655, 0x1078, 0x4064, 0x1078, 0x1c35,
+	0x1078, 0x4213, 0x1078, 0x3d73, 0x1078, 0x1b5d, 0x1078, 0x1c14,
+	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, 0x2a96, 0x1078, 0x21b9, 0x1078, 0x38c5,
+	0x1078, 0x373c, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0048,
+	0x10c1, 0x1078, 0x4078, 0x0078, 0x10a4, 0x1079, 0x10c5, 0x0078,
+	0x10aa, 0x1078, 0x52d8, 0x0078, 0x10b9, 0x10cf, 0x10d0, 0x1151,
+	0x10cd, 0x11aa, 0x1228, 0x1229, 0x122a, 0x1078, 0x12b7, 0x007c,
+	0x127e, 0x0f7e, 0x2091, 0x8000, 0x1078, 0x2aec, 0x2079, 0x0100,
+	0x7844, 0xa005, 0x00c0, 0x1142, 0x2011, 0x318e, 0x1078, 0x40d1,
+	0x780f, 0x00ff, 0x7840, 0xa084, 0xfffb, 0x7842, 0x2011, 0x8010,
+	0x73b8, 0x1078, 0x2a53, 0x1078, 0x5129, 0x2011, 0x0004, 0x1078,
+	0x6135, 0x1078, 0x35ef, 0x70c7, 0x0000, 0x70bf, 0x0000, 0x70c3,
+	0x0000, 0x1078, 0x1145, 0x2011, 0x0000, 0x2079, 0x6d51, 0x7804,
+	0xd0ac, 0x0040, 0x1104, 0xc295, 0x70a4, 0xa005, 0x0040, 0x1109,
+	0xc29d, 0x72be, 0xa296, 0x0004, 0x0040, 0x112a, 0x2011, 0x0001,
+	0x1078, 0x6135, 0x708b, 0x0000, 0x708f, 0xffff, 0x7003, 0x0002,
+	0x0f7f, 0x1078, 0x1ee6, 0x2011, 0x0005, 0x1078, 0x5232, 0x1078,
+	0x476a, 0x0c7e, 0x2061, 0x0100, 0x60e3, 0x0008, 0x0c7f, 0x127f,
+	0x0078, 0x1144, 0x7003, 0x0003, 0x2001, 0x0000, 0x1078, 0x1dc9,
+	0x2011, 0x0000, 0x1078, 0x5232, 0x2011, 0x0000, 0x1078, 0x523c,
+	0x0c7e, 0x2061, 0x0100, 0x60e3, 0x0008, 0x0c7f, 0x1078, 0x476a,
+	0x1078, 0x4821, 0x0f7f, 0x127f, 0x007c, 0x0c7e, 0x20a9, 0x0082,
+	0x2009, 0x007e, 0x1078, 0x342f, 0x8108, 0x00f0, 0x114a, 0x0c7f,
+	0x007c, 0x127e, 0x2091, 0x8000, 0x708c, 0xa086, 0xffff, 0x0040,
+	0x115f, 0x1078, 0x1ee6, 0x1078, 0x476a, 0x0078, 0x11a8, 0x70bc,
+	0xd09c, 0x0040, 0x1187, 0xd084, 0x0040, 0x1187, 0x0f7e, 0x2079,
+	0x0100, 0x790c, 0xc1b5, 0x790e, 0x0f7f, 0xd08c, 0x0040, 0x1187,
+	0x70c0, 0xa086, 0xffff, 0x0040, 0x1183, 0x1078, 0x1fdb, 0x1078,
+	0x476a, 0x2011, 0x0001, 0x2019, 0x0000, 0x1078, 0x2013, 0x1078,
+	0x476a, 0x0078, 0x11a8, 0x70c4, 0xa005, 0x00c0, 0x11a8, 0x7088,
+	0xa005, 0x00c0, 0x11a8, 0x7003, 0x0003, 0x708f, 0xffff, 0x2001,
+	0x0000, 0x1078, 0x1dc9, 0x1078, 0x2ad1, 0x2001, 0x6f11, 0x2004,
+	0xa086, 0x0005, 0x00c0, 0x11a0, 0x2011, 0x0000, 0x1078, 0x5232,
+	0x2011, 0x0000, 0x1078, 0x523c, 0x1078, 0x476a, 0x1078, 0x4821,
+	0x127f, 0x007c, 0x017e, 0x0f7e, 0x127e, 0x2091, 0x8000, 0x2079,
+	0x0100, 0x7843, 0x0000, 0x7924, 0xd1b4, 0x0040, 0x11b9, 0x7827,
+	0x0040, 0xd19c, 0x0040, 0x11be, 0x7827, 0x0008, 0x007e, 0x037e,
+	0x157e, 0x7900, 0xa18a, 0x0003, 0x0050, 0x11e4, 0x7954, 0xd1ac,
+	0x00c0, 0x11e4, 0x2009, 0x00f8, 0x1078, 0x3233, 0x7843, 0x0090,
+	0x7843, 0x0010, 0x20a9, 0x09c4, 0x7820, 0xd09c, 0x00c0, 0x11dc,
+	0x7824, 0xd0ac, 0x00c0, 0x1218, 0x00f0, 0x11d4, 0x2001, 0x0001,
+	0x1078, 0x1dc9, 0x0078, 0x1221, 0x7853, 0x0000, 0x782f, 0x0020,
+	0x20a9, 0x0008, 0x00e0, 0x11ea, 0x2091, 0x6000, 0x00f0, 0x11ea,
+	0x7853, 0x0400, 0x782f, 0x0000, 0x2009, 0x00f8, 0x1078, 0x3233,
+	0x20a9, 0x000e, 0x0005, 0x00f0, 0x11fa, 0x7853, 0x1400, 0x7843,
+	0x0090, 0x7843, 0x0010, 0x2019, 0x61a8, 0x7854, 0x0005, 0x0005,
+	0xd08c, 0x0040, 0x120f, 0x7824, 0xd0ac, 0x00c0, 0x1218, 0x8319,
+	0x00c0, 0x1205, 0x2001, 0x0001, 0x1078, 0x1dc9, 0x0078, 0x121f,
+	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, 0x1237, 0x704f, 0xffff, 0x0078, 0x1239, 0x704f,
+	0x0000, 0x7053, 0xffff, 0x7067, 0x0000, 0x706b, 0x0000, 0x2061,
+	0x6f00, 0x6003, 0x0909, 0x6007, 0x0000, 0x600b, 0x8800, 0x600f,
+	0x0200, 0x6013, 0x00ff, 0x6017, 0x0003, 0x601b, 0x0000, 0x601f,
+	0x07d0, 0x2061, 0x6f08, 0x6003, 0x8000, 0x6007, 0x0000, 0x600b,
+	0x0000, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x0000, 0x601b,
+	0x0001, 0x601f, 0x0000, 0x007c, 0x1078, 0x128a, 0x2011, 0x0000,
+	0x81ff, 0x0040, 0x1289, 0xa186, 0x0001, 0x00c0, 0x1279, 0x705f,
+	0x8fff, 0x7057, 0x7c01, 0x7063, 0x0100, 0x705b, 0x7c00, 0x0078,
+	0x1287, 0xa186, 0x0002, 0x00c0, 0x1281, 0x2011, 0x0000, 0x0078,
+	0x1287, 0xa186, 0x0005, 0x00c0, 0x1287, 0x2011, 0x0001, 0x1078,
+	0x12b1, 0x007c, 0x2009, 0x0000, 0x2011, 0x0000, 0x1078, 0x12b1,
+	0x2019, 0xaaaa, 0x2061, 0xffff, 0x2362, 0x2c24, 0x2061, 0x7fff,
+	0x2c04, 0xa406, 0x0040, 0x129f, 0xc18d, 0x0078, 0x12ac, 0xc185,
+	0x2011, 0x0001, 0x1078, 0x12b1, 0x2061, 0xffff, 0x2362, 0x2c04,
+	0xa306, 0x00c0, 0x12ac, 0xc195, 0x2011, 0x0001, 0x1078, 0x12b1,
+	0x007c, 0x3800, 0xa084, 0xfffc, 0xa205, 0x20c0, 0x007c, 0x2091,
+	0x8000, 0x0068, 0x12b9, 0x007e, 0x017e, 0x2079, 0x0000, 0x7818,
+	0xa084, 0x0000, 0x00c0, 0x12bf, 0x017f, 0x792e, 0x007f, 0x782a,
+	0x007f, 0x7826, 0x7823, 0x8002, 0x781b, 0x0001, 0x2091, 0x5000,
+	0x2091, 0x4080, 0x2079, 0x6d00, 0x7803, 0x0005, 0x0078, 0x12d6,
+	0x007c, 0x2071, 0x6d00, 0x7158, 0x712e, 0x2021, 0x0001, 0xa190,
+	0x002d, 0xa298, 0x002d, 0x0048, 0x12ef, 0x705c, 0xa302, 0x00c8,
+	0x12ef, 0x220a, 0x2208, 0x2310, 0x8420, 0x0078, 0x12e1, 0x200b,
+	0x0000, 0x749e, 0x74a2, 0x007c, 0x0e7e, 0x127e, 0x2091, 0x8000,
+	0x2071, 0x6d00, 0x70a0, 0xa0ea, 0x0010, 0x00c8, 0x1302, 0xa06e,
+	0x0078, 0x130c, 0x8001, 0x70a2, 0x702c, 0x2068, 0x2d04, 0x702e,
+	0x206b, 0x0000, 0x6807, 0x0000, 0x127f, 0x0e7f, 0x007c, 0x0e7e,
+	0x2071, 0x6d00, 0x127e, 0x2091, 0x8000, 0x70a0, 0x8001, 0x00c8,
+	0x131c, 0xa06e, 0x0078, 0x1325, 0x70a2, 0x702c, 0x2068, 0x2d04,
+	0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x127f, 0x0e7f, 0x007c,
+	0x0e7e, 0x127e, 0x2091, 0x8000, 0x2071, 0x6d00, 0x702c, 0x206a,
+	0x2d00, 0x702e, 0x70a0, 0x8000, 0x70a2, 0x127f, 0x0e7f, 0x007c,
+	0x8dff, 0x0040, 0x1344, 0x6804, 0x6807, 0x0000, 0x007e, 0x1078,
+	0x1328, 0x0d7f, 0x0078, 0x1338, 0x007c, 0x0e7e, 0x2071, 0x6d00,
+	0x70a0, 0xa08a, 0x0010, 0xa00d, 0x0e7f, 0x007c, 0x0e7e, 0x2071,
+	0x6f31, 0x7007, 0x0000, 0x701b, 0x0000, 0x701f, 0x0000, 0x2071,
+	0x0000, 0x7010, 0xa085, 0x8004, 0x7012, 0x0e7f, 0x007c, 0x0e7e,
+	0x2270, 0x700b, 0x0000, 0x2071, 0x6f31, 0x7018, 0xa088, 0x6f3a,
+	0x220a, 0x8000, 0xa084, 0x0007, 0x701a, 0x7004, 0xa005, 0x00c0,
+	0x1377, 0x0f7e, 0x2079, 0x0010, 0x1078, 0x1388, 0x0f7f, 0x0e7f,
+	0x007c, 0x0e7e, 0x2071, 0x6f31, 0x7004, 0xa005, 0x00c0, 0x1386,
+	0x0f7e, 0x2079, 0x0010, 0x1078, 0x1388, 0x0f7f, 0x0e7f, 0x007c,
+	0x7000, 0x0079, 0x138b, 0x138f, 0x13f9, 0x1416, 0x1416, 0x7018,
+	0x711c, 0xa106, 0x00c0, 0x1397, 0x7007, 0x0000, 0x007c, 0x0d7e,
+	0xa180, 0x6f3a, 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, 0x13b9, 0x7007, 0x0001, 0x1078, 0x13be,
+	0x007c, 0x7007, 0x0002, 0x1078, 0x13d4, 0x007c, 0x017e, 0x027e,
+	0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x00c8, 0x13c9, 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, 0x13e8, 0x2110, 0xa006,
+	0x700e, 0x22a8, 0x53a6, 0x8203, 0x7822, 0x7803, 0x0020, 0x7803,
+	0x0001, 0x3300, 0x7016, 0x157f, 0x147f, 0x137f, 0x027f, 0x017f,
+	0x007c, 0x137e, 0x147e, 0x157e, 0x2099, 0x6dc5, 0x20a1, 0x0018,
+	0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x127e, 0x2091, 0x8000,
+	0x7803, 0x0041, 0x7007, 0x0003, 0x7000, 0xc084, 0x7002, 0x700b,
+	0x6dc0, 0x127f, 0x157f, 0x147f, 0x137f, 0x007c, 0x137e, 0x147e,
+	0x157e, 0x2001, 0x6df4, 0x209c, 0x20a1, 0x0014, 0x7803, 0x0026,
+	0x2001, 0x6df5, 0x20ac, 0x53a6, 0x2099, 0x6df6, 0x20a1, 0x0018,
+	0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x127e, 0x2091, 0x8000,
+	0x7803, 0x0001, 0x7007, 0x0004, 0x7000, 0xc08c, 0x7002, 0x700b,
+	0x6df1, 0x127f, 0x157f, 0x147f, 0x137f, 0x007c, 0x017e, 0x0e7e,
+	0x2071, 0x6f31, 0x0f7e, 0x2079, 0x0010, 0x7904, 0x7803, 0x0002,
+	0xd1fc, 0x0040, 0x1459, 0xa18c, 0x0700, 0x0040, 0x1456, 0x7008,
+	0xa080, 0x0002, 0x2003, 0x0200, 0x0078, 0x1459, 0x7004, 0x1079,
+	0x145d, 0x0f7f, 0x0e7f, 0x017f, 0x007c, 0x1388, 0x1465, 0x1487,
+	0x14a1, 0x14ca, 0x1463, 0x0078, 0x1463, 0x137e, 0x147e, 0x157e,
+	0x7014, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x7010, 0x20a8,
+	0x53a5, 0x3400, 0x7016, 0x157f, 0x147f, 0x137f, 0x700c, 0xa005,
+	0x0040, 0x148e, 0x1078, 0x13be, 0x007c, 0x7008, 0xa080, 0x0002,
+	0x2003, 0x0100, 0x7007, 0x0000, 0x1078, 0x1388, 0x007c, 0x700c,
+	0xa005, 0x0040, 0x148e, 0x1078, 0x13d4, 0x007c, 0x0d7e, 0x7008,
+	0x2068, 0x7830, 0x6826, 0x7834, 0x682a, 0x7838, 0x682e, 0x783c,
+	0x6832, 0x680b, 0x0100, 0x0d7f, 0x7007, 0x0000, 0x1078, 0x1388,
+	0x007c, 0x137e, 0x147e, 0x157e, 0x2001, 0x6dc3, 0x2004, 0xa080,
+	0x000d, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x20a9, 0x0020,
+	0x53a5, 0x2001, 0x6dc5, 0x2004, 0xd0bc, 0x0040, 0x14c0, 0x2001,
+	0x6dce, 0x2004, 0xa080, 0x000d, 0x20a0, 0x20a9, 0x0020, 0x53a5,
+	0x157f, 0x147f, 0x137f, 0x7007, 0x0000, 0x1078, 0x396e, 0x1078,
+	0x1388, 0x007c, 0x2001, 0x6df3, 0x2003, 0x0100, 0x7007, 0x0000,
+	0x1078, 0x1388, 0x007c, 0x127e, 0x2091, 0x2100, 0x2079, 0x0030,
+	0x2071, 0x6f42, 0x7003, 0x0000, 0x700f, 0x6f48, 0x7013, 0x6f48,
+	0x780f, 0x0070, 0x127f, 0x007c, 0x6934, 0xa184, 0x0007, 0x0079,
+	0x14e9, 0x14f1, 0x151b, 0x14f1, 0x14f1, 0x14f1, 0x1500, 0x14f1,
+	0x14f5, 0xa085, 0x0001, 0x0078, 0x1531, 0x684c, 0xd0bc, 0x0040,
+	0x14f1, 0x6860, 0x682e, 0x685c, 0x682a, 0x6858, 0x0078, 0x1523,
+	0xa18c, 0x00ff, 0xa186, 0x0015, 0x00c0, 0x14f1, 0x684c, 0xd0ac,
+	0x0040, 0x14f1, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084,
+	0x000f, 0xa080, 0x1a82, 0x2004, 0x6832, 0xa006, 0x682e, 0x682a,
+	0x6858, 0x0078, 0x152b, 0x684c, 0xd0ac, 0x0040, 0x14f1, 0xa006,
+	0x682e, 0x682a, 0x6858, 0xa18c, 0x000f, 0xa188, 0x1a82, 0x210c,
+	0x6932, 0x2d08, 0x691a, 0x6826, 0x684c, 0xc0dd, 0x684e, 0xa006,
+	0x680a, 0x007c, 0x82ff, 0x0040, 0x1545, 0xa280, 0x0004, 0x0d7e,
+	0x206c, 0x684c, 0xd0dc, 0x00c0, 0x1541, 0x1078, 0x14e4, 0x10c0,
+	0x12b7, 0x6808, 0x8000, 0x680a, 0x0d7f, 0x127e, 0x047e, 0x037e,
+	0x027e, 0x2091, 0x2100, 0x027f, 0x037f, 0x047f, 0x7000, 0xa005,
+	0x00c0, 0x1559, 0x7206, 0x2001, 0x156d, 0x007e, 0x2260, 0x0078,
+	0x164f, 0x710c, 0x220a, 0x8108, 0x230a, 0x8108, 0x240a, 0x8108,
+	0xa182, 0x6f63, 0x0048, 0x1566, 0x2009, 0x6f48, 0x710e, 0x7000,
+	0xa005, 0x00c0, 0x156d, 0x1078, 0x1638, 0x127f, 0x007c, 0x127e,
+	0x027e, 0x037e, 0x0c7e, 0x007e, 0x2091, 0x2100, 0x007f, 0x047f,
+	0x037f, 0x027f, 0x0c7e, 0x0d7e, 0x2460, 0x6110, 0x2168, 0x6a62,
+	0x6b5e, 0xa005, 0x0040, 0x15bc, 0x6808, 0xa005, 0x0040, 0x15ea,
+	0x7000, 0xa005, 0x00c0, 0x158e, 0x0078, 0x15b4, 0x700c, 0x7110,
+	0xa106, 0x00c0, 0x15ba, 0x7004, 0xa406, 0x00c0, 0x15b4, 0x2001,
+	0x0005, 0x2004, 0xd08c, 0x00c0, 0x15ee, 0x2001, 0x0207, 0x2004,
+	0xd09c, 0x00c0, 0x1597, 0x7804, 0xa084, 0x6000, 0x0040, 0x15ae,
+	0xa086, 0x6000, 0x0040, 0x15ae, 0x0078, 0x1597, 0x7803, 0x0004,
+	0x7003, 0x0000, 0x7004, 0x2060, 0x2009, 0x0048, 0x1078, 0x5591,
+	0x0078, 0x15ee, 0x0078, 0x15ee, 0x6808, 0xa005, 0x0040, 0x15ea,
+	0x7000, 0xa005, 0x00c0, 0x15c6, 0x0078, 0x15ea, 0x700c, 0x7110,
+	0xa106, 0x00c0, 0x15ba, 0x7004, 0xa406, 0x00c0, 0x15ea, 0x2001,
+	0x0005, 0x2004, 0xd08c, 0x00c0, 0x15ee, 0x2001, 0x0207, 0x2004,
+	0xd09c, 0x00c0, 0x15cf, 0x7804, 0xa084, 0x6000, 0x0040, 0x15e6,
+	0xa086, 0x6000, 0x0040, 0x15e6, 0x0078, 0x15cf, 0x7803, 0x0004,
+	0x7003, 0x0000, 0x2009, 0x0048, 0x1078, 0x5591, 0x0d7f, 0x0c7f,
+	0x127f, 0x007c, 0x0f7e, 0x0e7e, 0x2071, 0x6f42, 0x7000, 0xa086,
+	0x0000, 0x0040, 0x1635, 0x7004, 0xac06, 0x00c0, 0x1626, 0x2079,
+	0x0030, 0x7804, 0xd0fc, 0x00c0, 0x1622, 0x2001, 0x0207, 0x2004,
+	0xd09c, 0x00c0, 0x1601, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x00c0,
+	0x160d, 0x7908, 0xd1ec, 0x00c0, 0x1619, 0x2009, 0x0009, 0x0078,
+	0x161b, 0x2009, 0x0019, 0x7803, 0x0002, 0x7902, 0x7003, 0x0003,
+	0x0078, 0x1635, 0x1078, 0x16e5, 0x0078, 0x15f6, 0x157e, 0x20a9,
+	0x0009, 0x2009, 0x6f48, 0x2104, 0xac06, 0x00c0, 0x1630, 0x200a,
+	0xa188, 0x0003, 0x00f0, 0x162b, 0x157f, 0x0e7f, 0x0f7f, 0x007c,
+	0x700c, 0x7110, 0xa106, 0x00c0, 0x1640, 0x7003, 0x0000, 0x007c,
+	0x2104, 0x7006, 0x2060, 0x8108, 0x211c, 0x8108, 0x2124, 0x8108,
+	0xa182, 0x6f63, 0x0048, 0x164e, 0x2009, 0x6f48, 0x7112, 0x8cff,
+	0x00c0, 0x1658, 0x7803, 0x0019, 0x7003, 0x0003, 0x0078, 0x167b,
+	0x6010, 0x2068, 0x2d58, 0x6828, 0xa406, 0x00c0, 0x1663, 0x682c,
+	0xa306, 0x0040, 0x1667, 0x1078, 0x1aa2, 0x00c0, 0x1652, 0x6824,
+	0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, 0x000f,
+	0x2009, 0x0011, 0x1078, 0x167c, 0x0040, 0x167a, 0x2009, 0x0001,
+	0x1078, 0x167c, 0x2d58, 0x007c, 0x8aff, 0x0040, 0x16e0, 0xa03e,
+	0x2730, 0x6850, 0xd0fc, 0x00c0, 0x169b, 0x0d7e, 0x2804, 0xac68,
+	0x2900, 0x0079, 0x168b, 0x16ca, 0x16ab, 0x16ab, 0x16ca, 0x16ca,
+	0x16c2, 0x16ca, 0x16ab, 0x16ca, 0x16b1, 0x16b1, 0x16ca, 0x16ca,
+	0x16ca, 0x16ca, 0x16b1, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c,
+	0x6c20, 0x0d7e, 0xd99c, 0x0040, 0x16cd, 0x2804, 0xac68, 0x6f08,
+	0x6e0c, 0x0078, 0x16cd, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x0078,
+	0x16cd, 0x7b0c, 0xd3bc, 0x0040, 0x16ba, 0x7b08, 0xa39c, 0x0fff,
+	0x0078, 0x16bb, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c,
+	0x0078, 0x16cd, 0x0d7f, 0x1078, 0x1a3f, 0x00c0, 0x167c, 0xa00e,
+	0x0078, 0x16e0, 0x0d7f, 0x1078, 0x12b7, 0x7b22, 0x7a26, 0x7d32,
+	0x7c36, 0x7f3a, 0x7e3e, 0x7902, 0x7000, 0x8000, 0x7002, 0x0d7f,
+	0x6828, 0xa300, 0x682a, 0x682c, 0xa201, 0x682e, 0x1078, 0x1a3f,
+	0x007c, 0x1078, 0x12b7, 0x1078, 0x12b7, 0x127e, 0x2091, 0x2100,
+	0x007e, 0x017e, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002,
+	0xa184, 0x0700, 0x00c0, 0x16e3, 0xa184, 0x0003, 0xa086, 0x0003,
+	0x0040, 0x16e3, 0x7000, 0x0079, 0x16fd, 0x1701, 0x1703, 0x1779,
+	0x17c0, 0x1078, 0x12b7, 0x8001, 0x7002, 0xa184, 0x0880, 0x00c0,
+	0x1718, 0x8aff, 0x0040, 0x175b, 0x2009, 0x0001, 0x1078, 0x167c,
+	0x0040, 0x17d3, 0x2009, 0x0001, 0x1078, 0x167c, 0x0078, 0x17d3,
+	0x7803, 0x0004, 0x7003, 0x0000, 0xd1dc, 0x0040, 0x1751, 0x027e,
+	0x037e, 0x6b28, 0x6a2c, 0x7820, 0x686e, 0xa31a, 0x7824, 0x6872,
+	0xa213, 0x6b2a, 0x6a2e, 0x037f, 0x027f, 0x7830, 0x681e, 0x7834,
+	0x6822, 0x1078, 0x1a58, 0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800,
+	0x6832, 0x7003, 0x0000, 0x6850, 0xc0fd, 0x6852, 0x6808, 0x8001,
+	0x680a, 0x00c0, 0x174d, 0x684c, 0xd0e4, 0x0040, 0x174d, 0x7004,
+	0x2060, 0x2009, 0x0048, 0x1078, 0x5591, 0x1078, 0x1638, 0x0078,
+	0x17d3, 0x057e, 0x7d0c, 0xd5bc, 0x00c0, 0x1758, 0x1078, 0x6c41,
+	0x057f, 0x0078, 0x1773, 0x684c, 0xc0f5, 0x684e, 0x7814, 0xa005,
+	0x00c0, 0x1773, 0x7003, 0x0000, 0x6808, 0x8001, 0x680a, 0x00c0,
+	0x176f, 0x7004, 0x2060, 0x2009, 0x0048, 0x1078, 0x5591, 0x1078,
+	0x1638, 0x0078, 0x17d3, 0x7803, 0x0009, 0x7003, 0x0003, 0x0078,
+	0x17d3, 0x8001, 0x7002, 0xd194, 0x0040, 0x178b, 0x7804, 0xd0fc,
+	0x00c0, 0x16ed, 0x8aff, 0x0040, 0x17d3, 0x2009, 0x0001, 0x1078,
+	0x167c, 0x0078, 0x17d3, 0xa184, 0x0880, 0x00c0, 0x1798, 0x8aff,
+	0x0040, 0x17d3, 0x2009, 0x0001, 0x1078, 0x167c, 0x0078, 0x17d3,
+	0x7803, 0x0004, 0x7003, 0x0000, 0xd1dc, 0x0040, 0x17b9, 0x027e,
+	0x037e, 0x6b28, 0x6a2c, 0x1078, 0x1a58, 0x0d7e, 0x2804, 0xac68,
+	0x6034, 0xd09c, 0x00c0, 0x17b2, 0x6808, 0xa31a, 0x680c, 0xa213,
+	0x0078, 0x17b6, 0x6810, 0xa31a, 0x6814, 0xa213, 0x0d7f, 0x0078,
+	0x1723, 0x057e, 0x7d0c, 0x1078, 0x6c41, 0x057f, 0x0078, 0x1773,
+	0x7003, 0x0000, 0x7004, 0xa00d, 0x0040, 0x17d1, 0x6808, 0x8001,
+	0x680a, 0x00c0, 0x17d1, 0x7004, 0x2060, 0x2009, 0x0048, 0x1078,
+	0x5591, 0x1078, 0x1638, 0x017f, 0x007f, 0x127f, 0x007c, 0x0e7e,
+	0x2071, 0x6f63, 0x7003, 0x0000, 0x0e7f, 0x007c, 0x0d7e, 0xa280,
+	0x0004, 0x206c, 0x694c, 0xd1dc, 0x00c0, 0x1836, 0x6934, 0xa184,
+	0x0007, 0x0079, 0x17eb, 0x17f3, 0x1821, 0x17f3, 0x17f3, 0x17f3,
+	0x1806, 0x17f3, 0x17f5, 0x1078, 0x12b7, 0x684c, 0xd0b4, 0x0040,
+	0x192f, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, 0x687c,
+	0x680a, 0x6880, 0x680e, 0x6958, 0x0078, 0x1829, 0xa18c, 0x00ff,
+	0xa186, 0x0015, 0x00c0, 0x1836, 0x684c, 0xd0b4, 0x0040, 0x192f,
+	0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080,
+	0x1a82, 0x2004, 0x6832, 0x6958, 0xa006, 0x682e, 0x682a, 0x0078,
+	0x1832, 0x684c, 0xd0b4, 0x0040, 0x16e1, 0x6958, 0xa006, 0x682e,
+	0x682a, 0x2d00, 0x681a, 0x6834, 0xa084, 0x000f, 0xa080, 0x1a82,
+	0x2004, 0x6832, 0x6926, 0x684c, 0xc0dd, 0x684e, 0x0d7f, 0x007c,
+	0x0f7e, 0x2079, 0x0020, 0x7804, 0xd0fc, 0x10c0, 0x1933, 0x0e7e,
+	0x0d7e, 0x2071, 0x6f63, 0x7000, 0xa005, 0x00c0, 0x18b2, 0x0c7e,
+	0x7206, 0xa280, 0x0004, 0x205c, 0x7004, 0x2068, 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, 0x1874, 0x017e,
+	0x2009, 0x0008, 0xa102, 0x017f, 0xa108, 0x791a, 0x7116, 0x701e,
+	0x680c, 0xa081, 0x0000, 0x781e, 0x701a, 0xa006, 0x700e, 0x7012,
+	0x7004, 0x692c, 0x6814, 0xa106, 0x00c0, 0x188b, 0x6928, 0x6810,
+	0xa106, 0x0040, 0x1898, 0x037e, 0x047e, 0x6b14, 0x6c10, 0x1078,
+	0x1aa2, 0x047f, 0x037f, 0x0040, 0x1898, 0x0c7f, 0x0078, 0x18b2,
+	0x8aff, 0x00c0, 0x18a0, 0x0c7f, 0xa085, 0x0001, 0x0078, 0x18b2,
+	0x127e, 0x2091, 0x8000, 0x2079, 0x0020, 0x2009, 0x0001, 0x1078,
+	0x18b6, 0x0040, 0x18af, 0x2009, 0x0001, 0x1078, 0x18b6, 0x127f,
+	0x0c7f, 0xa006, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x077e, 0x067e,
+	0x057e, 0x047e, 0x037e, 0x027e, 0x8aff, 0x0040, 0x1928, 0x700c,
+	0x7214, 0xa202, 0x7010, 0x7218, 0xa203, 0x0048, 0x1927, 0xa03e,
+	0x2730, 0x6850, 0xd0fc, 0x00c0, 0x18e3, 0x0d7e, 0x2804, 0xac68,
+	0x2900, 0x0079, 0x18d3, 0x1909, 0x18f3, 0x18f3, 0x1909, 0x1909,
+	0x1901, 0x1909, 0x18f3, 0x1909, 0x18f9, 0x18f9, 0x1909, 0x1909,
+	0x1909, 0x1909, 0x18f9, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c,
+	0x6c20, 0xd99c, 0x0040, 0x190d, 0x0d7e, 0x2804, 0xac68, 0x6f08,
+	0x6e0c, 0x0078, 0x190c, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x0078,
+	0x190c, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0078,
+	0x190c, 0x0d7f, 0x1078, 0x1a3f, 0x00c0, 0x18bc, 0xa00e, 0x0078,
+	0x1928, 0x0d7f, 0x1078, 0x12b7, 0x0d7f, 0x7b22, 0x7a26, 0x7d32,
+	0x7c36, 0x7f3a, 0x7e3e, 0x7902, 0x7000, 0x8000, 0x7002, 0x6828,
+	0xa300, 0x682a, 0x682c, 0xa201, 0x682e, 0x700c, 0xa300, 0x700e,
+	0x7010, 0xa201, 0x7012, 0x1078, 0x1a3f, 0x0078, 0x1928, 0xa006,
+	0x027f, 0x037f, 0x047f, 0x057f, 0x067f, 0x077f, 0x007c, 0x1078,
+	0x12b7, 0x1078, 0x12b7, 0x127e, 0x2091, 0x2200, 0x007e, 0x017e,
+	0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x2079, 0x0020, 0x2071, 0x6f63,
+	0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700,
+	0x00c0, 0x1931, 0x7000, 0x0079, 0x194d, 0x1a09, 0x1951, 0x19d6,
+	0x1a07, 0x8001, 0x7002, 0xd19c, 0x00c0, 0x1965, 0x8aff, 0x0040,
+	0x199a, 0x2009, 0x0001, 0x1078, 0x18b6, 0x0040, 0x1a09, 0x2009,
+	0x0001, 0x1078, 0x18b6, 0x0078, 0x1a09, 0x7803, 0x0004, 0xd194,
+	0x0040, 0x1975, 0x6850, 0xc0fc, 0x6852, 0x8aff, 0x00c0, 0x1990,
+	0x684c, 0xc0f5, 0x684e, 0x0078, 0x1990, 0x027e, 0x037e, 0x6b28,
+	0x6a2c, 0x701c, 0xa005, 0x10c0, 0x1a11, 0x7820, 0x686e, 0xa31a,
+	0x7824, 0x6872, 0xa213, 0x6b2a, 0x6a2e, 0x037f, 0x027f, 0x7830,
+	0x681e, 0x7834, 0x6822, 0x1078, 0x1a58, 0x6850, 0xc0fd, 0x6852,
+	0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, 0x0000,
+	0x0078, 0x1a09, 0x711c, 0x81ff, 0x0040, 0x19af, 0x7922, 0x7827,
+	0x0000, 0x7803, 0x0001, 0x7000, 0x8000, 0x7002, 0x700c, 0xa100,
+	0x700e, 0x7010, 0xa081, 0x0000, 0x7012, 0x0078, 0x1a09, 0x0f7e,
+	0x027e, 0x781c, 0x007e, 0x7818, 0x007e, 0x2079, 0x0100, 0x7a14,
+	0xa284, 0x0004, 0xa085, 0x0012, 0x7816, 0x7820, 0xd0bc, 0x00c0,
+	0x19bd, 0x79c8, 0x007f, 0xa102, 0x78ca, 0x79c4, 0x007f, 0xa102,
+	0x78c6, 0xa284, 0x0004, 0xa085, 0x0012, 0x7816, 0x027f, 0x0f7f,
+	0x7803, 0x0008, 0x7003, 0x0000, 0x0078, 0x1a09, 0x8001, 0x7002,
+	0xd194, 0x0040, 0x19eb, 0x7804, 0xd0fc, 0x00c0, 0x1943, 0xd19c,
+	0x00c0, 0x1a05, 0x8aff, 0x0040, 0x1a09, 0x2009, 0x0001, 0x1078,
+	0x18b6, 0x0078, 0x1a09, 0x027e, 0x037e, 0x6b28, 0x6a2c, 0x1078,
+	0x1a58, 0x0d7e, 0x2804, 0xac68, 0x6034, 0xd09c, 0x00c0, 0x19fe,
+	0x6808, 0xa31a, 0x680c, 0xa213, 0x0078, 0x1a02, 0x6810, 0xa31a,
+	0x6814, 0xa213, 0x0d7f, 0x0078, 0x1979, 0x0078, 0x1975, 0x1078,
+	0x12b7, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x017f, 0x007f, 0x127f,
+	0x007c, 0x7920, 0xa108, 0x7922, 0x7924, 0xa189, 0x0000, 0x7926,
+	0x7930, 0xa10a, 0x7932, 0x7934, 0xa18b, 0x0000, 0x7936, 0x007c,
+	0x0f7e, 0x0e7e, 0x2071, 0x6f63, 0x7000, 0xa086, 0x0000, 0x0040,
+	0x1a3c, 0x2079, 0x0020, 0x7804, 0xa084, 0x0003, 0x0040, 0x1a36,
+	0x7803, 0x0004, 0x7804, 0xd0ac, 0x00c0, 0x1a32, 0x20e1, 0x9040,
+	0x7803, 0x0002, 0x7003, 0x0000, 0x0e7f, 0x0f7f, 0x007c, 0x8840,
+	0x2804, 0xa005, 0x00c0, 0x1a53, 0x6004, 0xa005, 0x0040, 0x1a55,
+	0x681a, 0x2060, 0x6034, 0xa084, 0x000f, 0xa080, 0x1a82, 0x2044,
+	0x88ff, 0x1040, 0x12b7, 0x8a51, 0x007c, 0x2051, 0x0000, 0x007c,
+	0x8a50, 0x8841, 0x2804, 0xa005, 0x00c0, 0x1a72, 0x2c00, 0xad06,
+	0x0040, 0x1a67, 0x6000, 0xa005, 0x00c0, 0x1a67, 0x2d00, 0x2060,
+	0x681a, 0x6034, 0xa084, 0x000f, 0xa080, 0x1a92, 0x2044, 0x88ff,
+	0x1040, 0x12b7, 0x007c, 0x0000, 0x0011, 0x0015, 0x0019, 0x001d,
+	0x0021, 0x0025, 0x0029, 0x0000, 0x000f, 0x0015, 0x001b, 0x0021,
+	0x0027, 0x0000, 0x0000, 0x1a78, 0x1a74, 0x0000, 0x0000, 0x8000,
+	0x0000, 0x1a78, 0x0000, 0x1a7f, 0x1a7c, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x1a7f, 0x0000, 0x1a7a, 0x1a7a, 0x0000, 0x0000, 0x8000,
+	0x0000, 0x1a7a, 0x0000, 0x1a80, 0x1a80, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x1a80, 0x0a7e, 0x097e, 0x087e, 0x6858, 0xa055, 0x0040,
+	0x1b28, 0x2d60, 0x6034, 0xa0cc, 0x000f, 0xa9c0, 0x1a82, 0xa986,
+	0x0007, 0x0040, 0x1ab7, 0xa986, 0x000f, 0x00c0, 0x1abb, 0x605c,
+	0xa422, 0x6060, 0xa31a, 0x2804, 0xa045, 0x00c0, 0x1ac9, 0x0050,
+	0x1ac3, 0x0078, 0x1b28, 0x6004, 0xa065, 0x0040, 0x1b28, 0x0078,
+	0x1aaa, 0x2804, 0xa005, 0x0040, 0x1ae7, 0xac68, 0xd99c, 0x00c0,
+	0x1ad7, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0078, 0x1adb, 0x6810,
+	0xa422, 0x6814, 0xa31b, 0x0048, 0x1af5, 0x2300, 0xa405, 0x0040,
+	0x1aed, 0x8a51, 0x0040, 0x1b28, 0x8840, 0x0078, 0x1ac9, 0x6004,
+	0xa065, 0x0040, 0x1b28, 0x0078, 0x1aaa, 0x8a51, 0x8840, 0x2b68,
+	0x6850, 0xc0fc, 0x6852, 0x0078, 0x1b22, 0x8422, 0x8420, 0x831a,
+	0xa399, 0x0000, 0x0d7e, 0x2b68, 0x6c6e, 0x6b72, 0x0d7f, 0xd99c,
+	0x00c0, 0x1b10, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300, 0xa11b,
+	0x1048, 0x12b7, 0x6800, 0xa420, 0x6804, 0xa319, 0x0078, 0x1b1c,
+	0x6910, 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b, 0x1048, 0x12b7,
+	0x6800, 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e, 0x6b22, 0x6850,
+	0xc0fd, 0x6852, 0x007f, 0x007f, 0x007f, 0xa006, 0x0078, 0x1b2d,
+	0x087f, 0x097f, 0x0a7f, 0xa085, 0x0001, 0x007c, 0x2001, 0x0005,
+	0x2004, 0xa084, 0x0007, 0x0079, 0x1b35, 0x1b3d, 0x1b3e, 0x1b41,
+	0x1b44, 0x1b49, 0x1b4c, 0x1b51, 0x1b56, 0x007c, 0x1078, 0x1933,
+	0x007c, 0x1078, 0x16e5, 0x007c, 0x1078, 0x16e5, 0x1078, 0x1933,
+	0x007c, 0x1078, 0x143e, 0x007c, 0x1078, 0x1933, 0x1078, 0x143e,
+	0x007c, 0x1078, 0x16e5, 0x1078, 0x143e, 0x007c, 0x1078, 0x16e5,
+	0x1078, 0x1933, 0x1078, 0x143e, 0x007c, 0x127e, 0x2091, 0x2300,
+	0x2079, 0x0200, 0x2071, 0x7280, 0x2069, 0x6d00, 0x2009, 0x0004,
+	0x7912, 0x7916, 0x1078, 0x1df6, 0x781b, 0x0002, 0x20e1, 0x8700,
+	0x127f, 0x007c, 0x127e, 0x2091, 0x2300, 0x781c, 0xa084, 0x0007,
+	0x0079, 0x1b7a, 0x1b9e, 0x1b82, 0x1b86, 0x1b8a, 0x1b90, 0x1b94,
+	0x1b98, 0x1b9c, 0x1078, 0x3d7c, 0x0078, 0x1b9e, 0x1078, 0x3db0,
+	0x0078, 0x1b9e, 0x1078, 0x3d7c, 0x1078, 0x3db0, 0x0078, 0x1b9e,
+	0x1078, 0x1ba0, 0x0078, 0x1b9e, 0x1078, 0x1ba0, 0x0078, 0x1b9e,
+	0x1078, 0x1ba0, 0x0078, 0x1b9e, 0x1078, 0x1ba0, 0x127f, 0x007c,
+	0x007e, 0x017e, 0x027e, 0x7930, 0xa184, 0x0003, 0x0040, 0x1baa,
+	0x1078, 0x12b7, 0xa184, 0x0030, 0x0040, 0x1bbb, 0x6a00, 0xa286,
+	0x0003, 0x00c0, 0x1bb5, 0x1078, 0x12b7, 0x1078, 0x31cb, 0x20e1,
+	0x9010, 0x0078, 0x1bc7, 0xa184, 0x00c0, 0x0040, 0x1bc1, 0x1078,
+	0x12b7, 0xa184, 0x0300, 0x0040, 0x1bc7, 0x20e1, 0x9020, 0x7932,
+	0x027f, 0x017f, 0x007f, 0x007c, 0x017e, 0x0e7e, 0x0f7e, 0x2071,
+	0x6d00, 0x7128, 0x2001, 0x6f03, 0x2102, 0x2001, 0x6f0b, 0x2102,
+	0xa182, 0x0211, 0x00c8, 0x1be0, 0x2009, 0x0008, 0x0078, 0x1c0a,
+	0xa182, 0x0259, 0x00c8, 0x1be8, 0x2009, 0x0007, 0x0078, 0x1c0a,
+	0xa182, 0x02c1, 0x00c8, 0x1bf0, 0x2009, 0x0006, 0x0078, 0x1c0a,
+	0xa182, 0x0349, 0x00c8, 0x1bf8, 0x2009, 0x0005, 0x0078, 0x1c0a,
+	0xa182, 0x0421, 0x00c8, 0x1c00, 0x2009, 0x0004, 0x0078, 0x1c0a,
+	0xa182, 0x0581, 0x00c8, 0x1c08, 0x2009, 0x0003, 0x0078, 0x1c0a,
+	0x2009, 0x0002, 0x2079, 0x0200, 0x7912, 0x7916, 0x1078, 0x1df6,
+	0x0f7f, 0x0e7f, 0x017f, 0x007c, 0x127e, 0x2091, 0x2200, 0x2061,
+	0x0100, 0x2071, 0x6d00, 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, 0x6d2d, 0x2003,
+	0x0000, 0x2001, 0x6d2c, 0x2003, 0x0001, 0x007c, 0x127e, 0x2091,
+	0x2200, 0x007e, 0x017e, 0x027e, 0x6124, 0xa184, 0x002c, 0x00c0,
+	0x1c4d, 0xa184, 0x0007, 0x0079, 0x1c53, 0xa195, 0x0004, 0xa284,
+	0x0007, 0x0079, 0x1c53, 0x1c7f, 0x1c5b, 0x1c5f, 0x1c63, 0x1c69,
+	0x1c6d, 0x1c73, 0x1c79, 0x1078, 0x4226, 0x0078, 0x1c7f, 0x1078,
+	0x42e4, 0x0078, 0x1c7f, 0x1078, 0x42e4, 0x1078, 0x4226, 0x0078,
+	0x1c7f, 0x1078, 0x1c84, 0x0078, 0x1c7f, 0x1078, 0x4226, 0x1078,
+	0x1c84, 0x0078, 0x1c7f, 0x1078, 0x42e4, 0x1078, 0x1c84, 0x0078,
+	0x1c7f, 0x1078, 0x42e4, 0x1078, 0x4226, 0x1078, 0x1c84, 0x027f,
+	0x017f, 0x007f, 0x127f, 0x007c, 0xd1ac, 0x0040, 0x1d24, 0x017e,
+	0x047e, 0x0c7e, 0x644c, 0x74ba, 0xa48c, 0xff00, 0xa196, 0xff00,
+	0x0040, 0x1cb3, 0x6030, 0xa084, 0x00ff, 0x810f, 0xa116, 0x0040,
+	0x1cb3, 0x7130, 0xd18c, 0x00c0, 0x1cb3, 0x2011, 0x6d52, 0x2214,
+	0xd2ec, 0x0040, 0x1ca7, 0xc18d, 0x7132, 0x0078, 0x1cb3, 0x6240,
+	0xa294, 0x0010, 0x0040, 0x1cf2, 0x6248, 0xa294, 0xff00, 0xa296,
+	0xff00, 0x00c0, 0x1cf2, 0x2011, 0x8013, 0x1078, 0x2a53, 0x7130,
+	0xc185, 0x7132, 0x2011, 0x6d52, 0x220c, 0xd1a4, 0x0040, 0x1cda,
+	0x017e, 0x2009, 0x0001, 0x2011, 0x0100, 0x1078, 0x41f4, 0x2019,
+	0x000e, 0x1078, 0x6b8f, 0xa484, 0x00ff, 0xa080, 0x2091, 0x200c,
+	0xa18c, 0xff00, 0x810f, 0x8127, 0xa006, 0x2009, 0x000e, 0x1078,
+	0x6bf7, 0x017f, 0xd1ac, 0x00c0, 0x1ce3, 0x2019, 0x0004, 0x1078,
+	0x202f, 0x0078, 0x1cf2, 0x157e, 0x20a9, 0x007f, 0x2009, 0x0000,
+	0x1078, 0x3447, 0x00c0, 0x1cee, 0x1078, 0x3256, 0x8108, 0x00f0,
+	0x1ce8, 0x157f, 0x0c7f, 0x047f, 0x6043, 0x0000, 0x2009, 0x00f7,
+	0x1078, 0x3233, 0x2011, 0x0003, 0x1078, 0x5232, 0x2011, 0x0002,
+	0x1078, 0x523c, 0x1078, 0x5148, 0x1078, 0x414c, 0x037e, 0x2019,
+	0x0000, 0x1078, 0x51da, 0x037f, 0x60e3, 0x0000, 0x017f, 0x2001,
+	0x6d00, 0x2014, 0xa296, 0x0004, 0x00c0, 0x1d1c, 0xd19c, 0x00c0,
+	0x1d1c, 0x6228, 0xc29d, 0x622a, 0x2003, 0x0001, 0x2001, 0x6d20,
+	0x2003, 0x0000, 0x6027, 0x0020, 0xd194, 0x0040, 0x1d9d, 0x017e,
+	0x6220, 0xd2b4, 0x0040, 0x1d5b, 0x1078, 0x414c, 0x1078, 0x4fe5,
+	0x6027, 0x0004, 0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000,
+	0x0040, 0x1d3e, 0x6803, 0x1000, 0x6803, 0x0000, 0x0d7f, 0x0c7e,
+	0x2061, 0x6f10, 0x6028, 0xa09a, 0x0002, 0x00c8, 0x1d4e, 0x8000,
+	0x602a, 0x0c7f, 0x1078, 0x4fd7, 0x0078, 0x1d9c, 0x2019, 0x6f19,
+	0x2304, 0xa065, 0x0040, 0x1d58, 0x2009, 0x0014, 0x1078, 0x5591,
+	0x0c7f, 0x0078, 0x1d9c, 0xd2bc, 0x0040, 0x1d9c, 0x1078, 0x415a,
+	0x6017, 0x0010, 0x6027, 0x0004, 0x0d7e, 0x2069, 0x0140, 0x6804,
+	0xa084, 0x4000, 0x0040, 0x1d70, 0x6803, 0x1000, 0x6803, 0x0000,
+	0x0d7f, 0x0c7e, 0x2061, 0x6f10, 0x6044, 0xa09a, 0x0002, 0x00c8,
+	0x1d91, 0x8000, 0x6046, 0x603c, 0x0c7f, 0xa005, 0x0040, 0x1d9c,
+	0x1078, 0x4151, 0xa080, 0x0007, 0x2004, 0xa086, 0x0006, 0x00c0,
+	0x1d8d, 0x6017, 0x0012, 0x0078, 0x1d9c, 0x6017, 0x0016, 0x0078,
+	0x1d9c, 0x2019, 0x6f1f, 0x2304, 0xa065, 0x0040, 0x1d9b, 0x2009,
+	0x004a, 0x1078, 0x5591, 0x0c7f, 0x017f, 0xd19c, 0x0040, 0x1dc5,
+	0x017e, 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, 0x1078, 0x5232,
+	0x2011, 0x0002, 0x1078, 0x523c, 0x1078, 0x5148, 0x1078, 0x414c,
+	0x037e, 0x2019, 0x0000, 0x1078, 0x51da, 0x037f, 0x60e3, 0x0000,
+	0x1078, 0x6c5f, 0x1078, 0x6c7d, 0x2001, 0x6d00, 0x2003, 0x0004,
+	0x6027, 0x0008, 0x1078, 0x11aa, 0x017f, 0xa18c, 0xffd0, 0x6126,
+	0x007c, 0x007e, 0x017e, 0x027e, 0x0e7e, 0x0f7e, 0x127e, 0x2091,
+	0x8000, 0x2071, 0x6d00, 0x71b0, 0x70b2, 0xa116, 0x0040, 0x1def,
+	0x81ff, 0x0040, 0x1de1, 0x2011, 0x8011, 0x1078, 0x2a53, 0x0078,
+	0x1def, 0x2011, 0x8012, 0x1078, 0x2a53, 0x037e, 0x0c7e, 0x2061,
+	0x0100, 0x2019, 0x0028, 0x1078, 0x202f, 0x0c7f, 0x037f, 0x127f,
+	0x0f7f, 0x0e7f, 0x027f, 0x017f, 0x007f, 0x007c, 0x0c7e, 0x0f7e,
+	0x007e, 0x027e, 0x2061, 0x0100, 0xa190, 0x1e09, 0x2204, 0x60f2,
+	0xa190, 0x1e12, 0x2204, 0x60ee, 0x027f, 0x007f, 0x0f7f, 0x0c7f,
+	0x007c, 0x083e, 0x083e, 0x083e, 0x0580, 0x0420, 0x0348, 0x02c0,
+	0x0258, 0x0210, 0x01a8, 0x01a8, 0x01a8, 0x01a8, 0x0140, 0x00f8,
+	0x00d0, 0x00b0, 0x00a0, 0x2028, 0x2130, 0xa094, 0xff00, 0x00c0,
+	0x1e24, 0x81ff, 0x0040, 0x1e28, 0x1078, 0x3f00, 0x0078, 0x1e2f,
+	0xa080, 0x2091, 0x200c, 0xa18c, 0xff00, 0x810f, 0xa006, 0x007c,
+	0xa080, 0x2091, 0x200c, 0xa18c, 0x00ff, 0x007c, 0x1e56, 0x1e5a,
+	0x1e5e, 0x1e64, 0x1e6a, 0x1e70, 0x1e76, 0x1e7e, 0x1e86, 0x1e8c,
+	0x1e92, 0x1e9a, 0x1ea2, 0x1eaa, 0x1eb2, 0x1ebc, 0x1ec6, 0x1ec6,
+	0x1ec6, 0x1ec6, 0x1ec6, 0x1ec6, 0x1ec6, 0x1ec6, 0x1ec6, 0x1ec6,
+	0x1ec6, 0x1ec6, 0x1ec6, 0x1ec6, 0x1ec6, 0x1ec6, 0x107e, 0x007e,
+	0x0078, 0x1edf, 0x107e, 0x007e, 0x0078, 0x1edf, 0x107e, 0x007e,
+	0x1078, 0x1c3e, 0x0078, 0x1edf, 0x107e, 0x007e, 0x1078, 0x1c3e,
+	0x0078, 0x1edf, 0x107e, 0x007e, 0x1078, 0x1b2e, 0x0078, 0x1edf,
+	0x107e, 0x007e, 0x1078, 0x1b2e, 0x0078, 0x1edf, 0x107e, 0x007e,
+	0x1078, 0x1c3e, 0x1078, 0x1b2e, 0x0078, 0x1edf, 0x107e, 0x007e,
+	0x1078, 0x1c3e, 0x1078, 0x1b2e, 0x0078, 0x1edf, 0x107e, 0x007e,
+	0x1078, 0x1b72, 0x0078, 0x1edf, 0x107e, 0x007e, 0x1078, 0x1b72,
+	0x0078, 0x1edf, 0x107e, 0x007e, 0x1078, 0x1c3e, 0x1078, 0x1b72,
+	0x0078, 0x1edf, 0x107e, 0x007e, 0x1078, 0x1c3e, 0x1078, 0x1b72,
+	0x0078, 0x1edf, 0x107e, 0x007e, 0x1078, 0x1b2e, 0x1078, 0x1b72,
+	0x0078, 0x1edf, 0x107e, 0x007e, 0x1078, 0x1b2e, 0x1078, 0x1b72,
+	0x0078, 0x1edf, 0x107e, 0x007e, 0x1078, 0x1c3e, 0x1078, 0x1b2e,
+	0x1078, 0x1b72, 0x0078, 0x1edf, 0x107e, 0x007e, 0x1078, 0x1c3e,
+	0x1078, 0x1b2e, 0x1078, 0x1b72, 0x0078, 0x1edf, 0x0005, 0x0078,
+	0x1ec6, 0xb084, 0x003c, 0x8004, 0x8004, 0x0079, 0x1ecf, 0x1edf,
+	0x1e5c, 0x1e60, 0x1e66, 0x1e6c, 0x1e72, 0x1e78, 0x1e80, 0x1e88,
+	0x1e8e, 0x1e94, 0x1e9c, 0x1ea4, 0x1eac, 0x1eb4, 0x1ebe, 0x0008,
+	0x1ec9, 0x007f, 0x107f, 0x2091, 0x8001, 0x007c, 0x0c7e, 0x027e,
+	0x2041, 0x007e, 0x70bc, 0xd09c, 0x0040, 0x1ef0, 0x2041, 0x007f,
+	0x2001, 0x010c, 0x203c, 0x727c, 0x82ff, 0x0040, 0x1f3b, 0x037e,
+	0x738c, 0xa38e, 0xffff, 0x00c0, 0x1eff, 0x2019, 0x0001, 0x8314,
+	0xa2e0, 0x73c0, 0x2c04, 0xa38c, 0x0001, 0x0040, 0x1f0c, 0xa084,
+	0xff00, 0x8007, 0x0078, 0x1f0e, 0xa084, 0x00ff, 0xa70e, 0x0040,
+	0x1f30, 0xa08e, 0x00ff, 0x0040, 0x1f36, 0x2009, 0x0000, 0x1078,
+	0x1e1b, 0x1078, 0x3410, 0x00c0, 0x1f33, 0x6004, 0xa084, 0x00ff,
+	0xa086, 0x0006, 0x00c0, 0x1f2a, 0x1078, 0x1f8d, 0x0040, 0x1f33,
+	0x0078, 0x1f30, 0x1078, 0x208d, 0x1078, 0x1fb4, 0x0040, 0x1f33,
+	0x8318, 0x0078, 0x1eff, 0x738e, 0x0078, 0x1f38, 0x708f, 0xffff,
+	0x037f, 0x0078, 0x1f8a, 0xa780, 0x2091, 0x203c, 0xa7bc, 0xff00,
+	0x873f, 0x708c, 0xa096, 0xffff, 0x0040, 0x1f4d, 0xa812, 0x00c8,
+	0x1f5d, 0x708f, 0xffff, 0x0078, 0x1f87, 0x2009, 0x0000, 0x70bc,
+	0xd09c, 0x0040, 0x1f58, 0xd094, 0x0040, 0x1f58, 0x2009, 0x007e,
+	0x2100, 0xa802, 0x20a8, 0x0078, 0x1f61, 0x2008, 0x2810, 0xa202,
+	0x20a8, 0x2700, 0x157e, 0x017e, 0xa106, 0x0040, 0x1f7e, 0x1078,
+	0x3410, 0x00c0, 0x1f87, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006,
+	0x00c0, 0x1f78, 0x1078, 0x1f8d, 0x0040, 0x1f87, 0x0078, 0x1f7e,
+	0x1078, 0x208d, 0x1078, 0x1fb4, 0x0040, 0x1f87, 0x017f, 0x8108,
+	0x157f, 0x00f0, 0x1f61, 0x708f, 0xffff, 0x0078, 0x1f8a, 0x017f,
+	0x157f, 0x718e, 0x027f, 0x0c7f, 0x007c, 0x017e, 0x077e, 0x0d7e,
+	0x0c7e, 0x2c68, 0x1078, 0x5504, 0x0040, 0x1faf, 0x2d00, 0x601a,
+	0x601f, 0x0001, 0x2001, 0x0000, 0x1078, 0x33df, 0x2001, 0x0000,
+	0x1078, 0x33f3, 0x127e, 0x2091, 0x8000, 0x7088, 0x8000, 0x708a,
+	0x127f, 0x2009, 0x0004, 0x1078, 0x5591, 0xa085, 0x0001, 0x0c7f,
+	0x0d7f, 0x077f, 0x017f, 0x007c, 0x017e, 0x077e, 0x0d7e, 0x0c7e,
+	0x2c68, 0x1078, 0x5504, 0x0040, 0x1fd6, 0x2d00, 0x601a, 0x601f,
+	0x0001, 0x2001, 0x0000, 0x1078, 0x33df, 0x2001, 0x0002, 0x1078,
+	0x33f3, 0x127e, 0x2091, 0x8000, 0x7088, 0x8000, 0x708a, 0x127f,
+	0x2009, 0x0002, 0x1078, 0x5591, 0xa085, 0x0001, 0x0c7f, 0x0d7f,
+	0x077f, 0x017f, 0x007c, 0x0c7e, 0x027e, 0x2009, 0x0080, 0x1078,
+	0x3410, 0x00c0, 0x1fe9, 0x1078, 0x1fec, 0x0040, 0x1fe9, 0x70c3,
+	0xffff, 0x027f, 0x0c7f, 0x007c, 0x017e, 0x077e, 0x0d7e, 0x0c7e,
+	0x2c68, 0x1078, 0x5504, 0x0040, 0x200e, 0x2d00, 0x601a, 0x601f,
+	0x0001, 0x2001, 0x0000, 0x1078, 0x33df, 0x2001, 0x0002, 0x1078,
+	0x33f3, 0x127e, 0x2091, 0x8000, 0x70c4, 0x8000, 0x70c6, 0x127f,
+	0x2009, 0x0002, 0x1078, 0x5591, 0xa085, 0x0001, 0x0c7f, 0x0d7f,
+	0x077f, 0x017f, 0x007c, 0x0c7e, 0x0d7e, 0x2009, 0x007f, 0x1078,
+	0x3410, 0x00c0, 0x202c, 0x2c68, 0x1078, 0x5504, 0x0040, 0x202c,
+	0x2d00, 0x601a, 0x6312, 0x601f, 0x0001, 0x620a, 0x2009, 0x0022,
+	0x1078, 0x5591, 0xa085, 0x0001, 0x0d7f, 0x0c7f, 0x007c, 0x0e7e,
+	0x0c7e, 0x067e, 0x037e, 0x027e, 0x1078, 0x4463, 0x1078, 0x4417,
+	0x1078, 0x59ce, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078,
+	0x3447, 0x00c0, 0x2047, 0x1078, 0x35cf, 0x1078, 0x3256, 0x017f,
+	0x8108, 0x00f0, 0x203e, 0x027f, 0x037f, 0x067f, 0x0c7f, 0x0e7f,
+	0x007c, 0x0e7e, 0x0c7e, 0x037e, 0x027e, 0x017e, 0x6218, 0x2270,
+	0x72a0, 0x027e, 0x2019, 0x0029, 0x1078, 0x445c, 0x1078, 0x43a9,
+	0x2c08, 0x1078, 0x6a57, 0x017f, 0x2e60, 0x1078, 0x35cf, 0x1078,
+	0x3256, 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f, 0x007c, 0x0e7e,
+	0x007e, 0x6018, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x00c0, 0x2083,
+	0x2071, 0x6d00, 0x7088, 0xa005, 0x0040, 0x2080, 0x8001, 0x708a,
+	0x007f, 0x0e7f, 0x007c, 0x2071, 0x6d00, 0x70c4, 0xa005, 0x0040,
+	0x2080, 0x8001, 0x70c6, 0x0078, 0x2080, 0x6000, 0xc08c, 0x6002,
+	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,
+	0x8000, 0x2071, 0x6d6d, 0x7003, 0x0002, 0xa006, 0x7012, 0x7016,
+	0x703a, 0x703e, 0x7033, 0x6d7d, 0x7037, 0x6d7d, 0x7007, 0x0001,
+	0x2061, 0x6d9d, 0x6003, 0x0002, 0x007c, 0x0090, 0x21b8, 0x0068,
+	0x21b8, 0x2071, 0x6d6d, 0x2b78, 0x7818, 0xd084, 0x00c0, 0x21b8,
+	0x2a60, 0x7820, 0xa08e, 0x0069, 0x00c0, 0x229c, 0x0079, 0x223c,
+	0x007c, 0x2071, 0x6d6d, 0x7004, 0x0079, 0x21be, 0x21c2, 0x21c3,
+	0x21cd, 0x21df, 0x007c, 0x0090, 0x21cc, 0x0068, 0x21cc, 0x2b78,
+	0x7818, 0xd084, 0x0040, 0x21eb, 0x007c, 0x2b78, 0x2061, 0x6d9d,
+	0x6008, 0xa08e, 0x0100, 0x0040, 0x21da, 0xa086, 0x0200, 0x0040,
+	0x2294, 0x007c, 0x7014, 0x2068, 0x2a60, 0x7018, 0x007a, 0x7010,
+	0x2068, 0x6834, 0xa086, 0x0103, 0x0040, 0x21e7, 0x007c, 0x2a60,
+	0x2b78, 0x7018, 0x007a, 0x2a60, 0x7820, 0xa08a, 0x0040, 0x00c8,
+	0x21f4, 0x61b0, 0x0079, 0x21fc, 0x2100, 0xa08a, 0x0033, 0x00c8,
+	0x2290, 0x61b0, 0x0079, 0x223c, 0x2272, 0x22a4, 0x22ac, 0x22b0,
+	0x22b8, 0x22be, 0x22c2, 0x22cb, 0x22cf, 0x22d7, 0x22db, 0x2290,
+	0x2290, 0x2290, 0x22df, 0x2290, 0x22ef, 0x2306, 0x231d, 0x2399,
+	0x239e, 0x23cb, 0x2416, 0x2425, 0x2446, 0x247c, 0x2486, 0x2493,
+	0x24a6, 0x24be, 0x24c7, 0x2504, 0x250a, 0x2290, 0x251a, 0x2290,
+	0x2290, 0x2290, 0x2290, 0x2290, 0x251e, 0x2524, 0x2290, 0x2290,
+	0x2290, 0x2290, 0x2290, 0x2290, 0x2290, 0x2290, 0x252c, 0x2290,
+	0x2290, 0x2290, 0x2290, 0x2290, 0x2539, 0x253f, 0x2290, 0x2290,
+	0x2290, 0x2290, 0x2290, 0x2290, 0x2290, 0x2290, 0x2290, 0x2290,
+	0x2290, 0x2290, 0x2290, 0x2290, 0x2290, 0x2290, 0x2290, 0x2290,
+	0x2290, 0x2290, 0x2290, 0x2290, 0x22d7, 0x22db, 0x2290, 0x2290,
+	0x2551, 0x2290, 0x2290, 0x2290, 0x2290, 0x2290, 0x2290, 0x2290,
+	0x2290, 0x2290, 0x2290, 0x2290, 0x259e, 0x265d, 0x2671, 0x2678,
+	0x26db, 0x2736, 0x2741, 0x2783, 0x2790, 0x279d, 0x27a0, 0x2555,
+	0x27c9, 0x2811, 0x281e, 0x28fd, 0x29cb, 0x29f2, 0x2ade, 0x713c,
+	0x0078, 0x2272, 0x2021, 0x4000, 0x1078, 0x2a2d, 0x127e, 0x2091,
+	0x8000, 0x0068, 0x227f, 0x7818, 0xd084, 0x0040, 0x2282, 0x127f,
+	0x0078, 0x2276, 0x781b, 0x0001, 0x7c22, 0x7926, 0x7a2a, 0x7b2e,
+	0x2091, 0x4080, 0x7007, 0x0001, 0x2091, 0x5000, 0x127f, 0x007c,
+	0x2021, 0x4001, 0x0078, 0x2274, 0x2021, 0x4002, 0x0078, 0x2274,
+	0x2021, 0x4003, 0x0078, 0x2274, 0x2021, 0x4005, 0x0078, 0x2274,
+	0x2021, 0x4006, 0x0078, 0x2274, 0xa02e, 0x2520, 0x7b28, 0x7a2c,
+	0x7824, 0x7930, 0x0078, 0x2a3c, 0x7823, 0x0004, 0x7824, 0x007a,
+	0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0078, 0x2a40,
+	0x7924, 0x7828, 0x2114, 0x200a, 0x0078, 0x2272, 0x7924, 0x2114,
+	0x0078, 0x2272, 0x2099, 0x0009, 0x20a1, 0x0009, 0x20a9, 0x0007,
+	0x53a3, 0x0078, 0x2272, 0x7824, 0x2060, 0x0078, 0x22e1, 0x2009,
+	0x0001, 0x2011, 0x000d, 0x2019, 0x0000, 0x0078, 0x2272, 0x7d38,
+	0x7c3c, 0x0078, 0x22a6, 0x7d38, 0x7c3c, 0x0078, 0x22b2, 0x2061,
+	0x1000, 0x610c, 0xa006, 0x2c14, 0xa200, 0x8c60, 0x8109, 0x00c0,
+	0x22e3, 0x2010, 0xa005, 0x0040, 0x2272, 0x0078, 0x2298, 0x2061,
+	0x6d51, 0x7824, 0x7930, 0xa11a, 0x00c8, 0x22a0, 0x8019, 0x0040,
+	0x22a0, 0x604a, 0x6142, 0x782c, 0x6052, 0x7828, 0x6056, 0xa006,
+	0x605a, 0x605e, 0x1078, 0x3890, 0x0078, 0x2272, 0x2061, 0x6d51,
+	0x7824, 0x7930, 0xa11a, 0x00c8, 0x22a0, 0x8019, 0x0040, 0x22a0,
+	0x604e, 0x6146, 0x782c, 0x6062, 0x7828, 0x6066, 0xa006, 0x606a,
+	0x606e, 0x1078, 0x366e, 0x0078, 0x2272, 0xa02e, 0x2520, 0x81ff,
+	0x00c0, 0x229c, 0x7924, 0x7b28, 0x7a2c, 0x20a9, 0x0005, 0x20a1,
+	0x6d74, 0x41a1, 0x1078, 0x2a04, 0x0040, 0x229c, 0x2009, 0x0020,
+	0x1078, 0x2a3c, 0x701b, 0x2335, 0x007c, 0x6834, 0x2008, 0xa084,
+	0x00ff, 0xa096, 0x0011, 0x0040, 0x2341, 0xa096, 0x0019, 0x00c0,
+	0x229c, 0x810f, 0xa18c, 0x00ff, 0x0040, 0x229c, 0x710e, 0x700c,
+	0x8001, 0x0040, 0x2372, 0x700e, 0x1078, 0x2a04, 0x0040, 0x229c,
+	0x2009, 0x0020, 0x2061, 0x6d9d, 0x6224, 0x6328, 0x642c, 0x6530,
+	0xa290, 0x0040, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000,
+	0x1078, 0x2a3c, 0x701b, 0x2365, 0x007c, 0x6834, 0xa084, 0x00ff,
+	0xa096, 0x0002, 0x0040, 0x2370, 0xa096, 0x000a, 0x00c0, 0x229c,
+	0x0078, 0x2347, 0x7010, 0x2068, 0x6838, 0xc0fd, 0x683a, 0x1078,
+	0x3344, 0x00c0, 0x2380, 0x7007, 0x0003, 0x701b, 0x2382, 0x007c,
+	0x1078, 0x372d, 0x127e, 0x2091, 0x8000, 0x20a9, 0x0005, 0x2099,
+	0x6d74, 0x530a, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000,
+	0xa5a9, 0x0000, 0xad80, 0x000d, 0x2009, 0x0020, 0x127f, 0x0078,
+	0x2a40, 0x6198, 0x7824, 0x609a, 0x0078, 0x2272, 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, 0x229c, 0x1078, 0x2a1c,
+	0x0040, 0x22a0, 0x7c28, 0x7d2c, 0x1078, 0x3592, 0xd28c, 0x00c0,
+	0x23dd, 0x1078, 0x3522, 0x0078, 0x23df, 0x1078, 0x355e, 0x00c0,
+	0x2409, 0x2061, 0x7400, 0x127e, 0x2091, 0x8000, 0x6000, 0xa086,
+	0x0000, 0x0040, 0x23f7, 0x6010, 0xa06d, 0x0040, 0x23f7, 0x683c,
+	0xa406, 0x00c0, 0x23f7, 0x6840, 0xa506, 0x0040, 0x2402, 0x127f,
+	0xace0, 0x0008, 0x2001, 0x6d15, 0x2004, 0xac02, 0x00c8, 0x229c,
+	0x0078, 0x23e3, 0x1078, 0x5f5d, 0x127f, 0x0040, 0x229c, 0x0078,
+	0x2272, 0xa00e, 0x2001, 0x0005, 0x1078, 0x372d, 0x127e, 0x2091,
+	0x8000, 0x1078, 0x36a1, 0x127f, 0x0078, 0x2272, 0x81ff, 0x00c0,
+	0x229c, 0x1078, 0x2a1c, 0x0040, 0x22a0, 0x1078, 0x34d7, 0x1078,
+	0x35a3, 0x0040, 0x229c, 0x0078, 0x2272, 0x81ff, 0x00c0, 0x229c,
+	0x1078, 0x2a1c, 0x0040, 0x22a0, 0x2031, 0x000f, 0x1078, 0x34d7,
+	0x8631, 0x00c8, 0x242e, 0x2019, 0x0005, 0x1078, 0x35c4, 0x0040,
+	0x229c, 0x7828, 0xa08a, 0x1000, 0x00c8, 0x22a0, 0x8003, 0x800b,
+	0x810b, 0xa108, 0x1078, 0x40de, 0x0078, 0x2272, 0x127e, 0x2091,
+	0x8000, 0x81ff, 0x00c0, 0x2476, 0x2029, 0x00ff, 0x644c, 0x2400,
+	0xa506, 0x0040, 0x2470, 0x2508, 0x1078, 0x3447, 0x00c0, 0x2470,
+	0x2031, 0x000f, 0x1078, 0x34d7, 0x8631, 0x00c8, 0x245a, 0x2019,
+	0x0004, 0x1078, 0x35c4, 0x0040, 0x2476, 0x7824, 0xa08a, 0x1000,
+	0x00c8, 0x2479, 0x8003, 0x800b, 0x810b, 0xa108, 0x1078, 0x40de,
+	0x8529, 0x00c8, 0x244f, 0x127f, 0x0078, 0x2272, 0x127f, 0x0078,
+	0x229c, 0x127f, 0x0078, 0x22a0, 0x1078, 0x2a1c, 0x0040, 0x22a0,
+	0x1078, 0x3507, 0x1078, 0x3592, 0x0078, 0x2272, 0x81ff, 0x00c0,
+	0x229c, 0x1078, 0x2a1c, 0x0040, 0x22a0, 0x1078, 0x34f0, 0x1078,
+	0x3592, 0x0078, 0x2272, 0x81ff, 0x00c0, 0x229c, 0x1078, 0x2a1c,
+	0x0040, 0x22a0, 0x1078, 0x3561, 0x0040, 0x229c, 0x1078, 0x338c,
+	0x1078, 0x351b, 0x1078, 0x3592, 0x0078, 0x2272, 0x1078, 0x2a1c,
+	0x0040, 0x22a0, 0x1078, 0x34d7, 0x62a0, 0x2019, 0x0005, 0x0c7e,
+	0x1078, 0x35cf, 0x0c7f, 0x1078, 0x445c, 0x1078, 0x43a9, 0x2c08,
+	0x1078, 0x6a57, 0x1078, 0x3592, 0x0078, 0x2272, 0x1078, 0x2a1c,
+	0x0040, 0x22a0, 0x1078, 0x3592, 0x2208, 0x0078, 0x2272, 0x157e,
+	0x0d7e, 0x0e7e, 0x2069, 0x6ddf, 0x6810, 0x6914, 0xa10a, 0x00c8,
+	0x24d3, 0x2009, 0x0000, 0x6816, 0x2011, 0x0000, 0x2019, 0x0000,
+	0x20a9, 0x007e, 0x2069, 0x6e00, 0x2d04, 0xa075, 0x0040, 0x24e8,
+	0x704c, 0x1078, 0x24f2, 0xa210, 0x7080, 0x1078, 0x24f2, 0xa318,
+	0x8d68, 0x00f0, 0x24dc, 0x2300, 0xa218, 0x0e7f, 0x0d7f, 0x157f,
+	0x0078, 0x2272, 0x0f7e, 0x017e, 0xa07d, 0x0040, 0x2501, 0x2001,
+	0x0000, 0x8000, 0x2f0c, 0x81ff, 0x0040, 0x2501, 0x2178, 0x0078,
+	0x24f9, 0x017f, 0x0f7f, 0x007c, 0x2069, 0x6ddf, 0x6910, 0x629c,
+	0x0078, 0x2272, 0x81ff, 0x00c0, 0x229c, 0x614c, 0xa190, 0x2091,
+	0x2214, 0xa294, 0x00ff, 0x6068, 0xa084, 0xff00, 0xa215, 0x6364,
+	0x0078, 0x2272, 0x613c, 0x6240, 0x0078, 0x2272, 0x1078, 0x2a1c,
+	0x0040, 0x22a0, 0x0078, 0x2272, 0x1078, 0x2a1c, 0x0040, 0x22a0,
+	0x6244, 0x6338, 0x0078, 0x2272, 0x613c, 0x6240, 0x7824, 0x603e,
+	0x7b28, 0x6342, 0x2069, 0x6d51, 0x831f, 0xa305, 0x6816, 0x0078,
+	0x2272, 0x1078, 0x2a1c, 0x0040, 0x22a0, 0x0078, 0x2272, 0x1078,
+	0x2a1c, 0x0040, 0x22a0, 0x7828, 0xa00d, 0x0040, 0x22a0, 0x782c,
+	0xa005, 0x0040, 0x22a0, 0x6244, 0x6146, 0x6338, 0x603a, 0x0078,
+	0x2272, 0x7d38, 0x7c3c, 0x0078, 0x231f, 0x7824, 0xa09c, 0x00ff,
+	0xa39a, 0x0003, 0x00c8, 0x229c, 0x624c, 0xa084, 0xff00, 0x8007,
+	0xa206, 0x00c0, 0x256d, 0x2001, 0x6d40, 0x2009, 0x000c, 0x7a2c,
+	0x7b28, 0x7c3c, 0x7d38, 0x0078, 0x2a40, 0x81ff, 0x00c0, 0x229c,
+	0x1078, 0x2a1c, 0x0040, 0x22a0, 0x6004, 0xa084, 0x00ff, 0xa086,
+	0x0006, 0x00c0, 0x229c, 0x0c7e, 0x1078, 0x2a04, 0x0c7f, 0x0040,
+	0x229c, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x1078, 0x6223,
+	0x0040, 0x229c, 0x7007, 0x0003, 0x701b, 0x258f, 0x007c, 0x6830,
+	0xa086, 0x0100, 0x0040, 0x229c, 0xad80, 0x000e, 0x2009, 0x000c,
+	0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, 0x2a40, 0x1078, 0x2a04,
+	0x0040, 0x229c, 0x2009, 0x001c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
+	0x1078, 0x2a3c, 0x701b, 0x25ad, 0x007c, 0xade8, 0x000d, 0x6800,
+	0xa005, 0x0040, 0x22a0, 0x6804, 0xd0ac, 0x0040, 0x25ba, 0xd0a4,
+	0x0040, 0x22a0, 0xd094, 0x0040, 0x25c5, 0x0c7e, 0x2061, 0x0100,
+	0x6104, 0xa18c, 0xffdf, 0x6106, 0x0c7f, 0xd08c, 0x0040, 0x25d0,
+	0x0c7e, 0x2061, 0x0100, 0x6104, 0xa18d, 0x0010, 0x6106, 0x0c7f,
+	0x2009, 0x0100, 0x210c, 0xa18a, 0x0002, 0x0048, 0x25e5, 0xd084,
+	0x0040, 0x25e5, 0x6828, 0xa08a, 0x007f, 0x00c8, 0x22a0, 0xa088,
+	0x2091, 0x210c, 0xa18c, 0x00ff, 0x6152, 0xd0dc, 0x0040, 0x25ee,
+	0x6828, 0xa08a, 0x007f, 0x00c8, 0x22a0, 0x604e, 0x6808, 0xa08a,
+	0x0100, 0x0048, 0x22a0, 0xa08a, 0x0841, 0x00c8, 0x22a0, 0xa084,
+	0x0007, 0x00c0, 0x22a0, 0x680c, 0xa005, 0x0040, 0x22a0, 0x6810,
+	0xa005, 0x0040, 0x22a0, 0x6848, 0x6940, 0xa10a, 0x00c8, 0x22a0,
+	0x8001, 0x0040, 0x22a0, 0x684c, 0x6944, 0xa10a, 0x00c8, 0x22a0,
+	0x8001, 0x0040, 0x22a0, 0x20a9, 0x001c, 0x2d98, 0x2069, 0x6d51,
+	0x2da0, 0x53a3, 0x6814, 0xa08c, 0x00ff, 0x613e, 0x8007, 0xa084,
+	0x00ff, 0x6042, 0x1078, 0x3890, 0x1078, 0x366e, 0x6000, 0xa086,
+	0x0000, 0x00c0, 0x265b, 0x6808, 0x602a, 0x1078, 0x1bcc, 0x6818,
+	0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f, 0x6016,
+	0x611a, 0x621e, 0x6322, 0xa084, 0xf0ff, 0x6006, 0x610a, 0x620e,
+	0x6312, 0x1078, 0x4168, 0x0c7e, 0x2061, 0x0100, 0x602f, 0x0040,
+	0x602f, 0x0000, 0x0c7f, 0x60b4, 0xa005, 0x0040, 0x2657, 0x6003,
+	0x0001, 0x2091, 0x301d, 0x1078, 0x31cb, 0x0078, 0x265b, 0x6003,
+	0x0004, 0x2091, 0x301d, 0x0078, 0x2272, 0x6000, 0xa086, 0x0000,
+	0x0040, 0x229c, 0x2069, 0x6d51, 0x7830, 0x6842, 0x7834, 0x6846,
+	0x2d00, 0x2009, 0x001c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078,
+	0x2a40, 0x81ff, 0x00c0, 0x229c, 0x1078, 0x31cb, 0x0078, 0x2272,
+	0x81ff, 0x00c0, 0x229c, 0x617c, 0x81ff, 0x0040, 0x2692, 0x703f,
+	0x0000, 0x2001, 0x73c0, 0x2009, 0x0040, 0x7a2c, 0x7b28, 0x7c3c,
+	0x7d38, 0x127e, 0x2091, 0x8000, 0x1078, 0x2a40, 0x701b, 0x226f,
+	0x127f, 0x007c, 0x703f, 0x0001, 0x0d7e, 0x2069, 0x73c0, 0x20a9,
+	0x0040, 0x20a1, 0x73c0, 0x2019, 0xffff, 0x43a4, 0x654c, 0xa588,
+	0x2091, 0x210c, 0xa18c, 0x00ff, 0x216a, 0xa00e, 0x2011, 0x0002,
+	0x2100, 0xa506, 0x0040, 0x26c4, 0x1078, 0x3447, 0x00c0, 0x26c4,
+	0x6014, 0x821c, 0x0048, 0x26bc, 0xa398, 0x73c0, 0xa085, 0xff00,
+	0x8007, 0x201a, 0x0078, 0x26c3, 0xa398, 0x73c0, 0x2324, 0xa4a4,
+	0xff00, 0xa405, 0x201a, 0x8210, 0x8108, 0xa182, 0x0080, 0x00c8,
+	0x26cb, 0x0078, 0x26a8, 0x8201, 0x8007, 0x2d0c, 0xa105, 0x206a,
+	0x0d7f, 0x20a9, 0x0040, 0x20a1, 0x73c0, 0x2099, 0x73c0, 0x1078,
+	0x3213, 0x0078, 0x2681, 0x1078, 0x2a1c, 0x0040, 0x22a0, 0x0c7e,
+	0x1078, 0x2a04, 0x0c7f, 0x0040, 0x229c, 0x2001, 0x6d52, 0x2004,
+	0xd0b4, 0x0040, 0x2708, 0x6000, 0xd08c, 0x00c0, 0x2708, 0x6004,
+	0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x2708, 0x6837, 0x0000,
+	0x6838, 0xc0fd, 0x683a, 0x1078, 0x625b, 0x0040, 0x229c, 0x7007,
+	0x0003, 0x701b, 0x2704, 0x007c, 0x1078, 0x2a1c, 0x0040, 0x22a0,
+	0x20a9, 0x0029, 0x2c98, 0xade8, 0x0002, 0x2da0, 0x53a3, 0x20a9,
+	0x0002, 0xac80, 0x0004, 0x2098, 0xad80, 0x0004, 0x20a0, 0x1078,
+	0x3213, 0x20a9, 0x0004, 0xac80, 0x0006, 0x2098, 0xad80, 0x0006,
+	0x20a0, 0x1078, 0x3213, 0x20a9, 0x0004, 0xac80, 0x000a, 0x2098,
+	0xad80, 0x000a, 0x20a0, 0x1078, 0x3213, 0x2d00, 0x2009, 0x0029,
+	0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, 0x2a40, 0x81ff, 0x00c0,
+	0x229c, 0x1078, 0x2a1c, 0x0040, 0x22a0, 0x1078, 0x35ae, 0x0078,
+	0x2272, 0x81ff, 0x00c0, 0x229c, 0x7828, 0xa08a, 0x1000, 0x00c8,
+	0x22a0, 0x1078, 0x2a1c, 0x0040, 0x22a0, 0x2031, 0x000f, 0x1078,
+	0x34d7, 0x8631, 0x00c8, 0x274f, 0x2019, 0x0004, 0x1078, 0x35c4,
+	0x7924, 0x810f, 0x7a28, 0x1078, 0x275f, 0x0078, 0x2272, 0xa186,
+	0x00ff, 0x0040, 0x2767, 0x1078, 0x2777, 0x0078, 0x2776, 0x2029,
+	0x007e, 0x2061, 0x6d00, 0x644c, 0x2400, 0xa506, 0x0040, 0x2773,
+	0x2508, 0x1078, 0x2777, 0x8529, 0x00c8, 0x276c, 0x007c, 0x1078,
+	0x3447, 0x00c0, 0x2782, 0x2200, 0x8003, 0x800b, 0x810b, 0xa108,
+	0x1078, 0x40de, 0x007c, 0x81ff, 0x00c0, 0x229c, 0x1078, 0x2a1c,
+	0x0040, 0x22a0, 0x1078, 0x34d7, 0x1078, 0x35b9, 0x0078, 0x2272,
+	0x81ff, 0x00c0, 0x229c, 0x1078, 0x2a1c, 0x0040, 0x22a0, 0x1078,
+	0x34d7, 0x1078, 0x35a3, 0x0078, 0x2272, 0x6100, 0x0078, 0x2272,
+	0x1078, 0x2a1c, 0x0040, 0x22a0, 0x6004, 0xa086, 0x0707, 0x0040,
+	0x22a0, 0x2001, 0x6d00, 0x2004, 0xa086, 0x0003, 0x00c0, 0x229c,
+	0x0d7e, 0xace8, 0x000a, 0x7924, 0xd184, 0x0040, 0x27b9, 0xace8,
+	0x0006, 0x680c, 0x8007, 0x783e, 0x6808, 0x8007, 0x783a, 0x6b04,
+	0x831f, 0x6a00, 0x8217, 0x0d7f, 0x6100, 0xa18c, 0x0200, 0x0078,
+	0x2272, 0x81ff, 0x00c0, 0x229c, 0x7828, 0xa08a, 0x1000, 0x00c8,
+	0x22a0, 0x7924, 0xa184, 0x00ff, 0xa082, 0x0010, 0x00c8, 0x22a0,
+	0xa18c, 0xff00, 0x810f, 0xa186, 0x00ff, 0x0040, 0x27e6, 0xa182,
+	0x007f, 0x00c8, 0x22a0, 0x2100, 0x1078, 0x1e30, 0x027e, 0x0c7e,
+	0x127e, 0x2091, 0x8000, 0x2061, 0x6f23, 0x601b, 0x0000, 0x601f,
+	0x0000, 0x2061, 0x6d00, 0x6003, 0x0001, 0x2061, 0x0100, 0x6030,
+	0xa084, 0x00ff, 0x810f, 0xa105, 0x604a, 0x6043, 0x0090, 0x6043,
+	0x0010, 0x2009, 0x001e, 0x2011, 0x31f0, 0x1078, 0x415f, 0x7924,
+	0x810f, 0x7a28, 0x1078, 0x275f, 0x127f, 0x0c7f, 0x027f, 0x0078,
+	0x2272, 0x7924, 0xa18c, 0xff00, 0x810f, 0x0c7e, 0x1078, 0x3410,
+	0x2c08, 0x0c7f, 0x00c0, 0x22a0, 0x0078, 0x2272, 0x81ff, 0x00c0,
+	0x229c, 0x60bc, 0xd09c, 0x0040, 0x229c, 0x1078, 0x2a04, 0x0040,
+	0x229c, 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x2a3c,
+	0x701b, 0x2833, 0x007c, 0x2009, 0x0080, 0x1078, 0x3447, 0x00c0,
+	0x229c, 0x0d7e, 0xade8, 0x000d, 0x6900, 0x6a08, 0x6b0c, 0x6c10,
+	0x6d14, 0x6e18, 0x6820, 0xa0be, 0x0100, 0x0040, 0x28a7, 0xa0be,
+	0x0112, 0x0040, 0x28a7, 0xa0be, 0x0113, 0x0040, 0x28a7, 0xa0be,
+	0x0114, 0x0040, 0x28a7, 0xa0be, 0x0117, 0x0040, 0x28a7, 0xa0be,
+	0x011a, 0x0040, 0x28a7, 0xa0be, 0x0121, 0x0040, 0x289d, 0xa0be,
+	0x0131, 0x0040, 0x289d, 0xa0be, 0x0171, 0x0040, 0x28a7, 0xa0be,
+	0x01a1, 0x00c0, 0x2870, 0x6830, 0x8007, 0x6832, 0x0078, 0x28ad,
+	0xa0be, 0x0212, 0x0040, 0x28a3, 0xa0be, 0x0213, 0x0040, 0x28a3,
+	0xa0be, 0x0214, 0x0040, 0x2895, 0xa0be, 0x0217, 0x0040, 0x288f,
+	0xa0be, 0x021a, 0x00c0, 0x2889, 0x6838, 0x8007, 0x683a, 0x0078,
+	0x28a7, 0xa0be, 0x0300, 0x0040, 0x28a7, 0x0078, 0x229c, 0xad80,
+	0x0010, 0x20a9, 0x0007, 0x1078, 0x28d9, 0xad80, 0x000e, 0x20a9,
+	0x0001, 0x1078, 0x28d9, 0x0078, 0x28a7, 0xad80, 0x000c, 0x1078,
+	0x28e7, 0x0078, 0x28ad, 0xad80, 0x000e, 0x1078, 0x28e7, 0xad80,
+	0x000c, 0x20a9, 0x0001, 0x1078, 0x28d9, 0x0c7e, 0x1078, 0x2a04,
+	0x0040, 0x28ce, 0x6837, 0x0119, 0x684f, 0x0020, 0x685b, 0x0001,
+	0x810b, 0x697e, 0x6883, 0x0000, 0x6a86, 0x6b8a, 0x6c8e, 0x6d92,
+	0x6996, 0x689b, 0x0000, 0x0c7f, 0x0d7f, 0x1078, 0x623f, 0x0040,
+	0x229c, 0x7007, 0x0003, 0x701b, 0x28d2, 0x007c, 0x0c7f, 0x0d7f,
+	0x0078, 0x229c, 0x6820, 0xa086, 0x8001, 0x0040, 0x229c, 0x0078,
+	0x2272, 0x017e, 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x290a,
+	0x8108, 0x280a, 0x8108, 0x00f0, 0x28db, 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, 0x229c,
+	0x7924, 0xa18c, 0xff00, 0x810f, 0xa182, 0x0081, 0x0048, 0x22a0,
+	0xa182, 0x00ff, 0x00c8, 0x22a0, 0x7a2c, 0x7b28, 0x6064, 0xa306,
+	0x00c0, 0x2918, 0x6068, 0xa206, 0x00c0, 0x2918, 0x0078, 0x22a0,
+	0x0c7e, 0x1078, 0x297b, 0x2c68, 0x0c7f, 0x0040, 0x2939, 0xa0c6,
+	0x4007, 0x00c0, 0x2926, 0x7c26, 0x0078, 0x2936, 0xa0c6, 0x4008,
+	0x00c0, 0x292e, 0x7f26, 0x7e2a, 0x0078, 0x2936, 0xa0c6, 0x4009,
+	0x00c0, 0x2934, 0x0078, 0x2936, 0x2001, 0x4006, 0x2020, 0x0078,
+	0x2274, 0x017e, 0x0b7e, 0x0c7e, 0x0e7e, 0x2c70, 0x1078, 0x5504,
+	0x0040, 0x2969, 0x2d00, 0x601a, 0x2e58, 0x0e7f, 0x0e7e, 0x0c7e,
+	0x1078, 0x2a04, 0x0c7f, 0x2b70, 0x0040, 0x229c, 0x6837, 0x0000,
+	0x2d00, 0x6012, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, 0x33df,
+	0x2001, 0x0002, 0x1078, 0x33f3, 0x127e, 0x2091, 0x8000, 0x7088,
+	0x8000, 0x708a, 0x127f, 0x2009, 0x0002, 0x1078, 0x5591, 0xa085,
+	0x0001, 0x0e7f, 0x0c7f, 0x0b7f, 0x017f, 0x0040, 0x229c, 0x7007,
+	0x0003, 0x701b, 0x2974, 0x007c, 0x6830, 0xa086, 0x0100, 0x00c0,
+	0x2272, 0x0078, 0x229c, 0x0e7e, 0x0d7e, 0x2029, 0x0000, 0x2021,
+	0x0081, 0x20a9, 0x007e, 0x2071, 0x6e81, 0x2e04, 0xa005, 0x00c0,
+	0x298f, 0x2100, 0xa406, 0x0040, 0x29c0, 0x0078, 0x29b4, 0x2068,
+	0x6f10, 0x2700, 0xa306, 0x00c0, 0x29a5, 0x6e14, 0x2600, 0xa206,
+	0x00c0, 0x29a5, 0x2400, 0xa106, 0x00c0, 0x29a1, 0x2d60, 0x0078,
+	0x29c6, 0x2001, 0x4007, 0x0078, 0x29c7, 0x2400, 0xa106, 0x00c0,
+	0x29b4, 0x6e14, 0x87ff, 0x00c0, 0x29b0, 0x86ff, 0x0040, 0x29c0,
+	0x2001, 0x4008, 0x0078, 0x29c7, 0x8420, 0x8e70, 0x00f0, 0x2985,
+	0x2001, 0x4009, 0x0078, 0x29c7, 0x2001, 0x0001, 0x0078, 0x29c7,
+	0x1078, 0x3410, 0x00c0, 0x29bc, 0x6312, 0x6216, 0xa006, 0xa005,
+	0x0d7f, 0x0e7f, 0x007c, 0x81ff, 0x00c0, 0x229c, 0x1078, 0x2a04,
+	0x0040, 0x229c, 0x6837, 0x0000, 0x7824, 0xa005, 0x0040, 0x22a0,
+	0xa096, 0x00ff, 0x0040, 0x29e0, 0xa092, 0x0004, 0x00c8, 0x22a0,
+	0x2010, 0x2d18, 0x1078, 0x2013, 0x0040, 0x229c, 0x7007, 0x0003,
+	0x701b, 0x29eb, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x229c,
+	0x0078, 0x2272, 0x7924, 0xa18c, 0xff00, 0x810f, 0xa182, 0x0081,
+	0x0048, 0x22a0, 0xa182, 0x00ff, 0x00c8, 0x22a0, 0x1078, 0x615b,
+	0x1078, 0x342f, 0x0078, 0x2272, 0x1078, 0x12f4, 0x0040, 0x2a1b,
+	0xa006, 0x6802, 0x7010, 0xa005, 0x00c0, 0x2a13, 0x2d00, 0x7012,
+	0x7016, 0x0078, 0x2a19, 0x7014, 0x6802, 0x2060, 0x2d00, 0x6006,
+	0x7016, 0xad80, 0x000d, 0x007c, 0x7e24, 0x860f, 0xa18c, 0x00ff,
+	0x1078, 0x3447, 0x00c0, 0x2a2a, 0xa6b4, 0x00ff, 0xa682, 0x0010,
+	0x0048, 0x2a2b, 0xa066, 0x8cff, 0x007c, 0x017e, 0x7110, 0x81ff,
+	0x0040, 0x2a38, 0x2168, 0x6904, 0x1078, 0x1328, 0x0078, 0x2a2f,
+	0x7112, 0x7116, 0x017f, 0x007c, 0x2031, 0x0001, 0x0078, 0x2a42,
+	0x2031, 0x0000, 0x2061, 0x6d9d, 0x6606, 0x6112, 0x600e, 0x6226,
+	0x632a, 0x642e, 0x6532, 0x2c10, 0x1078, 0x135f, 0x7007, 0x0002,
+	0x701b, 0x2272, 0x007c, 0x0f7e, 0x127e, 0x2091, 0x8000, 0x2079,
+	0x0000, 0x2001, 0x6d7b, 0x2004, 0xa005, 0x00c0, 0x2a6e, 0x0068,
+	0x2a6e, 0x7818, 0xd084, 0x00c0, 0x2a6e, 0x781b, 0x0001, 0x7a22,
+	0x7b26, 0x7c2a, 0x2091, 0x4080, 0x0078, 0x2a93, 0x017e, 0x0c7e,
+	0x0e7e, 0x2071, 0x6d6d, 0x7138, 0xa182, 0x0004, 0x0048, 0x2a7c,
+	0x7030, 0x2060, 0x0078, 0x2a8d, 0x7030, 0xa0e0, 0x0008, 0xac82,
+	0x6d9d, 0x0048, 0x2a85, 0x2061, 0x6d7d, 0x2c00, 0x7032, 0x81ff,
+	0x00c0, 0x2a8b, 0x7036, 0x8108, 0x713a, 0x2262, 0x6306, 0x640a,
+	0x0e7f, 0x0c7f, 0x017f, 0x127f, 0x0f7f, 0x007c, 0x0e7e, 0x2071,
+	0x6d6d, 0x7038, 0xa005, 0x0040, 0x2acf, 0x127e, 0x2091, 0x8000,
+	0x0068, 0x2ace, 0x0f7e, 0x2079, 0x0000, 0x7818, 0xd084, 0x00c0,
+	0x2acd, 0x0c7e, 0x781b, 0x0001, 0x7034, 0x2060, 0x2c04, 0x7822,
+	0x6004, 0x7826, 0x6008, 0x782a, 0x2091, 0x4080, 0x7038, 0x8001,
+	0x703a, 0xa005, 0x00c0, 0x2ac3, 0x7033, 0x6d7d, 0x7037, 0x6d7d,
+	0x0c7f, 0x0078, 0x2acd, 0xac80, 0x0008, 0xa0fa, 0x6d9d, 0x0048,
+	0x2acb, 0x2001, 0x6d7d, 0x7036, 0x0c7f, 0x0f7f, 0x127f, 0x0e7f,
+	0x007c, 0x027e, 0x2001, 0x6d52, 0x2004, 0xd0c4, 0x0040, 0x2adc,
+	0x2011, 0x8014, 0x1078, 0x2a53, 0x027f, 0x007c, 0x81ff, 0x00c0,
+	0x229c, 0x127e, 0x2091, 0x8000, 0x6030, 0xc08d, 0x6032, 0x1078,
+	0x31cb, 0x127f, 0x0078, 0x2272, 0x127e, 0x0c7e, 0x0e7e, 0x2061,
+	0x0100, 0x2071, 0x6d00, 0x6044, 0xd0a4, 0x00c0, 0x2b11, 0xd084,
+	0x0040, 0x2afe, 0x1078, 0x2c34, 0x0078, 0x2b11, 0xd08c, 0x0040,
+	0x2b05, 0x1078, 0x2b4b, 0x0078, 0x2b11, 0xd094, 0x0040, 0x2b0c,
+	0x1078, 0x2b2c, 0x0078, 0x2b11, 0xd09c, 0x0040, 0x2b11, 0x1078,
+	0x2b15, 0x0e7f, 0x0c7f, 0x127f, 0x007c, 0x6043, 0x0040, 0x6043,
+	0x0000, 0x706f, 0x0000, 0x7087, 0x0001, 0x70a7, 0x0000, 0x2009,
+	0x73c0, 0x200b, 0x0000, 0x7073, 0x000f, 0x2009, 0x000f, 0x2011,
+	0x3187, 0x1078, 0x415f, 0x007c, 0x7070, 0xa005, 0x00c0, 0x2b4a,
+	0x2011, 0x3187, 0x1078, 0x40d1, 0x6043, 0x0020, 0x6043, 0x0000,
+	0x6044, 0xd08c, 0x00c0, 0x2b46, 0x7003, 0x0001, 0x7083, 0x0000,
+	0x6043, 0x0090, 0x6043, 0x0010, 0x0078, 0x2b4a, 0x7077, 0x0000,
+	0x0078, 0x2b4a, 0x007c, 0x7074, 0xa08a, 0x0003, 0x00c8, 0x2b54,
+	0x1079, 0x2b57, 0x0078, 0x2b56, 0x1078, 0x12b7, 0x007c, 0x2b5a,
+	0x2ba9, 0x2c33, 0x0f7e, 0x7077, 0x0001, 0x20e1, 0xa000, 0x20e1,
+	0x8700, 0x1078, 0x1bcc, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2079,
+	0x7200, 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, 0x720c, 0x207b, 0x1101, 0x7807, 0x0000, 0x2099,
+	0x6d05, 0x20a1, 0x720e, 0x20a9, 0x0004, 0x53a3, 0x2079, 0x7212,
+	0x207b, 0x0000, 0x7807, 0x0000, 0x2099, 0x7200, 0x20a1, 0x020b,
+	0x20a9, 0x0014, 0x53a6, 0x60c3, 0x000c, 0x600f, 0x0000, 0x1078,
+	0x31b2, 0x0f7f, 0x707b, 0x0000, 0x6043, 0x0008, 0x6043, 0x0000,
+	0x007c, 0x0d7e, 0x7078, 0x707b, 0x0000, 0xa025, 0x0040, 0x2c1d,
+	0x6020, 0xd0b4, 0x00c0, 0x2c1b, 0x7184, 0x81ff, 0x0040, 0x2c04,
+	0xa486, 0x000c, 0x00c0, 0x2c0f, 0xa480, 0x0018, 0x8004, 0x20a8,
+	0x2011, 0x7280, 0x2019, 0x7200, 0x220c, 0x2304, 0xa106, 0x00c0,
+	0x2bdb, 0x8210, 0x8318, 0x00f0, 0x2bc4, 0x6043, 0x0004, 0x608b,
+	0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006, 0x7077, 0x0002, 0x7083,
+	0x0002, 0x0078, 0x2c1b, 0x2069, 0x7280, 0x6930, 0xa18e, 0x1101,
+	0x00c0, 0x2c0f, 0x6834, 0xa005, 0x00c0, 0x2c0f, 0x6900, 0xa18c,
+	0x00ff, 0x00c0, 0x2bef, 0x6804, 0xa005, 0x0040, 0x2c04, 0x2011,
+	0x728e, 0x2019, 0x6d05, 0x20a9, 0x0004, 0x220c, 0x2304, 0xa102,
+	0x0048, 0x2c02, 0x00c0, 0x2c0f, 0x8210, 0x8318, 0x00f0, 0x2bf5,
+	0x0078, 0x2c0f, 0x7087, 0x0000, 0x20e1, 0x9080, 0x20e1, 0x4000,
+	0x2099, 0x7280, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x6043,
+	0x0008, 0x6043, 0x0000, 0x6020, 0xd0b4, 0x00c0, 0x2c1b, 0x60c3,
+	0x000c, 0x1078, 0x31b2, 0x0d7f, 0x007c, 0x6020, 0xd0b4, 0x00c0,
+	0x2c1b, 0x60c3, 0x000c, 0x2011, 0x6f1a, 0x2013, 0x0000, 0x707b,
+	0x0000, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x1078,
+	0x4fdc, 0x0078, 0x2c1b, 0x007c, 0x7080, 0xa08a, 0x001d, 0x00c8,
+	0x2c3d, 0x1079, 0x2c40, 0x0078, 0x2c3f, 0x1078, 0x12b7, 0x007c,
+	0x2c64, 0x2c73, 0x2ca6, 0x2cbb, 0x2ced, 0x2d17, 0x2d49, 0x2d73,
+	0x2da5, 0x2dcb, 0x2e1a, 0x2e3c, 0x2e60, 0x2e76, 0x2e9c, 0x2eaf,
+	0x2eb8, 0x2ed1, 0x2f01, 0x2f2b, 0x2f5b, 0x2f85, 0x2fce, 0x3003,
+	0x3025, 0x3063, 0x3087, 0x30a0, 0x30ad, 0x7003, 0x0007, 0x6004,
+	0xa084, 0xfff9, 0x6006, 0x007c, 0x608b, 0xbc94, 0x608f, 0xf0f0,
+	0x6043, 0x0002, 0x7083, 0x0001, 0x2009, 0x07d0, 0x2011, 0x318e,
+	0x1078, 0x40c4, 0x007c, 0x0f7e, 0x7078, 0xa086, 0x0014, 0x00c0,
+	0x2ca4, 0x6043, 0x0000, 0x6020, 0xd0b4, 0x00c0, 0x2ca4, 0x2079,
+	0x7280, 0x7a30, 0xa296, 0x1102, 0x00c0, 0x2ca2, 0x7834, 0xa005,
+	0x00c0, 0x2ca2, 0x7a38, 0xd2fc, 0x0040, 0x2c98, 0x70a4, 0xa005,
+	0x00c0, 0x2c98, 0x2019, 0x002a, 0x1078, 0x202f, 0x70a7, 0x0001,
+	0x2011, 0x318e, 0x1078, 0x40d1, 0x7083, 0x0010, 0x1078, 0x2eb8,
+	0x0078, 0x2ca4, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x0003,
+	0x6043, 0x0004, 0x1078, 0x321b, 0x20a3, 0x1102, 0x20a3, 0x0000,
+	0x20a9, 0x000a, 0x20a3, 0x0000, 0x00f0, 0x2cb2, 0x60c3, 0x0014,
+	0x1078, 0x31b2, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x2ceb,
+	0x2011, 0x318e, 0x1078, 0x40d1, 0xa086, 0x0014, 0x00c0, 0x2ce7,
+	0x2079, 0x7280, 0x7a30, 0xa296, 0x1102, 0x00c0, 0x2ce7, 0x7834,
+	0xa005, 0x00c0, 0x2ce7, 0x7a38, 0xd2fc, 0x0040, 0x2ce1, 0x70a4,
+	0xa005, 0x00c0, 0x2ce1, 0x2019, 0x002a, 0x1078, 0x202f, 0x70a7,
+	0x0001, 0x7083, 0x0004, 0x1078, 0x2ced, 0x0078, 0x2ceb, 0x7083,
+	0x0002, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x0005, 0x1078,
+	0x321b, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, 0x728e,
+	0x706c, 0xa005, 0x00c0, 0x2d09, 0x714c, 0xa186, 0xffff, 0x0040,
+	0x2d09, 0x1078, 0x3152, 0x0040, 0x2d09, 0x2019, 0x002a, 0x1078,
+	0x202f, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000,
+	0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x31b2, 0x007c, 0x0f7e,
+	0x7078, 0xa005, 0x0040, 0x2d47, 0x2011, 0x318e, 0x1078, 0x40d1,
+	0xa086, 0x0014, 0x00c0, 0x2d43, 0x2079, 0x7280, 0x7a30, 0xa296,
+	0x1103, 0x00c0, 0x2d43, 0x7834, 0xa005, 0x00c0, 0x2d43, 0x7a38,
+	0xd2fc, 0x0040, 0x2d3d, 0x70a4, 0xa005, 0x00c0, 0x2d3d, 0x2019,
+	0x002a, 0x1078, 0x202f, 0x70a7, 0x0001, 0x7083, 0x0006, 0x1078,
+	0x2d49, 0x0078, 0x2d47, 0x7083, 0x0002, 0x707b, 0x0000, 0x0f7f,
+	0x007c, 0x7083, 0x0007, 0x1078, 0x321b, 0x20a3, 0x1104, 0x20a3,
+	0x0000, 0x3430, 0x2011, 0x728e, 0x706c, 0xa005, 0x00c0, 0x2d65,
+	0x7150, 0xa186, 0xffff, 0x0040, 0x2d65, 0xa180, 0x2091, 0x200c,
+	0xa18c, 0xff00, 0x810f, 0x1078, 0x3152, 0x20a9, 0x0008, 0x2298,
+	0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014,
+	0x1078, 0x31b2, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x2da3,
+	0x2011, 0x318e, 0x1078, 0x40d1, 0xa086, 0x0014, 0x00c0, 0x2d9f,
+	0x2079, 0x7280, 0x7a30, 0xa296, 0x1104, 0x00c0, 0x2d9f, 0x7834,
+	0xa005, 0x00c0, 0x2d9f, 0x7a38, 0xd2fc, 0x0040, 0x2d99, 0x70a4,
+	0xa005, 0x00c0, 0x2d99, 0x2019, 0x002a, 0x1078, 0x202f, 0x70a7,
+	0x0001, 0x7083, 0x0008, 0x1078, 0x2da5, 0x0078, 0x2da3, 0x7083,
+	0x0002, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x0009, 0x1078,
+	0x321b, 0x20a3, 0x1105, 0x20a3, 0x0100, 0x3430, 0x706c, 0xa005,
+	0x00c0, 0x2db8, 0x1078, 0x30bc, 0x0040, 0x2dc8, 0x0078, 0x2dc2,
+	0x20a9, 0x0008, 0x2099, 0x728e, 0x26a0, 0x53a6, 0x20a3, 0x0000,
+	0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x31b2, 0x0078, 0x2dca,
+	0x1078, 0x2c5d, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x2e18,
+	0x2011, 0x318e, 0x1078, 0x40d1, 0xa086, 0x0014, 0x00c0, 0x2e14,
+	0x2079, 0x7280, 0x7a30, 0xa296, 0x1105, 0x00c0, 0x2e14, 0x7834,
+	0x2011, 0x0100, 0xa21e, 0x00c0, 0x2dfb, 0x7a38, 0xd2fc, 0x0040,
+	0x2df3, 0x70a4, 0xa005, 0x00c0, 0x2df3, 0x2019, 0x002a, 0x1078,
+	0x202f, 0x70a7, 0x0001, 0x707f, 0x0001, 0x7083, 0x000a, 0x1078,
+	0x2e1a, 0x0078, 0x2e18, 0xa005, 0x00c0, 0x2e14, 0x7a38, 0xd2fc,
+	0x0040, 0x2e0c, 0x70a4, 0xa005, 0x00c0, 0x2e0c, 0x2019, 0x002a,
+	0x1078, 0x202f, 0x70a7, 0x0001, 0x707f, 0x0000, 0x7083, 0x000e,
+	0x1078, 0x2e9c, 0x0078, 0x2e18, 0x7083, 0x0002, 0x707b, 0x0000,
+	0x0f7f, 0x007c, 0x7083, 0x000b, 0x2011, 0x720e, 0x22a0, 0x20a9,
+	0x0040, 0x2019, 0xffff, 0x43a4, 0x20a9, 0x0002, 0x2009, 0x0000,
+	0x41a4, 0x1078, 0x321b, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x6030,
+	0xa085, 0x0100, 0x2012, 0x2298, 0x20a9, 0x0042, 0x53a6, 0x60c3,
+	0x0084, 0x1078, 0x31b2, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040,
+	0x2e5e, 0x2011, 0x318e, 0x1078, 0x40d1, 0xa086, 0x0084, 0x00c0,
+	0x2e5a, 0x2079, 0x7280, 0x7a30, 0xa296, 0x1106, 0x00c0, 0x2e5a,
+	0x7834, 0xa005, 0x00c0, 0x2e5a, 0x7083, 0x000c, 0x1078, 0x2e60,
+	0x0078, 0x2e5e, 0x7083, 0x0002, 0x707b, 0x0000, 0x0f7f, 0x007c,
+	0x7083, 0x000d, 0x1078, 0x321b, 0x20a3, 0x1107, 0x20a3, 0x0000,
+	0x2099, 0x728e, 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3,
+	0x0000, 0x60c3, 0x0084, 0x1078, 0x31b2, 0x007c, 0x0f7e, 0x7078,
+	0xa005, 0x0040, 0x2e9a, 0x2011, 0x318e, 0x1078, 0x40d1, 0xa086,
+	0x0084, 0x00c0, 0x2e96, 0x2079, 0x7280, 0x7a30, 0xa296, 0x1107,
+	0x00c0, 0x2e96, 0x7834, 0xa005, 0x00c0, 0x2e96, 0x1078, 0x320d,
+	0x7083, 0x000e, 0x1078, 0x2e9c, 0x0078, 0x2e9a, 0x7083, 0x0002,
+	0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x000f, 0x707b, 0x0000,
+	0x608b, 0xbc85, 0x608f, 0xb5b5, 0x6043, 0x0005, 0x6043, 0x0004,
+	0x2009, 0x07d0, 0x2011, 0x318e, 0x1078, 0x40c4, 0x007c, 0x7078,
+	0xa005, 0x0040, 0x2eb7, 0x2011, 0x318e, 0x1078, 0x40d1, 0x007c,
+	0x7083, 0x0011, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0x7280,
+	0x20a1, 0x020b, 0x7478, 0xa480, 0x0018, 0xa080, 0x0007, 0xa084,
+	0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0014, 0x1078, 0x31b2,
+	0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x2eff, 0x2011, 0x318e,
+	0x1078, 0x40d1, 0xa086, 0x0014, 0x00c0, 0x2efd, 0x2079, 0x7280,
+	0x7a30, 0xa296, 0x1103, 0x00c0, 0x2efd, 0x7834, 0xa005, 0x00c0,
+	0x2efd, 0x7a38, 0xd2fc, 0x0040, 0x2ef7, 0x70a4, 0xa005, 0x00c0,
+	0x2ef7, 0x2019, 0x002a, 0x1078, 0x202f, 0x70a7, 0x0001, 0x7083,
+	0x0012, 0x1078, 0x2f01, 0x0078, 0x2eff, 0x707b, 0x0000, 0x0f7f,
+	0x007c, 0x7083, 0x0013, 0x1078, 0x3227, 0x20a3, 0x1103, 0x20a3,
+	0x0000, 0x3430, 0x2011, 0x728e, 0x706c, 0xa005, 0x00c0, 0x2f1d,
+	0x714c, 0xa186, 0xffff, 0x0040, 0x2f1d, 0x1078, 0x3152, 0x0040,
+	0x2f1d, 0x2019, 0x002a, 0x1078, 0x202f, 0x20a9, 0x0008, 0x2298,
+	0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014,
+	0x1078, 0x31b2, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x2f59,
+	0x2011, 0x318e, 0x1078, 0x40d1, 0xa086, 0x0014, 0x00c0, 0x2f57,
+	0x2079, 0x7280, 0x7a30, 0xa296, 0x1104, 0x00c0, 0x2f57, 0x7834,
+	0xa005, 0x00c0, 0x2f57, 0x7a38, 0xd2fc, 0x0040, 0x2f51, 0x70a4,
+	0xa005, 0x00c0, 0x2f51, 0x2019, 0x002a, 0x1078, 0x202f, 0x70a7,
+	0x0001, 0x7083, 0x0014, 0x1078, 0x2f5b, 0x0078, 0x2f59, 0x707b,
+	0x0000, 0x0f7f, 0x007c, 0x7083, 0x0015, 0x1078, 0x3227, 0x20a3,
+	0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, 0x728e, 0x706c, 0xa006,
+	0x00c0, 0x2f77, 0x7150, 0xa186, 0xffff, 0x0040, 0x2f77, 0xa180,
+	0x2091, 0x200c, 0xa18c, 0xff00, 0x810f, 0x1078, 0x3152, 0x20a9,
+	0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000,
+	0x60c3, 0x0014, 0x1078, 0x31b2, 0x007c, 0x0f7e, 0x7078, 0xa005,
+	0x0040, 0x2fcc, 0x2011, 0x318e, 0x1078, 0x40d1, 0xa086, 0x0014,
+	0x00c0, 0x2fca, 0x2079, 0x7280, 0x7a30, 0xa296, 0x1105, 0x00c0,
+	0x2fca, 0x7834, 0x2011, 0x0100, 0xa21e, 0x00c0, 0x2fb1, 0x7a38,
+	0xd2fc, 0x0040, 0x2fad, 0x70a4, 0xa005, 0x00c0, 0x2fad, 0x2019,
+	0x002a, 0x1078, 0x202f, 0x70a7, 0x0001, 0x707f, 0x0001, 0x0078,
+	0x2fc4, 0xa005, 0x00c0, 0x2fca, 0x7a38, 0xd2fc, 0x0040, 0x2fc2,
+	0x70a4, 0xa005, 0x00c0, 0x2fc2, 0x2019, 0x002a, 0x1078, 0x202f,
+	0x70a7, 0x0001, 0x707f, 0x0000, 0x7083, 0x0016, 0x1078, 0x2fce,
+	0x0078, 0x2fcc, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x20e1, 0x9080,
+	0x20e1, 0x4000, 0x2099, 0x7280, 0x20a1, 0x020b, 0x20a9, 0x000e,
+	0x53a6, 0x3430, 0x2011, 0x728e, 0x707c, 0xa005, 0x0040, 0x2fe4,
+	0x7083, 0x0017, 0x0078, 0x2fe6, 0x7083, 0x001b, 0x706c, 0xa005,
+	0x00c0, 0x2ff0, 0x1078, 0x30bc, 0x0040, 0x3000, 0x0078, 0x2ffa,
+	0x20a9, 0x0008, 0x2099, 0x728e, 0x26a0, 0x53a6, 0x20a3, 0x0000,
+	0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x31b2, 0x0078, 0x3002,
+	0x1078, 0x2c5d, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x3023,
+	0x2011, 0x318e, 0x1078, 0x40d1, 0xa086, 0x0084, 0x00c0, 0x3021,
+	0x2079, 0x7280, 0x7a30, 0xa296, 0x1106, 0x00c0, 0x3021, 0x7834,
+	0xa005, 0x00c0, 0x3021, 0x7083, 0x0018, 0x1078, 0x3025, 0x0078,
+	0x3023, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x0019, 0x1078,
+	0x3227, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x3430, 0x2099, 0x728e,
+	0x2039, 0x720e, 0x27a0, 0x20a9, 0x0040, 0x53a3, 0x2728, 0x2514,
+	0x8207, 0xa084, 0x00ff, 0x8000, 0x2018, 0xa294, 0x00ff, 0x8007,
+	0xa205, 0x202a, 0x6030, 0x2310, 0x8214, 0xa2a0, 0x720e, 0x2414,
+	0xa38c, 0x0001, 0x0040, 0x3050, 0xa294, 0xff00, 0x0078, 0x3053,
+	0xa294, 0x00ff, 0x8007, 0xa215, 0x2222, 0x2798, 0x26a0, 0x20a9,
+	0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084,
+	0x1078, 0x31b2, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x3085,
+	0x2011, 0x318e, 0x1078, 0x40d1, 0xa086, 0x0084, 0x00c0, 0x3083,
+	0x2079, 0x7280, 0x7a30, 0xa296, 0x1107, 0x00c0, 0x3083, 0x7834,
+	0xa005, 0x00c0, 0x3083, 0x1078, 0x320d, 0x7083, 0x001a, 0x1078,
+	0x3087, 0x0078, 0x3085, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083,
+	0x001b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0x7280, 0x20a1,
+	0x020b, 0x7478, 0xa480, 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8,
+	0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0084, 0x1078, 0x31b2, 0x007c,
+	0x7078, 0xa005, 0x0040, 0x30ac, 0x2011, 0x318e, 0x1078, 0x40d1,
+	0x7083, 0x001c, 0x1078, 0x30ad, 0x007c, 0x707b, 0x0000, 0x608b,
+	0xbc85, 0x608f, 0xb5b5, 0x6043, 0x0001, 0x2009, 0x07d0, 0x2011,
+	0x318e, 0x1078, 0x40c4, 0x007c, 0x087e, 0x097e, 0x2029, 0x6d52,
+	0x252c, 0x20a9, 0x0008, 0x2041, 0x720e, 0x28a0, 0x2099, 0x728e,
+	0x53a3, 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0040, 0x30d2,
+	0x2011, 0x0000, 0x2800, 0xa200, 0x200c, 0xa1a6, 0xffff, 0x00c0,
+	0x30e4, 0xd5d4, 0x0040, 0x30df, 0x8210, 0x0078, 0x30e0, 0x8211,
+	0x00f0, 0x30d2, 0x0078, 0x3149, 0x82ff, 0x00c0, 0x30f6, 0xd5d4,
+	0x0040, 0x30f0, 0xa1a6, 0x3fff, 0x0040, 0x30dc, 0x0078, 0x30f4,
+	0xa1a6, 0x3fff, 0x0040, 0x3149, 0xa18d, 0xc000, 0x20a9, 0x0010,
+	0x2019, 0x0001, 0xd5d4, 0x0040, 0x30ff, 0x2019, 0x0010, 0x2120,
+	0xd5d4, 0x0040, 0x3106, 0x8423, 0x0078, 0x3107, 0x8424, 0x00c8,
+	0x3114, 0xd5d4, 0x0040, 0x310f, 0x8319, 0x0078, 0x3110, 0x8318,
+	0x00f0, 0x3100, 0x0078, 0x3149, 0x23a8, 0x2021, 0x0001, 0x8426,
+	0x8425, 0x00f0, 0x3118, 0x2328, 0x8529, 0xa2be, 0x0007, 0x0040,
+	0x312c, 0x007e, 0x2039, 0x0007, 0x2200, 0xa73a, 0x007f, 0x27a8,
+	0xa5a8, 0x0010, 0x00f0, 0x3128, 0x754e, 0xa5c8, 0x2091, 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,
+	0x314f, 0xa006, 0x0078, 0x314f, 0xa006, 0x1078, 0x12b7, 0x097f,
+	0x087f, 0x007c, 0x2118, 0x2021, 0x0000, 0x2001, 0x0007, 0xa39a,
+	0x0010, 0x0048, 0x315f, 0x8420, 0x8001, 0x0078, 0x3157, 0x2118,
+	0x84ff, 0x0040, 0x3168, 0xa39a, 0x0010, 0x8421, 0x00c0, 0x3163,
+	0x2021, 0x0001, 0x83ff, 0x0040, 0x3171, 0x8423, 0x8319, 0x00c0,
+	0x316d, 0xa238, 0x2704, 0xa42c, 0x00c0, 0x3186, 0xa405, 0x203a,
+	0x714e, 0xa1a0, 0x2091, 0x242c, 0xa5ac, 0x00ff, 0x6532, 0x60e7,
+	0x0000, 0x65ea, 0x706f, 0x0001, 0xa084, 0x0000, 0x007c, 0x0e7e,
+	0x2071, 0x6d00, 0x7073, 0x0000, 0x0e7f, 0x007c, 0x0e7e, 0x0f7e,
+	0x2079, 0x0100, 0x2071, 0x0140, 0x1078, 0x4fe5, 0x7004, 0xa084,
+	0x4000, 0x0040, 0x319f, 0x7003, 0x1000, 0x7003, 0x0000, 0x127e,
+	0x2091, 0x8000, 0x2071, 0x6d00, 0x7003, 0x0001, 0x2071, 0x6d20,
+	0x2073, 0x0000, 0x7843, 0x0090, 0x7843, 0x0010, 0x127f, 0x0f7f,
+	0x0e7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x2011, 0x6f1a, 0x2013,
+	0x0000, 0x707b, 0x0000, 0x127f, 0x20e1, 0x9080, 0x60a3, 0x0056,
+	0x60a7, 0x9575, 0x1078, 0x4fdc, 0x2009, 0x07d0, 0x2011, 0x318e,
+	0x1078, 0x415f, 0x007c, 0x017e, 0x027e, 0x0c7e, 0x127e, 0x2091,
+	0x8000, 0x2009, 0x00f7, 0x1078, 0x3233, 0x2061, 0x6f23, 0x601b,
+	0x0000, 0x601f, 0x0000, 0x2061, 0x6d00, 0x6003, 0x0001, 0x2061,
+	0x0100, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x001e, 0x2011,
+	0x31f0, 0x1078, 0x40c4, 0x127f, 0x0c7f, 0x027f, 0x017f, 0x007c,
+	0x0e7e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0x0100, 0x1078,
+	0x4fe5, 0x2071, 0x0140, 0xa084, 0x4000, 0x0040, 0x3203, 0x7003,
+	0x1000, 0x7003, 0x0000, 0x2001, 0x0001, 0x1078, 0x1dc9, 0x1078,
+	0x31cb, 0x127f, 0x007f, 0x0e7f, 0x007c, 0x20a9, 0x0040, 0x20a1,
+	0x73c0, 0x2099, 0x728e, 0x3304, 0x8007, 0x20a2, 0x9398, 0x94a0,
+	0x00f0, 0x3213, 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099,
+	0x7200, 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, 0x007c, 0x20e1,
+	0x9080, 0x20e1, 0x4000, 0x2099, 0x7280, 0x20a1, 0x020b, 0x20a9,
+	0x000c, 0x53a6, 0x007c, 0x0c7e, 0x007e, 0x2061, 0x0100, 0x810f,
+	0x2001, 0x6d2c, 0x2004, 0xa005, 0x00c0, 0x3244, 0x6030, 0xa084,
+	0x00ff, 0xa105, 0x0078, 0x3246, 0xa185, 0x00f7, 0x604a, 0x007f,
+	0x0c7f, 0x007c, 0x157e, 0x20a9, 0x00ff, 0x2009, 0x6e00, 0xa006,
+	0x200a, 0x8108, 0x00f0, 0x3250, 0x157f, 0x007c, 0x0d7e, 0x037e,
+	0x157e, 0x137e, 0x147e, 0x2069, 0x6d51, 0xa006, 0x6002, 0x6007,
+	0x0707, 0x600a, 0x600e, 0x6012, 0xa198, 0x2091, 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, 0x604a, 0x6810,
+	0x603a, 0x680c, 0x6046, 0x147f, 0x137f, 0x157f, 0x037f, 0x0d7f,
+	0x007c, 0x127e, 0x2091, 0x8000, 0x6944, 0xa1b4, 0x00ff, 0xa682,
+	0x0010, 0x00c8, 0x3337, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff,
+	0x00c8, 0x333d, 0xa188, 0x6e00, 0x2104, 0xa065, 0x0040, 0x3316,
+	0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x00c0, 0x331c, 0x6078,
+	0xa00d, 0x0040, 0x32c1, 0xa680, 0x6c84, 0x2004, 0xa10c, 0x00c0,
+	0x3310, 0x607c, 0xa00d, 0x0040, 0x32dd, 0xa680, 0x6c84, 0x2004,
+	0xa10c, 0x0040, 0x32dd, 0x694c, 0xd1fc, 0x00c0, 0x32d3, 0x1078,
+	0x33d0, 0x0078, 0x330b, 0x1078, 0x33a1, 0x694c, 0xd1ec, 0x00c0,
+	0x330b, 0x1078, 0x34f0, 0x0078, 0x330b, 0x694c, 0xa184, 0xa000,
+	0x0040, 0x32fb, 0xd1ec, 0x0040, 0x32f4, 0xd1fc, 0x0040, 0x32ec,
+	0x1078, 0x3507, 0x0078, 0x32f7, 0xa680, 0x6c84, 0x200c, 0x607c,
+	0xa105, 0x607e, 0x0078, 0x32fb, 0xd1fc, 0x0040, 0x32fb, 0x1078,
+	0x33a1, 0x0078, 0x330b, 0x6050, 0xa00d, 0x0040, 0x3306, 0x2d00,
+	0x200a, 0x6803, 0x0000, 0x6052, 0x0078, 0x330b, 0x2d00, 0x6052,
+	0x604e, 0x6803, 0x0000, 0x1078, 0x4346, 0xa006, 0x127f, 0x007c,
+	0x2001, 0x0005, 0x2009, 0x0000, 0x0078, 0x3341, 0x2001, 0x0028,
+	0x2009, 0x0000, 0x0078, 0x3341, 0xa082, 0x0006, 0x0048, 0x32b7,
+	0x2009, 0x6d0c, 0x210c, 0xd18c, 0x0040, 0x332a, 0x2001, 0x0004,
+	0x0078, 0x3333, 0xd184, 0x0040, 0x3331, 0x2001, 0x0004, 0x0078,
+	0x3333, 0x2001, 0x0029, 0x2009, 0x0000, 0x0078, 0x3341, 0x2001,
+	0x0029, 0x2009, 0x0000, 0x0078, 0x3341, 0x2001, 0x0029, 0x2009,
+	0x0000, 0xa005, 0x127f, 0x007c, 0x6944, 0xa1b4, 0x00ff, 0xa682,
+	0x0010, 0x00c8, 0x3386, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff,
+	0x00c8, 0x3376, 0xa188, 0x6e00, 0x2104, 0xa065, 0x0040, 0x3376,
+	0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x00c0, 0x337c, 0x684c,
+	0xd0ec, 0x0040, 0x3369, 0x1078, 0x3507, 0x1078, 0x33a1, 0x0078,
+	0x3371, 0x1078, 0x33a1, 0x684c, 0xd0fc, 0x0040, 0x3371, 0x1078,
+	0x34f0, 0x1078, 0x351b, 0xa006, 0x0078, 0x338a, 0x2001, 0x0028,
+	0x2009, 0x0000, 0x0078, 0x338a, 0xa082, 0x0006, 0x0048, 0x335f,
+	0x2001, 0x0029, 0x2009, 0x0000, 0x0078, 0x338a, 0x2001, 0x0029,
+	0x2009, 0x0000, 0xa005, 0x007c, 0x127e, 0x2091, 0x8000, 0x6050,
+	0xa00d, 0x0040, 0x339a, 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052,
+	0x127f, 0x007c, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x0078,
+	0x3398, 0x127e, 0x2091, 0x8000, 0x604c, 0xa005, 0x0040, 0x33ad,
+	0x6802, 0x2d00, 0x604e, 0x127f, 0x007c, 0x2d00, 0x6052, 0x604e,
+	0x6803, 0x0000, 0x0078, 0x33ab, 0x127e, 0x2091, 0x8000, 0x604c,
+	0xa06d, 0x0040, 0x33c2, 0x6800, 0xa005, 0x00c0, 0x33c0, 0x6052,
+	0x604e, 0xad05, 0x127f, 0x007c, 0x604c, 0xa06d, 0x0040, 0x33cf,
+	0x6800, 0xa005, 0x00c0, 0x33cd, 0x6052, 0x604e, 0xad05, 0x007c,
+	0x6803, 0x0000, 0x6084, 0xa00d, 0x0040, 0x33da, 0x2d00, 0x200a,
+	0x6086, 0x007c, 0x2d00, 0x6086, 0x6082, 0x0078, 0x33d9, 0x127e,
+	0x0c7e, 0x027e, 0x2091, 0x8000, 0x6218, 0x2260, 0x6200, 0xa005,
+	0x0040, 0x33ed, 0xc285, 0x0078, 0x33ee, 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, 0x3419, 0xa085, 0x0001, 0x0078,
+	0x342d, 0xa190, 0x6e00, 0x2204, 0xa065, 0x00c0, 0x342c, 0x017e,
+	0x0d7e, 0x1078, 0x12f4, 0x2d60, 0x0d7f, 0x017f, 0x0040, 0x3415,
+	0x2c00, 0x2012, 0x1078, 0x3256, 0xa006, 0x027f, 0x007c, 0x027e,
+	0xa182, 0x00ff, 0x0048, 0x3438, 0xa085, 0x0001, 0x0078, 0x3445,
+	0x0d7e, 0xa190, 0x6e00, 0x2204, 0xa06d, 0x0040, 0x3443, 0x2013,
+	0x0000, 0x1078, 0x1328, 0x0d7f, 0xa006, 0x027f, 0x007c, 0x017e,
+	0xa182, 0x00ff, 0x0048, 0x3450, 0xa085, 0x0001, 0x0078, 0x3457,
+	0xa188, 0x6e00, 0x2104, 0xa065, 0x0040, 0x344c, 0xa006, 0x017f,
+	0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x600b, 0x0000, 0x600f,
+	0x0000, 0x6000, 0xc08c, 0x6002, 0x2069, 0x728e, 0x6808, 0x605e,
+	0x6810, 0x6062, 0x6138, 0xa10a, 0x0048, 0x346f, 0x603a, 0x6814,
+	0x6066, 0x2099, 0x7296, 0xac88, 0x000a, 0x21a0, 0x20a9, 0x0004,
+	0x53a3, 0x2099, 0x729a, 0xac88, 0x0006, 0x21a0, 0x20a9, 0x0004,
+	0x53a3, 0x2069, 0x72ae, 0x6904, 0xa18c, 0x00ff, 0x810f, 0x6808,
+	0xa084, 0x00ff, 0xa105, 0x606a, 0x690c, 0x616e, 0x6810, 0x6072,
+	0x6818, 0x6076, 0xa182, 0x0211, 0x00c8, 0x349a, 0x2009, 0x0008,
+	0x0078, 0x34c4, 0xa182, 0x0259, 0x00c8, 0x34a2, 0x2009, 0x0007,
+	0x0078, 0x34c4, 0xa182, 0x02c1, 0x00c8, 0x34aa, 0x2009, 0x0006,
+	0x0078, 0x34c4, 0xa182, 0x0349, 0x00c8, 0x34b2, 0x2009, 0x0005,
+	0x0078, 0x34c4, 0xa182, 0x0421, 0x00c8, 0x34ba, 0x2009, 0x0004,
+	0x0078, 0x34c4, 0xa182, 0x0581, 0x00c8, 0x34c2, 0x2009, 0x0003,
+	0x0078, 0x34c4, 0x2009, 0x0002, 0x6192, 0x147f, 0x137f, 0x157f,
+	0x0d7f, 0x007c, 0x0e7e, 0x2071, 0x728d, 0x2e04, 0x6896, 0x2071,
+	0x728e, 0x7004, 0x689a, 0x701c, 0x689e, 0x0e7f, 0x007c, 0x2001,
+	0x6c84, 0xa600, 0x2004, 0x127e, 0x2091, 0x8000, 0x6178, 0xa10d,
+	0x617a, 0x127f, 0x007c, 0x2001, 0x6c84, 0xa600, 0x2004, 0x8002,
+	0x127e, 0x2091, 0x8000, 0x6178, 0xa10c, 0x617a, 0x127f, 0x007c,
+	0x2001, 0x6c84, 0xa600, 0x2004, 0x8002, 0x127e, 0x2091, 0x8000,
+	0x617c, 0xa10c, 0x617e, 0x127f, 0x0078, 0x3500, 0x1078, 0x338c,
+	0x1078, 0x3561, 0x00c0, 0x34fe, 0x1078, 0x351b, 0x007c, 0x2001,
+	0x6c84, 0xa600, 0x2004, 0x127e, 0x2091, 0x8000, 0x617c, 0xa10d,
+	0x617e, 0x127f, 0x0078, 0x3516, 0x1078, 0x33d0, 0x1078, 0x3525,
+	0x00c0, 0x3514, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, 0x4346,
+	0x127f, 0x007c, 0xa01e, 0x0078, 0x3527, 0x2019, 0x0001, 0xa00e,
+	0x127e, 0x2091, 0x8000, 0x604c, 0x2068, 0x6000, 0xd0dc, 0x00c0,
+	0x3547, 0x8dff, 0x0040, 0x355c, 0x83ff, 0x0040, 0x353f, 0x6844,
+	0xa084, 0x00ff, 0xa606, 0x0040, 0x354c, 0x0078, 0x3547, 0x683c,
+	0xa406, 0x00c0, 0x3547, 0x6840, 0xa506, 0x0040, 0x354c, 0x2d08,
+	0x6800, 0x2068, 0x0078, 0x3531, 0x6a00, 0x604c, 0xad06, 0x00c0,
+	0x3554, 0x624e, 0x0078, 0x3557, 0xa180, 0x0000, 0x2202, 0x82ff,
+	0x00c0, 0x355c, 0x6152, 0x8dff, 0x127f, 0x007c, 0xa01e, 0x0078,
+	0x3563, 0x2019, 0x0001, 0xa00e, 0x6080, 0x2068, 0x8dff, 0x0040,
+	0x3591, 0x83ff, 0x0040, 0x3574, 0x6844, 0xa084, 0x00ff, 0xa606,
+	0x0040, 0x3581, 0x0078, 0x357c, 0x683c, 0xa406, 0x00c0, 0x357c,
+	0x6840, 0xa506, 0x0040, 0x3581, 0x2d08, 0x6800, 0x2068, 0x0078,
+	0x3566, 0x6a00, 0x6080, 0xad06, 0x00c0, 0x3589, 0x6282, 0x0078,
+	0x358c, 0xa180, 0x0000, 0x2202, 0x82ff, 0x00c0, 0x3591, 0x6186,
+	0x8dff, 0x007c, 0x2001, 0x6c84, 0xa600, 0x2004, 0x6178, 0xa10c,
+	0x0040, 0x359c, 0x2011, 0x0001, 0x617c, 0xa10c, 0x0040, 0x35a2,
+	0xa295, 0x0002, 0x007c, 0x1078, 0x35ec, 0x0040, 0x35ab, 0x1078,
+	0x61f8, 0x0078, 0x35ad, 0xa085, 0x0001, 0x007c, 0x1078, 0x35ec,
+	0x0040, 0x35b6, 0x1078, 0x6187, 0x0078, 0x35b8, 0xa085, 0x0001,
+	0x007c, 0x1078, 0x35ec, 0x0040, 0x35c1, 0x1078, 0x61cd, 0x0078,
+	0x35c3, 0xa085, 0x0001, 0x007c, 0x1078, 0x35ec, 0x0040, 0x35cc,
+	0x1078, 0x61a3, 0x0078, 0x35ce, 0xa085, 0x0001, 0x007c, 0x127e,
+	0x007e, 0x0d7e, 0x2091, 0x8000, 0x6080, 0xa06d, 0x0040, 0x35e4,
+	0x6800, 0x007e, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078,
+	0x36a1, 0x007f, 0x0078, 0x35d5, 0x6083, 0x0000, 0x6087, 0x0000,
+	0x0d7f, 0x007f, 0x127f, 0x007c, 0x609c, 0xd0a4, 0x007c, 0x0f7e,
+	0x2079, 0x6d51, 0x7804, 0xd0a4, 0x0040, 0x3618, 0x157e, 0x0c7e,
+	0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x3447, 0x00c0,
+	0x360c, 0x6004, 0xa084, 0xff00, 0x8007, 0xa086, 0x0006, 0x00c0,
+	0x360c, 0x6000, 0xc0ed, 0x6002, 0x017f, 0x8108, 0x00f0, 0x35fc,
+	0x0c7f, 0x157f, 0x2009, 0x07d0, 0x2011, 0x361a, 0x1078, 0x415f,
+	0x0f7f, 0x007c, 0x2011, 0x361a, 0x1078, 0x40d1, 0x157e, 0x0c7e,
+	0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x3447, 0x00c0,
+	0x3646, 0x6000, 0xd0ec, 0x0040, 0x3646, 0x047e, 0x62a0, 0xa294,
+	0x00ff, 0x8227, 0xa006, 0x2009, 0x0029, 0x1078, 0x6bf7, 0x6000,
+	0xc0e5, 0xc0ec, 0x6002, 0x2019, 0x0029, 0x1078, 0x445c, 0x1078,
+	0x43a9, 0x2009, 0x0000, 0x1078, 0x6a57, 0x047f, 0x017f, 0x8108,
+	0x00f0, 0x3624, 0x0c7f, 0x157f, 0x007c, 0x0c7e, 0x6018, 0x2060,
+	0x6000, 0xc0ec, 0x6002, 0x0c7f, 0x007c, 0x2071, 0x6ddf, 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,
+	0x6ddf, 0x684c, 0xa005, 0x00c0, 0x367c, 0x7028, 0xc085, 0x702a,
+	0xa085, 0x0001, 0x0078, 0x369f, 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, 0x36f2, 0x6804, 0xa00d,
+	0x0040, 0x36c0, 0x0d7e, 0x0e7e, 0x2071, 0x6d00, 0x027e, 0xa016,
+	0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x00c0,
+	0x36b1, 0x702e, 0x70a0, 0xa200, 0x70a2, 0x027f, 0x0e7f, 0x0d7f,
+	0x2071, 0x6ddf, 0x701c, 0xa005, 0x00c0, 0x3703, 0x0068, 0x3701,
+	0x2071, 0x6d51, 0x7004, 0xd09c, 0x0040, 0x3701, 0x6934, 0xa186,
+	0x0103, 0x00c0, 0x3714, 0x6948, 0x6844, 0xa105, 0x00c0, 0x36f4,
+	0x2009, 0x8020, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x3701,
+	0x7122, 0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, 0x2091,
+	0x4080, 0x2071, 0x6d00, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70a0,
+	0x8000, 0x70a2, 0x0e7f, 0x007c, 0x6844, 0xa086, 0x0100, 0x00c0,
+	0x3701, 0x6868, 0xa005, 0x00c0, 0x3701, 0x2009, 0x8020, 0x0078,
+	0x36da, 0x2071, 0x6ddf, 0x2d08, 0x206b, 0x0000, 0x7010, 0x8000,
+	0x7012, 0x7018, 0xa06d, 0x711a, 0x0040, 0x3711, 0x6902, 0x0078,
+	0x3712, 0x711e, 0x0078, 0x36f2, 0xa18c, 0x00ff, 0xa18e, 0x0017,
+	0x0040, 0x371e, 0xa18e, 0x001f, 0x00c0, 0x3701, 0x684c, 0xd0cc,
+	0x0040, 0x3701, 0x6850, 0xa084, 0x00ff, 0xa086, 0x0001, 0x00c0,
+	0x3701, 0x2009, 0x8021, 0x0078, 0x36da, 0x007e, 0x6837, 0x0103,
+	0x20a9, 0x001c, 0xad80, 0x0011, 0x20a0, 0x2001, 0x0000, 0x40a4,
+	0x007f, 0x684a, 0x6952, 0x007c, 0x2071, 0x6ddf, 0x7004, 0x0079,
+	0x3741, 0x3749, 0x3758, 0x37e4, 0x37e5, 0x37f5, 0x37fb, 0x374a,
+	0x37d2, 0x007c, 0x127e, 0x2091, 0x8000, 0x0068, 0x3757, 0x2009,
+	0x000d, 0x7030, 0x200a, 0x2091, 0x4080, 0x7007, 0x0001, 0x127f,
+	0x701c, 0xa06d, 0x0040, 0x37d1, 0x0e7e, 0x2071, 0x6d51, 0x7004,
+	0xd09c, 0x0040, 0x37b3, 0x6934, 0xa186, 0x0103, 0x00c0, 0x378d,
+	0x6948, 0x6844, 0xa105, 0x00c0, 0x37a6, 0x2009, 0x8020, 0x127e,
+	0x2091, 0x8000, 0x0068, 0x3789, 0x2071, 0x0000, 0x7018, 0xd084,
+	0x00c0, 0x3789, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a, 0x701b,
+	0x0001, 0x2091, 0x4080, 0x127f, 0x0e7f, 0x1078, 0x382e, 0x0078,
+	0x37d1, 0x127f, 0x0e7f, 0x0078, 0x37d1, 0xa18c, 0x00ff, 0xa18e,
+	0x0017, 0x0040, 0x3797, 0xa18e, 0x001f, 0x00c0, 0x37b3, 0x684c,
+	0xd0cc, 0x0040, 0x37b3, 0x6850, 0xa084, 0x00ff, 0xa086, 0x0001,
+	0x00c0, 0x37b3, 0x2009, 0x8021, 0x0078, 0x376f, 0x6844, 0xa086,
+	0x0100, 0x00c0, 0x37b3, 0x6868, 0xa005, 0x00c0, 0x37b3, 0x2009,
+	0x8020, 0x0078, 0x376f, 0x0e7f, 0x1078, 0x3842, 0x0040, 0x37d1,
+	0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, 0x0003, 0x00c0,
+	0x37c8, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0040, 0x37c8, 0x710e,
+	0x7007, 0x0003, 0x1078, 0x3862, 0x7050, 0xa086, 0x0100, 0x0040,
+	0x37e5, 0x007c, 0x701c, 0xa06d, 0x0040, 0x37e3, 0x1078, 0x3842,
+	0x0040, 0x37e3, 0x7007, 0x0003, 0x1078, 0x3862, 0x7050, 0xa086,
+	0x0100, 0x0040, 0x37e5, 0x007c, 0x007c, 0x7050, 0xa09e, 0x0100,
+	0x00c0, 0x37ee, 0x7007, 0x0004, 0x0078, 0x37f5, 0xa086, 0x0200,
+	0x00c0, 0x37f4, 0x7007, 0x0005, 0x007c, 0x1078, 0x37fc, 0x7006,
+	0x1078, 0x382e, 0x007c, 0x007c, 0x702c, 0x7130, 0x8108, 0xa102,
+	0x0048, 0x3809, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, 0x0078,
+	0x3813, 0x706c, 0xa080, 0x0040, 0x706e, 0x00c8, 0x3813, 0x7070,
+	0xa081, 0x0000, 0x7072, 0x7132, 0x700c, 0x8001, 0x700e, 0x00c0,
+	0x3827, 0x127e, 0x2091, 0x8000, 0x0068, 0x382a, 0x2001, 0x000d,
+	0x2102, 0x2091, 0x4080, 0x2001, 0x0001, 0x127f, 0x007c, 0x2001,
+	0x0007, 0x007c, 0x2001, 0x0006, 0x127f, 0x007c, 0x701c, 0xa06d,
+	0x0040, 0x3841, 0x127e, 0x2091, 0x8000, 0x7010, 0x8001, 0x7012,
+	0x2d04, 0x701e, 0xa005, 0x00c0, 0x383e, 0x701a, 0x127f, 0x1078,
+	0x1328, 0x007c, 0x2019, 0x000d, 0x2304, 0x230c, 0xa10e, 0x0040,
+	0x3851, 0x2304, 0x230c, 0xa10e, 0x0040, 0x3851, 0xa006, 0x0078,
+	0x3861, 0x732c, 0x8319, 0x7130, 0xa102, 0x00c0, 0x385b, 0x2300,
+	0xa005, 0x0078, 0x3861, 0x0048, 0x3860, 0xa302, 0x0078, 0x3861,
+	0x8002, 0x007c, 0x2d00, 0x7026, 0xa080, 0x000d, 0x7056, 0x7053,
+	0x0000, 0x127e, 0x2091, 0x8000, 0x2009, 0x6f31, 0x2104, 0xc08d,
+	0x200a, 0x127f, 0x1078, 0x1379, 0x007c, 0x2071, 0x6dad, 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, 0x6dad, 0x6848, 0xa005, 0x00c0, 0x389e, 0x7028,
+	0xc085, 0x702a, 0xa085, 0x0001, 0x0078, 0x38c3, 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, 0x6dad,
+	0x7004, 0x1079, 0x3923, 0x700c, 0x0079, 0x38ce, 0x38d3, 0x38c8,
+	0x38c8, 0x38c8, 0x38c8, 0x007c, 0x700c, 0x0079, 0x38d7, 0x38dc,
+	0x3921, 0x3921, 0x3922, 0x3922, 0x7830, 0x7930, 0xa106, 0x0040,
+	0x38e6, 0x7830, 0x7930, 0xa106, 0x00c0, 0x390c, 0x7030, 0xa10a,
+	0x0040, 0x390c, 0x00c8, 0x38ee, 0x712c, 0xa10a, 0xa18a, 0x0002,
+	0x00c8, 0x390d, 0x1078, 0x12f4, 0x0040, 0x390c, 0x2d00, 0x705a,
+	0x7063, 0x0040, 0x2001, 0x0003, 0x7057, 0x0000, 0x127e, 0x007e,
+	0x2091, 0x8000, 0x2009, 0x6f31, 0x2104, 0xc085, 0x200a, 0x007f,
+	0x700e, 0x127f, 0x1078, 0x1379, 0x007c, 0x1078, 0x12f4, 0x0040,
+	0x390c, 0x2d00, 0x705a, 0x1078, 0x12f4, 0x00c0, 0x3919, 0x0078,
+	0x38f8, 0x2d00, 0x7086, 0x7063, 0x0080, 0x2001, 0x0004, 0x0078,
+	0x38fc, 0x007c, 0x007c, 0x3934, 0x3935, 0x396c, 0x396d, 0x3921,
+	0x39a3, 0x39a8, 0x39df, 0x39e0, 0x39fb, 0x39fc, 0x39fd, 0x39fe,
+	0x39ff, 0x3a00, 0x3a69, 0x3a93, 0x007c, 0x700c, 0x0079, 0x3938,
+	0x393d, 0x3940, 0x3950, 0x396b, 0x396b, 0x1078, 0x38d4, 0x007c,
+	0x127e, 0x8001, 0x700e, 0x7058, 0x007e, 0x1078, 0x3d52, 0x0040,
+	0x394d, 0x2091, 0x8000, 0x1078, 0x38d4, 0x0d7f, 0x0078, 0x3959,
+	0x127e, 0x8001, 0x700e, 0x1078, 0x3d52, 0x7058, 0x2068, 0x7084,
+	0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff,
+	0xa08a, 0x0020, 0x00c8, 0x3968, 0x1079, 0x3983, 0x127f, 0x007c,
+	0x127f, 0x1078, 0x3a01, 0x007c, 0x007c, 0x007c, 0x0e7e, 0x2071,
+	0x6dad, 0x700c, 0x0079, 0x3974, 0x3979, 0x3979, 0x3979, 0x397b,
+	0x397f, 0x0e7f, 0x007c, 0x700f, 0x0001, 0x0078, 0x3981, 0x700f,
+	0x0002, 0x0e7f, 0x007c, 0x3a01, 0x3a01, 0x3a1d, 0x3a01, 0x3aff,
+	0x3a01, 0x3a01, 0x3a01, 0x3a01, 0x3a01, 0x3a1d, 0x3b44, 0x3b8d,
+	0x3be5, 0x3bf8, 0x3a01, 0x3a01, 0x3a39, 0x3a1d, 0x3a01, 0x3a01,
+	0x3a4f, 0x3c74, 0x3c91, 0x3a01, 0x3a39, 0x3a01, 0x3a01, 0x3a01,
+	0x3a01, 0x3a01, 0x3c91, 0x7020, 0x2068, 0x1078, 0x1328, 0x007c,
+	0x700c, 0x0079, 0x39ab, 0x39b0, 0x39b3, 0x39c3, 0x39de, 0x39de,
+	0x1078, 0x38d4, 0x007c, 0x127e, 0x8001, 0x700e, 0x7058, 0x007e,
+	0x1078, 0x3d52, 0x0040, 0x39c0, 0x2091, 0x8000, 0x1078, 0x38d4,
+	0x0d7f, 0x0078, 0x39cc, 0x127e, 0x8001, 0x700e, 0x1078, 0x3d52,
+	0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000,
+	0x6834, 0xa084, 0x00ff, 0xa08a, 0x001a, 0x00c8, 0x39db, 0x1079,
+	0x39e1, 0x127f, 0x007c, 0x127f, 0x1078, 0x3a01, 0x007c, 0x007c,
+	0x007c, 0x3a01, 0x3a1d, 0x3ae9, 0x3a01, 0x3a1d, 0x3a01, 0x3a1d,
+	0x3a1d, 0x3a01, 0x3a1d, 0x3ae9, 0x3a1d, 0x3a1d, 0x3a1d, 0x3a1d,
+	0x3a1d, 0x3a01, 0x3a1d, 0x3ae9, 0x3a01, 0x3a01, 0x3a1d, 0x3a01,
+	0x3a01, 0x3a01, 0x3a1d, 0x007c, 0x007c, 0x007c, 0x007c, 0x007c,
+	0x007c, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0d5, 0x683a,
+	0x127e, 0x2091, 0x8000, 0x1078, 0x36a1, 0x127f, 0x007c, 0x7007,
+	0x0001, 0x6838, 0xa084, 0x00ff, 0xc0e5, 0x683a, 0x127e, 0x2091,
+	0x8000, 0x1078, 0x36a1, 0x127f, 0x007c, 0x7007, 0x0001, 0x6838,
+	0xa084, 0x00ff, 0xc0ed, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078,
+	0x36a1, 0x127f, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff,
+	0xc0dd, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x36a1, 0x127f,
+	0x007c, 0x6834, 0x8007, 0xa084, 0x00ff, 0x0040, 0x3a0f, 0x8001,
+	0x00c0, 0x3a46, 0x7007, 0x0001, 0x0078, 0x3ac8, 0x7007, 0x0006,
+	0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x3ac8, 0x007c, 0x2d00,
+	0x7016, 0x701a, 0x20a9, 0x0004, 0xa080, 0x0024, 0x2098, 0x20a1,
+	0x6dd8, 0x53a3, 0x6858, 0x7012, 0xa082, 0x0401, 0x00c8, 0x3a2b,
+	0x6884, 0xa08a, 0x0003, 0x00c8, 0x3a2b, 0xa080, 0x3ab9, 0x2004,
+	0x70c6, 0x7010, 0xa015, 0x0040, 0x3ab3, 0x1078, 0x12f4, 0x00c0,
+	0x3a74, 0x7007, 0x000f, 0x007c, 0x2d00, 0x7022, 0x70c4, 0x2060,
+	0x6000, 0x6836, 0x6004, 0xad00, 0x7096, 0x6008, 0xa20a, 0x00c8,
+	0x3a83, 0xa00e, 0x2200, 0x7112, 0x620c, 0x8003, 0x800b, 0xa296,
+	0x0004, 0x0040, 0x3a8c, 0xa108, 0x719a, 0x810b, 0x719e, 0xae90,
+	0x0022, 0x1078, 0x135f, 0x7090, 0xa08e, 0x0100, 0x0040, 0x3aa7,
+	0xa086, 0x0200, 0x0040, 0x3a9f, 0x7007, 0x0010, 0x007c, 0x7020,
+	0x2068, 0x1078, 0x1328, 0x7014, 0x2068, 0x0078, 0x3a2b, 0x7020,
+	0x2068, 0x7018, 0x6802, 0x6807, 0x0000, 0x2d08, 0x2068, 0x6906,
+	0x711a, 0x0078, 0x3a69, 0x7014, 0x2068, 0x7007, 0x0001, 0x0078,
+	0x3ac8, 0x3abc, 0x3ac0, 0x3ac4, 0x0002, 0x0011, 0x0007, 0x0004,
+	0x000a, 0x000f, 0x0005, 0x0006, 0x0012, 0x000f, 0x0005, 0x0006,
+	0x2009, 0x6d2c, 0x210c, 0x81ff, 0x00c0, 0x3ae3, 0x6838, 0xa084,
+	0x00ff, 0x683a, 0x6853, 0x0000, 0x1078, 0x3299, 0x00c0, 0x3ad9,
+	0x007c, 0x1078, 0x372d, 0x127e, 0x2091, 0x8000, 0x1078, 0x36a1,
+	0x127f, 0x0078, 0x3ad8, 0x2001, 0x0028, 0x2009, 0x0000, 0x0078,
+	0x3ad9, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906, 0x711a, 0x7010,
+	0x8001, 0x7012, 0x0040, 0x3af8, 0x7007, 0x0006, 0x0078, 0x3afe,
+	0x7014, 0x2068, 0x7007, 0x0001, 0x7048, 0x107a, 0x007c, 0x7007,
+	0x0001, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x6848, 0xa084, 0x00ff,
+	0x20a9, 0x0001, 0xa096, 0x0001, 0x0040, 0x3b2a, 0x2009, 0x0000,
+	0x20a9, 0x007e, 0xa096, 0x0002, 0x0040, 0x3b2a, 0xa005, 0x00c0,
+	0x3b41, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x1078, 0x3447, 0x00c0,
+	0x3b41, 0x067e, 0x6e44, 0xa6b4, 0x000f, 0x1078, 0x34e3, 0x067f,
+	0x0078, 0x3b41, 0x047e, 0x2011, 0x6d0c, 0x2224, 0xc484, 0xc48c,
+	0x2412, 0x047f, 0x0c7e, 0x1078, 0x3447, 0x00c0, 0x3b3d, 0x2091,
+	0x8000, 0x607b, 0x0000, 0x2091, 0x8001, 0x8108, 0x00f0, 0x3b33,
+	0x0c7f, 0x1078, 0x1328, 0x007c, 0x127e, 0x2091, 0x8000, 0x7007,
+	0x0001, 0x2001, 0x6d52, 0x2004, 0xd0a4, 0x0040, 0x3b84, 0x6944,
+	0x1078, 0x3d6e, 0x6100, 0xd184, 0x0040, 0x3b69, 0x6858, 0xa084,
+	0x00ff, 0x00c0, 0x3b87, 0x6000, 0xd084, 0x0040, 0x3b84, 0x6004,
+	0xa005, 0x00c0, 0x3b8a, 0x6003, 0x0000, 0x600b, 0x0000, 0x0078,
+	0x3b81, 0x2011, 0x0001, 0x6860, 0xa005, 0x00c0, 0x3b71, 0x2001,
+	0x001e, 0x8000, 0x6016, 0x6858, 0xa084, 0x00ff, 0x0040, 0x3b84,
+	0x6006, 0x6858, 0x8007, 0xa084, 0x00ff, 0x0040, 0x3b84, 0x600a,
+	0x6202, 0x127f, 0x0078, 0x3d41, 0x127f, 0x0078, 0x3d39, 0x127f,
+	0x0078, 0x3d31, 0x127f, 0x0078, 0x3d35, 0x127e, 0x2091, 0x8000,
+	0x7007, 0x0001, 0x2001, 0x6d52, 0x2004, 0xd0a4, 0x0040, 0x3be2,
+	0x6944, 0x1078, 0x3d6e, 0x6000, 0xa084, 0x0001, 0x0040, 0x3be2,
+	0x6204, 0x6308, 0x6c48, 0xa484, 0x0003, 0x0040, 0x3bba, 0x6958,
+	0xa18c, 0x00ff, 0x8001, 0x00c0, 0x3bb3, 0x2100, 0xa210, 0x0048,
+	0x3bdf, 0x0078, 0x3bba, 0x8001, 0x00c0, 0x3bdf, 0x2100, 0xa212,
+	0x0048, 0x3bdf, 0xa484, 0x000c, 0x0040, 0x3bd4, 0x6958, 0x810f,
+	0xa18c, 0x00ff, 0xa082, 0x0004, 0x00c0, 0x3bcc, 0x2100, 0xa318,
+	0x0048, 0x3bdf, 0x0078, 0x3bd4, 0xa082, 0x0004, 0x00c0, 0x3bdf,
+	0x2100, 0xa31a, 0x0048, 0x3bdf, 0x6860, 0xa005, 0x0040, 0x3bda,
+	0x8000, 0x6016, 0x6206, 0x630a, 0x127f, 0x0078, 0x3d41, 0x127f,
+	0x0078, 0x3d3d, 0x127f, 0x0078, 0x3d39, 0x127e, 0x2091, 0x8000,
+	0x7007, 0x0001, 0x6944, 0x1078, 0x3d6e, 0x6308, 0x8318, 0x0048,
+	0x3bf5, 0x630a, 0x127f, 0x0078, 0x3d4f, 0x127f, 0x0078, 0x3d3d,
+	0x127e, 0x0c7e, 0x2091, 0x8000, 0x7007, 0x0001, 0x684c, 0xd0ac,
+	0x0040, 0x3c0c, 0x027e, 0x2009, 0x0000, 0x2011, 0xfcff, 0x1078,
+	0x41f4, 0x027f, 0x0078, 0x3c42, 0x6858, 0xa005, 0x0040, 0x3c56,
+	0x685c, 0xa065, 0x0040, 0x3c52, 0x2001, 0x6d2c, 0x2004, 0xa005,
+	0x0040, 0x3c1e, 0x1078, 0x6283, 0x0078, 0x3c24, 0x6013, 0x0400,
+	0x2009, 0x0041, 0x1078, 0x5591, 0x6958, 0xa18c, 0xe600, 0xa186,
+	0x2000, 0x0040, 0x3c3a, 0xa186, 0x0400, 0x0040, 0x3c3a, 0x6944,
+	0x0c7e, 0x1078, 0x416d, 0x6000, 0xa084, 0xfdff, 0x6002, 0x0c7f,
+	0x0078, 0x3c42, 0x027e, 0x2009, 0x0000, 0x2011, 0xfdff, 0x1078,
+	0x41f4, 0x027f, 0x684c, 0xd0c4, 0x0040, 0x3c4e, 0x6944, 0x1078,
+	0x416d, 0x6008, 0x8000, 0x0048, 0x3c4e, 0x600a, 0x0c7f, 0x127f,
+	0x0078, 0x3d41, 0x0c7f, 0x127f, 0x0078, 0x3d39, 0x6954, 0xa186,
+	0x0020, 0x0040, 0x3c6c, 0xa186, 0x0029, 0x00c0, 0x3c52, 0x6944,
+	0xa18c, 0xff00, 0x810f, 0x1078, 0x3447, 0x00c0, 0x3c42, 0x6000,
+	0xc0e4, 0x6002, 0x0078, 0x3c42, 0x685c, 0xa065, 0x0040, 0x3c52,
+	0x6017, 0x0014, 0x0078, 0x3c42, 0x6944, 0x1078, 0x3d6e, 0x6000,
+	0xa084, 0x0001, 0x0040, 0x3c8d, 0x2091, 0x8000, 0x6204, 0x8210,
+	0x0048, 0x3c87, 0x6206, 0x2091, 0x8001, 0x0078, 0x3d4f, 0x2091,
+	0x8001, 0x6853, 0x0016, 0x0078, 0x3d48, 0x6853, 0x0007, 0x0078,
+	0x3d48, 0x6834, 0x8007, 0xa084, 0x00ff, 0x00c0, 0x3c9b, 0x1078,
+	0x3a0f, 0x0078, 0x3cad, 0x2030, 0x8001, 0x00c0, 0x3ca5, 0x7007,
+	0x0001, 0x1078, 0x3cae, 0x0078, 0x3cad, 0x7007, 0x0006, 0x7012,
+	0x2d00, 0x7016, 0x701a, 0x704b, 0x3cae, 0x007c, 0x0e7e, 0x2009,
+	0x6d2c, 0x210c, 0x81ff, 0x00c0, 0x3d28, 0x6848, 0x2070, 0xae82,
+	0x7400, 0x0048, 0x3d18, 0x2001, 0x6d15, 0x2004, 0xae02, 0x00c8,
+	0x3d18, 0x6944, 0x1078, 0x3d6e, 0x6100, 0xa184, 0x0001, 0x0040,
+	0x3cfe, 0xa184, 0x0100, 0x00c0, 0x3d1c, 0xa184, 0x0200, 0x00c0,
+	0x3d20, 0x601c, 0xa005, 0x00c0, 0x3d24, 0x711c, 0xa186, 0x0006,
+	0x00c0, 0x3d03, 0x6853, 0x0000, 0x6803, 0x0000, 0x2d08, 0x127e,
+	0x2091, 0x8000, 0x7010, 0xa005, 0x00c0, 0x3cf5, 0x7112, 0x7018,
+	0xa065, 0x0040, 0x3d28, 0x6000, 0xd0e4, 0x00c0, 0x3d2c, 0x2e60,
+	0x1078, 0x4176, 0x127f, 0x0e7f, 0x007c, 0x2068, 0x6800, 0xa005,
+	0x00c0, 0x3cf5, 0x6902, 0x127f, 0x0e7f, 0x007c, 0x0e7f, 0x6853,
+	0x0006, 0x0078, 0x3d48, 0x6944, 0xa18c, 0xff00, 0x810f, 0x1078,
+	0x3447, 0x00c0, 0x3d2c, 0x6000, 0xd0e4, 0x00c0, 0x3d2c, 0x711c,
+	0xa186, 0x0007, 0x00c0, 0x3d18, 0x6853, 0x0002, 0x0078, 0x3d2e,
+	0x6853, 0x0008, 0x0078, 0x3d2e, 0x6853, 0x000e, 0x0078, 0x3d2e,
+	0x6853, 0x0017, 0x0078, 0x3d2e, 0x6853, 0x0035, 0x0078, 0x3d2e,
+	0x6853, 0x0028, 0x0078, 0x3d2e, 0x6853, 0x0029, 0x0e7f, 0x0078,
+	0x3d48, 0x2009, 0x003e, 0x0078, 0x3d43, 0x2009, 0x0004, 0x0078,
+	0x3d43, 0x2009, 0x0006, 0x0078, 0x3d43, 0x2009, 0x0016, 0x0078,
+	0x3d43, 0x2009, 0x0001, 0x6854, 0xa084, 0xff00, 0xa105, 0x6856,
+	0x2091, 0x8000, 0x1078, 0x36a1, 0x2091, 0x8001, 0x007c, 0x1078,
+	0x1328, 0x007c, 0x702c, 0x7130, 0x8108, 0xa102, 0x0048, 0x3d5f,
+	0xa00e, 0x7034, 0x7072, 0x7038, 0x7076, 0x0078, 0x3d6b, 0x7070,
+	0xa080, 0x0040, 0x7072, 0x00c8, 0x3d6b, 0x7074, 0xa081, 0x0000,
+	0x7076, 0xa085, 0x0001, 0x7932, 0x7132, 0x007c, 0x0d7e, 0x1078,
+	0x416d, 0x0d7f, 0x007c, 0x0d7e, 0x2011, 0x0004, 0x2204, 0xa085,
+	0x8002, 0x2012, 0x0d7f, 0x007c, 0x20e1, 0x0002, 0x3d08, 0x20e1,
+	0x2000, 0x3d00, 0xa084, 0x7000, 0x0040, 0x3d8a, 0xa086, 0x1000,
+	0x00c0, 0x3dab, 0x20e1, 0x0004, 0x3d60, 0xd1bc, 0x00c0, 0x3d91,
+	0x3e60, 0xac84, 0x0007, 0x00c0, 0x3dab, 0xac82, 0x7400, 0x0048,
+	0x3dab, 0x6854, 0xac02, 0x00c8, 0x3dab, 0x2009, 0x0047, 0x1078,
+	0x5591, 0x20e1, 0x0007, 0x20e1, 0x2000, 0x7a28, 0x7a1c, 0xd284,
+	0x00c0, 0x3d7c, 0x007c, 0xa016, 0x1078, 0x1532, 0x0078, 0x3da1,
+	0x157e, 0x137e, 0x147e, 0x20e1, 0x3000, 0x3d20, 0x3e28, 0xa584,
+	0x0070, 0x00c0, 0x3dd9, 0xa484, 0x7000, 0xa086, 0x1000, 0x00c0,
+	0x3dd9, 0x1078, 0x3de6, 0x0040, 0x3dd9, 0x20e1, 0x3000, 0x7828,
+	0x7828, 0x1078, 0x3e04, 0x147f, 0x137f, 0x157f, 0x2009, 0x6f18,
+	0x2104, 0xa005, 0x00c0, 0x3dd5, 0x007c, 0x1078, 0x476a, 0x0078,
+	0x3dd4, 0x1078, 0x6c23, 0x1078, 0x3de6, 0x20e1, 0x3000, 0x7828,
+	0x7828, 0x147f, 0x137f, 0x157f, 0x0078, 0x3dd4, 0xa484, 0x01ff,
+	0x687a, 0xa005, 0x0040, 0x3df8, 0xa080, 0x001f, 0xa084, 0x03f8,
+	0x80ac, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x007c,
+	0x20a9, 0x000c, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5,
+	0xa085, 0x0001, 0x0078, 0x3df7, 0x7000, 0xa084, 0xff00, 0xa08c,
+	0xf000, 0x8007, 0xa196, 0x0000, 0x00c0, 0x3e11, 0x0078, 0x3f51,
+	0x007c, 0xa196, 0x2000, 0x00c0, 0x3e22, 0x6900, 0xa18e, 0x0001,
+	0x00c0, 0x3e1e, 0x1078, 0x2aec, 0x0078, 0x3e10, 0x1078, 0x3e2a,
+	0x0078, 0x3e10, 0xa196, 0x8000, 0x00c0, 0x3e10, 0x1078, 0x3fd7,
+	0x0078, 0x3e10, 0x0c7e, 0x7110, 0xa18c, 0xff00, 0x810f, 0xa196,
+	0x0001, 0x0040, 0x3e37, 0xa196, 0x0023, 0x00c0, 0x3ef8, 0xa08e,
+	0x0023, 0x00c0, 0x3e68, 0x1078, 0x404e, 0x0040, 0x3ef8, 0x7124,
+	0x610a, 0x7030, 0xa08e, 0x0200, 0x00c0, 0x3e50, 0x7034, 0xa005,
+	0x00c0, 0x3ef8, 0x2009, 0x0015, 0x1078, 0x5591, 0x0078, 0x3ef8,
+	0xa08e, 0x0210, 0x00c0, 0x3e5a, 0x2009, 0x0015, 0x1078, 0x5591,
+	0x0078, 0x3ef8, 0xa08e, 0x0100, 0x00c0, 0x3ef8, 0x7034, 0xa005,
+	0x00c0, 0x3ef8, 0x2009, 0x0016, 0x1078, 0x5591, 0x0078, 0x3ef8,
+	0xa08e, 0x0022, 0x00c0, 0x3ef8, 0x7030, 0xa08e, 0x0300, 0x00c0,
+	0x3e79, 0x7034, 0xa005, 0x00c0, 0x3ef8, 0x2009, 0x0017, 0x0078,
+	0x3eda, 0xa08e, 0x0500, 0x00c0, 0x3e85, 0x7034, 0xa005, 0x00c0,
+	0x3ef8, 0x2009, 0x0018, 0x0078, 0x3eda, 0xa08e, 0x2010, 0x00c0,
+	0x3e8d, 0x2009, 0x0019, 0x0078, 0x3eda, 0xa08e, 0x2110, 0x00c0,
+	0x3e95, 0x2009, 0x001a, 0x0078, 0x3eda, 0xa08e, 0x5200, 0x00c0,
+	0x3ea1, 0x7034, 0xa005, 0x00c0, 0x3ef8, 0x2009, 0x001b, 0x0078,
+	0x3eda, 0xa08e, 0x5000, 0x00c0, 0x3ead, 0x7034, 0xa005, 0x00c0,
+	0x3ef8, 0x2009, 0x001c, 0x0078, 0x3eda, 0xa08e, 0x2400, 0x00c0,
+	0x3eb3, 0x0078, 0x3ed8, 0xa08e, 0x5300, 0x00c0, 0x3eb9, 0x0078,
+	0x3ed8, 0xa08e, 0x0f00, 0x00c0, 0x3ec1, 0x2009, 0x0020, 0x0078,
+	0x3eda, 0xa08e, 0x5300, 0x00c0, 0x3ec7, 0x0078, 0x3ed8, 0xa08e,
+	0x6104, 0x00c0, 0x3ed8, 0x2009, 0x728e, 0x2011, 0x8015, 0x211c,
+	0x8108, 0x2124, 0x1078, 0x2a53, 0x2009, 0x0023, 0x0078, 0x3eda,
+	0x2009, 0x001d, 0x017e, 0x2011, 0x7283, 0x2204, 0x8211, 0x220c,
+	0x1078, 0x1e1b, 0x00c0, 0x3efa, 0x1078, 0x3410, 0x00c0, 0x3efa,
+	0x6612, 0x6516, 0x0c7e, 0x1078, 0x5504, 0x0040, 0x3efd, 0x017f,
+	0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0x017f, 0x1078, 0x5591,
+	0x0c7f, 0x007c, 0x017f, 0x0078, 0x3ef8, 0x0c7f, 0x0078, 0x3efa,
+	0x0e7e, 0x0d7e, 0x2028, 0x2130, 0xa696, 0x00ff, 0x00c0, 0x3f20,
+	0xa596, 0xfffd, 0x00c0, 0x3f10, 0x2009, 0x007f, 0x0078, 0x3f4d,
+	0xa596, 0xfffe, 0x00c0, 0x3f18, 0x2009, 0x007e, 0x0078, 0x3f4d,
+	0xa596, 0xfffc, 0x00c0, 0x3f20, 0x2009, 0x0080, 0x0078, 0x3f4d,
+	0x2011, 0x0000, 0x2021, 0x007e, 0x20a9, 0x0082, 0x2071, 0x6e7e,
+	0x2e1c, 0x83ff, 0x00c0, 0x3f32, 0x82ff, 0x00c0, 0x3f41, 0x2410,
+	0x0078, 0x3f41, 0x2368, 0x6b10, 0x007e, 0x2100, 0xa31e, 0x007f,
+	0x00c0, 0x3f41, 0x6b14, 0xa31e, 0x00c0, 0x3f41, 0x2408, 0x0078,
+	0x3f4d, 0x8420, 0x8e70, 0x00f0, 0x3f28, 0x82ff, 0x00c0, 0x3f4c,
+	0xa085, 0x0001, 0x0078, 0x3f4e, 0x2208, 0xa006, 0x0d7f, 0x0e7f,
+	0x007c, 0xa084, 0x0007, 0x0079, 0x3f56, 0x007c, 0x3f5e, 0x3f5e,
+	0x3f5e, 0x3f5e, 0x3f5e, 0x3f5f, 0x3f78, 0x3fc0, 0x007c, 0x7110,
+	0xd1bc, 0x0040, 0x3f77, 0x7120, 0x2160, 0xac8c, 0x0007, 0x00c0,
+	0x3f77, 0xac8a, 0x7400, 0x0048, 0x3f77, 0x6854, 0xac02, 0x00c8,
+	0x3f77, 0x7124, 0x610a, 0x2009, 0x0046, 0x1078, 0x5591, 0x007c,
+	0x0c7e, 0x7110, 0xd1bc, 0x00c0, 0x3fbe, 0x2011, 0x7283, 0x2204,
+	0x8211, 0x220c, 0x1078, 0x1e1b, 0x00c0, 0x3fbe, 0x1078, 0x3447,
+	0x00c0, 0x3fbe, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006,
+	0x00c0, 0x3fa3, 0x0c7e, 0x1078, 0x5504, 0x017f, 0x0040, 0x3fbe,
+	0x611a, 0x601f, 0x0006, 0x7120, 0x610a, 0x2009, 0x0044, 0x1078,
+	0x5591, 0x0078, 0x3fbe, 0x0c7e, 0x1078, 0x5504, 0x017f, 0x0040,
+	0x3fbe, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0xa286, 0x0004,
+	0x00c0, 0x3fb6, 0x6007, 0x0005, 0x0078, 0x3fb8, 0x6007, 0x0001,
+	0x6003, 0x0001, 0x1078, 0x4376, 0x1078, 0x476a, 0x0c7f, 0x007c,
+	0x7110, 0xd1bc, 0x0040, 0x3fd6, 0x7020, 0x2060, 0xac84, 0x0007,
+	0x00c0, 0x3fd6, 0xac82, 0x7400, 0x0048, 0x3fd6, 0x6854, 0xac02,
+	0x00c8, 0x3fd6, 0x2009, 0x0045, 0x1078, 0x5591, 0x007c, 0x7110,
+	0xa18c, 0xff00, 0x810f, 0xa18e, 0x0000, 0x00c0, 0x3fe7, 0xa084,
+	0x000f, 0xa08a, 0x0006, 0x10c8, 0x12b7, 0x1079, 0x3fe8, 0x007c,
+	0x3fee, 0x3fef, 0x3fee, 0x3fee, 0x4030, 0x403f, 0x007c, 0x7110,
+	0xd1bc, 0x00c0, 0x402f, 0x700c, 0x7108, 0x1078, 0x1e1b, 0x00c0,
+	0x402f, 0x1078, 0x3410, 0x00c0, 0x402f, 0x6612, 0x6516, 0x6204,
+	0xa294, 0xff00, 0x8217, 0xa286, 0x0006, 0x00c0, 0x4018, 0x0c7e,
+	0x1078, 0x5504, 0x017f, 0x0040, 0x402f, 0x611a, 0x601f, 0x0005,
+	0x7120, 0x610a, 0x2009, 0x0028, 0x1078, 0x5591, 0x0078, 0x402f,
+	0x0c7e, 0x1078, 0x5504, 0x017f, 0x0040, 0x402f, 0x611a, 0x601f,
+	0x0004, 0x7120, 0x610a, 0xa286, 0x0004, 0x00c0, 0x402b, 0x2009,
+	0x0005, 0x0078, 0x402d, 0x2009, 0x0001, 0x1078, 0x5591, 0x007c,
+	0x7110, 0xd1bc, 0x0040, 0x403e, 0x1078, 0x404e, 0x0040, 0x403e,
+	0x7124, 0x610a, 0x2009, 0x0029, 0x1078, 0x5591, 0x007c, 0x7110,
+	0xd1bc, 0x0040, 0x404d, 0x1078, 0x404e, 0x0040, 0x404d, 0x7124,
+	0x610a, 0x2009, 0x002a, 0x1078, 0x5591, 0x007c, 0x7020, 0x2060,
+	0xac84, 0x0007, 0x00c0, 0x4061, 0xac82, 0x7400, 0x0048, 0x4061,
+	0x2001, 0x6d15, 0x2004, 0xac02, 0x00c8, 0x4061, 0xa085, 0x0001,
+	0x007c, 0xa006, 0x0078, 0x4060, 0x2071, 0x6f23, 0x7003, 0x0003,
+	0x700f, 0x0361, 0xa006, 0x701a, 0x7012, 0x7017, 0x7400, 0x7007,
+	0x0000, 0x7026, 0x702b, 0x4ff2, 0x7032, 0x7037, 0x503e, 0x007c,
+	0x2071, 0x6f23, 0x00e0, 0x40be, 0x2091, 0x6000, 0x700c, 0x8001,
+	0x700e, 0x00c0, 0x4087, 0x700f, 0x0361, 0x7007, 0x0001, 0x127e,
+	0x2091, 0x8000, 0x7024, 0xa00d, 0x0040, 0x409b, 0x7020, 0x8001,
+	0x7022, 0x00c0, 0x409b, 0x7023, 0x0009, 0x8109, 0x7126, 0x00c0,
+	0x409b, 0x7028, 0x107a, 0x7030, 0xa00d, 0x0040, 0x40ac, 0x702c,
+	0x8001, 0x702e, 0x00c0, 0x40ac, 0x702f, 0x0009, 0x8109, 0x7132,
+	0x00c0, 0x40ac, 0x7034, 0x107a, 0x7018, 0xa00d, 0x0040, 0x40bd,
+	0x7008, 0x8001, 0x700a, 0x00c0, 0x40bd, 0x700b, 0x0009, 0x8109,
+	0x711a, 0x00c0, 0x40bd, 0x701c, 0x107a, 0x127f, 0x7004, 0x0079,
+	0x40c1, 0x40e8, 0x40e9, 0x4105, 0x0e7e, 0x2071, 0x6f23, 0x7018,
+	0xa005, 0x00c0, 0x40cf, 0x711a, 0x721e, 0x700b, 0x0009, 0x0e7f,
+	0x007c, 0x0e7e, 0x007e, 0x2071, 0x6f23, 0x701c, 0xa206, 0x00c0,
+	0x40db, 0x701a, 0x701e, 0x007f, 0x0e7f, 0x007c, 0x0e7e, 0x2071,
+	0x6f23, 0x6088, 0xa102, 0x0048, 0x40e6, 0x618a, 0x0e7f, 0x007c,
+	0x007c, 0x7110, 0x1078, 0x3447, 0x00c0, 0x40fb, 0x6088, 0x8001,
+	0x0048, 0x40fb, 0x608a, 0x00c0, 0x40fb, 0x127e, 0x2091, 0x8000,
+	0x1078, 0x476a, 0x127f, 0x8108, 0xa182, 0x00ff, 0x0048, 0x4103,
+	0xa00e, 0x7007, 0x0002, 0x7112, 0x007c, 0x7014, 0x2060, 0x127e,
+	0x2091, 0x8000, 0x6014, 0xa005, 0x0040, 0x4134, 0x8001, 0x6016,
+	0x00c0, 0x4134, 0x611c, 0xa186, 0x0003, 0x0040, 0x411b, 0xa186,
+	0x0006, 0x00c0, 0x4132, 0x6010, 0x2068, 0x6854, 0xa08a, 0x199a,
+	0x0048, 0x4132, 0xa082, 0x1999, 0x6856, 0xa08a, 0x199a, 0x0048,
+	0x412b, 0x2001, 0x1999, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116,
+	0x0078, 0x4134, 0x1078, 0x5fea, 0x127f, 0xac88, 0x0008, 0x7116,
+	0x2001, 0x6d16, 0x2004, 0xa102, 0x0048, 0x4142, 0x7017, 0x7400,
+	0x7007, 0x0000, 0x007c, 0x0e7e, 0x2071, 0x6f23, 0x7027, 0x07d0,
+	0x7023, 0x0009, 0x0e7f, 0x007c, 0x2001, 0x6f2c, 0x2003, 0x0000,
+	0x007c, 0x0e7e, 0x2071, 0x6f23, 0x7033, 0x07d0, 0x702f, 0x0009,
+	0x0e7f, 0x007c, 0x2011, 0x6f2f, 0x2013, 0x0000, 0x007c, 0x0e7e,
+	0x2071, 0x6f23, 0x711a, 0x721e, 0x700b, 0x0009, 0x0e7f, 0x007c,
+	0x0c7e, 0x2061, 0x6fb2, 0x0c7f, 0x007c, 0xa184, 0x000f, 0x8003,
+	0x8003, 0x8003, 0xa080, 0x6fb2, 0x2060, 0x007c, 0x684c, 0xa08c,
+	0x00c0, 0xa18e, 0x00c0, 0x0040, 0x41ac, 0xd0b4, 0x00c0, 0x4188,
+	0xd0bc, 0x00c0, 0x419a, 0x2009, 0x0006, 0x1078, 0x41cf, 0x007c,
+	0xd0fc, 0x0040, 0x4195, 0xa084, 0x0003, 0xa08e, 0x0003, 0x0040,
+	0x41c8, 0xa08e, 0x0000, 0x00c0, 0x41c8, 0x2009, 0x0043, 0x1078,
+	0x5591, 0x007c, 0xd0fc, 0x0040, 0x41a7, 0xa084, 0x0003, 0xa08e,
+	0x0003, 0x0040, 0x41c8, 0xa08e, 0x0000, 0x00c0, 0x41c8, 0x2009,
+	0x0042, 0x1078, 0x5591, 0x007c, 0xd0fc, 0x0040, 0x41be, 0xa084,
+	0x0003, 0xa08e, 0x0003, 0x0040, 0x41c8, 0xa08e, 0x0002, 0x0040,
+	0x41c2, 0x2009, 0x0041, 0x1078, 0x5591, 0x007c, 0x1078, 0x41cd,
+	0x0078, 0x41bd, 0x2009, 0x0043, 0x1078, 0x5591, 0x0078, 0x41bd,
+	0x2009, 0x0004, 0x1078, 0x41cf, 0x007c, 0x2009, 0x0001, 0x6010,
+	0xa0ec, 0xf000, 0x0040, 0x41f3, 0x2068, 0x6952, 0x6800, 0x6012,
+	0xa186, 0x0001, 0x00c0, 0x41ed, 0x694c, 0xa18c, 0x8100, 0xa18e,
+	0x8100, 0x00c0, 0x41ed, 0x0c7e, 0x6944, 0x1078, 0x416d, 0x6204,
+	0x8210, 0x0048, 0x41ec, 0x6206, 0x0c7f, 0x1078, 0x36a1, 0x6010,
+	0xa06d, 0x10c0, 0x4176, 0x007c, 0x157e, 0x0c7e, 0x20a9, 0x0010,
+	0x2061, 0x6fb2, 0x6000, 0x81ff, 0x0040, 0x4201, 0xa205, 0x0078,
+	0x4202, 0xa204, 0x6002, 0xace0, 0x0008, 0x00f0, 0x41fa, 0x0c7f,
+	0x157f, 0x007c, 0x6808, 0xa005, 0x0040, 0x4212, 0x8001, 0x680a,
+	0xa085, 0x0001, 0x007c, 0x127e, 0x2091, 0x2200, 0x2079, 0x6f10,
+	0x127f, 0x0d7e, 0x2069, 0x6f10, 0x6803, 0x0005, 0x2069, 0x0004,
+	0x2d04, 0xa085, 0x8001, 0x206a, 0x0d7f, 0x007c, 0x0c7e, 0x6027,
+	0x0001, 0x7804, 0xa084, 0x0007, 0x0079, 0x422e, 0x4238, 0x425d,
+	0x428e, 0x423e, 0x425d, 0x4236, 0x4236, 0x4236, 0x1078, 0x12b7,
+	0x1078, 0x414c, 0x1078, 0x476a, 0x0c7f, 0x007c, 0x62c0, 0x82ff,
+	0x00c0, 0x4244, 0x0c7f, 0x007c, 0x2011, 0x318e, 0x1078, 0x40d1,
+	0x7828, 0xa092, 0x0002, 0x00c8, 0x4253, 0x8000, 0x782a, 0x1078,
+	0x31c2, 0x0078, 0x4242, 0x1078, 0x318e, 0x7807, 0x0003, 0x7827,
+	0x0000, 0x782b, 0x0000, 0x0078, 0x4242, 0x1078, 0x414c, 0x62c0,
+	0x82ff, 0x00c0, 0x426f, 0x782b, 0x0000, 0x7824, 0xa065, 0x1040,
+	0x12b7, 0x2009, 0x0013, 0x1078, 0x5591, 0x0c7f, 0x007c, 0x0c7e,
+	0x7824, 0xa065, 0x1040, 0x12b7, 0x7804, 0xa086, 0x0004, 0x0040,
+	0x42cc, 0x7828, 0xa092, 0x2710, 0x00c8, 0x4285, 0x8000, 0x782a,
+	0x0c7f, 0x1078, 0x4fd7, 0x0078, 0x426d, 0x1078, 0x6c76, 0x2009,
+	0x0014, 0x1078, 0x5591, 0x0c7f, 0x0078, 0x426d, 0x2001, 0x6f2c,
+	0x2003, 0x0000, 0x62c0, 0x82ff, 0x00c0, 0x42a2, 0x782b, 0x0000,
+	0x7824, 0xa065, 0x1040, 0x12b7, 0x2009, 0x0013, 0x1078, 0x55df,
+	0x0c7f, 0x007c, 0x0c7e, 0x0d7e, 0x7824, 0xa005, 0x1040, 0x12b7,
+	0x781c, 0xa06d, 0x1040, 0x12b7, 0x6800, 0xc0dc, 0x6802, 0x7924,
+	0x2160, 0x1078, 0x556a, 0x693c, 0x81ff, 0x1040, 0x12b7, 0x8109,
+	0x693e, 0x6854, 0xa015, 0x0040, 0x42c0, 0x7a1e, 0x0078, 0x42c2,
+	0x7918, 0x791e, 0x7807, 0x0000, 0x7827, 0x0000, 0x0d7f, 0x0c7f,
+	0x1078, 0x476a, 0x0078, 0x42a0, 0x6104, 0xa186, 0x0002, 0x0040,
+	0x42d7, 0xa186, 0x0004, 0x0040, 0x42d7, 0x0078, 0x4279, 0x7808,
+	0xac06, 0x0040, 0x4279, 0x1078, 0x4671, 0x1078, 0x4376, 0x0c7f,
+	0x1078, 0x476a, 0x0078, 0x426d, 0x0c7e, 0x6027, 0x0002, 0x2011,
+	0x6f2f, 0x2013, 0x0000, 0x62c8, 0x82ff, 0x00c0, 0x42fe, 0x62c4,
+	0x82ff, 0x00c0, 0x42fe, 0x793c, 0xa1e5, 0x0000, 0x0040, 0x42fc,
+	0x2009, 0x0049, 0x1078, 0x5591, 0x0c7f, 0x007c, 0x6017, 0x0010,
+	0x793c, 0x81ff, 0x0040, 0x42fc, 0x7944, 0xa192, 0x2710, 0x00c8,
+	0x431d, 0x8108, 0x7946, 0x1078, 0x4151, 0x793c, 0xa188, 0x0007,
+	0x210c, 0xa18e, 0x0006, 0x00c0, 0x4319, 0x6017, 0x0012, 0x0078,
+	0x42fc, 0x6017, 0x0016, 0x0078, 0x42fc, 0x1078, 0x6c76, 0x793c,
+	0x2160, 0x2009, 0x004a, 0x1078, 0x5591, 0x0078, 0x42fc, 0x007e,
+	0x017e, 0x0c7e, 0x127e, 0x600f, 0x0000, 0x2c08, 0x2061, 0x6f10,
+	0x2091, 0x8000, 0x6020, 0x8000, 0x6022, 0x6010, 0xa005, 0x0040,
+	0x4342, 0xa080, 0x0003, 0x2102, 0x6112, 0x127f, 0x0c7f, 0x017f,
+	0x007f, 0x007c, 0x6116, 0x6112, 0x0078, 0x433d, 0x0d7e, 0x2069,
+	0x6f10, 0x6000, 0xd0d4, 0x0040, 0x435d, 0x6820, 0x8000, 0x6822,
+	0xa086, 0x0001, 0x00c0, 0x4356, 0x2c00, 0x681e, 0x6804, 0xa084,
+	0x0007, 0x0079, 0x4772, 0x0d7f, 0x007c, 0xc0d5, 0x6002, 0x6818,
+	0xa005, 0x0040, 0x436f, 0x6056, 0x605b, 0x0000, 0x007e, 0x2c00,
+	0x681a, 0x0d7f, 0x685a, 0x2069, 0x6f10, 0x0078, 0x434d, 0x6056,
+	0x605a, 0x2c00, 0x681a, 0x681e, 0x0078, 0x434d, 0x007e, 0x017e,
+	0x0c7e, 0x127e, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061,
+	0x6f10, 0x6020, 0x8000, 0x6022, 0x6008, 0xa005, 0x0040, 0x4391,
+	0xa080, 0x0003, 0x2102, 0x610a, 0x127f, 0x0c7f, 0x017f, 0x007f,
+	0x007c, 0x610e, 0x610a, 0x0078, 0x438c, 0x0c7e, 0x600f, 0x0000,
+	0x2c08, 0x2061, 0x6f10, 0x6034, 0xa005, 0x0040, 0x43a5, 0xa080,
+	0x0003, 0x2102, 0x6136, 0x0c7f, 0x007c, 0x613a, 0x6136, 0x0078,
+	0x43a3, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x027e, 0x007e,
+	0x127e, 0x2071, 0x6f10, 0x7638, 0x2660, 0x2678, 0x2091, 0x8000,
+	0x8cff, 0x0040, 0x4405, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206,
+	0x00c0, 0x4400, 0x703c, 0xac06, 0x00c0, 0x43cb, 0x6003, 0x000a,
+	0x630a, 0x0078, 0x4400, 0x7038, 0xac36, 0x00c0, 0x43d1, 0x660c,
+	0x763a, 0x7034, 0xac36, 0x00c0, 0x43df, 0x2c00, 0xaf36, 0x0040,
+	0x43dd, 0x2f00, 0x7036, 0x0078, 0x43df, 0x7037, 0x0000, 0x660c,
+	0x067e, 0x2c00, 0xaf06, 0x0040, 0x43e8, 0x7e0e, 0x0078, 0x43e9,
+	0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003,
+	0x00c0, 0x440e, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078,
+	0x36a1, 0x1078, 0x6276, 0x1078, 0x6283, 0x0c7f, 0x0078, 0x43b8,
+	0x2c78, 0x600c, 0x2060, 0x0078, 0x43b8, 0x127f, 0x007f, 0x027f,
+	0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x601c, 0xa086,
+	0x0006, 0x00c0, 0x43f2, 0x1078, 0x6bb3, 0x0078, 0x43fb, 0x007e,
+	0x067e, 0x0c7e, 0x0d7e, 0x0f7e, 0x2031, 0x0000, 0x127e, 0x2091,
+	0x8000, 0x2079, 0x6f10, 0x7838, 0xa065, 0x0040, 0x444a, 0x600c,
+	0x007e, 0x600f, 0x0000, 0x783c, 0xac06, 0x00c0, 0x4435, 0x6003,
+	0x000a, 0x630a, 0x2c30, 0x0078, 0x4447, 0x6010, 0x2068, 0x601c,
+	0xa086, 0x0003, 0x00c0, 0x4453, 0x6837, 0x0103, 0x6b4a, 0x6847,
+	0x0000, 0x1078, 0x36a1, 0x1078, 0x6276, 0x1078, 0x6283, 0x007f,
+	0x0078, 0x4424, 0x7e3a, 0x7e36, 0x127f, 0x0f7f, 0x0d7f, 0x0c7f,
+	0x067f, 0x007f, 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x443c,
+	0x1078, 0x6bb3, 0x0078, 0x4445, 0x027e, 0x1078, 0x4470, 0x1078,
+	0x4507, 0x027f, 0x007c, 0x0f7e, 0x127e, 0x2079, 0x6f10, 0x2091,
+	0x8000, 0x1078, 0x4599, 0x1078, 0x4601, 0x127f, 0x0f7f, 0x007c,
+	0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x007e, 0x127e, 0x2091,
+	0x8000, 0x2071, 0x6f10, 0x7614, 0x2660, 0x2678, 0x8cff, 0x0040,
+	0x44f6, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x44f1,
+	0x7024, 0xac06, 0x00c0, 0x44b6, 0x2069, 0x0100, 0x68c0, 0xa005,
+	0x0040, 0x44b1, 0x1078, 0x4fe5, 0x68c3, 0x0000, 0x1078, 0x54a4,
+	0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000,
+	0x0040, 0x44a6, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100,
+	0x6824, 0xd084, 0x0040, 0x44ae, 0x6827, 0x0001, 0x037f, 0x0078,
+	0x44b6, 0x6003, 0x0009, 0x630a, 0x0078, 0x44f1, 0x7014, 0xac36,
+	0x00c0, 0x44bc, 0x660c, 0x7616, 0x7010, 0xac36, 0x00c0, 0x44ca,
+	0x2c00, 0xaf36, 0x0040, 0x44c8, 0x2f00, 0x7012, 0x0078, 0x44ca,
+	0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x44d3,
+	0x7e0e, 0x0078, 0x44d4, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068,
+	0x1078, 0x6120, 0x0040, 0x44ea, 0x601c, 0xa086, 0x0003, 0x00c0,
+	0x44fe, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x36a1,
+	0x1078, 0x6276, 0x1078, 0x6283, 0x1078, 0x5374, 0x0c7f, 0x0078,
+	0x447e, 0x2c78, 0x600c, 0x2060, 0x0078, 0x447e, 0x127f, 0x007f,
+	0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x601c, 0xa086,
+	0x0006, 0x00c0, 0x44e1, 0x1078, 0x6bb3, 0x0078, 0x44ea, 0x0c7e,
+	0x007e, 0x127e, 0x2091, 0x8000, 0xa280, 0x6e00, 0x2004, 0xa065,
+	0x0040, 0x4595, 0x0f7e, 0x0e7e, 0x0d7e, 0x067e, 0x2071, 0x6f10,
+	0x6654, 0x7018, 0xac06, 0x00c0, 0x451e, 0x761a, 0x701c, 0xac06,
+	0x00c0, 0x452a, 0x86ff, 0x00c0, 0x4529, 0x7018, 0x701e, 0x0078,
+	0x452a, 0x761e, 0x6058, 0xa07d, 0x0040, 0x452f, 0x7e56, 0xa6ed,
+	0x0000, 0x0040, 0x4535, 0x2f00, 0x685a, 0x6057, 0x0000, 0x605b,
+	0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x1078, 0x33c4, 0x0040,
+	0x4591, 0x7624, 0x86ff, 0x0040, 0x4586, 0xa680, 0x0004, 0x2004,
+	0xad06, 0x00c0, 0x4586, 0x0d7e, 0x2069, 0x0100, 0x68c0, 0xa005,
+	0x0040, 0x457d, 0x1078, 0x4fe5, 0x68c3, 0x0000, 0x1078, 0x54a4,
+	0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000,
+	0x0040, 0x4566, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100,
+	0x6824, 0xd084, 0x0040, 0x456e, 0x6827, 0x0001, 0x037f, 0x0d7f,
+	0x0c7e, 0x603c, 0xa005, 0x0040, 0x4577, 0x8001, 0x603e, 0x2660,
+	0x1078, 0x6283, 0x0c7f, 0x0078, 0x4586, 0x0d7f, 0x0c7e, 0x2660,
+	0x6003, 0x0009, 0x630a, 0x0c7f, 0x0078, 0x453d, 0x6837, 0x0103,
+	0x6b4a, 0x6847, 0x0000, 0x1078, 0x36a1, 0x1078, 0x5374, 0x0078,
+	0x453d, 0x067f, 0x0d7f, 0x0e7f, 0x0f7f, 0x127f, 0x007f, 0x0c7f,
+	0x007c, 0x007e, 0x067e, 0x0c7e, 0x0d7e, 0x2031, 0x0000, 0x7814,
+	0xa065, 0x0040, 0x45f1, 0x600c, 0x007e, 0x600f, 0x0000, 0x7824,
+	0xac06, 0x00c0, 0x45d6, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040,
+	0x45d0, 0x1078, 0x4fe5, 0x68c3, 0x0000, 0x1078, 0x54a4, 0x7827,
+	0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040,
+	0x45c5, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824,
+	0xd084, 0x0040, 0x45cd, 0x6827, 0x0001, 0x037f, 0x0078, 0x45d6,
+	0x6003, 0x0009, 0x630a, 0x2c30, 0x0078, 0x45ee, 0x6010, 0x2068,
+	0x1078, 0x6120, 0x0040, 0x45ea, 0x601c, 0xa086, 0x0003, 0x00c0,
+	0x45f8, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x36a1,
+	0x1078, 0x6276, 0x1078, 0x6283, 0x1078, 0x5374, 0x007f, 0x0078,
+	0x45a0, 0x7e16, 0x7e12, 0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c,
+	0x601c, 0xa086, 0x0006, 0x00c0, 0x45e1, 0x1078, 0x6bb3, 0x0078,
+	0x45ea, 0x007e, 0x067e, 0x0c7e, 0x0d7e, 0x7818, 0xa065, 0x0040,
+	0x466a, 0x6054, 0x007e, 0x6057, 0x0000, 0x605b, 0x0000, 0x6000,
+	0xc0d4, 0xc0dc, 0x6002, 0x1078, 0x33c4, 0x0040, 0x4667, 0x7e24,
+	0x86ff, 0x0040, 0x465c, 0xa680, 0x0004, 0x2004, 0xad06, 0x00c0,
+	0x465c, 0x0d7e, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x4653,
+	0x1078, 0x4fe5, 0x68c3, 0x0000, 0x1078, 0x54a4, 0x7827, 0x0000,
+	0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x463c,
+	0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084,
+	0x0040, 0x4644, 0x6827, 0x0001, 0x037f, 0x0d7f, 0x0c7e, 0x603c,
+	0xa005, 0x0040, 0x464d, 0x8001, 0x603e, 0x2660, 0x1078, 0x6283,
+	0x0c7f, 0x0078, 0x465c, 0x0d7f, 0x0c7e, 0x2660, 0x6003, 0x0009,
+	0x630a, 0x0c7f, 0x0078, 0x4613, 0x6837, 0x0103, 0x6b4a, 0x6847,
+	0x0000, 0x1078, 0x36a1, 0x1078, 0x5374, 0x0078, 0x4613, 0x007f,
+	0x0078, 0x4606, 0x781e, 0x781a, 0x0d7f, 0x0c7f, 0x067f, 0x007f,
+	0x007c, 0x0e7e, 0x0c7e, 0x2071, 0x6f10, 0x7004, 0xa084, 0x0007,
+	0x0079, 0x467a, 0x4684, 0x4687, 0x46a0, 0x46bc, 0x4701, 0x4684,
+	0x4682, 0x4682, 0x1078, 0x12b7, 0x0c7f, 0x0e7f, 0x007c, 0x7024,
+	0xa065, 0x0040, 0x4695, 0x7020, 0x8001, 0x7022, 0x600c, 0xa015,
+	0x0040, 0x469c, 0x7216, 0x600f, 0x0000, 0x7007, 0x0000, 0x7027,
+	0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x7216, 0x7212, 0x0078, 0x4695,
+	0x6018, 0x2060, 0x1078, 0x33c4, 0x6000, 0xc0dc, 0x6002, 0x7020,
+	0x8001, 0x7022, 0x0040, 0x46b1, 0x6054, 0xa015, 0x0040, 0x46b8,
+	0x721e, 0x7007, 0x0000, 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c,
+	0x7218, 0x721e, 0x0078, 0x46b1, 0x7024, 0xa065, 0x0040, 0x46fe,
+	0x700c, 0xac06, 0x00c0, 0x46d3, 0x1078, 0x5374, 0x600c, 0xa015,
+	0x0040, 0x46cf, 0x720e, 0x600f, 0x0000, 0x0078, 0x46fc, 0x720e,
+	0x720a, 0x0078, 0x46fc, 0x7014, 0xac06, 0x00c0, 0x46e6, 0x1078,
+	0x5374, 0x600c, 0xa015, 0x0040, 0x46e2, 0x7216, 0x600f, 0x0000,
+	0x0078, 0x46fc, 0x7216, 0x7212, 0x0078, 0x46fc, 0x6018, 0x2060,
+	0x1078, 0x33c4, 0x6000, 0xc0dc, 0x6002, 0x1078, 0x5374, 0x701c,
+	0xa065, 0x0040, 0x46fc, 0x6054, 0xa015, 0x0040, 0x46fa, 0x721e,
+	0x0078, 0x46fc, 0x7218, 0x721e, 0x7027, 0x0000, 0x0c7f, 0x0e7f,
+	0x007c, 0x7024, 0xa065, 0x0040, 0x470e, 0x1078, 0x5374, 0x600c,
+	0xa015, 0x0040, 0x4715, 0x720e, 0x600f, 0x0000, 0x1078, 0x54a4,
+	0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x720e, 0x720a, 0x0078,
+	0x470e, 0x0d7e, 0x2069, 0x6f10, 0x6830, 0xa084, 0x0003, 0x0079,
+	0x4721, 0x4727, 0x4729, 0x474f, 0x4725, 0x1078, 0x12b7, 0x0d7f,
+	0x007c, 0x0c7e, 0x6840, 0xa086, 0x0001, 0x0040, 0x4745, 0x683c,
+	0xa065, 0x0040, 0x473a, 0x600c, 0xa015, 0x0040, 0x4741, 0x6a3a,
+	0x600f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x0c7f, 0x0d7f,
+	0x007c, 0x683a, 0x6836, 0x0078, 0x473a, 0x6843, 0x0000, 0x6838,
+	0xa065, 0x0040, 0x473a, 0x6003, 0x0003, 0x0078, 0x473a, 0x0c7e,
+	0x6843, 0x0000, 0x6847, 0x0000, 0x683c, 0xa065, 0x0040, 0x4767,
+	0x600c, 0xa015, 0x0040, 0x4763, 0x6a3a, 0x600f, 0x0000, 0x683f,
+	0x0000, 0x0078, 0x4767, 0x683f, 0x0000, 0x683a, 0x6836, 0x0c7f,
+	0x0d7f, 0x007c, 0x0d7e, 0x2069, 0x6f10, 0x6804, 0xa084, 0x0007,
+	0x0079, 0x4772, 0x477c, 0x4810, 0x4810, 0x4810, 0x4810, 0x4812,
+	0x477a, 0x477a, 0x1078, 0x12b7, 0x6820, 0xa005, 0x00c0, 0x4782,
+	0x0d7f, 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, 0x4791, 0x6807,
+	0x0004, 0x6826, 0x682b, 0x0000, 0x1078, 0x4858, 0x0c7f, 0x0d7f,
+	0x007c, 0x6814, 0xa065, 0x0040, 0x479f, 0x6807, 0x0001, 0x6826,
+	0x682b, 0x0000, 0x1078, 0x4858, 0x0c7f, 0x0d7f, 0x007c, 0x0e7e,
+	0x037e, 0x6a1c, 0xa2f5, 0x0000, 0x0040, 0x480b, 0x704c, 0xa00d,
+	0x0040, 0x47ae, 0x7088, 0xa005, 0x0040, 0x47c6, 0x7054, 0xa075,
+	0x0040, 0x47b7, 0xa20e, 0x0040, 0x480b, 0x0078, 0x47bc, 0x6818,
+	0xa20e, 0x0040, 0x480b, 0x2070, 0x704c, 0xa00d, 0x0040, 0x47ae,
+	0x7088, 0xa005, 0x00c0, 0x47ae, 0x2e00, 0x681e, 0x733c, 0x7038,
+	0xa302, 0x00c8, 0x47ae, 0x1078, 0x5539, 0x0040, 0x480b, 0x8318,
+	0x733e, 0x6112, 0x2e10, 0x621a, 0xa180, 0x0015, 0x2004, 0xa08a,
+	0x199a, 0x0048, 0x47dd, 0x2001, 0x1999, 0x8003, 0x801b, 0x831b,
+	0xa318, 0x6316, 0x037f, 0x0f7e, 0x2c78, 0x71a0, 0xd1bc, 0x0040,
+	0x47ed, 0x2009, 0x0000, 0x0078, 0x47f2, 0xa1e0, 0x2091, 0x2c0c,
+	0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0x1078, 0x4c44, 0x7300,
+	0xc3dd, 0x7302, 0x6807, 0x0002, 0x2f18, 0x6b26, 0x682b, 0x0000,
+	0x781f, 0x0003, 0x7803, 0x0001, 0x7807, 0x0040, 0x0f7f, 0x0e7f,
+	0x0c7f, 0x0d7f, 0x007c, 0x037f, 0x0e7f, 0x0c7f, 0x0078, 0x4809,
+	0x0d7f, 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, 0x481e, 0x6807,
+	0x0004, 0x6826, 0x682b, 0x0000, 0x1078, 0x4858, 0x0c7f, 0x0d7f,
+	0x007c, 0x0f7e, 0x0d7e, 0x2069, 0x6f10, 0x6830, 0xa086, 0x0000,
+	0x00c0, 0x483f, 0x6838, 0xa07d, 0x0040, 0x483f, 0x6833, 0x0001,
+	0x683e, 0x6847, 0x0000, 0x127e, 0x0f7e, 0x2091, 0x2200, 0x027f,
+	0x1078, 0x1838, 0x00c0, 0x4842, 0x127f, 0x1078, 0x4ed5, 0x0d7f,
+	0x0f7f, 0x007c, 0x127f, 0x6843, 0x0000, 0x7803, 0x0002, 0x780c,
+	0xa015, 0x0040, 0x4854, 0x6a3a, 0x780f, 0x0000, 0x6833, 0x0000,
+	0x683f, 0x0000, 0x0078, 0x483f, 0x683a, 0x6836, 0x0078, 0x484e,
+	0x601c, 0xa084, 0x000f, 0x1079, 0x485e, 0x007c, 0x4867, 0x4869,
+	0x4b33, 0x4c15, 0x4869, 0x4b33, 0x4c15, 0x4867, 0x4869, 0x1078,
+	0x12b7, 0x157e, 0x137e, 0x147e, 0x0c7e, 0x0f7e, 0x6004, 0xa08a,
+	0x0024, 0x10c8, 0x12b7, 0x6118, 0x2178, 0x79a0, 0xa1f8, 0x2091,
+	0x2f0c, 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0x1079,
+	0x4887, 0x0f7f, 0x0c7f, 0x147f, 0x137f, 0x157f, 0x007c, 0x48ad,
+	0x48ec, 0x4904, 0x494c, 0x4979, 0x4981, 0x49a2, 0x49b3, 0x49c4,
+	0x49cc, 0x49dd, 0x49cc, 0x4a25, 0x49b3, 0x4a55, 0x4a5d, 0x49c4,
+	0x4a5d, 0x4a6e, 0x48ab, 0x48ab, 0x48ab, 0x48ab, 0x48ab, 0x48ab,
+	0x48ab, 0x48ab, 0x48ab, 0x48ab, 0x48ab, 0x48ab, 0x50b8, 0x50cd,
+	0x50f0, 0x5114, 0x49a2, 0x1078, 0x12b7, 0x20a1, 0x020b, 0x1078,
+	0x4a83, 0x20a3, 0x5200, 0x20a3, 0x0000, 0x0d7e, 0x2069, 0x6d51,
+	0x6804, 0xd084, 0x0040, 0x48ce, 0x6828, 0x017e, 0x2069, 0x6d00,
+	0x694c, 0xa106, 0x017f, 0x00c0, 0x48ce, 0x20a3, 0x0000, 0x6030,
+	0xa084, 0x00ff, 0x20a2, 0x0d7f, 0x0078, 0x48d3, 0x0d7f, 0x20a3,
+	0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, 0x6d05, 0x53a6,
+	0x20a9, 0x0004, 0x2099, 0x6d01, 0x53a6, 0x20a3, 0x0000, 0x6030,
+	0xa084, 0x00ff, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
+	0x001c, 0x1078, 0x4fd1, 0x007c, 0x20a1, 0x020b, 0x1078, 0x4a83,
+	0x20a3, 0x0500, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x6030, 0xa084,
+	0x00ff, 0x20a2, 0x20a9, 0x0004, 0x2099, 0x6d05, 0x53a6, 0x60c3,
+	0x0010, 0x1078, 0x4fd1, 0x007c, 0x20a1, 0x020b, 0x1078, 0x4a83,
+	0x7818, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x00c0, 0x4917,
+	0x20a3, 0x0400, 0x620c, 0xc2b4, 0x620e, 0x0078, 0x4919, 0x20a3,
+	0x0300, 0x20a3, 0x0000, 0x2099, 0x6f00, 0x20a9, 0x0008, 0x53a6,
+	0x20a9, 0x0004, 0x2099, 0x6d05, 0x53a6, 0x20a9, 0x0004, 0x2099,
+	0x6d01, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, 0x492c,
+	0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, 0x4932, 0x2099, 0x6f08,
+	0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0,
+	0x493d, 0x20a9, 0x000a, 0x20a3, 0x0000, 0x00f0, 0x4943, 0x60c3,
+	0x0074, 0x1078, 0x4fd1, 0x007c, 0x20a1, 0x020b, 0x1078, 0x4a83,
+	0x20a3, 0x2010, 0x20a3, 0x0014, 0x20a3, 0x0800, 0x20a3, 0x2000,
+	0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x0f7e, 0x2079,
+	0x6d51, 0x7904, 0x0f7f, 0xd1ac, 0x00c0, 0x4968, 0xa085, 0x0020,
+	0xd1a4, 0x0040, 0x496d, 0xa085, 0x0010, 0xa085, 0x0002, 0x20a2,
+	0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x4fd1,
+	0x007c, 0x20a1, 0x020b, 0x1078, 0x4a83, 0x20a3, 0x5000, 0x0078,
+	0x4919, 0x20a1, 0x020b, 0x1078, 0x4a83, 0x20a3, 0x2110, 0x20a3,
+	0x0014, 0x20a3, 0x0800, 0x20a3, 0x2000, 0x20a3, 0x0000, 0x20a3,
+	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
+	0x0022, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078,
+	0x4fd1, 0x007c, 0x20a1, 0x020b, 0x1078, 0x4afa, 0x20a3, 0x0200,
+	0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004,
+	0x1078, 0x4fd1, 0x007c, 0x20a1, 0x020b, 0x1078, 0x4afa, 0x20a3,
+	0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3,
+	0x0008, 0x1078, 0x4fd1, 0x007c, 0x20a1, 0x020b, 0x1078, 0x4afa,
+	0x20a3, 0x0200, 0x0078, 0x4919, 0x20a1, 0x020b, 0x1078, 0x4afa,
+	0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x7810, 0x20a2,
+	0x60c3, 0x0008, 0x1078, 0x4fd1, 0x007c, 0x0d7e, 0x20a1, 0x020b,
+	0x1078, 0x4afa, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0800,
+	0x7818, 0x2068, 0x6894, 0xa086, 0x0014, 0x00c0, 0x4a03, 0x6998,
+	0xa184, 0xc000, 0x00c0, 0x49ff, 0xd1ec, 0x0040, 0x49fb, 0x20a3,
+	0x2100, 0x0078, 0x4a05, 0x20a3, 0x0100, 0x0078, 0x4a05, 0x20a3,
+	0x0400, 0x0078, 0x4a05, 0x20a3, 0x0700, 0xa006, 0x20a2, 0x20a2,
+	0x20a2, 0x20a2, 0x20a2, 0x0f7e, 0x2079, 0x6d51, 0x7904, 0x0f7f,
+	0xd1ac, 0x00c0, 0x4a15, 0xa085, 0x0020, 0xd1a4, 0x0040, 0x4a1a,
+	0xa085, 0x0010, 0xa085, 0x0002, 0x20a2, 0x20a2, 0x20a2, 0x60c3,
+	0x0014, 0x1078, 0x4fd1, 0x0d7f, 0x007c, 0x20a1, 0x020b, 0x1078,
+	0x4afa, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x6018,
+	0x0d7e, 0x2068, 0x6804, 0x0d7f, 0xa084, 0x00ff, 0xa086, 0x0006,
+	0x0040, 0x4a3e, 0x20a3, 0x0400, 0x0078, 0x4a40, 0x20a3, 0x0100,
+	0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000,
+	0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000,
+	0x60c3, 0x0014, 0x1078, 0x4fd1, 0x007c, 0x20a1, 0x020b, 0x1078,
+	0x4afa, 0x20a3, 0x0200, 0x0078, 0x48b3, 0x20a1, 0x020b, 0x1078,
+	0x4afa, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3,
+	0x2a00, 0x60c3, 0x0008, 0x1078, 0x4fd1, 0x007c, 0x20e1, 0x9080,
+	0x20e1, 0x4000, 0x20a1, 0x020b, 0x1078, 0x4afa, 0x20a3, 0x0100,
+	0x20a3, 0x0000, 0x20a3, 0x000b, 0x20a3, 0x0000, 0x60c3, 0x0008,
+	0x1078, 0x4fd1, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000,
+	0x7818, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e, 0x00c0, 0x4a96,
+	0x20a3, 0x22ff, 0x20a3, 0xfffe, 0x0078, 0x4ac4, 0xa286, 0x007f,
+	0x00c0, 0x4aa1, 0x0d7e, 0x20a3, 0x22ff, 0x20a3, 0xfffd, 0x0078,
+	0x4ab8, 0xd2bc, 0x0040, 0x4ac0, 0xa286, 0x0080, 0x0d7e, 0x00c0,
+	0x4aaf, 0x20a3, 0x22ff, 0x20a3, 0xfffc, 0x0078, 0x4ab8, 0xa2e8,
+	0x6e00, 0x2d6c, 0x6810, 0xa085, 0x2200, 0x20a2, 0x6814, 0x20a2,
+	0x2069, 0x6d19, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x4ac8,
+	0x20a3, 0x2200, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2,
+	0x20a3, 0x0129, 0x20a3, 0x0000, 0x1078, 0x4fc0, 0x22a2, 0x20a3,
+	0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000,
+	0x027f, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a3,
+	0x02ff, 0x2011, 0xfffc, 0x22a2, 0x0d7e, 0x2069, 0x6d19, 0x2da6,
+	0x8d68, 0x2da6, 0x0d7f, 0x20a3, 0x2029, 0x20a3, 0x0000, 0x0078,
+	0x4acc, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0xfc02, 0x20a3,
+	0x0000, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818,
+	0xa080, 0x0028, 0x2004, 0xa092, 0x007e, 0x0048, 0x4b19, 0x0d7e,
+	0xa0e8, 0x6e00, 0x2d6c, 0x6810, 0xa085, 0x2300, 0x20a2, 0x6814,
+	0x20a2, 0x2069, 0x6d19, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078,
+	0x4b21, 0x20a3, 0x2300, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230,
+	0x22a2, 0x20a3, 0x0198, 0x20a3, 0x0000, 0x1078, 0x4fc0, 0x22a2,
+	0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3,
+	0x0000, 0x027f, 0x007c, 0x0c7e, 0x0f7e, 0x6004, 0xa08a, 0x0025,
+	0x1048, 0x12b7, 0xa08a, 0x002c, 0x10c8, 0x12b7, 0x6118, 0x2178,
+	0x79a0, 0xa1f8, 0x2091, 0x2f0c, 0xa18c, 0x00ff, 0x2c78, 0x2061,
+	0x0100, 0x619a, 0xa082, 0x0025, 0x1079, 0x4b51, 0x0f7f, 0x0c7f,
+	0x007c, 0x4b5a, 0x4b65, 0x4b7f, 0x4b58, 0x4b58, 0x4b58, 0x4b5a,
+	0x1078, 0x12b7, 0x147e, 0x20a1, 0x020b, 0x1078, 0x4b8e, 0x60c3,
+	0x0000, 0x1078, 0x4fd1, 0x147f, 0x007c, 0x147e, 0x20a1, 0x020b,
+	0x1078, 0x4bbb, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2,
+	0x2fa2, 0x20a3, 0x0000, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3,
+	0x0000, 0x60c3, 0x000c, 0x1078, 0x4fd1, 0x147f, 0x007c, 0x147e,
+	0x20a1, 0x020b, 0x1078, 0x4be8, 0x20a3, 0x0003, 0x20a3, 0x0300,
+	0x60c3, 0x0004, 0x1078, 0x4fd1, 0x147f, 0x007c, 0x027e, 0x20e1,
+	0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa092,
+	0x007e, 0x0048, 0x4bad, 0x0d7e, 0xa0e8, 0x6e00, 0x2d6c, 0x6810,
+	0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x6d19, 0x2da6,
+	0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x4bb5, 0x20a3, 0x8100, 0x6298,
+	0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0009, 0x20a3,
+	0x0000, 0x0078, 0x4acc, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000,
+	0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e, 0x0048, 0x4bda,
+	0x0d7e, 0xa0e8, 0x6e00, 0x2d6c, 0x6810, 0xa085, 0x8400, 0x20a2,
+	0x6814, 0x20a2, 0x2069, 0x6d19, 0x2da6, 0x8d68, 0x2da6, 0x0d7f,
+	0x0078, 0x4be2, 0x20a3, 0x8400, 0x6298, 0x22a2, 0x20a3, 0x0000,
+	0x6230, 0x22a2, 0x20a3, 0x00d1, 0x20a3, 0x0000, 0x0078, 0x4b25,
+	0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
+	0x2004, 0xa092, 0x007e, 0x0048, 0x4c07, 0x0d7e, 0xa0e8, 0x6e00,
+	0x2d6c, 0x6810, 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x2069,
+	0x6d19, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x4c0f, 0x20a3,
+	0x8500, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3,
+	0x00d1, 0x20a3, 0x0000, 0x0078, 0x4b25, 0x0c7e, 0x0f7e, 0x2c78,
+	0x7804, 0xa08a, 0x0040, 0x1048, 0x12b7, 0xa08a, 0x004f, 0x10c8,
+	0x12b7, 0x7918, 0x2160, 0x61a0, 0xa1e0, 0x2091, 0x2c0c, 0xa18c,
+	0x00ff, 0x2061, 0x0100, 0x619a, 0xa082, 0x0040, 0x1079, 0x4c33,
+	0x0f7f, 0x0c7f, 0x007c, 0x4c44, 0x4d28, 0x4cd0, 0x4e50, 0x4c42,
+	0x4c42, 0x4c42, 0x4c42, 0x4c42, 0x4c42, 0x4c42, 0x528d, 0x529e,
+	0x52af, 0x52c0, 0x1078, 0x12b7, 0x0d7e, 0x157e, 0x147e, 0x20a1,
+	0x020b, 0x1078, 0x4c93, 0x7910, 0x2168, 0x6944, 0xa18c, 0x00ff,
+	0x21a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x694c, 0xa184, 0x0006,
+	0x8004, 0x20a2, 0xd1ac, 0x0040, 0x4c61, 0x20a3, 0x0002, 0x0078,
+	0x4c6d, 0xd1b4, 0x0040, 0x4c68, 0x20a3, 0x0001, 0x0078, 0x4c6d,
+	0x20a3, 0x0000, 0x2230, 0x0078, 0x4c6f, 0x6a80, 0x6e7c, 0x20a9,
+	0x0008, 0xad80, 0x0017, 0x200c, 0x810f, 0x21a2, 0x8000, 0x00f0,
+	0x4c73, 0x22a2, 0x26a2, 0x60c3, 0x0020, 0x20e1, 0x9080, 0x6014,
+	0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x2001, 0x6f2c, 0x2003,
+	0x07d0, 0x2001, 0x6f2b, 0x2003, 0x0009, 0x1078, 0x14e4, 0x147f,
+	0x157f, 0x0d7f, 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7a18,
+	0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202, 0x8217,
+	0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x4cb9, 0x0d7e,
+	0xa0e8, 0x6e00, 0x2d6c, 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814,
+	0x20a2, 0x2069, 0x6d19, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078,
+	0x4cc1, 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, 0x4cf0,
+	0x7810, 0x2068, 0x6860, 0x20a2, 0x685c, 0x20a2, 0x6880, 0x20a2,
+	0x687c, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x60c3,
+	0x000c, 0x1078, 0x4fd1, 0x147f, 0x137f, 0x157f, 0x0d7f, 0x007c,
+	0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
+	0x2004, 0xd0bc, 0x0040, 0x4d0e, 0x0d7e, 0xa0e8, 0x6e00, 0x2d6c,
+	0x6810, 0xa085, 0x0500, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x6d19,
+	0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x4d16, 0x20a3, 0x0500,
+	0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0889,
+	0x20a3, 0x0000, 0x1078, 0x4fc0, 0x22a2, 0x20a3, 0x0000, 0x7a08,
+	0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c,
+	0x0d7e, 0x157e, 0x137e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x4e18,
+	0x7810, 0x2068, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2,
+	0x7810, 0xa084, 0xf000, 0x00c0, 0x4d45, 0x7810, 0xa084, 0x0700,
+	0x8007, 0x1079, 0x4d4d, 0x0078, 0x4d48, 0xa006, 0x1079, 0x4d4d,
+	0x147f, 0x137f, 0x157f, 0x0d7f, 0x007c, 0x4d57, 0x4db9, 0x4dbd,
+	0x4de0, 0x4ded, 0x4dff, 0x4e03, 0x4d55, 0x1078, 0x12b7, 0x017e,
+	0x037e, 0x694c, 0xa18c, 0x0003, 0xa186, 0x0000, 0x00c0, 0x4d6a,
+	0x6b78, 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x037f, 0x017f,
+	0x0078, 0x4de4, 0xa186, 0x0001, 0x00c0, 0x4db4, 0x6b78, 0x23a2,
+	0x6868, 0x20a2, 0x6864, 0x20a2, 0x22a2, 0x6874, 0x20a2, 0x22a2,
+	0x687c, 0x20a2, 0x2009, 0x0018, 0xa384, 0x0300, 0x0040, 0x4db3,
+	0xd3c4, 0x0040, 0x4d85, 0x687c, 0xa108, 0xd3cc, 0x0040, 0x4d8a,
+	0x6874, 0xa108, 0x157e, 0x20a9, 0x000d, 0xad80, 0x0020, 0x201c,
+	0x831f, 0x23a2, 0x8000, 0x00f0, 0x4d8f, 0x157f, 0x22a2, 0x22a2,
+	0x22a2, 0xa184, 0x0003, 0x0040, 0x4db3, 0x20a1, 0x020b, 0x20e1,
+	0x9080, 0x20e1, 0x4000, 0x20a3, 0x0700, 0x6298, 0x22a2, 0x20a3,
+	0x0000, 0x6230, 0x22a2, 0x20a3, 0x0898, 0x20a2, 0x1078, 0x4fc0,
+	0x22a2, 0x20a3, 0x0000, 0x61c2, 0x037f, 0x017f, 0x1078, 0x4fd1,
+	0x007c, 0x20a3, 0x0008, 0x0078, 0x4de2, 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, 0x4fd1, 0x007c,
+	0x20a3, 0x0028, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2,
+	0x60c3, 0x0018, 0x1078, 0x4fd1, 0x007c, 0x20a3, 0x0100, 0x22a2,
+	0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0008, 0x22a2, 0x22a2,
+	0x22a2, 0x22a2, 0x60c3, 0x0020, 0x1078, 0x4fd1, 0x007c, 0x20a3,
+	0x0008, 0x0078, 0x4de2, 0x037e, 0x7b10, 0xa384, 0xff00, 0x7812,
+	0xa384, 0x00ff, 0x8001, 0x00c0, 0x4e11, 0x22a2, 0x037f, 0x0078,
+	0x4de2, 0x20a3, 0x0800, 0x22a2, 0x20a2, 0x037f, 0x0078, 0x4de4,
+	0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
+	0x2004, 0xd0bc, 0x0040, 0x4e36, 0x0d7e, 0xa0e8, 0x6e00, 0x2d6c,
+	0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x6d19,
+	0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x4e3e, 0x20a3, 0x0700,
+	0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0898,
+	0x20a3, 0x0000, 0x1078, 0x4fc0, 0x22a2, 0x20a3, 0x0000, 0x7a08,
+	0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c,
+	0x0d7e, 0x157e, 0x137e, 0x147e, 0x017e, 0x037e, 0x7810, 0xa084,
+	0x0700, 0x8007, 0x1079, 0x4e63, 0x037f, 0x017f, 0x147f, 0x137f,
+	0x157f, 0x0d7f, 0x007c, 0x4e6b, 0x4e6b, 0x4e6d, 0x4e6b, 0x4e6b,
+	0x4e6b, 0x4e92, 0x4e6b, 0x1078, 0x12b7, 0x7910, 0xa18c, 0xf8ff,
+	0xa18d, 0x0600, 0x7912, 0x20a1, 0x020b, 0x2009, 0x0003, 0x1078,
+	0x4e9c, 0x0d7e, 0x2069, 0x6d51, 0x6804, 0xd0bc, 0x0040, 0x4e87,
+	0x682c, 0xa084, 0x00ff, 0x8007, 0x20a2, 0x0078, 0x4e89, 0x20a3,
+	0x3f00, 0x0d7f, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0001, 0x1078,
+	0x4fd1, 0x007c, 0x20a1, 0x020b, 0x2009, 0x0003, 0x1078, 0x4e9c,
+	0x20a3, 0x7f00, 0x0078, 0x4e8a, 0x027e, 0x20e1, 0x9080, 0x20e1,
+	0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x4eba,
+	0x0d7e, 0xa0e8, 0x6e00, 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2,
+	0x6814, 0x20a2, 0x2069, 0x6d19, 0x2da6, 0x8d68, 0x2da6, 0x0d7f,
+	0x0078, 0x4ec2, 0x20a3, 0x0100, 0x6298, 0x22a2, 0x20a3, 0x0000,
+	0x6230, 0x22a2, 0x20a3, 0x0888, 0xa18d, 0x0008, 0x21a2, 0x1078,
+	0x4fc0, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3,
+	0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x0e7e, 0x0d7e, 0x0c7e,
+	0x057e, 0x047e, 0x037e, 0x2061, 0x0100, 0x2071, 0x6d00, 0x6130,
+	0x7818, 0x2068, 0x68a0, 0x2028, 0xd0bc, 0x00c0, 0x4eee, 0xa080,
+	0x2091, 0x2014, 0xa294, 0x00ff, 0x0078, 0x4ef2, 0x6910, 0x6a14,
+	0x7364, 0x7468, 0x781c, 0xa086, 0x0006, 0x0040, 0x4f3d, 0xd5bc,
+	0x0040, 0x4f02, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e,
+	0x0078, 0x4f08, 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, 0x4f31, 0x2011,
+	0x0000, 0x629e, 0x6017, 0x0016, 0x1078, 0x4151, 0x037f, 0x047f,
+	0x057f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x7810, 0x2070, 0x704c,
+	0xa084, 0x0003, 0xa086, 0x0002, 0x0040, 0x4f83, 0xd5bc, 0x0040,
+	0x4f51, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, 0x0078,
+	0x4f57, 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, 0x4f7e, 0x2011, 0x0000, 0x629e, 0x6017,
+	0x0012, 0x0078, 0x4f34, 0xd5bc, 0x0040, 0x4f8e, 0xa185, 0x0700,
+	0x20a2, 0x6266, 0x636a, 0x646e, 0x0078, 0x4f94, 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,
+	0x4fbb, 0x2011, 0x0000, 0x629e, 0x6017, 0x0016, 0x0078, 0x4f34,
+	0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202,
+	0x8217, 0x007c, 0x0d7e, 0x2069, 0x6f10, 0x6843, 0x0001, 0x0d7f,
+	0x007c, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x1078,
+	0x4fdc, 0x1078, 0x4143, 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, 0x414c,
+	0x2061, 0x0100, 0x2069, 0x0140, 0x6904, 0xa194, 0x4000, 0x0040,
+	0x503a, 0x1078, 0x4fe5, 0x6803, 0x1000, 0x6803, 0x0000, 0x0c7e,
+	0x2061, 0x6f10, 0x6128, 0xa192, 0x0002, 0x00c8, 0x5027, 0x8108,
+	0x612a, 0x613c, 0x0c7f, 0x81ff, 0x0040, 0x5035, 0x1078, 0x4143,
+	0xa188, 0x0007, 0x210c, 0xa18e, 0x0006, 0x00c0, 0x5023, 0x6017,
+	0x0012, 0x0078, 0x5035, 0x1078, 0x4fdc, 0x0078, 0x5035, 0x6124,
+	0xa1e5, 0x0000, 0x0040, 0x5032, 0x1078, 0x6c76, 0x2009, 0x0014,
+	0x1078, 0x5591, 0x0c7f, 0x0078, 0x5035, 0x027f, 0x017f, 0x0d7f,
+	0x0c7f, 0x007c, 0x1078, 0x31cb, 0x0078, 0x5035, 0x0c7e, 0x0d7e,
+	0x0e7e, 0x017e, 0x027e, 0x1078, 0x415a, 0x2071, 0x6f10, 0x713c,
+	0x81ff, 0x0040, 0x5079, 0x2061, 0x0100, 0x2069, 0x0140, 0x6904,
+	0x017e, 0x017f, 0xa194, 0x4000, 0x0040, 0x507f, 0x6017, 0x0010,
+	0x7144, 0xa192, 0x0002, 0x00c8, 0x5071, 0x8108, 0x7146, 0x1078,
+	0x4151, 0x713c, 0xa188, 0x0007, 0x210c, 0xa18e, 0x0006, 0x00c0,
+	0x506d, 0x6017, 0x0012, 0x0078, 0x5079, 0x6017, 0x0016, 0x0078,
+	0x5079, 0x1078, 0x6c76, 0x2009, 0x004a, 0x1078, 0x5591, 0x0078,
+	0x5079, 0x027f, 0x017f, 0x0e7f, 0x0d7f, 0x0c7f, 0x007c, 0x1078,
+	0x4151, 0x0078, 0x5079, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x057e,
+	0x047e, 0x007e, 0x127e, 0x2091, 0x8000, 0x6018, 0x2068, 0x6ca0,
+	0x2071, 0x6f10, 0x7018, 0x2068, 0x8dff, 0x0040, 0x50af, 0x68a0,
+	0xa406, 0x0040, 0x509f, 0x6854, 0x2068, 0x0078, 0x5094, 0x6010,
+	0x2060, 0x643c, 0x6540, 0x6644, 0xa6b4, 0x000f, 0x2d60, 0x1078,
+	0x3522, 0x0040, 0x50af, 0x1078, 0x5374, 0xa085, 0x0001, 0x127f,
+	0x007f, 0x047f, 0x057f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c,
+	0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x4a83, 0x20a3, 0x0f00,
+	0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, 0x60c3, 0x0008,
+	0x1078, 0x4fd1, 0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x20a1,
+	0x020b, 0x1078, 0x4afa, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a9,
+	0x0006, 0x2011, 0x6d40, 0x2019, 0x6d40, 0x23a6, 0x22a6, 0xa398,
+	0x0002, 0xa290, 0x0002, 0x00f0, 0x50dd, 0x20a3, 0x0000, 0x20a3,
+	0x0000, 0x60c3, 0x001c, 0x1078, 0x4fd1, 0x147f, 0x157f, 0x007c,
+	0x157e, 0x147e, 0x017e, 0x027e, 0x20a1, 0x020b, 0x1078, 0x4ada,
+	0x1078, 0x4af1, 0x7810, 0x007e, 0xa080, 0x0015, 0x2098, 0x7808,
+	0xa088, 0x0002, 0x21a8, 0x53a6, 0xa080, 0x0004, 0x8003, 0x60c2,
+	0x007f, 0xa080, 0x0001, 0x2004, 0x7812, 0x1078, 0x4fd1, 0x027f,
+	0x017f, 0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b,
+	0x1078, 0x4a83, 0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3, 0x0000,
+	0x7808, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x4fd1, 0x147f, 0x157f,
+	0x007c, 0x0e7e, 0x0c7e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071,
+	0x6f10, 0x700c, 0x2060, 0x8cff, 0x0040, 0x513f, 0x600c, 0x007e,
+	0x1078, 0x556a, 0x1078, 0x5374, 0x0c7f, 0x0078, 0x5133, 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,
+	0x6f10, 0x7024, 0x2060, 0x8cff, 0x0040, 0x5198, 0x1078, 0x4fe5,
+	0x68c3, 0x0000, 0x1078, 0x414c, 0x2009, 0x0013, 0x1078, 0x5591,
+	0x20a9, 0x01f4, 0x6824, 0xd094, 0x0040, 0x517b, 0x6827, 0x0004,
+	0x7804, 0xa084, 0x4000, 0x0040, 0x518d, 0x7803, 0x1000, 0x7803,
+	0x0000, 0x0078, 0x518d, 0xd084, 0x0040, 0x5182, 0x6827, 0x0001,
+	0x0078, 0x5184, 0x00f0, 0x516a, 0x7804, 0xa084, 0x1000, 0x0040,
+	0x518d, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x007f, 0x017f,
+	0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f, 0x127f, 0x007c,
+	0x2001, 0x6d00, 0x2004, 0xa096, 0x0001, 0x0040, 0x51d0, 0xa096,
+	0x0004, 0x0040, 0x51d0, 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011,
+	0x318e, 0x1078, 0x40d1, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0040,
+	0x51be, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x0040, 0x51d0,
+	0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0x51d0, 0xd084, 0x0040,
+	0x51c5, 0x6827, 0x0001, 0x0078, 0x51c7, 0x00f0, 0x51ad, 0x7804,
+	0xa084, 0x1000, 0x0040, 0x51d0, 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, 0x6f10, 0x703c, 0x2060, 0x8cff, 0x0040, 0x5228,
+	0x6817, 0x0010, 0x68cb, 0x0000, 0x68c7, 0x0000, 0x1078, 0x415a,
+	0x1078, 0x1a20, 0xa39d, 0x0000, 0x00c0, 0x5202, 0x2009, 0x0049,
+	0x1078, 0x5591, 0x20a9, 0x03e8, 0x6824, 0xd094, 0x0040, 0x5215,
+	0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x0040, 0x5227, 0x7803,
+	0x1000, 0x7803, 0x0000, 0x0078, 0x5227, 0xd094, 0x0040, 0x521c,
+	0x6827, 0x0002, 0x0078, 0x521e, 0x00f0, 0x5204, 0x7804, 0xa084,
+	0x1000, 0x0040, 0x5227, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824,
+	0x007f, 0x017f, 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f,
+	0x127f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2069, 0x6f10,
+	0x6a06, 0x127f, 0x0d7f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000,
+	0x2069, 0x6f10, 0x6a32, 0x127f, 0x0d7f, 0x007c, 0x0f7e, 0x0e7e,
+	0x0c7e, 0x067e, 0x007e, 0x127e, 0x2071, 0x6f10, 0x7614, 0x2660,
+	0x2678, 0x2091, 0x8000, 0x8cff, 0x0040, 0x5286, 0x601c, 0xa206,
+	0x00c0, 0x5281, 0x7014, 0xac36, 0x00c0, 0x5260, 0x660c, 0x7616,
+	0x7010, 0xac36, 0x00c0, 0x526e, 0x2c00, 0xaf36, 0x0040, 0x526c,
+	0x2f00, 0x7012, 0x0078, 0x526e, 0x7013, 0x0000, 0x660c, 0x067e,
+	0x2c00, 0xaf06, 0x0040, 0x5277, 0x7e0e, 0x0078, 0x5278, 0x2678,
+	0x600f, 0x0000, 0x1078, 0x6283, 0x1078, 0x5374, 0x0c7f, 0x0078,
+	0x5253, 0x2c78, 0x600c, 0x2060, 0x0078, 0x5253, 0x127f, 0x007f,
+	0x067f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0x157e, 0x147e, 0x20a1,
+	0x020b, 0x1078, 0x4c93, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2,
+	0x20a2, 0x20a2, 0x20a3, 0x4000, 0x0078, 0x52cf, 0x157e, 0x147e,
+	0x20a1, 0x020b, 0x1078, 0x4c93, 0x7810, 0x20a2, 0xa006, 0x20a2,
+	0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x2000, 0x0078, 0x52cf, 0x157e,
+	0x147e, 0x20a1, 0x020b, 0x1078, 0x4c93, 0x7810, 0x20a2, 0xa006,
+	0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400, 0x0078, 0x52cf,
+	0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x4c93, 0x7810, 0x20a2,
+	0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200, 0x1078,
+	0x537f, 0x60c3, 0x0020, 0x1078, 0x4fd1, 0x147f, 0x157f, 0x007c,
+	0x127e, 0x0c7e, 0x2091, 0x8000, 0x2061, 0x0100, 0x6120, 0xd1b4,
+	0x00c0, 0x52e7, 0xd1bc, 0x00c0, 0x5331, 0x0078, 0x5371, 0x2009,
+	0x017f, 0x200b, 0x00a1, 0x157e, 0x007e, 0x0d7e, 0x2069, 0x0140,
+	0x20a9, 0x001e, 0x2009, 0x0169, 0x6804, 0xa084, 0x4000, 0x0040,
+	0x5328, 0x6020, 0xd0b4, 0x0040, 0x5328, 0x6024, 0xd094, 0x00c0,
+	0x5328, 0x2104, 0xa084, 0x000f, 0xa086, 0x0004, 0x00c0, 0x5328,
+	0x00f0, 0x52f4, 0x027e, 0x6198, 0xa18c, 0x00ff, 0x8107, 0x6130,
+	0xa18c, 0x00ff, 0xa10d, 0x6088, 0x628c, 0x618e, 0x608b, 0xbc91,
+	0x6043, 0x0001, 0x6043, 0x0000, 0x608a, 0x628e, 0x6024, 0xd094,
+	0x00c0, 0x5327, 0x6a04, 0xa294, 0x4000, 0x00c0, 0x531e, 0x027f,
+	0x0d7f, 0x007f, 0x157f, 0x2009, 0x017f, 0x200b, 0x0000, 0x0078,
+	0x5371, 0x2009, 0x017f, 0x200b, 0x00a1, 0x157e, 0x007e, 0x0d7e,
+	0x2069, 0x0140, 0x20a9, 0x001e, 0x2009, 0x0169, 0x6804, 0xa084,
+	0x4000, 0x0040, 0x536a, 0x6020, 0xd0bc, 0x0040, 0x536a, 0x2104,
+	0xa084, 0x000f, 0xa086, 0x0004, 0x00c0, 0x536a, 0x00f0, 0x533e,
+	0x027e, 0x6164, 0xa18c, 0x00ff, 0x8107, 0x6130, 0xa18c, 0x00ff,
+	0xa10d, 0x6088, 0x628c, 0x608b, 0xbc91, 0x618e, 0x6043, 0x0001,
+	0x6043, 0x0000, 0x608a, 0x628e, 0x6a04, 0xa294, 0x4000, 0x00c0,
+	0x5364, 0x027f, 0x0d7f, 0x007f, 0x157f, 0x2009, 0x017f, 0x200b,
+	0x0000, 0x0c7f, 0x127f, 0x007c, 0x0e7e, 0x2071, 0x6f10, 0x7020,
+	0xa005, 0x0040, 0x537d, 0x8001, 0x7022, 0x0e7f, 0x007c, 0x20a9,
+	0x0008, 0x20a2, 0x00f0, 0x5381, 0x20a2, 0x20a2, 0x007c, 0x0f7e,
+	0x0e7e, 0x0d7e, 0x0c7e, 0x077e, 0x067e, 0x007e, 0x127e, 0x2091,
+	0x8000, 0x2071, 0x6f10, 0x7614, 0x2660, 0x2678, 0x2039, 0x0001,
+	0x87ff, 0x0040, 0x5417, 0x8cff, 0x0040, 0x5417, 0x601c, 0xa086,
+	0x0006, 0x00c0, 0x5412, 0x88ff, 0x0040, 0x53ae, 0x2800, 0xac06,
+	0x00c0, 0x5412, 0x2039, 0x0000, 0x0078, 0x53b2, 0x6018, 0xa206,
+	0x00c0, 0x5412, 0x7024, 0xac06, 0x00c0, 0x53e0, 0x2069, 0x0100,
+	0x68c0, 0xa005, 0x0040, 0x53db, 0x6817, 0x0008, 0x68c3, 0x0000,
+	0x1078, 0x54a4, 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04,
+	0xa384, 0x1000, 0x0040, 0x53d0, 0x6803, 0x0100, 0x6803, 0x0000,
+	0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x53d8, 0x6827, 0x0001,
+	0x037f, 0x0078, 0x53e0, 0x6003, 0x0009, 0x630a, 0x0078, 0x5412,
+	0x7014, 0xac36, 0x00c0, 0x53e6, 0x660c, 0x7616, 0x7010, 0xac36,
+	0x00c0, 0x53f4, 0x2c00, 0xaf36, 0x0040, 0x53f2, 0x2f00, 0x7012,
+	0x0078, 0x53f4, 0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06,
+	0x0040, 0x53fd, 0x7e0e, 0x0078, 0x53fe, 0x2678, 0x600f, 0x0000,
+	0x6010, 0x2068, 0x1078, 0x6120, 0x0040, 0x5408, 0x1078, 0x6bb3,
+	0x1078, 0x6283, 0x1078, 0x5374, 0x88ff, 0x00c0, 0x5421, 0x0c7f,
+	0x0078, 0x5398, 0x2c78, 0x600c, 0x2060, 0x0078, 0x5398, 0xa006,
+	0x127f, 0x007f, 0x067f, 0x077f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f,
+	0x007c, 0x6017, 0x0000, 0x0c7f, 0xa8c5, 0x0001, 0x0078, 0x5418,
+	0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x027e, 0x007e, 0x127e,
+	0x2091, 0x8000, 0x2071, 0x6f10, 0x7638, 0x2660, 0x2678, 0x8cff,
+	0x0040, 0x5493, 0x601c, 0xa086, 0x0006, 0x00c0, 0x548e, 0x88ff,
+	0x0040, 0x5448, 0x2800, 0xac06, 0x00c0, 0x548e, 0x0078, 0x544c,
+	0x6018, 0xa206, 0x00c0, 0x548e, 0x703c, 0xac06, 0x00c0, 0x545e,
+	0x037e, 0x2019, 0x0001, 0x1078, 0x51da, 0x7033, 0x0000, 0x703f,
+	0x0000, 0x7043, 0x0000, 0x7047, 0x0000, 0x037f, 0x7038, 0xac36,
+	0x00c0, 0x5464, 0x660c, 0x763a, 0x7034, 0xac36, 0x00c0, 0x5472,
+	0x2c00, 0xaf36, 0x0040, 0x5470, 0x2f00, 0x7036, 0x0078, 0x5472,
+	0x7037, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x547b,
+	0x7e0e, 0x0078, 0x547c, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068,
+	0x1078, 0x6120, 0x0040, 0x5486, 0x1078, 0x6bb3, 0x1078, 0x6283,
+	0x88ff, 0x00c0, 0x549d, 0x0c7f, 0x0078, 0x5437, 0x2c78, 0x600c,
+	0x2060, 0x0078, 0x5437, 0xa006, 0x127f, 0x007f, 0x027f, 0x067f,
+	0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x6017, 0x0000, 0x0c7f,
+	0xa8c5, 0x0001, 0x0078, 0x5494, 0x0e7e, 0x2071, 0x6f10, 0x2001,
+	0x6d00, 0x2004, 0xa086, 0x0002, 0x00c0, 0x54b2, 0x7007, 0x0005,
+	0x0078, 0x54b4, 0x7007, 0x0000, 0x0e7f, 0x007c, 0x0f7e, 0x0e7e,
+	0x0c7e, 0x067e, 0x027e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071,
+	0x6f10, 0x2c10, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0040, 0x54f4,
+	0x2200, 0xac06, 0x00c0, 0x54ef, 0x7038, 0xac36, 0x00c0, 0x54d2,
+	0x660c, 0x763a, 0x7034, 0xac36, 0x00c0, 0x54e0, 0x2c00, 0xaf36,
+	0x0040, 0x54de, 0x2f00, 0x7036, 0x0078, 0x54e0, 0x7037, 0x0000,
+	0x660c, 0x2c00, 0xaf06, 0x0040, 0x54e8, 0x7e0e, 0x0078, 0x54e9,
+	0x2678, 0x600f, 0x0000, 0xa085, 0x0001, 0x0078, 0x54f4, 0x2c78,
+	0x600c, 0x2060, 0x0078, 0x54c5, 0x127f, 0x007f, 0x027f, 0x067f,
+	0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0x2061, 0x7400, 0x2a70, 0x7060,
+	0x7046, 0x704b, 0x7400, 0x007c, 0x0e7e, 0x127e, 0x2071, 0x6d00,
+	0x2091, 0x8000, 0x7544, 0xa582, 0x0001, 0x0048, 0x5536, 0x7048,
+	0x2060, 0x6000, 0xa086, 0x0000, 0x0040, 0x5522, 0xace0, 0x0008,
+	0x7054, 0xac02, 0x00c8, 0x551e, 0x0078, 0x5511, 0x2061, 0x7400,
+	0x0078, 0x5511, 0x6003, 0x0008, 0x8529, 0x7546, 0xaca8, 0x0008,
+	0x7054, 0xa502, 0x00c8, 0x5532, 0x754a, 0xa085, 0x0001, 0x127f,
+	0x0e7f, 0x007c, 0x704b, 0x7400, 0x0078, 0x552d, 0xa006, 0x0078,
+	0x552f, 0x0e7e, 0x2071, 0x6d00, 0x7544, 0xa582, 0x0001, 0x0048,
+	0x5567, 0x7048, 0x2060, 0x6000, 0xa086, 0x0000, 0x0040, 0x5554,
+	0xace0, 0x0008, 0x7054, 0xac02, 0x00c8, 0x5550, 0x0078, 0x5543,
+	0x2061, 0x7400, 0x0078, 0x5543, 0x6003, 0x0008, 0x8529, 0x7546,
+	0xaca8, 0x0008, 0x7054, 0xa502, 0x00c8, 0x5563, 0x754a, 0xa085,
+	0x0001, 0x0e7f, 0x007c, 0x704b, 0x7400, 0x0078, 0x555f, 0xa006,
+	0x0078, 0x5561, 0xac82, 0x7400, 0x1048, 0x12b7, 0x2001, 0x6d15,
+	0x2004, 0xac02, 0x10c8, 0x12b7, 0xa006, 0x6006, 0x600a, 0x600e,
+	0x6012, 0x6016, 0x601a, 0x601f, 0x0000, 0x6003, 0x0000, 0x2061,
+	0x6d00, 0x6044, 0x8000, 0x6046, 0xa086, 0x0001, 0x0040, 0x5589,
+	0x007c, 0x127e, 0x2091, 0x8000, 0x1078, 0x476a, 0x127f, 0x0078,
+	0x5588, 0x601c, 0xa084, 0x000f, 0x0079, 0x5596, 0x559f, 0x55a7,
+	0x55c3, 0x55df, 0x629a, 0x62b6, 0x62d2, 0x559f, 0x55a7, 0xa18e,
+	0x0047, 0x00c0, 0x55a6, 0xa016, 0x1078, 0x1532, 0x007c, 0x067e,
+	0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12b7, 0x1079, 0x55b1, 0x067f,
+	0x007c, 0x55c1, 0x5698, 0x5792, 0x55c1, 0x57d7, 0x55c1, 0x55c1,
+	0x55c1, 0x5653, 0x5a4d, 0x55c1, 0x55c1, 0x55c1, 0x55c1, 0x55c1,
+	0x55c1, 0x1078, 0x12b7, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8,
+	0x12b7, 0x1079, 0x55cd, 0x067f, 0x007c, 0x55dd, 0x55dd, 0x55dd,
+	0x55dd, 0x55dd, 0x55dd, 0x55dd, 0x55dd, 0x5e10, 0x5edd, 0x55dd,
+	0x5e29, 0x5e8f, 0x5e29, 0x5e8f, 0x55dd, 0x1078, 0x12b7, 0x067e,
+	0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12b7, 0x1079, 0x55e9, 0x067f,
+	0x007c, 0x55f9, 0x5a96, 0x5b05, 0x5bbb, 0x5cd2, 0x55f9, 0x55f9,
+	0x55f9, 0x5a75, 0x5dc6, 0x5dca, 0x55f9, 0x55f9, 0x55f9, 0x55f9,
+	0x5df0, 0x1078, 0x12b7, 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, 0x5609, 0x0e7e, 0x6010, 0x2070,
+	0x7007, 0x0000, 0x7037, 0x0103, 0x0e7f, 0x1078, 0x556a, 0x007c,
+	0x0d7e, 0x037e, 0x7330, 0xa386, 0x0200, 0x00c0, 0x562d, 0x6018,
+	0x2068, 0x6813, 0x00ff, 0x6817, 0xfffd, 0x6010, 0xa005, 0x0040,
+	0x5637, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6b32, 0x1078,
+	0x556a, 0x037f, 0x0d7f, 0x007c, 0x0d7e, 0x20a9, 0x000e, 0x2e98,
+	0x6010, 0x20a0, 0x53a3, 0xa1b6, 0x0015, 0x00c0, 0x5650, 0x6018,
+	0x2068, 0x7038, 0x680a, 0x703c, 0x680e, 0x6800, 0xc08d, 0x6802,
+	0x0d7f, 0x0078, 0x5615, 0x2100, 0xa1b2, 0x0024, 0x10c8, 0x12b7,
+	0x0079, 0x565a, 0x5680, 0x568c, 0x5680, 0x5680, 0x5680, 0x5680,
+	0x567e, 0x567e, 0x567e, 0x567e, 0x567e, 0x567e, 0x567e, 0x567e,
+	0x567e, 0x567e, 0x567e, 0x567e, 0x567e, 0x567e, 0x567e, 0x567e,
+	0x567e, 0x567e, 0x567e, 0x567e, 0x567e, 0x567e, 0x567e, 0x567e,
+	0x567e, 0x5680, 0x567e, 0x5680, 0x5680, 0x567e, 0x1078, 0x12b7,
+	0x6003, 0x0001, 0x6106, 0x1078, 0x4376, 0x127e, 0x2091, 0x8000,
+	0x1078, 0x476a, 0x127f, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078,
+	0x4376, 0x127e, 0x2091, 0x8000, 0x1078, 0x476a, 0x127f, 0x007c,
+	0x6004, 0xa0b2, 0x0024, 0x10c8, 0x12b7, 0xa1b6, 0x0013, 0x00c0,
+	0x56a4, 0x2008, 0x0079, 0x5706, 0xa1b6, 0x0014, 0x00c0, 0x56fd,
+	0x1078, 0x4671, 0x6004, 0xa08e, 0x0000, 0x0040, 0x56fe, 0xa08e,
+	0x0002, 0x0040, 0x56c9, 0xa08e, 0x0003, 0x0040, 0x56c9, 0xa08e,
+	0x0004, 0x0040, 0x56c9, 0xa08e, 0x001f, 0x0040, 0x56fe, 0xa08e,
+	0x0021, 0x0040, 0x5702, 0xa08e, 0x0022, 0x0040, 0x56fe, 0x0078,
+	0x56f9, 0x1078, 0x206f, 0x2001, 0x0007, 0x1078, 0x33f3, 0x6018,
+	0xa080, 0x0028, 0x200c, 0x1078, 0x5778, 0xa186, 0x007e, 0x00c0,
+	0x56df, 0x2001, 0x6d2f, 0x2014, 0xa295, 0x0001, 0x2202, 0x017e,
+	0x027e, 0x037e, 0x2110, 0x2019, 0x0028, 0x1078, 0x445c, 0x1078,
+	0x43a9, 0x0c7e, 0x6018, 0xa065, 0x0040, 0x56f0, 0x1078, 0x35cf,
+	0x0c7f, 0x2c08, 0x1078, 0x6a57, 0x037f, 0x027f, 0x017f, 0x1078,
+	0x342f, 0x1078, 0x556a, 0x1078, 0x476a, 0x007c, 0x1078, 0x5778,
+	0x0078, 0x56f9, 0x1078, 0x5786, 0x0078, 0x56f9, 0x572c, 0x572e,
+	0x5732, 0x5736, 0x573a, 0x573e, 0x572a, 0x572a, 0x572a, 0x572a,
+	0x572a, 0x572a, 0x572a, 0x572a, 0x572a, 0x572a, 0x572a, 0x572a,
+	0x572a, 0x572a, 0x572a, 0x572a, 0x572a, 0x572a, 0x572a, 0x572a,
+	0x572a, 0x572a, 0x572a, 0x572a, 0x5742, 0x5748, 0x572a, 0x5752,
+	0x5748, 0x572a, 0x1078, 0x12b7, 0x0078, 0x5748, 0x2001, 0x000b,
+	0x0078, 0x575b, 0x2001, 0x0003, 0x0078, 0x575b, 0x2001, 0x0005,
+	0x0078, 0x575b, 0x2001, 0x0001, 0x0078, 0x575b, 0x2001, 0x0009,
+	0x0078, 0x575b, 0x1078, 0x12b7, 0x0078, 0x575a, 0x1078, 0x33f3,
+	0x1078, 0x4671, 0x6003, 0x0002, 0x6017, 0x0028, 0x1078, 0x476a,
+	0x0078, 0x575a, 0x1078, 0x4671, 0x6003, 0x0004, 0x6017, 0x0028,
+	0x1078, 0x476a, 0x007c, 0x1078, 0x33f3, 0x1078, 0x4671, 0x6003,
+	0x0002, 0x037e, 0x2019, 0x6d5c, 0x2304, 0xa084, 0xff00, 0x00c0,
+	0x576d, 0x2019, 0x0028, 0x0078, 0x5772, 0x8007, 0x8003, 0x801b,
+	0x831b, 0xa318, 0x6316, 0x037f, 0x1078, 0x476a, 0x0078, 0x575a,
+	0x0e7e, 0x6010, 0xa005, 0x0040, 0x5784, 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, 0x12b7, 0x6604, 0xa6b6, 0x001f,
+	0x00c0, 0x57a6, 0x1078, 0x55fb, 0x0078, 0x57c6, 0x6604, 0xa6b6,
+	0x0000, 0x00c0, 0x57af, 0x1078, 0x563c, 0x0078, 0x57c6, 0x6604,
+	0xa6b6, 0x0022, 0x00c0, 0x57b8, 0x1078, 0x5620, 0x0078, 0x57c6,
+	0xa1b6, 0x0015, 0x00c0, 0x57c0, 0x1079, 0x57cb, 0x0078, 0x57c6,
+	0xa1b6, 0x0016, 0x00c0, 0x57c7, 0x1079, 0x58f6, 0x007c, 0x1078,
+	0x559f, 0x0078, 0x57c6, 0x57ef, 0x57f2, 0x57ef, 0x5833, 0x57ef,
+	0x5892, 0x57ef, 0x57ef, 0x57ef, 0x58ce, 0x57ef, 0x58e4, 0xa1b6,
+	0x0048, 0x0040, 0x57e3, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10,
+	0x1078, 0x1532, 0x007c, 0x0e7e, 0xacf0, 0x0004, 0x2e74, 0x7000,
+	0x2070, 0x7037, 0x0103, 0x0e7f, 0x1078, 0x556a, 0x007c, 0x0005,
+	0x0005, 0x007c, 0x0e7e, 0x2071, 0x6d00, 0x7078, 0xa086, 0x0074,
+	0x00c0, 0x581c, 0x1078, 0x6a2b, 0x00c0, 0x580e, 0x0d7e, 0x6018,
+	0x2068, 0x1078, 0x5820, 0x0d7f, 0x2001, 0x0006, 0x1078, 0x33f3,
+	0x1078, 0x206f, 0x1078, 0x556a, 0x0078, 0x581e, 0x2001, 0x000a,
+	0x1078, 0x33f3, 0x1078, 0x206f, 0x6003, 0x0001, 0x6007, 0x0001,
+	0x1078, 0x4376, 0x0078, 0x581e, 0x1078, 0x5889, 0x0e7f, 0x007c,
+	0x6800, 0xd084, 0x0040, 0x5832, 0x2001, 0x0000, 0x1078, 0x33df,
+	0x2069, 0x6d51, 0x6804, 0xd0a4, 0x0040, 0x5832, 0x2001, 0x0006,
+	0x1078, 0x3401, 0x007c, 0x0d7e, 0x2011, 0x6d1e, 0x2204, 0xa086,
+	0x0074, 0x00c0, 0x5885, 0x1078, 0x599f, 0x6018, 0x2068, 0xa080,
+	0x0028, 0x2014, 0xa286, 0x007e, 0x0040, 0x5850, 0xa286, 0x0080,
+	0x00c0, 0x5879, 0x6813, 0x00ff, 0x6817, 0xfffc, 0x0078, 0x586f,
+	0x0e7e, 0x0f7e, 0x6813, 0x00ff, 0x6817, 0xfffe, 0x2071, 0x6d2f,
+	0x2e04, 0xa085, 0x0003, 0x2072, 0x2071, 0x7280, 0x2079, 0x0100,
+	0x2e04, 0xa084, 0x00ff, 0x2069, 0x6d19, 0x206a, 0x78e6, 0x8e70,
+	0x2e04, 0x2069, 0x6d1a, 0x206a, 0x78ea, 0x0f7f, 0x0e7f, 0x2001,
+	0x0006, 0x1078, 0x33f3, 0x1078, 0x206f, 0x1078, 0x556a, 0x0078,
+	0x5887, 0x2001, 0x0004, 0x1078, 0x33f3, 0x6003, 0x0001, 0x6007,
+	0x0003, 0x1078, 0x4376, 0x0078, 0x5887, 0x1078, 0x5889, 0x0d7f,
+	0x007c, 0x2001, 0x0007, 0x1078, 0x33f3, 0x1078, 0x206f, 0x1078,
+	0x556a, 0x007c, 0x0e7e, 0x2071, 0x6d00, 0x7078, 0xa086, 0x0014,
+	0x00c0, 0x58c8, 0x7000, 0xa086, 0x0003, 0x00c0, 0x58a5, 0x6010,
+	0xa005, 0x00c0, 0x58a5, 0x1078, 0x2ad1, 0x0d7e, 0x6018, 0x2068,
+	0x1078, 0x34ca, 0x1078, 0x5820, 0x0d7f, 0x1078, 0x59a9, 0x00c0,
+	0x58c8, 0x2001, 0x0006, 0x1078, 0x33f3, 0x0e7e, 0x6010, 0xa005,
+	0x0040, 0x58c1, 0x2070, 0x7007, 0x0000, 0x7037, 0x0103, 0x7033,
+	0x0200, 0x0e7f, 0x1078, 0x206f, 0x1078, 0x556a, 0x0078, 0x58cc,
+	0x1078, 0x5778, 0x1078, 0x5889, 0x0e7f, 0x007c, 0x2011, 0x6d1e,
+	0x2204, 0xa086, 0x0014, 0x00c0, 0x58e1, 0x2001, 0x0002, 0x1078,
+	0x33f3, 0x6003, 0x0001, 0x6007, 0x0001, 0x1078, 0x4376, 0x0078,
+	0x58e3, 0x1078, 0x5889, 0x007c, 0x2011, 0x6d1e, 0x2204, 0xa086,
+	0x0004, 0x00c0, 0x58f3, 0x2001, 0x0007, 0x1078, 0x33f3, 0x1078,
+	0x556a, 0x0078, 0x58f5, 0x1078, 0x5889, 0x007c, 0x57ef, 0x5902,
+	0x57ef, 0x5928, 0x57ef, 0x5952, 0x57ef, 0x57ef, 0x57ef, 0x5967,
+	0x57ef, 0x597a, 0x0c7e, 0x1078, 0x598d, 0x00c0, 0x5917, 0x2001,
+	0x0000, 0x1078, 0x33df, 0x2001, 0x0002, 0x1078, 0x33f3, 0x6003,
+	0x0001, 0x6007, 0x0002, 0x1078, 0x4376, 0x0078, 0x5926, 0x2009,
+	0x728f, 0x2104, 0xa084, 0xff00, 0xa086, 0x1900, 0x00c0, 0x5924,
+	0x1078, 0x556a, 0x0078, 0x5926, 0x1078, 0x5889, 0x0c7f, 0x007c,
+	0x1078, 0x599c, 0x00c0, 0x593c, 0x2001, 0x0000, 0x1078, 0x33df,
+	0x2001, 0x0002, 0x1078, 0x33f3, 0x6003, 0x0001, 0x6007, 0x0002,
+	0x1078, 0x4376, 0x0078, 0x5951, 0x1078, 0x5778, 0x2009, 0x728f,
+	0x2104, 0xa084, 0xff00, 0xa086, 0x1900, 0x00c0, 0x594f, 0x2001,
+	0x0004, 0x1078, 0x33f3, 0x1078, 0x556a, 0x0078, 0x5951, 0x1078,
+	0x5889, 0x007c, 0x1078, 0x599c, 0x00c0, 0x5962, 0x2001, 0x0004,
+	0x1078, 0x33f3, 0x6003, 0x0001, 0x6007, 0x0003, 0x1078, 0x4376,
+	0x0078, 0x5966, 0x1078, 0x5778, 0x1078, 0x5889, 0x007c, 0x1078,
+	0x599c, 0x00c0, 0x5977, 0x2001, 0x0008, 0x1078, 0x33f3, 0x6003,
+	0x0001, 0x6007, 0x0005, 0x1078, 0x4376, 0x0078, 0x5979, 0x1078,
+	0x5889, 0x007c, 0x1078, 0x599c, 0x00c0, 0x598a, 0x2001, 0x000a,
+	0x1078, 0x33f3, 0x6003, 0x0001, 0x6007, 0x0001, 0x1078, 0x4376,
+	0x0078, 0x598c, 0x1078, 0x5889, 0x007c, 0x2009, 0x728e, 0x2104,
+	0xa086, 0x0003, 0x00c0, 0x599b, 0x2009, 0x728f, 0x2104, 0xa084,
+	0xff00, 0xa086, 0x2a00, 0x007c, 0xa085, 0x0001, 0x007c, 0x0c7e,
+	0x017e, 0xac88, 0x0006, 0x2164, 0x1078, 0x3459, 0x017f, 0x0c7f,
+	0x007c, 0x0e7e, 0x2071, 0x728c, 0x7004, 0xa086, 0x0014, 0x00c0,
+	0x59cc, 0x7008, 0xa086, 0x0800, 0x00c0, 0x59cc, 0x700c, 0xd0ec,
+	0x0040, 0x59ca, 0xa084, 0x0f00, 0xa086, 0x0100, 0x00c0, 0x59ca,
+	0x7024, 0xd0a4, 0x0040, 0x59ca, 0xd08c, 0x0040, 0x59ca, 0xa006,
+	0x0078, 0x59cc, 0xa085, 0x0001, 0x0e7f, 0x007c, 0x0e7e, 0x0d7e,
+	0x0c7e, 0x077e, 0x057e, 0x047e, 0x027e, 0x007e, 0x127e, 0x2091,
+	0x8000, 0x2029, 0x6f19, 0x252c, 0x2021, 0x6f1f, 0x2424, 0x2061,
+	0x7400, 0x2071, 0x6d00, 0x7244, 0x7060, 0xa202, 0x00c8, 0x5a23,
+	0x1078, 0x6c0f, 0x0040, 0x5a1b, 0x671c, 0xa786, 0x0001, 0x0040,
+	0x5a1b, 0xa786, 0x0007, 0x0040, 0x5a1b, 0x2500, 0xac06, 0x0040,
+	0x5a1b, 0x2400, 0xac06, 0x0040, 0x5a1b, 0x0c7e, 0x6010, 0x2068,
+	0x1078, 0x6120, 0x0040, 0x5a11, 0xa786, 0x0003, 0x00c0, 0x5a2d,
+	0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x36a1, 0x1078,
+	0x6276, 0x6000, 0xa086, 0x0004, 0x00c0, 0x5a18, 0x1078, 0x15f2,
+	0x1078, 0x6283, 0x0c7f, 0xace0, 0x0008, 0x7054, 0xac02, 0x00c8,
+	0x5a23, 0x0078, 0x59e3, 0x127f, 0x007f, 0x027f, 0x047f, 0x057f,
+	0x077f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0xa786, 0x0006, 0x00c0,
+	0x5a08, 0x1078, 0x6bb3, 0x0078, 0x5a11, 0x220c, 0x2304, 0xa106,
+	0x00c0, 0x5a40, 0x8210, 0x8318, 0x00f0, 0x5a35, 0xa006, 0x007c,
+	0x2304, 0xa102, 0x0048, 0x5a48, 0x2001, 0x0001, 0x0078, 0x5a4a,
+	0x2001, 0x0000, 0xa18d, 0x0001, 0x007c, 0x6004, 0xa08a, 0x0024,
+	0x10c8, 0x12b7, 0xa08e, 0x0000, 0x0040, 0x5a71, 0xa08e, 0x0002,
+	0x0040, 0x5a68, 0xa08e, 0x0003, 0x0040, 0x5a68, 0xa08e, 0x0004,
+	0x0040, 0x5a68, 0xa08e, 0x001f, 0x0040, 0x5a71, 0x0078, 0x5a6a,
+	0x1078, 0x206f, 0x1078, 0x4671, 0x1078, 0x556a, 0x1078, 0x476a,
+	0x007c, 0x1078, 0x5778, 0x0078, 0x5a6a, 0xa182, 0x0040, 0x0079,
+	0x5a79, 0x5a88, 0x5a88, 0x5a88, 0x5a88, 0x5a88, 0x5a88, 0x5a88,
+	0x5a88, 0x5a88, 0x5a88, 0x5a88, 0x5a8a, 0x5a8a, 0x5a8a, 0x5a8a,
+	0x1078, 0x12b7, 0x6003, 0x0001, 0x6106, 0x1078, 0x4327, 0x127e,
+	0x2091, 0x8000, 0x1078, 0x476a, 0x127f, 0x007c, 0xa186, 0x0013,
+	0x00c0, 0x5a9f, 0x6004, 0xa082, 0x0040, 0x0079, 0x5adf, 0xa186,
+	0x0014, 0x10c0, 0x12b7, 0x6004, 0xa082, 0x0040, 0x0079, 0x5aa8,
+	0x5ab9, 0x5ab7, 0x5ab7, 0x5ab7, 0x5ab7, 0x5ab7, 0x5ab7, 0x5ab7,
+	0x5ab7, 0x5ab7, 0x5ab7, 0x5ad4, 0x5ad4, 0x5ad4, 0x5ad4, 0x1078,
+	0x12b7, 0x2001, 0x0007, 0x1078, 0x33f3, 0x1078, 0x4671, 0x0d7e,
+	0x6110, 0x2168, 0x1078, 0x6120, 0x0040, 0x5ace, 0x6837, 0x0103,
+	0x684b, 0x0028, 0x1078, 0x36a1, 0x1078, 0x6276, 0x0d7f, 0x1078,
+	0x556a, 0x1078, 0x476a, 0x007c, 0x2001, 0x0007, 0x1078, 0x33f3,
+	0x1078, 0x4671, 0x1078, 0x556a, 0x1078, 0x476a, 0x007c, 0x5af0,
+	0x5aee, 0x5aee, 0x5aee, 0x5aee, 0x5aee, 0x5aee, 0x5aee, 0x5aee,
+	0x5aee, 0x5aee, 0x5afe, 0x5afe, 0x5afe, 0x5afe, 0x1078, 0x12b7,
+	0x1078, 0x4671, 0x6003, 0x0002, 0x1078, 0x476a, 0x6010, 0xa088,
+	0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x007c, 0x1078, 0x4671,
+	0x6003, 0x000f, 0x1078, 0x476a, 0x007c, 0xa182, 0x0040, 0x0079,
+	0x5b09, 0x5b18, 0x5b18, 0x5b18, 0x5b18, 0x5b18, 0x5b1a, 0x5b98,
+	0x5bb0, 0x5b18, 0x5b18, 0x5b18, 0x5b18, 0x5b18, 0x5b18, 0x5b18,
+	0x1078, 0x12b7, 0x0e7e, 0x0d7e, 0x2071, 0x728c, 0x6110, 0x2168,
+	0x7614, 0xa6b4, 0x0fff, 0x86ff, 0x0040, 0x5b87, 0xa68c, 0x00ff,
+	0xa186, 0x0002, 0x0040, 0x5b4c, 0xa186, 0x0028, 0x00c0, 0x5b36,
+	0x1078, 0x628a, 0x684b, 0x001c, 0x0078, 0x5b4e, 0xd6dc, 0x0040,
+	0x5b41, 0x684b, 0x0015, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0x0078,
+	0x5b4e, 0xd6d4, 0x0040, 0x5b4c, 0x684b, 0x0007, 0x7318, 0x6b62,
+	0x731c, 0x6b5e, 0x0078, 0x5b4e, 0x684b, 0x0000, 0x6837, 0x0103,
+	0x6e46, 0xa01e, 0xd6c4, 0x0040, 0x5b61, 0x7328, 0x732c, 0x6b56,
+	0x037e, 0x2308, 0x2019, 0x7298, 0xad90, 0x0019, 0x1078, 0x5f4c,
+	0x037f, 0xd6cc, 0x0040, 0x5b8c, 0x7124, 0x695a, 0xa192, 0x0021,
+	0x00c8, 0x5b75, 0x2071, 0x7298, 0x831c, 0x2300, 0xae18, 0xad90,
+	0x001d, 0x1078, 0x5f4c, 0x0078, 0x5b8c, 0x6838, 0xd0fc, 0x0040,
+	0x5b7e, 0x2009, 0x0020, 0x695a, 0x0078, 0x5b6a, 0x0f7e, 0x2d78,
+	0x1078, 0x5ee4, 0x0f7f, 0x1078, 0x5f39, 0x0078, 0x5b8e, 0x684b,
+	0x0000, 0x6837, 0x0103, 0x6e46, 0x1078, 0x36a1, 0x6218, 0x2268,
+	0x6a3c, 0x8211, 0x6a3e, 0x0d7f, 0x0e7f, 0x1078, 0x556a, 0x007c,
+	0x0f7e, 0x6003, 0x0003, 0x2079, 0x728c, 0x7c04, 0x7b00, 0x7e0c,
+	0x7d08, 0x6010, 0x2078, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x0f7f,
+	0x2c10, 0x1078, 0x17de, 0x1078, 0x4395, 0x1078, 0x4821, 0x007c,
+	0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10,
+	0x1078, 0x1532, 0x007c, 0xa182, 0x0040, 0x0079, 0x5bbf, 0x5bce,
+	0x5bce, 0x5bce, 0x5bce, 0x5bce, 0x5bd0, 0x5c5e, 0x5bce, 0x5bce,
+	0x5c74, 0x5cb4, 0x5bce, 0x5bce, 0x5bce, 0x5bce, 0x1078, 0x12b7,
+	0x077e, 0x0f7e, 0x0e7e, 0x0d7e, 0x2071, 0x728c, 0x6110, 0x2178,
+	0x7614, 0xa6b4, 0x0fff, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218,
+	0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x86ff, 0x0040, 0x5c59, 0xa694,
+	0xff00, 0xa284, 0x0c00, 0x0040, 0x5bf1, 0x7018, 0x7862, 0x701c,
+	0x785e, 0xa284, 0x0300, 0x0040, 0x5c59, 0x1078, 0x130f, 0x1040,
+	0x12b7, 0x2d00, 0x784a, 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, 0x0103,
+	0x7838, 0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c,
+	0x00ff, 0xa186, 0x0002, 0x0040, 0x5c2b, 0xa186, 0x0028, 0x00c0,
+	0x5c15, 0x684b, 0x001c, 0x0078, 0x5c2d, 0xd6dc, 0x0040, 0x5c20,
+	0x684b, 0x0015, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0x0078, 0x5c2d,
+	0xd6d4, 0x0040, 0x5c2b, 0x684b, 0x0007, 0x7318, 0x6b62, 0x731c,
+	0x6b5e, 0x0078, 0x5c2d, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852,
+	0x7854, 0x6856, 0xa01e, 0xd6c4, 0x0040, 0x5c42, 0x7328, 0x732c,
+	0x6b56, 0x037e, 0x2308, 0x2019, 0x7298, 0xad90, 0x0019, 0x1078,
+	0x5f4c, 0x037f, 0xd6cc, 0x0040, 0x5c59, 0x7124, 0x695a, 0xa192,
+	0x0021, 0x00c8, 0x5c56, 0x2071, 0x7298, 0x831c, 0x2300, 0xae18,
+	0xad90, 0x001d, 0x1078, 0x5f4c, 0x0078, 0x5c59, 0x2d78, 0x1078,
+	0x5ee4, 0x0d7f, 0x0e7f, 0x0f7f, 0x077f, 0x007c, 0x0f7e, 0x6003,
+	0x0003, 0x2079, 0x728c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010,
+	0x2078, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x0f7f, 0x2c10, 0x1078,
+	0x17de, 0x1078, 0x4fca, 0x007c, 0x0d7e, 0x6003, 0x0002, 0x1078,
+	0x4719, 0x1078, 0x4821, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0040,
+	0x5cb2, 0xd1cc, 0x0040, 0x5c8d, 0x6948, 0x017e, 0x1078, 0x1338,
+	0x0d7f, 0x1078, 0x5f39, 0x0078, 0x5cb0, 0x6837, 0x0103, 0x6944,
+	0xa184, 0x00ff, 0xa186, 0x0002, 0x0040, 0x5cac, 0xa086, 0x0028,
+	0x00c0, 0x5c9e, 0x684b, 0x001c, 0x0078, 0x5cae, 0xd1dc, 0x0040,
+	0x5ca5, 0x684b, 0x0015, 0x0078, 0x5cae, 0xd1d4, 0x0040, 0x5cac,
+	0x684b, 0x0007, 0x0078, 0x5cae, 0x684b, 0x0000, 0x1078, 0x36a1,
+	0x1078, 0x556a, 0x0d7f, 0x007c, 0x2001, 0x0007, 0x1078, 0x33f3,
+	0x1078, 0x4719, 0x0f7e, 0x0d7e, 0x6110, 0x2178, 0x1078, 0x6120,
+	0x0040, 0x5ccb, 0x7837, 0x0103, 0x784b, 0x0028, 0x2f68, 0x1078,
+	0x36a1, 0x1078, 0x6276, 0x0d7f, 0x0f7f, 0x1078, 0x556a, 0x1078,
+	0x4821, 0x007c, 0xa182, 0x0040, 0x0079, 0x5cd6, 0x5ce5, 0x5ce5,
+	0x5ce5, 0x5ce5, 0x5ce5, 0x5ce7, 0x5ce5, 0x5d82, 0x5d8a, 0x5ce5,
+	0x5ce5, 0x5ce5, 0x5ce5, 0x5ce5, 0x5ce5, 0x1078, 0x12b7, 0x077e,
+	0x0f7e, 0x0e7e, 0x0d7e, 0x2071, 0x728c, 0x6110, 0x2178, 0x7614,
+	0xa6b4, 0x0fff, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268,
+	0x6a3c, 0x8211, 0x6a3e, 0x86ff, 0x0040, 0x5d74, 0xa694, 0xff00,
+	0xa284, 0x0c00, 0x0040, 0x5d08, 0x7018, 0x7862, 0x701c, 0x785e,
+	0xa284, 0x0300, 0x0040, 0x5d71, 0x1078, 0x130f, 0x1040, 0x12b7,
+	0x2d00, 0x784a, 0x7f4c, 0xa7bd, 0x0200, 0x7f4e, 0x6837, 0x0103,
+	0x7838, 0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c,
+	0x00ff, 0xa186, 0x0002, 0x0040, 0x5d43, 0xa186, 0x0028, 0x00c0,
+	0x5d2d, 0x684b, 0x001c, 0x0078, 0x5d45, 0xd6dc, 0x0040, 0x5d38,
+	0x684b, 0x0015, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0x0078, 0x5d45,
+	0xd6d4, 0x0040, 0x5d43, 0x684b, 0x0007, 0x7318, 0x6b62, 0x731c,
+	0x6b5e, 0x0078, 0x5d45, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852,
+	0x7854, 0x6856, 0xa01e, 0xd6c4, 0x0040, 0x5d5a, 0x7328, 0x732c,
+	0x6b56, 0x037e, 0x2308, 0x2019, 0x7298, 0xad90, 0x0019, 0x1078,
+	0x5f4c, 0x037f, 0xd6cc, 0x0040, 0x5d71, 0x7124, 0x695a, 0xa192,
+	0x0021, 0x00c8, 0x5d6e, 0x2071, 0x7298, 0x831c, 0x2300, 0xae18,
+	0xad90, 0x001d, 0x1078, 0x5f4c, 0x0078, 0x5d71, 0x2d78, 0x1078,
+	0x5ee4, 0xd6dc, 0x00c0, 0x5d77, 0xa006, 0x0078, 0x5d7b, 0x2001,
+	0x0001, 0x7218, 0x731c, 0x1078, 0x156f, 0x0d7f, 0x0e7f, 0x0f7f,
+	0x077f, 0x007c, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078,
+	0x1532, 0x007c, 0x0d7e, 0x6003, 0x0002, 0x6110, 0x2168, 0x694c,
+	0xd1e4, 0x0040, 0x5dc4, 0xd1cc, 0x0040, 0x5d9f, 0x6948, 0x017e,
+	0x1078, 0x1338, 0x0d7f, 0x1078, 0x5f39, 0x0078, 0x5dc2, 0x6837,
+	0x0103, 0x6944, 0xa184, 0x00ff, 0xa186, 0x0002, 0x0040, 0x5dbe,
+	0xa086, 0x0028, 0x00c0, 0x5db0, 0x684b, 0x001c, 0x0078, 0x5dc0,
+	0xd1dc, 0x0040, 0x5db7, 0x684b, 0x0015, 0x0078, 0x5dc0, 0xd1d4,
+	0x0040, 0x5dbe, 0x684b, 0x0007, 0x0078, 0x5dc0, 0x684b, 0x0000,
+	0x1078, 0x36a1, 0x1078, 0x556a, 0x0d7f, 0x007c, 0x1078, 0x4671,
+	0x0078, 0x5dcc, 0x1078, 0x4719, 0x1078, 0x6120, 0x0040, 0x5de3,
+	0x0d7e, 0x6110, 0x2168, 0x6837, 0x0103, 0x2009, 0x6d0c, 0x210c,
+	0xd18c, 0x00c0, 0x5dec, 0xd184, 0x00c0, 0x5de8, 0x6108, 0x694a,
+	0x1078, 0x36a1, 0x0d7f, 0x1078, 0x556a, 0x1078, 0x476a, 0x007c,
+	0x684b, 0x0004, 0x0078, 0x5de0, 0x684b, 0x0004, 0x0078, 0x5de0,
+	0xa182, 0x0040, 0x0079, 0x5df4, 0x5e03, 0x5e03, 0x5e03, 0x5e03,
+	0x5e03, 0x5e05, 0x5e03, 0x5e08, 0x5e03, 0x5e03, 0x5e03, 0x5e03,
+	0x5e03, 0x5e03, 0x5e03, 0x1078, 0x12b7, 0x1078, 0x556a, 0x007c,
+	0x007e, 0x027e, 0xa016, 0x1078, 0x1532, 0x027f, 0x007f, 0x007c,
+	0xa182, 0x0025, 0x0079, 0x5e14, 0x5e1d, 0x5e1b, 0x5e1b, 0x5e1b,
+	0x5e1b, 0x5e1b, 0x5e1b, 0x1078, 0x12b7, 0x6003, 0x0001, 0x6106,
+	0x1078, 0x4327, 0x127e, 0x2091, 0x8000, 0x1078, 0x476a, 0x127f,
+	0x007c, 0xa186, 0x0013, 0x00c0, 0x5e33, 0x6004, 0xa082, 0x0025,
+	0x2008, 0x0079, 0x5e74, 0xa186, 0x0014, 0x00c0, 0x5e70, 0x1078,
+	0x4671, 0x2001, 0x0007, 0x1078, 0x33f3, 0x6018, 0xa080, 0x0028,
+	0x200c, 0x017e, 0x027e, 0x037e, 0x2110, 0x2019, 0x0028, 0x1078,
+	0x445c, 0x1078, 0x43a9, 0x0c7e, 0x6018, 0xa065, 0x0040, 0x5e52,
+	0x1078, 0x35cf, 0x0c7f, 0x2c08, 0x1078, 0x6a57, 0x037f, 0x027f,
+	0x017f, 0x1078, 0x342f, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x6120,
+	0x0040, 0x5e6a, 0x6837, 0x0103, 0x684b, 0x0006, 0x1078, 0x36a1,
+	0x1078, 0x6276, 0x0d7f, 0x1078, 0x556a, 0x1078, 0x476a, 0x007c,
+	0x1078, 0x559f, 0x0078, 0x5e6f, 0x5e7d, 0x5e7b, 0x5e7b, 0x5e7b,
+	0x5e7b, 0x5e7b, 0x5e86, 0x1078, 0x12b7, 0x1078, 0x4671, 0x6017,
+	0x0014, 0x6003, 0x000c, 0x1078, 0x476a, 0x007c, 0x1078, 0x4671,
+	0x6017, 0x0014, 0x6003, 0x000e, 0x1078, 0x476a, 0x007c, 0xa182,
+	0x002c, 0x00c8, 0x5e99, 0xa182, 0x0025, 0x0048, 0x5e99, 0x0079,
+	0x5e9c, 0x1078, 0x559f, 0x007c, 0x5ea3, 0x5ea3, 0x5ea3, 0x5ea3,
+	0x5ea5, 0x5ebf, 0x5ea3, 0x1078, 0x12b7, 0x0d7e, 0x1078, 0x6276,
+	0x6010, 0x2068, 0x6837, 0x0103, 0x6850, 0xa084, 0x0040, 0x0040,
+	0x5eb5, 0x684b, 0x0006, 0x0078, 0x5eb7, 0x684b, 0x0005, 0x6847,
+	0x0000, 0x1078, 0x36a1, 0x1078, 0x556a, 0x0d7f, 0x007c, 0x0d7e,
+	0x6010, 0x2068, 0x1078, 0x6120, 0x0040, 0x5ed9, 0x6837, 0x0103,
+	0x6850, 0xa084, 0x0040, 0x0040, 0x5ed1, 0x684b, 0x0006, 0x0078,
+	0x5ed3, 0x684b, 0x0005, 0x6847, 0x0000, 0x1078, 0x36a1, 0x1078,
+	0x6276, 0x0d7f, 0x1078, 0x556a, 0x007c, 0x1078, 0x4671, 0x1078,
+	0x556a, 0x1078, 0x476a, 0x007c, 0x057e, 0x067e, 0x0d7e, 0x0f7e,
+	0x2029, 0x0001, 0xa182, 0x0101, 0x00c8, 0x5ef0, 0x0078, 0x5ef2,
+	0x2009, 0x0100, 0x2130, 0x2069, 0x7298, 0x831c, 0x2300, 0xad18,
+	0x2009, 0x0020, 0xaf90, 0x001d, 0x1078, 0x5f4c, 0xa6b2, 0x0020,
+	0x7804, 0xa06d, 0x0040, 0x5f06, 0x1078, 0x1338, 0x1078, 0x130f,
+	0x0040, 0x5f30, 0x8528, 0x6837, 0x0110, 0x683b, 0x0000, 0x2d20,
+	0x7c06, 0xa68a, 0x003d, 0x00c8, 0x5f1c, 0x2608, 0xad90, 0x000f,
+	0x1078, 0x5f4c, 0x0078, 0x5f30, 0xa6b2, 0x003c, 0x2009, 0x003c,
+	0x2d78, 0xad90, 0x000f, 0x1078, 0x5f4c, 0x0078, 0x5f06, 0x0f7f,
+	0x852f, 0xa5ad, 0x0003, 0x7d36, 0xa5ac, 0x0000, 0x0078, 0x5f35,
+	0x0f7f, 0x852f, 0xa5ad, 0x0003, 0x7d36, 0x0d7f, 0x067f, 0x057f,
+	0x007c, 0x0f7e, 0x8dff, 0x0040, 0x5f4a, 0x6804, 0xa07d, 0x0040,
+	0x5f48, 0x6807, 0x0000, 0x1078, 0x36a1, 0x2f68, 0x0078, 0x5f3d,
+	0x1078, 0x36a1, 0x0f7f, 0x007c, 0x157e, 0xa184, 0x0001, 0x0040,
+	0x5f52, 0x8108, 0x810c, 0x21a8, 0x2304, 0x8007, 0x2012, 0x8318,
+	0x8210, 0x00f0, 0x5f54, 0x157f, 0x007c, 0x127e, 0x2091, 0x8000,
+	0x601c, 0xa084, 0x000f, 0x1079, 0x5f67, 0x127f, 0x007c, 0x5f76,
+	0x5f6f, 0x5f71, 0x5f8d, 0x5f6f, 0x5f71, 0x5f71, 0x5f71, 0x1078,
+	0x12b7, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c, 0x0d7e, 0x6010,
+	0x2068, 0x1078, 0x6120, 0x0040, 0x5f8a, 0xa00e, 0x2001, 0x0005,
+	0x1078, 0x372d, 0x1078, 0x36a1, 0x1078, 0x556a, 0xa085, 0x0001,
+	0x0d7f, 0x007c, 0xa006, 0x0078, 0x5f88, 0x6000, 0xa08a, 0x0010,
+	0x10c8, 0x12b7, 0x1079, 0x5f95, 0x007c, 0x5fa5, 0x5fc4, 0x5fa7,
+	0x5fd5, 0x5fc0, 0x5fa5, 0x5f71, 0x5f76, 0x5f76, 0x5f71, 0x5f71,
+	0x5f71, 0x5f71, 0x5f71, 0x5f71, 0x5f71, 0x1078, 0x12b7, 0x0d7e,
+	0x6010, 0x2068, 0x1078, 0x6120, 0x0040, 0x5fb2, 0x6850, 0xa085,
+	0x0005, 0x6852, 0x0d7f, 0x6007, 0x0025, 0x6003, 0x000b, 0x601f,
+	0x0002, 0x1078, 0x4327, 0x1078, 0x476a, 0xa085, 0x0001, 0x007c,
+	0x1078, 0x15f2, 0x0078, 0x5fa7, 0x0e7e, 0x2071, 0x6f10, 0x7024,
+	0xac06, 0x00c0, 0x5fcd, 0x1078, 0x5148, 0x1078, 0x5083, 0x0e7f,
+	0x00c0, 0x5fa7, 0x1078, 0x5f71, 0x007c, 0x037e, 0x0e7e, 0x2071,
+	0x6f10, 0x703c, 0xac06, 0x00c0, 0x5fe1, 0x2019, 0x0000, 0x1078,
+	0x51da, 0x1078, 0x54b6, 0x0e7f, 0x037f, 0x00c0, 0x5fa7, 0x1078,
+	0x5f71, 0x007c, 0x0c7e, 0x601c, 0xa084, 0x000f, 0x1079, 0x5ff2,
+	0x0c7f, 0x007c, 0x5ffb, 0x605b, 0x60c8, 0x5fff, 0x5ffb, 0x5ffb,
+	0x5ffb, 0x556a, 0x605b, 0x007c, 0x6017, 0x0001, 0x007c, 0x6000,
+	0xa08a, 0x0010, 0x10c8, 0x12b7, 0x1079, 0x6007, 0x007c, 0x6017,
+	0x6019, 0x603a, 0x604d, 0x604d, 0x6017, 0x5ffb, 0x5ffb, 0x5ffb,
+	0x604d, 0x604d, 0x6017, 0x6017, 0x6017, 0x6017, 0x6058, 0x1078,
+	0x12b7, 0x0e7e, 0x6010, 0x2070, 0x7050, 0xa085, 0x0040, 0x7052,
+	0x2071, 0x6f10, 0x7024, 0xac06, 0x0040, 0x6036, 0x1078, 0x5083,
+	0x6007, 0x0025, 0x6003, 0x000b, 0x601f, 0x0002, 0x6017, 0x0014,
+	0x1078, 0x4327, 0x1078, 0x476a, 0x0e7f, 0x007c, 0x6017, 0x0001,
+	0x0078, 0x6034, 0x0d7e, 0x6010, 0x2068, 0x6850, 0xa085, 0x0040,
+	0x6852, 0x0d7f, 0x6007, 0x0025, 0x6003, 0x000b, 0x601f, 0x0002,
+	0x1078, 0x4327, 0x1078, 0x476a, 0x007c, 0x0d7e, 0x6017, 0x0001,
+	0x6010, 0x2068, 0x6850, 0xa085, 0x0040, 0x6852, 0x0d7f, 0x007c,
+	0x1078, 0x556a, 0x007c, 0x6000, 0xa08a, 0x0010, 0x10c8, 0x12b7,
+	0x1079, 0x6063, 0x007c, 0x6073, 0x5ffc, 0x6075, 0x6073, 0x6075,
+	0x6073, 0x6073, 0x6073, 0x5ffb, 0x5ffb, 0x6073, 0x6073, 0x6073,
+	0x6073, 0x6073, 0x6073, 0x1078, 0x12b7, 0x0d7e, 0x6018, 0x2068,
+	0x6804, 0xa084, 0x00ff, 0x0d7f, 0xa08a, 0x000c, 0x10c8, 0x12b7,
+	0x1079, 0x6083, 0x007c, 0x608f, 0x60b1, 0x608f, 0x60b1, 0x608f,
+	0x60b1, 0x6091, 0x609a, 0x608f, 0x60b1, 0x608f, 0x60aa, 0x1078,
+	0x12b7, 0x6004, 0xa08e, 0x0004, 0x0040, 0x60ac, 0xa08e, 0x0002,
+	0x0040, 0x60ac, 0xa08e, 0x0000, 0x0040, 0x60c0, 0xa08e, 0x001f,
+	0x0040, 0x60c0, 0xa08e, 0x0021, 0x0040, 0x60c4, 0xa08e, 0x0022,
+	0x0040, 0x60c0, 0x1078, 0x2051, 0x1078, 0x5778, 0x1078, 0x556a,
+	0x007c, 0x1078, 0x5778, 0x1078, 0x2051, 0x0e7e, 0x127e, 0x2091,
+	0x8000, 0x1078, 0x206f, 0x127f, 0x0e7f, 0x1078, 0x556a, 0x007c,
+	0x1078, 0x5778, 0x0078, 0x60ac, 0x1078, 0x5786, 0x0078, 0x60ac,
+	0x6000, 0xa08a, 0x0010, 0x10c8, 0x12b7, 0x1079, 0x60d0, 0x007c,
+	0x60e0, 0x60e0, 0x60e0, 0x60e0, 0x60e0, 0x60e0, 0x60e0, 0x60e0,
+	0x60e0, 0x5ffb, 0x60e0, 0x5ffc, 0x60e2, 0x5ffc, 0x60eb, 0x60e0,
+	0x1078, 0x12b7, 0x6007, 0x002b, 0x6003, 0x000d, 0x1078, 0x4327,
+	0x1078, 0x476a, 0x007c, 0x1078, 0x6276, 0x1078, 0x6120, 0x0040,
+	0x6109, 0x1078, 0x2051, 0x0d7e, 0x6010, 0x2068, 0x6837, 0x0103,
+	0x684b, 0x0006, 0x1078, 0x36a1, 0x0d7f, 0x601f, 0x0001, 0x6007,
+	0x0001, 0x6003, 0x0001, 0x1078, 0x4376, 0x1078, 0x476a, 0x0078,
+	0x610b, 0x1078, 0x556a, 0x007c, 0xa284, 0x0007, 0x00c0, 0x611d,
+	0xa282, 0x7400, 0x0048, 0x611d, 0x2001, 0x6d15, 0x2004, 0xa202,
+	0x00c8, 0x611d, 0xa085, 0x0001, 0x007c, 0xa006, 0x0078, 0x611c,
+	0x027e, 0x0e7e, 0x2071, 0x6d00, 0x6210, 0x7058, 0xa202, 0x0048,
+	0x6132, 0x705c, 0xa202, 0x00c8, 0x6132, 0xa085, 0x0001, 0x0e7f,
+	0x027f, 0x007c, 0xa006, 0x0078, 0x612f, 0x0e7e, 0x0c7e, 0x037e,
+	0x007e, 0x127e, 0x2091, 0x8000, 0x2061, 0x7400, 0x2071, 0x6d00,
+	0x7344, 0x7060, 0xa302, 0x00c8, 0x6155, 0x601c, 0xa206, 0x00c0,
+	0x614d, 0x0c7e, 0x1078, 0x556a, 0x0c7f, 0xace0, 0x0008, 0x7054,
+	0xac02, 0x00c8, 0x6155, 0x0078, 0x6140, 0x127f, 0x007f, 0x037f,
+	0x0c7f, 0x0e7f, 0x007c, 0x0e7e, 0x0c7e, 0x017e, 0x127e, 0x2091,
+	0x8000, 0xa188, 0x6e00, 0x210c, 0x81ff, 0x0040, 0x6182, 0x2061,
+	0x7400, 0x2071, 0x6d00, 0x7344, 0x7060, 0xa302, 0x00c8, 0x6182,
+	0x6018, 0xa106, 0x00c0, 0x617c, 0x1078, 0x2051, 0x017e, 0x0c7e,
+	0x1078, 0x556a, 0x0c7f, 0x017f, 0xace0, 0x0008, 0x7054, 0xac02,
+	0x0048, 0x6170, 0x127f, 0x017f, 0x0c7f, 0x0e7f, 0x007c, 0x0c7e,
+	0x057e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, 0x5504, 0x057f,
+	0x0040, 0x61a0, 0x6612, 0x651a, 0x601f, 0x0003, 0x2009, 0x004b,
+	0x1078, 0x5591, 0xa085, 0x0001, 0x127f, 0x057f, 0x0c7f, 0x007c,
+	0xa006, 0x0078, 0x619c, 0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000,
+	0x62a0, 0x0c7e, 0x1078, 0x5504, 0x057f, 0x0040, 0x61ca, 0x6013,
+	0x0000, 0x651a, 0x601f, 0x0003, 0x0c7e, 0x2560, 0x1078, 0x35cf,
+	0x0c7f, 0x1078, 0x445c, 0x1078, 0x43a9, 0x2c08, 0x1078, 0x6a57,
+	0x2009, 0x004c, 0x1078, 0x5591, 0xa085, 0x0001, 0x127f, 0x057f,
+	0x0c7f, 0x007c, 0xa006, 0x0078, 0x61c6, 0x0c7e, 0x057e, 0x127e,
+	0x2091, 0x8000, 0x62a0, 0x0c7e, 0x1078, 0x5504, 0x057f, 0x0040,
+	0x61f5, 0x6612, 0x651a, 0x601f, 0x0003, 0x2019, 0x0005, 0x0c7e,
+	0x2560, 0x1078, 0x35cf, 0x0c7f, 0x1078, 0x445c, 0x1078, 0x43a9,
+	0x2c08, 0x1078, 0x6a57, 0x2009, 0x004d, 0x1078, 0x5591, 0xa085,
+	0x0001, 0x127f, 0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x61f1,
+	0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000, 0x62a0, 0x0c7e, 0x1078,
+	0x5504, 0x057f, 0x0040, 0x6220, 0x6612, 0x651a, 0x601f, 0x0003,
+	0x2019, 0x0005, 0x0c7e, 0x2560, 0x1078, 0x35cf, 0x0c7f, 0x1078,
+	0x445c, 0x1078, 0x43a9, 0x2c08, 0x1078, 0x6a57, 0x2009, 0x004e,
+	0x1078, 0x5591, 0xa085, 0x0001, 0x127f, 0x057f, 0x0c7f, 0x007c,
+	0xa006, 0x0078, 0x621c, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e,
+	0x1078, 0x5504, 0x017f, 0x0040, 0x623c, 0x660a, 0x611a, 0x601f,
+	0x0001, 0x2d00, 0x6012, 0x2009, 0x001f, 0x1078, 0x5591, 0xa085,
+	0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x6239, 0x0c7e,
+	0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, 0x5504, 0x017f, 0x0040,
+	0x6258, 0x660a, 0x611a, 0x601f, 0x0008, 0x2d00, 0x6012, 0x2009,
+	0x0021, 0x1078, 0x5591, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c,
+	0xa006, 0x0078, 0x6255, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e,
+	0x1078, 0x5504, 0x017f, 0x0040, 0x6273, 0x611a, 0x601f, 0x0001,
+	0x2d00, 0x6012, 0x2009, 0x0000, 0x1078, 0x5591, 0xa085, 0x0001,
+	0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x6270, 0x027e, 0x0d7e,
+	0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0040, 0x6280, 0x8211, 0x6a3e,
+	0x0d7f, 0x027f, 0x007c, 0x6013, 0x0000, 0x601f, 0x0007, 0x6017,
+	0x0014, 0x007c, 0x067e, 0x0c7e, 0x2031, 0x6d52, 0x2634, 0xd6e4,
+	0x0040, 0x6297, 0x6618, 0x2660, 0x6e44, 0x1078, 0x3507, 0x0c7f,
+	0x067f, 0x007c, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12b7,
+	0x1079, 0x62a4, 0x067f, 0x007c, 0x62b4, 0x640b, 0x64d4, 0x62b4,
+	0x62b4, 0x62b4, 0x62b4, 0x62b4, 0x62ee, 0x6542, 0x62b4, 0x62b4,
+	0x62b4, 0x62b4, 0x62b4, 0x62b4, 0x1078, 0x12b7, 0x067e, 0x6000,
+	0xa0b2, 0x0010, 0x10c8, 0x12b7, 0x1079, 0x62c0, 0x067f, 0x007c,
+	0x62d0, 0x6837, 0x62d0, 0x62d0, 0x62d0, 0x62d0, 0x62d0, 0x62d0,
+	0x6812, 0x687d, 0x62d0, 0x62d0, 0x62d0, 0x62d0, 0x62d0, 0x62d0,
+	0x1078, 0x12b7, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12b7,
+	0x1079, 0x62dc, 0x067f, 0x007c, 0x62ec, 0x668f, 0x66fb, 0x671c,
+	0x6769, 0x62ec, 0x62ec, 0x67be, 0x654e, 0x67fa, 0x67fe, 0x62ec,
+	0x62ec, 0x62ec, 0x62ec, 0x62ec, 0x1078, 0x12b7, 0xa1b2, 0x0024,
+	0x10c8, 0x12b7, 0x2100, 0x0079, 0x62f5, 0x6319, 0x63f5, 0x6319,
+	0x6319, 0x6319, 0x6319, 0x6319, 0x6319, 0x6319, 0x6319, 0x6319,
+	0x6319, 0x6319, 0x6319, 0x6319, 0x6319, 0x6319, 0x6319, 0x6319,
+	0x6319, 0x6319, 0x6319, 0x6319, 0x631b, 0x634a, 0x6354, 0x637c,
+	0x6382, 0x63b6, 0x63ee, 0x6319, 0x6319, 0x63fd, 0x6319, 0x6319,
+	0x6404, 0x1078, 0x12b7, 0x1078, 0x364d, 0x6618, 0x0c7e, 0x2660,
+	0x1078, 0x3459, 0x0c7f, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff,
+	0xa082, 0x0006, 0x0048, 0x633c, 0x1078, 0x6993, 0x00c0, 0x6376,
+	0x1078, 0x6931, 0x00c0, 0x6338, 0x6007, 0x0008, 0x0078, 0x63f0,
+	0x6007, 0x0009, 0x0078, 0x63f0, 0x1078, 0x6b02, 0x0040, 0x6346,
+	0x1078, 0x6993, 0x0040, 0x6330, 0x0078, 0x6376, 0x6013, 0x1900,
+	0x0078, 0x6338, 0x1078, 0x68b7, 0x6007, 0x0006, 0x0078, 0x63f0,
+	0x6007, 0x0007, 0x0078, 0x63f0, 0x0d7e, 0x6618, 0x2668, 0x6e04,
+	0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x6366, 0xa686,
+	0x0004, 0x0040, 0x6366, 0x0d7f, 0x0078, 0x6376, 0x1078, 0x69f1,
+	0x00c0, 0x6371, 0x1078, 0x34ca, 0x6007, 0x000a, 0x0d7f, 0x0078,
+	0x63f0, 0x6007, 0x000b, 0x0d7f, 0x0078, 0x63f0, 0x1078, 0x2051,
+	0x6007, 0x0001, 0x0078, 0x63f0, 0x1078, 0x2051, 0x6007, 0x000c,
+	0x0078, 0x63f0, 0x1078, 0x364d, 0x6618, 0xa6b0, 0x0001, 0x2634,
+	0xa684, 0x00ff, 0xa082, 0x0006, 0x0048, 0x63a3, 0xa6b4, 0xff00,
+	0x8637, 0xa686, 0x0006, 0x00c0, 0x6376, 0x1078, 0x6a00, 0x00c0,
+	0x639d, 0x6007, 0x000e, 0x0078, 0x63f0, 0x1078, 0x2051, 0x6007,
+	0x000f, 0x0078, 0x63f0, 0x1078, 0x6b02, 0x0040, 0x63b0, 0xa6b4,
+	0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x6395, 0x0078, 0x6376,
+	0x6013, 0x1900, 0x6007, 0x0009, 0x0078, 0x63f0, 0x1078, 0x364d,
+	0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006,
+	0x0048, 0x63db, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x00c0,
+	0x6376, 0x1078, 0x6a2b, 0x00c0, 0x63d5, 0x1078, 0x6931, 0x00c0,
+	0x63d5, 0x6007, 0x0010, 0x0078, 0x63f0, 0x1078, 0x2051, 0x6007,
+	0x0011, 0x0078, 0x63f0, 0x1078, 0x6b02, 0x0040, 0x63e8, 0xa6b4,
+	0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x63c9, 0x0078, 0x6376,
+	0x6013, 0x1900, 0x6007, 0x0009, 0x0078, 0x63f0, 0x6007, 0x0012,
+	0x6003, 0x0001, 0x1078, 0x4376, 0x007c, 0x6007, 0x0001, 0x6003,
+	0x0001, 0x1078, 0x4376, 0x0078, 0x63f4, 0x6007, 0x0020, 0x6003,
+	0x0001, 0x1078, 0x4376, 0x007c, 0x6007, 0x0023, 0x6003, 0x0001,
+	0x1078, 0x4376, 0x007c, 0x6004, 0xa0b2, 0x0024, 0x10c8, 0x12b7,
+	0xa1b6, 0x0013, 0x00c0, 0x6417, 0x2008, 0x0079, 0x6426, 0xa1b6,
+	0x0014, 0x10c0, 0x12b7, 0x2001, 0x0007, 0x1078, 0x3401, 0x1078,
+	0x4671, 0x1078, 0x6283, 0x1078, 0x476a, 0x007c, 0x644a, 0x644c,
+	0x644a, 0x644a, 0x644a, 0x644c, 0x6454, 0x64af, 0x6472, 0x64af,
+	0x6486, 0x64af, 0x6454, 0x64af, 0x64a7, 0x64af, 0x64a7, 0x64af,
+	0x64af, 0x644a, 0x644a, 0x644a, 0x644a, 0x644a, 0x644a, 0x644a,
+	0x644a, 0x644a, 0x644a, 0x644a, 0x644a, 0x644a, 0x64af, 0x644a,
+	0x644a, 0x64af, 0x1078, 0x12b7, 0x1078, 0x4671, 0x6003, 0x0002,
+	0x1078, 0x476a, 0x0078, 0x64b5, 0x0f7e, 0x2079, 0x6d51, 0x7804,
+	0x0f7f, 0xd0ac, 0x00c0, 0x64af, 0x2001, 0x0000, 0x1078, 0x33df,
+	0x2001, 0x0002, 0x1078, 0x33f3, 0x1078, 0x4671, 0x601f, 0x0001,
+	0x6003, 0x0001, 0x6007, 0x0002, 0x1078, 0x4376, 0x1078, 0x476a,
+	0x0078, 0x64b5, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa6b4,
+	0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x64af, 0xa686, 0x0004,
+	0x0040, 0x64af, 0x2001, 0x0004, 0x0078, 0x64ad, 0x2001, 0x6d00,
+	0x2004, 0xa086, 0x0003, 0x00c0, 0x648f, 0x1078, 0x2ad1, 0x2001,
+	0x0006, 0x1078, 0x64b6, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f,
+	0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x64af, 0x2001,
+	0x0006, 0x0078, 0x64ad, 0x2001, 0x0004, 0x0078, 0x64ad, 0x2001,
+	0x0006, 0x1078, 0x64b6, 0x0078, 0x64af, 0x1078, 0x3401, 0x1078,
+	0x4671, 0x1078, 0x556a, 0x1078, 0x476a, 0x007c, 0x017e, 0x0d7e,
+	0x6118, 0x2168, 0x6900, 0xd184, 0x0040, 0x64d1, 0x6104, 0xa18e,
+	0x000a, 0x00c0, 0x64c9, 0x699c, 0xd1a4, 0x00c0, 0x64c9, 0x2001,
+	0x0007, 0x1078, 0x33f3, 0x2001, 0x0000, 0x1078, 0x33df, 0x1078,
+	0x206f, 0x0d7f, 0x017f, 0x007c, 0x0d7e, 0x6618, 0x2668, 0x6804,
+	0xa084, 0xff00, 0x8007, 0x0d7f, 0xa0b2, 0x000c, 0x10c8, 0x12b7,
+	0xa1b6, 0x0015, 0x00c0, 0x64e8, 0x1079, 0x64ef, 0x0078, 0x64ee,
+	0xa1b6, 0x0016, 0x10c0, 0x12b7, 0x1079, 0x6527, 0x007c, 0x57ef,
+	0x57ef, 0x57ef, 0x57ef, 0x57ef, 0x57ef, 0x57ef, 0x64fb, 0x57ef,
+	0x57ef, 0x57ef, 0x57ef, 0x0f7e, 0x2079, 0x6d51, 0x7804, 0x0f7f,
+	0xd0ac, 0x00c0, 0x6517, 0x2001, 0x0000, 0x1078, 0x33df, 0x2001,
+	0x0002, 0x1078, 0x33f3, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007,
+	0x0002, 0x1078, 0x4376, 0x1078, 0x476a, 0x0078, 0x6526, 0x2011,
+	0x7283, 0x220c, 0x017e, 0x0c7e, 0x1078, 0x3447, 0x00c0, 0x6526,
+	0x1078, 0x3256, 0x0c7f, 0x017f, 0x1078, 0x556a, 0x007c, 0x57ef,
+	0x57ef, 0x57ef, 0x57ef, 0x57ef, 0x57ef, 0x57ef, 0x6533, 0x57ef,
+	0x57ef, 0x57ef, 0x57ef, 0x1078, 0x599c, 0x00c0, 0x653f, 0x6003,
+	0x0001, 0x6007, 0x0001, 0x1078, 0x4376, 0x0078, 0x6541, 0x1078,
+	0x556a, 0x007c, 0x6004, 0xa08a, 0x0024, 0x10c8, 0x12b7, 0x1078,
+	0x4671, 0x1078, 0x6283, 0x1078, 0x476a, 0x007c, 0xa182, 0x0040,
+	0x0079, 0x6552, 0x6561, 0x6561, 0x6561, 0x6561, 0x6563, 0x6561,
+	0x6561, 0x6561, 0x6561, 0x6561, 0x6561, 0x6561, 0x6561, 0x6561,
+	0x6561, 0x1078, 0x12b7, 0x0d7e, 0x0e7e, 0x0f7e, 0x157e, 0x047e,
+	0x027e, 0x2071, 0x7280, 0x7444, 0xa4a4, 0xe600, 0x0040, 0x65d4,
+	0xa486, 0x2000, 0x0040, 0x6592, 0xa486, 0x0400, 0x0040, 0x6592,
+	0x7130, 0xa18c, 0x00ff, 0xa182, 0x0010, 0x00c8, 0x6663, 0x0c7e,
+	0x1078, 0x416d, 0x2c68, 0x0c7f, 0x6a00, 0xa284, 0x0001, 0x0040,
+	0x6644, 0x1078, 0x420a, 0x0040, 0x666f, 0xa295, 0x0200, 0x6a02,
+	0x0078, 0x6598, 0x2009, 0x0001, 0x2011, 0x0200, 0x1078, 0x41f4,
+	0x1078, 0x130f, 0x1040, 0x12b7, 0x6003, 0x0007, 0x6106, 0x2d00,
+	0x6837, 0x010d, 0x6803, 0x0000, 0x683b, 0x0000, 0x6c5a, 0x2c00,
+	0x685e, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0xa18c, 0x00ff,
+	0xa10d, 0x6946, 0x684f, 0x0000, 0x6857, 0x0036, 0x1078, 0x36a1,
+	0xa486, 0x2000, 0x00c0, 0x65c2, 0x2019, 0x0017, 0x1078, 0x6b8f,
+	0x0078, 0x6631, 0xa486, 0x0400, 0x00c0, 0x65cc, 0x2019, 0x0002,
+	0x1078, 0x6b8f, 0x0078, 0x6631, 0xa486, 0x0200, 0x00c0, 0x65d2,
+	0x1078, 0x6b80, 0x0078, 0x6631, 0x7130, 0xa18c, 0x00ff, 0xa182,
+	0x0010, 0x00c8, 0x6687, 0x0c7e, 0x1078, 0x416d, 0x2c68, 0x0c7f,
+	0x6a00, 0xa284, 0x0001, 0x0040, 0x668b, 0xa284, 0x0300, 0x00c0,
+	0x6683, 0x6804, 0xa005, 0x0040, 0x666f, 0x8001, 0x6806, 0x6003,
+	0x0007, 0x6106, 0x1078, 0x12f4, 0x0040, 0x6638, 0x6013, 0x0000,
+	0x6803, 0x0000, 0x6837, 0x0116, 0x683b, 0x0000, 0x2c00, 0x684a,
+	0x6018, 0x2078, 0x78a0, 0x8007, 0xa10d, 0x6946, 0x6853, 0x003d,
+	0x7044, 0xa084, 0x0003, 0xa086, 0x0002, 0x00c0, 0x6613, 0x684f,
+	0x0040, 0x0078, 0x661d, 0xa086, 0x0001, 0x00c0, 0x661b, 0x684f,
+	0x0080, 0x0078, 0x661d, 0x684f, 0x0000, 0x20a9, 0x000a, 0x2001,
+	0x7290, 0xad90, 0x0015, 0x200c, 0x810f, 0x2112, 0x8000, 0x8210,
+	0x00f0, 0x6623, 0x200c, 0x6982, 0x8000, 0x200c, 0x697e, 0x1078,
+	0x36a1, 0x027f, 0x047f, 0x157f, 0x0f7f, 0x0e7f, 0x0d7f, 0x007c,
+	0x6013, 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, 0x4327,
+	0x1078, 0x476a, 0x0078, 0x6631, 0x2069, 0x7292, 0x2d04, 0xa084,
+	0xff00, 0xa086, 0x1200, 0x00c0, 0x6663, 0x2069, 0x7280, 0x686c,
+	0xa084, 0x00ff, 0x017e, 0x6110, 0xa18c, 0x0700, 0xa10d, 0x6112,
+	0x017f, 0x6003, 0x0001, 0x6007, 0x0043, 0x1078, 0x4327, 0x1078,
+	0x476a, 0x0078, 0x6631, 0x6013, 0x0200, 0x6003, 0x0001, 0x6007,
+	0x0041, 0x1078, 0x4327, 0x1078, 0x476a, 0x0078, 0x6631, 0xa284,
+	0x0004, 0x00c0, 0x6677, 0x6013, 0x0300, 0x0078, 0x6679, 0x6013,
+	0x0100, 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, 0x4327, 0x1078,
+	0x476a, 0x0078, 0x6631, 0x6013, 0x0500, 0x0078, 0x6679, 0x6013,
+	0x0600, 0x0078, 0x6644, 0x6013, 0x0200, 0x0078, 0x6644, 0xa186,
+	0x0013, 0x00c0, 0x66a1, 0x6004, 0xa08a, 0x0040, 0x1048, 0x12b7,
+	0xa08a, 0x004f, 0x10c8, 0x12b7, 0xa082, 0x0040, 0x2008, 0x0079,
+	0x66cd, 0xa186, 0x0047, 0x00c0, 0x66a7, 0x0078, 0x66fb, 0xa186,
+	0x0014, 0x10c0, 0x12b7, 0x6004, 0xa082, 0x0040, 0x2008, 0x0079,
+	0x66b1, 0x66c0, 0x66c2, 0x66c2, 0x66c0, 0x66c0, 0x66c0, 0x66c0,
+	0x66c0, 0x66c0, 0x66c0, 0x66c0, 0x66c0, 0x66c0, 0x66c0, 0x66c0,
+	0x1078, 0x12b7, 0x2001, 0x0007, 0x1078, 0x3401, 0x1078, 0x4671,
+	0x1078, 0x6283, 0x1078, 0x476a, 0x007c, 0x66dc, 0x66ec, 0x66e5,
+	0x66f5, 0x66dc, 0x66dc, 0x66dc, 0x66dc, 0x66dc, 0x66dc, 0x66dc,
+	0x66dc, 0x66dc, 0x66dc, 0x66dc, 0x1078, 0x12b7, 0x6010, 0xa088,
+	0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x1078, 0x4671, 0x6003,
+	0x0002, 0x1078, 0x476a, 0x007c, 0x1078, 0x4671, 0x1078, 0x41cd,
+	0x1078, 0x556a, 0x1078, 0x476a, 0x007c, 0x1078, 0x4671, 0x2009,
+	0x0041, 0x0078, 0x67be, 0xa182, 0x0040, 0x0079, 0x66ff, 0x670e,
+	0x6710, 0x670e, 0x670e, 0x670e, 0x670e, 0x670e, 0x6711, 0x670e,
+	0x670e, 0x670e, 0x670e, 0x670e, 0x670e, 0x670e, 0x1078, 0x12b7,
+	0x007c, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20,
+	0x2c10, 0x1078, 0x1532, 0x007c, 0xa182, 0x0040, 0x0079, 0x6720,
+	0x672f, 0x672f, 0x672f, 0x672f, 0x672f, 0x672f, 0x672f, 0x672f,
+	0x672f, 0x6731, 0x6754, 0x672f, 0x672f, 0x672f, 0x672f, 0x1078,
+	0x12b7, 0x1078, 0x4719, 0x1078, 0x4821, 0x6010, 0x0d7e, 0x2068,
+	0x684c, 0xd0fc, 0x0040, 0x6747, 0xa08c, 0x0003, 0xa18e, 0x0002,
+	0x0040, 0x674d, 0x2009, 0x0041, 0x0d7f, 0x0078, 0x67be, 0x6003,
+	0x0007, 0x1078, 0x41cd, 0x0d7f, 0x007c, 0x1078, 0x41cd, 0x1078,
+	0x556a, 0x0d7f, 0x0078, 0x674c, 0x2001, 0x0007, 0x1078, 0x3401,
+	0x1078, 0x4719, 0x1078, 0x4821, 0x6010, 0x0d7e, 0x2068, 0x037e,
+	0x2019, 0x0004, 0x1078, 0x6bb3, 0x037f, 0x1078, 0x6283, 0x0d7f,
+	0x007c, 0xa186, 0x0013, 0x00c0, 0x6777, 0x6004, 0xa086, 0x0042,
+	0x10c0, 0x12b7, 0x1078, 0x4671, 0x1078, 0x476a, 0x007c, 0xa186,
+	0x0014, 0x00c0, 0x678b, 0x6004, 0xa086, 0x0042, 0x10c0, 0x12b7,
+	0x2001, 0x0007, 0x1078, 0x3401, 0x1078, 0x4671, 0x1078, 0x6283,
+	0x1078, 0x476a, 0x007c, 0xa182, 0x0040, 0x0079, 0x678f, 0x679e,
+	0x679e, 0x679e, 0x679e, 0x679e, 0x679e, 0x679e, 0x67a0, 0x67ac,
+	0x679e, 0x679e, 0x679e, 0x679e, 0x679e, 0x679e, 0x1078, 0x12b7,
+	0x037e, 0x047e, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078,
+	0x1532, 0x047f, 0x037f, 0x007c, 0x6010, 0x0d7e, 0x2068, 0x684c,
+	0xd0fc, 0x0040, 0x67b8, 0x2009, 0x0041, 0x0d7f, 0x0078, 0x67be,
+	0x6003, 0x0007, 0x1078, 0x41cd, 0x0d7f, 0x007c, 0xa182, 0x0040,
+	0x0079, 0x67c2, 0x67d1, 0x67d3, 0x67df, 0x67eb, 0x67d1, 0x67d1,
+	0x67d1, 0x67d1, 0x67d1, 0x67d1, 0x67d1, 0x67d1, 0x67d1, 0x67d1,
+	0x67d1, 0x1078, 0x12b7, 0x6003, 0x0001, 0x6106, 0x1078, 0x4327,
+	0x127e, 0x2091, 0x8000, 0x1078, 0x476a, 0x127f, 0x007c, 0x6003,
+	0x0001, 0x6106, 0x1078, 0x4327, 0x127e, 0x2091, 0x8000, 0x1078,
+	0x476a, 0x127f, 0x007c, 0x6003, 0x0003, 0x6106, 0x2c10, 0x1078,
+	0x17de, 0x127e, 0x2091, 0x8000, 0x1078, 0x4395, 0x1078, 0x4821,
+	0x127f, 0x007c, 0x1078, 0x4671, 0x0078, 0x6800, 0x1078, 0x4719,
+	0x6110, 0x81ff, 0x0040, 0x680d, 0x0d7e, 0x2168, 0x037e, 0x2019,
+	0x0029, 0x1078, 0x6bb3, 0x037f, 0x0d7f, 0x1078, 0x6283, 0x1078,
+	0x476a, 0x007c, 0xa182, 0x0025, 0x0079, 0x6816, 0x681d, 0x681d,
+	0x681d, 0x681f, 0x681d, 0x681d, 0x681d, 0x1078, 0x12b7, 0x027e,
+	0x0e7e, 0x2071, 0x7280, 0x7220, 0x1078, 0x6ad1, 0x0040, 0x682c,
+	0x6007, 0x0026, 0x0078, 0x682e, 0x6007, 0x0027, 0x6003, 0x0001,
+	0x1078, 0x4327, 0x1078, 0x476a, 0x0e7f, 0x027f, 0x007c, 0xa186,
+	0x0013, 0x00c0, 0x6848, 0x6004, 0xa08a, 0x0025, 0x1048, 0x12b7,
+	0xa08a, 0x002c, 0x10c8, 0x12b7, 0xa082, 0x0025, 0x0079, 0x6857,
+	0xa186, 0x0014, 0x10c0, 0x12b7, 0x2001, 0x0007, 0x1078, 0x3401,
+	0x1078, 0x4671, 0x1078, 0x6283, 0x1078, 0x476a, 0x007c, 0x685e,
+	0x6860, 0x6860, 0x685e, 0x685e, 0x685e, 0x685e, 0x1078, 0x12b7,
+	0x1078, 0x4671, 0x1078, 0x556a, 0x1078, 0x476a, 0x007c, 0xa182,
+	0x0025, 0x1048, 0x12b7, 0xa182, 0x002c, 0x10c8, 0x12b7, 0xa182,
+	0x0025, 0x0079, 0x6873, 0x687a, 0x687a, 0x687a, 0x687c, 0x687a,
+	0x687a, 0x687a, 0x1078, 0x12b7, 0x007c, 0x1078, 0x4671, 0x1078,
+	0x6283, 0x1078, 0x476a, 0x007c, 0x127e, 0x037e, 0x087e, 0x2091,
+	0x8000, 0x2c40, 0x2019, 0x0002, 0x1078, 0x5387, 0x00c0, 0x68b3,
+	0x1078, 0x5428, 0x00c0, 0x68b3, 0x6000, 0xa086, 0x0000, 0x0040,
+	0x68b3, 0x601c, 0xa086, 0x0007, 0x0040, 0x68b3, 0x0d7e, 0x6010,
+	0x2068, 0x1078, 0x6120, 0x0040, 0x68a7, 0x1078, 0x6bb3, 0x0d7f,
+	0x6000, 0xa086, 0x0004, 0x00c0, 0x68af, 0x1078, 0x15f2, 0x6013,
+	0x0000, 0x601f, 0x0007, 0x087f, 0x037f, 0x127f, 0x007c, 0x0f7e,
+	0x0c7e, 0x037e, 0x157e, 0x2079, 0x7280, 0x7938, 0x783c, 0x1078,
+	0x1e1b, 0x00c0, 0x68e8, 0x017e, 0x0c7e, 0x1078, 0x3447, 0x00c0,
+	0x68e8, 0x2011, 0x7290, 0xac98, 0x000a, 0x20a9, 0x0004, 0x1078,
+	0x5a35, 0x00c0, 0x68e8, 0x017f, 0x027f, 0x027e, 0x017e, 0x2019,
+	0x0029, 0x1078, 0x445c, 0x1078, 0x43a9, 0x017f, 0x1078, 0x6a57,
+	0x1078, 0x35cf, 0x017f, 0x1078, 0x3256, 0xa006, 0x0078, 0x68ea,
+	0x0c7f, 0x017f, 0x157f, 0x037f, 0x0c7f, 0x0f7f, 0x007c, 0x0e7e,
+	0x0d7e, 0x0c7e, 0x047e, 0x037e, 0x027e, 0x2061, 0x7400, 0x2071,
+	0x6d00, 0x7444, 0x7060, 0x8001, 0xa402, 0x00c8, 0x6929, 0x2100,
+	0xac06, 0x0040, 0x691b, 0x6000, 0xa086, 0x0000, 0x0040, 0x691b,
+	0x6018, 0x2068, 0x68a0, 0xa206, 0x00c0, 0x691b, 0x631c, 0xa386,
+	0x0004, 0x0040, 0x6925, 0xa386, 0x0005, 0x0040, 0x6925, 0xa386,
+	0x0006, 0x0040, 0x6925, 0xace0, 0x0008, 0x2001, 0x6d15, 0x2004,
+	0xac02, 0x00c8, 0x6929, 0x0078, 0x68f7, 0xa085, 0x0001, 0x0078,
+	0x692a, 0xa006, 0x027f, 0x037f, 0x047f, 0x0c7f, 0x0d7f, 0x0e7f,
+	0x007c, 0x0c7e, 0x0d7e, 0x017e, 0x2009, 0x6d1e, 0x2104, 0xa086,
+	0x0074, 0x00c0, 0x6988, 0x2069, 0x728e, 0x690c, 0xa182, 0x0100,
+	0x0048, 0x6978, 0x6908, 0xa184, 0x8000, 0x0040, 0x6984, 0xa184,
+	0x0800, 0x0040, 0x6984, 0x6910, 0xa18a, 0x0001, 0x0048, 0x697c,
+	0x6914, 0x2069, 0x72ae, 0x6904, 0x81ff, 0x00c0, 0x6970, 0x690c,
+	0xa182, 0x0100, 0x0048, 0x6978, 0x6908, 0x81ff, 0x00c0, 0x6974,
+	0x6910, 0xa18a, 0x0001, 0x0048, 0x697c, 0x6918, 0xa18a, 0x0001,
+	0x0048, 0x6984, 0x0078, 0x698e, 0x6013, 0x0100, 0x0078, 0x698a,
+	0x6013, 0x0300, 0x0078, 0x698a, 0x6013, 0x0500, 0x0078, 0x698a,
+	0x6013, 0x0700, 0x0078, 0x698a, 0x6013, 0x0900, 0x0078, 0x698a,
+	0x6013, 0x0b00, 0x0078, 0x698a, 0x6013, 0x0f00, 0x0078, 0x698a,
+	0x6013, 0x2d00, 0xa085, 0x0001, 0x0078, 0x698f, 0xa006, 0x017f,
+	0x0d7f, 0x0c7f, 0x007c, 0x0c7e, 0x0d7e, 0x027e, 0x037e, 0x157e,
+	0x6218, 0x2268, 0x6b04, 0xa394, 0x00ff, 0xa286, 0x0006, 0x0040,
+	0x69b7, 0xa286, 0x0004, 0x0040, 0x69b7, 0xa394, 0xff00, 0x8217,
+	0xa286, 0x0006, 0x0040, 0x69b7, 0xa286, 0x0004, 0x0040, 0x69b7,
+	0x0c7e, 0x2d60, 0x1078, 0x3459, 0x0c7f, 0x0078, 0x69ea, 0x2011,
+	0x7296, 0xad98, 0x000a, 0x20a9, 0x0004, 0x1078, 0x5a35, 0x00c0,
+	0x69eb, 0x2011, 0x729a, 0xad98, 0x0006, 0x20a9, 0x0004, 0x1078,
+	0x5a35, 0x00c0, 0x69eb, 0x047e, 0x017e, 0x6aa0, 0xa294, 0x00ff,
+	0x8227, 0xa006, 0x2009, 0x6d52, 0x210c, 0xd1a4, 0x0040, 0x69df,
+	0x2009, 0x0029, 0x1078, 0x6bf7, 0x6800, 0xc0e5, 0x6802, 0x2019,
+	0x0029, 0x1078, 0x445c, 0x1078, 0x43a9, 0x2c08, 0x1078, 0x6a57,
+	0x017f, 0x047f, 0xa006, 0x157f, 0x037f, 0x027f, 0x0d7f, 0x0c7f,
+	0x007c, 0x0d7e, 0x2069, 0x728e, 0x6800, 0xa086, 0x0800, 0x0040,
+	0x69fd, 0x6013, 0x0000, 0x0078, 0x69fe, 0xa006, 0x0d7f, 0x007c,
+	0x0c7e, 0x0f7e, 0x017e, 0x027e, 0x037e, 0x157e, 0x2079, 0x728c,
+	0x7930, 0x7834, 0x1078, 0x1e1b, 0x00c0, 0x6a24, 0x1078, 0x3447,
+	0x00c0, 0x6a24, 0x2011, 0x7290, 0xac98, 0x000a, 0x20a9, 0x0004,
+	0x1078, 0x5a35, 0x00c0, 0x6a24, 0x2011, 0x7294, 0xac98, 0x0006,
+	0x20a9, 0x0004, 0x1078, 0x5a35, 0x157f, 0x037f, 0x027f, 0x017f,
+	0x0f7f, 0x0c7f, 0x007c, 0x0c7e, 0x007e, 0x017e, 0x027e, 0x037e,
+	0x157e, 0x2011, 0x7283, 0x2204, 0x8211, 0x220c, 0x1078, 0x1e1b,
+	0x00c0, 0x6a50, 0x1078, 0x3447, 0x00c0, 0x6a50, 0x2011, 0x7296,
+	0xac98, 0x000a, 0x20a9, 0x0004, 0x1078, 0x5a35, 0x00c0, 0x6a50,
+	0x2011, 0x729a, 0xac98, 0x0006, 0x20a9, 0x0004, 0x1078, 0x5a35,
+	0x157f, 0x037f, 0x027f, 0x017f, 0x007f, 0x0c7f, 0x007c, 0x0e7e,
+	0x0c7e, 0x077e, 0x067e, 0x057e, 0x047e, 0x027e, 0x127e, 0x2091,
+	0x8000, 0x2029, 0x6f19, 0x252c, 0x2021, 0x6f1f, 0x2424, 0x2061,
+	0x7400, 0x2071, 0x6d00, 0x7644, 0x7060, 0x8001, 0xa602, 0x00c8,
+	0x6abc, 0x2100, 0xac06, 0x0040, 0x6ab2, 0x1078, 0x6c0f, 0x0040,
+	0x6ab2, 0x671c, 0xa786, 0x0001, 0x0040, 0x6ab2, 0xa786, 0x0007,
+	0x0040, 0x6ab2, 0x2500, 0xac06, 0x0040, 0x6ab2, 0x2400, 0xac06,
+	0x0040, 0x6ab2, 0x6018, 0x2070, 0x70a0, 0xa206, 0x00c0, 0x6ab2,
+	0x0d7e, 0x6010, 0x2068, 0x1078, 0x6120, 0x0040, 0x6aa6, 0xa786,
+	0x0003, 0x00c0, 0x6ac5, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000,
+	0x017e, 0x1078, 0x36a1, 0x017f, 0x1078, 0x6276, 0x0d7f, 0x6000,
+	0xa086, 0x0004, 0x00c0, 0x6ab0, 0x017e, 0x1078, 0x15f2, 0x017f,
+	0x1078, 0x6283, 0xace0, 0x0008, 0x2001, 0x6d15, 0x2004, 0xac02,
+	0x00c8, 0x6abc, 0x0078, 0x6a69, 0x127f, 0x027f, 0x047f, 0x057f,
+	0x067f, 0x077f, 0x0c7f, 0x0e7f, 0x007c, 0xa786, 0x0006, 0x00c0,
+	0x6a9b, 0xa386, 0x0005, 0x0040, 0x6ab2, 0x1078, 0x6bb3, 0x0078,
+	0x6aa6, 0x0c7e, 0x0e7e, 0x017e, 0x2c08, 0x2170, 0x1078, 0x6bca,
+	0x017f, 0x0040, 0x6ae0, 0x601c, 0xa084, 0x000f, 0x1079, 0x6ae3,
+	0x0e7f, 0x0c7f, 0x007c, 0x6aeb, 0x6aeb, 0x6aeb, 0x6aeb, 0x6aeb,
+	0x6aeb, 0x6aed, 0x6aeb, 0xa006, 0x007c, 0x047e, 0x017e, 0x7018,
+	0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00, 0x2009,
+	0x0020, 0x1078, 0x6bf7, 0x017f, 0x047f, 0x1078, 0x6884, 0xa085,
+	0x0001, 0x007c, 0x2001, 0x0001, 0x1078, 0x33df, 0x157e, 0x017e,
+	0x027e, 0x037e, 0x20a9, 0x0004, 0x2019, 0x6d05, 0x2011, 0x7296,
+	0x1078, 0x5a35, 0x037f, 0x027f, 0x017f, 0x157f, 0xa005, 0x007c,
+	0x0f7e, 0x0e7e, 0x0c7e, 0x077e, 0x067e, 0x027e, 0x127e, 0x2091,
+	0x8000, 0x2061, 0x7400, 0x2079, 0x0001, 0x8fff, 0x0040, 0x6b73,
+	0x2071, 0x6d00, 0x7644, 0x7060, 0x8001, 0xa602, 0x00c8, 0x6b73,
+	0x88ff, 0x0040, 0x6b39, 0x2800, 0xac06, 0x00c0, 0x6b69, 0x2079,
+	0x0000, 0x1078, 0x6c0f, 0x0040, 0x6b69, 0x2400, 0xac06, 0x0040,
+	0x6b69, 0x671c, 0xa786, 0x0006, 0x00c0, 0x6b69, 0xa786, 0x0007,
+	0x0040, 0x6b69, 0x88ff, 0x00c0, 0x6b51, 0x6018, 0xa206, 0x00c0,
+	0x6b69, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x6120, 0x0040, 0x6b5c,
+	0x047e, 0x1078, 0x6bb3, 0x047f, 0x0d7f, 0x6000, 0xa086, 0x0004,
+	0x00c0, 0x6b64, 0x1078, 0x15f2, 0x1078, 0x6283, 0x88ff, 0x00c0,
+	0x6b7c, 0xace0, 0x0008, 0x2001, 0x6d15, 0x2004, 0xac02, 0x00c8,
+	0x6b73, 0x0078, 0x6b25, 0xa006, 0x127f, 0x027f, 0x067f, 0x077f,
+	0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0xa8c5, 0x0001, 0x0078, 0x6b74,
+	0x087e, 0x2041, 0x0000, 0x2c20, 0x2019, 0x0002, 0x6218, 0x1078,
+	0x5387, 0x1078, 0x5428, 0x1078, 0x6b18, 0x087f, 0x007c, 0x027e,
+	0x047e, 0x087e, 0x0c7e, 0x157e, 0x2c20, 0x20a9, 0x007f, 0x2009,
+	0x0000, 0x017e, 0x037e, 0x1078, 0x3447, 0x00c0, 0x6ba8, 0x2c10,
+	0x2041, 0x0000, 0x1078, 0x5387, 0x1078, 0x5428, 0x1078, 0x6b18,
+	0x037f, 0x017f, 0x8108, 0x00f0, 0x6b99, 0x157f, 0x0c7f, 0x087f,
+	0x047f, 0x027f, 0x007c, 0x017e, 0x0f7e, 0x8dff, 0x0040, 0x6bc7,
+	0x6800, 0xa07d, 0x0040, 0x6bc4, 0x6803, 0x0000, 0x6b52, 0x1078,
+	0x36a1, 0x2f68, 0x0078, 0x6bb8, 0x6b52, 0x1078, 0x36a1, 0x0f7f,
+	0x017f, 0x007c, 0x0e7e, 0x047e, 0x037e, 0x2061, 0x7400, 0x2071,
+	0x6d00, 0x7444, 0x7060, 0x8001, 0xa402, 0x00c8, 0x6bf2, 0x2100,
+	0xac06, 0x0040, 0x6be4, 0x6000, 0xa086, 0x0000, 0x0040, 0x6be4,
+	0x6008, 0xa206, 0x0040, 0x6bee, 0xace0, 0x0008, 0x2001, 0x6d15,
+	0x2004, 0xac02, 0x00c8, 0x6bf2, 0x0078, 0x6bcf, 0xa085, 0x0001,
+	0x0078, 0x6bf3, 0xa006, 0x037f, 0x047f, 0x0e7f, 0x007c, 0x0d7e,
+	0x007e, 0x1078, 0x130f, 0x007f, 0x1040, 0x12b7, 0x6837, 0x010d,
+	0x6803, 0x0000, 0x683b, 0x0000, 0x685b, 0x0000, 0x685e, 0x6956,
+	0x6c46, 0x684f, 0x0000, 0x1078, 0x36a1, 0x0d7f, 0x007c, 0x6700,
+	0xa786, 0x0000, 0x0040, 0x6c22, 0xa786, 0x0001, 0x0040, 0x6c22,
+	0xa786, 0x000a, 0x0040, 0x6c22, 0xa786, 0x0009, 0x0040, 0x6c22,
+	0xa085, 0x0001, 0x007c, 0x127e, 0x007e, 0x0e7e, 0x2091, 0x8000,
+	0x2071, 0x6d00, 0xd5a4, 0x0040, 0x6c30, 0x7034, 0x8000, 0x7036,
+	0xd5b4, 0x0040, 0x6c36, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0040,
+	0x6c3d, 0x2071, 0x6d0a, 0x1078, 0x6c6c, 0x0e7f, 0x007f, 0x127f,
+	0x007c, 0x127e, 0x007e, 0x0e7e, 0x2091, 0x8000, 0x2071, 0x6d00,
+	0xd5a4, 0x0040, 0x6c4e, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0040,
+	0x6c54, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0040, 0x6c5b, 0x2071,
+	0x6d0a, 0x1078, 0x6c6c, 0x0e7f, 0x007f, 0x127f, 0x007c, 0x127e,
+	0x007e, 0x0e7e, 0x2091, 0x8000, 0x2071, 0x6d02, 0x1078, 0x6c6c,
+	0x0e7f, 0x007f, 0x127f, 0x007c, 0x2e04, 0x8000, 0x2072, 0x00c8,
+	0x6c75, 0x8e70, 0x2e04, 0x8000, 0x2072, 0x007c, 0x0e7e, 0x2071,
+	0x6d00, 0x1078, 0x6c6c, 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0x6d04,
+	0x1078, 0x6c6c, 0x0e7f, 0x007c, 0x0001, 0x0002, 0x0004, 0x0008,
+	0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800,
+	0x1000, 0x2000, 0x4000, 0x8000, 0x614c
+};
+unsigned short   risc_code_length01 = 0x5c95;
+
diff -u --recursive --new-file v2.2.2/linux/drivers/scsi/scsi_error.c linux/drivers/scsi/scsi_error.c
--- v2.2.2/linux/drivers/scsi/scsi_error.c	Fri Jan  8 22:36:10 1999
+++ linux/drivers/scsi/scsi_error.c	Wed Feb 24 16:27:54 1999
@@ -563,6 +563,7 @@
     struct semaphore sem = MUTEX_LOCKED;
     struct timer_list timer;
 
+    init_timer(&timer);
     timer.data = (unsigned long) &sem;
     timer.expires = jiffies + timeout;
     timer.function = (void (*)(unsigned long))scsi_sleep_done;
diff -u --recursive --new-file v2.2.2/linux/drivers/scsi/sd_ioctl.c linux/drivers/scsi/sd_ioctl.c
--- v2.2.2/linux/drivers/scsi/sd_ioctl.c	Fri Oct 23 22:01:21 1998
+++ linux/drivers/scsi/sd_ioctl.c	Wed Feb 24 16:27:54 1999
@@ -108,6 +108,11 @@
                 return -EACCES;
 	return revalidate_scsidisk(dev, 1);
 
+    case BLKSSZGET:
+	/* Block size of media */
+	return put_user(blksize_size[MAJOR(dev)][MINOR(dev)&0x0F],
+		(int *)arg);
+				
     RO_IOCTLS(dev, arg);
 
     default:
diff -u --recursive --new-file v2.2.2/linux/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c
--- v2.2.2/linux/drivers/scsi/sr_ioctl.c	Wed Sep  9 14:51:09 1998
+++ linux/drivers/scsi/sr_ioctl.c	Wed Feb 24 16:27:54 1999
@@ -872,6 +872,11 @@
 	read_ahead[MAJOR(cdi->dev)] = arg;
 	return 0;
 
+    case BLKSSZGET:
+	/* Block size of media */
+	return put_user(blksize_size[MAJOR(cdi->dev)][MINOR(cdi->dev)],
+		(int *)arg);
+
     RO_IOCTLS(cdi->dev,arg);
 
     case BLKFLSBUF:
diff -u --recursive --new-file v2.2.2/linux/drivers/scsi/st.c linux/drivers/scsi/st.c
--- v2.2.2/linux/drivers/scsi/st.c	Mon Dec 28 15:00:52 1998
+++ linux/drivers/scsi/st.c	Sun Mar  7 15:20:26 1999
@@ -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 - 1998 Kai Makisara
+  Copyright 1992 - 1999 Kai Makisara
 		 email Kai.Makisara@metla.fi
 
-  Last modified: Thu Dec  3 20:27:46 1998 by makisara@home
+  Last modified: Sun Mar  7 09:03:17 1999 by makisara@home
   Some small formal changes - aeb, 950809
 */
 
@@ -1094,8 +1094,11 @@
 #endif
 
     /* Write must be integral number of blocks */
-    if (STp->block_size != 0 && (count % STp->block_size) != 0)
+    if (STp->block_size != 0 && (count % STp->block_size) != 0) {
+	printk(KERN_WARNING "st%d: Write not multiple of tape block size.\n",
+	       dev);
 	return (-EIO);
+    }
 
     if (STp->can_partitions &&
 	(retval = update_partition(inode)) < 0)
diff -u --recursive --new-file v2.2.2/linux/drivers/scsi/sym53c416.c linux/drivers/scsi/sym53c416.c
--- v2.2.2/linux/drivers/scsi/sym53c416.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/sym53c416.c	Wed Feb 24 16:28:43 1999
@@ -0,0 +1,806 @@
+/* 
+ *  sym53c416.c
+ *  Low-level SCSI driver for sym53c416 chip.
+ *  Copyright (C) 1998 Lieven Willems (lw_linux@hotmail.com)
+ * 
+ *  LILO command line usage: sym53c416=<PORTBASE>[,<IRQ>]
+ *
+ *  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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <asm/dma.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <linux/blk.h>
+#include <linux/version.h>
+#include "scsi.h"
+#include "hosts.h"
+#include "sd.h"
+#include "sym53c416.h"
+
+#define VERSION_STRING        "Version 1.0.0"
+
+#define TC_LOW       0x00     /* Transfer counter low        */
+#define TC_MID       0x01     /* Transfer counter mid        */
+#define SCSI_FIFO    0x02     /* SCSI FIFO register          */
+#define COMMAND_REG  0x03     /* Command Register            */
+#define STATUS_REG   0x04     /* Status Register (READ)      */
+#define DEST_BUS_ID  0x04     /* Destination Bus ID (WRITE)  */
+#define INT_REG      0x05     /* Interrupt Register (READ)   */
+#define TOM          0x05     /* Time out multiplier (WRITE) */
+#define STP          0x06     /* Synchronous Transfer period */
+#define SYNC_OFFSET  0x07     /* Synchronous Offset          */
+#define CONF_REG_1   0x08     /* Configuration register 1    */
+#define CONF_REG_2   0x0B     /* Configuration register 2    */
+#define CONF_REG_3   0x0C     /* Configuration register 3    */
+#define CONF_REG_4   0x0D     /* Configuration register 4    */
+#define TC_HIGH      0x0E     /* Transfer counter high       */
+#define PIO_FIFO_1   0x10     /* PIO FIFO register 1         */
+#define PIO_FIFO_2   0x11     /* PIO FIFO register 2         */
+#define PIO_FIFO_3   0x12     /* PIO FIFO register 3         */
+#define PIO_FIFO_4   0x13     /* PIO FIFO register 4         */
+#define PIO_FIFO_CNT 0x14     /* PIO FIFO count              */
+#define PIO_INT_REG  0x15     /* PIO interrupt register      */
+#define CONF_REG_5   0x16     /* Configuration register 5    */
+#define FEATURE_EN   0x1D     /* Feature Enable register     */
+
+/* Configuration register 1 entries: */
+/* Bits 2-0: SCSI ID of host adapter */
+#define SCM    0x80                     /* Slow Cable Mode              */
+#define SRID   0x40                     /* SCSI Reset Interrupt Disable */
+#define PTM    0x20                     /* Parity Test Mode             */
+#define EPC    0x10                     /* Enable Parity Checking       */
+#define CTME   0x08                     /* Special Test Mode            */
+
+/* Configuration register 2 entries: */
+#define FE     0x40                     /* Features Enable              */
+#define SCSI2  0x08                     /* SCSI 2 Enable                */
+#define TBPA   0x04                     /* Target Bad Parity Abort      */
+
+/* Configuration register 3 entries: */
+#define IDMRC  0x80                     /* ID Message Reserved Check    */
+#define QTE    0x40                     /* Queue Tag Enable             */
+#define CDB10  0x20                     /* Command Descriptor Block 10  */
+#define FSCSI  0x10                     /* FastSCSI                     */
+#define FCLK   0x08                     /* FastClock                    */
+
+/* Configuration register 4 entries: */
+#define RBS    0x08                     /* Register bank select         */
+#define EAN    0x04                     /* Enable Active Negotiation    */
+
+/* Configuration register 5 entries: */
+#define LPSR   0x80                     /* Lower Power SCSI Reset       */
+#define IE     0x20                     /* Interrupt Enable             */
+#define LPM    0x02                     /* Low Power Mode               */
+#define WSE0   0x01                     /* 0WS Enable                   */
+
+/* Interrupt register entries: */
+#define SRST   0x80                     /* SCSI Reset                   */
+#define ILCMD  0x40                     /* Illegal Command              */
+#define DIS    0x20                     /* Disconnect                   */
+#define BS     0x10                     /* Bus Service                  */
+#define FC     0x08                     /* Function Complete            */
+#define RESEL  0x04                     /* Reselected                   */
+#define SI     0x03                     /* Selection Interrupt          */
+
+/* Status Register Entries: */
+#define SCI    0x80                     /* SCSI Core Int                */
+#define GE     0x40                     /* Gross Error                  */
+#define PE     0x20                     /* Parity Error                 */
+#define TC     0x10                     /* Terminal Count               */
+#define VGC    0x08                     /* Valid Group Code             */
+#define PHBITS 0x07                     /* Phase bits                   */
+
+/* PIO Interrupt Register Entries: */
+#define SCI    0x80                     /* SCSI Core Int                */
+#define PFI    0x40                     /* PIO FIFO Interrupt           */
+#define FULL   0x20                     /* PIO FIFO Full                */
+#define EMPTY  0x10                     /* PIO FIFO Empty               */
+#define CE     0x08                     /* Collision Error              */
+#define OUE    0x04                     /* Overflow / Underflow error   */
+#define FIE    0x02                     /* Full Interrupt Enable        */
+#define EIE    0x01                     /* Empty Interrupt Enable       */
+
+/* SYM53C416 SCSI phases (lower 3 bits of SYM53C416_STATUS_REG) */
+#define PHASE_DATA_OUT    0x00
+#define PHASE_DATA_IN     0x01
+#define PHASE_COMMAND     0x02
+#define PHASE_STATUS      0x03
+#define PHASE_RESERVED_1  0x04
+#define PHASE_RESERVED_2  0x05
+#define PHASE_MESSAGE_OUT 0x06
+#define PHASE_MESSAGE_IN  0x07
+
+/* SYM53C416 core commands */
+#define NOOP                      0x00
+#define FLUSH_FIFO                0x01
+#define RESET_CHIP                0x02
+#define RESET_SCSI_BUS            0x03
+#define DISABLE_SEL_RESEL         0x45
+#define RESEL_SEQ                 0x40
+#define SEL_WITHOUT_ATN_SEQ       0x41
+#define SEL_WITH_ATN_SEQ          0x42
+#define SEL_WITH_ATN_AND_STOP_SEQ 0x43
+#define ENABLE_SEL_RESEL          0x44
+#define SEL_WITH_ATN3_SEQ         0x46
+#define RESEL3_SEQ                0x47
+#define SND_MSG                   0x20
+#define SND_STAT                  0x21
+#define SND_DATA                  0x22
+#define DISCONNECT_SEQ            0x23
+#define TERMINATE_SEQ             0x24
+#define TARGET_COMM_COMPLETE_SEQ  0x25
+#define DISCONN                   0x27
+#define RECV_MSG_SEQ              0x28
+#define RECV_CMD                  0x29
+#define RECV_DATA                 0x2A
+#define RECV_CMD_SEQ              0x2B
+#define TARGET_ABORT_PIO          0x04
+#define TRANSFER_INFORMATION      0x10
+#define INIT_COMM_COMPLETE_SEQ    0x11
+#define MSG_ACCEPTED              0x12
+#define TRANSFER_PAD              0x18
+#define SET_ATN                   0x1A
+#define RESET_ATN                 0x1B
+#define ILLEGAL                   0xFF
+
+#define PIO_MODE                  0x80
+
+#define IO_RANGE 0x20         /* 0x00 - 0x1F                   */
+#define ID       "sym53c416"
+#define PIO_SIZE 128          /* Size of PIO fifo is 128 bytes */
+
+#define READ_TIMEOUT              150
+#define WRITE_TIMEOUT             150
+
+#ifdef MODULE
+
+#define sym53c416_base sym53c416
+#define sym53c416_base_1 sym53c416_1
+#define sym53c416_base_2 sym53c416_2
+#define sym53c416_base_3 sym53c416_3
+
+static unsigned short sym53c416_base = 0;
+static unsigned int sym53c416_irq = 0;
+static unsigned short sym53c416_base_1 = 0;
+static unsigned int sym53c416_irq_1 = 0;
+static unsigned short sym53c416_base_2 = 0;
+static unsigned int sym53c416_irq_2 = 0;
+static unsigned short sym53c416_base_3 = 0;
+static unsigned int sym53c416_irq_3 = 0;
+
+#endif
+
+/* #define DEBUG */
+
+/* Macro for debugging purposes */
+
+#ifdef DEBUG
+#define DEB(x) x
+#else
+#define DEB(x)
+#endif
+
+#define MAXHOSTS 4
+
+enum phases
+  {
+  idle,
+  data_out,
+  data_in,
+  command_ph,
+  status_ph,
+  message_out,
+  message_in
+  };
+
+typedef struct
+  {
+  int base;
+  int irq;
+  int scsi_id;
+  } host;
+
+host hosts[MAXHOSTS] = {
+                       {0, 0, SYM53C416_SCSI_ID},
+                       {0, 0, SYM53C416_SCSI_ID},
+                       {0, 0, SYM53C416_SCSI_ID},
+                       {0, 0, SYM53C416_SCSI_ID}
+                       };
+
+static int host_index = 0;
+
+static char info[120];
+
+static Scsi_Cmnd *current_command = NULL;
+
+struct proc_dir_entry proc_scsi_sym53c416 = {PROC_SCSI_SYM53C416, 7, ID, S_IFDIR | S_IRUGO | S_IXUGO, 2};
+
+int fastpio = 1;
+
+int probeaddrs[] = {0x200, 0x220, 0x240, 0};
+
+static void sym53c416_set_transfer_counter(int base, unsigned int len)
+  {
+  /* Program Transfer Counter */
+  outb(len & 0x0000FF, base + TC_LOW);
+  outb((len & 0x00FF00) >> 8, base + TC_MID);
+  outb((len & 0xFF0000) >> 16, base + TC_HIGH);
+  }
+
+/* Returns the number of bytes read */
+static __inline__ unsigned int sym53c416_read(int base, unsigned char *buffer, unsigned int len)
+  {
+  unsigned int orig_len = len;
+  unsigned long flags = 0;
+  unsigned int bytes_left;
+  int i;
+  int timeout = READ_TIMEOUT;
+
+  /* Do transfer */
+  save_flags(flags);
+  cli();
+  while(len && timeout)
+    {
+    bytes_left = inb(base + PIO_FIFO_CNT); /* Number of bytes in the PIO FIFO */
+    if(fastpio && bytes_left > 3)
+      {
+      insl(base + PIO_FIFO_1, buffer, bytes_left >> 2);
+      buffer += bytes_left & 0xFC;
+      len -= bytes_left & 0xFC;
+      }
+    else if(bytes_left > 0)
+      {
+      len -= bytes_left;
+      for(; bytes_left > 0; bytes_left--)
+        *(buffer++) = inb(base + PIO_FIFO_1);
+      }
+    else
+      {
+      i = jiffies + timeout;
+      restore_flags(flags);
+      while(jiffies < i && (inb(base + PIO_INT_REG) & EMPTY) && timeout)
+        if(inb(base + PIO_INT_REG) & SCI)
+          timeout = 0;
+      save_flags(flags);
+      cli();
+      if(inb(base + PIO_INT_REG) & EMPTY)
+        timeout = 0;
+      }
+    }
+  restore_flags(flags);
+  return orig_len - len;
+  }
+
+/* Returns the number of bytes written */
+static __inline__ unsigned int sym53c416_write(int base, unsigned char *buffer, unsigned int len)
+  {
+  unsigned int orig_len = len;
+  unsigned long flags = 0;
+  unsigned int bufferfree;
+  unsigned int i;
+  unsigned int timeout = WRITE_TIMEOUT;
+
+  /* Do transfer */
+  save_flags(flags);
+  cli();
+  while(len && timeout)
+    {
+    bufferfree = PIO_SIZE - inb(base + PIO_FIFO_CNT);
+    if(bufferfree > len)
+      bufferfree = len;
+    if(fastpio && bufferfree > 3)
+      {
+      outsl(base + PIO_FIFO_1, buffer, bufferfree >> 2);
+      buffer += bufferfree & 0xFC;
+      len -= bufferfree & 0xFC;
+      }
+    else if(bufferfree > 0)
+      {
+      len -= bufferfree;
+      for(; bufferfree > 0; bufferfree--)
+        outb(*(buffer++), base + PIO_FIFO_1);
+      }
+    else
+      {
+      i = jiffies + timeout;
+      restore_flags(flags);
+      while(jiffies < i && (inb(base + PIO_INT_REG) & FULL) && timeout)
+        ;
+      save_flags(flags);
+      cli();
+      if(inb(base + PIO_INT_REG) & FULL)
+        timeout = 0;
+      }
+    }
+  restore_flags(flags);
+  return orig_len - len;
+  }
+
+static void sym53c416_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
+  {
+  int base = 0;
+  int i;
+  unsigned long flags = 0;
+  unsigned char status_reg, pio_int_reg, int_reg;
+  struct scatterlist *sglist;
+  unsigned int sgcount;
+  unsigned int tot_trans = 0;
+
+  /* We search the base address of the host adapter which caused the interrupt */
+  for(i = 0; i < host_index && !base; i++)
+    if(irq == hosts[i].irq)
+      base = hosts[i].base;
+  /* If no adapter found, we cannot handle the interrupt. Leave a message */
+  /* and continue. This should never happen...                            */
+  if(!base)
+    {
+    printk("sym53c416: No host adapter defined for interrupt %d\n", irq);
+    return;
+    }
+  /* Now we have the base address and we can start handling the interrupt */
+  save_flags(flags);
+  cli();
+  status_reg = inb(base + STATUS_REG);
+  pio_int_reg = inb(base + PIO_INT_REG);
+  int_reg = inb(base + INT_REG);
+  restore_flags(flags);
+
+  /* First, we handle error conditions */
+  if(int_reg & SCI)         /* SCSI Reset */
+    {
+    printk("sym53c416: Warning: Reset received\n");
+    current_command->SCp.phase = idle;
+    current_command->result = DID_RESET << 16;
+    current_command->scsi_done(current_command);
+    return;
+    }
+  if(int_reg & ILCMD)       /* Illegal Command */
+    {
+    printk("sym53c416: Warning: Illegal Command: 0x%02x\n", inb(base + COMMAND_REG));
+    current_command->SCp.phase = idle;
+    current_command->result = DID_ERROR << 16;
+    current_command->scsi_done(current_command);
+    return;
+    }
+  if(status_reg & GE)         /* Gross Error */
+    {
+    printk("sym53c416: Warning: Gross Error\n");
+    current_command->SCp.phase = idle;
+    current_command->result = DID_ERROR << 16;
+    current_command->scsi_done(current_command);
+    return;
+    }
+  if(status_reg & PE)         /* Parity Error */
+    {
+    printk("sym53c416: Warning: Parity Error\n");
+    current_command->SCp.phase = idle;
+    current_command->result = DID_PARITY << 16;
+    current_command->scsi_done(current_command);
+    return;
+    }
+  if(pio_int_reg & (CE | OUE))
+    {
+    printk("sym53c416: Warning: PIO Interrupt Error\n");
+    current_command->SCp.phase = idle;
+    current_command->result = DID_ERROR << 16;
+    current_command->scsi_done(current_command);
+    return;
+    }
+  if(int_reg & DIS)           /* Disconnect */
+    {
+    if(current_command->SCp.phase != message_in)
+      current_command->result = DID_NO_CONNECT << 16;
+    else
+      current_command->result = (current_command->SCp.Status & 0xFF) | ((current_command->SCp.Message & 0xFF) << 8) | (DID_OK << 16);
+    current_command->SCp.phase = idle;
+    current_command->scsi_done(current_command);
+    return;
+    }
+  /* Now we handle SCSI phases         */
+  switch(status_reg & PHBITS)       /* Filter SCSI phase out of status reg */
+    {
+    case PHASE_DATA_OUT:
+      {
+      if(int_reg & BS)
+        {
+        current_command->SCp.phase = data_out;
+        outb(FLUSH_FIFO, base + COMMAND_REG);
+        sym53c416_set_transfer_counter(base, current_command->request_bufflen);
+        outb(TRANSFER_INFORMATION | PIO_MODE, base + COMMAND_REG);
+        if(!current_command->use_sg)
+          tot_trans = sym53c416_write(base, current_command->request_buffer, current_command->request_bufflen);
+        else
+          {
+          sgcount = current_command->use_sg;
+          sglist = current_command->request_buffer;
+          while(sgcount--)
+            {
+            tot_trans += sym53c416_write(base, sglist->address, sglist->length);
+            sglist++;
+            }
+          }
+        if(tot_trans < current_command->underflow)
+          printk("sym53c416: Warning: underflow, wrote %d bytes, request for %d bytes\n", tot_trans, current_command->underflow);
+        }
+      break;
+      }
+    case PHASE_DATA_IN:
+      {
+      if(int_reg & BS)
+        {
+        current_command->SCp.phase = data_in;
+        outb(FLUSH_FIFO, base + COMMAND_REG);
+        sym53c416_set_transfer_counter(base, current_command->request_bufflen);
+        outb(TRANSFER_INFORMATION | PIO_MODE, base + COMMAND_REG);
+        if(!current_command->use_sg)
+          tot_trans = sym53c416_read(base, current_command->request_buffer, current_command->request_bufflen);
+        else
+          {
+          sgcount = current_command->use_sg;
+          sglist = current_command->request_buffer;
+          while(sgcount--)
+            {
+            tot_trans += sym53c416_read(base, sglist->address, sglist->length);
+            sglist++;
+            }
+          }
+        if(tot_trans < current_command->underflow)
+          printk("sym53c416: Warning: underflow, read %d bytes, request for %d bytes\n", tot_trans, current_command->underflow);
+        }
+      break;
+      }
+    case PHASE_COMMAND:
+      {
+      current_command->SCp.phase = command_ph;
+      printk("sym53c416: Warning: Unknown interrupt in command phase\n");
+      break;
+      }
+    case PHASE_STATUS:
+      {
+      current_command->SCp.phase = status_ph;
+      outb(FLUSH_FIFO, base + COMMAND_REG);
+      outb(INIT_COMM_COMPLETE_SEQ, base + COMMAND_REG);
+      break;
+      }
+    case PHASE_RESERVED_1:
+    case PHASE_RESERVED_2:
+      {
+      printk("sym53c416: Warning: Reserved phase\n");
+      break;
+      }
+    case PHASE_MESSAGE_OUT:
+      {
+      current_command->SCp.phase = message_out;
+      outb(SET_ATN, base + COMMAND_REG);
+      outb(MSG_ACCEPTED, base + COMMAND_REG);
+      break;
+      }
+    case PHASE_MESSAGE_IN:
+      {
+      current_command->SCp.phase = message_in;
+      current_command->SCp.Status = inb(base + SCSI_FIFO);
+      current_command->SCp.Message = inb(base + SCSI_FIFO);
+      if(current_command->SCp.Message == SAVE_POINTERS || current_command->SCp.Message == DISCONNECT)
+        outb(SET_ATN, base + COMMAND_REG);
+      outb(MSG_ACCEPTED, base + COMMAND_REG);
+      break;
+      }
+    }
+  }
+
+static void sym53c416_init(int base, int scsi_id)
+  {
+  outb(RESET_CHIP, base + COMMAND_REG);
+  outb(NOOP, base + COMMAND_REG);
+  outb(0x99, base + TOM); /* Time out of 250 ms */
+  outb(0x05, base + STP);
+  outb(0x00, base + SYNC_OFFSET);
+  outb(EPC | scsi_id, base + CONF_REG_1);
+  outb(FE | SCSI2 | TBPA, base + CONF_REG_2);
+  outb(IDMRC | QTE | CDB10 | FSCSI | FCLK, base + CONF_REG_3);
+  outb(0x83 | EAN, base + CONF_REG_4);
+  outb(IE | WSE0, base + CONF_REG_5);
+  outb(0, base + FEATURE_EN);
+  }
+
+static int sym53c416_probeirq(int base, int scsi_id)
+  {
+  int irq, irqs, i;
+
+  /* Clear interrupt register */
+  inb(base + INT_REG);
+  /* Start probing for irq's */
+  irqs = probe_irq_on();
+  /* Reinit chip */
+  sym53c416_init(base, scsi_id);
+  /* Cause interrupt */
+  outb(NOOP, base + COMMAND_REG);
+  outb(ILLEGAL, base + COMMAND_REG);
+  outb(0x07, base + DEST_BUS_ID);
+  outb(0x00, base + DEST_BUS_ID);
+  /* Wait for interrupt to occur */
+  i = jiffies + 20;
+  while(i > jiffies && !(inb(base + STATUS_REG) & SCI))
+    barrier();
+  if(i <= jiffies) /* timed out */
+    return 0;
+  /* Get occurred irq */
+  irq = probe_irq_off(irqs);
+  sym53c416_init(base, scsi_id);
+  return irq;
+  }
+
+/* Setup: sym53c416=base,irq */
+void sym53c416_setup(char *str, int *ints)
+  {
+  int i;
+
+  if(host_index >= MAXHOSTS)
+    {
+    printk("sym53c416.c: Too many hosts defined\n");
+    }
+  else
+    {
+    if(ints[0] < 1 || ints[0] > 2)
+      {
+      printk("sym53c416.c: Wrong number of parameters:\n");
+      printk("sym53c416.c: usage: sym53c416=<base>[,<irq>]\n");
+      }
+    else
+      {
+      for(i = 0; i < host_index && i >= 0; i++)
+        if(hosts[i].base == ints[1])
+          i = -2;
+      if(i >= 0)
+        {
+        hosts[host_index].base = ints[1];
+        hosts[host_index].irq = (ints[0] == 2)? ints[2] : 0;
+        host_index++;
+        }
+      }
+    }
+  }
+
+static int sym53c416_test(int base)
+  {
+  outb(RESET_CHIP, base + COMMAND_REG);
+  outb(NOOP, base + COMMAND_REG);
+  if(inb(base + COMMAND_REG) != NOOP)
+    return 0;
+  if(!inb(base + TC_HIGH) || inb(base + TC_HIGH) == 0xFF)
+    return 0;
+  if((inb(base + PIO_INT_REG) & (FULL | EMPTY | CE | OUE | FIE | EIE)) != EMPTY)
+    return 0;
+  return 1;
+  }
+
+void sym53c416_probe(void)
+  {
+  int *base = probeaddrs;
+  int ints[2];
+
+  ints[0] = 1;
+  for(; *base; base++)
+    if(!check_region(*base, IO_RANGE) && sym53c416_test(*base))
+      {
+      ints[1] = *base;
+      sym53c416_setup(NULL, ints);
+      }
+  }
+
+int sym53c416_detect(Scsi_Host_Template *tpnt)
+  {
+  unsigned long flags;
+  struct Scsi_Host * shpnt = NULL;
+  int i;
+  int count;
+
+#ifdef MODULE
+  int ints[3];
+
+  ints[0] = 2;
+  if(sym53c416_base)
+    {
+    ints[1] = sym53c416_base;
+    ints[2] = sym53c416_irq;
+    sym53c416_setup(NULL, ints);
+    }
+  if(sym53c416_base_1)
+    {
+    ints[1] = sym53c416_base_1;
+    ints[2] = sym53c416_irq_1;
+    sym53c416_setup(NULL, ints);
+    }
+  if(sym53c416_base_2)
+    {
+    ints[1] = sym53c416_base_2;
+    ints[2] = sym53c416_irq_2;
+    sym53c416_setup(NULL, ints);
+    }
+  if(sym53c416_base_3)
+    {
+    ints[1] = sym53c416_base_3;
+    ints[2] = sym53c416_irq_3;
+    sym53c416_setup(NULL, ints);
+    }
+#endif
+
+  printk("sym53c416.c: %s\n", VERSION_STRING);
+
+  sym53c416_probe();
+
+  /* Now we register and set up each host adapter found... */
+  for(count = 0, i = 0; i < host_index; i++)
+    if(!sym53c416_test(hosts[i].base))
+      printk("No sym53c416 found at address 0x%03x\n", hosts[i].base);
+    else
+      {
+      if(hosts[i].irq == 0)
+        /* We don't have an irq yet, so we should probe for one */
+        if((hosts[i].irq = sym53c416_probeirq(hosts[i].base, hosts[i].scsi_id)) == 0)
+          printk("irq autoprobing failed for sym53c416 at address 0x%03x\n", hosts[i].base);
+      if(hosts[i].irq && !check_region(hosts[i].base, IO_RANGE))
+        {
+        shpnt = scsi_register(tpnt, 0);
+        save_flags(flags);
+        cli();
+        /* Request for specified IRQ */
+        if(request_irq(hosts[i].irq, sym53c416_intr_handle, 0, ID, NULL))
+          {
+          restore_flags(flags);
+          printk("Unable to assign IRQ %d\n", hosts[i].irq);
+          scsi_unregister(shpnt);
+          }
+        else
+          {
+          /* Inform the kernel of our IO range */
+          request_region(hosts[i].base, IO_RANGE, ID);
+          shpnt->unique_id = hosts[i].base;
+          shpnt->io_port = hosts[i].base;
+          shpnt->n_io_port = IO_RANGE;
+          shpnt->irq = hosts[i].irq;
+          shpnt->this_id = hosts[i].scsi_id;
+          sym53c416_init(hosts[i].base, hosts[i].scsi_id);
+          count++;
+          restore_flags(flags);
+          }
+        }
+      }
+  return count;
+  }
+
+const char *sym53c416_info(struct Scsi_Host *SChost)
+  {
+  int i;
+  int base = SChost->io_port;
+  int irq = SChost->irq;
+  int scsi_id = 0;
+  int rev = inb(base + TC_HIGH);
+
+  for(i = 0; i < host_index; i++)
+    if(hosts[i].base == base)
+      scsi_id = hosts[i].scsi_id;
+  sprintf(info, "Symbios Logic 53c416 (rev. %d) at 0x%03x, irq %d, SCSI-ID %d, %s pio", rev, base, irq, scsi_id, (fastpio)? "fast" : "slow");
+  return info;
+  }
+
+int sym53c416_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
+  {
+  int base;
+  unsigned long flags = 0;
+  int i;
+
+  /* Store base register as we can have more than one controller in the system */
+  base = SCpnt->host->io_port;
+  current_command = SCpnt;                  /* set current command                */
+  current_command->scsi_done = done;        /* set ptr to done function           */
+  current_command->SCp.phase = command_ph;  /* currect phase is the command phase */
+  current_command->SCp.Status = 0;
+  current_command->SCp.Message = 0;
+
+  save_flags(flags);
+  cli();
+  outb(SCpnt->target, base + DEST_BUS_ID); /* Set scsi id target        */
+  outb(FLUSH_FIFO, base + COMMAND_REG);    /* Flush SCSI and PIO FIFO's */
+  /* Write SCSI command into the SCSI fifo */
+  for(i = 0; i < SCpnt->cmd_len; i++)
+    outb(SCpnt->cmnd[i], base + SCSI_FIFO);
+  /* Start selection sequence */
+  outb(SEL_WITHOUT_ATN_SEQ, base + COMMAND_REG);
+  /* Now an interrupt will be generated which we will catch in out interrupt routine */
+  restore_flags(flags);
+  return 0;
+  }
+
+static void internal_done(Scsi_Cmnd *SCpnt)
+  {
+  SCpnt->SCp.Status++;
+  }
+
+int sym53c416_command(Scsi_Cmnd *SCpnt)
+  {
+  sym53c416_queuecommand(SCpnt, internal_done);
+  SCpnt->SCp.Status = 0;
+  while(!SCpnt->SCp.Status)
+    barrier();
+  return SCpnt->result;
+  }
+
+int sym53c416_abort(Scsi_Cmnd *SCpnt)
+  {
+  printk("sym53c416_abort\n");
+
+  /* We don't know how to abort for the moment */
+  return SCSI_ABORT_SNOOZE;
+  }
+
+int sym53c416_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
+  {
+  int base;
+  int scsi_id = -1;
+  int i;
+
+  printk("sym53c416_reset\n");
+  base = SCpnt->host->io_port;
+  /* search scsi_id */
+  for(i = 0; i < host_index && scsi_id != -1; i++)
+    if(hosts[i].base == base)
+      scsi_id = hosts[i].scsi_id;
+  outb(RESET_CHIP, base + COMMAND_REG);
+  outb(NOOP | PIO_MODE, base + COMMAND_REG);
+  outb(RESET_SCSI_BUS, base + COMMAND_REG);
+  sym53c416_init(base, scsi_id);
+  return SCSI_RESET_PENDING;
+  }
+
+int sym53c416_bios_param(Disk *disk, kdev_t dev, int *ip)
+  {
+  int size;
+
+  size = disk->capacity;
+  ip[0] = 64;                         /* heads                        */
+  ip[1] = 32;                         /* sectors                      */
+  if((ip[2] = size >> 11) > 1024)     /* cylinders, test for big disk */
+    {
+    ip[0] = 255;                      /* heads                        */
+    ip[1] = 63;                       /* sectors                      */
+    ip[2] = size / (255 * 63);        /* cylinders                    */
+    }
+  return 0;
+  }
+
+/* Loadable module support */
+#ifdef MODULE
+
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,26)
+MODULE_AUTHOR("Lieven Willems");
+MODULE_PARM(sym53c416, "1-2i");
+MODULE_PARM(sym53c416_1, "1-2i");
+MODULE_PARM(sym53c416_2, "1-2i");
+MODULE_PARM(sym53c416_3, "1-2i");
+#endif
+
+Scsi_Host_Template driver_template = SYM53C416;
+
+#include "scsi_module.c"
+#endif
diff -u --recursive --new-file v2.2.2/linux/drivers/scsi/sym53c416.h linux/drivers/scsi/sym53c416.h
--- v2.2.2/linux/drivers/scsi/sym53c416.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/sym53c416.h	Mon Mar  8 15:52:16 1999
@@ -0,0 +1,91 @@
+/*
+ *  sym53c416.h
+ * 
+ *  Copyright (C) 1998 Lieven Willems (lw_linux@hotmail.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, 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.
+ *
+ */
+
+#ifndef _SYM53C416_H
+#define _SYM53C416_H
+
+#if !defined(LINUX_VERSION_CODE)
+#include <linux/version.h>
+#endif
+
+#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
+
+#include <linux/types.h>
+#include <linux/kdev_t.h>
+
+#define SYM53C416_SCSI_ID 7
+
+extern struct proc_dir_entry proc_scsi_sym53c416;
+
+extern int sym53c416_detect(Scsi_Host_Template *);
+extern const char *sym53c416_info(struct Scsi_Host *);
+extern int sym53c416_command(Scsi_Cmnd *);
+extern int sym53c416_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+extern int sym53c416_abort(Scsi_Cmnd *);
+extern int sym53c416_reset(Scsi_Cmnd *, unsigned int);
+extern int sym53c416_bios_param(Disk *, kdev_t, int *);
+extern void sym53c416_setup(char *str, int *ints);
+
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,75)
+
+#define SYM53C416 {                                          \
+                  proc_dir:          &proc_scsi_sym53c416,   \
+                  name:              "Symbios Logic 53c416", \
+                  detect:            sym53c416_detect,       \
+                  info:              sym53c416_info,         \
+                  command:           sym53c416_command,      \
+                  queuecommand:      sym53c416_queuecommand, \
+                  abort:             sym53c416_abort,        \
+                  reset:             sym53c416_reset,        \
+                  bios_param:        sym53c416_bios_param,   \
+                  can_queue:         1,                      \
+                  this_id:           SYM53C416_SCSI_ID,      \
+                  sg_tablesize:      32,                     \
+                  cmd_per_lun:       1,                      \
+                  unchecked_isa_dma: 1,                      \
+                  use_clustering:    ENABLE_CLUSTERING       \
+                  }
+
+#else
+
+#define SYM53C416 {                       \
+                  NULL,                   \
+                  NULL,                   \
+                  &proc_scsi_sym53c416,   \
+                  NULL,                   \
+                  "Symbios Logic 53c416", \
+                  sym53c416_detect,       \
+                  NULL,                   \
+                  sym53c416_info,         \
+                  sym53c416_command,      \
+                  sym53c416_queuecommand, \
+                  sym53c416_abort,        \
+                  sym53c416_reset,        \
+                  NULL,                   \
+                  sym53c416_bios_param,   \
+                  1,                      \
+                  SYM53C416_SCSI_ID,      \
+                  32, /* ???? */          \
+                  1,                      \
+                  0,                      \
+                  1,                      \
+                  ENABLE_CLUSTERING       \
+                  }
+
+#endif
+
+#endif
diff -u --recursive --new-file v2.2.2/linux/drivers/sound/Config.in linux/drivers/sound/Config.in
--- v2.2.2/linux/drivers/sound/Config.in	Tue Jan 19 11:32:51 1999
+++ linux/drivers/sound/Config.in	Sun Mar  7 15:22:06 1999
@@ -12,7 +12,7 @@
 dep_tristate 'Ensoniq AudioPCI (ES1370)' CONFIG_SOUND_ES1370 $CONFIG_SOUND
 if [ "$CONFIG_SOUND_ES1370" = "y" ]; then
    bool 'Joystick support at boot time' CONFIG_SOUND_ES1370_JOYPORT_BOOT
-fi  
+fi
 dep_tristate 'Creative Ensoniq AudioPCI 97 (ES1371)' CONFIG_SOUND_ES1371 $CONFIG_SOUND
 if [ "$CONFIG_SOUND_ES1371" = "y" ]; then
    bool 'Joystick support at boot time' CONFIG_SOUND_ES1371_JOYPORT_BOOT
@@ -75,6 +75,10 @@
 dep_tristate 'OSS sound modules' CONFIG_SOUND_OSS $CONFIG_SOUND
 
 if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
+  if [ "$CONFIG_SOUND_OSS" = "y" ]; then
+    bool 'Persistent DMA buffers' CONFIG_SOUND_DMAP
+  fi
+
   dep_tristate 'ProAudioSpectrum 16 support' CONFIG_SOUND_PAS $CONFIG_SOUND_OSS
   if [ "$CONFIG_SOUND_PAS" = "y" ]; then
       int 'PAS16 IRQ 3, 4, 5, 7, 9, 10, 11, 12, 14 or 15' CONFIG_PAS_IRQ 10
@@ -138,6 +142,7 @@
   
   dep_tristate 'Microsoft Sound System support' CONFIG_SOUND_MSS $CONFIG_SOUND_OSS
   if [ "$CONFIG_SOUND_MSS" = "y" ]; then
+      bool 'Enable support for the SoundPro mixer' CONFIG_SOUND_SPRO
       hex 'MSS/WSS I/O base 530, 604, E80 or F40' CONFIG_MSS_BASE 530
       int 'MSS/WSS IRQ 7, 9, 10 or 11' CONFIG_MSS_IRQ 11
       int 'MSS/WSS DMA 0, 1 or 3' CONFIG_MSS_DMA 3
diff -u --recursive --new-file v2.2.2/linux/drivers/sound/ad1848.c linux/drivers/sound/ad1848.c
--- v2.2.2/linux/drivers/sound/ad1848.c	Wed Jan 20 23:14:06 1999
+++ linux/drivers/sound/ad1848.c	Sun Mar  7 15:22:06 1999
@@ -100,6 +100,11 @@
 
 static int nr_ad1848_devs = 0;
 int deskpro_xl = 0;
+#ifdef CONFIG_SOUND_SPRO
+int soundpro = 1;
+#else
+int soundpro = 0;
+#endif
 
 static volatile char irq2dev[17] = {
 	-1, -1, -1, -1, -1, -1, -1, -1,
@@ -312,22 +317,21 @@
 		if (mask & (1 << i))
 			n++;
 
-	if (n == 0)
-		mask = SOUND_MASK_MIC;
-	else if (n != 1)	/* Too many devices selected */
-	{
-		  mask &= ~devc->recmask;	/* Filter out active settings */
+	if (!soundpro) {
+		if (n == 0)
+			mask = SOUND_MASK_MIC;
+		else if (n != 1) {	/* Too many devices selected */
+			mask &= ~devc->recmask;	/* Filter out active settings */
 
-		n = 0;
-		for (i = 0; i < 32; i++)	/* Count selected device bits */
-			if (mask & (1 << i))
-				n++;
+			n = 0;
+			for (i = 0; i < 32; i++)	/* Count selected device bits */
+				if (mask & (1 << i))
+					n++;
 
-		if (n != 1)
-			mask = SOUND_MASK_MIC;
-	}
-	switch (mask)
-	{
+			if (n != 1)
+				mask = SOUND_MASK_MIC;
+		}
+		switch (mask) {
 		case SOUND_MASK_MIC:
 			recdev = 2;
 			break;
@@ -349,11 +353,38 @@
 		default:
 			mask = SOUND_MASK_MIC;
 			recdev = 2;
-	}
+		}
+
+		recdev <<= 6;
+		ad_write(devc, 0, (ad_read(devc, 0) & 0x3f) | recdev);
+		ad_write(devc, 1, (ad_read(devc, 1) & 0x3f) | recdev);
+	} else { /* soundpro */
+		unsigned char val;
+		int set_rec_bit;
+		int j;
+
+		for (i = 0; i < 32; i++) {	/* For each bit */
+			if ((devc->supported_rec_devices & (1 << i)) == 0)
+				continue;	/* Device not supported */
+
+			for (j = LEFT_CHN; j <= RIGHT_CHN; j++) {
+				if (devc->mix_devices[i][j].nbits == 0) /* Inexistent channel */
+					continue;
+
+				/*
+				 * This is tricky:
+				 * set_rec_bit becomes 1 if the corresponding bit in mask is set
+				 * then it gets flipped if the polarity is inverse
+				 */
+				set_rec_bit = ((mask & (1 << i)) != 0) ^ devc->mix_devices[i][j].recpol;
 
-	recdev <<= 6;
-	ad_write(devc, 0, (ad_read(devc, 0) & 0x3f) | recdev);
-	ad_write(devc, 1, (ad_read(devc, 1) & 0x3f) | recdev);
+				val = ad_read(devc, devc->mix_devices[i][j].recreg);
+				val &= ~(1 << devc->mix_devices[i][j].recpos);
+				val |= (set_rec_bit << devc->mix_devices[i][j].recpos);
+				ad_write(devc, devc->mix_devices[i][j].recreg, val);
+			}
+		}
+	}
 
 	/* Rename the mixer bits back if necessary */
 	for (i = 0; i < 32; i++)
@@ -371,7 +402,8 @@
 	return mask;
 }
 
-static void change_bits(ad1848_info * devc, unsigned char *regval, int dev, int chn, int newval)
+static void change_bits(ad1848_info * devc, unsigned char *regval,
+			unsigned char *muteval, int dev, int chn, int newval)
 {
 	unsigned char mask;
 	int shift;
@@ -379,7 +411,7 @@
 	int mutemask;
 	int set_mute_bit;
 
-	set_mute_bit = (newval == 0);
+	set_mute_bit = (newval == 0) ^ devc->mix_devices[dev][chn].mutepol;
 
 	if (devc->mix_devices[dev][chn].polarity == 1)	/* Reverse */
 		newval = 100 - newval;
@@ -399,8 +431,11 @@
 	}
 
 	newval = (int) ((newval * mask) + 50) / 100;	/* Scale it */
-	*regval &= (~(mask << shift)) & (mutemask);	/* Clear bits */
-	*regval |= ((newval & mask) << shift) | mute;	/* Set new value */
+	*regval &= ~(mask << shift);			/* Clear bits */
+	*regval |= (newval & mask) << shift;		/* Set new value */
+
+	*muteval &= mutemask;
+	*muteval |= mute;
 }
 
 static int ad1848_mixer_get(ad1848_info * devc, int dev)
@@ -413,15 +448,36 @@
 	return devc->levels[dev];
 }
 
+static void ad1848_mixer_set_channel(ad1848_info *devc, int dev, int value, int channel)
+{
+	int regoffs, muteregoffs;
+	unsigned char val, muteval;
+
+	regoffs = devc->mix_devices[dev][channel].regno;
+	muteregoffs = devc->mix_devices[dev][channel].mutereg;
+	val = ad_read(devc, regoffs);
+
+	if (muteregoffs != regoffs) {
+		muteval = ad_read(devc, muteregoffs);
+		change_bits(devc, &val, &muteval, dev, channel, value);
+	}
+	else
+		change_bits(devc, &val, &val, dev, channel, value);
+
+	ad_write(devc, regoffs, val);
+	devc->saved_regs[regoffs] = val;
+	if (muteregoffs != regoffs) {
+		ad_write(devc, muteregoffs, muteval);
+		devc->saved_regs[muteregoffs] = muteval;
+	}
+}
+
 static int ad1848_mixer_set(ad1848_info * devc, int dev, int value)
 {
 	int left = value & 0x000000ff;
 	int right = (value & 0x0000ff00) >> 8;
 	int retvol;
 
-	int regoffs;
-	unsigned char val;
-
 	if (dev > 31)
 		return -EINVAL;
 
@@ -430,6 +486,9 @@
 
 	dev = devc->mixer_reroute[dev];
 
+	if (devc->mix_devices[dev][LEFT_CHN].nbits == 0)
+		return -EINVAL;
+
 	if (left > 100)
 		left = 100;
 	if (right > 100)
@@ -444,34 +503,21 @@
 	left = mix_cvt[left];
 	right = mix_cvt[right];
 
-	if (devc->mix_devices[dev][LEFT_CHN].nbits == 0)
-		return -EINVAL;
-
 	devc->levels[dev] = retvol;
 
 	/*
 	 * Set the left channel
 	 */
-
-	regoffs = devc->mix_devices[dev][LEFT_CHN].regno;
-	val = ad_read(devc, regoffs);
-	change_bits(devc, &val, dev, LEFT_CHN, left);
-	ad_write(devc, regoffs, val);
-	devc->saved_regs[regoffs] = val;
+	ad1848_mixer_set_channel(devc, dev, left, LEFT_CHN);
 
 	/*
 	 * Set the right channel
 	 */
-
 	if (devc->mix_devices[dev][RIGHT_CHN].nbits == 0)
-		return retvol;	/* Was just a mono channel */
-
-	regoffs = devc->mix_devices[dev][RIGHT_CHN].regno;
-	val = ad_read(devc, regoffs);
-	change_bits(devc, &val, dev, RIGHT_CHN, right);
-	ad_write(devc, regoffs, val);
-	devc->saved_regs[regoffs] = val;
+		goto out;
+	ad1848_mixer_set_channel(devc, dev, right, RIGHT_CHN);
 
+ out:
 	return retvol;
 }
 
@@ -487,6 +533,8 @@
 	for (i = 0; i < 32; i++)
 		devc->mixer_reroute[i] = i;
 
+	devc->supported_rec_devices = MODE1_REC_DEVICES;
+
 	switch (devc->model)
 	{
 		case MD_4231:
@@ -509,11 +557,18 @@
 			devc->supported_devices = MODE3_MIXER_DEVICES;
 			break;
 
+		case MD_1848:
+			if (soundpro) {
+				devc->supported_devices = SPRO_MIXER_DEVICES;
+				devc->supported_rec_devices = SPRO_REC_DEVICES;
+				devc->mix_devices = &(spro_mix_devices[0]);
+				break;
+			}
+
 		default:
 			devc->supported_devices = MODE1_MIXER_DEVICES;
 	}
 
-	devc->supported_rec_devices = MODE1_REC_DEVICES;
 	devc->orig_devices = devc->supported_devices;
 	devc->orig_rec_devices = devc->supported_rec_devices;
 
@@ -528,10 +583,20 @@
 	ad1848_set_recmask(devc, SOUND_MASK_MIC);
 	
 	devc->mixer_output_port = devc->levels[31] | AUDIO_HEADPHONE | AUDIO_LINE_OUT;
-	if (devc->mixer_output_port & AUDIO_SPEAKER)
-		ad_write(devc, 26, ad_read(devc, 26) & ~0x40);	/* Unmute mono out */
-	else
-		ad_write(devc, 26, ad_read(devc, 26) | 0x40);	/* Mute mono out */
+
+	if (!soundpro) {
+		if (devc->mixer_output_port & AUDIO_SPEAKER)
+			ad_write(devc, 26, ad_read(devc, 26) & ~0x40);	/* Unmute mono out */
+		else
+			ad_write(devc, 26, ad_read(devc, 26) | 0x40);	/* Mute mono out */
+	} else {
+		/*
+		 * From the "wouldn't it be nice if the mixer API had (better)
+		 * support for custom stuff" category
+		 */
+		/* Enable surround mode and SB16 mixer */
+		ad_write(devc, 16, 0x60);
+	}
 }
 
 static int ad1848_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
@@ -1357,6 +1422,8 @@
 	{
 		  devc->audio_flags &= ~DMA_DUPLEX;
 		  ad_write(devc, 9, ad_read(devc, 9) | 0x04);	/* Single DMA mode */
+		  if (soundpro)
+			  ad_write(devc, 12, ad_read(devc, 12) | 0x40);	/* Mode2 = enabled */
 	}
 
 	outb((0), io_Status(devc));	/* Clear pending interrupts */
@@ -1706,7 +1773,27 @@
 
 			DDB(printk("ad1848_detect() - step K\n"));
 		}
+	} else if (tmp1 == 0x0a) {
+		/*
+		 * Is it perhaps a SoundPro CMI8330?
+		 * If so, then we should be able to change indirect registers
+		 * greater than I15 after activating MODE2, even though reading
+		 * back I12 does not show it.
+		 */
+
+		/*
+		 * Let's try comparing register values
+		 */
+		for (i = 0; i < 16; i++) {
+			if ((tmp1 = ad_read(devc, i)) != (tmp2 = ad_read(devc, i + 16))) {
+				DDB(printk("ad1848 detect step H(%d/%x/%x) - SoundPro chip?\n", i, tmp1, tmp2));
+				soundpro = 1;
+				devc->chip_name = "SoundPro CMI 8330";
+				break;
+			}
+		}
 	}
+
 	DDB(printk("ad1848_detect() - step L\n"));
 	if (ad_flags)
 	{
@@ -2302,7 +2389,8 @@
 	    (hw_config->irq != 7)  &&
 	    (hw_config->irq != 9)  &&
 	    (hw_config->irq != 10) &&
-	    (hw_config->irq != 11))
+	    (hw_config->irq != 11) &&
+	    (hw_config->irq != 12))
 	{
 		printk(KERN_ERR "MSS: Bad IRQ %d\n", hw_config->irq);
 		return 0;
@@ -2555,6 +2643,7 @@
 MODULE_PARM(dma2, "i");			/* Second DMA channel */
 MODULE_PARM(type, "i");			/* Card type */
 MODULE_PARM(deskpro_xl, "i");		/* Special magic for Deskpro XL boxen */
+MODULE_PARM(soundpro, "i");		/* More special magic for SoundPro chips */
 
 int io = -1;
 int irq = -1;
diff -u --recursive --new-file v2.2.2/linux/drivers/sound/ad1848_mixer.h linux/drivers/sound/ad1848_mixer.h
--- v2.2.2/linux/drivers/sound/ad1848_mixer.h	Fri Oct 23 22:01:21 1998
+++ linux/drivers/sound/ad1848_mixer.h	Sun Mar  7 15:22:06 1999
@@ -24,7 +24,10 @@
  * solution).
  */
 #define MODE1_REC_DEVICES		(SOUND_MASK_LINE3 | SOUND_MASK_MIC | \
-					 SOUND_MASK_LINE1|SOUND_MASK_IMIX)
+					 SOUND_MASK_LINE1 | SOUND_MASK_IMIX)
+
+#define SPRO_REC_DEVICES		(SOUND_MASK_LINE | SOUND_MASK_MIC | \
+					 SOUND_MASK_CD | SOUND_MASK_LINE1)
 
 #define MODE1_MIXER_DEVICES		(SOUND_MASK_LINE1 | SOUND_MASK_MIC | \
 					 SOUND_MASK_LINE2 | \
@@ -47,16 +50,27 @@
 				 SOUND_MASK_LINE3 | \
 				 SOUND_MASK_IGAIN | SOUND_MASK_PCM)
 
+#define SPRO_MIXER_DEVICES	(SOUND_MASK_VOLUME | SOUND_MASK_PCM | \
+				 SOUND_MASK_LINE | SOUND_MASK_SYNTH | \
+				 SOUND_MASK_CD | SOUND_MASK_MIC | \
+				 SOUND_MASK_SPEAKER | SOUND_MASK_LINE1 | \
+				 SOUND_MASK_OGAIN)
+
 struct mixer_def {
-	unsigned int regno: 5;
-	unsigned int polarity:1;	/* 0=normal, 1=reversed */
-	unsigned int bitpos:3;
-	unsigned int nbits:3;
-	unsigned int mutepos:4;
+	unsigned int regno:5;		/* register number for volume */
+	unsigned int polarity:1;	/* volume polarity: 0=normal, 1=reversed */
+	unsigned int bitpos:3;		/* position of bits in register for volume */
+	unsigned int nbits:3;		/* number of bits in register for volume */
+	unsigned int mutereg:5;		/* register number for mute bit */
+	unsigned int mutepol:1;		/* mute polarity: 0=normal, 1=reversed */
+	unsigned int mutepos:4;		/* position of mute bit in register */
+	unsigned int recreg:5;		/* register number for recording bit */
+	unsigned int recpol:1;		/* recording polarity: 0=normal, 1=reversed */
+	unsigned int recpos:4;		/* position of recording bit in register */
 };
 
 static char mix_cvt[101] = {
-	0, 0,3,7,10,13,16,19,21,23,26,28,30,32,34,35,37,39,40,42,
+	 0, 0, 3, 7,10,13,16,19,21,23,26,28,30,32,34,35,37,39,40,42,
 	43,45,46,47,49,50,51,52,53,55,56,57,58,59,60,61,62,63,64,65,
 	65,66,67,68,69,70,70,71,72,73,73,74,75,75,76,77,77,78,79,79,
 	80,81,81,82,82,83,84,84,85,85,86,86,87,87,88,88,89,89,90,90,
@@ -77,7 +91,17 @@
  */
 
 #define MIX_ENT(name, reg_l, pola_l, pos_l, len_l, reg_r, pola_r, pos_r, len_r, mute_bit)	\
-	{{reg_l, pola_l, pos_l, len_l, mute_bit}, {reg_r, pola_r, pos_r, len_r, mute_bit}}
+	[name] = {{reg_l, pola_l, pos_l, len_l, reg_l, 0, mute_bit, 0, 0, 8},			\
+		  {reg_r, pola_r, pos_r, len_r, reg_r, 0, mute_bit, 0, 0, 8}}
+
+#define MIX_ENT2(name, reg_l, pola_l, pos_l, len_l, mute_reg_l, mute_pola_l, mute_pos_l, \
+		    rec_reg_l, rec_pola_l, rec_pos_l,					 \
+		 reg_r, pola_r, pos_r, len_r, mute_reg_r, mute_pola_r, mute_pos_r,	 \
+		    rec_reg_r, rec_pola_r, rec_pos_r)					 \
+	[name] = {{reg_l, pola_l, pos_l, len_l, mute_reg_l, mute_pola_l, mute_pos_l,	 \
+		    rec_reg_l, rec_pola_l, rec_pos_l},					 \
+		  {reg_r, pola_r, pos_r, len_r, mute_reg_r, mute_pola_r, mute_pos_r,	 \
+		    rec_reg_r, rec_pola_r, rec_pos_r}}
 
 static mixer_ents ad1848_mix_devices[32] = {
 MIX_ENT(SOUND_MIXER_VOLUME,	27, 1, 0, 4,	29, 1, 0, 4,  8),
@@ -142,6 +166,30 @@
 MIX_ENT(SOUND_MIXER_LINE1,	 2, 1, 1, 4,	 3, 1, 1, 4,  7),
 MIX_ENT(SOUND_MIXER_LINE2,	 4, 1, 1, 4,	 5, 1, 1, 4,  7),
 MIX_ENT(SOUND_MIXER_LINE3,	18, 1, 1, 4,	19, 1, 1, 4,  7)
+};
+
+static mixer_ents spro_mix_devices[32] = {
+MIX_ENT (SOUND_MIXER_VOLUME,	19, 0, 4, 4,			 19, 0, 0, 4,  8),
+MIX_ENT (SOUND_MIXER_BASS,	 0, 0, 0, 0,			  0, 0, 0, 0,  8),
+MIX_ENT (SOUND_MIXER_TREBLE,	 0, 0, 0, 0,			  0, 0, 0, 0,  8),
+MIX_ENT2(SOUND_MIXER_SYNTH,	 4, 1, 1, 4, 23, 0, 3,  0, 0, 8,
+	 			 5, 1, 1, 4, 23, 0, 3, 0, 0, 8),
+MIX_ENT (SOUND_MIXER_PCM,	 6, 1, 1, 4,			  7, 1, 1, 4,  8),
+MIX_ENT (SOUND_MIXER_SPEAKER,	18, 0, 3, 2,			  0, 0, 0, 0,  8),
+MIX_ENT2(SOUND_MIXER_LINE,	20, 0, 4, 4, 17, 1, 4, 16, 0, 2,
+	 			20, 0, 0, 4, 17, 1, 3, 16, 0, 1),
+MIX_ENT2(SOUND_MIXER_MIC,	18, 0, 0, 3, 17, 1, 0, 16, 0, 0,
+	 			 0, 0, 0, 0,  0, 0, 0,  0, 0, 0),
+MIX_ENT2(SOUND_MIXER_CD,	21, 0, 4, 4, 17, 1, 2, 16, 0, 4,
+				21, 0, 0, 4, 17, 1, 1, 16, 0, 3),
+MIX_ENT (SOUND_MIXER_IMIX,	 0, 0, 0, 0,			  0, 0, 0, 0,  8),
+MIX_ENT (SOUND_MIXER_ALTPCM,	 0, 0, 0, 0,			  0, 0, 0, 0,  8),
+MIX_ENT (SOUND_MIXER_RECLEV,	 0, 0, 0, 0,			  0, 0, 0, 0,  8),
+MIX_ENT (SOUND_MIXER_IGAIN,	 0, 0, 0, 0,			  0, 0, 0, 0,  8),
+MIX_ENT (SOUND_MIXER_OGAIN,	17, 1, 6, 1,			  0, 0, 0, 0,  8),
+/* This is external wavetable */
+MIX_ENT2(SOUND_MIXER_LINE1,	22, 0, 4, 4, 23, 1, 1, 23, 0, 4,
+	 			22, 0, 0, 4, 23, 1, 0, 23, 0, 5),
 };
 
 static int default_mixer_levels[32] =
diff -u --recursive --new-file v2.2.2/linux/drivers/sound/es1370.c linux/drivers/sound/es1370.c
--- v2.2.2/linux/drivers/sound/es1370.c	Fri Jan  8 22:36:10 1999
+++ linux/drivers/sound/es1370.c	Sun Mar  7 15:22:06 1999
@@ -1228,8 +1228,6 @@
 	if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))
 		return -EAGAIN;
 	db->mapped = 1;
-	vma->vm_file = file;
-	file->f_count++;
 	return 0;
 }
 
@@ -1597,6 +1595,7 @@
 	down(&s->open_sem);
 	if (file->f_mode & FMODE_WRITE) {
 		stop_dac2(s);
+		synchronize_irq();
 		dealloc_dmabuf(&s->dma_dac2);
 	}
 	if (file->f_mode & FMODE_READ) {
@@ -1725,8 +1724,6 @@
 	if (remap_page_range(vma->vm_start, virt_to_phys(s->dma_dac1.rawbuf), size, vma->vm_page_prot))
 		return -EAGAIN;
 	s->dma_dac1.mapped = 1;
-	vma->vm_file = file;
-	file->f_count++;
 	return 0;
 }
 
diff -u --recursive --new-file v2.2.2/linux/drivers/sound/es1371.c linux/drivers/sound/es1371.c
--- v2.2.2/linux/drivers/sound/es1371.c	Fri Jan  8 22:36:10 1999
+++ linux/drivers/sound/es1371.c	Sun Mar  7 10:37:40 1999
@@ -1675,8 +1675,6 @@
 	if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))
 		return -EAGAIN;
 	db->mapped = 1;
-	vma->vm_file = file;
-	file->f_count++;
 	return 0;
 }
 
@@ -2172,8 +2170,6 @@
 	if (remap_page_range(vma->vm_start, virt_to_phys(s->dma_dac1.rawbuf), size, vma->vm_page_prot))
 		return -EAGAIN;
 	s->dma_dac1.mapped = 1;
-	vma->vm_file = file;
-	file->f_count++;
 	return 0;
 }
 
diff -u --recursive --new-file v2.2.2/linux/drivers/sound/lowlevel/awe_compat.h linux/drivers/sound/lowlevel/awe_compat.h
--- v2.2.2/linux/drivers/sound/lowlevel/awe_compat.h	Fri Jan  8 22:36:11 1999
+++ linux/drivers/sound/lowlevel/awe_compat.h	Sun Mar  7 15:22:06 1999
@@ -54,7 +54,7 @@
 #include "../soundvers.h"
 #endif
 
-#if SOUND_INTERNAL_VERSION >= 0x30803
+#if defined(SOUND_INTERNAL_VERSION) && SOUND_INTERNAL_VERSION >= 0x30803
 /* OSS/Free-3.8 */
 #define AWE_NO_PATCHMGR
 #define AWE_OSS38
@@ -151,18 +151,9 @@
 #define my_malloc_memptr()	_mem_start
 #define my_free(ptr)	/* do nothing */
 
-static void *my_malloc(int size)
-{
-	char *ptr;
-	PERMANENT_MALLOC(ptr, char*, size, _mem_start);
-	return (void*)ptr;
-}
-#define my_kmalloc(size) my_malloc(size)
-#define kfree(ptr)	/* do nothing */
-
 /* allocate buffer only once */
 #define INIT_TABLE(buffer,index,nums,type) {\
-buffer = my_malloc(sizeof(type) * (nums)); index = (nums);\
+PERMANENT_MALLOC(buffer, char*, size, _mem_start); index = (nums);\
 }
 
 #else
@@ -173,8 +164,6 @@
 #define my_malloc_memptr()	0
 #define my_malloc(size)		vmalloc(size)
 #define my_free(ptr)		if (ptr) {vfree(ptr);}
-#define my_kmalloc(size)	kmalloc(size,GFP_KERNEL)
-#define my_kfree(ptr)		kfree(ptr)
 
 /* do not allocate buffer at beginning */
 #define INIT_TABLE(buffer,index,nums,type) {buffer=NULL; index=0;}
@@ -254,6 +243,14 @@
 #define sound_unload_mididev(dev)	/**/
 
 #endif /* AWE_MODULE_SUPPORT */
+
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,0)
+inline static void interruptible_sleep_on_timeout(struct wait_queue **q, unsigned long timeout)
+{
+	current->timeout = jiffies + timeout;
+	interruptible_sleep_on(q);
+}
+#endif
 
 #endif /* CONFIG_AWE32_SYNTH */
 
diff -u --recursive --new-file v2.2.2/linux/drivers/sound/lowlevel/awe_wave.c linux/drivers/sound/lowlevel/awe_wave.c
--- v2.2.2/linux/drivers/sound/lowlevel/awe_wave.c	Tue Dec 22 14:16:56 1998
+++ linux/drivers/sound/lowlevel/awe_wave.c	Sun Mar  7 15:22:06 1999
@@ -2,9 +2,9 @@
  * sound/awe_wave.c
  *
  * The low level driver for the AWE32/SB32/AWE64 wave table synth.
- *   version 0.4.3; Nov. 1, 1998
+ *   version 0.4.3; Feb. 1, 1999
  *
- * Copyright (C) 1996-1998 Takashi Iwai
+ * Copyright (C) 1996-1999 Takashi Iwai
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -204,16 +204,20 @@
 #if defined(AWE_MODULE_SUPPORT) && defined(MODULE)
 /* replace awe_port variable with exported variable */
 #define awe_port	io
-#define BASEVAR_DECL	/**/
+#define awe_mem_size	memsize
+int io = AWE_DEFAULT_BASE_ADDR; /* Emu8000 base address */
+int memsize = AWE_DEFAULT_MEM_SIZE; /* memory size in Kbytes */
+#ifdef MODULE_PARM
+MODULE_PARM(io, "i");
+MODULE_PARM_DESC(io, "base i/o port of Emu8000");
+MODULE_PARM(memsize, "i");
+MODULE_PARM_DESC(memsize, "onboard DRAM size in Kbytes");
+#endif
 #else
-#define BASEVAR_DECL	static
+static int awe_port = AWE_DEFAULT_BASE_ADDR;
+static int awe_mem_size = AWE_DEFAULT_MEM_SIZE;
 #endif /* module */
 
-/* awe32 base address (overwritten at initialization) */
-BASEVAR_DECL int awe_port = AWE_DEFAULT_BASE_ADDR;
-/* memory byte size */
-BASEVAR_DECL int memsize = AWE_DEFAULT_MEM_SIZE; /* for module option */
-static int awe_mem_size = -1;
 /* DRAM start offset */
 static int awe_mem_start = AWE_DRAM_OFFSET;
 
@@ -669,7 +673,7 @@
 
 #include <linux/pnp.h>
 
-BASEVAR_DECL int pnp = 1;	/* use PnP as default */
+static int pnp = 1;	/* use PnP as default */
 
 #define AWE_NUM_CHIPS	3
 static unsigned int pnp_ids[AWE_NUM_CHIPS] = {
@@ -812,6 +816,7 @@
 }
 
 #ifdef MODULE_PARM
+EXPORT_NO_SYMBOLS;
 MODULE_AUTHOR("Takashi Iwai <iwai@ww.uni-erlangen.de>");
 MODULE_DESCRIPTION("SB AWE32/64 WaveTable driver");
 MODULE_SUPPORTED_DEVICE("sound");
@@ -975,23 +980,9 @@
 #else
 
 static struct wait_queue *awe_sleeper = NULL;
-static void awe_wakeup(unsigned long dummy)
-{
-	wake_up(&awe_sleeper);
-}
-
-static struct timer_list awe_timer =
-{NULL, NULL, 0, 0, awe_wakeup};
-
 static void awe_wait(unsigned short delay)
 {
-	unsigned long   flags;
-	awe_timer.expires = jiffies + (HZ * (unsigned long)delay + 44099) / 44100;
-	add_timer(&awe_timer);
-	save_flags (flags);
-	cli();
-	sleep_on(&awe_sleeper);
-	restore_flags(flags);
+	interruptible_sleep_on_timeout(&awe_sleeper, (HZ * (unsigned long)delay + 44099) / 44100);
 }
 #endif /* wait by loop */
 
@@ -1553,7 +1544,7 @@
 			  vp->parm.moddcysus));
 
 	if (parm->volatk >= 0x80 && parm->voldelay >= 0x8000) {
-		awe_poke(AWE_ENVVAL(voice), 0xBFFF);
+		awe_poke(AWE_ENVVOL(voice), 0xBFFF);
 		vtarget = voltarget[voices[voice].avol%0x10]>>(voices[voice].avol>>4);
 	} else {
 		awe_poke(AWE_ENVVOL(voice),
@@ -3268,7 +3259,7 @@
 	sf_list *sf;
 
 	/* search for all sharing lists */
-	for (sf_id = rec->v.sf_id; sf_id > 0; sf_id = sf->shared) {
+	for (sf_id = rec->v.sf_id; sf_id > 0 && sf_id <= current_sf_id; sf_id = sf->shared) {
 		sf = &sflists[sf_id - 1];
 		for (j = sf->infos; j >= 0; j = infos[j].next) {
 			awe_voice_list *p = &infos[j];
@@ -4201,7 +4192,7 @@
 		if (id1 < id2) { /* make sure id1 > id2 */
 			int tmp; tmp = id1; id1 = id2; id2 = tmp;
 		}
-		for (i = sflists[id1-1].shared; i > 0; i = sflists[i-1].shared) {
+		for (i = sflists[id1-1].shared; i > 0 && i <= current_sf_id; i = sflists[i-1].shared) {
 			if (i == id2)
 				return TRUE;
 		}
@@ -4223,10 +4214,10 @@
 			return i;
 	}
 #ifdef AWE_ALLOW_SAMPLE_SHARING
-	if (sflists[sf-1].shared) { /* search recursively */
+	if ((i = sflists[sf-1].shared) > 0 && i <= current_sf_id) { /* search recursively */
 		if (level > current_sf_id)
 			return -1; /* strange sharing loop.. quit */
-		return search_sample_index(sflists[sf-1].shared, sample, level + 1);
+		return search_sample_index(i, sample, level + 1);
 	}
 #endif
 	return -1;
@@ -4272,10 +4263,12 @@
 		    note <= infos[rec].v.high &&
 		    velocity >= infos[rec].v.vellow &&
 		    velocity <= infos[rec].v.velhigh) {
-			vlist[nvoices] = &infos[rec].v;
-			if (infos[rec].type == V_ST_MAPPED) /* mapper */
+			if (infos[rec].type == V_ST_MAPPED) {
+				/* mapper */
+				vlist[0] = &infos[rec].v;
 				return -1;
-			nvoices++;
+			}
+			vlist[nvoices++] = &infos[rec].v;
 			if (nvoices >= AWE_MAX_VOICES)
 				break;
 		}
@@ -5009,8 +5002,6 @@
 		DEBUG(0,printk("AWE32 not found\n"));
 		return 0;
 	}
-	if (memsize >= 0) /* given by config file or module option */
-		awe_mem_size = memsize * 1024; /* convert to Kbytes */
 
 	return 1;
 }
@@ -5028,8 +5019,13 @@
 static void
 awe_check_dram(void)
 {
-	if (awe_mem_size >= 0) /* already initialized */
+	if (awe_present) /* already initialized */
 		return;
+
+	if (awe_mem_size >= 0) { /* given by config file or module option */
+		awe_mem_size *= 1024; /* convert to Kbytes */
+		return;
+	}
 
 	awe_open_dram_for_check();
 
diff -u --recursive --new-file v2.2.2/linux/drivers/sound/mad16.c linux/drivers/sound/mad16.c
--- v2.2.2/linux/drivers/sound/mad16.c	Fri Jan  8 22:36:11 1999
+++ linux/drivers/sound/mad16.c	Sun Mar  7 15:22:06 1999
@@ -800,7 +800,7 @@
 
 		mad_write(MC3_PORT, tmp | 0x04);
 		hw_config->driver_use_1 = SB_MIDI_ONLY;
-		return sb_dsp_detect(hw_config);
+		return sb_dsp_detect(hw_config, 0, 0);
 #else
 		return 0;
 #endif
diff -u --recursive --new-file v2.2.2/linux/drivers/sound/sb.h linux/drivers/sound/sb.h
--- v2.2.2/linux/drivers/sound/sb.h	Tue Feb 23 15:21:34 1999
+++ linux/drivers/sound/sb.h	Sun Mar  7 15:22:06 1999
@@ -47,11 +47,13 @@
 #define MDL_AZTECH	13	/* Aztech Sound Galaxy family */
 #define MDL_ES1868MIDI	14	/* MIDI port of ESS1868 */
 #define MDL_AEDSP	15	/* Audio Excel DSP 16 */
+#define MDL_ESSPCI	16	/* ESS PCI card */
 
 #define SUBMDL_ALS007	42	/* ALS-007 differs from SB16 only in mixer */
 				/* register assignment */
 #define SUBMDL_ALS100	43	/* ALS-100 allows sampling rates of up */
 				/* to 48kHz */
+				
 /*
  * Config flags
  */
@@ -60,6 +62,7 @@
 #define SB_NO_AUDIO	0x00000004
 #define SB_NO_RECORDING	0x00000008 /* No audio recording */
 #define SB_MIDI_ONLY	(SB_NO_AUDIO|SB_NO_MIXER)
+#define SB_PCI_IRQ	0x00000010 /* PCI shared IRQ */
 
 struct mixer_def {
 	unsigned int regno: 8;
@@ -86,6 +89,8 @@
 	   int base;
 	   int irq;
 	   int dma8, dma16;
+	   
+	   int pcibase;		/* For ESS Maestro etc */
 
 	/* State variables */
  	   int opened;
@@ -128,13 +133,24 @@
 	   void (*midi_input_intr) (int dev, unsigned char data);
 	   void *midi_irq_cookie;	/* IRQ cookie for the midi */
 	} sb_devc;
+	
+/*
+ *	PCI card types
+ */
 
+#define	SB_PCI_ESSMAESTRO	1	/* ESS Maestro Legacy */
+#define	SB_PCI_YAMAHA		2	/* Yamaha Legacy */
+
+/* 
+ *	Functions
+ */
+ 
 int sb_dsp_command (sb_devc *devc, unsigned char val);
 int sb_dsp_get_byte(sb_devc * devc);
 int sb_dsp_reset (sb_devc *devc);
 void sb_setmixer (sb_devc *devc, unsigned int port, unsigned int value);
 unsigned int sb_getmixer (sb_devc *devc, unsigned int port);
-int sb_dsp_detect (struct address_info *hw_config);
+int sb_dsp_detect (struct address_info *hw_config, int pci, int pciio);
 int sb_dsp_init (struct address_info *hw_config);
 void sb_dsp_unload(struct address_info *hw_config, int sbmpu);
 int sb_mixer_init(sb_devc *devc);
diff -u --recursive --new-file v2.2.2/linux/drivers/sound/sb_card.c linux/drivers/sound/sb_card.c
--- v2.2.2/linux/drivers/sound/sb_card.c	Tue Feb 23 15:21:34 1999
+++ linux/drivers/sound/sb_card.c	Sun Mar  7 15:22:06 1999
@@ -103,7 +103,7 @@
 		printk(KERN_ERR "sb_card: I/O port %x is already in use\n\n", hw_config->io_base);
 		return 0;
 	}
-	return sb_dsp_detect(hw_config);
+	return sb_dsp_detect(hw_config, 0, 0);
 }
 
 void unload_sb(struct address_info *hw_config)
@@ -135,6 +135,7 @@
 int mad16 = 0;		/* Set mad16=1 to load this as support for mad16 */
 int trix = 0;		/* Set trix=1 to load this as support for trix */
 int pas2 = 0;		/* Set pas2=1 to load this as support for pas2 */
+int support = 0;	/* Set support to load this as a support module */
 int sm_games = 0;	/* Mixer - see sb_mixer.c */
 int acer = 0;		/* Do acer notebook init */
 
@@ -145,6 +146,7 @@
 MODULE_PARM(mpu_io, "i");
 MODULE_PARM(type, "i");
 MODULE_PARM(mad16, "i");
+MODULE_PARM(support, "i");
 MODULE_PARM(trix, "i");
 MODULE_PARM(pas2, "i");
 MODULE_PARM(sm_games, "i");
@@ -156,7 +158,7 @@
 {
 	printk(KERN_INFO "Soundblaster audio driver Copyright (C) by Hannu Savolainen 1993-1996\n");
 
-	if (mad16 == 0 && trix == 0 && pas2 == 0)
+	if (mad16 == 0 && trix == 0 && pas2 == 0 && support == 0)
 	{
 		if (io == -1 || dma == -1 || irq == -1)
 		{
@@ -191,7 +193,7 @@
 {
 	if (smw_free)
 		vfree(smw_free);
-	if (!mad16 && !trix && !pas2)
+	if (!mad16 && !trix && !pas2 && !support)
 		unload_sb(&config);
 	if (sbmpu)
 		unload_sbmpu(&config_mpu);
diff -u --recursive --new-file v2.2.2/linux/drivers/sound/sb_common.c linux/drivers/sound/sb_common.c
--- v2.2.2/linux/drivers/sound/sb_common.c	Mon Jan 25 17:44:34 1999
+++ linux/drivers/sound/sb_common.c	Sun Mar  7 15:22:06 1999
@@ -179,13 +179,25 @@
 		status = inb(DSP_DATA_AVL16);
 }
 
+static void pci_intr(sb_devc *devc)
+{
+	int src = inb(devc->pcibase+0x1A);
+	src&=3;
+	if(src)
+		sb_intr(devc);
+}
+
 static void sbintr(int irq, void *dev_id, struct pt_regs *dummy)
 {
-    sb_devc *devc = dev_id;
+	sb_devc *devc = dev_id;
 
 	devc->irq_ok = 1;
 
 	switch (devc->model) {
+	case MDL_ESSPCI:
+		pci_intr (devc);
+		break;
+		
 	case MDL_ESS:
 		ess_intr (devc);
 		break;
@@ -478,7 +490,7 @@
 #endif
 }
 
-int sb_dsp_detect(struct address_info *hw_config)
+int sb_dsp_detect(struct address_info *hw_config, int pci, int pciio)
 {
 	sb_devc sb_info;
 	sb_devc *devc = &sb_info;
@@ -508,7 +520,22 @@
 	devc->dma8 = hw_config->dma;
 
 	devc->dma16 = -1;
-
+	devc->pcibase = pciio;
+	
+	if(pci == SB_PCI_ESSMAESTRO)
+	{
+		devc->model = MDL_ESSPCI;
+		devc->caps |= SB_PCI_IRQ;
+		hw_config->driver_use_1 |= SB_PCI_IRQ;
+		hw_config->card_subtype	= MDL_ESSPCI;
+	}
+	
+	if(pci == SB_PCI_YAMAHA)
+	{
+		devc->caps |= SB_PCI_IRQ;
+		hw_config->driver_use_1 |= SB_PCI_IRQ;
+	}
+	
 	if (acer)
 	{
 		cli();
@@ -569,6 +596,10 @@
 				}
 		}
 	}
+	
+	if(devc->type == MDL_ESSPCI)
+		devc->model = MDL_ESSPCI;
+		
 	/*
 	 * Save device information for sb_dsp_init()
 	 */
@@ -619,7 +650,15 @@
 
 	if (!(devc->caps & SB_NO_AUDIO && devc->caps & SB_NO_MIDI) && hw_config->irq > 0)
 	{			/* IRQ setup */
-		if (request_irq(hw_config->irq, sbintr, 0, "soundblaster", devc) < 0)
+		
+		/*
+		 *	ESS PCI cards do shared PCI IRQ stuff. Since they
+		 *	will get shared PCI irq lines we must cope.
+		 */
+		 
+		int i=(devc->caps&SB_PCI_IRQ)?SA_SHIRQ:0;
+		
+		if (request_irq(hw_config->irq, sbintr, i, "soundblaster", devc) < 0)
 		{
 			printk(KERN_ERR "SB: Can't allocate IRQ%d\n", hw_config->irq);
 			return 0;
diff -u --recursive --new-file v2.2.2/linux/drivers/sound/sb_mixer.c linux/drivers/sound/sb_mixer.c
--- v2.2.2/linux/drivers/sound/sb_mixer.c	Mon Jan 25 17:44:34 1999
+++ linux/drivers/sound/sb_mixer.c	Sun Mar  7 15:22:06 1999
@@ -673,6 +673,7 @@
 
 	switch (devc->model)
 	{
+		case MDL_ESSPCI:
 		case MDL_SBPRO:
 		case MDL_AZTECH:
 		case MDL_JAZZ:
diff -u --recursive --new-file v2.2.2/linux/drivers/sound/sequencer.c linux/drivers/sound/sequencer.c
--- v2.2.2/linux/drivers/sound/sequencer.c	Tue Jan 19 11:32:52 1999
+++ linux/drivers/sound/sequencer.c	Sun Mar  7 15:22:06 1999
@@ -1105,7 +1105,7 @@
 		 */
 
 		for (i = 0; i < max_mididev; i++)
-			if (!midi_opened[i])
+			if (!midi_opened[i] && midi_devs[i])
 			{
 				if ((retval = midi_devs[i]->open(i, mode,
 					sequencer_midi_input, sequencer_midi_output)) >= 0)
@@ -1411,7 +1411,7 @@
 		case SNDCTL_SEQ_TESTMIDI:
 			if (__get_user(midi_dev, (int *)arg))
 				return -EFAULT;
-			if (midi_dev < 0 || midi_dev >= max_mididev)
+			if (midi_dev < 0 || midi_dev >= max_mididev || !midi_devs[midi_dev])
 				return -ENXIO;
 
 			if (!midi_opened[midi_dev] &&
@@ -1529,7 +1529,7 @@
 		case SNDCTL_MIDI_INFO:
 			if (get_user(dev, (int *)(&(((struct midi_info *)arg)->device))))
 				return -EFAULT;
-			if (dev < 0 || dev >= max_mididev)
+			if (dev < 0 || dev >= max_mididev || !midi_devs[dev])
 				return -ENXIO;
 			midi_devs[dev]->info.device = dev;
 			return copy_to_user(arg, &midi_devs[dev]->info, sizeof(struct midi_info))?-EFAULT:0;
diff -u --recursive --new-file v2.2.2/linux/drivers/sound/sonicvibes.c linux/drivers/sound/sonicvibes.c
--- v2.2.2/linux/drivers/sound/sonicvibes.c	Fri Jan  8 22:36:12 1999
+++ linux/drivers/sound/sonicvibes.c	Sun Mar  7 10:37:54 1999
@@ -1431,8 +1431,6 @@
 	if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))
 		return -EAGAIN;
 	db->mapped = 1;
-	vma->vm_file = file;
-	file->f_count++;
 	return 0;
 }
 
diff -u --recursive --new-file v2.2.2/linux/drivers/sound/sound_core.c linux/drivers/sound/sound_core.c
--- v2.2.2/linux/drivers/sound/sound_core.c	Tue Feb 23 15:21:34 1999
+++ linux/drivers/sound/sound_core.c	Sun Mar  7 15:22:06 1999
@@ -39,7 +39,6 @@
 #include <linux/malloc.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
 #include <linux/fs.h>
 #include <linux/sound.h>
 #include <linux/major.h>
diff -u --recursive --new-file v2.2.2/linux/drivers/sound/soundcard.c linux/drivers/sound/soundcard.c
--- v2.2.2/linux/drivers/sound/soundcard.c	Tue Jan 19 11:32:52 1999
+++ linux/drivers/sound/soundcard.c	Sun Mar  7 15:22:06 1999
@@ -67,7 +67,11 @@
 int             sound_nblocks = 0;
 
 /* Persistent DMA buffers */
-int		sound_dmap_flag = 0;	/* Off by default */
+#ifdef CONFIG_SOUND_DMAP
+int		sound_dmap_flag = 1;
+#else
+int		sound_dmap_flag = 0;
+#endif
 
 static int      soundcard_configured = 0;
 
@@ -751,9 +755,6 @@
 		vma->vm_page_prot))
 		return -EAGAIN;
 
-	vma->vm_file = file;
-	file->f_count++;
-
 	dmap->mapping_flags |= DMA_MAP_MAPPED;
 
 	if( audio_devs[dev]->d->mmap)
@@ -802,13 +803,6 @@
 	return -1;
 }
 
-static void destroy_special_devices(void)
-{
-	unregister_sound_special(6);
-	unregister_sound_special(1);
-	unregister_sound_special(8);
-}
-
 #ifdef MODULE
 static void
 #else
@@ -849,11 +843,18 @@
 #endif		
 }
 
+#ifdef MODULE
+
+static void destroy_special_devices(void)
+{
+	unregister_sound_special(6);
+	unregister_sound_special(1);
+	unregister_sound_special(8);
+}
+
 static int      sound[20] = {
 	0
 };
-
-#ifdef MODULE
 
 int traceinit = 0;
 static int dmabuf = 0;
diff -u --recursive --new-file v2.2.2/linux/drivers/sound/trix.c linux/drivers/sound/trix.c
--- v2.2.2/linux/drivers/sound/trix.c	Mon Dec 28 15:00:52 1998
+++ linux/drivers/sound/trix.c	Sun Mar  7 15:22:06 1999
@@ -323,7 +323,7 @@
 
 	hw_config->name = "AudioTrix SB";
 #ifdef CONFIG_SBDSP
-	return sb_dsp_detect(hw_config);
+	return sb_dsp_detect(hw_config, 0, 0);
 #else
 	return 0;
 #endif
diff -u --recursive --new-file v2.2.2/linux/drivers/video/Config.in linux/drivers/video/Config.in
--- v2.2.2/linux/drivers/video/Config.in	Wed Jan 20 23:14:06 1999
+++ linux/drivers/video/Config.in	Thu Feb 25 10:02:12 1999
@@ -4,12 +4,17 @@
 
 if [ "$CONFIG_FB" = "y" ]; then
   define_bool CONFIG_DUMMY_CONSOLE y
-  if [ "$CONFIG_APUS" = "y" ]; then
-    bool 'Permedia2 support' CONFIG_FB_PM2
-    if [ "$CONFIG_FB_PM2" = "y" ]; then
-      bool '  enable FIFO disconnect feature' CONFIG_FB_PM2_FIFO_DISCONNECT
-      if [ "$CONFIG_APUS" = "y" ]; then
-        bool '  Phase5 CVisionPPC/BVisionPPC support' CONFIG_FB_PM2_CVPPC
+  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+    if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_PCI" = "y" ]; then
+      bool 'Permedia2 support (experimental)' CONFIG_FB_PM2
+      if [ "$CONFIG_FB_PM2" = "y" ]; then
+        if [ "$CONFIG_PCI" = "y" ]; then
+          bool '  enable FIFO disconnect feature' CONFIG_FB_PM2_FIFO_DISCONNECT
+          bool '  generic Permedia2 PCI board support' CONFIG_FB_PM2_PCI
+        fi
+        if [ "$CONFIG_AMIGA" = "y" ]; then
+          bool '  Phase5 CVisionPPC/BVisionPPC support' CONFIG_FB_PM2_CVPPC
+        fi
       fi
     fi
   fi
@@ -19,6 +24,9 @@
   if [ "$CONFIG_APOLLO" = "y" ]; then
     define_bool CONFIG_FB_APOLLO y
   fi
+  if [ "$CONFIG_Q40" = "y" ]; then
+    define_bool CONFIG_FB_Q40 y
+  fi
   if [ "$CONFIG_AMIGA" = "y" ]; then
     bool 'Amiga native chipset support' CONFIG_FB_AMIGA
     if [ "$CONFIG_FB_AMIGA" != "n" ]; then
@@ -33,6 +41,7 @@
       bool 'Amiga CyberVision3D support (experimental)' CONFIG_FB_VIRGE
       tristate 'Amiga RetinaZ3 support' CONFIG_FB_RETINAZ3
       tristate 'Amiga CLgen driver' CONFIG_FB_CLGEN
+      bool 'Amiga FrameMaster II/Rainbow II support (experimental)' CONFIG_FB_FM2
     fi
   fi
   if [ "$CONFIG_ATARI" = "y" ]; then
@@ -185,6 +194,7 @@
     if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATY" = "y" -o \
 	 "$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_VESA" = "y" -o \
 	 "$CONFIG_FB_VIRTUAL" = "y" -o "$CONFIG_FB_TBOX" = "y" -o \
+	 "$CONFIG_FB_Q40" = "y" -o \
 	 "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
 	 "$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_CYBER" = "y" -o \
 	 "$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \
@@ -195,6 +205,7 @@
       if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
 	   "$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_VESA" = "m" -o \
 	   "$CONFIG_FB_VIRTUAL" = "m" -o "$CONFIG_FB_TBOX" = "m" -o \
+	 "$CONFIG_FB_Q40" = "m" -o \
 	   "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
 	   "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \
  	   "$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \
@@ -218,7 +229,8 @@
 	 "$CONFIG_FB_VESA" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \
 	 "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
 	 "$CONFIG_FB_TGA" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \
-	 "$CONFIG_FB_MATROX" = "y" -o "$CONFIG_FB_PM2" = "y" ]; then
+	 "$CONFIG_FB_MATROX" = "y" -o "$CONFIG_FB_PM2" = "y" -o \
+	 "$CONFIG_FB_FM2" = "y" ]; then
       define_bool CONFIG_FBCON_CFB32 y
     else
       if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
diff -u --recursive --new-file v2.2.2/linux/drivers/video/Makefile linux/drivers/video/Makefile
--- v2.2.2/linux/drivers/video/Makefile	Wed Jan 20 23:14:06 1999
+++ linux/drivers/video/Makefile	Thu Feb 25 10:02:12 1999
@@ -88,6 +88,10 @@
 L_OBJS += dnfb.o
 endif
 
+ifeq ($(CONFIG_FB_Q40),y)
+L_OBJS += q40fb.o
+endif
+
 ifeq ($(CONFIG_FB_ATARI),y)
 L_OBJS += atafb.o
 else
@@ -192,6 +196,10 @@
 
 ifdef CONFIG_FB_G364
 L_OBJS := $(L_OBJS) g364fb.o
+endif
+
+ifdef CONFIG_FB_FM2
+L_OBJS := $(L_OBJS) fm2fb.o
 endif
 
 ifeq ($(CONFIG_FB_SBUS),y)
diff -u --recursive --new-file v2.2.2/linux/drivers/video/atafb.c linux/drivers/video/atafb.c
--- v2.2.2/linux/drivers/video/atafb.c	Wed Jan 20 23:14:06 1999
+++ linux/drivers/video/atafb.c	Thu Feb 25 10:02:11 1999
@@ -103,7 +103,7 @@
 static int ovsc_offset=0, ovsc_addlen=0;
 
 static struct atafb_par {
-	unsigned long screen_base;
+	void *screen_base;
 	int yres_virtual;
 #if defined ATAFB_TT || defined ATAFB_STE
 	union {
@@ -167,8 +167,8 @@
 
 static struct fb_info fb_info;
 
-static unsigned long screen_base;	/* base address of screen */
-static unsigned long real_screen_base;	/* (only for Overscan) */
+static void *screen_base;	/* base address of screen */
+static void *real_screen_base;	/* (only for Overscan) */
 
 static int screen_len;
 
@@ -193,7 +193,7 @@
 
 static unsigned			external_depth;
 static int				external_pmode;
-static unsigned long	external_addr = 0;
+static void *external_addr = 0;
 static unsigned long	external_len;
 static unsigned long	external_vgaiobase = 0;
 static unsigned int		external_bitspercol = 6;
@@ -299,7 +299,7 @@
  *   Read a single color register and split it into
  *   colors/transparent. Return != 0 for invalid regno.
  *
- * void (*set_screen_base)( unsigned long s_base )
+ * void (*set_screen_base)(void *s_base)
  *   Set the base address of the displayed frame buffer. Only called
  *   if yres_virtual > yres or xres_virtual > xres.
  *
@@ -328,7 +328,7 @@
 	int  (*setcolreg)( unsigned regno, unsigned red,
 					   unsigned green, unsigned blue,
 					   unsigned transp, struct fb_info *info );
-	void (*set_screen_base)( unsigned long s_base );
+	void (*set_screen_base)(void *s_base);
 	int  (*blank)( int blank_mode );
 	int  (*pan_display)( struct fb_var_screeninfo *var,
 						 struct atafb_par *par);
@@ -464,7 +464,7 @@
 	int mode;
 
 	strcpy(fix->id,"Atari Builtin");
-	fix->smem_start = (char *)real_screen_base;
+	fix->smem_start = real_screen_base;
 	fix->smem_len = screen_len;
 	fix->type=FB_TYPE_INTERLEAVED_PLANES;
 	fix->type_aux=2;
@@ -797,7 +797,7 @@
 							  struct atafb_par *par )
 {
 	strcpy(fix->id, "Atari Builtin");
-	fix->smem_start = (char *)real_screen_base;
+	fix->smem_start = real_screen_base;
 	fix->smem_len = screen_len;
 	fix->type = FB_TYPE_INTERLEAVED_PLANES;
 	fix->type_aux = 2;
@@ -1760,7 +1760,7 @@
 	int mode;
 
 	strcpy(fix->id,"Atari Builtin");
-	fix->smem_start = (char *)real_screen_base;
+	fix->smem_start = real_screen_base;
 	fix->smem_len = screen_len;
 	fix->type = FB_TYPE_INTERLEAVED_PLANES;
 	fix->type_aux = 2;
@@ -2024,7 +2024,7 @@
 	return 1;
 }
 
-static void stste_set_screen_base(unsigned long s_base)
+static void stste_set_screen_base(void *s_base)
 {
 	unsigned long addr;
 	addr= virt_to_phys(s_base);
@@ -2104,8 +2104,8 @@
 
 {
 	strcpy(fix->id,"Unknown Extern");
-	fix->smem_start=(char *)external_addr;
-	fix->smem_len=(external_len + PAGE_SIZE -1) & PAGE_MASK;
+	fix->smem_start=external_addr;
+	fix->smem_len = PAGE_ALIGN(external_len);
 	if (external_depth == 1) {
 		fix->type = FB_TYPE_PACKED_PIXELS;
 		/* The letters 'n' and 'i' in the "atavideo=external:" stand
@@ -2295,7 +2295,7 @@
 
 /* ------ This is the same for most hardware types -------- */
 
-static void set_screen_base(unsigned long s_base)
+static void set_screen_base(void *s_base)
 {
 	unsigned long addr;
 	addr= virt_to_phys(s_base);
@@ -2804,15 +2804,13 @@
 #ifdef ATAFB_EXT
 	if (!external_addr) {
 #endif /* ATAFB_EXT */
-		mem_req = default_mem_req + ovsc_offset +
-			ovsc_addlen;
-		mem_req = ((mem_req + PAGE_SIZE - 1) & PAGE_MASK) + PAGE_SIZE;
-		screen_base = (unsigned long)atari_stram_alloc(mem_req, NULL,
-							       "atafb");
+		mem_req = default_mem_req + ovsc_offset + ovsc_addlen;
+		mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE;
+		screen_base = atari_stram_alloc(mem_req, NULL, "atafb");
 		if (!screen_base)
 			panic("Cannot allocate screen memory");
-		memset((char *) screen_base, 0, mem_req);
-		pad = ((screen_base + PAGE_SIZE-1) & PAGE_MASK) - screen_base;
+		memset(screen_base, 0, mem_req);
+		pad = -(unsigned long)screen_base & (PAGE_SIZE-1);
 		screen_base+=pad;
 		real_screen_base=screen_base+ovsc_offset;
 		screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
@@ -2820,9 +2818,9 @@
 		if (CPU_IS_040_OR_060) {
 			/* On a '040+, the cache mode of video RAM must be set to
 			 * write-through also for internal video hardware! */
-			cache_push( virt_to_phys(screen_base), screen_len );
-			kernel_set_cachemode( screen_base, screen_len,
-					      IOMAP_WRITETHROUGH );
+			cache_push(virt_to_phys(screen_base), screen_len);
+			kernel_set_cachemode(screen_base, screen_len,
+					     IOMAP_WRITETHROUGH);
 		}
 #ifdef ATAFB_EXT
 	}
@@ -2836,7 +2834,7 @@
 		screen_base      =
 		real_screen_base = external_addr;
 		screen_len       = external_len & PAGE_MASK;
-		memset ((char *) screen_base, 0, external_len);
+		memset (screen_base, 0, external_len);
 	}
 #endif /* ATAFB_EXT */
 
diff -u --recursive --new-file v2.2.2/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c
--- v2.2.2/linux/drivers/video/atyfb.c	Wed Jan 20 23:14:06 1999
+++ linux/drivers/video/atyfb.c	Sun Mar  7 10:38:37 1999
@@ -1,4 +1,4 @@
-/*  $Id: atyfb.c,v 1.98 1999/01/14 08:50:53 geert Exp $
+/*  $Id: atyfb.c,v 1.102 1999/01/21 22:44:42 geert Exp $
  *  linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
  *
  *	Copyright (C) 1997-1998  Geert Uytterhoeven
@@ -66,6 +66,8 @@
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
 #include <video/macmodes.h>
+#include <asm/adb.h>
+#include <asm/pmu.h>
 #endif
 #ifdef __sparc__
 #include <asm/pbm.h>
@@ -439,10 +441,10 @@
 
     /* mach64CT family / mach64GT (3D RAGE) class */
     { 0x4c42, 0x4c42, "3D RAGE LT PRO (AGP)" },
-    { 0x4c42, 0x4c44, "3D RAGE LT PRO" },
-    { 0x4c42, 0x4c47, "3D RAGE LT PRO" },
-    { 0x4c42, 0x4c49, "3D RAGE LT PRO" },
-    { 0x4c42, 0x4c50, "3D RAGE LT PRO" },
+    { 0x4c44, 0x4c44, "3D RAGE LT PRO" },
+    { 0x4c47, 0x4c47, "3D RAGE LT PRO" },
+    { 0x4c49, 0x4c49, "3D RAGE LT PRO" },
+    { 0x4c50, 0x4c50, "3D RAGE LT PRO" },
     { 0x4c54, 0x4c54, "3D RAGE LT" },
     { 0x4754, 0x4754, "3D RAGE (GT)" },
     { 0x4755, 0x4755, "3D RAGE II+ (GTB)" },
@@ -1282,7 +1284,7 @@
 	    bpp = 16;
 	    var->red.offset = 11;
 	    var->red.length = 5;
-	    var->green.offset = 6;
+	    var->green.offset = 5;
 	    var->green.length = 6;
 	    var->blue.offset = 0;
 	    var->blue.length = 5;
@@ -2321,8 +2323,6 @@
 	if (!map_size)
 		return -EINVAL;
 
-	vma->vm_file = file;
-	file->f_count++;
 	vma->vm_flags |= VM_IO;
 
 	if (!fb->mmaped) {
@@ -2353,10 +2353,10 @@
 
 	for (i = 0; i < 256; i++) {
 		tmp = aty_ld_8(DAC_CNTL, info) & 0xfc;
-		if ((Gx == GT_CHIP_ID) || (Gx == GU_CHIP_ID) ||
-		    (Gx == LG_CHIP_ID) || (Gx == GB_CHIP_ID) ||
-		    (Gx == GD_CHIP_ID) || (Gx == GI_CHIP_ID) ||
-		    (Gx == GP_CHIP_ID) || (Gx == GQ_CHIP_ID))
+		if (Gx == GT_CHIP_ID || Gx == GU_CHIP_ID || Gx == GV_CHIP_ID ||
+		    Gx == GW_CHIP_ID || Gx == GZ_CHIP_ID || Gx == LG_CHIP_ID ||
+		    Gx == GB_CHIP_ID || Gx == GD_CHIP_ID || Gx == GI_CHIP_ID ||
+		    Gx == GP_CHIP_ID || Gx == GQ_CHIP_ID)
 			tmp |= 0x2;
 		aty_st_8(DAC_CNTL, tmp, info);
 		aty_st_8(DAC_MASK, 0xff, info);
@@ -3296,6 +3296,11 @@
     struct fb_info_aty *info = (struct fb_info_aty *)fb;
     u8 gen_cntl;
 
+#if defined(CONFIG_PPC)
+    if ((_machine == _MACH_Pmac) && blank)
+    	pmu_enable_backlight(0);
+#endif
+
     gen_cntl = aty_ld_8(CRTC_GEN_CNTL, info);
     if (blank > 0)
 	switch (blank-1) {
@@ -3315,6 +3320,11 @@
     else
 	gen_cntl &= ~(0x4c);
     aty_st_8(CRTC_GEN_CNTL, gen_cntl, info);
+
+#if defined(CONFIG_PPC)
+    if ((_machine == _MACH_Pmac) && !blank)
+    	pmu_enable_backlight(1);
+#endif
 }
 
 
@@ -3359,9 +3369,10 @@
     info->palette[regno].green = green;
     info->palette[regno].blue = blue;
     i = aty_ld_8(DAC_CNTL, info) & 0xfc;
-    if ((Gx == GT_CHIP_ID) || (Gx == GU_CHIP_ID) || (Gx == LG_CHIP_ID) ||
-	(Gx == GB_CHIP_ID) || (Gx == GD_CHIP_ID) || (Gx == GI_CHIP_ID) ||
-	(Gx == GP_CHIP_ID) || (Gx == GQ_CHIP_ID))
+    if (Gx == GT_CHIP_ID || Gx == GU_CHIP_ID || Gx == GV_CHIP_ID ||
+	Gx == GW_CHIP_ID || Gx == GZ_CHIP_ID || Gx == LG_CHIP_ID ||
+	Gx == GB_CHIP_ID || Gx == GD_CHIP_ID || Gx == GI_CHIP_ID ||
+	Gx == GP_CHIP_ID || Gx == GQ_CHIP_ID)
 	i |= 0x2;	/*DAC_CNTL|0x2 turns off the extra brightness for gt*/
     aty_st_8(DAC_CNTL, i, info);
     aty_st_8(DAC_MASK, 0xff, info);
diff -u --recursive --new-file v2.2.2/linux/drivers/video/bwtwofb.c linux/drivers/video/bwtwofb.c
--- v2.2.2/linux/drivers/video/bwtwofb.c	Mon Oct  5 13:13:41 1998
+++ linux/drivers/video/bwtwofb.c	Thu Feb 25 10:02:12 1999
@@ -1,4 +1,4 @@
-/* $Id: bwtwofb.c,v 1.6 1998/09/15 15:45:35 jj Exp $
+/* $Id: bwtwofb.c,v 1.7 1999/01/26 10:55:02 jj Exp $
  * bwtwofb.c: BWtwo frame buffer driver
  *
  * Copyright (C) 1998 Jakub Jelinek   (jj@ultra.linux.cz)
@@ -199,6 +199,7 @@
 	strcpy(fb->info.modename, "BWtwo");
 	strcpy(fix->id, "BWtwo");
 	fix->line_length = fb->var.xres_virtual>>3;
+	fix->accel = FB_ACCEL_SUN_BWTWO;
 	
 	disp->scrollmode = SCROLL_YREDRAW;
 	disp->inverse = 1;
diff -u --recursive --new-file v2.2.2/linux/drivers/video/cgfourteenfb.c linux/drivers/video/cgfourteenfb.c
--- v2.2.2/linux/drivers/video/cgfourteenfb.c	Mon Oct  5 13:13:41 1998
+++ linux/drivers/video/cgfourteenfb.c	Thu Feb 25 10:02:12 1999
@@ -1,4 +1,4 @@
-/* $Id: cgfourteenfb.c,v 1.3 1998/09/04 15:43:41 jj Exp $
+/* $Id: cgfourteenfb.c,v 1.4 1999/01/26 10:55:03 jj Exp $
  * cgfourteenfb.c: CGfourteen frame buffer driver
  *
  * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -355,6 +355,7 @@
 	strcpy(fb->info.modename, "CGfourteen");
 	strcpy(fix->id, "CGfourteen");
 	fix->line_length = fb->var.xres_virtual;
+	fix->accel = FB_ACCEL_SUN_CG14;
 	
 	disp->scrollmode = SCROLL_YREDRAW;
 	disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin;
diff -u --recursive --new-file v2.2.2/linux/drivers/video/cgsixfb.c linux/drivers/video/cgsixfb.c
--- v2.2.2/linux/drivers/video/cgsixfb.c	Tue Dec 22 14:16:56 1998
+++ linux/drivers/video/cgsixfb.c	Thu Feb 25 10:02:12 1999
@@ -1,4 +1,4 @@
-/* $Id: cgsixfb.c,v 1.12 1998/11/27 00:02:04 anton Exp $
+/* $Id: cgsixfb.c,v 1.13 1999/01/28 08:19:18 ecd Exp $
  * cgsixfb.c: CGsix (GX,GXplus) frame buffer driver
  *
  * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -352,8 +352,8 @@
 	do {
 		i = fbc->s;
 	} while (i & 0x10000000);
-	fbc->fg = attr_fgcol(p,*s);
-	fbc->bg = attr_bgcol(p,*s);
+	fbc->fg = attr_fgcol(p, scr_readw(s));
+	fbc->bg = attr_bgcol(p, scr_readw(s));
 	fbc->mode = 0x140000;
 	fbc->alu = 0xe880fc30;
 	fbc->pixelm = ~(0);
@@ -379,15 +379,15 @@
 			fbc->x1 = (x += 4 * fontwidth(p)) - 1;
 			fbc->y0 = y;
 			if (fontheightlog(p)) {
-				fd1 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
-				fd2 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
-				fd3 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
-				fd4 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
+				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
+				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
+				fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
+				fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
 			} else {
-				fd1 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
-				fd2 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
-				fd3 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
-				fd4 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
+				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
+				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
+				fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
+				fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
 			}
 			if (fontwidth(p) == 8) {
 				for (i = 0; i < fontheight(p); i++)
@@ -408,11 +408,11 @@
 			fbc->x1 = (x += 2 * fontwidth(p)) - 1;
 			fbc->y0 = y;
 			if (fontheightlog(p)) {
-				fd1 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
-				fd2 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
+				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
+				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
 			} else {
-				fd1 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
-				fd2 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
+				fd1 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
+				fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
 			}
 			for (i = 0; i < fontheight(p); i++) {
 				fbc->font = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
@@ -428,9 +428,9 @@
 		fbc->x1 = (x += fontwidth(p)) - 1;
 		fbc->y0 = y;
 		if (fontheightlog(p))
-			i = ((*s++ & p->charmask) << fontheightlog(p));
+			i = ((scr_readw(s++) & p->charmask) << fontheightlog(p));
 		else
-			i = ((*s++ & p->charmask) * fontheight(p));
+			i = ((scr_readw(s++) & p->charmask) * fontheight(p));
 		if (fontwidth(p) <= 8) {
 			fd1 = p->fontdata + i;
 			for (i = 0; i < fontheight(p); i++)
@@ -535,6 +535,7 @@
 	struct cg6_tec *tec = fb->s.cg6.tec;
 	struct cg6_fbc *fbc = fb->s.cg6.fbc;
 	u32 mode;
+	int i;
 	
 	/* Turn off stuff in the Transform Engine. */
 	tec->tec_matrix = 0;
@@ -557,6 +558,9 @@
 	 * back to back store/loads on the mode register, so copy it
 	 * out instead. */
 	mode = fbc->mode;
+	do {
+		i = fbc->s;
+	} while (i & 0x10000000);
 	mode &= ~(CG6_FBC_BLIT_MASK | CG6_FBC_MODE_MASK |
 		       CG6_FBC_DRAW_MASK | CG6_FBC_BWRITE0_MASK |
 		       CG6_FBC_BWRITE1_MASK | CG6_FBC_BREAD_MASK |
diff -u --recursive --new-file v2.2.2/linux/drivers/video/cgthreefb.c linux/drivers/video/cgthreefb.c
--- v2.2.2/linux/drivers/video/cgthreefb.c	Mon Oct  5 13:13:41 1998
+++ linux/drivers/video/cgthreefb.c	Thu Feb 25 10:02:12 1999
@@ -1,4 +1,4 @@
-/* $Id: cgthreefb.c,v 1.3 1998/09/04 15:43:43 jj Exp $
+/* $Id: cgthreefb.c,v 1.4 1999/01/26 10:55:01 jj Exp $
  * cgthreefb.c: CGthree frame buffer driver
  *
  * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -186,6 +186,7 @@
 	strcpy(fb->info.modename, "CGthree");
 	strcpy(fix->id, "CGthree");
 	fix->line_length = fb->var.xres_virtual;
+	fix->accel = FB_ACCEL_SUN_CGTHREE;
 	
 	disp->scrollmode = SCROLL_YREDRAW;
 	if (!disp->screen_base)
diff -u --recursive --new-file v2.2.2/linux/drivers/video/clgenfb.c linux/drivers/video/clgenfb.c
--- v2.2.2/linux/drivers/video/clgenfb.c	Wed Jan 20 23:14:06 1999
+++ linux/drivers/video/clgenfb.c	Thu Feb 25 10:02:11 1999
@@ -204,8 +204,8 @@
 			      struct fb_info_gen *info);
 static int  clgen_blank(int blank_mode, struct fb_info_gen *info);
 
-static void clgen_set_dispsw(const void *par, struct display *disp,
-			     struct fb_info_gen *info);
+static void clgen_set_disp(const void *par, struct display *disp,
+			   struct fb_info_gen *info);
 
 /* function table of the above functions */
 static struct fbgen_hwswitch clgen_hwswitch = 
@@ -220,7 +220,7 @@
     clgen_setcolreg,
     clgen_pan_display,
     clgen_blank,
-    clgen_set_dispsw
+    clgen_set_disp
 };
 
 /* Text console acceleration */
@@ -1372,13 +1372,14 @@
 	}
 }
 
-static void clgen_set_dispsw(const void *par, struct display *disp,
-			     struct fb_info_gen *info)
+static void clgen_set_disp(const void *par, struct display *disp,
+			   struct fb_info_gen *info)
 {
     struct clgenfb_par *_par = (struct clgenfb_par*) par;
     struct clgenfb_info *info2 = (struct clgenfb_info *)info;
 
-    printk("clgen_get_dispsw(): ");
+    printk("clgen_set_disp(): ");
+    disp->screen_base = info2->fbmem;
     switch (_par->var.bits_per_pixel)
     {
 #ifdef FBCON_HAS_MFB
@@ -1670,7 +1671,7 @@
 int init_module(void)
 {
     printk("init_module()\n");
-    clgenfb_init(0);
+    clgenfb_init();
     return 0;
 }
 
diff -u --recursive --new-file v2.2.2/linux/drivers/video/controlfb.c linux/drivers/video/controlfb.c
--- v2.2.2/linux/drivers/video/controlfb.c	Tue Dec 22 14:16:56 1998
+++ linux/drivers/video/controlfb.c	Thu Feb 25 10:02:11 1999
@@ -377,7 +377,7 @@
 	control_set_hardware(p, &par);
 	control_set_dispsw(&fb_display[con], par.cmode, p);
 
-	if(fb_display[oldcon].var.yoffset != fb_display[con].var.yoffset);
+	if(fb_display[oldcon].var.yoffset != fb_display[con].var.yoffset)
 		controlfb_updatevar(con, info);
 
 	do_install_cmap(con, info);
@@ -447,21 +447,24 @@
 			     u_int transp, struct fb_info *info)
 {
 	struct fb_info_control *p = (struct fb_info_control *) info;
-	int i;
+	u_int i;
+	__u8 r, g, b;
 
 	if (regno > 255)
 		return 1;
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-	p->palette[regno].red = red;
-	p->palette[regno].green = green;
-	p->palette[regno].blue = blue;
+
+	r = red >> 8;
+	g = green >> 8;
+	b = blue >> 8;
+
+	p->palette[regno].red = r;
+	p->palette[regno].green = g;
+	p->palette[regno].blue = b;
 
 	out_8(&p->cmap_regs->addr, regno);	/* tell clut what addr to fill	*/
-	out_8(&p->cmap_regs->lut, red);		/* send one color channel at	*/
-	out_8(&p->cmap_regs->lut, green);	/* a time...			*/
-	out_8(&p->cmap_regs->lut, blue);
+	out_8(&p->cmap_regs->lut, r);		/* send one color channel at	*/
+	out_8(&p->cmap_regs->lut, g);		/* a time...			*/
+	out_8(&p->cmap_regs->lut, b);
 
 	if (regno < 16)
 		switch (p->par.cmode) {
@@ -501,8 +504,9 @@
 
 static inline int control_vram_reqd(int video_mode, int color_mode)
 {
-	return control_reg_init[video_mode-1]->vres
-		* control_reg_init[video_mode-1]->hres << color_mode;
+	return (control_reg_init[video_mode-1]->vres
+		* control_reg_init[video_mode-1]->hres << color_mode)
+	       + control_reg_init[video_mode-1]->offset[color_mode];
 }
 
 static void set_control_clock(unsigned char *params)
@@ -557,6 +561,7 @@
 	par_set = 1;	/* Debug */
 	
 	control_par_to_var(par, &var);
+	var.activate = FB_ACTIVATE_NOW;
 	control_set_var(&var, -1, &p->info);
 	
 	p->info.flags = FBINFO_FLAG_DEFAULT;
@@ -616,11 +621,11 @@
 	for (i = 0; i < 16; ++i, ++rp)
 		out_le32(&rp->r, init->regs[i]);
 	
-	out_le32(&p->control_regs->pitch.r, init->hres << cmode);
+	out_le32(&p->control_regs->pitch.r, par->vxres << cmode);
 	out_le32(&p->control_regs->mode.r, init->mode[cmode]);
 	out_le32(&p->control_regs->flags.r, flags);
 	out_le32(&p->control_regs->start_addr.r,
-	    par->yoffset * (par->vxres << par->cmode));
+	    par->yoffset * (par->vxres << cmode));
 	out_le32(&p->control_regs->reg18.r, 0x1e5);
 	out_le32(&p->control_regs->reg19.r, 0);
 
@@ -762,8 +767,6 @@
 	int xres = var->xres;
 	int yres = var->yres;
 	int bpp = var->bits_per_pixel;
-	
-	struct control_regvals *init;
 	struct fb_info_control *p = (struct fb_info_control *) fb_info;
 
     /*
@@ -776,7 +779,7 @@
      */
 	/* swiped by jonh from atyfb.c */
 	if (xres <= 512 && yres <= 384)
-		par->vmode = VMODE_512_384_60;		 /* 512x384, 60Hz */
+		par->vmode = VMODE_512_384_60;		/* 512x384, 60Hz */
 	else if (xres <= 640 && yres <= 480)
 		par->vmode = VMODE_640_480_67;		/* 640x480, 67Hz */
 	else if (xres <= 640 && yres <= 870)
@@ -844,8 +847,7 @@
 	}
 
 	/* Check if we know about the wanted video mode */
-	init = control_reg_init[par->vmode-1];
-	if (init == NULL) {
+	if (control_reg_init[par->vmode - 1] == NULL) {
 		printk(KERN_ERR "init is null in control_var_to_par().\n");
 		/* I'm not sure if control has any specific requirements --	*/
 		/* if we have a regvals struct, we're good to go?		*/
@@ -1010,7 +1012,7 @@
 
 	fix->smem_start = (void *)(p->frame_buffer_phys
 		+ control_reg_init[par->vmode-1]->offset[par->cmode]);
-	fix->smem_len = p->total_vram;
+	fix->smem_len = p->total_vram - control_reg_init[par->vmode-1]->offset[par->cmode];
 	fix->visual = (par->cmode == CMODE_8) ?
 		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
 	fix->line_length = par->vxres << par->cmode;
@@ -1046,6 +1048,70 @@
 	control_set_dispsw(disp, par->cmode, p);
 }
 
+static void control_cfb16_revc(struct display *p, int xx, int yy)
+{
+    u8 *dest;
+    int bytes = p->next_line, rows;
+
+    dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p)*2;
+    for (rows = fontheight(p); rows--; dest += bytes) {
+       switch (fontwidth(p)) {
+       case 16:
+           ((u32 *)dest)[6] ^= 0x3def3def; ((u32 *)dest)[7] ^= 0x3def3def;
+           /* FALL THROUGH */
+       case 12:
+           ((u32 *)dest)[4] ^= 0x3def3def; ((u32 *)dest)[5] ^= 0x3def3def;
+           /* FALL THROUGH */
+       case 8:
+           ((u32 *)dest)[2] ^= 0x3def3def; ((u32 *)dest)[3] ^= 0x3def3def;
+           /* FALL THROUGH */
+       case 4:
+           ((u32 *)dest)[0] ^= 0x3def3def; ((u32 *)dest)[1] ^= 0x3def3def;
+       }
+    }
+}
+
+static void control_cfb32_revc(struct display *p, int xx, int yy)
+{
+    u8 *dest;
+    int bytes = p->next_line, rows;
+
+    dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 4;
+    for (rows = fontheight(p); rows--; dest += bytes) {
+       switch (fontwidth(p)) {
+       case 16:
+           ((u32 *)dest)[12] ^= 0x0f0f0f0f; ((u32 *)dest)[13] ^= 0x0f0f0f0f;
+           ((u32 *)dest)[14] ^= 0x0f0f0f0f; ((u32 *)dest)[15] ^= 0x0f0f0f0f;
+           /* FALL THROUGH */
+       case 12:
+           ((u32 *)dest)[8] ^= 0x0f0f0f0f; ((u32 *)dest)[9] ^= 0x0f0f0f0f;
+           ((u32 *)dest)[10] ^= 0x0f0f0f0f; ((u32 *)dest)[11] ^= 0x0f0f0f0f;
+           /* FALL THROUGH */
+       case 8:
+           ((u32 *)dest)[4] ^= 0x0f0f0f0f; ((u32 *)dest)[5] ^= 0x0f0f0f0f;
+           ((u32 *)dest)[6] ^= 0x0f0f0f0f; ((u32 *)dest)[7] ^= 0x0f0f0f0f;
+           /* FALL THROUGH */
+       case 4:
+           ((u32 *)dest)[0] ^= 0x0f0f0f0f; ((u32 *)dest)[1] ^= 0x0f0f0f0f;
+           ((u32 *)dest)[2] ^= 0x0f0f0f0f; ((u32 *)dest)[3] ^= 0x0f0f0f0f;
+           /* FALL THROUGH */
+       }
+    }
+}
+
+static struct display_switch control_cfb16 = {
+    fbcon_cfb16_setup, fbcon_cfb16_bmove, fbcon_cfb16_clear, fbcon_cfb16_putc,
+    fbcon_cfb16_putcs, control_cfb16_revc, NULL, NULL, fbcon_cfb16_clear_margins,
+    FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+
+static struct display_switch control_cfb32 = {
+    fbcon_cfb32_setup, fbcon_cfb32_bmove, fbcon_cfb32_clear, fbcon_cfb32_putc,
+    fbcon_cfb32_putcs, control_cfb32_revc, NULL, NULL, fbcon_cfb32_clear_margins,
+    FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+
+
 static void control_set_dispsw(struct display *disp, int cmode, struct fb_info_control *p)
 {
 	switch (cmode) {
@@ -1056,13 +1122,13 @@
 #endif
 #ifdef FBCON_HAS_CFB16
 		case CMODE_16:
-			disp->dispsw = &fbcon_cfb16;
+			disp->dispsw = &control_cfb16;
 			disp->dispsw_data = p->fbcon_cmap.cfb16;
 			break;
 #endif
 #ifdef FBCON_HAS_CFB32
 		case CMODE_32:
-			disp->dispsw = &fbcon_cfb32;
+			disp->dispsw = &control_cfb32;
 			disp->dispsw_data = p->fbcon_cmap.cfb32;
 			break;
 #endif
diff -u --recursive --new-file v2.2.2/linux/drivers/video/creatorfb.c linux/drivers/video/creatorfb.c
--- v2.2.2/linux/drivers/video/creatorfb.c	Wed Jan 20 23:14:06 1999
+++ linux/drivers/video/creatorfb.c	Thu Feb 25 10:02:12 1999
@@ -1,7 +1,7 @@
-/* $Id: creatorfb.c,v 1.17 1998/12/28 11:23:37 jj Exp $
+/* $Id: creatorfb.c,v 1.19 1999/02/22 16:20:25 jj Exp $
  * creatorfb.c: Creator/Creator3D frame buffer driver
  *
- * Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz)
+ * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
  */
 
 #include <linux/module.h>
@@ -276,16 +276,18 @@
 	volatile u32	mer;
 };
 
-static __inline__ void FFBFifo(struct ffb_fbc *ffb, int n)
+static __inline__ void FFBFifo(struct fb_info_sbusfb *fb, int n)
 {
-	int limit = 10000;
+	struct ffb_fbc *fbc;
+	int cache = fb->s.ffb.fifo_cache;
 
-	do {
-		if((ffb->ucsr & FFB_UCSR_FIFO_MASK) >= (n + 4))
-			break;
-		if((ffb->ucsr & FFB_UCSR_ALL_ERRORS) != 0)
-			ffb->ucsr = FFB_UCSR_ALL_ERRORS;
-	} while(--limit > 0);
+	if (cache - n < 0) {
+		fbc = fb->s.ffb.fbc;
+		do {
+			cache = (fbc->ucsr & FFB_UCSR_FIFO_MASK) - 4;
+		} while (cache - n < 0);
+	}
+	fb->s.ffb.fifo_cache = cache - n;
 }
 
 static __inline__ void FFBWait(struct ffb_fbc *ffb)
@@ -340,40 +342,45 @@
 {
 	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
 	register struct ffb_fbc *fbc = fb->s.ffb.fbc;
-	int x, y, w, h;
+	u64 yx, hw;
+	int fg;
 	
-	FFBWait(fbc);
-	FFBFifo(fbc, 6);
-	fbc->fg = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p,conp)];
-	fbc->drawop = FFB_DRAWOP_RECTANGLE;
+	fg = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p,conp)];
+	if (fg != fb->s.ffb.fg_cache) {
+		FFBFifo(fb, 5);
+		fbc->fg = fg;
+		fb->s.ffb.fg_cache = fg;
+	} else
+		FFBFifo(fb, 4);
 
 	if (fontheightlog(p)) {
-		y = sy << fontheightlog(p); h = height << fontheightlog(p);
+		yx = (u64)sy << (fontheightlog(p) + 32); hw = (u64)height << (fontheightlog(p) + 32);
 	} else {
-		y = sy * fontheight(p); h = height * fontheight(p);
+		yx = (u64)(sy * fontheight(p)) << 32; hw = (u64)(height * fontheight(p)) << 32;
 	}
 	if (fontwidthlog(p)) {
-		x = sx << fontwidthlog(p); w = width << fontwidthlog(p);
+		yx += sx << fontwidthlog(p); hw += width << fontwidthlog(p);
 	} else {
-		x = sx * fontwidth(p); w = width * fontwidth(p);
+		yx += sx * fontwidth(p); hw += width * fontwidth(p);
 	}
-	fbc->by = y + fb->y_margin;
-	fbc->bx = x + fb->x_margin;
-	fbc->bh = h;
-	fbc->bw = w;
+	*(volatile u64 *)&fbc->by = yx + fb->s.ffb.yx_margin;
+	*(volatile u64 *)&fbc->bh = hw;
 }
 
 static void ffb_fill(struct fb_info_sbusfb *fb, struct display *p, int s,
 		     int count, unsigned short *boxes)
 {
 	register struct ffb_fbc *fbc = fb->s.ffb.fbc;
+	int fg;
 
-	FFBWait(fbc);
-	FFBFifo(fbc, 2);
-	fbc->fg = ((u32 *)p->dispsw_data)[attr_bgcol(p,s)];
-	fbc->drawop = FFB_DRAWOP_RECTANGLE;
+	fg = ((u32 *)p->dispsw_data)[attr_bgcol(p,s)];
+	if (fg != fb->s.ffb.fg_cache) {
+		FFBFifo(fb, 1);
+		fbc->fg = fg;
+		fb->s.ffb.fg_cache = fg;
+	}
 	while (count-- > 0) {
-		FFBFifo(fbc, 4);
+		FFBFifo(fb, 4);
 		fbc->by = boxes[1];
 		fbc->bx = boxes[0];
 		fbc->bh = boxes[3] - boxes[1];
@@ -388,6 +395,7 @@
 	register struct ffb_fbc *fbc = fb->s.ffb.fbc;
 	int i, xy;
 	u8 *fd;
+	u64 fgbg;
 
 	if (fontheightlog(p)) {
 		xy = (yy << (16 + fontheightlog(p)));
@@ -404,14 +412,16 @@
 		xy += (xx << fontwidthlog(p)) + fb->s.ffb.xy_margin;
 	else
 		xy += (xx * fontwidth(p)) + fb->s.ffb.xy_margin;
-	FFBWait(fbc);
-	FFBFifo(fbc, 5);
-	fbc->fg = ((u32 *)p->dispsw_data)[attr_fgcol(p,c)];
-	fbc->bg = ((u32 *)p->dispsw_data)[attr_bgcol(p,c)];
-	fbc->fontw = fontwidth(p);
-	fbc->fontinc = 0x10000;
+	fgbg = (((u64)(((u32 *)p->dispsw_data)[attr_fgcol(p,c)])) << 32) |
+	       ((u32 *)p->dispsw_data)[attr_bgcol(p,c)];
+	if (fgbg != *(u64 *)&fb->s.ffb.fg_cache) {
+		FFBFifo(fb, 2);
+		*(volatile u64 *)&fbc->fg = fgbg;
+		*(u64 *)&fb->s.ffb.fg_cache = fgbg;
+	}
+	FFBFifo(fb, 2 + fontheight(p));
 	fbc->fontxy = xy;
-	FFBFifo(fbc, fontheight(p));
+	fbc->fontw = fontwidth(p);
 	if (fontwidth(p) <= 8) {
 		for (i = 0; i < fontheight(p); i++)
 			fbc->font = *fd++ << 24;
@@ -430,11 +440,15 @@
 	register struct ffb_fbc *fbc = fb->s.ffb.fbc;
 	int i, xy;
 	u8 *fd1, *fd2, *fd3, *fd4;
+	u64 fgbg;
 
-	FFBWait(fbc);
-	FFBFifo(fbc, 2);
-	fbc->fg = ((u32 *)p->dispsw_data)[attr_fgcol(p,*s)];
-	fbc->bg = ((u32 *)p->dispsw_data)[attr_bgcol(p,*s)];
+	fgbg = (((u64)(((u32 *)p->dispsw_data)[attr_fgcol(p,scr_readw(s))])) << 32) |
+	       ((u32 *)p->dispsw_data)[attr_bgcol(p,scr_readw(s))];
+	if (fgbg != *(u64 *)&fb->s.ffb.fg_cache) {
+		FFBFifo(fb, 2);
+		*(volatile u64 *)&fbc->fg = fgbg;
+		*(u64 *)&fb->s.ffb.fg_cache = fgbg;
+	}
 	xy = fb->s.ffb.xy_margin;
 	if (fontwidthlog(p))
 		xy += (xx << fontwidthlog(p));
@@ -447,22 +461,20 @@
 	if (fontwidth(p) <= 8) {
 		while (count >= 4) {
 			count -= 4;
-			FFBFifo(fbc, 3);
+			FFBFifo(fb, 2 + fontheight(p));
 			fbc->fontw = 4 * fontwidth(p);
-			fbc->fontinc = 0x10000;
 			fbc->fontxy = xy;
 			if (fontheightlog(p)) {
-				fd1 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
-				fd2 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
-				fd3 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
-				fd4 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
+				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
+				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
+				fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
+				fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
 			} else {
-				fd1 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
-				fd2 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
-				fd3 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
-				fd4 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
+				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
+				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
+				fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
+				fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
 			}
-			FFBFifo(fbc, fontheight(p));
 			if (fontwidth(p) == 8) {
 				for (i = 0; i < fontheight(p); i++)
 					fbc->font = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
@@ -478,18 +490,16 @@
 	} else {
 		while (count >= 2) {
 			count -= 2;
-			FFBFifo(fbc, 3);
+			FFBFifo(fb, 2 + fontheight(p));
 			fbc->fontw = 2 * fontwidth(p);
-			fbc->fontinc = 0x10000;
 			fbc->fontxy = xy;
 			if (fontheightlog(p)) {
-				fd1 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
-				fd2 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
+				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
+				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
 			} else {
-				fd1 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
-				fd2 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
+				fd1 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
+				fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
 			}
-			FFBFifo(fbc, fontheight(p));
 			for (i = 0; i < fontheight(p); i++) {
 				fbc->font = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
 				fd1 += 2; fd2 += 2;
@@ -499,15 +509,13 @@
 	}
 	while (count) {
 		count--;
-		FFBFifo(fbc, 3);
+		FFBFifo(fb, 2 + fontheight(p));
 		fbc->fontw = fontwidth(p);
-		fbc->fontinc = 0x10000;
 		fbc->fontxy = xy;
 		if (fontheightlog(p))
-			i = ((*s++ & p->charmask) << fontheightlog(p));
+			i = ((scr_readw(s++) & p->charmask) << fontheightlog(p));
 		else
-			i = ((*s++ & p->charmask) * fontheight(p));
-		FFBFifo(fbc, fontheight(p));
+			i = ((scr_readw(s++) & p->charmask) * fontheight(p));
 		if (fontwidth(p) <= 8) {
 			fd1 = p->fontdata + i;
 			for (i = 0; i < fontheight(p); i++)
@@ -554,8 +562,12 @@
 
 static void ffb_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
 {
+	register struct ffb_fbc *fbc = fb->s.ffb.fbc;
+
 	fb->s.ffb.xy_margin = (y_margin << 16) + x_margin;
+	fb->s.ffb.yx_margin = (((u64)y_margin) << 32) + x_margin;
 	p->screen_base += 8192 * (y_margin - fb->y_margin) + 4 * (x_margin - fb->x_margin);
+	FFBWait(fbc);
 }
 
 static inline void ffb_curs_enable (struct fb_info_sbusfb *fb, int enable)
@@ -619,11 +631,16 @@
 	register struct ffb_fbc *fbc = fb->s.ffb.fbc;
 
 	FFBWait(fbc);
-	FFBFifo(fbc, 4);
+	fb->s.ffb.fifo_cache = 0;
+	FFBFifo(fb, 8);
 	fbc->ppc = FFB_PPC_VCE_DISABLE|FFB_PPC_TBE_OPAQUE|FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST;
 	fbc->fbc = 0x2000707f;
 	fbc->rop = FFB_ROP_NEW;
+	fbc->drawop = FFB_DRAWOP_RECTANGLE;
 	fbc->pmask = 0xffffffff;
+	fbc->fontinc = 0x10000;
+	fbc->fg = fb->s.ffb.fg_cache;
+	fbc->bg = fb->s.ffb.bg_cache;
 	FFBWait(fbc);
 }                                
 
@@ -675,6 +692,7 @@
 	disp->scrollmode = SCROLL_YREDRAW;
 	disp->screen_base = (char *)__va(regs[0].phys_addr) + FFB_DFB24_POFF + 8192 * fb->y_margin + 4 * fb->x_margin;
 	fb->s.ffb.xy_margin = (fb->y_margin << 16) + fb->x_margin;
+	fb->s.ffb.yx_margin = (((u64)fb->y_margin) << 32) + fb->x_margin;
 	fb->s.ffb.fbc = (struct ffb_fbc *)((char *)__va(regs[0].phys_addr) + FFB_FBC_REGS_POFF);
 	fb->s.ffb.dac = (struct ffb_dac *)((char *)__va(regs[0].phys_addr) + FFB_DAC_POFF);
 	fb->dispsw = ffb_dispsw;
diff -u --recursive --new-file v2.2.2/linux/drivers/video/cvisionppc.h linux/drivers/video/cvisionppc.h
--- v2.2.2/linux/drivers/video/cvisionppc.h	Wed Jan 20 23:14:06 1999
+++ linux/drivers/video/cvisionppc.h	Thu Feb 25 10:02:12 1999
@@ -4,7 +4,7 @@
  *
  * Copyright (c) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
  * --------------------------------------------------------------------------
- * $Id: cvisionppc.h,v 1.1.2.1 1999/01/12 19:52:59 geert Exp $
+ * $Id: cvisionppc.h,v 1.8 1999/01/28 13:18:07 illo Exp $
  * --------------------------------------------------------------------------
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file README.legal in the main directory of this archive
@@ -21,7 +21,7 @@
 struct cvppc_par {
 	unsigned char* pci_config;
 	unsigned char* pci_bridge;
-	unsigned long user_flags;
+	u32 user_flags;
 };
 
 #define CSPPC_PCI_BRIDGE		0xfffe0000
diff -u --recursive --new-file v2.2.2/linux/drivers/video/fbcon-afb.c linux/drivers/video/fbcon-afb.c
--- v2.2.2/linux/drivers/video/fbcon-afb.c	Mon Oct  5 13:13:41 1998
+++ linux/drivers/video/fbcon-afb.c	Thu Feb 25 10:02:12 1999
@@ -290,12 +290,12 @@
     int fg0, bg0, fg, bg;
 
     dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
-    fg0 = attr_fgcol(p,*s);
-    bg0 = attr_bgcol(p,*s);
+    fg0 = attr_fgcol(p, scr_readw(s));
+    bg0 = attr_bgcol(p, scr_readw(s));
 
     while (count--)
 	if (xx&3 || count < 3) {	/* Slow version */
-	    c1 = *s++ & p->charmask;
+	    c1 = scr_readw(s++) & p->charmask;
 	    dest1 = dest0++;
 	    xx++;
 
@@ -322,10 +322,10 @@
 		dest1 += p->next_plane;
 	    } while (--i);
 	} else {			/* Fast version */
-	    c1 = s[0] & p->charmask;
-	    c2 = s[1] & p->charmask;
-	    c3 = s[2] & p->charmask;
-	    c4 = s[3] & p->charmask;
+	    c1 = scr_readw(&s[0]) & p->charmask;
+	    c2 = scr_readw(&s[1]) & p->charmask;
+	    c3 = scr_readw(&s[2]) & p->charmask;
+	    c4 = scr_readw(&s[3]) & p->charmask;
 
 	    dest1 = dest0;
 	    cdat10 = p->fontdata+c1*fontheight(p);
diff -u --recursive --new-file v2.2.2/linux/drivers/video/fbcon-cfb16.c linux/drivers/video/fbcon-cfb16.c
--- v2.2.2/linux/drivers/video/fbcon-cfb16.c	Mon Oct  5 13:13:41 1998
+++ linux/drivers/video/fbcon-cfb16.c	Thu Feb 25 10:02:12 1999
@@ -177,8 +177,8 @@
     u32 eorx, fgx, bgx;
 
     dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 2;
-    fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, *s)];
-    bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, *s)];
+    fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, scr_readw(s))];
+    bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, scr_readw(s))];
     fgx |= (fgx << 16);
     bgx |= (bgx << 16);
     eorx = fgx ^ bgx;
@@ -187,7 +187,7 @@
     case 4:
     case 8:
 	while (count--) {
-	    c = *s++ & p->charmask;
+	    c = scr_readw(s++) & p->charmask;
 	    cdat = p->fontdata + c * fontheight(p);
 	    for (rows = fontheight(p), dest = dest0; rows--; dest += bytes) {
 		u8 bits = *cdat++;
@@ -204,7 +204,7 @@
     case 12:
     case 16:
 	while (count--) {
-	    c = *s++ & p->charmask;
+	    c = scr_readw(s++) & p->charmask;
 	    cdat = p->fontdata + (c * fontheight(p) << 1);
 	    for (rows = fontheight(p), dest = dest0; rows--; dest += bytes) {
 		u8 bits = *cdat++;
diff -u --recursive --new-file v2.2.2/linux/drivers/video/fbcon-cfb2.c linux/drivers/video/fbcon-cfb2.c
--- v2.2.2/linux/drivers/video/fbcon-cfb2.c	Mon Oct  5 13:13:41 1998
+++ linux/drivers/video/fbcon-cfb2.c	Thu Feb 25 10:02:12 1999
@@ -156,15 +156,15 @@
 	u32 eorx, fgx, bgx;
 
 	dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * 2;
-	fgx=3/*attr_fgcol(p,*s)*/;
-	bgx=attr_bgcol(p,*s);
+	fgx=3/*attr_fgcol(p,scr_readw(s))*/;
+	bgx=attr_bgcol(p,scr_readw(s));
 	fgx |= (fgx << 2);
 	fgx |= (fgx << 4);
 	bgx |= (bgx << 2);
 	bgx |= (bgx << 4);
 	eorx = fgx ^ bgx;
 	while (count--) {
-		c = *s++ & p->charmask;
+		c = scr_readw(s++) & p->charmask;
 		cdat = p->fontdata + c * fontheight(p);
 
 		for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
diff -u --recursive --new-file v2.2.2/linux/drivers/video/fbcon-cfb24.c linux/drivers/video/fbcon-cfb24.c
--- v2.2.2/linux/drivers/video/fbcon-cfb24.c	Mon Oct  5 13:13:41 1998
+++ linux/drivers/video/fbcon-cfb24.c	Thu Feb 25 10:02:12 1999
@@ -187,11 +187,11 @@
     u32 eorx, fgx, bgx, d1, d2, d3, d4;
 
     dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 3;
-    fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, *s)];
-    bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, *s)];
+    fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, scr_readw(s))];
+    bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, scr_readw(s))];
     eorx = fgx ^ bgx;
     while (count--) {
-	c = *s++ & p->charmask;
+	c = scr_readw(s++) & p->charmask;
 	if (fontwidth(p) <= 8)
 	    cdat = p->fontdata + c * fontheight(p);
 	  
diff -u --recursive --new-file v2.2.2/linux/drivers/video/fbcon-cfb32.c linux/drivers/video/fbcon-cfb32.c
--- v2.2.2/linux/drivers/video/fbcon-cfb32.c	Mon Oct  5 13:13:41 1998
+++ linux/drivers/video/fbcon-cfb32.c	Thu Feb 25 10:02:12 1999
@@ -163,11 +163,11 @@
     u32 eorx, fgx, bgx;
 
     dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 4;
-    fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, *s)];
-    bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, *s)];
+    fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, scr_readw(s))];
+    bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, scr_readw(s))];
     eorx = fgx ^ bgx;
     while (count--) {
-	c = *s++ & p->charmask;
+	c = scr_readw(s++) & p->charmask;
 	if (fontwidth(p) <= 8)
 	    cdat = p->fontdata + c * fontheight(p);
 	else
diff -u --recursive --new-file v2.2.2/linux/drivers/video/fbcon-cfb4.c linux/drivers/video/fbcon-cfb4.c
--- v2.2.2/linux/drivers/video/fbcon-cfb4.c	Mon Oct  5 13:13:41 1998
+++ linux/drivers/video/fbcon-cfb4.c	Thu Feb 25 10:02:12 1999
@@ -158,8 +158,8 @@
 	u32 eorx, fgx, bgx;
 
 	dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * 4;
-	fgx=attr_fgcol(p,*s);
-	bgx=attr_bgcol(p,*s);
+	fgx=attr_fgcol(p,scr_readw(s));
+	bgx=attr_bgcol(p,scr_readw(s));
 	fgx |= (fgx << 4);
 	fgx |= (fgx << 8);
 	fgx |= (fgx << 16);
@@ -168,7 +168,7 @@
 	bgx |= (bgx << 16);
 	eorx = fgx ^ bgx;
 	while (count--) {
-		c = *s++ & p->charmask;
+		c = scr_readw(s++) & p->charmask;
 		cdat = p->fontdata + c * fontheight(p);
 
 		for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
diff -u --recursive --new-file v2.2.2/linux/drivers/video/fbcon-cfb8.c linux/drivers/video/fbcon-cfb8.c
--- v2.2.2/linux/drivers/video/fbcon-cfb8.c	Tue Dec 22 14:16:56 1998
+++ linux/drivers/video/fbcon-cfb8.c	Thu Feb 25 10:02:12 1999
@@ -163,8 +163,8 @@
     u32 eorx, fgx, bgx;
 
     dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p);
-    fgx=attr_fgcol(p,*s);
-    bgx=attr_bgcol(p,*s);
+    fgx=attr_fgcol(p,scr_readw(s));
+    bgx=attr_bgcol(p,scr_readw(s));
     fgx |= (fgx << 8);
     fgx |= (fgx << 16);
     bgx |= (bgx << 8);
@@ -173,7 +173,7 @@
     switch (fontwidth(p)) {
     case 4:
 	while (count--) {
-	    c = *s++ & p->charmask;
+	    c = scr_readw(s++) & p->charmask;
 	    cdat = p->fontdata + c * fontheight(p);
 
 	    for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes)
@@ -183,7 +183,7 @@
         break;
     case 8:
 	while (count--) {
-	    c = *s++ & p->charmask;
+	    c = scr_readw(s++) & p->charmask;
 	    cdat = p->fontdata + c * fontheight(p);
 
 	    for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
@@ -196,7 +196,7 @@
     case 12:
     case 16:
 	while (count--) {
-	    c = *s++ & p->charmask;
+	    c = scr_readw(s++) & p->charmask;
 	    cdat = p->fontdata + (c * fontheight(p) << 1);
 
 	    for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
diff -u --recursive --new-file v2.2.2/linux/drivers/video/fbcon-ilbm.c linux/drivers/video/fbcon-ilbm.c
--- v2.2.2/linux/drivers/video/fbcon-ilbm.c	Mon Oct  5 13:13:41 1998
+++ linux/drivers/video/fbcon-ilbm.c	Thu Feb 25 10:02:12 1999
@@ -154,12 +154,12 @@
     int fg0, bg0, fg, bg;
 
     dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
-    fg0 = attr_fgcol(p,*s);
-    bg0 = attr_bgcol(p,*s);
+    fg0 = attr_fgcol(p,scr_readw(s));
+    bg0 = attr_bgcol(p,scr_readw(s));
 
     while (count--)
 	if (xx&3 || count < 3) {	/* Slow version */
-	    c1 = *s++ & p->charmask;
+	    c1 = scr_readw(s++) & p->charmask;
 	    dest = dest0++;
 	    xx++;
 
@@ -185,10 +185,10 @@
 		}
 	    }
 	} else {		/* Fast version */
-	    c1 = s[0] & p->charmask;
-	    c2 = s[1] & p->charmask;
-	    c3 = s[2] & p->charmask;
-	    c4 = s[3] & p->charmask;
+	    c1 = scr_readw(&s[0]) & p->charmask;
+	    c2 = scr_readw(&s[1]) & p->charmask;
+	    c3 = scr_readw(&s[2]) & p->charmask;
+	    c4 = scr_readw(&s[3]) & p->charmask;
 
 	    dest = dest0;
 	    cdat1 = p->fontdata+c1*fontheight(p);
diff -u --recursive --new-file v2.2.2/linux/drivers/video/fbcon-iplan2p2.c linux/drivers/video/fbcon-iplan2p2.c
--- v2.2.2/linux/drivers/video/fbcon-iplan2p2.c	Wed Jan 20 23:14:06 1999
+++ linux/drivers/video/fbcon-iplan2p2.c	Thu Feb 25 10:02:12 1999
@@ -361,12 +361,12 @@
     else
 	dest0 = (p->screen_base + yy * bytes * fontheight(p) +
 		 (xx>>1)*4 + (xx & 1));
-    fgx = expand2w(COLOR_2P(attr_fgcol(p,*s)));
-    bgx = expand2w(COLOR_2P(attr_bgcol(p,*s)));
+    fgx = expand2w(COLOR_2P(attr_fgcol(p,scr_readw(s))));
+    bgx = expand2w(COLOR_2P(attr_bgcol(p,scr_readw(s))));
     eorx = fgx ^ bgx;
 
     while (count--) {
-	c = *s++ & p->charmask;
+	c = scr_readw(s++) & p->charmask;
 	if (fontheightlog(p))
 	    cdat = p->fontdata + (c << fontheightlog(p));
 	else
diff -u --recursive --new-file v2.2.2/linux/drivers/video/fbcon-iplan2p4.c linux/drivers/video/fbcon-iplan2p4.c
--- v2.2.2/linux/drivers/video/fbcon-iplan2p4.c	Wed Jan 20 23:14:06 1999
+++ linux/drivers/video/fbcon-iplan2p4.c	Thu Feb 25 10:02:12 1999
@@ -371,8 +371,8 @@
     else
 	dest0 = (p->screen_base + yy * bytes * fontheight(p) +
 		 (xx>>1)*8 + (xx & 1));
-    fgx = expand4l(attr_fgcol(p,*s));
-    bgx = expand4l(attr_bgcol(p,*s));
+    fgx = expand4l(attr_fgcol(p,scr_readw(s)));
+    bgx = expand4l(attr_bgcol(p,scr_readw(s)));
     eorx = fgx ^ bgx;
 
     while (count--) {
@@ -383,7 +383,7 @@
 	* cache :-(
 	*/
 
-	c = *s++ & p->charmask;
+	c = scr_readw(s++) & p->charmask;
 	if (fontheightlog(p))
 	    cdat = p->fontdata + (c << fontheightlog(p));
 	else
diff -u --recursive --new-file v2.2.2/linux/drivers/video/fbcon-iplan2p8.c linux/drivers/video/fbcon-iplan2p8.c
--- v2.2.2/linux/drivers/video/fbcon-iplan2p8.c	Wed Jan 20 23:14:06 1999
+++ linux/drivers/video/fbcon-iplan2p8.c	Thu Feb 25 10:02:12 1999
@@ -404,8 +404,8 @@
 	dest0 = (p->screen_base + yy * bytes * fontheight(p) +
 		 (xx>>1)*16 + (xx & 1));
 
-    expand8dl(attr_fgcol(p,*s), &fgx1, &fgx2);
-    expand8dl(attr_bgcol(p,*s), &bgx1, &bgx2);
+    expand8dl(attr_fgcol(p,scr_readw(s)), &fgx1, &fgx2);
+    expand8dl(attr_bgcol(p,scr_readw(s)), &bgx1, &bgx2);
     eorx1 = fgx1 ^ bgx1; eorx2  = fgx2 ^ bgx2;
 
     while (count--) {
@@ -417,7 +417,7 @@
 	* cache :-(
 	*/
 
-	c = *s++ & p->charmask;
+	c = scr_readw(s++) & p->charmask;
 	if (fontheightlog(p))
 	    cdat = p->fontdata + (c << fontheightlog(p));
 	else
diff -u --recursive --new-file v2.2.2/linux/drivers/video/fbcon-mac.c linux/drivers/video/fbcon-mac.c
--- v2.2.2/linux/drivers/video/fbcon-mac.c	Mon Oct  5 13:13:41 1998
+++ linux/drivers/video/fbcon-mac.c	Thu Feb 25 10:02:12 1999
@@ -301,7 +301,7 @@
    u16 c;
 
    while (count--) {
-      c = *s++;
+      c = scr_readw(s++);
       fbcon_mac_putc(conp, p, c, yy, xx++);
    }
 }
diff -u --recursive --new-file v2.2.2/linux/drivers/video/fbcon-mfb.c linux/drivers/video/fbcon-mfb.c
--- v2.2.2/linux/drivers/video/fbcon-mfb.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/video/fbcon-mfb.c	Thu Feb 25 10:02:12 1999
@@ -117,12 +117,12 @@
     u16 c;
 
     dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
-    bold = attr_bold(p,*s);
-    revs = attr_reverse(p,*s);
-    underl = attr_underline(p,*s);
+    bold = attr_bold(p,scr_readw(s));
+    revs = attr_reverse(p,scr_readw(s));
+    underl = attr_underline(p,scr_readw(s));
 
     while (count--) {
-	c = *s++ & p->charmask;
+	c = scr_readw(s++) & p->charmask;
 	dest = dest0++;
 	cdat = p->fontdata+c*fontheight(p);
 	for (rows = fontheight(p); rows--; dest += p->next_line) {
diff -u --recursive --new-file v2.2.2/linux/drivers/video/fbcon-vga.c linux/drivers/video/fbcon-vga.c
--- v2.2.2/linux/drivers/video/fbcon-vga.c	Mon Oct  5 13:13:41 1998
+++ linux/drivers/video/fbcon-vga.c	Thu Feb 25 10:02:12 1999
@@ -155,11 +155,11 @@
     u16 sattr;
     if (conp->vc_can_do_color)
     	while (count--)
-    	    vga_writew(*s++, dst++);
+    	    vga_writew(scr_readw(s++), dst++);
     else {
-        sattr = fbcon_vga_attr(p, *s);
+        sattr = fbcon_vga_attr(p, scr_readw(s));
         while (count--)
-	    vga_writew(sattr | ((int) (*s++) & 0xff), dst++);
+	    vga_writew(sattr | ((int) (scr_readw(s++)) & 0xff), dst++);
     }
 }
 
diff -u --recursive --new-file v2.2.2/linux/drivers/video/fbcon.c linux/drivers/video/fbcon.c
--- v2.2.2/linux/drivers/video/fbcon.c	Wed Jan 20 23:14:06 1999
+++ linux/drivers/video/fbcon.c	Sun Mar  7 23:50:49 1999
@@ -26,7 +26,7 @@
  *
  *  Hardware cursor support added by Emmanuel Marty (core@ggi-project.org)
  *  Smart redraw scrolling, arbitrary font width support, 512char font support
- *  added by 
+ *  and software scrollback added by 
  *                         Jakub Jelinek (jj@ultra.linux.cz)
  *
  *  Random hacking by Martin Mares <mj@ucw.cz>
@@ -111,6 +111,12 @@
 struct display fb_display[MAX_NR_CONSOLES];
 static int logo_lines;
 static int logo_shown = -1;
+/* Software scrollback */
+extern int fbcon_softback_size;
+static unsigned long softback_buf, softback_curr;
+static unsigned long softback_in;
+static unsigned long softback_top, softback_end;
+static int softback_lines;
 
 #define REFCOUNT(fd)	(((int *)(fd))[-1])
 #define FNTSIZE(fd)	(((int *)(fd))[-2])
@@ -118,7 +124,12 @@
 #define FNTSUM(fd)	(((int *)(fd))[-4])
 #define FONT_EXTRA_WORDS 4
 
-static void fbcon_free_font(struct display *p);
+#define CM_SOFTBACK	(8)
+
+#define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * conp->vc_size_row)
+
+static void fbcon_free_font(struct display *);
+static int fbcon_set_origin(struct vc_data *);
 
 /*
  * Emmanuel: fbcon will now use a hardware cursor if the
@@ -422,6 +433,27 @@
     	logo = 0;
 
     p->var.xoffset = p->var.yoffset = p->yscroll = 0;  /* reset wrap/pan */
+
+    if (con == fg_console && p->type != FB_TYPE_TEXT) {   
+	if (fbcon_softback_size) {
+	    if (!softback_buf) {
+		softback_buf = (unsigned long)kmalloc(fbcon_softback_size, GFP_KERNEL);
+		if (!softback_buf) {
+    	            fbcon_softback_size = 0;
+    	            softback_top = 0;
+    		}
+    	    }
+	} else {
+	    if (softback_buf) {
+		kfree((void *)softback_buf);
+		softback_buf = 0;
+		softback_top = 0;
+	    }
+	}
+	if (softback_buf)
+	    softback_in = softback_top = softback_curr = softback_buf;
+	softback_lines = 0;
+    }
     
     for (i = 0; i < MAX_NR_CONSOLES; i++)
     	if (i != con && fb_display[i].fb_info == p->fb_info &&
@@ -579,6 +611,17 @@
 	logo_shown = -2;
     	conp->vc_top = logo_lines;
     }
+    
+    if (con == fg_console && softback_buf) {
+    	int l = fbcon_softback_size / conp->vc_size_row;
+    	if (l > 5)
+    	    softback_end = softback_buf + l * conp->vc_size_row;
+    	else {
+    	    /* Smaller scrollback makes no sense, and 0 would screw
+    	       the operation totally */
+    	    softback_top = 0;
+    	}
+    }
 }
 
 
@@ -703,17 +746,29 @@
 {
     int unit = conp->vc_num;
     struct display *p = &fb_display[unit];
+    int y = conp->vc_y;
+    
+    if (mode & CM_SOFTBACK) {
+    	mode &= ~CM_SOFTBACK;
+    	if (softback_lines) {
+    	    if (y + softback_lines >= conp->vc_rows)
+    		mode = CM_ERASE;
+    	    else
+    	        y += softback_lines;
+    	}
+    } else if (softback_lines)
+        fbcon_set_origin(conp);
 
     /* do we have a hardware cursor ? */
     if (p->dispsw->cursor) {
 	p->cursor_x = conp->vc_x;
-	p->cursor_y = conp->vc_y;
+	p->cursor_y = y;
 	p->dispsw->cursor(p, mode, p->cursor_x, real_y(p, p->cursor_y));
 	return;
     }
 
     /* Avoid flickering if there's no real change. */
-    if (p->cursor_x == conp->vc_x && p->cursor_y == conp->vc_y &&
+    if (p->cursor_x == conp->vc_x && p->cursor_y == y &&
 	(mode == CM_ERASE) == !cursor_on)
 	return;
 
@@ -722,7 +777,7 @@
         p->dispsw->revc(p, p->cursor_x, real_y(p, p->cursor_y));
 
     p->cursor_x = conp->vc_x;
-    p->cursor_y = conp->vc_y;
+    p->cursor_y = y;
 
     switch (mode) {
         case CM_ERASE:
@@ -836,6 +891,94 @@
     scrollback_current = 0;
 }
 
+static void fbcon_redraw_softback(struct vc_data *conp, struct display *p, long delta)
+{
+    unsigned short *d, *s;
+    unsigned long n;
+    int line = 0;
+    int count = conp->vc_rows;
+    
+    d = (u16 *)softback_curr;
+    if (d == (u16 *)softback_in)
+	d = (u16 *)conp->vc_origin;
+    n = softback_curr + delta * conp->vc_size_row;
+    softback_lines -= delta;
+    if (delta < 0) {
+        if (softback_curr < softback_top && n < softback_buf) {
+            n += softback_end - softback_buf;
+	    if (n < softback_top) {
+		softback_lines -= (softback_top - n) / conp->vc_size_row;
+		n = softback_top;
+	    }
+        } else if (softback_curr >= softback_top && n < softback_top) {
+	    softback_lines -= (softback_top - n) / conp->vc_size_row;
+	    n = softback_top;
+        }
+    } else {
+    	if (softback_curr > softback_in && n >= softback_end) {
+    	    n += softback_buf - softback_end;
+	    if (n > softback_in) {
+		n = softback_in;
+		softback_lines = 0;
+	    }
+	} else if (softback_curr <= softback_in && n > softback_in) {
+	    n = softback_in;
+	    softback_lines = 0;
+	}
+    }
+    if (n == softback_curr)
+    	return;
+    softback_curr = n;
+    s = (u16 *)softback_curr;
+    if (s == (u16 *)softback_in)
+	s = (u16 *)conp->vc_origin;
+    while (count--) {
+	unsigned short *start;
+	unsigned short *le;
+	unsigned short c;
+	int x = 0;
+	unsigned short attr = 1;
+
+	start = s;
+	le = advance_row(s, 1);
+	do {
+	    c = scr_readw(s);
+	    if (attr != (c & 0xff00)) {
+		attr = c & 0xff00;
+		if (s > start) {
+		    p->dispsw->putcs(conp, p, start, s - start,
+				     real_y(p, line), x);
+		    x += s - start;
+		    start = s;
+		}
+	    }
+	    if (c == scr_readw(d)) {
+	    	if (s > start) {
+	    	    p->dispsw->putcs(conp, p, start, s - start,
+				     real_y(p, line), x);
+		    x += s - start + 1;
+		    start = s + 1;
+	    	} else {
+	    	    x++;
+	    	    start++;
+	    	}
+	    }
+	    s++;
+	    d++;
+	} while (s < le);
+	if (s > start)
+	    p->dispsw->putcs(conp, p, start, s - start, real_y(p, line), x);
+	line++;
+	if (d == (u16 *)softback_end)
+	    d = (u16 *)softback_buf;
+	if (d == (u16 *)softback_in)
+	    d = (u16 *)conp->vc_origin;
+	if (s == (u16 *)softback_end)
+	    s = (u16 *)softback_buf;
+	if (s == (u16 *)softback_in)
+	    s = (u16 *)conp->vc_origin;
+    }
+}
 
 static void fbcon_redraw(struct vc_data *conp, struct display *p, 
 			 int line, int count, int offset)
@@ -846,8 +989,7 @@
 
     while (count--) {
 	unsigned short *start = s;
-	unsigned short *le = (unsigned short *)
-	    ((unsigned long)s + conp->vc_size_row);
+	unsigned short *le = advance_row(s, 1);
 	unsigned short c;
 	int x = 0;
 	unsigned short attr = 1;
@@ -940,13 +1082,32 @@
     }
 }
 
+static inline void fbcon_softback_note(struct vc_data *conp, int t, int count)
+{
+    unsigned short *p = (unsigned short *)
+    	(conp->vc_origin + t * conp->vc_size_row);
+    while (count) {
+    	scr_memcpyw((u16 *)softback_in, p, conp->vc_size_row);
+    	count--;
+    	p = advance_row(p, 1);
+    	softback_in += conp->vc_size_row;
+    	if (softback_in == softback_end)
+    	    softback_in = softback_buf;
+    	if (softback_in == softback_top) {
+    	    softback_top += conp->vc_size_row;
+    	    if (softback_top == softback_end)
+    	    	softback_top = softback_buf;
+    	}
+    }
+    softback_curr = softback_in;
+}
+
 static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir,
 			int count)
 {
     int unit = conp->vc_num;
     struct display *p = &fb_display[unit];
     int scroll_partial = !(p->scrollmode & __SCROLL_YNOPARTIAL);
-    int logos_left = 0; int logos_width = conp->vc_cols;
 
     if (!p->can_soft_blank && console_blanked)
 	return 0;
@@ -955,7 +1116,7 @@
 	return 0;
 
     fbcon_cursor(conp, CM_ERASE);
-
+    
     /*
      * ++Geert: Only use ywrap/ypan if the console is in text mode
      * ++Andrew: Only use ypan on hardware text mode when scrolling the
@@ -964,34 +1125,25 @@
 
     switch (dir) {
 	case SM_UP:
-	    /* K.Garloff@ping.de, 98/10/21: If logo is diplayed, only save logo
-	     * and not the hole top region. In combination with the logo being
-	     * displayed on the right side, this allows scrollback feature
-	     * when bootlogo is displayed. */
-            if (t != 0 && logo_shown == fg_console) {
-		struct display *p = &fb_display[unit];
-		int lw = (smp_num_cpus * (LOGO_W + 8) - 7) / fontwidth(p) + 1;
-		logos_left = conp->vc_cols - lw;
-		while (logos_left < 0) logos_left += (LOGO_W + 8 - 7) / fontwidth(p);
-		logos_width = conp->vc_cols - logos_left;
-	    }
 	    if (count > conp->vc_rows)	/* Maximum realistic size */
 		count = conp->vc_rows;
+	    if (softback_top)
+	        fbcon_softback_note(conp, t, count);
+	    if (logo_shown >= 0) goto redraw_up;
 	    switch (p->scrollmode & __SCROLL_YMASK) {
 	    case __SCROLL_YMOVE:
-	        if (t > 0) p->dispsw->bmove(p, 0, logos_left, count,
-					logos_left, t, logos_width);
-	        p->dispsw->bmove(p, count, 0, 0, 0, b-count,
+		p->dispsw->bmove(p, t+count, 0, t, 0, b-t-count,
 				 conp->vc_cols);
-	        p->dispsw->clear(conp, p, b-count, 0, count,
+		p->dispsw->clear(conp, p, b-count, 0, count,
 				 conp->vc_cols);
 		break;
 
 	    case __SCROLL_YWRAP:
-		if (b-t-count > 2*conp->vc_rows/3) {
+		if (b-t-count > 3*conp->vc_rows>>2) {
 		    if (t > 0)
-			fbcon_bmove(conp, 0, logos_left, count, logos_left, t, logos_width);
-		    ywrap_up(unit, conp, p, count);
+			fbcon_bmove(conp, 0, 0, count, 0, t,
+				    conp->vc_cols);
+			ywrap_up(unit, conp, p, count);
 		    if (conp->vc_rows-b > 0)
 			fbcon_bmove(conp, b-count, 0, b, 0,
 				    conp->vc_rows-b, conp->vc_cols);
@@ -1004,11 +1156,12 @@
 		break;
 
 	    case __SCROLL_YPAN:
-		if (( !scroll_partial && (b-t == conp->vc_rows)) ||
-		    ( scroll_partial  && (b-t-count > 3*conp->vc_rows>>2))) {
+		if (( p->yscroll + count <= 2 * (p->vrows - conp->vc_rows)) &&
+		    (( !scroll_partial && (b-t == conp->vc_rows)) ||
+		     ( scroll_partial  && (b-t-count > 3*conp->vc_rows>>2)))) {
 		    if (t > 0)
-			fbcon_bmove(conp, 0, logos_left, count, logos_left, t,
-				    logos_width);
+			fbcon_bmove(conp, 0, 0, count, 0, t,
+				    conp->vc_cols);
 		    ypan_up(unit, conp, p, count);
 		    if (conp->vc_rows-b > 0)
 			fbcon_bmove(conp, b-count, 0, b, 0,
@@ -1063,8 +1216,9 @@
 		break;
 
 	    case __SCROLL_YPAN:
-		if (( !scroll_partial && (b-t == conp->vc_rows)) ||
-		    ( scroll_partial  && (b-t-count > 3*conp->vc_rows>>2))) {
+		if (( count-p->yscroll <= p->vrows-conp->vc_rows) &&
+		    (( !scroll_partial && (b-t == conp->vc_rows)) ||
+		     ( scroll_partial  && (b-t-count > 3*conp->vc_rows>>2)))) {
 		    if (conp->vc_rows-b > 0)
 			fbcon_bmove(conp, b, 0, b-count, 0,
 				    conp->vc_rows-b, conp->vc_cols);
@@ -1112,7 +1266,7 @@
 	  (sx <= p->cursor_x) && (p->cursor_x < sx+width)) ||
 	 ((dy <= p->cursor_y) && (p->cursor_y < dy+height) &&
 	  (dx <= p->cursor_x) && (p->cursor_x < dx+width)))
-	fbcon_cursor(conp, CM_ERASE);
+	fbcon_cursor(conp, CM_ERASE|CM_SOFTBACK);
 
     /*  Split blits that cross physical y_wrap case.
      *  Pathological case involves 4 blits, better to use recursive
@@ -1162,6 +1316,21 @@
     struct display *p = &fb_display[unit];
     struct fb_info *info = p->fb_info;
 
+    if (softback_top) {
+    	int l = fbcon_softback_size / conp->vc_size_row;
+	if (softback_lines)
+	    fbcon_set_origin(conp);
+        softback_top = softback_curr = softback_in = softback_buf;
+        softback_lines = 0;
+
+	if (l > 5)
+	    softback_end = softback_buf + l * conp->vc_size_row;
+	else {
+	    /* Smaller scrollback makes no sense, and 0 would screw
+	       the operation totally */
+	    softback_top = 0;
+	}
+    }
     if (logo_shown >= 0) {
     	struct vc_data *conp2 = vc_cons[logo_shown].d;
     	
@@ -1227,8 +1396,22 @@
 		    mymemset(p->screen_base,
 			     p->var.xres_virtual*p->var.yres_virtual*
 			     p->var.bits_per_pixel>>3);
-	     } else
-		 p->dispsw->clear(conp, p, 0, 0, conp->vc_rows, conp->vc_cols);
+	    } else {
+	    	unsigned short oldc;
+	    	u_int height;
+	    	u_int y_break;
+
+	    	oldc = conp->vc_video_erase_char;
+	    	conp->vc_video_erase_char &= p->charmask;
+	    	height = conp->vc_rows;
+		y_break = p->vrows-p->yscroll;
+		if (height > y_break) {
+			p->dispsw->clear(conp, p, real_y(p, 0), 0, y_break, conp->vc_cols);
+			p->dispsw->clear(conp, p, real_y(p, y_break), 0, height-y_break, conp->vc_cols);
+		} else
+			p->dispsw->clear(conp, p, real_y(p, 0), 0, height, conp->vc_cols);
+		conp->vc_video_erase_char = oldc;
+	    }
 	    return 0;
 	} else {
 	    /* Tell console.c that it has to restore the screen itself */
@@ -1320,6 +1503,9 @@
 	return -ENXIO;
     }
 
+    if (CON_IS_VISIBLE(p->conp) && softback_lines)
+	fbcon_set_origin(p->conp);
+	
     resize = (w != fontwidth(p)) || (h != fontheight(p));
     if (p->userfont)
         old_data = p->fontdata;
@@ -1390,6 +1576,7 @@
     fbcon_font_widths(p);
 
     if (resize) {
+    	struct vc_data *conp = p->conp;
 	/* reset wrap/pan */
 	p->var.xoffset = p->var.yoffset = p->yscroll = 0;
 	p->vrows = p->var.yres_virtual/h;
@@ -1397,6 +1584,16 @@
 	    p->vrows--;
 	updatescrollmode(p);
 	vc_resize_con( p->var.yres/h, p->var.xres/w, unit );
+        if (CON_IS_VISIBLE(conp) && softback_buf) {
+	    int l = fbcon_softback_size / conp->vc_size_row;
+	    if (l > 5)
+		softback_end += l * conp->vc_size_row;
+	    else {
+		/* Smaller scrollback makes no sense, and 0 would screw
+		   the operation totally */
+		softback_top = 0;
+    	    }
+    	}
     } else if (CON_IS_VISIBLE(p->conp) && vt_cons[unit]->vc_mode == KD_TEXT) {
 	if (p->dispsw->clear_margins)
 	    p->dispsw->clear_margins(p->conp, p, 0);
@@ -1432,9 +1629,6 @@
     int h = op->height;
     int size = h;
     int i, k;
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
-    int j;
-#endif
     u8 *new_data, *data = op->data, *p;
 
 #ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
@@ -1476,6 +1670,7 @@
 	}
     } else if (w <= 24) {
 	for (i = 0; i < op->charcount; i++) {
+	    int j;
 	    for (j = 0; j < h; j++) {
 	        memcpy(p, data, 3);
 		p[3] = 0;
@@ -1586,10 +1781,119 @@
     return p->fb_info->fbops->fb_set_cmap(&palette_cmap, 1, unit, p->fb_info);
 }
 
+static u16 *fbcon_screen_pos(struct vc_data *conp, int offset)
+{
+    int line;
+    unsigned long p;
+
+    if (conp->vc_num != fg_console || !softback_lines)
+    	return (u16 *)(conp->vc_origin + offset);
+    line = offset / conp->vc_size_row;
+    if (line >= softback_lines)
+    	return (u16 *)(conp->vc_origin + offset - softback_lines * conp->vc_size_row);
+    p = softback_curr + offset;
+    if (p >= softback_end)
+    	p += softback_buf - softback_end;
+    return (u16 *)p;
+}
+
+static unsigned long fbcon_getxy(struct vc_data *conp, unsigned long pos, int *px, int *py)
+{
+    int x, y;
+    unsigned long ret;
+    if (pos >= conp->vc_origin && pos < conp->vc_scr_end) {
+    	unsigned long offset = (pos - conp->vc_origin) / 2;
+    	
+    	x = offset % conp->vc_cols;
+    	y = offset / conp->vc_cols;
+    	if (conp->vc_num == fg_console)
+    	    y += softback_lines;
+    	ret = pos + (conp->vc_cols - x) * 2;
+    } else if (conp->vc_num == fg_console && softback_lines) {
+    	unsigned long offset = (pos - softback_curr) / 2;
+    	
+    	x = offset % conp->vc_cols;
+    	y = offset / conp->vc_cols;
+    	if (pos < softback_curr)
+	    y += (softback_end - softback_buf) / conp->vc_size_row;
+	ret = pos + (conp->vc_cols - x) * 2;
+	if (ret == softback_end)
+	    ret = softback_buf;
+	if (ret == softback_in)
+	    ret = conp->vc_origin;
+    } else {
+    	/* Should not happen */
+    	x = y = 0;
+    	ret = conp->vc_origin;
+    }
+    if (px) *px = x;
+    if (py) *py = y;
+    return ret;
+}
+
+/* As we might be inside of softback, we may work with non-contiguous buffer,
+   that's why we have to use a separate routine. */
+static void fbcon_invert_region(struct vc_data *conp, u16 *p, int cnt)
+{
+    while (cnt--) {
+	if (!conp->vc_can_do_color)
+	    *p++ ^= 0x0800;
+	else if (conp->vc_hi_font_mask == 0x100) {
+	    u16 a = *p;
+	    a = ((a) & 0x11ff) | (((a) & 0xe000) >> 4) | (((a) & 0x0e00) << 4);
+	    *p++ = a;
+	} else {
+	    u16 a = *p;
+	    a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4);
+	    *p++ = a;
+	}
+	if (p == (u16 *)softback_end)
+	    p = (u16 *)softback_buf;
+	if (p == (u16 *)softback_in)
+	    p = (u16 *)conp->vc_origin;
+    }
+}
+
 static int fbcon_scrolldelta(struct vc_data *conp, int lines)
 {
     int unit, offset, limit, scrollback_old;
     struct display *p;
+    
+    unit = fg_console;
+    p = &fb_display[unit];
+    if (softback_top) {
+    	if (conp->vc_num != unit)
+    	    return 0;
+    	if (vt_cons[unit]->vc_mode != KD_TEXT || !lines)
+    	    return 0;
+    	if (logo_shown >= 0) {
+		struct vc_data *conp2 = vc_cons[logo_shown].d;
+    	
+		if (conp2->vc_top == logo_lines && conp2->vc_bottom == conp2->vc_rows)
+    		    conp2->vc_top = 0;
+    		if (logo_shown == unit) {
+    		    unsigned long p, q;
+    		    int i;
+    		    
+    		    p = softback_in;
+    		    q = conp->vc_origin + logo_lines * conp->vc_size_row;
+    		    for (i = 0; i < logo_lines; i++) {
+    		    	if (p == softback_top) break;
+    		    	if (p == softback_buf) p = softback_end;
+    		    	p -= conp->vc_size_row;
+    		    	q -= conp->vc_size_row;
+    		    	scr_memcpyw((u16 *)q, (u16 *)p, conp->vc_size_row);
+    		    }
+    		    softback_in = p;
+    		    update_region(unit, conp->vc_origin, logo_lines * conp->vc_cols);
+    		}
+		logo_shown = -1;
+	}
+    	fbcon_cursor(conp, CM_ERASE|CM_SOFTBACK);
+    	fbcon_redraw_softback(conp, p, lines);
+    	fbcon_cursor(conp, CM_DRAW|CM_SOFTBACK);
+    	return 0;
+    }
 
     if (!scrollback_phys_max)
 	return -ENOSYS;
@@ -1603,8 +1907,6 @@
     if (scrollback_current == scrollback_old)
 	return 0;
 
-    unit = fg_console;
-    p = &fb_display[unit];
     if (!p->can_soft_blank &&
 	(console_blanked || vt_cons[unit]->vc_mode != KD_TEXT || !lines))
 	return 0;
@@ -1633,6 +1935,13 @@
     return 0;
 }
 
+static int fbcon_set_origin(struct vc_data *conp)
+{
+    if (softback_lines && !console_blanked)
+        fbcon_scrolldelta(conp, softback_lines);
+    return 0;
+}
+
 static inline unsigned safe_shift(unsigned d,int n)
 {
     return n<0 ? d>>-n : d<<n;
@@ -1705,8 +2014,8 @@
 	logo_depth = 1;
     }
 
-    for (x = p->var.xres - LOGO_W; x > 0 && x > (int)p->var.xres 
-        - smp_num_cpus * (LOGO_W + 8); x -= (LOGO_W + 8)) {
+    for (x = 0; x < smp_num_cpus * (LOGO_W + 8) &&
+    	 x < p->var.xres - (LOGO_W + 8); x += (LOGO_W + 8)) {
     	 
 #if defined(CONFIG_FBCON_CFB16) || defined(CONFIG_FBCON_CFB24) || \
     defined(CONFIG_FBCON_CFB32) || defined(CONFIG_FB_SBUS)
@@ -1939,10 +2248,12 @@
     con_font_op:	fbcon_font_op,
     con_set_palette: 	fbcon_set_palette,
     con_scrolldelta: 	fbcon_scrolldelta,
-    con_set_origin: 	NULL,
+    con_set_origin: 	fbcon_set_origin,
     con_save_screen: 	NULL,
     con_build_attr:	NULL,
-    con_invert_region:	NULL,
+    con_invert_region:	fbcon_invert_region,
+    con_screen_pos:	fbcon_screen_pos,
+    con_getxy:		fbcon_getxy,
 };
 
 
diff -u --recursive --new-file v2.2.2/linux/drivers/video/fbgen.c linux/drivers/video/fbgen.c
--- v2.2.2/linux/drivers/video/fbgen.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/video/fbgen.c	Thu Feb 25 10:02:11 1999
@@ -244,7 +244,6 @@
     memset(&fix, 0, sizeof(struct fb_fix_screeninfo));
     fbhw->encode_fix(&fix, &par, info);
 
-    display->screen_base = phys_to_virt((unsigned long)fix.smem_start);
     display->visual = fix.visual;
     display->type = fix.type;
     display->type_aux = fix.type_aux;
@@ -256,7 +255,7 @@
 	display->can_soft_blank = 1;
     else
 	display->can_soft_blank = 0;
-    fbhw->set_dispsw(&par, display, info);
+    fbhw->set_disp(&par, display, info);
 #if 0 /* FIXME: generic inverse is not supported yet */
     display->inverse = (fix.visual == FB_VISUAL_MONO01 ? !inverse : inverse);
 #else
diff -u --recursive --new-file v2.2.2/linux/drivers/video/fbmem.c linux/drivers/video/fbmem.c
--- v2.2.2/linux/drivers/video/fbmem.c	Wed Jan 20 23:14:06 1999
+++ linux/drivers/video/fbmem.c	Sun Mar  7 10:38:51 1999
@@ -88,6 +88,9 @@
 extern void valkyriefb_init(void);
 extern void valkyriefb_setup(char *options, int *ints);
 extern void g364fb_init(void);
+extern void fm2fb_init(void);
+extern void fm2fb_setup(char *options, int *ints);
+extern void q40fb_init(void);
 
 static struct {
 	const char *name;
@@ -136,6 +139,9 @@
 #ifdef CONFIG_APOLLO
 	{ "apollo", dnfb_init, NULL },
 #endif
+#ifdef CONFIG_FB_Q40
+	{ "q40fb", q40fb_init, NULL },
+#endif
 #ifdef CONFIG_FB_S3TRIO
 	{ "s3trio", s3triofb_init, s3triofb_setup },
 #endif 
@@ -160,6 +166,9 @@
 #ifdef CONFIG_FB_G364
 	{ "g364", g364fb_init, NULL },
 #endif
+#ifdef CONFIG_FB_FM2
+	{ "fm2fb", fm2fb_init, fm2fb_setup },
+#endif 
 #ifdef CONFIG_GSP_RESOLVER
 	/* Not a real frame buffer device... */
 	{ "resolver", NULL, resolver_video_setup },
@@ -181,6 +190,7 @@
 
 struct fb_info *registered_fb[FB_MAX];
 int num_registered_fb = 0;
+int fbcon_softback_size = 32768;
 
 char con2fb_map[MAX_NR_CONSOLES];
 
@@ -485,8 +495,6 @@
 	if (remap_page_range(vma->vm_start, vma->vm_offset,
 			     vma->vm_end - vma->vm_start, vma->vm_page_prot))
 		return -EAGAIN;
-	vma->vm_file = file;
-	file->f_count++;
 	return 0;
 }
 
@@ -648,6 +656,21 @@
     if (!options || !*options)
 	    return;
 	    
+    if (!strncmp(options, "scrollback:", 11)) {
+	    options += 11;
+	    if (*options) {
+		fbcon_softback_size = simple_strtoul(options, &options, 0);
+		if (*options == 'k' || *options == 'K') {
+			fbcon_softback_size *= 1024;
+			options++;
+		}
+		if (*options != ',')
+			return;
+		options++;
+	    } else
+	        return;
+    }
+
     if (!strncmp(options, "map:", 4)) {
 	    options += 4;
 	    if (*options)
@@ -658,7 +681,7 @@
 		    }
 	    return;
     }
-
+    
     if (!strncmp(options, "vc:", 3)) {
 	    options += 3;
 	    if (*options)
diff -u --recursive --new-file v2.2.2/linux/drivers/video/fm2fb.c linux/drivers/video/fm2fb.c
--- v2.2.2/linux/drivers/video/fm2fb.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/fm2fb.c	Thu Feb 25 10:02:12 1999
@@ -0,0 +1,572 @@
+/*
+ *  linux/drivers/video/fm2fb.c -- BSC FrameMaster II/Rainbow II frame buffer
+ *				   device
+ *
+ *	Copyright (C) 1998 Steffen A. Mork (mork@ls7.cs.uni-dortmund.de)
+ *	Copyright (C) 1999 Geert Uytterhoeven
+ *
+ *  Written for 2.0.x by Steffen A. Mork
+ *  Ported to 2.1.x by Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/zorro.h>
+
+#include <asm/io.h>
+
+#include <video/fbcon.h>
+#include <video/fbcon-cfb32.h>
+
+
+/*
+ *	Some technical notes:
+ *
+ *	The BSC FrameMaster II (or Rainbow II) is a simple very dumb
+ *	frame buffer which allows to display 24 bit true color images.
+ *	Each pixel is 32 bit width so it's very easy to maintain the
+ *	frame buffer. One long word has the following layout:
+ *	AARRGGBB which means: AA the alpha channel byte, RR the red
+ *	channel, GG the green channel and BB the blue channel.
+ *
+ *	The FrameMaster II supports the following video modes.
+ *	- PAL/NTSC
+ *	- interlaced/non interlaced
+ *	- composite sync/sync/sync over green
+ *
+ *	The resolution is to the following both ones:
+ *	- 768x576 (PAL)
+ *	- 768x480 (NTSC)
+ *
+ *	This means that pixel access per line is fixed due to the
+ *	fixed line width. In case of maximal resolution the frame
+ *	buffer needs an amount of memory of 1.769.472 bytes which
+ *	is near to 2 MByte (the allocated address space of Zorro2).
+ *	The memory is channel interleaved. That means every channel
+ *	owns four VRAMs. Unfortunatly most FrameMasters II are
+ *	not assembled with memory for the alpha channel. In this
+ *	case it could be possible to add the frame buffer into the
+ *	normal memory pool.
+ *	
+ *	At relative address 0x1ffff8 of the frame buffers base address
+ *	there exists a control register with the number of
+ *	four control bits. They have the following meaning:
+ *	bit value meaning
+ *
+ *	 0    1   0=interlaced/1=non interlaced
+ *	 1    2   0=video out disabled/1=video out enabled
+ *	 2    4   0=normal mode as jumpered via JP8/1=complement mode
+ *	 3    8   0=read  onboard ROM/1 normal operation (required)
+ *
+ *	As mentioned above there are several jumper. I think there
+ *	is not very much information about the FrameMaster II in
+ *	the world so I add these information for completeness.
+ *
+ *	JP1  interlace selection (1-2 non interlaced/2-3 interlaced) 
+ *	JP2  wait state creation (leave as is!)
+ *	JP3  wait state creation (leave as is!)
+ *	JP4  modulate composite sync on green output (1-2 composite
+ *	     sync on green channel/2-3 normal composite sync)
+ *	JP5  create test signal, shorting this jumper will create
+ *	     a white screen
+ *	JP6  sync creation (1-2 composite sync/2-3 H-sync output)
+ *	JP8  video mode (1-2 PAL/2-3 NTSC)
+ *
+ *	With the following jumpering table you can connect the
+ *	FrameMaster II to a normal TV via SCART connector:
+ *	JP1:  2-3
+ *	JP4:  2-3
+ *	JP6:  2-3
+ *	JP8:  1-2 (means PAL for Europe)
+ *
+ *	NOTE:
+ *	There is no other possibility to change the video timings
+ *	except the interlaced/non interlaced, sync control and the
+ *	video mode PAL (50 Hz)/NTSC (60 Hz). Inside this
+ *	FrameMaster II driver are assumed values to avoid anomalies
+ *	to a future X server. Except the pixel clock is really
+ *	constant at 30 MHz.
+ *
+ *	9 pin female video connector:
+ *
+ *	1  analog red 0.7 Vss
+ *	2  analog green 0.7 Vss
+ *	3  analog blue 0.7 Vss
+ *	4  H-sync TTL
+ *	5  V-sync TTL
+ *	6  ground
+ *	7  ground
+ *	8  ground
+ *	9  ground
+ *
+ *	Some performance notes:
+ *	The FrameMaster II was not designed to display a console
+ *	this driver would do! It was designed to display still true
+ *	color images. Imagine: When scroll up a text line there
+ *	must copied ca. 1.7 MBytes to another place inside this
+ *	frame buffer. This means 1.7 MByte read and 1.7 MByte write
+ *	over the slow 16 bit wide Zorro2 bus! A scroll of one
+ *	line needs 1 second so do not expect to much from this
+ *	driver - he is at the limit!
+ *
+ */
+
+
+/*
+ *	definitions
+ */
+
+#define FRAMEMASTER_SIZE	0x200000
+#define FRAMEMASTER_REG		0x1ffff8
+
+#define FRAMEMASTER_NOLACE	1
+#define FRAMEMASTER_ENABLE	2
+#define FRAMEMASTER_COMPL	4
+#define FRAMEMASTER_ROM		8
+
+
+struct FrameMaster_fb_par
+{
+	int xres;
+	int yres;
+	int bpp;
+	int pixclock;
+};
+
+static unsigned long fm2fb_mem_phys;
+static void *fm2fb_mem;
+static unsigned long fm2fb_reg_phys;
+static volatile unsigned char *fm2fb_reg;
+
+#define arraysize(x)	(sizeof(x)/sizeof(*(x)))
+
+static int currcon = 0;
+static struct display disp;
+static struct fb_info fb_info;
+static struct { u_char red, green, blue, pad; } palette[16];
+#ifdef FBCON_HAS_CFB32
+static u32 fbcon_cfb32_cmap[16];
+#endif
+
+static struct fb_fix_screeninfo fb_fix;
+static struct fb_var_screeninfo fb_var;
+
+static int fm2fb_mode __initdata = -1;
+
+#define FM2FB_MODE_PAL	0
+#define FM2FB_MODE_NTSC	1
+
+static struct fb_var_screeninfo fb_var_modes[] __initdata = {
+    {
+	/* 768 x 576, 32 bpp (PAL) */
+	768, 576, 768, 576, 0, 0, 32, 0,
+	{ 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 8, 0 },
+	0, FB_ACTIVATE_NOW, -1, -1, FB_ACCEL_NONE,
+	33333, 10, 102, 10, 5, 80, 34, FB_SYNC_COMP_HIGH_ACT, 0
+    }, {
+	/* 768 x 480, 32 bpp (NTSC - not supported yet */
+	768, 480, 768, 480, 0, 0, 32, 0,
+	{ 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 8, 0 },
+	0, FB_ACTIVATE_NOW, -1, -1, FB_ACCEL_NONE,
+	33333, 10, 102, 10, 5, 80, 34, FB_SYNC_COMP_HIGH_ACT, 0
+    }
+};
+
+
+    /*
+     *  Interface used by the world
+     */
+
+static int fm2fb_open(struct fb_info *info, int user);
+static int fm2fb_release(struct fb_info *info, int user);
+static int fm2fb_get_fix(struct fb_fix_screeninfo *fix, int con,
+			 struct fb_info *info);
+static int fm2fb_get_var(struct fb_var_screeninfo *var, int con,
+			 struct fb_info *info);
+static int fm2fb_set_var(struct fb_var_screeninfo *var, int con,
+			 struct fb_info *info);
+static int fm2fb_pan_display(struct fb_var_screeninfo *var, int con,
+			     struct fb_info *info);
+static int fm2fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+			  struct fb_info *info);
+static int fm2fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+			  struct fb_info *info);
+static int fm2fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
+		       u_long arg, int con, struct fb_info *info);
+
+
+    /*
+     *  Interface to the low level console driver
+     */
+
+void fm2fb_init(void);
+static int fm2fbcon_switch(int con, struct fb_info *info);
+static int fm2fbcon_updatevar(int con, struct fb_info *info);
+static void fm2fbcon_blank(int blank, struct fb_info *info);
+
+
+    /*
+     *  Internal routines
+     */
+
+static int fm2fb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+			   u_int *transp, struct fb_info *info);
+static int fm2fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			   u_int transp, struct fb_info *info);
+static void do_install_cmap(int con, struct fb_info *info);
+
+
+static struct fb_ops fm2fb_ops = {
+    fm2fb_open, fm2fb_release, fm2fb_get_fix, fm2fb_get_var, fm2fb_set_var,
+    fm2fb_get_cmap, fm2fb_set_cmap, fm2fb_pan_display, fm2fb_ioctl
+};
+
+
+    /*
+     *  Open/Release the frame buffer device
+     */
+
+static int fm2fb_open(struct fb_info *info, int user)
+{
+    /*                                                                     
+     *  Nothing, only a usage count for the moment                          
+     */                                                                    
+
+    MOD_INC_USE_COUNT;
+    return(0);                              
+}
+        
+static int fm2fb_release(struct fb_info *info, int user)
+{
+    MOD_DEC_USE_COUNT;
+    return(0);                                                    
+}
+
+
+    /*
+     *  Get the Fixed Part of the Display
+     */
+
+static int fm2fb_get_fix(struct fb_fix_screeninfo *fix, int con,
+			 struct fb_info *info)
+{
+    memcpy(fix, &fb_fix, sizeof(fb_fix));
+    return 0;
+}
+
+
+    /*
+     *  Get the User Defined Part of the Display
+     */
+
+static int fm2fb_get_var(struct fb_var_screeninfo *var, int con,
+			 struct fb_info *info)
+{
+    memcpy(var, &fb_var, sizeof(fb_var));
+    return 0;
+}
+
+
+    /*
+     *  Set the User Defined Part of the Display
+     */
+
+static int fm2fb_set_var(struct fb_var_screeninfo *var, int con,
+			 struct fb_info *info)
+{
+    struct display *display;
+    int oldbpp = -1, err;
+
+    if (con >= 0)
+	display = &fb_display[con];
+    else
+	display = &disp;	/* used during initialization */
+
+    if (var->xres > fb_var.xres || var->yres > fb_var.yres ||
+	var->xres_virtual > fb_var.xres_virtual ||
+	var->yres_virtual > fb_var.yres_virtual ||
+	var->bits_per_pixel > fb_var.bits_per_pixel ||
+	var->nonstd ||
+	(var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+	return -EINVAL;
+    memcpy(var, &fb_var, sizeof(fb_var));
+
+    if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
+	oldbpp = display->var.bits_per_pixel;
+	display->var = *var;
+    }
+    if (oldbpp != var->bits_per_pixel) {
+	if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
+	    return err;
+	do_install_cmap(con, info);
+    }
+    return 0;
+}
+
+
+    /*
+     *  Pan or Wrap the Display
+     *
+     *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+     */
+
+static int fm2fb_pan_display(struct fb_var_screeninfo *var, int con,
+			     struct fb_info *info)
+{
+    if (var->xoffset || var->yoffset)
+	return -EINVAL;
+    else
+	return 0;
+}
+
+    /*
+     *  Get the Colormap
+     */
+
+static int fm2fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+			  struct fb_info *info)
+{
+    if (con == currcon) /* current console? */
+	return fb_get_cmap(cmap, kspc, fm2fb_getcolreg, info);
+    else if (fb_display[con].cmap.len) /* non default colormap? */
+	fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
+    else
+	fb_copy_cmap(fb_default_cmap(256), cmap, kspc ? 0 : 2);
+    return 0;
+}
+
+    /*
+     *  Set the Colormap
+     */
+
+static int fm2fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+			  struct fb_info *info)
+{
+    int err;
+
+    if (!fb_display[con].cmap.len) {	/* no colormap allocated? */
+	if ((err = fb_alloc_cmap(&fb_display[con].cmap, 256, 0)))
+	    return err;
+    }
+    if (con == currcon) {		/* current console? */
+	err = fb_set_cmap(cmap, kspc, fm2fb_setcolreg, info);
+	return err;
+    } else
+	fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+    return 0;
+}
+
+
+static int fm2fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
+		       u_long arg, int con, struct fb_info *info)
+{
+    return -EINVAL;
+}
+
+
+    /*
+     *  Initialisation
+     */
+
+__initfunc(void fm2fb_init(void))
+{
+    int key, is_fm;
+    const struct ConfigDev *cd  = NULL;
+    unsigned long board, *ptr;
+    int x, y;
+
+    if (!(key = is_fm = zorro_find(ZORRO_PROD_BSC_FRAMEMASTER_II, 0, 0)) &&
+	!(key = zorro_find(ZORRO_PROD_HELFRICH_RAINBOW_II, 0, 0)))
+	return;
+    cd = zorro_get_board(key);
+    if (!(board = (u_long)cd->cd_BoardAddr))
+	return;
+    zorro_config_board(key, 0);
+
+    /* assigning memory to kernel space */
+    fm2fb_mem_phys = board;
+    fm2fb_mem  = ioremap(board, FRAMEMASTER_SIZE);
+    fm2fb_reg_phys = fm2fb_mem_phys+FRAMEMASTER_REG;
+    fm2fb_reg  = (unsigned char *)(fm2fb_mem+FRAMEMASTER_REG);
+
+    /* make EBU color bars on display */
+    ptr = (unsigned long *)fm2fb_mem;
+    for (y = 0; y < 576; y++) {
+	for (x = 0; x < 96; x++) *ptr++ = 0xffffff;	/* white */
+	for (x = 0; x < 96; x++) *ptr++ = 0xffff00;	/* yellow */
+	for (x = 0; x < 96; x++) *ptr++ = 0x00ffff;	/* cyan */
+	for (x = 0; x < 96; x++) *ptr++ = 0x00ff00;	/* green */
+	for (x = 0; x < 96; x++) *ptr++ = 0xff00ff;	/* magenta */
+	for (x = 0; x < 96; x++) *ptr++ = 0xff0000;	/* red */
+	for (x = 0; x < 96; x++) *ptr++ = 0x0000ff;	/* blue */
+	for (x = 0; x < 96; x++) *ptr++ = 0x000000;	/* black */
+    }
+    fm2fbcon_blank(0, NULL);
+
+    if (fm2fb_mode == -1)
+	fm2fb_mode = FM2FB_MODE_PAL;
+
+    fb_var = fb_var_modes[fm2fb_mode];
+
+    strcpy(fb_fix.id, is_fm ? "FrameMaster II" : "Rainbow II");
+    fb_fix.smem_start = (char *)fm2fb_mem_phys;
+    fb_fix.smem_len = FRAMEMASTER_REG;
+    fb_fix.type = FB_TYPE_PACKED_PIXELS;
+    fb_fix.type_aux = 0;
+    fb_fix.visual = FB_VISUAL_TRUECOLOR;
+    fb_fix.line_length = 768<<2;
+    fb_fix.mmio_start = (char *)fm2fb_reg_phys;
+    fb_fix.mmio_len = 8;
+    fb_fix.accel = FB_ACCEL_NONE;
+
+    disp.var = fb_var;
+    disp.cmap.start = 0;
+    disp.cmap.len = 0;
+    disp.cmap.red = disp.cmap.green = disp.cmap.blue = disp.cmap.transp = NULL;
+    disp.screen_base = (char *)fm2fb_mem;
+    disp.visual = fb_fix.visual;
+    disp.type = fb_fix.type;
+    disp.type_aux = fb_fix.type_aux;
+    disp.ypanstep = 0;
+    disp.ywrapstep = 0;
+    disp.line_length = fb_fix.line_length;
+    disp.can_soft_blank = 1;
+    disp.inverse = 0;
+#ifdef FBCON_HAS_CFB32
+    disp.dispsw = &fbcon_cfb32;
+    disp.dispsw_data = &fbcon_cfb32_cmap;
+#else
+    disp.dispsw = &fbcon_dummy;
+#endif
+    disp.scrollmode = SCROLL_YREDRAW;
+
+    strcpy(fb_info.modename, fb_fix.id);
+    fb_info.node = -1;
+    fb_info.fbops = &fm2fb_ops;
+    fb_info.disp = &disp;
+    fb_info.fontname[0] = '\0';
+    fb_info.changevar = NULL;
+    fb_info.switch_con = &fm2fbcon_switch;
+    fb_info.updatevar = &fm2fbcon_updatevar;
+    fb_info.blank = &fm2fbcon_blank;
+    fb_info.flags = FBINFO_FLAG_DEFAULT;
+
+    fm2fb_set_var(&fb_var, -1, &fb_info);
+
+    if (register_framebuffer(&fb_info) < 0)
+	return;
+
+    printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.node),
+	   fb_fix.id);
+}
+
+__initfunc(void fm2fb_setup(char *options, int *ints))
+{
+    char *this_opt;
+
+    if (!options || !*options)
+	return;
+
+    for (this_opt = strtok(options, ","); this_opt;
+	 this_opt = strtok(NULL, ",")) {
+	if (!strncmp(this_opt, "pal", 3))
+	    fm2fb_mode = FM2FB_MODE_PAL;
+	else if (!strncmp(this_opt, "ntsc", 4))
+	    fm2fb_mode = FM2FB_MODE_NTSC;
+    }
+}
+
+
+static int fm2fbcon_switch(int con, struct fb_info *info)
+{
+    /* Do we have to save the colormap? */
+    if (fb_display[currcon].cmap.len)
+	fb_get_cmap(&fb_display[currcon].cmap, 1, fm2fb_getcolreg, info);
+
+    currcon = con;
+    /* Install new colormap */
+    do_install_cmap(con, info);
+    return 0;
+}
+
+    /*
+     *  Update the `var' structure (called by fbcon.c)
+     */
+
+static int fm2fbcon_updatevar(int con, struct fb_info *info)
+{
+    /* Nothing */
+    return 0;
+}
+
+    /*
+     *  Blank the display.
+     */
+
+static void fm2fbcon_blank(int blank, struct fb_info *info)
+{
+    unsigned char t = FRAMEMASTER_ROM;
+
+    if (!blank)
+	t |= FRAMEMASTER_ENABLE | FRAMEMASTER_NOLACE;
+    fm2fb_reg[0] = t;
+}
+
+    /*
+     *  Read a single color register and split it into
+     *  colors/transparent. Return != 0 for invalid regno.
+     */
+
+static int fm2fb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+                         u_int *transp, struct fb_info *info)
+{
+    if (regno > 15)
+	return 1;
+    *red = (palette[regno].red<<8) | palette[regno].red;
+    *green = (palette[regno].green<<8) | palette[regno].green;
+    *blue = (palette[regno].blue<<8) | palette[regno].blue;
+    *transp = 0;
+    return 0;
+}
+
+
+    /*
+     *  Set a single color register. The values supplied are already
+     *  rounded down to the hardware's capabilities (according to the
+     *  entries in the var structure). Return != 0 for invalid regno.
+     */
+
+static int fm2fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+                         u_int transp, struct fb_info *info)
+{
+    if (regno > 15)
+	return 1;
+    red >>= 8;
+    green >>= 8;
+    blue >>= 8;
+    palette[regno].red = red;
+    palette[regno].green = green;
+    palette[regno].blue = blue;
+
+#ifdef FBCON_HAS_CFB32
+    fbcon_cfb32_cmap[regno] = (red << 16) | (green << 8) | blue;
+#endif
+    return 0;
+}
+
+
+static void do_install_cmap(int con, struct fb_info *info)
+{
+    if (con != currcon)
+	return;
+    if (fb_display[con].cmap.len)
+	fb_set_cmap(&fb_display[con].cmap, 1, fm2fb_setcolreg, info);
+    else
+	fb_set_cmap(fb_default_cmap(256), 1, fm2fb_setcolreg, info);
+}
diff -u --recursive --new-file v2.2.2/linux/drivers/video/igafb.c linux/drivers/video/igafb.c
--- v2.2.2/linux/drivers/video/igafb.c	Fri Oct 23 22:01:22 1998
+++ linux/drivers/video/igafb.c	Sun Mar  7 10:39:03 1999
@@ -304,8 +304,6 @@
 	if (!map_size)
 		return -EINVAL;
 
-	vma->vm_file = file;
-	file->f_count++;
 	vma->vm_flags |= VM_IO;
 
 	if (!fb->mmaped) {
diff -u --recursive --new-file v2.2.2/linux/drivers/video/leofb.c linux/drivers/video/leofb.c
--- v2.2.2/linux/drivers/video/leofb.c	Mon Oct  5 13:13:42 1998
+++ linux/drivers/video/leofb.c	Thu Feb 25 10:02:12 1999
@@ -265,8 +265,8 @@
 	do {
 		i = us->csr;
 	} while (i & 0x20000000);
-	ss->fg = attr_fgcol(p,*s) << 24;
-	ss->bg = attr_bgcol(p,*s) << 24;
+	ss->fg = attr_fgcol(p,scr_readw(s)) << 24;
+	ss->bg = attr_bgcol(p,scr_readw(s)) << 24;
 	ss->rop = 0x310040;
 	ss->planemask = 0xff000000;
 	us->fontc2 = 0xFFFFFFFE;
@@ -287,15 +287,15 @@
 		while (count >= 4) {
 			count -= 4;
 			if (fontheightlog(p)) {
-				fd1 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
-				fd2 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
-				fd3 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
-				fd4 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
+				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
+				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
+				fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
+				fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
 			} else {
-				fd1 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
-				fd2 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
-				fd3 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
-				fd4 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
+				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
+				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
+				fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
+				fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
 			}
 			if (fontwidth(p) == 8) {
 				for (i = 0; i < fontheight(p); i++, u += 2048)
@@ -315,11 +315,11 @@
 		while (count >= 2) {
 			count -= 2;
 			if (fontheightlog(p)) {
-				fd1 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
-				fd2 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
+				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
+				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
 			} else {
-				fd1 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
-				fd2 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
+				fd1 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
+				fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
 			}
 			for (i = 0; i < fontheight(p); i++, u += 2048) {
 				*u = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
@@ -333,9 +333,9 @@
 	while (count) {
 		count--;
 		if (fontheightlog(p))
-			i = ((*s++ & p->charmask) << fontheightlog(p));
+			i = ((scr_readw(s++) & p->charmask) << fontheightlog(p));
 		else
-			i = ((*s++ & p->charmask) * fontheight(p));
+			i = ((scr_readw(s++) & p->charmask) * fontheight(p));
 		if (fontwidth(p) <= 8) {
 			fd1 = p->fontdata + i;
 			for (i = 0; i < fontheight(p); i++, u += 2048)
diff -u --recursive --new-file v2.2.2/linux/drivers/video/matroxfb.c linux/drivers/video/matroxfb.c
--- v2.2.2/linux/drivers/video/matroxfb.c	Tue Jan 19 11:32:52 1999
+++ linux/drivers/video/matroxfb.c	Thu Feb 25 10:02:12 1999
@@ -1473,7 +1473,7 @@
 	mga_outl(M_FCOL, fgx);
 	mga_outl(M_BCOL, bgx);
 	while (count--) {
-		u_int32_t ar3 = ACCESS_FBINFO(fastfont.mgabase) + (*s++ & p->charmask)*charcell;
+		u_int32_t ar3 = ACCESS_FBINFO(fastfont.mgabase) + (scr_readw(s++) & p->charmask)*charcell;
 
 		mga_fifo(4);
 		mga_outl(M_FXBNDRY, ((xx + fontwidth(p) - 1) << 16) | xx);
@@ -1531,7 +1531,7 @@
 	fxbndry = ((xx + fontwidth(p) - 1) << 16) | xx;
 	mmio = ACCESS_FBINFO(mmio.vbase);
 	while (count--) {
-		u_int8_t* chardata = p->fontdata + (*s++ & p->charmask)*charcell;
+		u_int8_t* chardata = p->fontdata + (scr_readw(s++) & p->charmask)*charcell;
 
 		mga_fifo(5);
 		mga_writel(mmio, M_FXBNDRY, fxbndry);
@@ -1586,8 +1586,8 @@
 
 	DBG_HEAVY("matroxfb_cfb8_putcs");
 
-	fgx = attr_fgcol(p, *s);
-	bgx = attr_bgcol(p, *s);
+	fgx = attr_fgcol(p, scr_readw(s));
+	bgx = attr_bgcol(p, scr_readw(s));
 	fgx |= (fgx << 8);
 	fgx |= (fgx << 16);
 	bgx |= (bgx << 8);
@@ -1603,8 +1603,8 @@
 
 	DBG_HEAVY("matroxfb_cfb16_putcs");
 
-	fgx = ((u_int16_t*)p->dispsw_data)[attr_fgcol(p, *s)];
-	bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol(p, *s)];
+	fgx = ((u_int16_t*)p->dispsw_data)[attr_fgcol(p, scr_readw(s))];
+	bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol(p, scr_readw(s))];
 	fgx |= (fgx << 16);
 	bgx |= (bgx << 16);
 	ACCESS_FBINFO(curr.putcs)(fgx, bgx, p, s, count, yy, xx);
@@ -1618,8 +1618,8 @@
 
 	DBG_HEAVY("matroxfb_cfb32_putcs");
 
-	fgx = ((u_int32_t*)p->dispsw_data)[attr_fgcol(p, *s)];
-	bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol(p, *s)];
+	fgx = ((u_int32_t*)p->dispsw_data)[attr_fgcol(p, scr_readw(s))];
+	bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol(p, scr_readw(s))];
 	ACCESS_FBINFO(curr.putcs)(fgx, bgx, p, s, count, yy, xx);
 }
 #endif
@@ -2191,9 +2191,9 @@
 
 	step = ACCESS_FBINFO(devflags.textstep);
 	offs = yy * p->next_line + xx * step;
-	attr = attr_fgcol(p,*s) | (attr_bgcol(p,*s) << 4);
+	attr = attr_fgcol(p,scr_readw(s)) | (attr_bgcol(p,scr_readw(s)) << 4);
 	while (count-- > 0) {
-		unsigned int chr = ((*s++) & p->charmask) << 8;
+		unsigned int chr = ((scr_readw(s++)) & p->charmask) << 8;
 		if (chr & 0x10000) chr ^= 0x10008;
 		mga_writew(ACCESS_FBINFO(video.vbase), offs, ntohs(attr|chr));
 		offs += step;
diff -u --recursive --new-file v2.2.2/linux/drivers/video/mdacon.c linux/drivers/video/mdacon.c
--- v2.2.2/linux/drivers/video/mdacon.c	Wed Jan 13 15:00:43 1999
+++ linux/drivers/video/mdacon.c	Thu Feb 25 10:02:12 1999
@@ -429,7 +429,7 @@
 	u16 *dest = MDA_ADDR(x, y);
 
 	for (; count > 0; count--) {
-		scr_writew(mda_convert_attr(*s++), dest++);
+		scr_writew(mda_convert_attr(scr_readw(s++)), dest++);
 	}
 }
 
diff -u --recursive --new-file v2.2.2/linux/drivers/video/newport_con.c linux/drivers/video/newport_con.c
--- v2.2.2/linux/drivers/video/newport_con.c	Mon Oct  5 13:13:42 1998
+++ linux/drivers/video/newport_con.c	Thu Feb 25 10:02:12 1999
@@ -200,7 +200,7 @@
 			  int ypos, int xpos)
 {
     while (count--)
-	newport_putc (vc, *s++, ypos, xpos++);
+	newport_putc (vc, scr_readw(s++), ypos, xpos++);
 }
 
 static void newport_cursor(struct vc_data *vc, int mode)
diff -u --recursive --new-file v2.2.2/linux/drivers/video/pm2fb.c linux/drivers/video/pm2fb.c
--- v2.2.2/linux/drivers/video/pm2fb.c	Wed Jan 20 23:14:06 1999
+++ linux/drivers/video/pm2fb.c	Thu Feb 25 10:02:12 1999
@@ -3,7 +3,9 @@
  * Copyright (c) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
  * Based on linux/drivers/video/skeletonfb.c by Geert Uytterhoeven.
  * --------------------------------------------------------------------------
- * $Id: pm2fb.c,v 1.1.2.1 1999/01/12 19:53:02 geert Exp $
+ * $Id: pm2fb.c,v 1.163 1999/02/21 14:06:49 illo Exp $
+ * --------------------------------------------------------------------------
+ * TODO multiple boards support
  * --------------------------------------------------------------------------
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file README.legal in the main directory of this archive
@@ -26,23 +28,27 @@
 #include <linux/console.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
 #include <video/fbcon.h>
 #include <video/fbcon-cfb8.h>
 #include <video/fbcon-cfb16.h>
 #include <video/fbcon-cfb24.h>
 #include <video/fbcon-cfb32.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
 #include "pm2fb.h"
-#ifdef CONFIG_FB_PM2_CVPPC
 #include "cvisionppc.h"
-#endif
 
 #if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
 #error	"The endianness of the target host has not been defined."
 #endif
 
-#undef PM2FB_MASTER_DEBUG
+#if defined(CONFIG_FB_PM2_PCI) && !defined(CONFIG_PCI)
+#undef CONFIG_FB_PM2_PCI
+#warning "support for Permedia2 PCI boards with no generic PCI support!"
+#endif
+
+#define PM2FB_MASTER_DEBUG
 #ifdef PM2FB_MASTER_DEBUG
 #define DPRINTK(a,b...)	printk("pm2fb: %s: " a, __FUNCTION__ , ## b)
 #else
@@ -52,12 +58,20 @@
 #define PICOS2KHZ(a) (1000000000UL/(a))
 #define KHZ2PICOS(a) (1000000000UL/(a))
 
-#ifdef CONFIG_APUS
-#define MMAP(a,b)	(unsigned char* )kernel_map((unsigned long )(a), \
-					b, KERNELMAP_NOCACHE_SER, NULL)
-#else
-#define MMAP(a,b)	ioremap(a, b)
-#endif
+/*
+ * The _DEFINITIVE_ memory mapping/unmapping functions.
+ * This is due to the fact that they're changing soooo often...
+ */
+#define MMAP(a,b)	ioremap((u32 )(a), b)
+#define UNMAP(a,b)	iounmap(a)
+
+/*
+ * The _DEFINITIVE_ memory i/o barrier functions.
+ * This is due to the fact that they're changing soooo often...
+ */
+#define DEFW()		wmb()
+#define DEFR()		rmb()
+#define DEFRW()		mb()
 
 #ifndef MIN
 #define MIN(a,b) ((a)<(b)?(a):(b))
@@ -67,35 +81,33 @@
 #define MAX(a,b) ((a)>(b)?(a):(b))
 #endif
 
-#ifndef __powerpc__
-#define eieio()
-#endif
-
 struct pm2fb_par {
-	unsigned long pixclock;		/* pixclock in KHz */
-	unsigned long width;		/* width of virtual screen */
-	unsigned long height;		/* height of virtual screen */
-	unsigned long hsstart;		/* horiz. sync start */
-	unsigned long hsend;		/* horiz. sync end */
-	unsigned long hbend;		/* horiz. blank end (also gate end) */
-	unsigned long htotal;		/* total width (w/ sync & blank) */
-	unsigned long vsstart;		/* vert. sync start */
-	unsigned long vsend;		/* vert. sync end */
-	unsigned long vbend;		/* vert. blank end */
-	unsigned long vtotal;		/* total height (w/ sync & blank) */
-	unsigned long stride;		/* screen stride */
-	unsigned long base;		/* screen base (xoffset+yoffset) */
-	unsigned long depth;		/* screen depth (8, 16, 24 or 32) */
-	unsigned long video;		/* video control (hsync,vsync) */
+	u32 pixclock;		/* pixclock in KHz */
+	u32 width;		/* width of virtual screen */
+	u32 height;		/* height of virtual screen */
+	u32 hsstart;		/* horiz. sync start */
+	u32 hsend;		/* horiz. sync end */
+	u32 hbend;		/* horiz. blank end (also gate end) */
+	u32 htotal;		/* total width (w/ sync & blank) */
+	u32 vsstart;		/* vert. sync start */
+	u32 vsend;		/* vert. sync end */
+	u32 vbend;		/* vert. blank end */
+	u32 vtotal;		/* total height (w/ sync & blank) */
+	u32 stride;		/* screen stride */
+	u32 base;		/* screen base (xoffset+yoffset) */
+	u32 depth;		/* screen depth (8, 16, 24 or 32) */
+	u32 video;		/* video control (hsync,vsync) */
 };
 
-#define OPTF_OLD_MEM		0x00000001
-#define OPTF_YPAN		0x00000002
+#define OPTF_OLD_MEM		(1L<<0)
+#define OPTF_YPAN		(1L<<1)
+#define OPTF_VIRTUAL		(1L<<2)
 static struct {
 	char font[40];
-	unsigned long flags;
+	u32 flags;
 	struct pm2fb_par user_mode;
-} pm2fb_options;
+} pm2fb_options =
+	{"\0", 0L, {25174,640,480,4,28,40,199,9,11,45,524,80,0,8,121}};
 
 static const struct {
 	char name[16];
@@ -164,6 +176,15 @@
 	{"\0", },
 };
 
+#ifdef CONFIG_FB_PM2_PCI
+struct pm2pci_par {
+	u32 mem_config;
+	u32 mem_control;
+	u32 boot_address;
+	struct pci_dev* dev;
+};
+#endif
+
 static const char permedia2_name[16]="Permedia2";
 
 static struct pm2fb_info {
@@ -172,7 +193,7 @@
 					   board_table[] below) */
 	struct {
 		unsigned char* fb_base;	/* framebuffer memory base */
-		unsigned long  fb_size;	/* framebuffer memory size */
+		u32 fb_size;		/* framebuffer memory size */
 		unsigned char* rg_base;	/* register memory base */
 		unsigned char* p_fb;	/* physical address of frame buffer */
 		unsigned char* v_fb;	/* virtual address of frame buffer */
@@ -186,10 +207,13 @@
 #ifdef CONFIG_FB_PM2_CVPPC
 		struct cvppc_par cvppc;	/* CVisionPPC data */
 #endif
+#ifdef CONFIG_FB_PM2_PCI
+		struct pm2pci_par pci;	/* Permedia2 PCI boards data */
+#endif
 	} board_par;
 	struct pm2fb_par current_par;	/* displayed screen */
 	int current_par_valid;
-	unsigned long memclock;		/* memclock (set by the per-board
+	u32 memclock;			/* memclock (set by the per-board
 					   		init routine) */
 	struct display disp;
 	struct {
@@ -216,6 +240,11 @@
 static void cvppc_init(struct pm2fb_info*);
 #endif
 
+#ifdef CONFIG_FB_PM2_PCI
+static int pm2pci_detect(struct pm2fb_info*);
+static void pm2pci_init(struct pm2fb_info*);
+#endif
+
 /*
  * Table of the supported Permedia2 based boards.
  * Three hooks are defined for each board:
@@ -236,6 +265,9 @@
 	void (*cleanup)(struct pm2fb_info*);
 	char name[32];
 } board_table[] = {
+#ifdef CONFIG_FB_PM2_PCI
+	{ pm2pci_detect, pm2pci_init, NULL, "Permedia2 PCI board" },
+#endif
 #ifdef CONFIG_FB_PM2_CVPPC
 	{ cvppc_detect, cvppc_init, NULL, "CVisionPPC/BVisionPPC" },
 #endif
@@ -247,8 +279,8 @@
  */
 #define PACKPP(p0,p1,p2)	(((p2)<<6)|((p1)<<3)|(p0))
 static const struct {
-	unsigned short width;
-	unsigned short pp;
+	u16 width;
+	u16 pp;
 } pp_table[] = {
 	{ 32,	PACKPP(1, 0, 0) }, { 64,	PACKPP(1, 1, 0) },
 	{ 96,	PACKPP(1, 1, 1) }, { 128,	PACKPP(2, 1, 1) },
@@ -286,14 +318,14 @@
 static int pm2fb_blank(int blank_mode, struct fb_info_gen* info);
 static int pm2fb_pan_display(const struct fb_var_screeninfo* var,
 					struct fb_info_gen* info);
-static void pm2fb_dispsw(const void* par, struct display* disp,
+static void pm2fb_set_disp(const void* par, struct display* disp,
 						struct fb_info_gen* info);
 
 static struct fbgen_hwswitch pm2fb_hwswitch={
 	pm2fb_detect, pm2fb_encode_fix, pm2fb_decode_var,
 	pm2fb_encode_var, pm2fb_get_par, pm2fb_set_par,
 	pm2fb_getcolreg, pm2fb_setcolreg, pm2fb_pan_display,
-	pm2fb_blank, pm2fb_dispsw
+	pm2fb_blank, pm2fb_set_disp
 };
 
 static int pm2fb_open(struct fb_info* info, int user);
@@ -309,61 +341,61 @@
  * Begin of Permedia2 specific functions
  ***************************************************************************/
 
-inline static unsigned long RD32(unsigned char* base, long off) {
+inline static u32 RD32(unsigned char* base, s32 off) {
 
-	return *((volatile unsigned long* )(base+off));
+	return readl(base+off);
 }
 
-inline static void WR32(unsigned char* base, long off, unsigned long v) {
+inline static void WR32(unsigned char* base, s32 off, u32 v) {
 
-	*((volatile unsigned long* )(base+off))=v;
+	writel(v, base+off);
 }
 
-inline static unsigned long pm2_RD(struct pm2fb_info* p, long off) {
+inline static u32 pm2_RD(struct pm2fb_info* p, s32 off) {
 
 	return RD32(p->regions.v_regs, off);
 }
 
-inline static void pm2_WR(struct pm2fb_info* p, long off, unsigned long v) {
+inline static void pm2_WR(struct pm2fb_info* p, s32 off, u32 v) {
 
 	WR32(p->regions.v_regs, off, v);
 }
 
-inline static unsigned long pm2_RDAC_RD(struct pm2fb_info* p, long idx) {
+inline static u32 pm2_RDAC_RD(struct pm2fb_info* p, s32 idx) {
 
 	pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx);
-	eieio();
+	DEFRW();
 	return pm2_RD(p, PM2R_RD_INDEXED_DATA);
 }
 
-inline static void pm2_RDAC_WR(struct pm2fb_info* p, long idx,
-						unsigned long v) {
+inline static void pm2_RDAC_WR(struct pm2fb_info* p, s32 idx,
+						u32 v) {
 
 	pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx);
-	eieio();
+	DEFW();
 	pm2_WR(p, PM2R_RD_INDEXED_DATA, v);
 }
 
 #ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
 #define WAIT_FIFO(p,a)
 #else
-inline static void WAIT_FIFO(struct pm2fb_info* p, unsigned long a) {
+inline static void WAIT_FIFO(struct pm2fb_info* p, u32 a) {
 
 	while(pm2_RD(p, PM2R_IN_FIFO_SPACE)<a);
-	eieio();
+	DEFRW();
 }
 #endif
 
-static unsigned long partprod(unsigned long xres) {
+static u32 partprod(u32 xres) {
 	int i;
 
 	for (i=0; pp_table[i].width && pp_table[i].width!=xres; i++);
 	if (!pp_table[i].width)
-		DPRINTK("invalid width %lu\n", xres);
+		DPRINTK("invalid width %u\n", xres);
 	return pp_table[i].pp;
 }
 
-static unsigned long to3264(unsigned long timing, int bpp, int is64) {
+static u32 to3264(u32 timing, int bpp, int is64) {
 
 	switch (bpp) {
 		case 8:
@@ -383,7 +415,7 @@
 	return timing;
 }
 
-static unsigned long from3264(unsigned long timing, int bpp, int is64) {
+static u32 from3264(u32 timing, int bpp, int is64) {
 
 	switch (bpp) {
 		case 8:
@@ -403,14 +435,14 @@
 	return timing;
 }
 
-static void mnp(unsigned long clk, unsigned char* mm, unsigned char* nn,
+static void mnp(u32 clk, unsigned char* mm, unsigned char* nn,
 							unsigned char* pp) {
 	unsigned char m;
 	unsigned char n;
 	unsigned char p;
-	unsigned long f;
-	long current;
-	long delta=100000;
+	u32 f;
+	s32 curr;
+	s32 delta=100000;
 
 	*mm=*nn=*pp=0;
 	for (n=2; n<15; n++) {
@@ -418,9 +450,9 @@
 			f=PM2_REFERENCE_CLOCK*m/n;
 			if (f>=150000 && f<=300000) {
 				for (p=0; p<5; p++, f>>=1) {
-					current=clk>f?clk-f:f-clk;
-					if (current<delta) {
-						delta=current;
+					curr=clk>f?clk-f:f-clk;
+					if (curr<delta) {
+						delta=curr;
 						*mm=m;
 						*nn=n;
 						*pp=p;
@@ -435,62 +467,75 @@
 
 	WAIT_FIFO(i, 1);
 	pm2_WR(i, PM2R_SYNC, 0);
-	eieio();
+	DEFRW();
 	do {
 		while (pm2_RD(i, PM2R_OUT_FIFO_WORDS)==0);
-		eieio();
+		DEFR();
 	} while (pm2_RD(i, PM2R_OUT_FIFO)!=PM2TAG(PM2R_SYNC));
 }
 
-static void set_memclock(struct pm2fb_info* info, unsigned long clk) {
+static void set_memclock(struct pm2fb_info* info, u32 clk) {
 	int i;
 	unsigned char m, n, p;
 
 	mnp(clk, &m, &n, &p);
 	WAIT_FIFO(info, 5);
 	pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_3, 6);
-	eieio();
+	DEFW();
 	pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_1, m);
 	pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_2, n);
-	eieio();
+	DEFW();
 	pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_3, 8|p);
-	eieio();
+	DEFW();
 	pm2_RDAC_RD(info, PM2I_RD_MEMORY_CLOCK_STATUS);
-	eieio();
+	DEFR();
 	for (i=256; i &&
 		!(pm2_RD(info, PM2R_RD_INDEXED_DATA)&PM2F_PLL_LOCKED); i--);
 }
 
-static void set_pixclock(struct pm2fb_info* info, unsigned long clk) {
+static void set_pixclock(struct pm2fb_info* info, u32 clk) {
 	int i;
 	unsigned char m, n, p;
 
 	mnp(clk, &m, &n, &p);
 	WAIT_FIFO(info, 5);
 	pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A3, 0);
-	eieio();
+	DEFW();
 	pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A1, m);
 	pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A2, n);
-	eieio();
+	DEFW();
 	pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A3, 8|p);
-	eieio();
+	DEFW();
 	pm2_RDAC_RD(info, PM2I_RD_PIXEL_CLOCK_STATUS);
-	eieio();
+	DEFR();
 	for (i=256; i &&
 		!(pm2_RD(info, PM2R_RD_INDEXED_DATA)&PM2F_PLL_LOCKED); i--);
 }
 
+static void clear_palette(struct pm2fb_info* p) {
+	int i=256;
+
+	WAIT_FIFO(p, 1);
+	pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, 0);
+	DEFW();
+	while (i--) {
+		WAIT_FIFO(p, 3);
+		pm2_WR(p, PM2R_RD_PALETTE_DATA, 0);
+		pm2_WR(p, PM2R_RD_PALETTE_DATA, 0);
+		pm2_WR(p, PM2R_RD_PALETTE_DATA, 0);
+	}
+}
+
 static void set_color(struct pm2fb_info* p, unsigned char regno,
 			unsigned char r, unsigned char g, unsigned char b) {
 
 	WAIT_FIFO(p, 4);
-	eieio();
 	pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, regno);
-	eieio();
+	DEFW();
 	pm2_WR(p, PM2R_RD_PALETTE_DATA, r);
-	eieio();
+	DEFW();
 	pm2_WR(p, PM2R_RD_PALETTE_DATA, g);
-	eieio();
+	DEFW();
 	pm2_WR(p, PM2R_RD_PALETTE_DATA, b);
 }
 
@@ -520,12 +565,13 @@
 }
 
 static void set_screen(struct pm2fb_info* i, struct pm2fb_par* p) {
-	unsigned long clrmode=0;
-	unsigned long txtmap=0;
-	unsigned long xres;
+	u32 clrmode=0;
+	u32 txtmap=0;
+	u32 xres;
 
 	xres=(p->width+31)&~31;
 	set_aperture(i, p);
+	DEFRW();
 	WAIT_FIFO(i, 22);
 	pm2_RDAC_WR(i, PM2I_RD_COLOR_KEY_CONTROL, p->depth==8?0:
 						PM2F_COLOR_KEY_TEST_OFF);
@@ -565,7 +611,7 @@
 	pm2_WR(i, PM2R_VS_END, p->vsend);
 	pm2_WR(i, PM2R_VB_END, p->vbend);
 	pm2_WR(i, PM2R_SCREEN_STRIDE, p->stride);
-	eieio();
+	DEFW();
 	pm2_WR(i, PM2R_SCREEN_BASE, p->base);
 	pm2_RDAC_WR(i, PM2I_RD_COLOR_MODE, PM2F_RD_COLOR_MODE_RGB|
 						PM2F_RD_GUI_ACTIVE|clrmode);
@@ -573,6 +619,63 @@
 	set_pixclock(i, p->pixclock);
 };
 
+/*
+ * copy with packed pixels (8/16bpp only).
+ */
+static void pm2fb_pp_copy(struct pm2fb_info* i, s32 xsrc, s32 ysrc,
+					s32 x, s32 y, s32 w, s32 h) {
+	s32 scale=i->current_par.depth==8?2:1;
+	s32 offset;
+
+	if (!w || !h)
+		return;
+	WAIT_FIFO(i, 7);
+	pm2_WR(i, PM2R_CONFIG,	PM2F_CONFIG_FB_WRITE_ENABLE|
+				PM2F_CONFIG_FB_PACKED_DATA|
+				PM2F_CONFIG_FB_READ_SOURCE_ENABLE);
+	pm2_WR(i, PM2R_FB_PIXEL_OFFSET, 0);
+	pm2_WR(i, PM2R_FB_SOURCE_DELTA,	((ysrc-y)&0xfff)<<16|
+						((xsrc-x)&0xfff));
+	offset=(x&0x3)-(xsrc&0x3);
+	pm2_WR(i, PM2R_RECTANGLE_ORIGIN, (y<<16)|(x>>scale));
+	pm2_WR(i, PM2R_RECTANGLE_SIZE, (h<<16)|((w+7)>>scale));
+	pm2_WR(i, PM2R_PACKED_DATA_LIMITS, (offset<<29)|(x<<16)|(x+w));
+	DEFW();
+	pm2_WR(i, PM2R_RENDER,	PM2F_RENDER_RECTANGLE|
+				(x<xsrc?PM2F_INCREASE_X:0)|
+				(y<ysrc?PM2F_INCREASE_Y:0));
+	wait_pm2(i);
+}
+
+/*
+ * block operation. copy=0: rectangle fill, copy=1: rectangle copy.
+ */
+static void pm2fb_block_op(struct pm2fb_info* i, int copy,
+					s32 xsrc, s32 ysrc,
+					s32 x, s32 y, s32 w, s32 h,
+					u32 color) {
+
+	if (!w || !h)
+		return;
+	WAIT_FIFO(i, 6);
+	pm2_WR(i, PM2R_CONFIG,	PM2F_CONFIG_FB_WRITE_ENABLE|
+				PM2F_CONFIG_FB_READ_SOURCE_ENABLE);
+	pm2_WR(i, PM2R_FB_PIXEL_OFFSET, 0);
+	if (copy)
+		pm2_WR(i, PM2R_FB_SOURCE_DELTA,	((ysrc-y)&0xfff)<<16|
+							((xsrc-x)&0xfff));
+	else
+		pm2_WR(i, PM2R_FB_BLOCK_COLOR, color);
+	pm2_WR(i, PM2R_RECTANGLE_ORIGIN, (y<<16)|x);
+	pm2_WR(i, PM2R_RECTANGLE_SIZE, (h<<16)|w);
+	DEFW();
+	pm2_WR(i, PM2R_RENDER,	PM2F_RENDER_RECTANGLE|
+				(x<xsrc?PM2F_INCREASE_X:0)|
+				(y<ysrc?PM2F_INCREASE_Y:0)|
+				(copy?0:PM2F_RENDER_FASTFILL));
+	wait_pm2(i);
+}
+
 /***************************************************************************
  * Begin of generic initialization functions
  ***************************************************************************/
@@ -580,14 +683,14 @@
 static void pm2fb_reset(struct pm2fb_info* p) {
 
 	pm2_WR(p, PM2R_RESET_STATUS, 0);
-	eieio();
+	DEFRW();
 	while (pm2_RD(p, PM2R_RESET_STATUS)&PM2F_BEING_RESET);
-	eieio();
+	DEFRW();
 #ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
 	DPRINTK("FIFO disconnect enabled\n");
 	pm2_WR(p, PM2R_FIFO_DISCON, 1);
+	DEFRW();
 #endif
-	eieio();
 	if (board_table[p->board].init)
 		board_table[p->board].init(p);
 	WAIT_FIFO(p, 48);
@@ -633,8 +736,9 @@
 	pm2_RDAC_WR(p, PM2I_RD_RED_KEY, 0);
 	pm2_RDAC_WR(p, PM2I_RD_GREEN_KEY, 0);
 	pm2_RDAC_WR(p, PM2I_RD_BLUE_KEY, 0);
-	eieio();
-	set_memclock(p, p->memclock);
+	clear_palette(p);
+	if (p->memclock)
+		set_memclock(p, p->memclock);
 }
 
 __initfunc(static int pm2fb_conf(struct pm2fb_info* p)) {
@@ -661,9 +765,12 @@
  * Begin of per-board initialization functions
  ***************************************************************************/
 
+/*
+ * Phase5 CvisionPPC/BVisionPPC
+ */
 #ifdef CONFIG_FB_PM2_CVPPC
 static int cvppc_PCI_init(struct cvppc_par* p) {
-	extern unsigned long powerup_PCI_present;
+	extern u32 powerup_PCI_present;
 
 	if (!powerup_PCI_present) {
 		DPRINTK("no PCI bridge detected\n");
@@ -683,14 +790,14 @@
 		return 0;
 	}
 	WR32(p->pci_bridge, CSPPC_BRIDGE_ENDIAN, CSPPCF_BRIDGE_BIG_ENDIAN);
-	eieio();
+	DEFW();
 	if (pm2fb_options.flags & OPTF_OLD_MEM)
 		WR32(p->pci_config, PCI_CACHE_LINE_SIZE, 0xff00);
 	WR32(p->pci_config, PCI_BASE_ADDRESS_0, CVPPC_REGS_REGION);
 	WR32(p->pci_config, PCI_BASE_ADDRESS_1, CVPPC_FB_APERTURE_ONE);
 	WR32(p->pci_config, PCI_BASE_ADDRESS_2, CVPPC_FB_APERTURE_TWO);
 	WR32(p->pci_config, PCI_ROM_ADDRESS, CVPPC_ROM_ADDRESS);
-	eieio();
+	DEFW();
 	WR32(p->pci_config, PCI_COMMAND, 0xef000000 |
 						PCI_COMMAND_IO |
 						PCI_COMMAND_MEMORY |
@@ -714,7 +821,7 @@
 	WAIT_FIFO(p, 3);
 	pm2_WR(p, PM2R_MEM_CONTROL, 0);
 	pm2_WR(p, PM2R_BOOT_ADDRESS, 0x30);
-	eieio();
+	DEFW();
 	if (pm2fb_options.flags & OPTF_OLD_MEM)
 		pm2_WR(p, PM2R_MEM_CONFIG, CVPPC_MEM_CONFIG_OLD);
 	else
@@ -722,70 +829,100 @@
 }
 #endif /* CONFIG_FB_PM2_CVPPC */
 
-/***************************************************************************
- * Console hw acceleration
- ***************************************************************************/
-
 /*
- * copy with packed pixels (8/16bpp only).
+ * Generic PCI detection routines
  */
-static void pm2fb_pp_copy(struct pm2fb_info* i, long xsrc, long ysrc,
-					long x, long y, long w, long h) {
-	long scale=i->current_par.depth==8?2:1;
-	long offset;
-
-	if (!w || !h)
-		return;
-	WAIT_FIFO(i, 7);
-	pm2_WR(i, PM2R_CONFIG,	PM2F_CONFIG_FB_WRITE_ENABLE|
-				PM2F_CONFIG_FB_PACKED_DATA|
-				PM2F_CONFIG_FB_READ_SOURCE_ENABLE);
-	pm2_WR(i, PM2R_FB_PIXEL_OFFSET, 0);
-	pm2_WR(i, PM2R_FB_SOURCE_DELTA,	((ysrc-y)&0xfff)<<16|
-						((xsrc-x)&0xfff));
-	offset=(x&0x3)-(xsrc&0x3);
-	pm2_WR(i, PM2R_RECTANGLE_ORIGIN, (y<<16)|(x>>scale));
-	pm2_WR(i, PM2R_RECTANGLE_SIZE, (h<<16)|((w+7)>>scale));
-	pm2_WR(i, PM2R_PACKED_DATA_LIMITS, (offset<<29)|(x<<16)|(x+w));
-	eieio();
-	pm2_WR(i, PM2R_RENDER,	PM2F_RENDER_RECTANGLE|
-				(x<xsrc?PM2F_INCREASE_X:0)|
-				(y<ysrc?PM2F_INCREASE_Y:0));
-	wait_pm2(i);
+#ifdef CONFIG_FB_PM2_PCI
+static int pm2pci_detect(struct pm2fb_info* p) {
+	struct pm2pci_par* pci=&p->board_par.pci;
+	unsigned char* m;
+
+	memset(pci, 0, sizeof(struct pm2pci_par));
+	if (!pci_present()) {
+		DPRINTK("no PCI bus found.\n");
+		return 0;
+	}
+	DPRINTK("scanning PCI bus for known chipsets...\n");
+	if ((pci->dev=pci_find_device(PCI_VENDOR_ID_TI,
+					PCI_DEVICE_ID_TI_TVP4020, NULL))) {
+		DPRINTK("... found Texas Instruments TVP4020\n");
+	}
+	if (!pci->dev) {
+		DPRINTK("no PCI board found.\n");
+		return 0;
+	}
+	DPRINTK("PCI board @%08lx %08lx %08lx rom %08lx\n",
+			pci->dev->base_address[0],
+			pci->dev->base_address[1],
+			pci->dev->base_address[2],
+			pci->dev->rom_address);
+#ifdef __sparc__
+	p->regions.rg_base=(unsigned char* )
+		__pa(pci->dev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK);
+	p->regions.fb_base=(unsigned char* )
+		__pa(pci->dev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK);
+#else
+	if (pm2fb_options.flags & OPTF_VIRTUAL) {
+		p->regions.rg_base=(unsigned char* )
+			__pa(pci->dev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK);
+		p->regions.fb_base=(unsigned char* )
+			__pa(pci->dev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK);
+	}
+	else {
+		p->regions.rg_base=(unsigned char* )
+			(pci->dev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK);
+		p->regions.fb_base=(unsigned char* )
+			(pci->dev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK);
+	}
+#endif
+#ifdef __BIG_ENDIAN
+	p->regions.rg_base += PM2_REGS_SIZE;
+#endif
+	if ((m=MMAP(p->regions.rg_base, PM2_REGS_SIZE))) {
+		pci->mem_control=RD32(m, PM2R_MEM_CONTROL);
+		pci->boot_address=RD32(m, PM2R_BOOT_ADDRESS);
+		pci->mem_config=RD32(m, PM2R_MEM_CONFIG);
+		switch (pci->mem_config & PM2F_MEM_CONFIG_RAM_MASK) {
+			case PM2F_MEM_BANKS_1:
+				p->regions.fb_size=0x200000;
+				break;
+			case PM2F_MEM_BANKS_2:
+				p->regions.fb_size=0x400000;
+				break;
+			case PM2F_MEM_BANKS_3:
+				p->regions.fb_size=0x600000;
+				break;
+			case PM2F_MEM_BANKS_4:
+				p->regions.fb_size=0x800000;
+				break;
+		}
+		p->memclock=CVPPC_MEMCLOCK;
+		UNMAP(m, PM2_REGS_SIZE);
+		return 1;
+	}
+	DPRINTK("MMAP() failed.\n");
+	return 0;
 }
 
-/*
- * block operation. copy=0: rectangle fill, copy=1: rectangle copy.
- */
-static void pm2fb_block_op(struct pm2fb_info* i, int copy,
-					long xsrc, long ysrc,
-					long x, long y, long w, long h,
-					unsigned long color) {
+static void pm2pci_init(struct pm2fb_info* p) {
+	struct pm2pci_par* pci=&p->board_par.pci;
 
-	if (!w || !h)
-		return;
-	WAIT_FIFO(i, 6);
-	pm2_WR(i, PM2R_CONFIG,	PM2F_CONFIG_FB_WRITE_ENABLE|
-				PM2F_CONFIG_FB_READ_SOURCE_ENABLE);
-	pm2_WR(i, PM2R_FB_PIXEL_OFFSET, 0);
-	if (copy)
-		pm2_WR(i, PM2R_FB_SOURCE_DELTA,	((ysrc-y)&0xfff)<<16|
-							((xsrc-x)&0xfff));
-	else
-		pm2_WR(i, PM2R_FB_BLOCK_COLOR, color);
-	pm2_WR(i, PM2R_RECTANGLE_ORIGIN, (y<<16)|x);
-	pm2_WR(i, PM2R_RECTANGLE_SIZE, (h<<16)|w);
-	eieio();
-	pm2_WR(i, PM2R_RENDER,	PM2F_RENDER_RECTANGLE|
-				(x<xsrc?PM2F_INCREASE_X:0)|
-				(y<ysrc?PM2F_INCREASE_Y:0)|
-				(copy?0:PM2F_RENDER_FASTFILL));
-	wait_pm2(i);
+	WAIT_FIFO(p, 3);
+	pm2_WR(p, PM2R_MEM_CONTROL, pci->mem_control);
+	pm2_WR(p, PM2R_BOOT_ADDRESS, pci->boot_address);
+	DEFW();
+	pm2_WR(p, PM2R_MEM_CONFIG, pci->mem_config);
 }
+#endif /* CONFIG_FB_PM2_PCI */
+
+/***************************************************************************
+ * Console hw acceleration
+ ***************************************************************************/
+
 
 static int pm2fb_blank(int blank_mode, struct fb_info_gen* info) {
 	struct pm2fb_info* i=(struct pm2fb_info* )info;
-	unsigned long video;
+	u32 video;
 
 	if (!i->current_par_valid)
 		return 1;
@@ -871,7 +1008,7 @@
 #ifdef FBCON_HAS_CFB8
 static void pm2fb_clear8(struct vc_data* conp, struct display* p,
 				int sy, int sx, int height, int width) {
-	unsigned long c;
+	u32 c;
 
 	sx=sx*fontwidth(p);
 	width=width*fontwidth(p);
@@ -886,9 +1023,9 @@
 
 static void pm2fb_clear_margins8(struct vc_data* conp, struct display* p,
 							int bottom_only) {
-	unsigned long c;
-	unsigned long sx;
-	unsigned long sy;
+	u32 c;
+	u32 sx;
+	u32 sy;
 
 	c=attr_bgcol_ec(p, conp);
 	c|=c<<8;
@@ -913,7 +1050,7 @@
 #ifdef FBCON_HAS_CFB16
 static void pm2fb_clear16(struct vc_data* conp, struct display* p,
 				int sy, int sx, int height, int width) {
-	unsigned long c;
+	u32 c;
 
 	sx=sx*fontwidth(p);
 	width=width*fontwidth(p);
@@ -927,9 +1064,9 @@
 
 static void pm2fb_clear_margins16(struct vc_data* conp, struct display* p,
 							int bottom_only) {
-	unsigned long c;
-	unsigned long sx;
-	unsigned long sy;
+	u32 c;
+	u32 sx;
+	u32 sy;
 
 	c = ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
 	c|=c<<16;
@@ -957,7 +1094,7 @@
 static void pm2fb_clear24(struct vc_data* conp, struct display* p,
 				int sy, int sx, int height, int width) {
 	struct pm2fb_info* i=(struct pm2fb_info* )p->fb_info;
-	unsigned long c;
+	u32 c;
 
 	c=attr_bgcol_ec(p, conp);
 	if (		i->palette[c].red==i->palette[c].green &&
@@ -978,9 +1115,9 @@
 static void pm2fb_clear_margins24(struct vc_data* conp, struct display* p,
 							int bottom_only) {
 	struct pm2fb_info* i=(struct pm2fb_info* )p->fb_info;
-	unsigned long c;
-	unsigned long sx;
-	unsigned long sy;
+	u32 c;
+	u32 sx;
+	u32 sy;
 
 	c=attr_bgcol_ec(p, conp);
 	if (		i->palette[c].red==i->palette[c].green &&
@@ -1011,7 +1148,7 @@
 #ifdef FBCON_HAS_CFB32
 static void pm2fb_clear32(struct vc_data* conp, struct display* p,
 				int sy, int sx, int height, int width) {
-	unsigned long c;
+	u32 c;
 
 	sx=sx*fontwidth(p);
 	width=width*fontwidth(p);
@@ -1024,9 +1161,9 @@
 
 static void pm2fb_clear_margins32(struct vc_data* conp, struct display* p,
 							int bottom_only) {
-	unsigned long c;
-	unsigned long sx;
-	unsigned long sy;
+	u32 c;
+	u32 sx;
+	u32 sy;
 
 	c = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
 	sx=conp->vc_cols*fontwidth(p);
@@ -1065,18 +1202,55 @@
 	fix->accel=FB_ACCEL_3DLABS_PERMEDIA2;
 	fix->type=FB_TYPE_PACKED_PIXELS;
 	fix->visual=p->depth==8?FB_VISUAL_PSEUDOCOLOR:FB_VISUAL_TRUECOLOR;
-	fix->line_length=0;
+	if (i->current_par_valid)
+		fix->line_length=i->current_par.width*(i->current_par.depth/8);
+	else
+		fix->line_length=0;
 	fix->xpanstep=p->depth==24?8:64/p->depth;
 	fix->ypanstep=1;
 	fix->ywrapstep=0;
 	return 0;
 }
 
+#ifdef PM2FB_MASTER_DEBUG
+static void pm2fb_display_var(const struct fb_var_screeninfo* var) {
+
+	printk( KERN_DEBUG
+"- struct fb_var_screeninfo ---------------------------------------------------\n");
+	printk( KERN_DEBUG
+		"resolution: %ux%ux%u (virtual %ux%u+%u+%u)\n",
+			var->xres, var->yres, var->bits_per_pixel,
+			var->xres_virtual, var->yres_virtual,
+			var->xoffset, var->yoffset);
+	printk( KERN_DEBUG
+		"color: %c%c "
+		"R(%u,%u,%u), G(%u,%u,%u), B(%u,%u,%u), T(%u,%u,%u)\n",
+			var->grayscale?'G':'C', var->nonstd?'N':'S',
+			var->red.offset, var->red.length, var->red.msb_right,
+			var->green.offset, var->green.length, var->green.msb_right,
+			var->blue.offset, var->blue.length, var->blue.msb_right,
+			var->transp.offset, var->transp.length,
+			var->transp.msb_right);
+	printk( KERN_DEBUG
+		"timings: %ups (%u,%u)-(%u,%u)+%u+%u\n",
+		var->pixclock,
+		var->left_margin, var->upper_margin, var->right_margin,
+		var->lower_margin, var->hsync_len, var->vsync_len);
+	printk(	KERN_DEBUG
+		"activate %08x accel_flags %08x sync %08x vmode %08x\n",
+		var->activate, var->accel_flags, var->sync, var->vmode);
+	printk(	KERN_DEBUG
+"------------------------------------------------------------------------------\n");
+}
+
+#define pm2fb_decode_var pm2fb_wrapped_decode_var
+#endif
+
 static int pm2fb_decode_var(const struct fb_var_screeninfo* var,
 				void* par, struct fb_info_gen* info) {
 	struct pm2fb_info* i=(struct pm2fb_info* )info;
 	struct pm2fb_par p;
-	unsigned long xres;
+	u32 xres;
 	int data64;
 
 	memset(&p, 0, sizeof(struct pm2fb_par));
@@ -1086,39 +1260,39 @@
 	p.depth=p.depth>32?32:p.depth;
 	data64=p.depth>8;
 	xres=(var->xres+31)&~31;
-	if (p.width==~(0L))
-		p.width=xres;
-	if (p.height==~(0L))
-		p.height=var->yres;
 	if (p.width<xres+var->xoffset)
 		p.width=xres+var->xoffset;
 	if (p.height<var->yres+var->yoffset)
 		p.height=var->yres+var->yoffset;
 	if (!partprod(xres)) {
-		DPRINTK("width not supported: %lu\n", xres);
+		DPRINTK("width not supported: %u\n", xres);
 		return -EINVAL;
 	}
 	if (p.width>2047) {
-		DPRINTK("virtual width not supported: %lu\n", p.width);
+		DPRINTK("virtual width not supported: %u\n", p.width);
 		return -EINVAL;
 	}
 	if (var->yres<200) {
-		DPRINTK("height not supported: %lu\n",
-						(unsigned long )var->yres);
+		DPRINTK("height not supported: %u\n",
+						(u32 )var->yres);
 		return -EINVAL;
 	}
 	if (p.height<200 || p.height>2047) {
-		DPRINTK("virtual height not supported: %lu\n", p.height);
+		DPRINTK("virtual height not supported: %u\n", p.height);
+		return -EINVAL;
+	}
+	if (p.depth>32) {
+		DPRINTK("depth not supported: %u\n", p.depth);
 		return -EINVAL;
 	}
 	if (p.width*p.height*p.depth/8>i->regions.fb_size) {
-		DPRINTK("no memory for screen (%lux%lux%lu)\n",
-						xres, p.height, p.depth);
+		DPRINTK("no memory for screen (%ux%ux%u)\n",
+						p.width, p.height, p.depth);
 		return -EINVAL;
 	}
 	p.pixclock=PICOS2KHZ(var->pixclock);
 	if (p.pixclock>PM2_MAX_PIXCLOCK) {
-		DPRINTK("pixclock too high (%luKHz)\n", p.pixclock);
+		DPRINTK("pixclock too high (%uKHz)\n", p.pixclock);
 		return -EINVAL;
 	}
 	p.hsstart=to3264(var->right_margin, p.depth, data64);
@@ -1153,11 +1327,24 @@
 	return 0;
 }
 
+#ifdef PM2FB_MASTER_DEBUG
+#undef pm2fb_decode_var
+
+static int pm2fb_decode_var(const struct fb_var_screeninfo* var,
+				void* par, struct fb_info_gen* info) {
+	int result;
+
+	result=pm2fb_wrapped_decode_var(var, par, info);
+	pm2fb_display_var(var);
+	return result;
+}
+#endif
+
 static int pm2fb_encode_var(struct fb_var_screeninfo* var,
 				const void* par, struct fb_info_gen* info) {
 	struct pm2fb_par* p=(struct pm2fb_par* )par;
 	struct fb_var_screeninfo v;
-	unsigned long base;
+	u32 base;
 
 	memset(&v, 0, sizeof(struct fb_var_screeninfo));
 	v.xres_virtual=p->width;
@@ -1266,9 +1453,9 @@
 			return;
 		}
 	}
+	set_screen(i, p);
 	i->current_par=*p;
 	i->current_par_valid=1;
-	set_screen(i, &i->current_par);
 }
 
 static int pm2fb_getcolreg(unsigned regno,
@@ -1322,7 +1509,7 @@
 				break;
 #endif
 			default:
-				DPRINTK("bad depth %lu\n",
+				DPRINTK("bad depth %u\n",
 						i->current_par.depth);
 				break;
 		}
@@ -1338,14 +1525,15 @@
 	return regno>255;
 }
 
-static void pm2fb_dispsw(const void* par, struct display* disp,
+static void pm2fb_set_disp(const void* par, struct display* disp,
 						struct fb_info_gen* info) {
 	struct pm2fb_info* i=(struct pm2fb_info* )info;
-	unsigned long flags;
-	unsigned long depth;
+	u32 flags;
+	u32 depth;
 
 	save_flags(flags);
 	cli();
+	disp->screen_base=i->regions.v_fb;
 	switch (depth=((struct pm2fb_par* )par)->depth) {
 #ifdef FBCON_HAS_CFB8
 		case 8:
@@ -1408,6 +1596,7 @@
 	memset(&fb_info, 0, sizeof(fb_info));
 	if (!pm2fb_conf(&fb_info))
 		return;
+	pm2fb_reset(&fb_info);
 	fb_info.disp.scrollmode=SCROLL_YNOMOVE;
 	fb_info.gen.parsize=sizeof(struct pm2fb_par);
 	fb_info.gen.fbhw=&pm2fb_hwswitch;
@@ -1420,19 +1609,18 @@
 	fb_info.gen.info.updatevar=&fbgen_update_var;
 	fb_info.gen.info.blank=&fbgen_blank;
 	fbgen_get_var(&fb_info.disp.var, -1, &fb_info.gen.info);
-	if (fbgen_do_set_var(&fb_info.disp.var, 1, &fb_info.gen)<0)
-		return;
+	fbgen_do_set_var(&fb_info.disp.var, 1, &fb_info.gen);
 	fbgen_set_disp(-1, &fb_info.gen);
 	fbgen_install_cmap(0, &fb_info.gen);
 	if (register_framebuffer(&fb_info.gen.info)<0) {
 		printk("pm2fb: unable to register.\n");
 		return;
 	}
-	printk("fb%d: %s (%s), using %ldK of video memory.\n",
+	printk("fb%d: %s (%s), using %uK of video memory.\n",
 				GET_FB_IDX(fb_info.gen.info.node),
 				board_table[fb_info.board].name,
 				permedia2_name,
-				(unsigned long )(fb_info.regions.fb_size>>10));
+				(u32 )(fb_info.regions.fb_size>>10));
 	MOD_INC_USE_COUNT;
 }
 
@@ -1455,9 +1643,6 @@
 __initfunc(void pm2fb_setup(char* options, int* ints)) {
 	char* next;
 
-	memset(&pm2fb_options, 0, sizeof(pm2fb_options));
-	memcpy(&pm2fb_options.user_mode, &user_mode[0].par,
-				sizeof(pm2fb_options.user_mode));
 	while (options) {
 		if ((next=strchr(options, ',')))
 			*(next++)='\0';
@@ -1469,6 +1654,8 @@
 			pm2fb_options.flags |= OPTF_YPAN;
 		else if (!strcmp(options, "oldmem"))
 			pm2fb_options.flags |= OPTF_OLD_MEM;
+		else if (!strcmp(options, "virtual"))
+			pm2fb_options.flags |= OPTF_VIRTUAL;
 		options=next;
 	}
 }
diff -u --recursive --new-file v2.2.2/linux/drivers/video/pm2fb.h linux/drivers/video/pm2fb.h
--- v2.2.2/linux/drivers/video/pm2fb.h	Wed Jan 20 23:14:06 1999
+++ linux/drivers/video/pm2fb.h	Thu Feb 25 10:02:12 1999
@@ -2,7 +2,7 @@
  * Permedia2 framebuffer driver definitions.
  * Copyright (c) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
  * --------------------------------------------------------------------------
- * $Id: pm2fb.h,v 1.1.2.1 1999/01/12 19:53:02 geert Exp $
+ * $Id: pm2fb.h,v 1.21 1999/01/28 13:18:07 illo Exp $
  * --------------------------------------------------------------------------
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file README.legal in the main directory of this archive
@@ -16,7 +16,7 @@
 #define PM2_MAX_PIXCLOCK	230000			/* in KHz */
 #define PM2_REGS_SIZE		0x10000
 
-#define PM2TAG(r) (unsigned long )(((r)-0x8000)>>3)
+#define PM2TAG(r) (u32 )(((r)-0x8000)>>3)
 
 /*****************************************************************************
  * Permedia2 registers used in the framebuffer
@@ -128,16 +128,16 @@
 #define PM2I_RD_BLUE_KEY				0x44
 
 /* Fields and flags */
-#define PM2F_RENDER_AREASTIPPLE				(1<<0)
-#define PM2F_RENDER_FASTFILL				(1<<3)
-#define PM2F_RENDER_PRIMITIVE_MASK			(0x3<<6)
+#define PM2F_RENDER_AREASTIPPLE				(1L<<0)
+#define PM2F_RENDER_FASTFILL				(1L<<3)
+#define PM2F_RENDER_PRIMITIVE_MASK			(3L<<6)
 #define PM2F_RENDER_LINE				0
-#define PM2F_RENDER_TRAPEZOID				(1<<6)
-#define PM2F_RENDER_POINT				(2<<6)
-#define PM2F_RENDER_RECTANGLE				(3<<6)
-#define PM2F_SYNCHRONIZATION				(1<<10)
+#define PM2F_RENDER_TRAPEZOID				(1L<<6)
+#define PM2F_RENDER_POINT				(2L<<6)
+#define PM2F_RENDER_RECTANGLE				(3L<<6)
+#define PM2F_SYNCHRONIZATION				(1L<<10)
 #define PM2F_PLL_LOCKED					0x10
-#define PM2F_BEING_RESET				(1<<31)
+#define PM2F_BEING_RESET				(1L<<31)
 #define PM2F_DATATYPE_COLOR				0x8000
 #define PM2F_VGA_ENABLE					0x02
 #define PM2F_VGA_FIXED					0x04
@@ -166,13 +166,18 @@
 #define PM2F_TEXTEL_SIZE_32				0x00100000
 #define PM2F_TEXTEL_SIZE_4				0x00180000
 #define PM2F_TEXTEL_SIZE_24				0x00200000
-#define PM2F_INCREASE_X					(1<<21)
-#define PM2F_INCREASE_Y					(1<<22)
-#define PM2F_CONFIG_FB_WRITE_ENABLE			(1<<3)
-#define PM2F_CONFIG_FB_PACKED_DATA			(1<<2)
-#define PM2F_CONFIG_FB_READ_DEST_ENABLE			(1<<1)
-#define PM2F_CONFIG_FB_READ_SOURCE_ENABLE		(1<<0)
-#define PM2F_COLOR_KEY_TEST_OFF				(1<<4)
+#define PM2F_INCREASE_X					(1L<<21)
+#define PM2F_INCREASE_Y					(1L<<22)
+#define PM2F_CONFIG_FB_WRITE_ENABLE			(1L<<3)
+#define PM2F_CONFIG_FB_PACKED_DATA			(1L<<2)
+#define PM2F_CONFIG_FB_READ_DEST_ENABLE			(1L<<1)
+#define PM2F_CONFIG_FB_READ_SOURCE_ENABLE		(1L<<0)
+#define PM2F_COLOR_KEY_TEST_OFF				(1L<<4)
+#define PM2F_MEM_CONFIG_RAM_MASK			(3L<<29)
+#define PM2F_MEM_BANKS_1				0L
+#define PM2F_MEM_BANKS_2				(1L<<29)
+#define PM2F_MEM_BANKS_3				(2L<<29)
+#define PM2F_MEM_BANKS_4				(3L<<29)
 
 #endif /* PM2FB_H */
 
diff -u --recursive --new-file v2.2.2/linux/drivers/video/promcon.c linux/drivers/video/promcon.c
--- v2.2.2/linux/drivers/video/promcon.c	Mon Oct  5 13:13:42 1998
+++ linux/drivers/video/promcon.c	Thu Feb 25 10:02:12 1999
@@ -1,4 +1,4 @@
-/* $Id: promcon.c,v 1.12 1998/08/23 20:19:01 mj Exp $
+/* $Id: promcon.c,v 1.13 1999/01/19 09:56:46 jj Exp $
  * Console driver utilizing PROM sun terminal emulation
  *
  * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
@@ -230,7 +230,7 @@
 	      int count, int y, int x)
 {
 	unsigned char buf[256], *b = buf;
-	unsigned short attr = *s;
+	unsigned short attr = scr_readw(s);
 	unsigned char save;
 	int i, last = 0;
 
@@ -256,9 +256,9 @@
 			}
 
 			if (inverted(attr))
-				b += sprintf(b, "\033[7m%c\033[m", *s++);
+				b += sprintf(b, "\033[7m%c\033[m", scr_readw(s++));
 			else
-				b += sprintf(b, "%c", *s++);
+				b += sprintf(b, "%c", scr_readw(s++));
 
 			strcpy(b, "\b\033[@");
 			b += 4;
@@ -295,14 +295,14 @@
 			promcon_puts(buf, b - buf);
 			b = buf;
 		}
-		*b++ = *s++;
+		*b++ = scr_readw(s++);
 	}
 
 	px += count;
 
 	if (last) {
-		save = *s++;
-		b += sprintf(b, "%c\b\033[@%c", *s++, save);
+		save = scr_readw(s++);
+		b += sprintf(b, "%c\b\033[@%c", scr_readw(s++), save);
 		px++;
 	}
 
@@ -318,11 +318,12 @@
 static void
 promcon_putc(struct vc_data *conp, int c, int y, int x)
 {
-	unsigned short s = c;
+	unsigned short s;
 
 	if (console_blanked)
 		return;
 	
+	scr_writew(c, &s);
 	promcon_putcs(conp, &s, 1, y, x);
 }
 
@@ -591,8 +592,11 @@
 
 __initfunc(void prom_con_init(void))
 {
+#ifdef CONFIG_DUMMY_CONSOLE
 	if (conswitchp == &dummy_con)
 		take_over_console(&prom_con, 0, MAX_NR_CONSOLES-1, 1);
-	else if (conswitchp == &prom_con)
+	else
+#endif
+	if (conswitchp == &prom_con)
 		promcon_init_unimap(vc_cons[fg_console].d);
 }
diff -u --recursive --new-file v2.2.2/linux/drivers/video/q40fb.c linux/drivers/video/q40fb.c
--- v2.2.2/linux/drivers/video/q40fb.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/q40fb.c	Thu Feb 25 10:02:12 1999
@@ -0,0 +1,362 @@
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <asm/setup.h>
+#include <asm/segment.h>
+#include <asm/system.h>
+/*#include <asm/irq.h>*/
+#include <asm/q40_master.h>
+#include <linux/fb.h>
+#include <linux/module.h>
+#include <asm/pgtable.h>
+
+#include <video/fbcon-cfb16.h>
+
+
+#define Q40_PHYS_SCREEN_ADDR 0xFE800000
+static unsigned long q40_screen_addr;
+
+static u16 fbcon_cmap_cfb16[16];
+
+/* frame buffer operations */
+
+static int q40fb_open(struct fb_info *info, int user);
+static int q40fb_release(struct fb_info *info, int user);
+static int q40fb_get_fix(struct fb_fix_screeninfo *fix, int con,
+			struct fb_info *info);
+static int q40fb_get_var(struct fb_var_screeninfo *var, int con,
+			struct fb_info *info);
+static int q40fb_set_var(struct fb_var_screeninfo *var, int con,
+			struct fb_info *info);
+static int q40fb_get_cmap(struct fb_cmap *cmap,int kspc,int con,
+			 struct fb_info *info);
+static int q40fb_set_cmap(struct fb_cmap *cmap,int kspc,int con,
+			 struct fb_info *info);
+static int q40fb_pan_display(struct fb_var_screeninfo *var, int con,
+			    struct fb_info *info);
+static int q40fb_ioctl(struct inode *inode, struct file *file,
+		      unsigned int cmd, unsigned long arg, int con,
+		      struct fb_info *info);
+
+static int q40con_switch(int con, struct fb_info *info);
+static int q40con_updatevar(int con, struct fb_info *info);
+static void q40con_blank(int blank, struct fb_info *info);
+
+static void q40fb_set_disp(int con, struct fb_info *info);
+
+static struct display disp[MAX_NR_CONSOLES];
+static struct fb_info fb_info;
+static struct fb_ops q40fb_ops = { 
+	q40fb_open,q40fb_release, q40fb_get_fix, q40fb_get_var, q40fb_set_var,
+	q40fb_get_cmap, q40fb_set_cmap, q40fb_pan_display, q40fb_ioctl
+};
+
+static int currcon=0;
+
+static char q40fb_name[]="Q40";
+
+static int q40fb_open(struct fb_info *info, int user)
+{
+        /*
+         * Nothing, only a usage count for the moment
+         */
+
+        MOD_INC_USE_COUNT;
+        return(0);
+}
+
+static int q40fb_release(struct fb_info *info, int user)
+{
+        MOD_DEC_USE_COUNT;
+        return(0);
+}
+
+static int q40fb_get_fix(struct fb_fix_screeninfo *fix, int con,
+			struct fb_info *info)
+{
+	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+
+	strcpy(fix->id,"Q40");
+	fix->smem_start=(char*)q40_screen_addr;
+	fix->smem_len=1024*1024;
+	fix->type=FB_TYPE_PACKED_PIXELS;
+	fix->type_aux=0;
+	fix->visual=FB_VISUAL_TRUECOLOR;  /* good approximation so far ..*/;
+	fix->xpanstep=0;
+	fix->ypanstep=0;
+	fix->ywrapstep=0;
+        fix->line_length=1024*2;
+
+	/* no mmio,accel ...*/
+
+	return 0;
+
+}
+        
+static int q40fb_get_var(struct fb_var_screeninfo *var, int con,
+			struct fb_info *info)
+{
+	memset(var, 0, sizeof(struct fb_var_screeninfo));
+
+	var->xres=1024;
+	var->yres=512;
+	var->xres_virtual=1024;
+	var->yres_virtual=512;
+	var->xoffset=0;
+	var->yoffset=0;
+	var->bits_per_pixel=16;
+	var->grayscale=0;
+	var->nonstd=0;
+	var->activate=FB_ACTIVATE_NOW;
+	var->height=230;     /* approx for my 17" monitor, more important */
+	var->width=300;      /* than the absolute values is the unusual aspect ratio*/
+
+	var->red.offset=6; /*6*/
+	var->red.length=5;
+	var->green.offset=11; /*11*/
+	var->green.length=5;
+	var->blue.offset=0;
+	var->blue.length=6;
+	var->transp.length=0;
+
+	var->pixclock=0;
+	var->left_margin=0;
+	var->right_margin=0;
+	var->hsync_len=0;
+	var->vsync_len=0;
+	var->sync=0;
+	var->vmode=FB_VMODE_NONINTERLACED;
+
+	return 0;
+
+}
+
+static int q40fb_set_var(struct fb_var_screeninfo *var, int con,
+			struct fb_info *info)
+{
+	if(var->xres!=1024) 
+		return -EINVAL;
+	if(var->yres!=512)
+		return -EINVAL;
+	if(var->xres_virtual!=1024)
+		return -EINVAL;
+	if(var->yres_virtual!=512)
+		return -EINVAL;
+	if(var->xoffset!=0)
+		return -EINVAL;
+	if(var->yoffset!=0)
+		return -EINVAL;
+	if(var->bits_per_pixel!=16)
+		return -EINVAL;
+	if(var->grayscale!=0)
+		return -EINVAL;
+	if(var->nonstd!=0)
+		return -EINVAL;
+	if(var->activate!=FB_ACTIVATE_NOW)
+		return -EINVAL;
+	if(var->pixclock!=0)
+		return -EINVAL;
+	if(var->left_margin!=0)
+		return -EINVAL;
+	if(var->right_margin!=0)
+		return -EINVAL;
+	if(var->hsync_len!=0)
+		return -EINVAL;
+	if(var->vsync_len!=0)
+		return -EINVAL;
+	if(var->sync!=0)
+		return -EINVAL;
+	if(var->vmode!=FB_VMODE_NONINTERLACED)
+		return -EINVAL;
+
+	return 0;
+
+}
+
+static int q40_getcolreg(unsigned regno, unsigned *red, unsigned *green,
+			 unsigned *blue, unsigned *transp,
+			 struct fb_info *info)
+{
+    /*
+     *  Read a single color register and split it into colors/transparent.
+     *  The return values must have a 16 bit magnitude.
+     *  Return != 0 for invalid regno.
+     */
+    if (regno>=16) return 1;
+
+    *transp=0;
+    *green = ((fbcon_cmap_cfb16[regno]>>11) & 31)<<11;
+    *red   = ((fbcon_cmap_cfb16[regno]>>6) & 31)<<11;
+    *blue  = ((fbcon_cmap_cfb16[regno]) & 63)<<10;
+
+    return 0;
+}
+
+static int q40_setcolreg(unsigned regno, unsigned red, unsigned green,
+			 unsigned blue, unsigned transp,
+			 const struct fb_info *info)
+{
+    /*
+     *  Set a single color register. The values supplied have a 16 bit
+     *  magnitude.
+     *  Return != 0 for invalid regno.
+     */
+  
+  red>>=11;
+  green>>=11;
+  blue>>=10;
+
+    if (regno < 16) {
+      fbcon_cmap_cfb16[regno] = ((red & 31) <<5) |
+	                         ((green & 31) << 11) |
+	                         (blue & 63);
+    }
+    return 0;
+}
+
+static int q40fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+			 struct fb_info *info)
+{
+#if 1
+	if (con == currcon) /* current console? */
+		return fb_get_cmap(cmap, kspc, q40_getcolreg, info);
+	else if (fb_display[con].cmap.len) /* non default colormap? */
+		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
+	else
+		fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
+			     cmap, kspc ? 0 : 2);
+	return 0;
+#else
+	printk("get cmap not supported\n");
+
+	return -EINVAL;
+#endif
+}
+
+static int q40fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+			 struct fb_info *info)
+{
+#if 1
+	int err;
+
+	if (!fb_display[con].cmap.len) {	/* no colormap allocated? */
+		if ((err = fb_alloc_cmap(&fb_display[con].cmap,
+					 1<<fb_display[con].var.bits_per_pixel,
+					 0)))
+			return err;
+	}
+	if (con == currcon)			/* current console? */
+		return fb_set_cmap(cmap, kspc, q40_setcolreg, info);
+	else
+		fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+	return 0;
+#else
+	printk("set cmap not supported\n");
+
+	return -EINVAL;
+#endif
+}
+
+static int q40fb_pan_display(struct fb_var_screeninfo *var, int con,
+			    struct fb_info *info)
+{
+	printk("panning not supported\n");
+
+	return -EINVAL;
+
+}
+
+static int q40fb_ioctl(struct inode *inode, struct file *file,
+		      unsigned int cmd, unsigned long arg, int con,
+		      struct fb_info *info)
+{
+	return -EINVAL;
+}
+
+static void q40fb_set_disp(int con, struct fb_info *info)
+{
+  struct fb_fix_screeninfo fix;
+  struct display *display;
+
+  q40fb_get_fix(&fix, con, info);
+
+  if (con>=0)
+    display = &fb_display[con];
+  else 	
+    display = &disp[0];
+
+  if (con<0) con=0;
+
+   display->screen_base = fix.smem_start;
+   display->visual = fix.visual;
+   display->type = fix.type;
+   display->type_aux = fix.type_aux;
+   display->ypanstep = fix.ypanstep;
+   display->ywrapstep = fix.ywrapstep;
+   display->can_soft_blank = 0;
+   display->inverse = 0;
+   display->line_length = fix.line_length;
+
+#ifdef FBCON_HAS_CFB16
+   display->dispsw = &fbcon_cfb16;
+   disp->dispsw_data = fbcon_cmap_cfb16;
+#else
+   display->dispsw = &fbcon_dummy;
+#endif
+}
+  
+void q40fb_init(void)
+{
+#if 0
+        q40_screen_addr = kernel_map(Q40_PHYS_SCREEN_ADDR, 1024*1024,
+					   KERNELMAP_NO_COPYBACK, NULL);
+#else
+	q40_screen_addr = Q40_PHYS_SCREEN_ADDR; /* mapped in q40/config.c */
+#endif
+
+	fb_info.changevar=NULL;
+	strcpy(&fb_info.modename[0],q40fb_name);
+	fb_info.fontname[0]=0;
+	fb_info.disp=disp;
+	fb_info.switch_con=&q40con_switch;
+	fb_info.updatevar=&q40con_updatevar;
+	fb_info.blank=&q40con_blank;	
+	fb_info.node = -1;
+	fb_info.fbops = &q40fb_ops;
+	fb_info.flags = FBINFO_FLAG_DEFAULT;  /* not as module for now */
+	
+	master_outb(3,DISPLAY_CONTROL_REG);
+
+        q40fb_get_var(&disp[0].var, 0, &fb_info);
+	q40fb_set_disp(-1, &fb_info);
+
+	if (register_framebuffer(&fb_info) < 0)
+		panic("unable to register Q40 frame buffer\n");
+ 
+
+        printk("fb%d: Q40 frame buffer alive and kicking !\n",
+	       GET_FB_IDX(fb_info.node));
+}	
+
+	
+static int q40con_switch(int con, struct fb_info *info)
+{ 
+	currcon=con;
+	
+	return 0;
+
+}
+
+static int q40con_updatevar(int con, struct fb_info *info)
+{
+	return 0;
+}
+
+static void q40con_blank(int blank, struct fb_info *info)
+{
+}
diff -u --recursive --new-file v2.2.2/linux/drivers/video/retz3fb.c linux/drivers/video/retz3fb.c
--- v2.2.2/linux/drivers/video/retz3fb.c	Wed Jan 20 23:14:06 1999
+++ linux/drivers/video/retz3fb.c	Thu Feb 25 10:02:11 1999
@@ -101,8 +101,8 @@
 
 struct retz3_fb_info {
 	struct fb_info info;
-	unsigned long base;
-	unsigned long fbmem;
+	unsigned char *base;
+	unsigned char *fbmem;
 	unsigned long fbsize;
 	volatile unsigned char *regs;
 	unsigned long physfbmem;
@@ -1209,7 +1209,7 @@
 	if (con == -1)
 		con = 0;
 
-	display->screen_base = (char *)zinfo->fbmem;
+	display->screen_base = zinfo->fbmem;
 	display->visual = fix.visual;
 	display->type = fix.type;
 	display->type_aux = fix.type_aux;
@@ -1282,7 +1282,7 @@
 			struct fb_fix_screeninfo fix;
 			retz3fb_get_fix(&fix, con, info);
 
-			display->screen_base = (char *)zinfo->fbmem;
+			display->screen_base = zinfo->fbmem;
 			display->visual = fix.visual;
 			display->type = fix.type;
 			display->type_aux = fix.type_aux;
@@ -1456,7 +1456,7 @@
 	board_size = (unsigned long)cd->cd_BoardSize;
 
 	zinfo->base = ioremap(board_addr, board_size);
-	zinfo->regs = (unsigned char *)(zinfo->base);
+	zinfo->regs = zinfo->base;
 	zinfo->fbmem = zinfo->base + VIDEO_MEM_OFFSET;
 	/* Get memory size - for now we asume its a 4MB board */
 	zinfo->fbsize = 0x00400000; /* 4 MB */
diff -u --recursive --new-file v2.2.2/linux/drivers/video/sbusfb.c linux/drivers/video/sbusfb.c
--- v2.2.2/linux/drivers/video/sbusfb.c	Wed Jan 20 23:14:06 1999
+++ linux/drivers/video/sbusfb.c	Sun Mar  7 10:39:15 1999
@@ -244,8 +244,6 @@
 		page += map_size;
 	}
 	
-	vma->vm_file = file;
-	file->f_count++;
 	vma->vm_flags |= VM_IO;
 	if (!fb->mmaped) {
 		int lastconsole = 0;
diff -u --recursive --new-file v2.2.2/linux/drivers/video/skeletonfb.c linux/drivers/video/skeletonfb.c
--- v2.2.2/linux/drivers/video/skeletonfb.c	Mon Oct  5 13:13:42 1998
+++ linux/drivers/video/skeletonfb.c	Thu Feb 25 10:02:12 1999
@@ -240,12 +240,11 @@
     return 0;
 }
 
-static void xxx_set_dispsw(const void *par, struct display *disp,
-			   struct fb_info_gen *info)
+static void xxx_set_disp(const void *par, struct display *disp,
+			 struct fb_info_gen *info)
 {
-    unsigned long flags;
-
     /*
+     *  Fill in a pointer with the virtual address of the mapped frame buffer.
      *  Fill in a pointer to appropriate low level text console operations (and
      *  optionally a pointer to help data) for the video mode `par' of your
      *  video hardware. These can be generic software routines, or hardware
@@ -253,7 +252,7 @@
      *  If you don't have any appropriate operations, you must fill in a
      *  pointer to dummy operations, and there will be no text output.
      */
-    save_flags(flags); cli();
+    disp->screen_base = virtual_frame_buffer_address;
 #ifdef FBCON_HAS_CFB8
     if (is_cfb8) {
 	disp->dispsw = fbcon_cfb8;
@@ -278,7 +277,6 @@
     } else
 #endif
 	disp->dispsw = &fbcon_dummy;
-    restore_flags(flags);
 }
 
 
diff -u --recursive --new-file v2.2.2/linux/drivers/video/tcxfb.c linux/drivers/video/tcxfb.c
--- v2.2.2/linux/drivers/video/tcxfb.c	Mon Oct  5 13:13:42 1998
+++ linux/drivers/video/tcxfb.c	Thu Feb 25 10:02:12 1999
@@ -1,4 +1,4 @@
-/* $Id: tcxfb.c,v 1.6 1998/09/04 15:43:46 jj Exp $
+/* $Id: tcxfb.c,v 1.7 1999/01/26 10:55:03 jj Exp $
  * tcxfb.c: TCX 24/8bit frame buffer driver
  *
  * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -228,6 +228,7 @@
 		strcpy(fix->id, "TCX24");
 	}
 	fix->line_length = fb->var.xres_virtual;
+	fix->accel = FB_ACCEL_SUN_TCX;
 	
 	disp->scrollmode = SCROLL_YREDRAW;
 	if (!disp->screen_base)
diff -u --recursive --new-file v2.2.2/linux/drivers/video/vesafb.c linux/drivers/video/vesafb.c
--- v2.2.2/linux/drivers/video/vesafb.c	Fri Nov 27 13:09:27 1998
+++ linux/drivers/video/vesafb.c	Thu Feb 25 10:02:13 1999
@@ -254,6 +254,7 @@
 static int vesafb_set_var(struct fb_var_screeninfo *var, int con,
 			  struct fb_info *info)
 {
+	static int first = 1;
 
 	if (var->xres           != vesafb_defined.xres           ||
 	    var->yres           != vesafb_defined.yres           ||
@@ -262,8 +263,13 @@
 	    var->yres_virtual   <  video_height                  ||
 	    var->xoffset                                         ||
 	    var->bits_per_pixel != vesafb_defined.bits_per_pixel ||
-	    var->nonstd)
+	    var->nonstd) {
+		if (first) {
+			printk("Vesafb does not support changing the video mode\n");
+			first = 0;
+		}
 		return -EINVAL;
+	}
 
 	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST)
 		return 0;
diff -u --recursive --new-file v2.2.2/linux/drivers/video/virgefb.c linux/drivers/video/virgefb.c
--- v2.2.2/linux/drivers/video/virgefb.c	Wed Jan 20 23:14:06 1999
+++ linux/drivers/video/virgefb.c	Thu Feb 25 10:02:11 1999
@@ -89,11 +89,6 @@
 #define rl_3d(reg) \
                 (*((unsigned long volatile *)(CyberRegs + reg)))
 
-
-
-
-
-
 struct virgefb_par {
    int xres;
    int yres;
@@ -109,6 +104,11 @@
 static struct display disp;
 static struct fb_info fb_info;
 
+static union {
+#ifdef FBCON_HAS_CFB16
+    u16 cfb16[16];
+#endif
+} fbcon_cmap;
 
 /*
  *    Switch for Chipset Independency
@@ -132,6 +132,7 @@
    void (*blank)(int blank);
 } *fbhw;
 
+static int blit_maybe_busy = 0;
 
 /*
  *    Frame Buffer Name
@@ -148,7 +149,7 @@
 #define VIRGE8_HEIGHT 886
 #define VIRGE8_PIXCLOCK 12500    /* ++Geert: Just a guess */
 
-#if 0
+#if 1
 #define VIRGE16_WIDTH 800
 #define VIRGE16_HEIGHT 600
 #endif
@@ -167,6 +168,8 @@
 static unsigned long Cyber_vcode_switch_base;
 static unsigned char cv3d_on_zorro2;
  
+#define CYBMEM_OFFSET_8  0x800000	/* offsets from start of video - */ 
+#define CYBMEM_OFFSET_16 0x400000	/* ram to appropriate aperture */
 
 /*
  *    Predefined Video Modes
@@ -216,10 +219,17 @@
 	    FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
 	}
     }, {
+	"640x480-16", {		/* Cybervision 16 bpp */
+	    640, 480, 640, 480, 0, 0, 16, 0,
+	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
+	    0, 0, -1, -1, FB_ACCELF_TEXT, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
+	    FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}
+    }, {
 	"800x600-16", {		/* Cybervision 16 bpp */
 	    800, 600, 800, 600, 0, 0, 16, 0,
 	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-	    0, 0, -1, -1, 0, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
+	    0, 0, -1, -1, FB_ACCELF_TEXT, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
 	    FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
 	}
     }, {
@@ -229,6 +239,27 @@
 	    0, 0, -1, -1, 0, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
 	    FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
        }
+    }, {
+	"1152x886-16", {         /* Cybervision 16 bpp */
+	    1152, 886, 1152, 886, 0, 0, 16, 0,
+	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
+	    0, 0, -1, -1, 0, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
+	    FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+       }
+    }, {
+	"1280x1024-16", {         /* Cybervision 16 bpp */
+	    1280, 1024, 1280, 1024, 0, 0, 16, 0,
+	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
+	    0, 0, -1, -1, 0, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
+	    FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+       }
+    }, {
+	"1600x1200-16", {         /* Cybervision 16 bpp */
+	    1600, 1200, 1600, 1200, 0, 0, 16, 0,
+	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
+	    0, 0, -1, -1, 0, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
+	    FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+       }
     }
 };
 
@@ -246,8 +277,8 @@
  *    Some default modes
  */
 
-#define VIRGE8_DEFMODE     (0)
-#define VIRGE16_DEFMODE    (6)
+#define VIRGE8_DEFMODE     (1)
+#define VIRGE16_DEFMODE    (7)
 
 static struct fb_var_screeninfo virgefb_default;
 
@@ -294,6 +325,9 @@
 static struct display_switch fbcon_virge8;
 #endif
 
+#ifdef FBCON_HAS_CFB16
+static struct display_switch fbcon_virge16;
+#endif
 
 /*
  *   Hardware Specific Routines
@@ -353,15 +387,14 @@
 	 *                (the 3D penguin might need texture memory :-) )
 	 */
 
-	memset ((char*)CyberMem, 0, 1600 * 1200);
-
-	/* Disable hardware cursor */
 	if (cv3d_on_zorro2) {
 		CyberSize = 0x00380000; /* 3.5 MB , we need some space for the registers? */
 	} else {
 		CyberSize = 0x00400000; /* 4 MB */
 	}
+	memset ((char*)CyberMem, 0, CyberSize);
 
+	/* Disable hardware cursor */
 	vgawb_3d(0x3c8, 255);
 	vgawb_3d(0x3c9, 56);
 	vgawb_3d(0x3c9, 100);
@@ -396,7 +429,18 @@
 {
 	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
 	strcpy(fix->id, virgefb_name);
-	fix->smem_start = (char*) CyberMem_phys;
+	if (cv3d_on_zorro2) {
+		fix->smem_start = (char*) CyberMem_phys;
+	} else {
+		switch (par->bpp) {
+			case 8:
+				fix->smem_start = (char*) (CyberMem_phys + CYBMEM_OFFSET_8);
+				break;
+			case 16:
+				fix->smem_start = (char*) (CyberMem_phys + CYBMEM_OFFSET_16);
+				break;
+		}
+	}
 	fix->smem_len = CyberSize;
 	fix->mmio_start = (char*) CyberRegs_phys;
 	fix->mmio_len = 0x10000; /* TODO: verify this for the CV64/3D */
@@ -467,24 +511,27 @@
 	var->bits_per_pixel = par->bpp;
 	var->grayscale = 0;
 
-	if (par->bpp == 8) {
-		var->red.offset = 0;
-		var->red.length = 6;
-		var->red.msb_right = 0;
-		var->blue = var->green = var->red;
-	} else {
-		var->red.offset = 11;
-		var->red.length = 5;
-		var->red.msb_right = 0;
-		var->green.offset = 5;
-		var->green.length = 6;
-		var->green.msb_right = 0;
-		var->blue.offset = 0;
-		var->blue.length = 5;
-		var->blue.msb_right = 0;
-	}
-	var->transp.offset = 0;
-	var->transp.length = 0;
+	switch (var->bits_per_pixel) {
+		case 8:		/* CLUT */
+			var->red.offset = 0;
+			var->red.length = 6;
+			var->red.msb_right = 0;
+			var->blue = var->green = var->red;
+			break;
+		case 16:	/* RGB 565 */
+			var->red.offset = 11;
+			var->red.length = 5;
+			var->green.offset = 5;
+			var->green.length = 6;
+			var->blue.offset = 0;
+			var->blue.length = 5;
+			var->transp.offset = 0;
+			var->transp.length = 0;
+			break;
+	}
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
 	var->transp.msb_right = 0;
 
 	var->nonstd = 0;
@@ -493,8 +540,10 @@
 	var->height = -1;
 	var->width = -1;
 
-	var->accel_flags = (par->accel && par->bpp == 8) ? FB_ACCELF_TEXT : 0;
-	DPRINTK("accel CV64/3D\n");
+ 	var->accel_flags = (par->accel &&
+		((par->bpp == 8) || (par->bpp == 16))) ? FB_ACCELF_TEXT : 0;
+
+/*	printk("CV64/3D : %s\n",(var->accel_flags ? "accel" : "no accel")); */
 
 	var->vmode = FB_VMODE_NONINTERLACED;
 
@@ -525,28 +574,34 @@
 static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
 			   u_int transp, struct fb_info *info)
 {
-	if (regno > 255)
-	{
-		return (1);
-	}
-
-	/*
-	 * No colors on the CV3D yet.
-	 */
+	if (((current_par.bpp==8) && (regno>255)) ||
+		((current_par.bpp!=8) && (regno>15)))
+			return (1);
 
-	vgawb_3d(0x3c8, (unsigned char) regno);
-	red >>= 10;
-	green >>= 10;
-	blue >>= 10;
-
-	Cyber_colour_table [regno][0] = red;
-	Cyber_colour_table [regno][1] = green;
-	Cyber_colour_table [regno][2] = blue;
-
-	vgawb_3d(0x3c9, red);
-	vgawb_3d(0x3c9, green);
-	vgawb_3d(0x3c9, blue);
+	if (((current_par.bpp==8) && (regno<256)) || ((current_par.bpp==16) &&(regno<16))) {
+		Cyber_colour_table [regno][0] = red >> 10;
+		Cyber_colour_table [regno][1] = green >> 10;
+		Cyber_colour_table [regno][2] = blue >> 10;
+	}
 
+	switch (current_par.bpp) {
+#ifdef FBCON_HAS_CFB8
+		case 8:
+			vgawb_3d(0x3c8, (unsigned char) regno);
+			vgawb_3d(0x3c9, ((unsigned char) (red >> 10)));
+			vgawb_3d(0x3c9, ((unsigned char) (green >> 10)));
+			vgawb_3d(0x3c9, ((unsigned char) (blue >> 10)));
+			break;
+#endif
+#ifdef FBCON_HAS_CFB16
+		case 16:
+			fbcon_cmap.cfb16[regno] =
+				((red  & 0xf800) |
+				((green & 0xfc00) >> 5) |
+				((blue  & 0xf800) >> 11));
+			break;
+#endif
+	}
 	return (0);
 }
 
@@ -561,14 +616,18 @@
 {
 	int t;
 
-	if (regno >= 256)
+	if (regno > 255)
 		return (1);
-	t       = Cyber_colour_table [regno][0];
-	*red    = (t<<10) | (t<<4) | (t>>2);
-	t       = Cyber_colour_table [regno][1];
-	*green  = (t<<10) | (t<<4) | (t>>2);
-	t       = Cyber_colour_table [regno][2];
-	*blue   = (t<<10) | (t<<4) | (t>>2);
+
+	if (((current_par.bpp==8) && (regno<256)) || ((current_par.bpp==16) && (regno<16))) {
+
+		t = Cyber_colour_table [regno][0];
+		*red    = (t<<10) | (t<<4) | (t>>2);
+		t = Cyber_colour_table [regno][1];
+		*green  = (t<<10) | (t<<4) | (t>>2);
+		t = Cyber_colour_table [regno][2];
+		*blue   = (t<<10) | (t<<4) | (t>>2);
+	}
 	*transp = 0;
 	return (0);
 }
@@ -615,8 +674,10 @@
 unsigned long status;
 
 	do {
+		mb();
 		status = rl_3d(0x8504);
 	} while (!(status & (1 << 13)));
+	blit_maybe_busy = 0;
 }
 
 #define S3V_BITBLT	(0x0 << 27)
@@ -666,6 +727,10 @@
 		desty += (height - 1);
 	}
 
+	if (blit_maybe_busy)
+		Cyber3D_WaitBusy();
+	blit_maybe_busy = 1;
+
 	wl_3d(0xa4f4, 1); /* pattern fb color */
 
 	wl_3d(0xa4e8, ~0); /* mono pat 0 */
@@ -676,8 +741,6 @@
 	wl_3d(0xa50c, ((destx << 16) | desty));		/* rdest_xy */
 
 	wl_3d(0xa500, blitcmd);				/* GO! */
-
-	Cyber3D_WaitBusy();
 }
 
 /*
@@ -691,6 +754,10 @@
 	unsigned int blitcmd = S3V_RECTFILL | S3V_DRAW | S3V_DST_8BPP |
 		S3V_BLT_CLEAR | S3V_MONO_PAT | (1 << 26) | (1 << 25);
 
+	if (blit_maybe_busy)
+		Cyber3D_WaitBusy();
+	blit_maybe_busy = 1;
+
 	tmp = color & 0xff;
 	wl_3d(0xa4f4, tmp);
 
@@ -698,19 +765,20 @@
 	wl_3d(0xa50c, ((x << 16) | y));			/* rdest_xy */
 
 	wl_3d(0xa500, blitcmd);				/* GO! */
-	Cyber3D_WaitBusy();
 }
 
 
 /**************************************************************
  * Move cursor to x, y
  */
+
+#if 0
 static void Cyber_MoveCursor (u_short x, u_short y)
 {
 	printk("Yuck .... MoveCursor on a 3D\n");
 	return;
 }
-
+#endif
 
 /* -------------------- Interfaces to hardware functions -------------------- */
 
@@ -868,7 +936,18 @@
 	virgefb_get_fix(&fix, con, info);
 	if (con == -1)
 		con = 0;
-	display->screen_base = (char*) CyberMem;
+	if (cv3d_on_zorro2) {
+		display->screen_base = (char*) CyberMem;
+	} else {
+	        switch (display->var.bits_per_pixel) {
+			case 8:
+				display->screen_base = (char*) (CyberMem + CYBMEM_OFFSET_8);
+				break;
+			case 16:
+				display->screen_base = (char*) (CyberMem + CYBMEM_OFFSET_16);
+				break;
+		}
+	}
 	display->visual = fix.visual;
 	display->type = fix.type;
 	display->type_aux = fix.type_aux;
@@ -878,22 +957,26 @@
 	display->inverse = Cyberfb_inverse;
 	switch (display->var.bits_per_pixel) {
 #ifdef FBCON_HAS_CFB8
-	    case 8:
-		if (display->var.accel_flags & FB_ACCELF_TEXT) {
-		    display->dispsw = &fbcon_virge8;
+		case 8:
+			if (display->var.accel_flags & FB_ACCELF_TEXT) {
+		   		display->dispsw = &fbcon_virge8;
 #warning FIXME: We should reinit the graphics engine here
-		} else
-		    display->dispsw = &fbcon_virge8;
-		break;
+			} else
+				display->dispsw = &fbcon_cfb8;
+			break;
 #endif
 #ifdef FBCON_HAS_CFB16
-	    case 16:
-		display->dispsw = &fbcon_cfb16;
-		break;
+		case 16:
+			if (display->var.accel_flags & FB_ACCELF_TEXT) {
+				display->dispsw = &fbcon_virge16;
+			} else
+				display->dispsw = &fbcon_cfb16;
+			display->dispsw_data = &fbcon_cmap.cfb16;
+			break;
 #endif
-	    default:
-		display->dispsw = &fbcon_dummy;
-		break;
+		default:
+			display->dispsw = &fbcon_dummy;
+			break;
 	}
 }
 
@@ -962,7 +1045,7 @@
 
 	if (!fb_display[con].cmap.len) {       /* no colormap allocated? */
 		if ((err = fb_alloc_cmap(&fb_display[con].cmap,
-				 1<<fb_display[con].var.bits_per_pixel, 0)))
+				1<<fb_display[con].var.bits_per_pixel, 0)))
 			return(err);
 	}
 	if (con == currcon)		 /* current console? */
@@ -987,8 +1070,8 @@
 
 
 /*
-    *	 Cybervision Frame Buffer Specific ioctls
-    */
+ *	 Cybervision Frame Buffer Specific ioctls
+ */
 
 static int virgefb_ioctl(struct inode *inode, struct file *file,
 			 u_int cmd, u_long arg, int con, struct fb_info *info)
@@ -1073,12 +1156,12 @@
 	}
 	else
 	{
-		CyberVGARegs = ioremap(board_addr +0x0c000000, 0x00010000);
+		CyberVGARegs = (unsigned long)ioremap(board_addr +0x0c000000, 0x00010000);
 
 		CyberRegs_phys = board_addr + 0x05000000;
-		CyberMem_phys  = board_addr + 0x04800000;
+		CyberMem_phys  = board_addr + 0x04000000;	/* was 0x04800000 */
 		CyberRegs = ioremap(CyberRegs_phys, 0x00010000);
-		CyberMem = ioremap(CyberMem_phys, 0x00400000);
+		CyberMem = (unsigned long)ioremap(CyberMem_phys, 0x01000000);	/* was 0x00400000 */
 		cv3d_on_zorro2 = 0;
 		printk("CV3D detected running in Z3 mode\n");
 	}
@@ -1146,8 +1229,8 @@
 
 
 /*
-    *    Blank the display.
-    */
+ *    Blank the display.
+ */
 
 static void Cyberfb_blank(int blank, struct fb_info *info)
 {
@@ -1201,13 +1284,103 @@
                          (u_short)bg);
 }
 
+static void fbcon_virge8_putc(struct vc_data *conp, struct display *p, int c, int yy,
+                              int xx)
+{
+	if (blit_maybe_busy)
+		Cyber3D_WaitBusy();
+	fbcon_cfb8_putc(conp, p, c, yy, xx);
+}
+
+static void fbcon_virge8_putcs(struct vc_data *conp, struct display *p,
+                      const unsigned short *s, int count, int yy, int xx)
+{
+	if (blit_maybe_busy)
+		Cyber3D_WaitBusy();
+	fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
+}
+
+static void fbcon_virge8_revc(struct display *p, int xx, int yy)
+{
+	if (blit_maybe_busy)
+		Cyber3D_WaitBusy();
+	fbcon_cfb8_revc(p, xx, yy);
+}
+
+static void fbcon_virge8_clear_margins(struct vc_data *conp, struct display *p,
+                              int bottom_only)
+{
+	if (blit_maybe_busy)
+		Cyber3D_WaitBusy();
+	fbcon_cfb8_clear_margins(conp, p, bottom_only);
+}
+
 static struct display_switch fbcon_virge8 = {
-   fbcon_cfb8_setup, fbcon_virge8_bmove, fbcon_virge8_clear, fbcon_cfb8_putc,
-   fbcon_cfb8_putcs, fbcon_cfb8_revc, NULL, NULL, fbcon_cfb8_clear_margins,
-   FONTWIDTH(8)
+   fbcon_cfb8_setup, fbcon_virge8_bmove, fbcon_virge8_clear, fbcon_virge8_putc,
+   fbcon_virge8_putcs, fbcon_virge8_revc, NULL, NULL, fbcon_virge8_clear_margins,
+   FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
 };
 #endif
 
+#ifdef FBCON_HAS_CFB16
+static void fbcon_virge16_bmove(struct display *p, int sy, int sx, int dy,
+                               int dx, int height, int width)
+{
+        sx *= 16; dx *= 16; width *= 16;
+        Cyber3D_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
+                       (u_short)(dy*fontheight(p)), (u_short)width,
+                       (u_short)(height*fontheight(p)));
+}
+                
+static void fbcon_virge16_clear(struct vc_data *conp, struct display *p, int sy,
+                               int sx, int height, int width)
+{
+        unsigned char bg;   
+                
+        sx *= 16; width *= 16;
+        bg = attr_bgcol_ec(p,conp);
+        Cyber3D_RectFill((u_short)sx, (u_short)(sy*fontheight(p)),
+                         (u_short)width, (u_short)(height*fontheight(p)),
+                         (u_short)bg);
+}
+   
+static void fbcon_virge16_putc(struct vc_data *conp, struct display *p, int c, int yy,
+                              int xx)
+{
+	if (blit_maybe_busy)
+		Cyber3D_WaitBusy();
+	fbcon_cfb16_putc(conp, p, c, yy, xx);
+}
+
+static void fbcon_virge16_putcs(struct vc_data *conp, struct display *p,
+                      const unsigned short *s, int count, int yy, int xx)
+{
+	if (blit_maybe_busy)
+		Cyber3D_WaitBusy();
+	fbcon_cfb16_putcs(conp, p, s, count, yy, xx);
+}
+
+static void fbcon_virge16_revc(struct display *p, int xx, int yy)
+{
+	if (blit_maybe_busy)
+		Cyber3D_WaitBusy();
+	fbcon_cfb16_revc(p, xx, yy);
+}
+
+static void fbcon_virge16_clear_margins(struct vc_data *conp, struct display *p,
+                              int bottom_only)
+{
+	if (blit_maybe_busy)
+		Cyber3D_WaitBusy();
+	fbcon_cfb16_clear_margins(conp, p, bottom_only);
+}
+
+static struct display_switch fbcon_virge16 = {
+   fbcon_cfb16_setup, fbcon_virge16_bmove, fbcon_virge16_clear, fbcon_virge16_putc,
+   fbcon_virge16_putcs, fbcon_virge16_revc, NULL, NULL, fbcon_virge16_clear_margins,
+   FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+#endif
 
 #ifdef MODULE
 int init_module(void)
diff -u --recursive --new-file v2.2.2/linux/fs/Config.in linux/fs/Config.in
--- v2.2.2/linux/fs/Config.in	Wed Jan 20 23:14:06 1999
+++ linux/fs/Config.in	Sun Mar  7 15:25:23 1999
@@ -100,10 +100,6 @@
 endmenu
 fi
 
-if [ "$CONFIG_AFFS_FS" != "n" ]; then
-  define_bool CONFIG_AMIGA_PARTITION y
-fi
-
 mainmenu_option next_comment
 comment 'Partition Types'
 
@@ -115,6 +111,10 @@
   bool 'Unixware slices support (EXPERIMENTAL)' CONFIG_UNIXWARE_DISKLABEL
 fi
 endmenu
+
+if [ "$CONFIG_AFFS_FS" != "n" ]; then
+  define_bool CONFIG_AMIGA_PARTITION y
+fi
 
 source fs/nls/Config.in
 
diff -u --recursive --new-file v2.2.2/linux/fs/affs/inode.c linux/fs/affs/inode.c
--- v2.2.2/linux/fs/affs/inode.c	Tue Feb 23 15:21:34 1999
+++ linux/fs/affs/inode.c	Sun Mar  7 15:25:23 1999
@@ -21,7 +21,6 @@
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/locks.h>
-#include <linux/errno.h>
 #include <linux/genhd.h>
 #include <linux/amigaffs.h>
 #include <linux/major.h>
diff -u --recursive --new-file v2.2.2/linux/fs/affs/super.c linux/fs/affs/super.c
--- v2.2.2/linux/fs/affs/super.c	Wed Jun 24 22:54:08 1998
+++ linux/fs/affs/super.c	Sun Mar  7 15:25:23 1999
@@ -22,7 +22,6 @@
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/locks.h>
-#include <linux/errno.h>
 #include <linux/genhd.h>
 #include <linux/amigaffs.h>
 #include <linux/major.h>
diff -u --recursive --new-file v2.2.2/linux/fs/buffer.c linux/fs/buffer.c
--- v2.2.2/linux/fs/buffer.c	Tue Feb 23 15:21:34 1999
+++ linux/fs/buffer.c	Fri Mar  5 16:19:34 1999
@@ -74,7 +74,6 @@
 
 static int nr_buffers = 0;
 static int nr_buffers_type[NR_LIST] = {0,};
-static int size_buffers_type[NR_LIST] = {0,};
 static int nr_buffer_heads = 0;
 static int nr_unused_buffer_heads = 0;
 
@@ -100,8 +99,7 @@
 				each time we call refill */
 		int nref_dirt; /* Dirty buffer threshold for activating bdflush
 				  when trying to refill buffers. */
-		int pct_dirt;    /* Max %age of mem for dirty buffers before
-				    activating bdflush */
+		int dummy1;    /* unused */
 		int age_buffer;  /* Time for normal buffer to age before 
 				    we flush it */
 		int age_super;  /* Time for superblock to age before we 
@@ -482,7 +480,6 @@
 		return;
 	}
 	nr_buffers_type[bh->b_list]--;
-	size_buffers_type[bh->b_list] -= bh->b_size;
 	remove_from_hash_queue(bh);
 	remove_from_lru_list(bh);
 }
@@ -556,7 +553,6 @@
 		(*bhp)->b_prev_free = bh;
 
 		nr_buffers_type[bh->b_list]++;
-		size_buffers_type[bh->b_list] += bh->b_size;
 
 		/* Put the buffer in new hash-queue if it has a device. */
 		bh->b_next = NULL;
@@ -808,19 +804,13 @@
 		file_buffer(buf, dispose);
 		if(dispose == BUF_DIRTY) {
 			int too_many = (nr_buffers * bdf_prm.b_un.nfract/100);
-			int too_large = (num_physpages * bdf_prm.b_un.pct_dirt/100);
 
 			/* This buffer is dirty, maybe we need to start flushing.
 			 * If too high a percentage of the buffers are dirty...
 			 */
-			if (nr_buffers_type[BUF_DIRTY] > too_many ||
-			    size_buffers_type[BUF_DIRTY]/PAGE_SIZE > too_large) {
-				if (nr_buffers_type[BUF_LOCKED] > 3 * bdf_prm.b_un.ndirty)
-					wakeup_bdflush(1);
-				else
-					wakeup_bdflush(0);
-			}
-			
+			if (nr_buffers_type[BUF_DIRTY] > too_many)
+				wakeup_bdflush(1);
+
 			/* If this is a loop device, and
 			 * more than half of the buffers are dirty...
 			 * (Prevents no-free-buffers deadlock with loop device.)
diff -u --recursive --new-file v2.2.2/linux/fs/dcache.c linux/fs/dcache.c
--- v2.2.2/linux/fs/dcache.c	Mon Jan 25 17:44:34 1999
+++ linux/fs/dcache.c	Wed Feb 24 16:00:25 1999
@@ -470,7 +470,8 @@
  */
 void shrink_dcache_memory(int priority, unsigned int gfp_mask)
 {
-	prune_dcache(0);
+	if (gfp_mask & __GFP_IO)
+		prune_dcache(0);
 }
 
 #define NAME_ALLOC_LEN(len)	((len+16) & ~15)
diff -u --recursive --new-file v2.2.2/linux/fs/dquot.c linux/fs/dquot.c
--- v2.2.2/linux/fs/dquot.c	Mon Sep 28 10:51:34 1998
+++ linux/fs/dquot.c	Sun Mar  7 15:25:23 1999
@@ -483,7 +483,10 @@
 	if (dquot->dq_flags & (DQ_LOCKED | DQ_MOD)) {
 		wait_on_dquot(dquot);
 		if (dquot->dq_flags & DQ_MOD)
-			write_dquot(dquot);
+		{
+			if(dquot->dq_mnt != (struct vfsmount *)NULL)
+				write_dquot(dquot);
+		}
 		/*
 		 * The dquot may be back in use now, so we
 		 * must recheck the free list.
diff -u --recursive --new-file v2.2.2/linux/fs/fat/cvf.c linux/fs/fat/cvf.c
--- v2.2.2/linux/fs/fat/cvf.c	Thu Jan  8 14:02:41 1998
+++ linux/fs/fat/cvf.c	Sun Feb 28 09:47:37 1999
@@ -1,8 +1,11 @@
-/*
+/* 
  * CVF extensions for fat-based filesystems
  *
  * written 1997,1998 by Frank Gockel <gockel@sent13.uni-duisburg.de>
  *
+ * please do not remove the next line, dmsdos needs it for verifying patches
+ * CVF-FAT-VERSION-ID: 1.2.0
+ *
  */
  
 #include<linux/sched.h>
@@ -11,6 +14,10 @@
 #include<linux/msdos_fs_sb.h>
 #include<linux/string.h>
 #include<linux/fat_cvf.h>
+#include<linux/config.h>
+#ifdef CONFIG_KMOD
+#include<linux/kmod.h>
+#endif
 
 #define MAX_CVF_FORMATS 3
 
@@ -95,6 +102,24 @@
   int found_i=-1;
 
   if(force)
+    if(strcmp(force,"autoload")==0)
+    {
+#ifdef CONFIG_KMOD
+      request_module("cvf_autoload");
+      force=NULL;
+#else
+      printk("cannot autoload CVF modules: kmod support is not compiled into kernel\n");
+      return -1;
+#endif
+    }
+    
+#ifdef CONFIG_KMOD
+  if(force)
+    if(*force)
+      request_module(force);
+#endif
+
+  if(force)
   { if(*force)
     { for(i=0;i<MAX_CVF_FORMATS;++i)
       { if(cvf_formats[i])
@@ -102,6 +127,8 @@
             return i;
         }
       }
+      printk("CVF format %s unknown (module not loaded?)\n",force);
+      return -1;
     }
   }
 
@@ -115,6 +142,6 @@
   }
   
   if(found==1)return found_i;
-  if(found>1)printk("CVF detection ambiguous, use cvf_format=xxx option\n"); 
+  if(found>1)printk("CVF detection ambiguous, please use cvf_format=xxx option\n"); 
   return -1;
 }
diff -u --recursive --new-file v2.2.2/linux/fs/fat/file.c linux/fs/fat/file.c
--- v2.2.2/linux/fs/fat/file.c	Mon Dec 28 15:00:52 1998
+++ linux/fs/fat/file.c	Sun Feb 28 09:47:37 1999
@@ -456,6 +456,10 @@
 	/* Why no return value?  Surely the disk could fail... */
 	if (IS_IMMUTABLE(inode))
 		return /* -EPERM */;
+	if(inode->i_sb->s_flags&MS_RDONLY) {
+		printk("FAT: fat_truncate called though fs is read-only, uhh...\n");
+		return /* -EROFS */;
+	}
 	cluster = SECTOR_SIZE*MSDOS_SB(inode->i_sb)->cluster_size;
 	(void) fat_free(inode,(inode->i_size+(cluster-1))/cluster);
 	MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
diff -u --recursive --new-file v2.2.2/linux/fs/fat/mmap.c linux/fs/fat/mmap.c
--- v2.2.2/linux/fs/fat/mmap.c	Sun Nov  8 14:03:05 1998
+++ linux/fs/fat/mmap.c	Sun Mar  7 10:40:14 1999
@@ -113,8 +113,6 @@
 		mark_inode_dirty(inode);
 	}
 
-	vma->vm_file = file;
-	file->f_count++;
 	vma->vm_ops = &fat_file_mmap;
 	return 0;
 }
diff -u --recursive --new-file v2.2.2/linux/fs/file_table.c linux/fs/file_table.c
--- v2.2.2/linux/fs/file_table.c	Mon Dec 28 15:00:52 1998
+++ linux/fs/file_table.c	Tue Feb 23 15:30:59 1999
@@ -81,6 +81,8 @@
 		memset(f, 0, sizeof(*f));
 		f->f_count = 1;
 		f->f_version = ++event;
+		f->f_uid = current->fsuid;
+		f->f_gid = current->fsgid;
 		put_inuse(f);
 		return f;
 	}
@@ -119,6 +121,8 @@
 	filp->f_mode   = mode;
 	filp->f_count  = 1;
 	filp->f_dentry = dentry;
+	filp->f_uid    = current->fsuid;
+	filp->f_gid    = current->fsgid;
 	filp->f_op     = dentry->d_inode->i_op->default_file_ops;
 	if (filp->f_op->open)
 		return filp->f_op->open(dentry->d_inode, filp);
diff -u --recursive --new-file v2.2.2/linux/fs/isofs/file.c linux/fs/isofs/file.c
--- v2.2.2/linux/fs/isofs/file.c	Wed Aug 26 11:37:41 1998
+++ linux/fs/isofs/file.c	Sun Mar  7 15:25:23 1999
@@ -16,7 +16,6 @@
 #include <linux/stat.h>
 #include <linux/locks.h>
 #include <linux/fs.h>
-#include <linux/iso_fs.h>
 
 /*
  * We have mostly NULLs here: the current defaults are OK for
diff -u --recursive --new-file v2.2.2/linux/fs/lockd/host.c linux/fs/lockd/host.c
--- v2.2.2/linux/fs/lockd/host.c	Thu Dec 31 10:29:02 1998
+++ linux/fs/lockd/host.c	Mon Mar  1 10:34:56 1999
@@ -134,7 +134,7 @@
 	host->h_addr.sin_port = 0;	/* ouch! */
 	host->h_version    = version;
 	host->h_proto      = proto;
-	host->h_authflavor = RPC_AUTH_NULL;
+	host->h_authflavor = RPC_AUTH_UNIX;
 	host->h_rpcclnt    = NULL;
 	host->h_sema	   = MUTEX;
 	host->h_nextrebind = jiffies + NLM_HOST_REBIND;
diff -u --recursive --new-file v2.2.2/linux/fs/lockd/svcsubs.c linux/fs/lockd/svcsubs.c
--- v2.2.2/linux/fs/lockd/svcsubs.c	Thu Dec 31 10:29:02 1998
+++ linux/fs/lockd/svcsubs.c	Mon Mar  1 10:34:56 1999
@@ -52,8 +52,6 @@
 	struct nlm_file	*file;
 	unsigned int	hash;
 	u32		nfserr;
-	uid_t		saved_cr_uid;
-	struct svc_cred	*cred;
 
 	dprintk("lockd: nlm_file_lookup(%s/%u)\n",
 		kdevname(u32_to_kdev_t(fh->fh_dev)), fh->fh_ino);
@@ -86,15 +84,10 @@
 	 * We have to make sure we have the right credential to open
 	 * the file.
 	 */
-	cred = &rqstp->rq_cred;
-	saved_cr_uid = cred->cr_uid;
-	cred->cr_uid = 0;
 	if ((nfserr = nlmsvc_ops->fopen(rqstp, fh, &file->f_file)) != 0) {
 		dprintk("lockd: open failed (nfserr %ld)\n", ntohl(nfserr));
-		cred->cr_uid = saved_cr_uid;
 		goto out_free;
 	}
-	cred->cr_uid = saved_cr_uid;
 
 	file->f_next = nlm_files[hash];
 	nlm_files[hash] = file;
diff -u --recursive --new-file v2.2.2/linux/fs/ncpfs/mmap.c linux/fs/ncpfs/mmap.c
--- v2.2.2/linux/fs/ncpfs/mmap.c	Tue Mar 10 10:03:34 1998
+++ linux/fs/ncpfs/mmap.c	Sun Mar  7 10:40:33 1999
@@ -137,8 +137,6 @@
 		inode->i_atime = CURRENT_TIME;
 	}
 
-	vma->vm_file = file;
-	file->f_count++;
 	vma->vm_ops = &ncp_file_mmap;
 	return 0;
 }
diff -u --recursive --new-file v2.2.2/linux/fs/nfs/dir.c linux/fs/nfs/dir.c
--- v2.2.2/linux/fs/nfs/dir.c	Tue Jan 19 11:32:52 1999
+++ linux/fs/nfs/dir.c	Fri Mar  5 16:19:34 1999
@@ -713,17 +713,6 @@
 	return error;
 }
 
-/*
- * To avoid retaining a stale inode reference, we check the dentry
- * use count prior to the operation, and return EBUSY if it has
- * multiple users.
- *
- * We update inode->i_nlink and free the inode prior to the operation
- * to avoid possible races if the server reuses the inode.
- *
- * FIXME! We don't do it anymore (2.1.131) - it interacts badly with
- * new rmdir().  -- AV
- */
 static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
 {
 	int error;
@@ -735,10 +724,6 @@
 	if (dentry->d_name.len > NFS_MAXNAMLEN)
 		goto out;
 
-	error = -EBUSY;
-	if (!list_empty(&dentry->d_hash))
-		goto out;
-
 #ifdef NFS_PARANOIA
 if (dentry->d_inode->i_count > 1)
 printk("nfs_rmdir: %s/%s inode busy?? i_count=%d, i_nlink=%d\n",
@@ -746,14 +731,17 @@
 dentry->d_inode->i_count, dentry->d_inode->i_nlink);
 #endif
 
-	/*
-	 * Update i_nlink and free the inode before unlinking.
-	 */
-	if (dentry->d_inode->i_nlink)
-		dentry->d_inode->i_nlink --;
 	nfs_invalidate_dircache(dir);
 	error = nfs_proc_rmdir(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
 				dentry->d_name.name);
+
+	/* Update i_nlink and invalidate dentry. */
+	if (!error) {
+		d_drop(dentry);
+		if (dentry->d_inode->i_nlink)
+			dentry->d_inode->i_nlink --;
+	}
+
 out:
 	return error;
 }
diff -u --recursive --new-file v2.2.2/linux/fs/nfs/file.c linux/fs/nfs/file.c
--- v2.2.2/linux/fs/nfs/file.c	Wed Dec 16 10:32:56 1998
+++ linux/fs/nfs/file.c	Thu Mar  4 18:27:27 1999
@@ -97,7 +97,7 @@
 
 	status = nfs_wb_all(inode);
 	if (!status)
-		status = nfs_write_error(inode);
+		status = file->f_error;
 	return status;
 }
 
@@ -161,9 +161,11 @@
 
 	dfprintk(VFS, "nfs: fsync(%x/%ld)\n", inode->i_dev, inode->i_ino);
 
-	status = nfs_wb_pid(inode, current->pid);
-	if (!status)
-		status = nfs_write_error(inode);
+	status = nfs_wb_file(inode, file);
+	if (!status) {
+		status = file->f_error;
+		file->f_error = 0;
+	}
 	return status;
 }
 
@@ -193,10 +195,7 @@
 	if (!count)
 		goto out;
 
-	/* Check for an error from a previous async call */
-	result = nfs_write_error(inode);
-	if (!result)
-		result = generic_file_write(file, buf, count, ppos);
+	result = generic_file_write(file, buf, count, ppos);
 out:
 	return result;
 
diff -u --recursive --new-file v2.2.2/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
--- v2.2.2/linux/fs/nfs/inode.c	Thu Jan  7 15:11:40 1999
+++ linux/fs/nfs/inode.c	Wed Mar  3 11:17:02 1999
@@ -597,10 +597,8 @@
 		sattr.gid = attr->ia_gid;
 
 	sattr.size = (u32) -1;
-	if ((attr->ia_valid & ATTR_SIZE) && S_ISREG(inode->i_mode)) {
+	if ((attr->ia_valid & ATTR_SIZE) && S_ISREG(inode->i_mode))
 		sattr.size = attr->ia_size;
-		nfs_flush_trunc(inode, sattr.size);
-	}
 
 	sattr.mtime.seconds = sattr.mtime.useconds = (u32) -1;
 	if (attr->ia_valid & ATTR_MTIME) {
@@ -613,6 +611,10 @@
 		sattr.atime.seconds = attr->ia_atime;
 		sattr.atime.useconds = 0;
 	}
+
+	error = nfs_wb_all(inode);
+	if (error)
+		goto out;
 
 	error = nfs_proc_setattr(NFS_DSERVER(dentry), NFS_FH(dentry),
 				&sattr, &fattr);
diff -u --recursive --new-file v2.2.2/linux/fs/nfs/nfs2xdr.c linux/fs/nfs/nfs2xdr.c
--- v2.2.2/linux/fs/nfs/nfs2xdr.c	Wed Aug 26 11:37:43 1998
+++ linux/fs/nfs/nfs2xdr.c	Sat Mar  6 14:21:13 1999
@@ -612,6 +612,7 @@
 	{ NFSERR_FBIG,		EFBIG		},
 	{ NFSERR_NOSPC,		ENOSPC		},
 	{ NFSERR_ROFS,		EROFS		},
+	{ NFSERR_OPNOTSUPP,	EOPNOTSUPP	},
 	{ NFSERR_NAMETOOLONG,	ENAMETOOLONG	},
 	{ NFSERR_NOTEMPTY,	ENOTEMPTY	},
 	{ NFSERR_DQUOT,		EDQUOT		},
diff -u --recursive --new-file v2.2.2/linux/fs/nfs/write.c linux/fs/nfs/write.c
--- v2.2.2/linux/fs/nfs/write.c	Mon Jan  4 15:08:17 1999
+++ linux/fs/nfs/write.c	Wed Mar  3 11:17:02 1999
@@ -50,6 +50,7 @@
 #include <linux/malloc.h>
 #include <linux/swap.h>
 #include <linux/pagemap.h>
+#include <linux/file.h>
 
 #include <linux/sunrpc/clnt.h>
 #include <linux/nfs_fs.h>
@@ -237,17 +238,6 @@
 	if (rqlast < first || last < rqfirst)
 		return 0;
 
-	/* Check the credentials associated with this write request.
-	 * If the buffer is owned by the same user, we can happily
-	 * add our data without risking server permission problems.
-	 * Note that I'm not messing around with RPC root override creds
-	 * here, because they're used by swap requests only which
-	 * always write out full pages. */
-	if (!rpcauth_matchcred(&req->wb_task, req->wb_task.tk_cred)) {
-		dprintk("NFS:      update failed (cred mismatch)\n");
-		return 0;
-	}
-
 	if (first < rqfirst)
 		rqfirst = first;
 	if (rqlast < last)
@@ -271,9 +261,10 @@
  * Create and initialize a writeback request
  */
 static inline struct nfs_wreq *
-create_write_request(struct dentry *dentry, struct inode *inode,
-		struct page *page, unsigned int offset, unsigned int bytes)
+create_write_request(struct file * file, struct page *page, unsigned int offset, unsigned int bytes)
 {
+	struct dentry	*dentry = file->f_dentry;
+	struct inode	*inode = dentry->d_inode;
 	struct rpc_clnt	*clnt = NFS_CLIENT(inode);
 	struct nfs_wreq *wreq;
 	struct rpc_task	*task;
@@ -298,8 +289,7 @@
 		goto out_req;
 
 	/* Put the task on inode's writeback request list. */
-	wreq->wb_dentry = dentry;
-	wreq->wb_inode  = inode;
+	wreq->wb_file = file;
 	wreq->wb_pid    = current->pid;
 	wreq->wb_page   = page;
 	wreq->wb_offset = offset;
@@ -336,7 +326,9 @@
 schedule_write_request(struct nfs_wreq *req, int sync)
 {
 	struct rpc_task	*task = &req->wb_task;
-	struct inode	*inode = req->wb_inode;
+	struct file	*file = req->wb_file;
+	struct dentry	*dentry = file->f_dentry;
+	struct inode	*inode = dentry->d_inode;
 
 	if (NFS_CONGESTED(inode) || nr_write_requests >= NFS_WRITEBACK_MAX)
 		sync = 1;
@@ -367,7 +359,10 @@
 static int
 wait_on_write_request(struct nfs_wreq *req)
 {
-	struct rpc_clnt		*clnt = NFS_CLIENT(req->wb_inode);
+	struct file		*file = req->wb_file;
+	struct dentry		*dentry = file->f_dentry;
+	struct inode		*inode = dentry->d_inode;
+	struct rpc_clnt		*clnt = NFS_CLIENT(inode);
 	struct wait_queue	wait = { current, NULL };
 	sigset_t		oldmask;
 	int retval;
@@ -435,7 +430,7 @@
 	 * page and retry the update.
 	 */
 	req = find_write_request(inode, page);
-	if (req && update_write_request(req, offset, count))
+	if (req && req->wb_file == file && update_write_request(req, offset, count))
 		goto updated;
 
 	/*
@@ -446,7 +441,7 @@
 		return nfs_writepage_sync(dentry, inode, page, offset, count);
 
 	/* Create the write request. */
-	req = create_write_request(dentry, inode, page, offset, count);
+	req = create_write_request(file, page, offset, count);
 	if (!req)
 		return -ENOBUFS;
 
@@ -455,7 +450,7 @@
 	 * The IO completion will then free the page and the dentry.
 	 */
 	atomic_inc(&page->count);
-	dget(dentry);
+	file->f_count++;
 
 	/* Schedule request */
 	synchronous = schedule_write_request(req, sync);
@@ -571,24 +566,12 @@
 }
 
 /*
- * Write back all pending writes for one user.. 
+ * Write back all pending writes from one file descriptor..
  */
 int
-nfs_wb_pid(struct inode *inode, pid_t pid)
+nfs_wb_file(struct inode *inode, struct file *file)
 {
-	NFS_WB(inode, req->wb_pid == pid);
-}
-
-/*
- * Flush all write requests for truncation:
- * 	Simplification of the comparison has the side-effect of
- *	causing all writes in an infested page to be waited upon.
- */
-int
-nfs_flush_trunc(struct inode *inode, unsigned long from)
-{
-	from &= PAGE_MASK;
-	NFS_WB(inode, req->wb_page->offset >= from);
+	NFS_WB(inode, req->wb_file == file);
 }
 
 void
@@ -598,16 +581,6 @@
 }
 
 /*
- * Check if a previous write operation returned an error
- */
-int
-nfs_check_error(struct inode *inode)
-{
-	/* FIXME! */
-	return 0;
-}
-
-/*
  * The following procedures make up the writeback finite state machinery:
  *
  * 1.	Try to lock the page if not yet locked by us,
@@ -618,7 +591,8 @@
 {
 	struct nfs_wreq	*req = (struct nfs_wreq *) task->tk_calldata;
 	struct page	*page = req->wb_page;
-	struct dentry	*dentry = req->wb_dentry;
+	struct file	*file = req->wb_file;
+	struct dentry	*dentry = file->f_dentry;
 
 	dprintk("NFS: %4d nfs_wback_begin (%s/%s, status=%d flags=%x)\n",
 		task->tk_pid, dentry->d_parent->d_name.name,
@@ -645,13 +619,15 @@
 nfs_wback_result(struct rpc_task *task)
 {
 	struct nfs_wreq *req = (struct nfs_wreq *) task->tk_calldata;
-	struct inode	*inode = req->wb_inode;
-	struct page	*page  = req->wb_page;
+	struct file	*file = req->wb_file;
+	struct page	*page = req->wb_page;
 	int		status = task->tk_status;
+	struct dentry	*dentry = file->f_dentry;
+	struct inode	*inode = dentry->d_inode;
 
 	dprintk("NFS: %4d nfs_wback_result (%s/%s, status=%d, flags=%x)\n",
-		task->tk_pid, req->wb_dentry->d_parent->d_name.name,
-		req->wb_dentry->d_name.name, status, req->wb_flags);
+		task->tk_pid, dentry->d_parent->d_name.name,
+		dentry->d_name.name, status, req->wb_flags);
 
 	/* Set the WRITE_COMPLETE flag, but leave WRITE_INPROGRESS set */
 	req->wb_flags |= NFS_WRITE_COMPLETE;
@@ -659,6 +635,7 @@
 
 	if (status < 0) {
 		req->wb_flags |= NFS_WRITE_INVALIDATE;
+		file->f_error = status;
 	} else if (!WB_CANCELLED(req)) {
 		struct nfs_fattr *fattr = &req->wb_fattr;
 		/* Update attributes as result of writeback. 
@@ -696,22 +673,8 @@
 	__free_page(page);
 	remove_write_request(&NFS_WRITEBACK(inode), req);
 	nr_write_requests--;
-	dput(req->wb_dentry);
+	fput(req->wb_file);
 
 	wake_up(&req->wb_wait);
-	
-	/*
-	 * FIXME!
-	 *
-	 * We should not free the request here if it has pending
-	 * error status on it. We should just leave it around, to
-	 * let the error be collected later. However, the error
-	 * collecting routines are too stupid for that right now,
-	 * so we just drop the error on the floor at this point
-	 * for any async writes.
-	 *
-	 * This should not be a major headache to fix, but I want
-	 * to validate basic operations first.
-	 */
 	free_write_request(req);
 }
diff -u --recursive --new-file v2.2.2/linux/fs/proc/array.c linux/fs/proc/array.c
--- v2.2.2/linux/fs/proc/array.c	Thu Jan 28 12:58:02 1999
+++ linux/fs/proc/array.c	Mon Mar  8 11:07:29 1999
@@ -1343,6 +1343,7 @@
 {
 	struct task_struct *p;
 	uid_t euid=0;	/* Save the euid keep the lock short */
+	int ok = 0;
 		
 	read_lock(&tasklist_lock);
 	
@@ -1352,9 +1353,11 @@
 	 */
 	
 	p = find_task_by_pid(pid);
-	if(p)
-	{
+	if (p) {
 		euid=p->euid;
+		ok = p->dumpable;
+		if(!cap_issubset(p->cap_permitted, current->cap_permitted))
+			ok=0;			
 		if(!p->mm)	/* Scooby scooby doo where are you ? */
 			p=NULL;
 	}
@@ -1374,7 +1377,7 @@
 		case PROC_PID_CPU:
 			return 0;	
 	}
-	if(capable(CAP_DAC_OVERRIDE) || current->fsuid == euid)
+	if(capable(CAP_DAC_OVERRIDE) || (current->fsuid == euid && ok))
 		return 0;
 	return 1;
 }
diff -u --recursive --new-file v2.2.2/linux/fs/smbfs/cache.c linux/fs/smbfs/cache.c
--- v2.2.2/linux/fs/smbfs/cache.c	Mon Nov 24 10:30:40 1997
+++ linux/fs/smbfs/cache.c	Sun Mar  7 15:25:23 1999
@@ -12,7 +12,6 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include <linux/errno.h>
 #include <linux/dirent.h>
 #include <linux/smb_fs.h>
 
@@ -142,7 +141,7 @@
 
 #ifdef SMBFS_DEBUG_VERBOSE
 printk("smb_add_to_cache: cache inode %p, status %d, adding %s at %ld\n",
-inode, cachep->status, entry->d_name, fpos);
+inode, cachep->status, entry->name, fpos);
 #endif
 	/*
 	 * Don't do anything if we've had an error ...
@@ -171,7 +170,7 @@
 		cachep->entries++;
 #ifdef SMBFS_DEBUG_VERBOSE
 printk("smb_add_to_cache: added entry %s, len=%d, pos=%ld, entries=%d\n",
-entry->d_name, len, fpos, cachep->entries);
+entry->name, len, fpos, cachep->entries);
 #endif
 		return;
 	}
diff -u --recursive --new-file v2.2.2/linux/fs/vfat/namei.c linux/fs/vfat/namei.c
--- v2.2.2/linux/fs/vfat/namei.c	Mon Jan 25 17:44:34 1999
+++ linux/fs/vfat/namei.c	Sun Feb 28 09:47:37 1999
@@ -506,10 +506,10 @@
 			continue;
 		if (memcmp(de->name,name,MSDOS_NAME))
 			continue;
-		brelse(bh);
+		fat_brelse(dir->i_sb,bh);
 		return 0;
 	}
-	brelse(bh);
+	fat_brelse(dir->i_sb,bh);
 	return -ENOENT;
 }
 
@@ -1659,6 +1659,9 @@
 		res = vfat_remove_entry(new_dir,&sinfo,new_inode);
 		if (res)
 			goto rename_done;
+
+		if (is_dir)
+			new_dir->i_nlink--;
 	}
 
 	/* Serious lossage here. FAT uses braindead inode numbers scheme,
@@ -1669,9 +1672,6 @@
 	 * in icache and as a part of stat output. It would kill all the
 	 * 'busy' stuff on the spot. Later.
 	 */
-
-	if (is_dir)
-		new_dir->i_nlink--;
 
 	res = vfat_find(new_dir,&new_dentry->d_name,1,is_dir,&sinfo);
 
diff -u --recursive --new-file v2.2.2/linux/include/asm-alpha/semaphore-helper.h linux/include/asm-alpha/semaphore-helper.h
--- v2.2.2/linux/include/asm-alpha/semaphore-helper.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-alpha/semaphore-helper.h	Thu Feb 25 10:02:11 1999
@@ -0,0 +1,122 @@
+#ifndef _ALPHA_SEMAPHORE_HELPER_H
+#define _ALPHA_SEMAPHORE_HELPER_H
+
+/*
+ * SMP- and interrupt-safe semaphores helper functions.
+ *
+ * (C) Copyright 1996 Linus Torvalds
+ * (C) Copyright 1999 Richard Henderson
+ */
+
+/*
+ * These two _must_ execute atomically wrt each other.
+ *
+ * This is trivially done with load_locked/store_cond,
+ * which we have.  Let the rest of the losers suck eggs.
+ */
+
+static inline void
+wake_one_more(struct semaphore * sem)
+{
+	atomic_inc(&sem->waking);
+}
+
+static inline int
+waking_non_zero(struct semaphore *sem)
+{
+	long ret, tmp;
+
+	/* An atomic conditional decrement.  */
+	__asm__ __volatile__(
+		"1:	ldl_l	%1,%2\n"
+		"	blt	%1,2f\n"
+		"	subl	%1,1,%0\n"
+		"	stl_c	%0,%2\n"
+		"	beq	%0,3f\n"
+		"2:\n"
+		".section .text2,\"ax\"\n"
+		"3:	br	1b\n"
+		".previous"
+		: "=r"(ret), "=r"(tmp), "=m"(__atomic_fool_gcc(&sem->waking))
+		: "0"(0));
+
+	return ret > 0;
+}
+
+
+/*
+ * waking_non_zero_interruptible:
+ *	1	got the lock
+ *	0	go to sleep
+ *	-EINTR	interrupted
+ *
+ * We must undo the sem->count down_interruptible increment
+ * simultaneously and atomicly with the sem->waking adjustment,
+ * otherwise we can race with wake_one_more.
+ *
+ * This is accomplished by doing a 64-bit ll/sc on the 2 32-bit words.
+ */
+
+static inline int
+waking_non_zero_interruptible(struct semaphore *sem, struct task_struct *tsk)
+{
+	long ret, tmp, tmp2, tmp3;
+
+	/* "Equivalent" C.  Note that we have to do this all without
+	   (taken) branches in order to be a valid ll/sc sequence.
+
+	   do {
+	       tmp = ldq_l;
+	       ret = 0;
+	       if (tmp >= 0) {
+	           tmp += 0xffffffff00000000;
+	           ret = 1;
+	       }
+	       else if (pending) {
+	           tmp += 1;
+	           ret = -EINTR;
+	       }
+	       else {
+		   break;	// ideally.  we don't actually break 
+		   		// since this is a predicate we don't
+				// have, and is more trouble to build
+				// than to elide the noop stq_c.
+	       }
+	       tmp = stq_c = tmp;
+	   } while (tmp == 0);
+	*/
+
+	__asm__ __volatile__(
+		"1:	ldq_l	%1,%4\n"
+		"	lda	%0,0\n"
+		"	addq	%1,1,%2\n"
+		"	ldah	%3,0x8000(%1)\n"
+		"	cmovne	%5,%6,%0\n"
+		"	ldah	%3,0x8000(%3)\n"
+		"	cmovge	%1,1,%0\n"
+		"	cmovne	%5,%2,%1\n"
+		"	cmovge	%2,%3,%1\n"
+		"	stq_c	%1,%4\n"
+		"	beq	%1,3f\n"
+		"2:\n"
+		".section .text2,\"ax\"\n"
+		"3:	br	1b\n"
+		".previous"
+		: "=&r"(ret), "=&r"(tmp), "=&r"(tmp2), "=&r"(tmp3), "=m"(*sem)
+		: "r"(signal_pending(tsk)), "r"(-EINTR));
+
+	return ret;
+}
+
+/*
+ * waking_non_zero_trylock is unused.  we do everything in 
+ * down_trylock and let non-ll/sc hosts bounce around.
+ */
+
+static inline int
+waking_non_zero_trylock(struct semaphore *sem)
+{
+	return 0;
+}
+
+#endif
diff -u --recursive --new-file v2.2.2/linux/include/asm-alpha/semaphore.h linux/include/asm-alpha/semaphore.h
--- v2.2.2/linux/include/asm-alpha/semaphore.h	Wed Jan 20 23:14:06 1999
+++ linux/include/asm-alpha/semaphore.h	Thu Feb 25 10:02:11 1999
@@ -5,123 +5,38 @@
  * SMP- and interrupt-safe semaphores..
  *
  * (C) Copyright 1996 Linus Torvalds
+ * (C) Copyright 1996 Richard Henderson
  */
 
 #include <asm/current.h>
 #include <asm/system.h>
 #include <asm/atomic.h>
 
-/*
- * Semaphores are recursive: we allow the holder process to recursively do
- * down() operations on a semaphore that the process already owns. In order
- * to do that, we need to keep a semaphore-local copy of the owner and the
- * "depth of ownership".
- *
- * NOTE! Nasty memory ordering rules:
- *  - "owner" and "owner_count" may only be modified once you hold the lock.
- *  - "owner_count" must be written _after_ modifying owner, and must be
- *  read _before_ reading owner. There must be appropriate write and read
- *  barriers to enforce this.
- */
-
 struct semaphore {
+	/* Careful, inline assembly knows about the position of these two.  */
 	atomic_t count;
-	atomic_t waking;
-	struct task_struct *owner;
-	long owner_depth;
-	struct wait_queue * wait;
+	atomic_t waking;		/* biased by -1 */
+	struct wait_queue *wait;
 };
 
 #define MUTEX ((struct semaphore) \
- { ATOMIC_INIT(1), ATOMIC_INIT(0), NULL, 0, NULL })
+ { ATOMIC_INIT(1), ATOMIC_INIT(-1), NULL })
 #define MUTEX_LOCKED ((struct semaphore) \
- { ATOMIC_INIT(0), ATOMIC_INIT(0), NULL, 1, NULL })
+ { ATOMIC_INIT(0), ATOMIC_INIT(-1), NULL })
 
-#define semaphore_owner(sem)	((sem)->owner)
 #define sema_init(sem, val)	atomic_set(&((sem)->count), val)
 
 extern void __down(struct semaphore * sem);
 extern int  __down_interruptible(struct semaphore * sem);
+extern int  __down_trylock(struct semaphore * sem);
 extern void __up(struct semaphore * sem);
 
-/* All three have custom assembly linkages.  */
+/* All have custom assembly linkages.  */
 extern void __down_failed(struct semaphore * sem);
 extern void __down_failed_interruptible(struct semaphore * sem);
+extern void __down_failed_trylock(struct semaphore * sem);
 extern void __up_wakeup(struct semaphore * sem);
 
-
-/*
- * These two _must_ execute atomically wrt each other.
- *
- * This is trivially done with load_locked/store_cond,
- * which we have.  Let the rest of the losers suck eggs.
- *
- * Tricky bits --
- *
- * (1) One task does two downs, no other contention
- *	initial state:
- *		count = 1, waking = 0, depth = undef;
- *	down(&sem)
- *		count = 0, waking = 0, depth = 1;
- *	down(&sem)
- *		atomic dec and test sends us to waking_non_zero via __down
- *			count = -1, waking = 0;
- *		conditional atomic dec on waking discovers no free slots
- *			count = -1, waking = 0;
- *		test for owner succeeeds and we return ok.
- *			count = -1, waking = 0, depth = 2;
- *	up(&sem)
- *		dec depth
- *			count = -1, waking = 0, depth = 1;
- *		atomic inc and test sends us to slow path
- *			count = 0, waking = 0, depth = 1;
- *		notice !(depth < 0) and don't call __up.
- *	up(&sem)
- *		dec depth
- *			count = 0, waking = 0, depth = 0;
- *		atomic inc and test succeeds.
- *			count = 1, waking = 0, depth = 0;
- */
-
-static inline void wake_one_more(struct semaphore * sem)
-{
-	atomic_inc(&sem->waking);
-}
-
-static inline int waking_non_zero(struct semaphore *sem,
-				  struct task_struct *tsk)
-{
-	long owner_depth;
-	int ret, tmp;
-
-	owner_depth = sem->owner_depth;
-	
-	/* Atomic decrement, iff the value is > 0.  */
-	__asm__ __volatile__(
-	"1:	ldl_l	%1,%2\n"
-	"	ble	%1,2f\n"
-	"	subl	%1,1,%0\n"
-	"	stl_c	%0,%2\n"
-	"	beq	%0,3f\n"
-	"2:	mb\n"
-	".section .text2,\"ax\"\n"
-	"3:	br	1b\n"
-	".previous"
-	: "=r"(ret), "=r"(tmp), "=m"(__atomic_fool_gcc(&sem->waking))
-	: "0"(0));
-
-	ret |= ((owner_depth != 0) & (sem->owner == tsk));
-	if (ret) {
-		sem->owner = tsk;
-		wmb();
-		/* Don't use the old value, which is stale in the
-		   !owner case.  */
-		sem->owner_depth++;
-	}
-
-	return ret;
-}
-
 /*
  * Whee.  Hidden out of line code is fun.  The contention cases are
  * handled out of line in kernel/sched.c; arch/alpha/lib/semaphore.S
@@ -140,27 +55,21 @@
 
 	__asm__ __volatile__ (
 		"/* semaphore down operation */\n"
-		"1:	ldl_l	$27,%3\n"
+		"1:	ldl_l	$27,%0\n"
 		"	subl	$27,1,$27\n"
 		"	mov	$27,$28\n"
 		"	stl_c	$28,%0\n"
 		"	beq	$28,2f\n"
 		"	blt	$27,3f\n"
-		/* Got the semaphore no contention.  Set owner and depth.  */
-		"	stq	$8,%1\n"
-		"	lda	$28,1\n"
-		"	wmb\n"
-		"	stq	$28,%2\n"
 		"4:	mb\n"
 		".section .text2,\"ax\"\n"
 		"2:	br	1b\n"
-		"3:	lda	$24,%3\n"
+		"3:	lda	$24,%0\n"
 		"	jsr	$28,__down_failed\n"
 		"	ldgp	$29,0($28)\n"
 		"	br	4b\n"
 		".previous"
-		: "=m"(sem->count), "=m"(sem->owner), "=m"(sem->owner_depth)
-		: "m"(sem->count)
+		: : "m"(sem->count)
 		: "$24", "$27", "$28", "memory");
 }
 
@@ -175,34 +84,79 @@
 
 	__asm__ __volatile__ (
 		"/* semaphore down interruptible operation */\n"
-		"1:	ldl_l	$27,%4\n"
+		"1:	ldl_l	$27,%1\n"
 		"	subl	$27,1,$27\n"
 		"	mov	$27,$28\n"
 		"	stl_c	$28,%1\n"
 		"	beq	$28,2f\n"
 		"	blt	$27,3f\n"
-		/* Got the semaphore no contention.  Set owner and depth.  */
-		"	stq	$8,%2\n"
-		"	lda	$28,1\n"
-		"	wmb\n"
-		"	stq	$28,%3\n"
-		"	mov	$31,$24\n"
+		"	mov	$31,%0\n"
 		"4:	mb\n"
 		".section .text2,\"ax\"\n"
 		"2:	br	1b\n"
-		"3:	lda	$24,%4\n"
+		"3:	lda	$24,%1\n"
 		"	jsr	$28,__down_failed_interruptible\n"
 		"	ldgp	$29,0($28)\n"
 		"	br	4b\n"
 		".previous"
-		: "=r"(ret), "=m"(sem->count), "=m"(sem->owner),
-		  "=m"(sem->owner_depth)
+		: "=r"(ret)
 		: "m"(sem->count)
 		: "$27", "$28", "memory");
 
 	return ret;
 }
 
+/*
+ * down_trylock returns 0 on success, 1 if we failed to get the lock.
+ *
+ * We must manipulate count and waking simultaneously and atomically.
+ * Do this by using ll/sc on the pair of 32-bit words.
+ */
+
+extern inline int down_trylock(struct semaphore * sem)
+{
+	long ret, tmp, tmp2;
+
+	/* "Equivalent" C.  Note that we have to do this all without
+	   (taken) branches in order to be a valid ll/sc sequence.
+
+	   do {
+	       tmp = ldq_l;
+	       ret = 0;
+	       tmp -= 1;
+	       if ((int)tmp < 0)		// count
+	           break;
+	       if ((long)tmp < 0)		// waking
+	           break;
+	       tmp += 0xffffffff00000000;
+	       ret = 1;
+	       tmp = stq_c = tmp;
+	   } while (tmp == 0);
+	*/
+
+	__asm__ __volatile__(
+		"1:	ldq_l	%1,%3\n"
+		"	lda	%0,0\n"
+		"	subl	%1,1,%2\n"
+		"	subq	%1,1,%1\n"
+		"	blt	%2,2f\n"
+		"	blt	%1,2f\n"
+		"	ldah	%1,0x8000(%1)\n"
+		"	ldah	%1,0x8000(%1)\n"
+		"	lda	%0,1\n"
+		"	stq_c	%1,%3\n"
+		"	beq	%1,3f\n"
+		"2:	mb\n"
+		".section .text2,\"ax\"\n"
+		"3:	br	1b\n"
+		".previous"
+		: "=&r"(ret), "=&r"(tmp), "=&r"(tmp2)
+		: "m"(*sem)
+		: "memory");
+
+	return ret;
+}
+
 extern inline void up(struct semaphore * sem)
 {
 	/* Given that we have to use particular hard registers to 
@@ -216,7 +170,7 @@
 	__asm__ __volatile__ (
 		"/* semaphore up operation */\n"
 		"	mb\n"
-		"1:	ldl_l	$27,%1\n"
+		"1:	ldl_l	$27,%0\n"
 		"	addl	$27,1,$27\n"
 		"	mov	$27,$28\n"
 		"	stl_c	$28,%0\n"
@@ -226,14 +180,12 @@
 		"4:\n"
 		".section .text2,\"ax\"\n"
 		"2:	br	1b\n"
-		"3:	lda	$24,%1\n"
-		"	bgt	%2,4b\n"
+		"3:	lda	$24,%0\n"
 		"	jsr	$28,__up_wakeup\n"
 		"	ldgp	$29,0($28)\n"
 		"	br	4b\n"
 		".previous"
-		: "=m"(sem->count)
-		: "m"(sem->count), "r"(--sem->owner_depth)
+		: : "m"(sem->count)
 		: "$24", "$27", "$28", "memory");
 }
 
diff -u --recursive --new-file v2.2.2/linux/include/asm-alpha/vga.h linux/include/asm-alpha/vga.h
--- v2.2.2/linux/include/asm-alpha/vga.h	Thu Jul 16 18:09:28 1998
+++ linux/include/asm-alpha/vga.h	Thu Feb 25 10:02:12 1999
@@ -21,7 +21,7 @@
 		writew(val, (unsigned long) addr);
 }
 
-extern inline u16 scr_readw(u16 *addr)
+extern inline u16 scr_readw(const u16 *addr)
 {
 	if ((long) addr < 0)
 		return *addr;
@@ -37,12 +37,12 @@
 		memsetw_io(s, c, count);
 }
 
-extern inline void scr_memcpyw_from(u16 *d, u16 *s, unsigned int count)
+extern inline void scr_memcpyw_from(u16 *d, const u16 *s, unsigned int count)
 {
 	memcpy_fromio(d, s, count);
 }
 
-extern inline void scr_memcpyw_to(u16 *d, u16 *s, unsigned int count)
+extern inline void scr_memcpyw_to(u16 *d, const u16 *s, unsigned int count)
 {
 	memcpy_toio(d, s, count);
 }
diff -u --recursive --new-file v2.2.2/linux/include/asm-mips/vga.h linux/include/asm-mips/vga.h
--- v2.2.2/linux/include/asm-mips/vga.h	Thu Jul 16 18:09:29 1998
+++ linux/include/asm-mips/vga.h	Thu Feb 25 10:02:12 1999
@@ -19,7 +19,7 @@
 		writew(val, (unsigned long) addr);
 }
 
-extern inline u16 scr_readw(u16 *addr)
+extern inline u16 scr_readw(const u16 *addr)
 {
 	if ((long) addr < 0)
 		return *addr;
diff -u --recursive --new-file v2.2.2/linux/include/asm-ppc/vga.h linux/include/asm-ppc/vga.h
--- v2.2.2/linux/include/asm-ppc/vga.h	Thu Nov 19 09:56:29 1998
+++ linux/include/asm-ppc/vga.h	Thu Feb 25 10:02:12 1999
@@ -16,7 +16,7 @@
 	st_le16(addr, val);
 }
 
-extern inline u16 scr_readw(u16 *addr)
+extern inline u16 scr_readw(const u16 *addr)
 {
 	return ld_le16(addr);
 }
diff -u --recursive --new-file v2.2.2/linux/include/asm-sparc64/vga.h linux/include/asm-sparc64/vga.h
--- v2.2.2/linux/include/asm-sparc64/vga.h	Thu Jul 16 18:09:29 1998
+++ linux/include/asm-sparc64/vga.h	Thu Feb 25 10:02:12 1999
@@ -17,7 +17,7 @@
 		writew(val, (unsigned long) addr);
 }
 
-static inline u16 scr_readw(u16 *addr)
+static inline u16 scr_readw(const u16 *addr)
 {
 	if ((long) addr < 0)
 		return *addr;
diff -u --recursive --new-file v2.2.2/linux/include/linux/awe_voice.h linux/include/linux/awe_voice.h
--- v2.2.2/linux/include/linux/awe_voice.h	Tue Dec 22 14:16:58 1998
+++ linux/include/linux/awe_voice.h	Sun Mar  7 15:25:23 1999
@@ -3,9 +3,9 @@
  *
  * Voice information definitions for the low level driver for the 
  * AWE32/SB32/AWE64 wave table synth.
- *   version 0.4.3; Mar. 1, 1998
+ *   version 0.4.3; Feb. 1, 1999
  *
- * Copyright (C) 1996-1998 Takashi Iwai
+ * Copyright (C) 1996-1999 Takashi Iwai
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -133,7 +133,7 @@
 	unsigned short moddelay;	/* modulation delay (0x8000) */
 	unsigned char modatk, modhld;
 	unsigned char moddcy, modsus;
-	unsigned short modrel, moddummy;
+	unsigned char modrel, moddummy;
 	short modkeyhold, modkeydecay;	/* envelope change per key (not used) */
 	unsigned short voldelay;	/* volume delay (0x8000) */
 	unsigned char volatk, volhld;
diff -u --recursive --new-file v2.2.2/linux/include/linux/console.h linux/include/linux/console.h
--- v2.2.2/linux/include/linux/console.h	Fri Nov 27 13:09:29 1998
+++ linux/include/linux/console.h	Thu Feb 25 10:02:12 1999
@@ -42,6 +42,8 @@
 	void	(*con_save_screen)(struct vc_data *);
 	u8	(*con_build_attr)(struct vc_data *, u8, u8, u8, u8, u8);
 	void	(*con_invert_region)(struct vc_data *, u16 *, int);
+	u16    *(*con_screen_pos)(struct vc_data *, int);
+	unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int *);
 };
 
 extern struct consw *conswitchp;
diff -u --recursive --new-file v2.2.2/linux/include/linux/dtlk.h linux/include/linux/dtlk.h
--- v2.2.2/linux/include/linux/dtlk.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/dtlk.h	Sun Mar  7 16:15:39 1999
@@ -0,0 +1,104 @@
+#if 0
+
+#define TRACE_TXT(text) \
+	{ \
+	  if(dtlk_trace) \
+	  { \
+	    console_print(text); \
+	    console_print("\n"); \
+	  } \
+	}
+
+#define TRACE_CHR(chr) \
+	{ \
+	  if(dtlk_trace) \
+	    console_print(chr); \
+	} \
+
+#endif
+
+#define DTLK_MINOR	0
+#define DTLK_IO_EXTENT	0x02
+
+	/* ioctl's use magic number of 0xa3 */
+#define DTLK_INTERROGATE 0xa390	/* get settings from the DoubleTalk */
+#define DTLK_STATUS 0xa391	/* get status from the DoubleTalk */
+
+
+#define DTLK_CLEAR 0x18		/* stops speech */
+
+#define DTLK_MAX_RETRIES (loops_per_sec/10000)
+
+	/* TTS Port Status Flags */
+#define TTS_READABLE     0x80	/* mask for bit which is nonzero if a
+				   byte can be read from the TTS port */
+#define TTS_SPEAKING     0x40	/* mask for SYNC bit, which is nonzero
+				   while DoubleTalk is producing
+				   output with TTS, PCM or CVSD
+				   synthesizers or tone generators
+				   (that is, all but LPC) */
+#define TTS_SPEAKING2    0x20	/* mask for SYNC2 bit,
+				   which falls to zero up to 0.4 sec
+				   before speech stops */
+#define TTS_WRITABLE     0x10	/* mask for RDY bit, which when set to
+             			   1, indicates the TTS port is ready
+             			   to accept a byte of data.  The RDY
+             			   bit goes zero 2-3 usec after
+             			   writing, and goes 1 again 180-190
+             			   usec later. */
+#define TTS_ALMOST_FULL  0x08	/* mask for AF bit: When set to 1,
+				   indicates that less than 300 free
+				   bytes are available in the TTS
+				   input buffer. AF is always 0 in the
+				   PCM, TGN and CVSD modes. */
+#define TTS_ALMOST_EMPTY 0x04	/* mask for AE bit: When set to 1,
+				   indicates that less than 300 bytes
+				   of data remain in DoubleTalk's
+				   input (TTS or PCM) buffer. AE is
+				   always 1 in the TGN and CVSD
+				   modes. */
+
+	/* LPC speak commands */
+#define LPC_5220_NORMAL 0x60	/* 5220 format decoding table, normal rate */
+#define LPC_5220_FAST 0x64	/* 5220 format decoding table, fast rate */
+#define LPC_D6_NORMAL 0x20	/* D6 format decoding table, normal rate */
+#define LPC_D6_FAST 0x24	/* D6 format decoding table, fast rate */
+
+	/* LPC Port Status Flags (valid only after one of the LPC
+           speak commands) */
+#define LPC_SPEAKING     0x80	/* mask for TS bit: When set to 1,
+				   indicates the LPC synthesizer is
+				   producing speech.*/
+#define LPC_BUFFER_LOW   0x40	/* mask for BL bit: When set to 1,
+				   indicates that the hardware LPC
+				   data buffer has less than 30 bytes
+				   remaining. (Total internal buffer
+				   size = 4096 bytes.) */
+#define LPC_BUFFER_EMPTY 0x20	/* mask for BE bit: When set to 1,
+				   indicates that the LPC data buffer
+				   ran out of data (error condition if
+				   TS is also 1).  */
+
+				/* data returned by Interrogate command */
+struct dtlk_settings
+{
+  unsigned short serial_number;	/* 0-7Fh:0-7Fh */
+  unsigned char rom_version[24]; /* null terminated string */
+  unsigned char mode;		/* 0=Character; 1=Phoneme; 2=Text */
+  unsigned char punc_level;	/* nB; 0-7 */
+  unsigned char formant_freq;	/* nF; 0-9 */
+  unsigned char pitch;		/* nP; 0-99 */
+  unsigned char speed;		/* nS; 0-9 */
+  unsigned char volume;		/* nV; 0-9 */
+  unsigned char tone;		/* nX; 0-2 */
+  unsigned char expression;	/* nE; 0-9 */
+  unsigned char ext_dict_loaded; /* 1=exception dictionary loaded */
+  unsigned char ext_dict_status; /* 1=exception dictionary enabled */
+  unsigned char free_ram;	/* # pages (truncated) remaining for
+                                   text buffer */
+  unsigned char articulation;	/* nA; 0-9 */
+  unsigned char reverb;		/* nR; 0-9 */
+  unsigned char eob;		/* 7Fh value indicating end of
+                                   parameter block */
+  unsigned char has_indexing;	/* nonzero if indexing is implemented */
+};
diff -u --recursive --new-file v2.2.2/linux/include/linux/fb.h linux/include/linux/fb.h
--- v2.2.2/linux/include/linux/fb.h	Tue Dec 22 14:16:58 1998
+++ linux/include/linux/fb.h	Thu Feb 25 10:02:12 1999
@@ -67,6 +67,10 @@
 #define FB_ACCEL_MATROX_MGA2164W_AGP 19	/* Matrox MGA2164W (Millenium II) */
 #define FB_ACCEL_MATROX_MGAG100	20	/* Matrox G100 (Productiva G100) */
 #define FB_ACCEL_MATROX_MGAG200	21	/* Matrox G200 (Myst, Mill, ...) */
+#define FB_ACCEL_SUN_CG14	22	/* Sun cgfourteen		 */
+#define FB_ACCEL_SUN_BWTWO	23	/* Sun bwtwo			 */
+#define FB_ACCEL_SUN_CGTHREE	24	/* Sun cgthree			 */
+#define FB_ACCEL_SUN_TCX	25	/* Sun tcx			 */
 
 struct fb_fix_screeninfo {
 	char id[16];			/* identification string eg "TT Builtin" */
@@ -340,8 +344,8 @@
     int (*pan_display)(const struct fb_var_screeninfo *var,
 		       struct fb_info_gen *info);
     int (*blank)(int blank_mode, struct fb_info_gen *info);
-    void (*set_dispsw)(const void *par, struct display *disp,
-		       struct fb_info_gen *info);
+    void (*set_disp)(const void *par, struct display *disp,
+		     struct fb_info_gen *info);
 };
 
 struct fb_info_gen {
diff -u --recursive --new-file v2.2.2/linux/include/linux/filter.h linux/include/linux/filter.h
--- v2.2.2/linux/include/linux/filter.h	Sun Dec 21 17:41:24 1997
+++ linux/include/linux/filter.h	Mon Mar  8 13:05:01 1999
@@ -18,18 +18,32 @@
  
 struct sock_filter	/* Filter block */
 {
-        u16	code;   /* Actual filter code */
-        u8	jt;	/* Jump true */
-        u8	jf;	/* Jump false */
-        u32	k;      /* Generic multiuse field */
+        __u16	code;   /* Actual filter code */
+        __u8	jt;	/* Jump true */
+        __u8	jf;	/* Jump false */
+        __u32	k;      /* Generic multiuse field */
 };
 
 struct sock_fprog	/* Required for SO_ATTACH_FILTER. */
 {
-        unsigned short         len;	/* Number of filter blocks */
-        struct sock_filter     *filter;
+	unsigned short		len;	/* Number of filter blocks */
+	struct sock_filter	*filter;
 };
 
+#ifdef __KERNEL__
+struct sk_filter
+{
+	atomic_t		refcnt;
+        unsigned int         	len;	/* Number of filter blocks */
+        struct sock_filter     	insns[0];
+};
+
+extern __inline__ unsigned int sk_filter_len(struct sk_filter *fp)
+{
+	return fp->len*sizeof(struct sock_filter) + sizeof(*fp);
+}
+#endif
+
 /*
  * Instruction classes
  */
@@ -86,21 +100,40 @@
 #define         BPF_TAX         0x00
 #define         BPF_TXA         0x80
 
-#define BPF_MAXINSNS 512
+#ifndef BPF_MAXINSNS
+#define BPF_MAXINSNS 4096
+#endif
 
 /*
  * Macros for filter block array initializers.
  */
+#ifndef BPF_STMT
 #define BPF_STMT(code, k) { (unsigned short)(code), 0, 0, k }
+#endif
+#ifndef BPF_JUMP
 #define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }
+#endif
 
 /*
  * Number of scratch memory words for: BPF_ST and BPF_STX
  */
 #define BPF_MEMWORDS 16
 
+/* RATIONALE. Negative offsets are invalid in BPF.
+   We use them to reference ancillary data.
+   Unlike introduction new instructions, it does not break
+   existing compilers/optimizers.
+ */
+#define SKF_AD_OFF    (-0x1000)
+#define SKF_AD_PROTOCOL 0
+#define SKF_AD_PKTTYPE 	4
+#define SKF_AD_IFINDEX 	8
+#define SKF_AD_MAX 	12
+#define SKF_NET_OFF   (-0x100000)
+#define SKF_LL_OFF    (-0x200000)
+
 #ifdef __KERNEL__
-extern int sk_run_filter(unsigned char *data, int len, struct sock_filter *filter, int flen);
+extern int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen);
 extern int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk);
 #endif /* __KERNEL__ */
 
diff -u --recursive --new-file v2.2.2/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.2.2/linux/include/linux/fs.h	Tue Feb 23 15:21:35 1999
+++ linux/include/linux/fs.h	Mon Mar  8 15:51:33 1999
@@ -373,6 +373,7 @@
 
 	int			i_writecount;
 	unsigned int		i_attr_flags;
+	__u32			i_generation;
 	union {
 		struct pipe_inode_info		pipe_i;
 		struct minix_inode_info		minix_i;
@@ -424,6 +425,8 @@
 	unsigned int 		f_count, f_flags;
 	unsigned long 		f_reada, f_ramax, f_raend, f_ralen, f_rawin;
 	struct fown_struct	f_owner;
+	unsigned int		f_uid, f_gid;
+	int			f_error;
 
 	unsigned long		f_version;
 
diff -u --recursive --new-file v2.2.2/linux/include/linux/if_shaper.h linux/include/linux/if_shaper.h
--- v2.2.2/linux/include/linux/if_shaper.h	Tue Aug 18 22:02:07 1998
+++ linux/include/linux/if_shaper.h	Wed Feb 24 16:27:53 1999
@@ -23,7 +23,7 @@
 	__u32 shapeclock;
 	__u32 recovery;		/* Time we can next clock a packet out on
 				   an empty queue */
-	char locked;
+	unsigned long locked;
 	struct device *dev;
 	int  (*hard_start_xmit) (struct sk_buff *skb,
 		struct device *dev);
diff -u --recursive --new-file v2.2.2/linux/include/linux/miscdevice.h linux/include/linux/miscdevice.h
--- v2.2.2/linux/include/linux/miscdevice.h	Thu Mar 26 15:57:05 1998
+++ linux/include/linux/miscdevice.h	Sun Mar  7 15:25:23 1999
@@ -16,7 +16,7 @@
 #define RTC_MINOR 135
 #define SUN_OPENPROM_MINOR 139
 #define NVRAM_MINOR 144
-#define RADIO_MINOR 152
+#define I2O_MINOR 166
 #define MISC_DYNAMIC_MINOR 255
 
 extern int misc_init(void);
diff -u --recursive --new-file v2.2.2/linux/include/linux/mm.h linux/include/linux/mm.h
--- v2.2.2/linux/include/linux/mm.h	Wed Jan 20 23:14:06 1999
+++ linux/include/linux/mm.h	Mon Mar  8 15:51:40 1999
@@ -177,10 +177,12 @@
 			(test_and_clear_bit(PG_swap_cache, &(page)->flags))
 
 /*
- * page->reserved denotes a page which must never be accessed (which
+ * Various page->flags bits:
+ *
+ * PG_reserved is set for a page which must never be accessed (which
  * may not even be present).
  *
- * page->dma is set for those pages which lie in the range of
+ * PG_DMA is set for those pages which lie in the range of
  * physical addresses capable of carrying DMA transfers.
  *
  * Multiple processes may "see" the same page. E.g. for untouched
@@ -204,8 +206,8 @@
  * The following discussion applies only to them.
  *
  * A page may belong to an inode's memory mapping. In this case,
- * page->inode is the inode, and page->offset is the file offset
- * of the page (not necessarily a multiple of PAGE_SIZE).
+ * page->inode is the pointer to the inode, and page->offset is the
+ * file offset of the page (not necessarily a multiple of PAGE_SIZE).
  *
  * A page may have buffers allocated to it. In this case,
  * page->buffers is a circular list of these buffer heads. Else,
@@ -219,7 +221,7 @@
  * fields are also used for freelist management when page->count==0.)
  * There is also a hash table mapping (inode,offset) to the page
  * in memory if present. The lists for this hash table use the fields
- * page->next_hash and page->prev_hash.
+ * page->next_hash and page->pprev_hash.
  *
  * All process pages can do I/O:
  * - inode pages may need to be read from disk,
@@ -227,18 +229,23 @@
  *   to be written to disk,
  * - private pages which have been modified may need to be swapped out
  *   to swap space and (later) to be read back into memory.
- * During disk I/O, page->locked is true. This bit is set before I/O
+ * During disk I/O, PG_locked is used. This bit is set before I/O
  * and reset when I/O completes. page->wait is a wait queue of all
  * tasks waiting for the I/O on this page to complete.
- * page->uptodate tells whether the page's contents is valid.
+ * PG_uptodate tells whether the page's contents is valid.
  * When a read completes, the page becomes uptodate, unless a disk I/O
  * error happened.
- * When a write completes, and page->free_after is true, the page is
+ * When a write completes, and PG_free_after is set, the page is
  * freed without any further delay.
  *
  * For choosing which pages to swap out, inode pages carry a
- * page->referenced bit, which is set any time the system accesses
+ * PG_referenced bit, which is set any time the system accesses
  * that page through the (inode,offset) hash table.
+ *
+ * PG_skip is used on sparc/sparc64 architectures to "skip" certain
+ * parts of the address space.
+ *
+ * PG_error is set to indicate that an I/O error occurred on this page.
  */
 
 extern mem_map_t * mem_map;
@@ -340,11 +347,6 @@
 
 #define GFP_DMA		__GFP_DMA
 
-/*
- * Decide if we should try to do some swapout..
- */
-extern int free_memory_available(void);
-			
 /* vma is the first one with  address < vma->vm_end,
  * and even  address < vma->vm_start. Have to extend vma. */
 static inline int expand_stack(struct vm_area_struct * vma, unsigned long address)
diff -u --recursive --new-file v2.2.2/linux/include/linux/nbd.h linux/include/linux/nbd.h
--- v2.2.2/linux/include/linux/nbd.h	Mon Sep 28 10:51:35 1998
+++ linux/include/linux/nbd.h	Mon Mar  8 13:05:11 1999
@@ -8,6 +8,7 @@
 #define NBD_CLEAR_SOCK	_IO( 0xab, 4 )
 #define NBD_CLEAR_QUE	_IO( 0xab, 5 )
 #define NBD_PRINT_DEBUG	_IO( 0xab, 6 )
+#define NBD_SET_SIZE_BLOCKS	_IO( 0xab, 7 )
 
 #ifdef MAJOR_NR
 
@@ -60,13 +61,21 @@
 #define NBD_REPLY_MAGIC 0x67446698
 /* Do *not* use magics: 0x12560953 0x96744668. */
 
+/*
+ * This is packet used for communication between client and
+ * server. All data are in network byte order.
+ */
 struct nbd_request {
 	u32 magic;
 	u32 type;	/* == READ || == WRITE 	*/
 	char handle[8];
 	u64 from;
 	u32 len;
-};
+}
+#ifdef __GNUC__
+	__attribute__ ((packed))
+#endif
+;
 
 struct nbd_reply {
 	u32 magic;
diff -u --recursive --new-file v2.2.2/linux/include/linux/nfs.h linux/include/linux/nfs.h
--- v2.2.2/linux/include/linux/nfs.h	Fri Jan 30 11:28:10 1998
+++ linux/include/linux/nfs.h	Sat Mar  6 14:21:13 1999
@@ -41,6 +41,7 @@
 	NFSERR_FBIG = 27,
 	NFSERR_NOSPC = 28,
 	NFSERR_ROFS = 30,
+	NFSERR_OPNOTSUPP = 45,
 	NFSERR_NAMETOOLONG = 63,
 	NFSERR_NOTEMPTY = 66,
 	NFSERR_DQUOT = 69,
diff -u --recursive --new-file v2.2.2/linux/include/linux/nfs_fs.h linux/include/linux/nfs_fs.h
--- v2.2.2/linux/include/linux/nfs_fs.h	Tue Dec 22 14:16:58 1998
+++ linux/include/linux/nfs_fs.h	Mon Mar  8 15:51:37 1999
@@ -98,8 +98,7 @@
 struct nfs_wreq {
 	struct rpc_listitem	wb_list;	/* linked list of req's */
 	struct rpc_task		wb_task;	/* RPC task */
-	struct dentry *		wb_dentry;	/* dentry referenced */
-	struct inode *		wb_inode;	/* inode referenced */
+	struct file *		wb_file;	/* dentry referenced */
 	struct page *		wb_page;	/* page to be written */
 	struct wait_queue *	wb_wait;	/* wait for completion */
 	unsigned int		wb_offset;	/* offset within page */
@@ -213,7 +212,6 @@
  */
 extern int  nfs_writepage(struct file *, struct page *);
 extern int  nfs_check_failed_request(struct inode *);
-extern int  nfs_check_error(struct inode *);
 
 /*
  * Try to write back everything synchronously (but check the
@@ -221,8 +219,7 @@
  */
 extern int  nfs_wb_all(struct inode *);
 extern int  nfs_wb_page(struct inode *, struct page *);
-extern int  nfs_wb_pid(struct inode *, pid_t);
-extern int  nfs_flush_trunc(struct inode *, unsigned long);
+extern int  nfs_wb_file(struct inode *, struct file *);
 
 /*
  * Invalidate write-backs, possibly trying to write them
@@ -252,12 +249,6 @@
 	if (jiffies - NFS_READTIME(inode) < NFS_ATTRTIMEO(inode))
 		return 0;
 	return _nfs_revalidate_inode(server, dentry);
-}
-
-static inline int
-nfs_write_error(struct inode *inode)
-{
-	return NFS_WRITEBACK(inode) && nfs_check_error(inode);
 }
 
 /* NFS root */
diff -u --recursive --new-file v2.2.2/linux/include/linux/pci.h linux/include/linux/pci.h
--- v2.2.2/linux/include/linux/pci.h	Tue Jan 19 11:32:53 1999
+++ linux/include/linux/pci.h	Mon Mar  8 15:51:32 1999
@@ -3,7 +3,7 @@
  *
  *	PCI defines and function prototypes
  *	Copyright 1994, Drew Eckhardt
- *	Copyright 1997, 1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ *	Copyright 1997--1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
  *
  *	For more information, please consult the following manuals (look at
  *	http://www.pcisig.com/ for how to get them):
@@ -36,9 +36,9 @@
 #define  PCI_COMMAND_FAST_BACK	0x200	/* Enable back-to-back writes */
 
 #define PCI_STATUS		0x06	/* 16 bits */
+#define  PCI_STATUS_CAP_LIST	0x10	/* Support Capability List */
 #define  PCI_STATUS_66MHZ	0x20	/* Support 66 Mhz PCI 2.1 bus */
 #define  PCI_STATUS_UDF		0x40	/* Support User Definable Features */
-
 #define  PCI_STATUS_FAST_BACK	0x80	/* Accept fast-back to back */
 #define  PCI_STATUS_PARITY	0x100	/* Detected parity error */
 #define  PCI_STATUS_DEVSEL_MASK	0x600	/* DEVSEL timing */
@@ -101,7 +101,9 @@
 #define  PCI_ROM_ADDRESS_ENABLE	0x01
 #define PCI_ROM_ADDRESS_MASK	(~0x7ffUL)
 
-/* 0x34-0x3b are reserved */
+#define PCI_CAPABILITY_LIST	0x34	/* Offset of first capability list entry */
+
+/* 0x35-0x3b are reserved */
 #define PCI_INTERRUPT_LINE	0x3c	/* 8 bits */
 #define PCI_INTERRUPT_PIN	0x3d	/* 8 bits */
 #define PCI_MIN_GNT		0x3e	/* 8 bits */
@@ -182,6 +184,12 @@
 #define PCI_CB_LEGACY_MODE_BASE	0x44	/* 16-bit PC Card legacy mode base address (ExCa) */
 /* 0x48-0x7f reserved */
 
+/* Capability lists */
+#define PCI_CAP_LIST_ID		0	/* Capability ID */
+#define  PCI_CAP_ID_PM		0x01	/* Power Management */
+#define  PCI_CAP_ID_AGP		0x02	/* Accelerated Graphics Port */
+#define PCI_CAP_LIST_NEXT	1	/* Next capability in the list */
+
 /* Device classes and subclasses */
 
 #define PCI_CLASS_NOT_DEFINED		0x0000
@@ -356,6 +364,7 @@
 #define PCI_DEVICE_ID_DEC_21052		0x0021
 #define PCI_DEVICE_ID_DEC_21150		0x0022
 #define PCI_DEVICE_ID_DEC_21152		0x0024
+#define PCI_DEVICE_ID_DEC_21153		0x0025
 
 #define PCI_VENDOR_ID_CIRRUS		0x1013
 #define PCI_DEVICE_ID_CIRRUS_7548	0x0038
@@ -949,6 +958,9 @@
 #define PCI_VENDOR_ID_CBOARDS		0x1307
 #define PCI_DEVICE_ID_CBOARDS_DAS1602_16 0x0001
 
+#define PCI_VENDOR_ID_NETGEAR		0x1385
+#define PCI_DEVICE_ID_NETGEAR_GA620	0x620a
+
 #define PCI_VENDOR_ID_SYMPHONY		0x1c1c
 #define PCI_DEVICE_ID_SYMPHONY_101	0x0001
 
@@ -1031,6 +1043,7 @@
 #define PCI_DEVICE_ID_INTEL_82443BX_2	0x7192
 #define PCI_DEVICE_ID_INTEL_P6		0x84c4
 #define PCI_DEVICE_ID_INTEL_82450GX	0x84c5
+#define PCI_DEVICE_ID_INTEL_82451NX	0x84ca
 
 #define PCI_VENDOR_ID_KTI		0x8e2e
 #define PCI_DEVICE_ID_KTI_ET32P2	0x3000
@@ -1197,6 +1210,7 @@
 void pci_setup(char *str, int *ints);
 void pci_quirks_init(void);
 unsigned int pci_scan_bus(struct pci_bus *bus);
+struct pci_bus *pci_scan_peer_bridge(int bus);
 void pci_proc_init(void);
 void proc_old_pci_init(void);
 int get_pci_list(char *buf);
diff -u --recursive --new-file v2.2.2/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- v2.2.2/linux/include/linux/proc_fs.h	Wed Jan 13 15:00:44 1999
+++ linux/include/linux/proc_fs.h	Mon Mar  8 15:51:59 1999
@@ -184,6 +184,7 @@
 	PROC_SCSI_AM53C974,
 	PROC_SCSI_SSC,
 	PROC_SCSI_NCR53C406A,
+	PROC_SCSI_SYM53C416,
 	PROC_SCSI_MEGARAID,
 	PROC_SCSI_PPA,
 	PROC_SCSI_ATP870U,
@@ -202,6 +203,7 @@
 	PROC_SCSI_53C94,
 	PROC_SCSI_PLUTO,
 	PROC_SCSI_INI9100U,
+	PROC_SCSI_INIA100,
 	PROC_SCSI_SCSI_DEBUG,	
 	PROC_SCSI_NOT_PRESENT,
 	PROC_SCSI_FILE,                        /* I'm assuming here that we */
diff -u --recursive --new-file v2.2.2/linux/include/linux/sched.h linux/include/linux/sched.h
--- v2.2.2/linux/include/linux/sched.h	Tue Feb 23 15:21:35 1999
+++ linux/include/linux/sched.h	Mon Mar  8 15:51:37 1999
@@ -672,6 +672,58 @@
 	write_unlock_irqrestore(&waitqueue_lock, flags); 
 }
 
+#define __wait_event(wq, condition) 					\
+do {									\
+	struct wait_queue __wait;					\
+									\
+	__wait.task = current;						\
+	add_wait_queue(&wq, &__wait);					\
+	for (;;) {							\
+		current->state = TASK_UNINTERRUPTIBLE;			\
+		if (condition)						\
+			break;						\
+		schedule();						\
+	}								\
+	current->state = TASK_RUNNING;					\
+	remove_wait_queue(&wq, &__wait);				\
+} while (0)
+
+#define wait_event(wq, condition) 					\
+do {									\
+	if (condition)	 						\
+		break;							\
+	__wait_event(wq, condition);					\
+} while (0)
+
+#define __wait_event_interruptible(wq, condition, ret)			\
+do {									\
+	struct wait_queue __wait;					\
+									\
+	__wait.task = current;						\
+	add_wait_queue(&wq, &__wait);					\
+	for (;;) {							\
+		current->state = TASK_INTERRUPTIBLE;			\
+		if (condition)						\
+			break;						\
+		if (!signal_pending(current)) {				\
+			schedule();					\
+			continue;					\
+		}							\
+		ret = -ERESTARTSYS;					\
+		break;							\
+	}								\
+	current->state = TASK_RUNNING;					\
+	remove_wait_queue(&wq, &__wait);				\
+} while (0)
+	
+#define wait_event_interruptible(wq, condition)				\
+({									\
+	int __ret = 0;							\
+	if (!(condition))						\
+		__wait_event_interruptible(wq, condition, __ret);	\
+	__ret;								\
+})
+
 #define REMOVE_LINKS(p) do { \
 	(p)->next_task->prev_task = (p)->prev_task; \
 	(p)->prev_task->next_task = (p)->next_task; \
diff -u --recursive --new-file v2.2.2/linux/include/linux/selection.h linux/include/linux/selection.h
--- v2.2.2/linux/include/linux/selection.h	Mon Sep 28 10:51:35 1998
+++ linux/include/linux/selection.h	Mon Mar  8 15:51:33 1999
@@ -38,7 +38,7 @@
 extern void getconsxy(int currcons, char *p);
 extern void putconsxy(int currcons, char *p);
 
-extern u16 vcs_scr_readw(int currcons, u16 *org);
+extern u16 vcs_scr_readw(int currcons, const u16 *org);
 extern void vcs_scr_writew(int currcons, u16 val, u16 *org);
 
 #endif
diff -u --recursive --new-file v2.2.2/linux/include/linux/vt_buffer.h linux/include/linux/vt_buffer.h
--- v2.2.2/linux/include/linux/vt_buffer.h	Mon Sep 28 10:51:36 1998
+++ linux/include/linux/vt_buffer.h	Mon Mar  8 15:51:32 1999
@@ -41,7 +41,7 @@
 #endif
 
 #ifndef VT_BUF_HAVE_MEMCPYW
-extern inline void scr_memcpyw(u16 *d, u16 *s, unsigned int count)
+extern inline void scr_memcpyw(u16 *d, const u16 *s, unsigned int count)
 {
 	count /= 2;
 	while (count--)
@@ -50,7 +50,7 @@
 #endif
 
 #ifndef VT_BUF_HAVE_MEMMOVEW
-extern inline void scr_memmovew(u16 *d, u16 *s, unsigned int count)
+extern inline void scr_memmovew(u16 *d, const u16 *s, unsigned int count)
 {
 	if (d < s)
 		scr_memcpyw(d, s, count);
@@ -65,14 +65,14 @@
 #endif
 
 #ifndef VT_BUF_HAVE_MEMCPYF
-extern inline void scr_memcpyw_from(u16 *d, u16 *s, unsigned int count)
+extern inline void scr_memcpyw_from(u16 *d, const u16 *s, unsigned int count)
 {
 	count /= 2;
 	while (count--)
 		*d++ = scr_readw(s++);
 }
 
-extern inline void scr_memcpyw_to(u16 *d, u16 *s, unsigned int count)
+extern inline void scr_memcpyw_to(u16 *d, const u16 *s, unsigned int count)
 {
 	count /= 2;
 	while (count--)
diff -u --recursive --new-file v2.2.2/linux/include/linux/zorro.h linux/include/linux/zorro.h
--- v2.2.2/linux/include/linux/zorro.h	Thu Nov 12 16:21:24 1998
+++ linux/include/linux/zorro.h	Thu Feb 25 10:02:12 1999
@@ -301,7 +301,7 @@
 #define  ZORRO_PROD_BSC_MULTIFACE_I				ZORRO_ID(BSC_ALFADATA_3, 0x10, 0)
 #define  ZORRO_PROD_BSC_MULTIFACE_II				ZORRO_ID(BSC_ALFADATA_3, 0x11, 0)
 #define  ZORRO_PROD_BSC_MULTIFACE_III				ZORRO_ID(BSC_ALFADATA_3, 0x12, 0)
-#define  ZORRO_PROD_BSC_FRAMEBUFFER				ZORRO_ID(BSC_ALFADATA_3, 0x20, 0)
+#define  ZORRO_PROD_BSC_FRAMEMASTER_II				ZORRO_ID(BSC_ALFADATA_3, 0x20, 0)
 #define  ZORRO_PROD_BSC_GRAFFITI_RAM				ZORRO_ID(BSC_ALFADATA_3, 0x21, 0)
 #define  ZORRO_PROD_BSC_GRAFFITI_REG				ZORRO_ID(BSC_ALFADATA_3, 0x22, 0)
 #define  ZORRO_PROD_BSC_ISDN_MASTERCARD				ZORRO_ID(BSC_ALFADATA_3, 0x40, 0)
diff -u --recursive --new-file v2.2.2/linux/include/net/br.h linux/include/net/br.h
--- v2.2.2/linux/include/net/br.h	Fri Jan  8 22:36:25 1999
+++ linux/include/net/br.h	Sun Mar  7 15:25:23 1999
@@ -258,6 +258,7 @@
 #define BR_UP		0x0001	/* bridging enabled */
 #define BR_DEBUG	0x0002	/* debugging enabled */
 #define BR_PROT_STATS	0x0004	/* protocol statistics enabled */
+#define BR_STP_DISABLED	0x0008	/* Spanning tree protocol disabled */
 
 struct br_cf {
 	unsigned int cmd;
@@ -281,6 +282,7 @@
 #define BRCMD_ENABLE_PROT_STATS	13
 #define BRCMD_DISABLE_PROT_STATS 14
 #define BRCMD_ZERO_PROT_STATS	15
+#define BRCMD_TOGGLE_STP	16
 
 /* prototypes of exported bridging functions... */
 
@@ -295,7 +297,7 @@
 struct fdb *br_avl_insert (struct fdb * new_node);
 void sprintf_avl (char **pbuffer, struct fdb * tree, off_t *pos,int* len, off_t offset, int length);
 int br_tree_get_info(char *buffer, char **start, off_t offset, int length, int dummy);
-
+void br_avl_delete_by_port(int port);
 /* externs */
 
 extern struct br_stat br_stats;
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/dongle.h linux/include/net/irda/dongle.h
--- v2.2.2/linux/include/net/irda/dongle.h	Tue Dec 22 14:16:58 1998
+++ linux/include/net/irda/dongle.h	Sun Mar  7 15:26:43 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Wed Oct 21 22:47:12 1998
- * Modified at:   Mon Dec 14 11:47:25 1998
+ * Modified at:   Sat Feb  6 07:37:49 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -34,6 +34,7 @@
 	ESI_DONGLE,
 	ACTISYS_DONGLE,
 	ACTISYS_PLUS_DONGLE,
+	GIRBIL_DONGLE,
 } DONGLE_T;
 
 struct dongle {
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/ircomm_common.h linux/include/net/irda/ircomm_common.h
--- v2.2.2/linux/include/net/irda/ircomm_common.h	Tue Dec 22 14:16:58 1998
+++ linux/include/net/irda/ircomm_common.h	Sun Mar  7 15:26:43 1999
@@ -149,6 +149,7 @@
 	int max_txbuff_size;          
 	int maxsdusize;
  	__u32 daddr;        /* Device address of the peer device */ 
+	__u32 saddr;
 
 	void (*d_handler)(struct ircomm_cb *self);
 	struct notify_t notify;     /* container of callbacks */
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/irda.h linux/include/net/irda/irda.h
--- v2.2.2/linux/include/net/irda/irda.h	Mon Jan 25 17:44:34 1999
+++ linux/include/net/irda/irda.h	Sun Mar  7 15:26:43 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Dec  9 21:13:12 1997
- * Modified at:   Sat Jan 16 01:23:15 1999
+ * Modified at:   Wed Jan 27 14:15:50 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -44,7 +44,7 @@
 
 extern __u32 irda_debug;
 
-#define IRDA_DEBUG 3
+#define IRDA_DEBUG 0
 
 #define DEBUG(n, args...) if (irda_debug >= (n)) printk( KERN_DEBUG args)
 #define ASSERT(expr, func) \
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/irda_device.h linux/include/net/irda/irda_device.h
--- v2.2.2/linux/include/net/irda/irda_device.h	Wed Jan 20 23:14:06 1999
+++ linux/include/net/irda/irda_device.h	Sun Mar  7 15:26:43 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Haris Zukanovic <haris@stud.cs.uit.no>
  * Created at:    Tue Apr 14 12:41:42 1998
- * Modified at:   Mon Jan 18 10:52:10 1999
+ * Modified at:   Tue Feb  9 14:01:50 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Haris Zukanovic, <haris@stud.cs.uit.no>
@@ -35,11 +35,13 @@
 #include <net/irda/qos.h>
 #include <net/irda/irqueue.h>
 
-#define SIR_MODE 	0x01
-#define MIR_MODE 	0x02
-#define FIR_MODE 	0x04
-#define IO_PIO   	0x08
-#define IO_DMA		0x10
+/* Some non-standard interface flags (should not conflict with any in if.h */
+#define IFF_SIR 	0x01 /* Supports SIR speeds */
+#define IFF_MIR 	0x02 /* Supports MIR speeds */
+#define IFF_FIR 	0x04 /* Supports FIR speeds */
+#define IFF_PIO   	0x08 /* Supports PIO transfer of data */
+#define IFF_DMA		0x10 /* Supports DMA transfer of data */
+#define IFF_DONGLE      0x20 /* Interface has a dongle attached */
 
 #define IO_XMIT 0x01
 #define IO_RECV 0x02
@@ -93,7 +95,7 @@
 	struct device netdev;   /* Yes! we are some kind of netdevice */
 	struct enet_statistics stats;
 
-/* 	int flags; */
+ 	int flags;            /* Interface flags (see defs above) */
 
  	void *priv;           /* Pointer to low level implementation */
 
@@ -103,6 +105,7 @@
 	struct iobuff_t tx_buff;
 	struct iobuff_t rx_buff;
 
+	int xbofs;
 	int media_busy;
 	
 	/* Media busy stuff */
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/iriap.h linux/include/net/irda/iriap.h
--- v2.2.2/linux/include/net/irda/iriap.h	Tue Dec 22 14:16:58 1998
+++ linux/include/net/irda/iriap.h	Sun Mar  7 15:26:43 1999
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      iriap.h
- * Version:       
+ * Version:       0.5
  * Description:   Information Access Protocol (IAP)
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Aug 21 00:02:07 1997
- * Modified at:   Sat Dec  5 13:45:37 1998
+ * Modified at:   Tue Jan 26 11:50:33 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -55,23 +55,13 @@
 typedef void (*CONFIRM_CALLBACK)( __u16 obj_id, struct ias_value *value,
 				  void *priv);
 
-struct iap_value {
-	char *full;
-        char *name;
-        char *attr;
-        __u16   obj_id;
-        __u8    ret_code;
-        __u8    type;
-        int     len;
-        int value_int;
-        char *value_char;
-};
-
 struct iriap_cb {
 	QUEUE queue; /* Must be first */
 	
 	int          magic;  /* Magic cookie */
 	int          mode;   /* Client or server */
+
+	__u32        saddr;
 	__u32        daddr;
 	__u8         operation;
 
@@ -95,10 +85,10 @@
 
 int  iriap_init(void);
 void iriap_cleanup(void);
-void iriap_getvaluebyclass_request( __u32 addr, char *name, char *attr, 
+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);
+void iriap_getvaluebyclass_confirm(struct iriap_cb *self, struct sk_buff *skb);
 
 void iriap_send_ack( struct iriap_cb *self);
 void iriap_data_indication( void *instance, void *sap, struct sk_buff *skb);
@@ -121,3 +111,5 @@
 }
 
 #endif
+
+
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/irias_object.h linux/include/net/irda/irias_object.h
--- v2.2.2/linux/include/net/irda/irias_object.h	Tue Dec 22 14:16:58 1998
+++ linux/include/net/irda/irias_object.h	Sun Mar  7 15:26:43 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Oct  1 22:49:50 1998
- * Modified at:   Sun Oct 25 00:28:56 1998
+ * Modified at:   Wed Feb  3 10:38:02 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -25,7 +25,7 @@
 #ifndef LM_IAS_OBJECT_H
 #define LM_IAS_OBJECT_H
 
-#include "irqueue.h"
+#include <net/irda/irqueue.h>
 
 /* LM-IAS Attribute types */
 #define IAS_MISSING 0
@@ -38,12 +38,10 @@
  */
 struct ias_object {
 	QUEUE queue;     /* Must be first! */
-
 	int magic;
 	
 	char  *name;
 	int   id;
-
 	hashbin_t *attribs;
 };
 
@@ -51,8 +49,7 @@
  *  Values used by LM-IAS attributes
  */
 struct ias_value {
-	/* Value description */
-        __u8    type;
+        __u8    type;    /* Value description */
 	int     charset; /* Only used by string type */
         int     len;
 	
@@ -68,16 +65,11 @@
  *  Attributes used by LM-IAS objects
  */
 struct ias_attrib {
-	QUEUE queue;     /* Must be first! */
-
+	QUEUE queue; /* Must be first! */
 	int magic;
 
-	/* Attribute name */
-        char *name;
- /*        char *attr; What do we need this for?  */
-
-	/* Attribute value */
-	struct ias_value *value;
+        char *name;   	         /* Attribute name */
+	struct ias_value *value; /* Attribute value */
 };
 
 char *strdup( char *str);
@@ -87,12 +79,12 @@
 void __irias_delete_object( struct ias_object *obj);
 void irias_delete_object( char *name);
 
-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);
-void irias_add_octseq_attrib( struct ias_object *obj, char *name, 
-			      __u8 *octets, int len);
+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);
+void irias_add_octseq_attrib(struct ias_object *obj, char *name, __u8 *octets,
+			     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);
 
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/irlan_cli.h linux/include/net/irda/irlan_cli.h
--- v2.2.2/linux/include/net/irda/irlan_cli.h	Tue Dec 22 14:16:58 1998
+++ linux/include/net/irda/irlan_cli.h	Wed Dec 31 16:00:00 1969
@@ -1,65 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      client.h
- * Version:       0.3
- * Description:   IrDA LAN access layer
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Mon Oct 19 12:37:20 1998
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     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.
- *
- *     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 IRLAN_CLIENT_H
-#define IRLAN_CLIENT_H
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-
-int  irlan_client_init(void);
-void irlan_client_cleanup(void);
-
-void irlan_discovery_indication( DISCOVERY*);
-void irlan_client_disconnect_indication( void *instance, void *sap, 
-					 LM_REASON reason, struct sk_buff *);
-
-void irlan_client_data_indication( void *instance, void *sap, 
-				   struct sk_buff *skb);
-
-void irlan_client_control_data_indication( void *instance, void *sap, 
-					   struct sk_buff *skb);
-
-void irlan_client_connect_confirm( void *instance, void *sap, 
-				   struct qos_info *qos, int max_sdu_size,
-				   struct sk_buff *);
-void irlan_client_connect_indication( void *instance, void *sap, 
-				      struct sk_buff *);
-void irlan_client_connect_response( void *instance, void *sap, 
-				    int max_sdu_size, struct sk_buff *skb);
-
-void irlan_client_open_tsaps( struct irlan_cb *self);
-
-void irlan_client_extract_params( struct irlan_cb *self, 
-				  struct sk_buff *skb);
-void check_response_param( struct irlan_cb *self, char *param, 
-			   char *value, int val_len);
-void handle_request( struct irlan_cb *self);
-void irlan_client_register_server(void);
-void irlan_client_get_value_confirm( __u16 obj_id, struct ias_value *value, 
-				     void *priv);
-
-#endif
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/irlan_client.h linux/include/net/irda/irlan_client.h
--- v2.2.2/linux/include/net/irda/irlan_client.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irlan_client.h	Sun Mar  7 15:26:43 1999
@@ -0,0 +1,44 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_client.h
+ * Version:       0.3
+ * Description:   IrDA LAN access layer
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Aug 31 20:14:37 1997
+ * Modified at:   Wed Feb  3 14:29:49 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     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.
+ *
+ *     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 IRLAN_CLIENT_H
+#define IRLAN_CLIENT_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+
+#include <net/irda/irlan_event.h>
+
+void irlan_client_start_kick_timer(struct irlan_cb *self, int timeout);
+void irlan_client_discovery_indication(DISCOVERY*);
+void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr);
+
+void irlan_client_open_ctrl_tsap( struct irlan_cb *self);
+
+void irlan_client_extract_params(struct irlan_cb *self, struct sk_buff *skb);
+void irlan_client_get_value_confirm( __u16 obj_id, struct ias_value *value, 
+				     void *priv);
+#endif
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/irlan_common.h linux/include/net/irda/irlan_common.h
--- v2.2.2/linux/include/net/irda/irlan_common.h	Tue Dec 22 14:16:58 1998
+++ linux/include/net/irda/irlan_common.h	Sun Mar  7 15:26:43 1999
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
- * Filename:      irlan.h
- * Version:       0.1
+ * Filename:      irlan_common.h
+ * Version:       0.8
  * Description:   IrDA LAN access layer
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Thu Oct 29 13:23:11 1998
+ * Modified at:   Wed Feb 17 23:28:53 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -30,10 +30,11 @@
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 
-#include "irqueue.h"
-#include "irttp.h"
+#include <net/irda/irqueue.h>
+#include <net/irda/irttp.h>
 
-#define IRLAN_MTU 1518
+#define IRLAN_MTU        1518
+#define IRLAN_TIMEOUT    1000
 
 /* Command packet types */
 #define CMD_GET_PROVIDER_INFO   0
@@ -61,23 +62,23 @@
 #define MEDIA_802_5 2
 
 /* Filter parameters */
-#define DATA_CHAN 1
+#define DATA_CHAN   1
 #define FILTER_TYPE 2
 #define FILTER_MODE 3
 
 /* Filter types */
-#define IR_DIRECTED   1
-#define IR_FUNCTIONAL 2
-#define IR_GROUP      3
-#define IR_MAC_FRAME  4
-#define IR_MULTICAST  5
-#define IR_BROADCAST  6
-#define IR_IPX_SOCKET 7
+#define IRLAN_DIRECTED   0x01
+#define IRLAN_FUNCTIONAL 0x02
+#define IRLAN_GROUP      0x04
+#define IRLAN_MAC_FRAME  0x08
+#define IRLAN_MULTICAST  0x10
+#define IRLAN_BROADCAST  0x20
+#define IRLAN_IPX_SOCKET 0x40
 
 /* Filter modes */
-#define ALL    1
-#define FILTER 2
-#define NONE   3
+#define ALL     1
+#define FILTER  2
+#define NONE    3
 
 /* Filter operations */
 #define GET     1
@@ -87,36 +88,51 @@
 #define DYNAMIC 5
 
 /* Access types */
-#define DIRECT 1
-#define PEER   2
-#define HOSTED 3
+#define ACCESS_DIRECT  1
+#define ACCESS_PEER    2
+#define ACCESS_HOSTED  3
+
+#define IRLAN_BYTE   0
+#define IRLAN_SHORT  1
+#define IRLAN_ARRAY  2
 
 #define IRLAN_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_HEADER)
 
 /*
- *  IrLAN client subclass
+ *  IrLAN client
  */
 struct irlan_client_cb {
-	/*
-	 *  Client fields
-	 */
+	int state;
+
 	int open_retries;
+
+	struct tsap_cb *tsap_ctrl;
 	
 	__u8 reconnect_key[255];
 	__u8 key_len;
 	
+	__u16 recv_arb_val;
+	__u16 max_frame;
+	int filter_type;
+
 	int unicast_open;
 	int broadcast_open;
+
+	struct timer_list kick_timer;
+	int start_new_provider;
 };
 
 /*
- * IrLAN servers subclass
+ * IrLAN provider
  */
-struct irlan_server_cb {
+struct irlan_provider_cb {
+	int state;
 	
+	struct tsap_cb *tsap_ctrl;
+
 	/*
-	 *  Store some values here which are used by the irlan_server to parse
-	 *  FILTER_OPERATIONs
+	 *  Store some values here which are used by the provider to parse
+	 *  the filter operations
 	 */
 	int data_chan;
 	int filter_type;
@@ -124,11 +140,13 @@
 	int filter_operation;
 	int filter_entry;
 
+	__u16 send_arb_val;
+
 	__u8 mac_address[6]; /* Generated MAC address for peer device */
 };
 
 /*
- *  IrLAN super class
+ *  IrLAN
  */
 struct irlan_cb {
 	QUEUE queue; /* Must be first */
@@ -140,57 +158,52 @@
 
 	__u32 saddr;        /* Source devcie address */
 	__u32 daddr;        /* Destination device address */
-	int   connected;    /* TTP layer ready to exchange ether frames */
+	int   netdev_registered;
+	int   notify_irmanager;
 	
-	int state;  /* Current state of IrLAN layer */
-
-	int media;	
+	int media;          /* Media type */
+	int access_type;    /* Currently used access type */
+	__u8 version[2];    /* IrLAN version */
 	
-	struct tsap_cb *tsap_ctrl;
 	struct tsap_cb *tsap_data;
 
 	int  use_udata;  /* Use Unit Data transfers */
 
-	__u8 dtsap_sel_data; /* Destination data TSAP selector */
 	__u8 stsap_sel_data; /* Source data TSAP selector */
+	__u8 dtsap_sel_data; /* Destination data TSAP selector */
 	__u8 dtsap_sel_ctrl; /* Destination ctrl TSAP selector */
 
-	int client; /* Client or server */
-	union {
-		struct irlan_client_cb client;
-		struct irlan_server_cb server;
-	} t;
-
-	/* void (*irlan_dev_init)(struct irlan_cb *); */
-
-	/* 
-         *  Used by extract_params, placed here for now to avoid placing 
-         *  them on the stack. FIXME: remove these!
-         */
-        char name[255];
-        char value[1016];
+	struct irlan_client_cb client;     /* Client specific fields */
+	struct irlan_provider_cb provider; /* Provider specific fields */
+	
+	struct timer_list watchdog_timer;
 };
 
-struct irlan_cb *irlan_open(void);
-
-void irlan_get_provider_info( struct irlan_cb *self);
-void irlan_get_unicast_addr( struct irlan_cb *self);
-void irlan_get_media_char( struct irlan_cb *self);
-void irlan_open_data_channel( struct irlan_cb *self);
-void irlan_set_multicast_filter( struct irlan_cb *self, int status);
-void irlan_set_broadcast_filter( struct irlan_cb *self, int status);
-void irlan_open_unicast_addr( struct irlan_cb *self);
-
-int insert_byte_param( struct sk_buff *skb, char *param, __u8 value);
-int insert_string_param( struct sk_buff *skb, char *param, char *value);
-int insert_array_param( struct sk_buff *skb, char *name, __u8 *value, 
-			__u16 value_len);
-
-int insert_param( struct sk_buff *skb, char *param, int type, char *value_char,
-		  __u8 value_byte, __u16 value_short);
+struct irlan_cb *irlan_open(__u32 saddr, __u32 daddr, int netdev);
+void irlan_close(struct irlan_cb *self);
+int  irlan_register_netdev(struct irlan_cb *self);
+void irlan_ias_register(struct irlan_cb *self, __u8 tsap_sel);
+void irlan_start_watchdog_timer(struct irlan_cb *self, int timeout);
+
+void irlan_open_data_tsap(struct irlan_cb *self);
+
+void irlan_get_provider_info(struct irlan_cb *self);
+void irlan_get_unicast_addr(struct irlan_cb *self);
+void irlan_get_media_char(struct irlan_cb *self);
+void irlan_open_data_channel(struct irlan_cb *self);
+void irlan_close_data_channel(struct irlan_cb *self);
+void irlan_set_multicast_filter(struct irlan_cb *self, int status);
+void irlan_set_broadcast_filter(struct irlan_cb *self, int status);
+void irlan_open_unicast_addr(struct irlan_cb *self);
+
+int irlan_insert_byte_param(struct sk_buff *skb, char *param, __u8 value);
+int irlan_insert_short_param(struct sk_buff *skb, char *param, __u16 value);
+int irlan_insert_string_param(struct sk_buff *skb, char *param, char *value);
+int irlan_insert_array_param(struct sk_buff *skb, char *name, __u8 *value, 
+			     __u16 value_len);
 
-int irlan_get_response_param( __u8 *buf, char *name, char *value, int *len);
-void print_ret_code( __u8 code);
+int irlan_get_param(__u8 *buf, char *name, char *value, __u16 *len);
+void print_ret_code(__u8 code);
 
 extern hashbin_t *irlan;
 
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/irlan_eth.h linux/include/net/irda/irlan_eth.h
--- v2.2.2/linux/include/net/irda/irlan_eth.h	Tue Dec 22 14:16:58 1998
+++ linux/include/net/irda/irlan_eth.h	Sun Mar  7 15:26:43 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Oct 15 08:36:58 1998
- * Modified at:   Thu Oct 15 12:28:12 1998
+ * Modified at:   Fri Jan 29 15:20:45 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -25,12 +25,8 @@
 #ifndef IRLAN_ETH_H
 #define IRLAN_ETH_H
 
-int irlan_eth_init( struct device *dev);
-int irlan_eth_open( struct device *dev);
-int irlan_eth_close( struct device *dev);
-
-void irlan_eth_rx( void *instance, void *sap, struct sk_buff *skb);
-int irlan_eth_tx( struct sk_buff *skb, struct device *dev);
+void irlan_eth_receive( void *instance, void *sap, struct sk_buff *skb);
+int  irlan_eth_xmit( struct sk_buff *skb, struct device *dev);
 
 void irlan_eth_flow_indication( void *instance, void *sap, LOCAL_FLOW flow);
 
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/irlan_event.h linux/include/net/irda/irlan_event.h
--- v2.2.2/linux/include/net/irda/irlan_event.h	Tue Dec 22 14:16:58 1998
+++ linux/include/net/irda/irlan_event.h	Sun Mar  7 15:26:43 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Tue Oct 20 09:59:31 1998
+ * Modified at:   Tue Feb  2 09:45:17 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -44,7 +44,6 @@
 	IRLAN_SYNC
 } IRLAN_STATE;
 
-/* IrLAN Client Events */
 typedef enum {
 	IRLAN_DISCOVERY_INDICATION,
 	IRLAN_IAS_PROVIDER_AVAIL,
@@ -61,26 +60,22 @@
 	IRLAN_GET_MEDIA_CMD,
 	IRLAN_OPEN_DATA_CMD,
 	IRLAN_FILTER_CONFIG_CMD,
-} IRLAN_EVENT;
 
-struct irlan_info {
-	__u8   dlsap_sel;
-	__u32  daddr;
-	struct tsap_cb *tsap;
-};
+	IRLAN_CHECK_CON_ARB,
+	IRLAN_PROVIDER_SIGNAL,
+
+	IRLAN_WATCHDOG_TIMEOUT,
+} IRLAN_EVENT;
 
 extern char *irlan_state[];
 
-void irlan_do_client_event( struct irlan_cb *self, 
-			    IRLAN_EVENT event, 
-			    struct sk_buff *skb);
-
-void irlan_do_server_event( struct irlan_cb *self, 
-			    IRLAN_EVENT event, 
-			    struct sk_buff *skb, 
-			    struct irlan_info *info);
+void irlan_do_client_event(struct irlan_cb *self, IRLAN_EVENT event, 
+			   struct sk_buff *skb);
+
+void irlan_do_provider_event(struct irlan_cb *self, IRLAN_EVENT event, 
+			     struct sk_buff *skb);
 
-void irlan_next_state( struct irlan_cb *self, 
-		       IRLAN_STATE state);
+void irlan_next_client_state(struct irlan_cb *self, IRLAN_STATE state);
+void irlan_next_provider_state(struct irlan_cb *self, IRLAN_STATE state);
 
 #endif
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/irlan_filter.h linux/include/net/irda/irlan_filter.h
--- v2.2.2/linux/include/net/irda/irlan_filter.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irlan_filter.h	Sun Mar  7 15:26:43 1999
@@ -0,0 +1,33 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_filter.h
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Fri Jan 29 15:24:08 1999
+ * Modified at:   Sun Feb  7 23:35:31 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 IRLAN_FILTER_H
+#define IRLAN_FILTER_H
+
+void irlan_check_command_param(struct irlan_cb *self, char *param, 
+			       char *value);
+void handle_filter_request(struct irlan_cb *self, struct sk_buff *skb);
+int irlan_print_filter(int filter_type, char *buf);
+
+#endif /* IRLAN_FILTER_H */
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/irlan_provider.h linux/include/net/irda/irlan_provider.h
--- v2.2.2/linux/include/net/irda/irlan_provider.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irlan_provider.h	Sun Mar  7 15:26:43 1999
@@ -0,0 +1,57 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_provider.h
+ * Version:       0.1
+ * Description:   IrDA LAN access layer
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Aug 31 20:14:37 1997
+ * Modified at:   Sat Jan 30 16:22:24 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     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.
+ *
+ *     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 IRLAN_SERVER_H
+#define IRLAN_SERVER_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+
+#include <net/irda/irlan_common.h>
+
+void irlan_provider_ctrl_disconnect_indication(void *instance, void *sap, 
+					       LM_REASON reason, 
+					       struct sk_buff *skb);
+
+void irlan_provider_ctrl_data_indication(void *instance, void *sap,
+					 struct sk_buff *skb);
+
+void irlan_provider_connect_indication(void *instance, void *sap, 
+				       struct qos_info *qos, int max_sdu_size,
+				       struct sk_buff *skb);
+void irlan_provider_connect_response(struct irlan_cb *, struct tsap_cb *);
+
+int irlan_parse_open_data_cmd(struct irlan_cb *self, struct sk_buff *skb);
+int irlan_provider_extract_params(struct irlan_cb *self, int cmd,
+				  struct sk_buff *skb);
+
+void irlan_provider_send_reply(struct irlan_cb *self, int command, 
+			       int ret_code);
+void irlan_provider_open_ctrl_tsap( struct irlan_cb *self);
+
+#endif
+
+
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/irlan_srv.h linux/include/net/irda/irlan_srv.h
--- v2.2.2/linux/include/net/irda/irlan_srv.h	Tue Dec 22 14:16:58 1998
+++ linux/include/net/irda/irlan_srv.h	Wed Dec 31 16:00:00 1969
@@ -1,62 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      server.h
- * Version:       0.1
- * Description:   IrDA LAN access layer
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Fri Oct 16 11:25:37 1998
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     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.
- *
- *     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 IRLAN_SERVER_H
-#define IRLAN_SERVER_H
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-
-#include <net/irda/irlan_common.h>
-
-int  irlan_server_init(void);
-void irlan_server_cleanup(void);
-struct irlan_cb *irlan_server_open(void);
-void irlan_server_close( struct irlan_cb *self);
-
-void irlan_server_disconnect_indication( void *instance, void *sap, 
-					 LM_REASON reason, 
-					 struct sk_buff *skb);
-
-void irlan_server_data_indication( void *instance, void *sap,
-				   struct sk_buff *skb);
-void irlan_server_control_data_indication( void *instance, void *sap,
-					   struct sk_buff *skb);
-
-void irlan_server_connect_indication( void *instance, void *sap, 
-				      struct qos_info *qos, int max_sdu_size,
-				      struct sk_buff *skb);
-void irlan_server_connect_response( struct irlan_cb *, struct tsap_cb *);
-
-int irlan_parse_open_data_cmd( struct irlan_cb *self, struct sk_buff *skb);
-int irlan_server_extract_params( struct irlan_cb *self, int cmd,
-				  struct sk_buff *skb);
-
-void irlan_server_send_reply( struct irlan_cb *self, int command, 
-			      int ret_code);
-void irlan_server_register(void);
-
-#endif
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/irlap.h linux/include/net/irda/irlap.h
--- v2.2.2/linux/include/net/irda/irlap.h	Tue Dec 22 14:16:58 1998
+++ linux/include/net/irda/irlap.h	Sun Mar  7 15:26:43 1999
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irlap.h
- * Version:       0.3
+ * Version:       0.8
  * Description:   An IrDA LAP driver for Linux
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Sat Dec 12 12:25:33 1998
+ * Modified at:   Mon Jan 25 13:58:59 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -105,6 +105,7 @@
 	struct timer_list backoff_timer;
 
 	/* Timeouts which will be different with different turn time */
+	int slot_timeout;
 	int poll_timeout;
 	int final_timeout;
 	int wd_timeout;
@@ -118,14 +119,15 @@
 	int     retry_count;  /* Times tried to establish connection */
 	int     add_wait;     /* True if we are waiting for frame */
 
+	__u8    connect_pending;
+	__u8    disconnect_pending;
+
+	/*  To send a faster RR if tx queue empty */
 #ifdef CONFIG_IRDA_FAST_RR
-	/* 
-	 *  To send a faster RR if tx queue empty 
-	 */
 	int     fast_RR_timeout;
 	int     fast_RR;      
 #endif
-
+	
 	int N1; /* N1 * F-timer = Negitiated link disconnect warning threshold */
 	int N2; /* N2 * F-timer = Negitiated link disconnect time */
 	int N3; /* Connection retry count */
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/irlap_event.h linux/include/net/irda/irlap_event.h
--- v2.2.2/linux/include/net/irda/irlap_event.h	Wed Jan 20 23:14:06 1999
+++ linux/include/net/irda/irlap_event.h	Sun Mar  7 15:26:43 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Aug 16 00:59:29 1997
- * Modified at:   Thu Dec 17 11:58:10 1998
+ * Modified at:   Thu Feb 11 00:41:02 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -111,7 +111,7 @@
 	DISCOVERY *discovery; /* Discovery information */
 };
 
-extern char *irlap_state[];
+extern const char *irlap_state[];
 
 void irlap_do_event( struct irlap_cb *self, IRLAP_EVENT event, 
 		     struct sk_buff *skb, struct irlap_info *info);
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/irlmp.h linux/include/net/irda/irlmp.h
--- v2.2.2/linux/include/net/irda/irlmp.h	Tue Dec 22 14:16:58 1998
+++ linux/include/net/irda/irlmp.h	Sun Mar  7 15:26:43 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 17 20:54:32 1997
- * Modified at:   Mon Dec  7 21:11:32 1998
+ * Modified at:   Thu Feb  4 11:06:24 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -28,17 +28,19 @@
 #include <linux/config.h>
 #include <linux/types.h>
 
-#include "irmod.h"
-#include "qos.h"
-#include "irlap.h"
-#include "irlmp_event.h"
-#include "irqueue.h"
+#include <net/irda/irmod.h>
+#include <net/irda/qos.h>
+#include <net/irda/irlap.h>
+#include <net/irda/irlmp_event.h>
+#include <net/irda/irqueue.h>
 
 /* LSAP-SEL's */
 #define LSAP_MASK     0x7f
 #define LSAP_IAS      0x00
 #define LSAP_ANY      0xff
 
+#define DEV_ADDR_ANY  0xffffffff
+
 /* Predefined LSAPs used by the various servers */
 #define TSAP_IRLAN    0x05
 #define LSAP_IRLPT    0x06
@@ -69,6 +71,8 @@
 #define HINT_HTTP        0x10
 #define HINT_OBEX        0x20
 
+#define LM_IDLE_TIMEOUT  200 /* 2 seconds for now */
+
 typedef enum {
 	S_PNP,
 	S_PDA,
@@ -150,6 +154,7 @@
 	hashbin_t *cachelog;    /* Discovered devices for this link */
 
 	struct qos_info *qos;  /* LAP QoS for this session */
+	struct timer_list idle_timer;
 };
 
 /*
@@ -171,10 +176,8 @@
 
 	__u8 conflict_flag;
 	
-	/* int discovery; */
-
-	DISCOVERY  discovery_rsp; /* Discovery response to use by IrLAP */
 	DISCOVERY  discovery_cmd; /* Discovery command to use by IrLAP */
+	DISCOVERY  discovery_rsp; /* Discovery response to use by IrLAP */
 
 	int free_lsap_sel;
 
@@ -205,7 +208,8 @@
 			   struct notify_t *);
 void irlmp_unregister_irlap( __u32 saddr);
 
-void irlmp_connect_request( struct lsap_cb *, __u8 dlsap_sel, __u32 daddr, 
+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 *);
@@ -231,9 +235,14 @@
 
 int  irlmp_slsap_inuse( __u8 slsap);
 __u8 irlmp_find_free_slsap(void);
-
 LM_REASON irlmp_convert_lap_reason( LAP_REASON);
 
+__u32 irlmp_get_saddr(struct lsap_cb *self);
+__u32 irlmp_get_daddr(struct lsap_cb *self);
+
+
+extern char *lmp_reasons[];
+extern int sysctl_discovery_slots;
 extern struct irlmp_cb *irlmp;
 
 #endif
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/irlmp_event.h linux/include/net/irda/irlmp_event.h
--- v2.2.2/linux/include/net/irda/irlmp_event.h	Tue Dec 22 14:16:58 1998
+++ linux/include/net/irda/irlmp_event.h	Sun Mar  7 15:26:43 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Wed Oct 28 14:58:23 1998
+ * Modified at:   Thu Feb 11 00:42:41 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -72,7 +72,7 @@
 	LM_LAP_DISCONNECT_REQUEST,
 	LM_LAP_DISCOVERY_REQUEST,
  	LM_LAP_DISCOVERY_CONFIRM,
-
+	LM_LAP_IDLE_TIMEOUT,
 } IRLMP_EVENT;
 
 /*
@@ -95,11 +95,12 @@
 	DISCOVERY *discovery;
 };
 
-extern char *irlmp_state[];
-extern char *irlsap_state[];
+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);
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/irlmp_frame.h linux/include/net/irda/irlmp_frame.h
--- v2.2.2/linux/include/net/irda/irlmp_frame.h	Tue Dec 22 14:16:58 1998
+++ linux/include/net/irda/irlmp_frame.h	Sun Mar  7 15:26:43 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Aug 19 02:09:59 1997
- * Modified at:   Sun Oct 25 00:30:31 1998
+ * Modified at:   Tue Feb  2 11:07:45 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -42,8 +42,8 @@
 			 __u8 opcode, struct sk_buff *skb);
 void irlmp_link_data_indication( struct lap_cb *, int reliable, 
 				 struct sk_buff *);
-void irlmp_link_connect_indication( struct lap_cb *, struct qos_info *qos, 
-				    struct sk_buff *skb);
+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);
 void irlmp_link_connect_confirm( struct lap_cb *self, struct qos_info *qos, 
 				 struct sk_buff *skb);
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/irlpt_cli.h linux/include/net/irda/irlpt_cli.h
--- v2.2.2/linux/include/net/irda/irlpt_cli.h	Wed Jan 20 23:14:06 1999
+++ linux/include/net/irda/irlpt_cli.h	Sun Mar  7 15:26:43 1999
@@ -1,6 +1,6 @@
 /*********************************************************************
  *                
- * Filename:      irlpt_client.h
+ * Filename:      irlpt_cli.h
  * Version:       0.1
  * Description:   
  * Status:        Experimental.
@@ -35,8 +35,10 @@
  */
 
 void irlpt_client_get_value_confirm(__u16 obj_id, 
-				    struct ias_value *value, void *priv);
-void irlpt_client_connect_indication( void *instance, void *sap, 
+				    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);
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/irlpt_cli_fsm.h linux/include/net/irda/irlpt_cli_fsm.h
--- v2.2.2/linux/include/net/irda/irlpt_cli_fsm.h	Wed Jan 20 23:14:06 1999
+++ linux/include/net/irda/irlpt_cli_fsm.h	Sun Mar  7 15:26:43 1999
@@ -1,19 +1,21 @@
 /*********************************************************************
  *                
- * Filename:      irlpt_client_fsm.h
+ * 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.
+ *     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.
+ *     I, Thomas Davis, provide no warranty for any of this software. 
+ *     This material is provided "AS-IS" and at no charge.
  *
  ********************************************************************/
 
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/irlpt_common.h linux/include/net/irda/irlpt_common.h
--- v2.2.2/linux/include/net/irda/irlpt_common.h	Wed Jan 20 23:14:06 1999
+++ linux/include/net/irda/irlpt_common.h	Sun Mar  7 15:26:43 1999
@@ -1,6 +1,6 @@
 /*********************************************************************
  *
- * Filename:      irlpt.c
+ * Filename:      irlpt_common.h
  * Version:       
  * Description:   
  * Status:        Experimental.
@@ -67,7 +67,6 @@
 	IRLPT_CLIENT_QUERY,
 	IRLPT_CLIENT_READY,
 	IRLPT_CLIENT_WAITI,
-	IRLPT_CLIENT_WAITR,
 	IRLPT_CLIENT_CONN,
 } IRLPT_CLIENT_STATE;
 
@@ -87,10 +86,6 @@
 	LMP_DISCONNECT,
 	LMP_CONNECT_INDICATION,
 	LMP_DISCONNECT_INDICATION,
-#if 0
-	TTP_CONNECT_INDICATION,
-	TTP_DISCONNECT_INDICATION,
-#endif
         IRLPT_DISCOVERY_INDICATION,
 	IRLPT_CONNECT_REQUEST,
 	IRLPT_DISCONNECT_REQUEST,
@@ -101,6 +96,7 @@
 	struct lsap_cb *lsap;
 	__u8 dlsap_sel;
 	__u32 daddr;
+	__u32 saddr;
 };
 
 /* Command packet types */
@@ -142,7 +138,8 @@
 
 	int magic;		/* magic used to detect corruption of 
 				   the struct */
-	__u32 daddr;		/* my local address. */
+	__u32 daddr;		/* address of remote printer */
+	__u32 saddr;            /* my local address. */
 
 	struct timer_list retry_timer;
 	
@@ -167,6 +164,14 @@
 	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 */
 
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/irlpt_server.h linux/include/net/irda/irlpt_server.h
--- v2.2.2/linux/include/net/irda/irlpt_server.h	Wed Jan 20 23:14:06 1999
+++ linux/include/net/irda/irlpt_server.h	Sun Mar  7 15:26:43 1999
@@ -1,6 +1,6 @@
 /*********************************************************************
  *                
- * Filename:      server.h
+ * Filename:      irlpt_server.h
  * Version:       0.1
  * Description:   
  * Status:        Experimental.
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/irlpt_server_fsm.h linux/include/net/irda/irlpt_server_fsm.h
--- v2.2.2/linux/include/net/irda/irlpt_server_fsm.h	Wed Jan 20 23:14:06 1999
+++ linux/include/net/irda/irlpt_server_fsm.h	Sun Mar  7 15:26:43 1999
@@ -1,19 +1,21 @@
 /*********************************************************************
  *                
- * Filename:      server_fsm.h<2>
+ * 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.
+ *     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.
+ *     I, Thomas Davis, provide no warranty for any of this software. 
+ *     This material is provided "AS-IS" and at no charge.
  *
  ********************************************************************/
 
@@ -23,8 +25,11 @@
 #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);
+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 --recursive --new-file v2.2.2/linux/include/net/irda/irmod.h linux/include/net/irda/irmod.h
--- v2.2.2/linux/include/net/irda/irmod.h	Wed Jan 20 23:14:06 1999
+++ linux/include/net/irda/irmod.h	Sun Mar  7 15:26:44 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Dec 15 13:58:52 1997
- * Modified at:   Tue Jan 12 14:56:11 1999
+ * Modified at:   Thu Feb 11 15:14:30 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  *
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -45,6 +45,7 @@
 	EVENT_IRLAN_STOP,
 	EVENT_IRLPT_START,
 	EVENT_IRLPT_STOP,
+/* 	EVENT_IROBEX_INIT, */
 	EVENT_IROBEX_START,
 	EVENT_IROBEX_STOP,
 	EVENT_IRDA_STOP,
@@ -190,7 +191,13 @@
 	LM_CONNECT_FAILURE,   /* Failed to establish IrLAP connection */
 	LM_LAP_RESET,         /* IrLAP reset */
 	LM_INIT_DISCONNECT,   /* Link Management initiated disconnect */
-} LM_REASON; /* FIXME: Just for now */
+	LM_LSAP_NOTCONN,      /* Data delivered on unconnected LSAP */
+	LM_NON_RESP_CLIENT,   /* Non responsive LM-MUX client */
+	LM_NO_AVAIL_CLIENT,   /* No available LM-MUX client */
+	LM_CONN_HALF_OPEN,    /* Connection is half open */
+	LM_BAD_SOURCE_ADDR,   /* Illegal source address (i.e 0x00) */
+} LM_REASON;
+#define LM_UNKNOWN 0xff       /* Unspecified disconnect reason */
 
 /*
  *  IrLMP character code values
@@ -214,16 +221,17 @@
 struct discovery_t {
 	QUEUE queue;              /* Must be first! */
 
-	__u32       saddr;        /* Which link the device was discovered */
-	__u32       daddr;        /* Remote device address */
-	LAP_REASON  condition;    /* More info about the discovery */
-
-	__u8        hint[2];      /* Discovery hint bits */
-	__u8        charset;
-	char        info[32];     /* Usually the name of the device */
-	__u8        info_len;     /* Length of device info field */
+	__u32      saddr;        /* Which link the device was discovered */
+	__u32      daddr;        /* Remote device address */
+	LAP_REASON condition;    /* More info about the discovery */
+
+	__u8       hint[2];      /* Discovery hint bits */
+	__u8       charset;
+	char       info[32];     /* Usually the name of the device */
+	__u8       info_len;     /* Length of device info field */
 
-	int         gen_addr_bit; /* Need to generate a new device address? */
+	int        gen_addr_bit; /* Need to generate a new device address? */
+	int        nslots;       /* Number of slots to use when discovering */
 };
 
 typedef enum { FLOW_STOP, FLOW_START } LOCAL_FLOW;
@@ -254,12 +262,14 @@
 int irmod_init_module(void);
 void irmod_cleanup_module(void);
 
-inline int irda_lock( int *lock);
-inline int irda_unlock( int *lock);
+inline int irda_lock(int *lock);
+inline int irda_unlock(int *lock);
 
-void irda_notify_init( struct notify_t *notify);
+void irda_notify_init(struct notify_t *notify);
 
-void irda_execute_as_process( void *self, TODO_CALLBACK callback, __u32 param);
-void irmanager_notify( struct irmanager_event *event);
+void irda_execute_as_process(void *self, TODO_CALLBACK callback, __u32 param);
+void irmanager_notify(struct irmanager_event *event);
+
+extern void irda_proc_modcount(struct inode *, int);
 
 #endif
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/irobex.h linux/include/net/irda/irobex.h
--- v2.2.2/linux/include/net/irda/irobex.h	Wed Jan 20 23:14:06 1999
+++ linux/include/net/irda/irobex.h	Sun Mar  7 15:26:44 1999
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irobex.h
- * Version:       
+ * Version:       0.8
  * Description:   
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Jul  4 22:43:57 1998
- * Modified at:   Wed Jan 13 15:55:28 1999
+ * Modified at:   Tue Jan 26 11:49:55 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -28,7 +28,6 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/skbuff.h>
-/* #include <linux/netdevice.h> */
 #include <linux/miscdevice.h>
 
 #include <net/irda/timer.h>
@@ -97,30 +96,7 @@
 	LOCAL_FLOW rx_flow;
 };
 
-int    irobex_init(void);
-void   irobex_cleanup(void);
-struct irobex_cb *irobex_open(void);
-void   irobex_close( struct irobex_cb *self);
-
-void irobex_discovery_indication( DISCOVERY *);
-
-void irobex_data_request( int handle, struct sk_buff *skb);
-void irobex_data_indication( void *instance, void *sap, struct sk_buff *skb);
-void irobex_control_data_indication( void *instance, void *sap, 
-				     struct sk_buff *skb);
-
-void irobex_connect_request( struct irobex_cb *self);
-void irobex_connect(struct irobex_cb *self, struct sk_buff *skb);
-void irobex_connect_confirm( void *instance, void *sap, struct qos_info *qos,
-			     int max_sdu_size, struct sk_buff *skb);
-void irobex_disconnect_indication( void *instance, void *sap, LM_REASON reason,
-				   struct sk_buff *skb);
-void irobex_flow_indication( void *instance, void *sap, LOCAL_FLOW flow);
-
-void irobex_extract_params( struct sk_buff *skb);
-void irobex_get_value_confirm(__u16 obj_id, struct ias_value *value, 
-			      void *priv);
-void irobex_register_server( struct irobex_cb *self);
+int irobex_init(void);
 
 void irobex_watchdog_timer_expired( unsigned long data);
 
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/irttp.h linux/include/net/irda/irttp.h
--- v2.2.2/linux/include/net/irda/irttp.h	Tue Dec 22 14:16:58 1998
+++ linux/include/net/irda/irttp.h	Sun Mar  7 15:26:44 1999
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irttp.h
- * Version:       0.3
+ * Version:       1.0
  * Description:   Tiny Transport Protocol (TTP) definitions
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:31 1997
- * Modified at:   Sat Dec  5 13:48:12 1998
+ * Modified at:   Tue Feb  2 10:55:18 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -33,21 +33,21 @@
 #include <net/irda/qos.h>
 #include <net/irda/irqueue.h>
 
-#define TTP_MAX_CONNECTIONS   LM_MAX_CONNECTIONS
-#define TTP_HEADER            1
-#define TTP_HEADER_WITH_SAR   6
-#define TTP_PARAMETERS        0x80
-#define TTP_MORE              0x80
+#define TTP_MAX_CONNECTIONS    LM_MAX_CONNECTIONS
+#define TTP_HEADER             1
+#define TTP_HEADER_WITH_SAR    6
+#define TTP_PARAMETERS         0x80
+#define TTP_MORE               0x80
 
 #define DEFAULT_INITIAL_CREDIT 22
 
-#define LOW_THRESHOLD  4
-#define HIGH_THRESHOLD 8
-#define TTP_MAX_QUEUE 22
+#define LOW_THRESHOLD   4
+#define HIGH_THRESHOLD  8
+#define TTP_MAX_QUEUE  22
 
 /* Some priorities for disconnect requests */
-#define P_NORMAL 0
-#define P_HIGH 1
+#define P_NORMAL    0
+#define P_HIGH      1
 
 #define SAR_DISABLE 0
 
@@ -56,13 +56,13 @@
  *  connection.
  */
 struct tsap_cb {
-	QUEUE queue;         /* For linking it into the hashbin */
-	int  magic;          /* Just in case */
+	QUEUE queue;          /* For linking it into the hashbin */
+	int  magic;           /* Just in case */
 
-	int max_seg_size;    /* Max data that fit into an IrLAP frame */
+	int max_seg_size;     /* Max data that fit into an IrLAP frame */
 
-	__u8 stsap_sel;      /* Source TSAP */
-	__u8 dtsap_sel;      /* Destination TSAP */
+	__u8 stsap_sel;       /* Source TSAP */
+	__u8 dtsap_sel;       /* Destination TSAP */
 
 	struct lsap_cb *lsap; /* Corresponding LSAP to this TSAP */
 
@@ -85,8 +85,8 @@
 	struct irda_statistics stats;
 	struct timer_list todo_timer; 
 	
-	int rx_sdu_busy;   /* RxSdu.busy */
-	int rx_sdu_size;   /* The current size of a partially received frame */
+	int rx_sdu_busy;     /* RxSdu.busy */
+	int rx_sdu_size;     /* Current size of a partially received frame */
 	int rx_max_sdu_size; /* Max receive user data size */
 
 	int tx_sdu_busy;     /* TxSdu.busy */
@@ -94,7 +94,8 @@
 
         int no_defrag;       /* Don't reassemble received fragments */
 
-	int disconnect_pend;   /* Disconnect, but still data to send */
+	int close_pend;      /* Close, but disconnect_pend */
+	int disconnect_pend; /* Disconnect, but still data to send */
 	struct sk_buff *disconnect_skb;
 };
 
@@ -107,28 +108,39 @@
 int  irttp_init(void);
 void irttp_cleanup(void);
 
-struct tsap_cb *irttp_open_tsap( __u8 stsap, int credit, 
-				 struct notify_t *notify);
-void irttp_close_tsap( struct tsap_cb *self);
-
-int  irttp_data_request( struct tsap_cb *self, struct sk_buff *skb);
-int  irttp_udata_request( struct tsap_cb *self, struct sk_buff *skb);
-
-void irttp_connect_request( struct tsap_cb *self, __u8 dtsap_sel, __u32 daddr,
-			    struct qos_info *qos, int max_sdu_size, 
+struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, 
+				struct notify_t *notify);
+int irttp_close_tsap(struct tsap_cb *self);
+
+int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb);
+int irttp_udata_request(struct tsap_cb *self, struct sk_buff *skb);
+
+void irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel, 
+			   __u32 saddr, __u32 daddr,
+			   struct qos_info *qos, int max_sdu_size, 
+			   struct sk_buff *userdata);
+void irttp_connect_confirm(void *instance, void *sap, struct qos_info *qos, 
+			   int max_sdu_size, struct sk_buff *skb);
+void irttp_connect_response(struct tsap_cb *self, int max_sdu_size, 
 			    struct sk_buff *userdata);
-void irttp_connect_confirm( void *instance, void *sap, struct qos_info *qos, 
-			    int max_sdu_size, struct sk_buff *skb);
-void irttp_connect_response( struct tsap_cb *self, int max_sdu_size, 
-			     struct sk_buff *userdata);
-
-void irttp_disconnect_request( struct tsap_cb *self, struct sk_buff *skb,
-			       int priority);
-void irttp_flow_request( struct tsap_cb *self, LOCAL_FLOW flow);
 
-static __inline__ void irttp_no_reassemble( struct tsap_cb *self)
+void irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *skb,
+			      int priority);
+void irttp_flow_request(struct tsap_cb *self, LOCAL_FLOW flow);
+
+static __inline__ void irttp_no_reassemble(struct tsap_cb *self)
 {
 	self->no_defrag = TRUE;
+}
+
+static __inline __u32 irttp_get_saddr(struct tsap_cb *self)
+{
+	return irlmp_get_saddr(self->lsap);
+}
+
+static __inline __u32 irttp_get_daddr(struct tsap_cb *self)
+{
+	return irlmp_get_daddr(self->lsap);
 }
 
 extern struct irttp_cb *irttp;
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/irtty.h linux/include/net/irda/irtty.h
--- v2.2.2/linux/include/net/irda/irtty.h	Tue Dec 22 14:16:58 1998
+++ linux/include/net/irda/irtty.h	Sun Mar  7 15:26:44 1999
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irtty.h
- * Version:       0.1
+ * Version:       1.0
  * Description:   
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Dec  9 21:13:12 1997
- * Modified at:   Mon Dec 14 11:22:37 1998
+ * Modified at:   Sun Feb  7 01:57:33 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  *  
  *     Copyright (c) 1997 Dag Brattli, All Rights Reserved.
@@ -64,5 +64,7 @@
  
 int irtty_register_dongle( struct dongle *dongle);
 void irtty_unregister_dongle( struct dongle *dongle);
+
+void irtty_set_dtr_rts(struct tty_struct *tty, int dtr, int rts);
 
 #endif
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/pc87108.h linux/include/net/irda/pc87108.h
--- v2.2.2/linux/include/net/irda/pc87108.h	Tue Dec 22 14:16:58 1998
+++ linux/include/net/irda/pc87108.h	Sun Mar  7 15:26:44 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Fri Nov 13 14:37:40 1998
- * Modified at:   Thu Dec 10 19:58:20 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>
@@ -148,8 +148,8 @@
 #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_OVR2     0x02 /* Receive overrun */
-#define FRM_ST_OVR1     0x01 /* Frame status FIFO overrun */
+#define FRM_ST_OVR1     0x02 /* Receive overrun */
+#define FRM_ST_OVR2     0x01 /* Frame status FIFO overrun */
 
 #define RFLFL           0x06
 #define RFLFH           0x07
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/timer.h linux/include/net/irda/timer.h
--- v2.2.2/linux/include/net/irda/timer.h	Tue Dec 22 14:16:58 1998
+++ linux/include/net/irda/timer.h	Sun Mar  7 15:26:44 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Aug 16 00:59:29 1997
- * Modified at:   Mon Nov  2 14:31:55 1998
+ * Modified at:   Thu Feb  4 11:05:24 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997, 1998 Dag Brattli <dagb@cs.uit.no>, 
@@ -26,11 +26,11 @@
 #ifndef TIMER_H
 #define TIMER_H
 
-#include "irda.h"
-#include "irmod.h"
-#include "irlap.h"
-#include "irlmp.h"
-#include "irda_device.h"
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irlap.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/irda_device.h>
 
 /* 
  *  Timeout definitions, some defined in IrLAP p. 92
@@ -53,7 +53,6 @@
 #define QUERY_TIMEOUT          100
 
 #define WATCHDOG_TIMEOUT      2000                /* 20 sec */
-#define RETRY_TIMEOUT           51
 
 typedef void (*TIMER_CALLBACK)( unsigned long);
 
@@ -69,8 +68,10 @@
 inline void irda_device_start_mbusy_timer( struct irda_device *self);
 
 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_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);
diff -u --recursive --new-file v2.2.2/linux/include/net/irda/wrapper.h linux/include/net/irda/wrapper.h
--- v2.2.2/linux/include/net/irda/wrapper.h	Tue Dec 22 14:16:58 1998
+++ linux/include/net/irda/wrapper.h	Sun Mar  7 15:26:44 1999
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      wrapper.h
- * Version:       
+ * Version:       1.0
  * Description:   IrDA Wrapper layer
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Thu Nov 19 13:17:56 1998
+ * Modified at:   Fri Jan 29 10:15:46 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -28,7 +28,7 @@
 #include <linux/types.h>
 #include <linux/skbuff.h>
 
-#include "irda_device.h"
+#include <net/irda/irda_device.h>
 
 #define BOF  0xc0 /* Beginning of frame */
 #define XBOF 0xff
@@ -39,9 +39,6 @@
 #define STO EOF  /* End flag */
 
 #define IR_TRANS 0x20    /* Asynchronous transparency modifier */       
-
-#define SOP BOF  /* Start of */
-#define EOP EOF  /* End of */
 
 enum {
 	OUTSIDE_FRAME = 1, 
diff -u --recursive --new-file v2.2.2/linux/include/net/sock.h linux/include/net/sock.h
--- v2.2.2/linux/include/net/sock.h	Tue Feb 23 15:21:35 1999
+++ linux/include/net/sock.h	Mon Mar  8 15:52:30 1999
@@ -99,8 +99,7 @@
 	struct semaphore	readsem;
 	struct sock *		other;
 	struct sock **		list;
-	int 			marksweep;
-#define MARKED			1
+	struct sock *		gc_tree;
 	int			inflight;
 };
 
diff -u --recursive --new-file v2.2.2/linux/include/video/fbcon.h linux/include/video/fbcon.h
--- v2.2.2/linux/include/video/fbcon.h	Mon Dec 28 15:00:53 1998
+++ linux/include/video/fbcon.h	Thu Feb 25 10:02:12 1999
@@ -13,6 +13,7 @@
 
 #include <linux/config.h>
 #include <linux/console_struct.h>
+#include <linux/vt_buffer.h>
 
 
     /*                                  
diff -u --recursive --new-file v2.2.2/linux/include/video/sbusfb.h linux/include/video/sbusfb.h
--- v2.2.2/linux/include/video/sbusfb.h	Mon Oct  5 13:13:47 1998
+++ linux/include/video/sbusfb.h	Thu Feb 25 10:02:11 1999
@@ -15,8 +15,12 @@
 struct fb_info_creator {
 	struct ffb_fbc *fbc;
 	struct ffb_dac *dac;
-	int dac_rev;
 	int xy_margin;
+	int fifo_cache;
+	u64 yx_margin;
+	int fg_cache;
+	int bg_cache;
+	int dac_rev;
 };
 struct fb_info_cgsix {
 	struct bt_regs *bt;
diff -u --recursive --new-file v2.2.2/linux/init/main.c linux/init/main.c
--- v2.2.2/linux/init/main.c	Tue Feb 23 15:21:35 1999
+++ linux/init/main.c	Wed Feb 24 16:27:54 1999
@@ -185,6 +185,7 @@
 extern void ibmmca_scsi_setup(char *str, int *ints);
 extern void in2000_setup(char *str, int *ints);
 extern void NCR53c406a_setup(char *str, int *ints);
+extern void sym53c416_setup(char *str, int *ints);
 extern void wd7000_setup(char *str, int *ints);
 extern void dc390_setup(char* str, int *ints);
 extern void scsi_luns_setup(char *str, int *ints);
@@ -689,6 +690,9 @@
 #ifdef CONFIG_SCSI_NCR53C406A
 	{ "ncr53c406a=", NCR53c406a_setup},
 #endif
+#ifdef CONFIG_SCSI_SYM53C416
+	{ "sym53c416=", sym53c416_setup},
+#endif
 #ifdef CONFIG_SCSI_FUTURE_DOMAIN
 	{ "fdomain=", fdomain_setup},
 #endif
@@ -961,7 +965,7 @@
 		ticks = jiffies - ticks;
 		if (ticks)
 			break;
-		}
+	}
 
 /* Do a binary approximation to get loops_per_second set to equal one clock
    (up to lps_precision bits) */
diff -u --recursive --new-file v2.2.2/linux/kernel/fork.c linux/kernel/fork.c
--- v2.2.2/linux/kernel/fork.c	Tue Jan 19 11:32:53 1999
+++ linux/kernel/fork.c	Tue Feb 23 10:41:35 1999
@@ -172,8 +172,8 @@
 					if(last_pid & 0xffff8000)
 						last_pid = 300;
 					next_safe = PID_MAX;
-					goto repeat;
 				}
+				goto repeat;
 			}
 			if(p->pid > last_pid && next_safe > p->pid)
 				next_safe = p->pid;
diff -u --recursive --new-file v2.2.2/linux/kernel/printk.c linux/kernel/printk.c
--- v2.2.2/linux/kernel/printk.c	Fri Nov 27 13:09:30 1998
+++ linux/kernel/printk.c	Sat Mar  6 14:37:10 1999
@@ -137,15 +137,9 @@
 		error = verify_area(VERIFY_WRITE,buf,len);
 		if (error)
 			goto out;
-		cli();
-		error = -ERESTARTSYS;
-		while (!log_size) {
-			if (signal_pending(current)) {
-				sti();
-				goto out;
-			}
-			interruptible_sleep_on(&log_wait);
-		}
+		error = wait_event_interruptible(log_wait, log_size);
+		if (error)
+			goto out;
 		i = 0;
 		while (log_size && i < len) {
 			c = *((char *) log_buf+log_start);
diff -u --recursive --new-file v2.2.2/linux/mm/filemap.c linux/mm/filemap.c
--- v2.2.2/linux/mm/filemap.c	Tue Feb 23 15:21:35 1999
+++ linux/mm/filemap.c	Sun Mar  7 10:35:18 1999
@@ -1334,8 +1334,6 @@
 	if (!inode->i_op || !inode->i_op->readpage)
 		return -ENOEXEC;
 	UPDATE_ATIME(inode);
-	vma->vm_file = file;
-	file->f_count++;
 	vma->vm_ops = ops;
 	return 0;
 }
@@ -1455,6 +1453,12 @@
 
 	if (!inode->i_op || !inode->i_op->updatepage)
 		return -EIO;
+
+	if (file->f_error) {
+		int error = file->f_error;
+		file->f_error = 0;
+		return error;
+	}
 
 	sync    = file->f_flags & O_SYNC;
 	written = 0;
diff -u --recursive --new-file v2.2.2/linux/mm/mmap.c linux/mm/mmap.c
--- v2.2.2/linux/mm/mmap.c	Thu Jan 28 12:58:02 1999
+++ linux/mm/mmap.c	Mon Mar  8 09:30:29 1999
@@ -319,6 +319,8 @@
 			file->f_dentry->d_inode->i_writecount++;
 		if (error)
 			goto unmap_and_free_vma;
+		vma->vm_file = file;
+		file->f_count++;
 	}
 
 	/*
@@ -605,7 +607,7 @@
 		return -EINVAL;
 
 	if ((len = PAGE_ALIGN(len)) == 0)
-		return 0;
+		return -EINVAL;
 
 	/* Check if this memory area is ok - put it on the temporary
 	 * list if so..  The checks here are pretty simple --
diff -u --recursive --new-file v2.2.2/linux/mm/swapfile.c linux/mm/swapfile.c
--- v2.2.2/linux/mm/swapfile.c	Wed Jan 20 23:14:07 1999
+++ linux/mm/swapfile.c	Sun Mar  7 15:49:14 1999
@@ -556,7 +556,7 @@
 		for (i = 0 ; i < nr_swapfiles ; i++) {
 			if (i == type)
 				continue;
-			if (p->swap_file == swap_info[i].swap_file)
+			if (swap_dentry->d_inode == swap_info[i].swap_file->d_inode)
 				goto bad_swap;
 		}
 	} else
@@ -701,6 +701,8 @@
 	p->swap_map = NULL;
 	p->swap_lockmap = NULL;
 	p->flags = 0;
+	if (!(swap_flags & SWAP_FLAG_PREFER))
+		++least_priority;
 out:
 	if (swap_header)
 		free_page((long) swap_header);
diff -u --recursive --new-file v2.2.2/linux/net/Config.in linux/net/Config.in
--- v2.2.2/linux/net/Config.in	Thu Dec 31 10:29:03 1998
+++ linux/net/Config.in	Thu Feb 25 10:46:47 1999
@@ -10,7 +10,6 @@
   tristate 'Netlink device emulation' CONFIG_NETLINK_DEV
 fi
 bool 'Network firewalls' CONFIG_FIREWALL
-bool 'Network aliasing'  CONFIG_NET_ALIAS
 bool 'Socket Filtering'  CONFIG_FILTER
 tristate 'Unix domain sockets' CONFIG_UNIX
 bool 'TCP/IP networking' CONFIG_INET
diff -u --recursive --new-file v2.2.2/linux/net/Makefile linux/net/Makefile
--- v2.2.2/linux/net/Makefile	Tue Feb 23 15:21:35 1999
+++ linux/net/Makefile	Sun Mar  7 15:25:23 1999
@@ -128,7 +128,7 @@
 ifeq ($(CONFIG_IRDA),y)
 SUB_DIRS += irda
 # There might be some irda features that are compiled as modules
-MOD_SUB_DIRS += irda
+MOD_IN_SUB_DIRS += irda
 else
   ifeq ($(CONFIG_IRDA),m)
   MOD_SUB_DIRS += irda
diff -u --recursive --new-file v2.2.2/linux/net/ax25/af_ax25.c linux/net/ax25/af_ax25.c
--- v2.2.2/linux/net/ax25/af_ax25.c	Thu Jan  7 15:11:41 1999
+++ linux/net/ax25/af_ax25.c	Sun Mar  7 15:25:23 1999
@@ -957,7 +957,7 @@
 						ax25_stop_t3timer(sk->protinfo.ax25);
 						ax25_stop_idletimer(sk->protinfo.ax25);
 						break;
-#ifdef AX25_CONFIG_DAMA_SLAVE
+#ifdef CONFIG_AX25_DAMA_SLAVE
 					case AX25_PROTO_DAMA_SLAVE:
 						ax25_stop_t3timer(sk->protinfo.ax25);
 						ax25_stop_idletimer(sk->protinfo.ax25);
diff -u --recursive --new-file v2.2.2/linux/net/bridge/br.c linux/net/bridge/br.c
--- v2.2.2/linux/net/bridge/br.c	Fri Jan  8 22:36:25 1999
+++ linux/net/bridge/br.c	Sun Mar  7 15:25:23 1999
@@ -6,7 +6,7 @@
  *	More hacks to be able to switch protocols on and off by Christoph Lameter
  *	<clameter@debian.org>
  *	Software and more Documentation for the bridge is available from ftp.debian.org
- *	in the bridge package or at ftp.fuller.edu/Linux/bridge
+ *	in the bridgex package
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -63,7 +63,6 @@
 #include <linux/net.h>
 #include <linux/inet.h>
 #include <linux/netdevice.h>
-#include <linux/string.h>
 #include <linux/skbuff.h>
 #include <linux/if_arp.h>
 #include <linux/ip.h>
@@ -1239,6 +1238,13 @@
 	struct sk_buff *skb;
 	
 	/*
+	 *	Keep silent when disabled or when STP disabled
+	 */
+	 
+	if(!(br_stats.flags & BR_UP) || (br_stats.flags & BR_STP_DISABLED))
+		return -1;
+
+	/*
 	 *	Create and send the message
 	 */
 	 
@@ -1270,6 +1276,14 @@
 static int send_tcn_bpdu(int port_no, Tcn_bpdu *bpdu)
 {
 	struct sk_buff *skb;
+	
+	/*
+	 *	Keep silent when disabled or when STP disabled
+	 */
+	 
+	if(!(br_stats.flags & BR_UP) || (br_stats.flags & BR_STP_DISABLED))
+		return -1;
+	
  	
 	skb = alloc_bridge_skb(port_no, sizeof(Tcn_bpdu), "tcn");
 	if (skb == NULL)
@@ -1336,13 +1350,25 @@
 							enable_port(i);
 						set_path_cost(i, br_port_cost(dev));
 						set_port_priority(i); 
-						make_forwarding(i);
+						if (br_stats.flags & BR_STP_DISABLED)
+							port_info[i].state = Forwarding;
+						else
+							make_forwarding(i);
 					}
 					return NOTIFY_DONE;
 					break;
 				}
 			}
 			break;
+		case NETDEV_UNREGISTER:
+			if (br_stats.flags & BR_DEBUG)
+				printk(KERN_DEBUG "br_device_event: NETDEV_UNREGISTER...\n");
+                        i = find_port(dev);
+                        if (i > 0) {
+				br_avl_delete_by_port(i);
+				port_info[i].dev = NULL;
+			}
+			break;
 	}
 	return NOTIFY_DONE;
 }
@@ -1833,6 +1859,8 @@
  
 static int br_port_cost(struct device *dev)	/* 4.10.2 */
 {
+	if (strncmp(dev->name, "lec", 3) == 0)	/* ATM Lan Emulation (LANE) */
+		return(7);                      /* 155 Mbs */
 	if (strncmp(dev->name, "eth", 3) == 0)	/* ethernet */
 		return(100);
 	if (strncmp(dev->name, "plip",4) == 0) /* plip */
@@ -1850,7 +1878,8 @@
 	Tcn_bpdu *bpdu = (Tcn_bpdu *) (bufp + BRIDGE_LLC1_HS);
 	Config_bpdu rcv_bpdu;
 
-	if((*bufp++ == BRIDGE_LLC1_DSAP) && (*bufp++ == BRIDGE_LLC1_SSAP) &&
+	if(!(br_stats.flags & BR_STP_DISABLED) &&
+	        (*bufp++ == BRIDGE_LLC1_DSAP) && (*bufp++ == BRIDGE_LLC1_SSAP) &&
 		(*bufp++ == BRIDGE_LLC1_CTRL) &&
 		(bpdu->protocol_id == BRIDGE_BPDU_8021_PROTOCOL_ID) &&
 		(bpdu->protocol_version_id == BRIDGE_BPDU_8021_PROTOCOL_VERSION_ID)) 
@@ -1970,6 +1999,10 @@
 						}
 					}
 					port_state_selection();	  /* (4.8.1.5)	 */
+					if (br_stats.flags & BR_STP_DISABLED)
+						for(i=One;i<=No_of_ports; i++)
+							if((user_port_state[i] != Disabled) && port_info[i].dev)
+								port_info[i].state = Forwarding;
 					config_bpdu_generation();  /* (4.8.1.6)	 */
 					/* initialize system timer */
 					tl.expires = jiffies+HZ;	/* 1 second */
@@ -1986,6 +2019,20 @@
 					for (i = One; i <= No_of_ports; i++)
 						if (port_info[i].state != Disabled)
 							disable_port(i);
+					break;
+				case BRCMD_TOGGLE_STP:
+					printk(KERN_DEBUG "br: %s spanning tree protcol\n",
+					       (br_stats.flags & BR_STP_DISABLED) ? "enabling" : "disabling");
+					if (br_stats.flags & BR_STP_DISABLED) { /* enable STP */
+						for(i=One;i<=No_of_ports; i++)
+							if((user_port_state[i] != Disabled) && port_info[i].dev)
+								enable_port(i);
+					} else { /* STP was enabled, now disable it */
+						for (i = One; i <= No_of_ports; i++)
+							if (port_info[i].state != Disabled && port_info[i].dev)
+								port_info[i].state = Forwarding;
+					}
+					br_stats.flags ^= BR_STP_DISABLED;
 					break;
 				case BRCMD_PORT_ENABLE:
 					if (port_info[bcf.arg1].dev == 0)
diff -u --recursive --new-file v2.2.2/linux/net/bridge/br_tree.c linux/net/bridge/br_tree.c
--- v2.2.2/linux/net/bridge/br_tree.c	Fri Jan  8 22:36:25 1999
+++ linux/net/bridge/br_tree.c	Sun Mar  7 15:25:23 1999
@@ -474,3 +474,27 @@
 
 	return;
 }
+
+/*
+ * Delete all nodes learnt by the port
+ */
+void br_avl_delete_by_port(int port)
+{
+        struct fdb *fdb, *next;
+
+	if (!fdb_inited)
+		fdb_init();
+
+        for(fdb = port_info[port].fdb; fdb != NULL; fdb = next) {
+                next = fdb->fdb_next;
+                br_avl_remove(fdb);
+        }
+        port_info[port].fdb = NULL;
+
+        /* remove the local mac too */
+        next = br_avl_find_addr(port_info[port].dev->dev_addr);
+        if (next != NULL)
+                br_avl_remove(next);
+
+        return;
+}
diff -u --recursive --new-file v2.2.2/linux/net/core/scm.c linux/net/core/scm.c
--- v2.2.2/linux/net/core/scm.c	Sun Nov  8 14:03:13 1998
+++ linux/net/core/scm.c	Sun Mar  7 15:25:23 1999
@@ -27,7 +27,6 @@
 #include <asm/uaccess.h>
 
 #include <linux/inet.h>
-#include <linux/netdevice.h>
 #include <net/ip.h>
 #include <net/protocol.h>
 #include <net/rarp.h>
diff -u --recursive --new-file v2.2.2/linux/net/core/skbuff.c linux/net/core/skbuff.c
--- v2.2.2/linux/net/core/skbuff.c	Tue Feb 23 15:21:35 1999
+++ linux/net/core/skbuff.c	Sun Mar  7 10:12:18 1999
@@ -4,7 +4,7 @@
  *	Authors:	Alan Cox <iiitac@pyr.swan.ac.uk>
  *			Florian La Roche <rzsfl@rz.uni-sb.de>
  *
- *	Version:	$Id: skbuff.c,v 1.54 1998/09/15 02:11:09 davem Exp $
+ *	Version:	$Id: skbuff.c,v 1.55 1999/02/23 08:12:27 davem Exp $
  *
  *	Fixes:	
  *		Alan Cox	:	Fixed the worst of the load balancer bugs.
diff -u --recursive --new-file v2.2.2/linux/net/core/sock.c linux/net/core/sock.c
--- v2.2.2/linux/net/core/sock.c	Tue Feb 23 15:21:35 1999
+++ linux/net/core/sock.c	Sun Mar  7 10:12:18 1999
@@ -7,7 +7,7 @@
  *		handler for protocols to use and generic option handler.
  *
  *
- * Version:	$Id: sock.c,v 1.75 1998/11/07 10:54:38 davem Exp $
+ * Version:	$Id: sock.c,v 1.76 1999/02/23 08:12:29 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
diff -u --recursive --new-file v2.2.2/linux/net/econet/econet.c linux/net/econet/econet.c
--- v2.2.2/linux/net/econet/econet.c	Thu Nov 19 09:56:29 1998
+++ linux/net/econet/econet.c	Sun Mar  7 15:25:23 1999
@@ -44,7 +44,6 @@
 #include <net/udp.h>
 #include <net/ip.h>
 #include <asm/spinlock.h>
-#include <linux/inetdevice.h>
 
 static struct proto_ops econet_ops;
 static struct sock *econet_sklist;
diff -u --recursive --new-file v2.2.2/linux/net/ipv4/Config.in linux/net/ipv4/Config.in
--- v2.2.2/linux/net/ipv4/Config.in	Wed Jan 13 15:00:44 1999
+++ linux/net/ipv4/Config.in	Sun Mar  7 15:25:23 1999
@@ -78,7 +78,6 @@
 tristate 'IP: Reverse ARP' CONFIG_INET_RARP
 #bool 'IP: Path MTU Discovery (normally enabled)' CONFIG_PATH_MTU_DISCOVERY
 #bool 'IP: Disable NAGLE algorithm (normally enabled)' CONFIG_TCP_NAGLE_OFF
-bool 'IP: Drop source routed frames' CONFIG_IP_NOSR
 bool 'IP: Allow large windows (not recommended if <16Mb of memory)' CONFIG_SKB_LARGE
 #if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then 
 #bool 'IP: support experimental checksum copy to user for UDP'  CONFIG_UDP_DELAY_CSUM
diff -u --recursive --new-file v2.2.2/linux/net/ipv4/arp.c linux/net/ipv4/arp.c
--- v2.2.2/linux/net/ipv4/arp.c	Thu Nov 19 09:56:29 1998
+++ linux/net/ipv4/arp.c	Sun Mar  7 15:25:23 1999
@@ -557,6 +557,19 @@
 		if (htons(dev_type) != arp->ar_hrd)
 			goto out;
 		break;
+#ifdef CONFIG_NET_ETHERNET
+	case ARPHRD_ETHER:
+		/*
+		 * ETHERNET devices will accept ARP hardware types of either
+		 * 1 (Ethernet) or 6 (IEEE 802.2).
+		 */
+		if (arp->ar_hrd != __constant_htons(ARPHRD_ETHER) &&
+		    arp->ar_hrd != __constant_htons(ARPHRD_IEEE802))
+			goto out;
+		if (arp->ar_pro != __constant_htons(ETH_P_IP))
+			goto out;
+		break;
+#endif
 #ifdef CONFIG_FDDI
 	case ARPHRD_FDDI:
 		/*
diff -u --recursive --new-file v2.2.2/linux/net/ipv4/icmp.c linux/net/ipv4/icmp.c
--- v2.2.2/linux/net/ipv4/icmp.c	Tue Feb 23 15:21:35 1999
+++ linux/net/ipv4/icmp.c	Sun Mar  7 10:12:19 1999
@@ -3,7 +3,7 @@
  *	
  *		Alan Cox, <alan@cymru.net>
  *
- *	Version: $Id: icmp.c,v 1.48 1999/01/02 16:51:41 davem Exp $
+ *	Version: $Id: icmp.c,v 1.49 1999/02/23 08:12:37 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 --recursive --new-file v2.2.2/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- v2.2.2/linux/net/ipv4/tcp.c	Tue Feb 23 15:21:35 1999
+++ linux/net/ipv4/tcp.c	Sun Mar  7 10:12:19 1999
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp.c,v 1.135 1999/02/22 13:54:21 davem Exp $
+ * Version:	$Id: tcp.c,v 1.136 1999/03/07 13:26:01 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1070,6 +1070,7 @@
 	if(copied > 0) {
 		struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 		__u32 rcv_window_now = tcp_receive_window(tp);
+		__u32 new_window = __tcp_select_window(sk);
 
 		/* We won't be raising the window any further than
 		 * the window-clamp allows.  Our window selection
@@ -1077,7 +1078,7 @@
 		 * checks are necessary to prevent spurious ACKs
 		 * which don't advertize a larger window.
 		 */
-		if((copied >= rcv_window_now) &&
+		if((new_window && (new_window >= rcv_window_now * 2)) &&
 		   ((rcv_window_now + tp->mss_cache) <= tp->window_clamp))
 			tcp_read_wakeup(sk);
 	}
diff -u --recursive --new-file v2.2.2/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- v2.2.2/linux/net/ipv4/tcp_input.c	Tue Feb 23 15:21:35 1999
+++ linux/net/ipv4/tcp_input.c	Sun Mar  7 10:12:19 1999
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_input.c,v 1.156 1999/02/22 13:54:13 davem Exp $
+ * Version:	$Id: tcp_input.c,v 1.157 1999/03/05 09:35:06 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -241,8 +241,8 @@
 extern __inline__ int tcp_paws_discard(struct tcp_opt *tp, struct tcphdr *th, unsigned len)
 {
 	/* ts_recent must be younger than 24 days */
-	return (((jiffies - tp->ts_recent_stamp) >= PAWS_24DAYS) ||
-		(((s32)(tp->rcv_tsval-tp->ts_recent) < 0) &&
+	return (((s32)(jiffies - tp->ts_recent_stamp) >= PAWS_24DAYS) ||
+		(((s32)(tp->rcv_tsval - tp->ts_recent) < 0) &&
 		 /* Sorry, PAWS as specified is broken wrt. pure-ACKs -DaveM */
 		 (len != (th->doff * 4))));
 }
diff -u --recursive --new-file v2.2.2/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
--- v2.2.2/linux/net/ipv4/tcp_ipv4.c	Tue Feb 23 15:21:35 1999
+++ linux/net/ipv4/tcp_ipv4.c	Sun Mar  7 10:12:19 1999
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_ipv4.c,v 1.165 1999/02/08 11:19:56 davem Exp $
+ * Version:	$Id: tcp_ipv4.c,v 1.166 1999/02/23 08:12:41 davem Exp $
  *
  *		IPv4 specific functions
  *
diff -u --recursive --new-file v2.2.2/linux/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c
--- v2.2.2/linux/net/ipv4/tcp_output.c	Tue Feb 23 15:21:35 1999
+++ linux/net/ipv4/tcp_output.c	Sun Mar  7 10:12:19 1999
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_output.c,v 1.102 1999/02/22 13:54:26 davem Exp $
+ * Version:	$Id: tcp_output.c,v 1.104 1999/03/07 13:26:04 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -580,6 +580,18 @@
 	if(tp->af_specific->rebuild_header(sk))
 		return 1; /* Routing failure or similar. */
 
+	/* Some Solaris stacks overoptimize and ignore the FIN on a
+	 * retransmit when old data is attached.  So strip it off
+	 * since it is cheap to do so and saves bytes on the network.
+	 */
+	if(skb->len > 0 &&
+	   (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) &&
+	   tp->snd_una == (TCP_SKB_CB(skb)->end_seq - 1)) {
+		TCP_SKB_CB(skb)->seq = TCP_SKB_CB(skb)->end_seq - 1;
+		skb_trim(skb, 0);
+		skb->csum = 0;
+	}
+
 	/* Ok, we're gonna send it out, update state. */
 	TCP_SKB_CB(skb)->sacked |= TCPCB_SACKED_RETRANS;
 	tp->retrans_out++;
@@ -592,6 +604,7 @@
 		skb = skb_copy(skb, GFP_ATOMIC);
 	else
 		skb = skb_clone(skb, GFP_ATOMIC);
+
 	tcp_transmit_skb(sk, skb);
 
 	/* Update global TCP statistics and return success. */
diff -u --recursive --new-file v2.2.2/linux/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c
--- v2.2.2/linux/net/ipv6/tcp_ipv6.c	Tue Feb 23 15:21:36 1999
+++ linux/net/ipv6/tcp_ipv6.c	Sun Mar  7 10:12:19 1999
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: tcp_ipv6.c,v 1.95 1999/02/08 11:20:03 davem Exp $
+ *	$Id: tcp_ipv6.c,v 1.96 1999/03/05 13:23:13 davem Exp $
  *
  *	Based on: 
  *	linux/net/ipv4/tcp.c
@@ -1238,7 +1238,6 @@
 			goto reset;
 		if (users)
 			goto ipv6_pktoptions;
-		release_sock(sk);
 		return 0;
 	}
 
diff -u --recursive --new-file v2.2.2/linux/net/irda/Makefile linux/net/irda/Makefile
--- v2.2.2/linux/net/irda/Makefile	Wed Jan 20 23:14:07 1999
+++ linux/net/irda/Makefile	Sun Mar  7 15:26:44 1999
@@ -10,13 +10,19 @@
 ALL_SUB_DIRS := irlan ircomm irlpt compressors
 SUB_DIRS :=
 MOD_SUB_DIRS :=
+OX_OBJS :=
 
 O_TARGET := irda.o
-O_OBJS	 := irmod.o iriap.o iriap_event.o irlmp.o irlmp_event.o irlmp_frame.o \
+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
+OX_OBJS := irmod.o
+
 MOD_LIST_NAME := IRDA_MODULES
+
+ifeq ($(CONFIG_IRDA),m)
 M_OBJS   := $(O_TARGET)
+endif
 
 ifeq ($(CONFIG_IRDA_COMPRESSION),y)
 O_OBJS += irlap_comp.o
diff -u --recursive --new-file v2.2.2/linux/net/irda/af_irda.c linux/net/irda/af_irda.c
--- v2.2.2/linux/net/irda/af_irda.c	Wed Jan 20 23:14:07 1999
+++ linux/net/irda/af_irda.c	Sun Mar  7 15:26:44 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun May 31 10:12:43 1998
- * Modified at:   Thu Jan 14 13:42:16 1999
+ * Modified at:   Sat Feb 20 01:31:15 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       af_netroom.c, af_ax25.x
  * 
@@ -23,11 +23,17 @@
  *     
  ********************************************************************/
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
+#include <linux/init.h>
+#include <linux/if_arp.h>
+#include <linux/net.h>
+
+#include <asm/uaccess.h>
+
 #include <net/sock.h>
-#include <asm/segment.h>
 
 #include <net/irda/irda.h>
 #include <net/irda/irmod.h>
@@ -37,8 +43,12 @@
 extern void irda_cleanup(void);
 extern int irlap_input(struct sk_buff *, struct device *, struct packet_type *);
 
+static struct proto_ops irda_proto_ops;
+
 #define IRDA_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_HEADER)
 
+#define IRDA_SOCKETS
+
 #ifdef IRDA_SOCKETS
 
 /*
@@ -56,120 +66,6 @@
 }
 
 /*
- * Function irda_sendmsg (sock, msg, len, noblock, flags)
- *
- *    
- *
- */
-static int irda_sendmsg( struct socket *sock, struct msghdr *msg, int len, 
-			 int noblock, int flags)
-{
-#if 0
-	struct sock *sk = (struct sock *) sock->data;
-	/* struct sockaddr_irda *usax = (struct sockaddr_irda *)msg->msg_name; */
-	int err;
-	struct sk_buff *skb;
-	unsigned char *asmptr;
-	int size;
-	struct tsap_cb *tsap;
-	
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-	if (sk->err)
-		return sock_error(sk);
-
-	if (flags)
-		return -EINVAL;
-	
-	if (sk->zapped)
-		return -EADDRNOTAVAIL;
-	
-	if (sk->debug)
-		printk( "IrDA: sendto: Addresses built.\n");
-	
-	/* Build a packet */
-	if (sk->debug)
-		printk( "IrDA: sendto: building packet.\n");
-	
-	size = len + IRDA_MAX_HEADER;
-	
-	if ((skb = sock_alloc_send_skb(sk, size, 0, 0, &err)) == NULL)
-		return err;
-	
-	skb->sk   = sk;
-	skb->free = 1;
-	skb->arp  = 1;
-	
-	skb_reserve(skb, size - len);
-	
-	memcpy_fromiovec( asmptr, msg->msg_iov, len);
-	
-	if (sk->debug)
-		printk( "IrDA: Transmitting buffer\n");
-	
-        if (sk->state != TCP_ESTABLISHED) {
-                kfree_skb( skb, FREE_WRITE);
-		return -ENOTCONN;
-	}
-	
-	tsap = (struct tsap_cb *) sk->protinfo.irda;
-	ASSERT( tsap != NULL, return -ENODEV;);
-	ASSERT( tsap->magic == TTP_TSAP_MAGIC, return -EBADR;);
-	
-	irttp_data_request( tsap, skb);
-#endif	
-	return len;
-}
-
-/*
- * Function irda_recvmsg (sock, msg, size, noblock, flags, addr_len)
- *
- *    
- *
- */
-static int irda_recvmsg( struct socket *sock, struct msghdr *msg, int size, 
-			 int noblock, int flags, int *addr_len)
-{
-	int copied=0;
-#if 0
-	struct sock *sk = (struct sock *)sock->data;
-	struct sockaddr_irda *sax = (struct sockaddr_irda *)msg->msg_name;
-	struct sk_buff *skb;
-	int er;
-
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-	if (sk->err)
-		return sock_error(sk);
-	
-	if (addr_len != NULL)
-		*addr_len = sizeof(*sax);
-
-	/*
-	 * This works for seqpacket too. The receiver has ordered the queue for
-	 * us! We do one quick check first though
-	 */
-	if (sk->state != TCP_ESTABLISHED)
-		return -ENOTCONN;
-
-	/* Now we can treat all alike */
-	if ((skb = skb_recv_datagram( sk, flags, noblock, &er)) == NULL)
-		return er;
-
-/* 	if (!sk->nr->hdrincl) { */
-/* 		skb_pull(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN); */
-/* 		skb->h.raw = skb->data; */
-/* 	} */
-
-	copied = (size < skb->len) ? size : skb->len;
-	skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
-
-	skb_free_datagram(sk, skb);
-#endif
-	return copied;
-}
-
-/*
  * Function irda_listen (sock, backlog)
  *
  *    
@@ -177,52 +73,17 @@
  */
 static int irda_listen( struct socket *sock, int backlog)
 {
-#if 0
-	struct sock *sk = (struct sock *)sock->data;
+	struct sock *sk = sock->sk;
 
-	if (sk->state != TCP_LISTEN) {
+	if (sk->type == SOCK_SEQPACKET && sk->state != TCP_LISTEN) {
 		sk->max_ack_backlog = backlog;
 		sk->state           = TCP_LISTEN;
 		return 0;
-        }
-#endif
+	}
+
 	return -EOPNOTSUPP;
 }
 
-/*
- * Function irda_bind (sock, uaddr, addr_len)
- *
- *    Bind to a specified TSAP
- *
- */
-static int irda_bind( struct socket *sock, struct sockaddr *uaddr, 
-		      int addr_len)
-{
-#if 0	
-	struct sock *sk;
-	struct full_sockaddr_irda *addr = (struct full_sockaddr_irda *)uaddr;
-	struct device *dev;
-        irda_address *user, *source;
-        struct tsap_cb *tsap;
-	struct notify_t notify;
-
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-	sk = (struct sock *) sock->data;
-
-	if ( sk->zapped == 0)
-		return -EIO;
-	
-	irda_notify_init( &notify);
-	tsap = irttp_open_tsap( LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);
-
-	sk->zapped = 0;
-
-	if (sk->debug)
-		printk("IrDA: socket is bound\n");
-#endif
-	return 0;
-}
 
 /*
  * Function irda_connect (sock, uaddr, addr_len, flags)
@@ -289,83 +150,6 @@
 #endif
 	return 0;
 }
-	
-static int irda_socketpair( struct socket *sock1, struct socket *sock2)
-{
-	DEBUG( 0, __FUNCTION__ "(), Not implemented\n");
-
-	return -EOPNOTSUPP;
-}
-
-static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
-{
-	struct sock *sk;
-	struct sock *newsk;
-	struct sk_buff *skb;
-
-	DEBUG( 0, __FUNCTION__ "()\n");
-#if 0
-	if (newsock->data)
-		sk_free(newsock->data);
-
-	newsock->data = NULL;
-	
-	sk = (struct sock *)sock->data;
-
-	if (sk->type != SOCK_SEQPACKET)
-		return -EOPNOTSUPP;
-	
-	if (sk->state != TCP_LISTEN)
-		return -EINVAL;
-		
-	/*
-	 *	The write queue this time is holding sockets ready to use
-	 *	hooked into the SABM we saved
-	 */
-	do {
-		cli();
-		if ((skb = skb_dequeue(&sk->receive_queue)) == NULL) {
-			if (flags & O_NONBLOCK) {
-				sti();
-				return 0;
-			}
-			interruptible_sleep_on(sk->sleep);
-			if (current->signal & ~current->blocked) {
-				sti();
-				return -ERESTARTSYS;
-			}
-		}
-	} while (skb == NULL);
-
-	newsk = skb->sk;
-	newsk->pair = NULL;
-	sti();
-
-	/* Now attach up the new socket */
-	skb->sk = NULL;
-	kfree_skb(skb, FREE_READ);
-	sk->ack_backlog--;
-	newsock->data = newsk;
-#endif
-	return 0;
-}
-
-static void def_callback1(struct sock *sk)
-{
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-        if (!sk->dead)
-                wake_up_interruptible(sk->sleep);
-}
-
-static void def_callback2(struct sock *sk, int len)
-{
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-        if (!sk->dead)
-                wake_up_interruptible(sk->sleep);
-}
-
 
 /*
  * Function irda_create (sock, protocol)
@@ -373,47 +157,42 @@
  *    Create IrDA socket
  *
  */
-static int irda_create( struct socket *sock, int protocol)
+static int irda_create(struct socket *sock, int protocol)
 {
 	struct sock *sk;
 
 	DEBUG( 0, __FUNCTION__ "()\n");
-#if 0
-	if (sock->type != SOCK_SEQPACKET || protocol != 0)
-		return -ESOCKTNOSUPPORT;
+
+	/* Compatibility */
+	if (sock->type == SOCK_PACKET) {
+		static int warned; 
+		if (net_families[PF_PACKET]==NULL)
+		{
+#if defined(CONFIG_KMOD) && defined(CONFIG_PACKET_MODULE)
+			char module_name[30];
+			sprintf(module_name,"net-pf-%d", PF_PACKET);
+			request_module(module_name);
+			if (net_families[PF_PACKET] == NULL)
+#endif
+				return -ESOCKTNOSUPPORT;
+		}
+		if (!warned++)
+			printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n", current->comm);
+		return net_families[PF_PACKET]->create(sock, protocol);
+	}
+	
+/* 	if (sock->type != SOCK_SEQPACKET || protocol != 0) */
+/* 		return -ESOCKTNOSUPPORT; */
 
 	/* Allocate socket */
-	if ((sk = sk_alloc( GFP_ATOMIC)) == NULL)
+	if ((sk = sk_alloc(PF_IRDA, GFP_ATOMIC, 1)) == NULL)
 		return -ENOMEM;
+	
+	sock_init_data(sock, sk);
+
+	sock->ops    = &irda_proto_ops;
+	sk->protocol = protocol;
 
-	skb_queue_head_init(&sk->receive_queue);
-	skb_queue_head_init(&sk->write_queue);
-	skb_queue_head_init(&sk->back_log);
-
-	init_timer( &sk->timer);
-
-	sk->socket        = sock;
-	sk->type          = sock->type;
-	sk->protocol      = protocol;
-	sk->allocation	  = GFP_KERNEL;
-	sk->rcvbuf        = SK_RMEM_MAX;
-	sk->sndbuf        = SK_WMEM_MAX;
-	sk->state         = TCP_CLOSE;
-	sk->priority      = SOPRI_NORMAL;
-	sk->mtu           = 2048; /* FIXME, insert the right size*/
-	sk->zapped        = 1;
-/* 	sk->window	  = nr_default.window; */
-
-	sk->state_change = def_callback1;
-	sk->data_ready   = def_callback2;
-	sk->write_space  = def_callback1;
-	sk->error_report = def_callback1;
-
-	if (sock != NULL) {
-		sock->data = (void *)sk;
-		sk->sleep  = sock->wait;
-	}
-#endif
 	return 0;
 }
 
@@ -463,26 +242,32 @@
         return 0;
 }
 
-
-/*
- * Function irda_dup (newsock, oldsock)
- *
- *    
- *
- */
-static int irda_dup( struct socket *newsock, struct socket *oldsock)
+static int irda_recvmsg(struct socket *sock, struct msghdr *msg, int size,
+			int flags, struct scm_cookie *scm)
 {
-#if 0
-        struct sock *sk = (struct sock *)oldsock->data;
+	struct sock *sk = sock->sk;
+	struct sk_buff *skb;
+	int copied, err;
 
-	DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG(0, __FUNCTION__ "()\n");
 
-        if (sk == NULL || newsock == NULL)
-                return -EINVAL;
+	skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, 
+				flags & MSG_DONTWAIT, &err);
+	if (!skb)
+		return err;
 
-        return irda_create( newsock, sk->protocol);
-#endif
-	return 0;
+	skb->h.raw = skb->data;
+	copied     = skb->len;
+	
+	if (copied > size) {
+		copied = size;
+		msg->msg_flags |= MSG_TRUNC;
+	}
+	skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+
+	skb_free_datagram(sk, skb);
+
+	return copied;
 }
 
 static int irda_shutdown( struct socket *sk, int how)
@@ -497,7 +282,8 @@
 unsigned int irda_poll( struct file *file, struct socket *sock, 
 			struct poll_table_struct *wait)
 {
-	
+	DEBUG(0, __FUNCTION__ "()\n");
+	return 0;
 }
 
 /*
@@ -506,172 +292,114 @@
  *    
  *
  */
-static int irda_ioctl( struct socket *sock, unsigned int cmd, 
-		       unsigned long arg)
-{
-#if 0
-        struct sock *sk = (struct sock *) sock->data;
-        int err;
-
-	DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
-#endif
-	return 0;
-}
-
-static int irda_setsockopt( struct socket *sock, int level, int optname,
-			    char *optval, int optlen)
-{
-#if 0
-        struct sock *sk = (struct sock *)sock->data;
-        int err, opt;
-
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-        if (level == SOL_SOCKET)
-                return sock_setsockopt(sk, level, optname, optval, optlen);
-
-        /* if (level != SOL_AX25) */
-/*                 return -EOPNOTSUPP; */
-
-        if (optval == NULL)
-                return -EINVAL;
-
-        if ((err = verify_area(VERIFY_READ, optval, sizeof(int))) != 0)
-                return err;
-
-        opt = get_fs_long((int *)optval);
-
-        switch (optname) {  
-	default:
-		return -ENOPROTOOPT;
-        }
-#endif
-	return -ENOPROTOOPT;
-}
-
-static int irda_getsockopt(struct socket *sock, int level, int optname,
-        char *optval, int *optlen)
+static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
-#if 0
-        struct sock *sk = (struct sock *)sock->data;
-        int val = 0;
-        int err;
+	struct sock *sk = sock->sk;
 
 	DEBUG( 0, __FUNCTION__ "()\n");
-
-        if (level == SOL_SOCKET)
-                return sock_getsockopt(sk, level, optname, optval, optlen);
-
-        /* if (level != SOL_AX25) */
-/*                 return -EOPNOTSUPP; */
-
-        switch (optname) {
-	default:
-		return -ENOPROTOOPT;
-        }
 	
-        if ((err = verify_area(VERIFY_WRITE, optlen, sizeof(int))) != 0)
-                return err;
-
-        put_user(sizeof(int), optlen);
+	switch (cmd) {
+	case TIOCOUTQ: {
+		long amount;
+		amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);
+		if (amount < 0)
+			amount = 0;
+		if (put_user(amount, (unsigned int *)arg))
+			return -EFAULT;
+		return 0;
+	}
 	
-        if ((err = verify_area(VERIFY_WRITE, optval, sizeof(int))) != 0)
-                return err;
-
-        put_user(val, (int *)optval);
-#endif
-        return 0;
-}
-
-static int irda_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg)
-{
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-        return -EINVAL;
-}
-/*
- * Function irda_rcv (skb, dev, dev_addr, ptype)
- *
- *    
- *
- */
-static int irda_rcv( struct sk_buff *skb, struct device *dev, 
-		     irda_address *dev_addr, struct packet_type *ptype)
-{
-	DEBUG( 0, __FUNCTION__ "()\n");
+	case TIOCINQ: {
+		struct sk_buff *skb;
+		long amount = 0L;
+		/* These two are safe on a single CPU system as only user tasks fiddle here */
+		if ((skb = skb_peek(&sk->receive_queue)) != NULL)
+			amount = skb->len;
+		if (put_user(amount, (unsigned int *)arg))
+			return -EFAULT;
+		return 0;
+	}
+	
+	case SIOCGSTAMP:
+		if (sk != NULL) {
+			if (sk->stamp.tv_sec == 0)
+				return -ENOENT;
+			if (copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)))
+				return -EFAULT;
+			return 0;
+		}
+		return -EINVAL;
+		
+	case SIOCGIFADDR:
+	case SIOCSIFADDR:
+	case SIOCGIFDSTADDR:
+	case SIOCSIFDSTADDR:
+	case SIOCGIFBRDADDR:
+	case SIOCSIFBRDADDR:
+	case SIOCGIFNETMASK:
+	case SIOCSIFNETMASK:
+	case SIOCGIFMETRIC:
+	case SIOCSIFMETRIC:
+		return -EINVAL;
+		
+	default:
+		return dev_ioctl(cmd, (void *)arg);
+	}
 
+	/*NOTREACHED*/
 	return 0;
 }
 
-/*
- * Function irda_driver_rcv (skb, dev, ptype)
- *
- *    
- *
- */
-static int irda_driver_rcv( struct sk_buff *skb, struct device *dev, 
-			    struct packet_type *ptype)
+static struct net_proto_family irda_family_ops =
 {
-        skb->sk = NULL;         /* Initially we don't know who it's for */
-	
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-#if 0
-        if ((*skb->data & 0x0F) != 0) {
-                kfree_skb(skb, FREE_READ);      /* Not a KISS data frame */
-                return 0;
-        }
-
-        /* skb_pull(skb, AX25_KISS_HEADER_LEN);  */   /* Remove the KISS byte */
-
-        return irda_rcv( skb, dev, (irda_address *)dev->dev_addr, ptype);
-#endif
-	return NULL;
-}
+	PF_IRDA,
+	irda_create
+};
 
 static struct proto_ops irda_proto_ops = {
-	AF_IRDA,
+	PF_IRDA,
 	
-	irda_create,
-	irda_dup,
+	sock_no_dup,
 	irda_release,
-	irda_bind,
+	sock_no_bind,
 	irda_connect,
-	irda_socketpair,
-	irda_accept,
+	sock_no_socketpair,
+	sock_no_accept,
 	irda_getname,
 	irda_poll,
 	irda_ioctl,
 	irda_listen,
 	irda_shutdown,
-	irda_setsockopt,
-	irda_getsockopt,
-	irda_fcntl,
-	irda_sendmsg,
+	sock_no_setsockopt,
+	sock_no_getsockopt,
+	sock_no_fcntl,
+	sock_no_sendmsg,
 	irda_recvmsg
 };
 
 #endif /* IRDA_SOCKETS */
 
-static int irda_device_event( struct notifier_block *this, unsigned long event,
-			      void *ptr)
+static int irda_device_event(struct notifier_block *this, unsigned long event,
+			     void *ptr)
 {
-	/* struct device *dev = (struct device *) ptr; */
+	struct device *dev = (struct device *) ptr;
 	
-	DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG(3, __FUNCTION__ "()\n");
 	
-        /* Reject non AX.25 devices */
-	/*  if (dev->type != ARPHRD_AX25) */
-/*                 return NOTIFY_DONE; */
+        /* Reject non IrDA devices */
+	if (dev->type != ARPHRD_IRDA) 
+		return NOTIFY_DONE;
 	
         switch (event) {
 	case NETDEV_UP:
-		/* ax25_dev_device_up(dev); */
+		DEBUG(3, __FUNCTION__ "(), NETDEV_UP\n");
+		/* irda_dev_device_up(dev); */
 		break;
 	case NETDEV_DOWN:
-		/* ax25_kill_by_device(dev); */
-/*                         ax25_rt_device_down(dev); */
-/*                         ax25_dev_device_down(dev); */
+		DEBUG(3, __FUNCTION__ "(), NETDEV_DOWN\n");
+		/* irda_kill_by_device(dev); */
+		/* irda_rt_device_down(dev); */
+		/* irda_dev_device_down(dev); */
 		break;
 	default:
 		break;
@@ -701,17 +429,17 @@
  *    Initialize IrDA protocol layer
  *
  */
-void irda_proto_init(struct net_proto *pro)
+__initfunc(void irda_proto_init(struct net_proto *pro))
 {
 	DEBUG( 4, __FUNCTION__ "\n");
 
-	/* sock_register( irda_proto_ops.family, &irda_proto_ops); */
+	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);
 
-	/* printk( KERN_INFO "IrDA Sockets for Linux (Dag Brattli)\n"); */
 	irda_init();
 }
 
@@ -728,9 +456,9 @@
 	irda_packet_type.type = htons(ETH_P_IRDA);
         dev_remove_pack(&irda_packet_type);
 
-        /* unregister_netdevice_notifier( &irda_dev_notifier); */
+        unregister_netdevice_notifier( &irda_dev_notifier);
 	
-	/* (void) sock_unregister( irda_proto_ops.family); */
+	sock_unregister(PF_IRDA);
 	irda_cleanup();
 	
         return;
diff -u --recursive --new-file v2.2.2/linux/net/irda/ircomm/attach.c linux/net/irda/ircomm/attach.c
--- v2.2.2/linux/net/irda/ircomm/attach.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/ircomm/attach.c	Sun Mar  7 15:26:44 1999
@@ -44,7 +44,8 @@
 
 static void got_lsapsel(struct ircomm_cb * info);
 static void query_lsapsel(struct ircomm_cb * self);
-void ircomm_getvalue_confirm( __u16 obj_id, struct ias_value *value, void *priv );
+void ircomm_getvalue_confirm( __u16 obj_id, struct ias_value *value, 
+			      void *priv);
 
 #if 0
 static char *rcsid = "$Id: attach.c,v 1.11 1998/10/22 12:02:20 dagb Exp $";
@@ -55,14 +56,20 @@
  * handler for iriap_getvaluebyclass_request() 
  *
  */
-
-void ircomm_getvalue_confirm( __u16 obj_id, struct ias_value *value, void *priv ){
-
+void ircomm_getvalue_confirm( __u16 obj_id, struct ias_value *value,void *priv)
+{
 	struct ircomm_cb *self = (struct ircomm_cb *) priv;
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IRCOMM_MAGIC, return;);
 
+	/* Check if request succeeded */
+	if ( !value) {
+		DEBUG( 0, __FUNCTION__ "(), got NULL value!\n");
+
+		return;
+	}
+
 	DEBUG(0, __FUNCTION__"type(%d)\n", value->type);
 
 	switch(value->type){
@@ -100,9 +107,8 @@
 		break;
 
 	case IAS_STRING:
-		DEBUG( 0, __FUNCTION__":STRING is not implemented\n");
-		DEBUG( 0, __FUNCTION__":received string:%s\n",
-		       value->t.string);
+		DEBUG(0, __FUNCTION__":STRING is not implemented\n");
+		DEBUG(0, __FUNCTION__":received string:%s\n", value->t.string);
 		query_lsapsel(self);  /* experiment */
 		break;
 
@@ -116,9 +122,8 @@
 	}
 }
 
-
-static void got_lsapsel(struct ircomm_cb * self){
-
+static void got_lsapsel(struct ircomm_cb * self)
+{
 	struct notify_t notify;
 
 	DEBUG(0, "ircomm:got_lsapsel: got peersap!(%d)\n", self->dlsap );
@@ -136,11 +141,10 @@
 	strncpy( notify.name, "IrCOMM cli", NOTIFY_MAX_NAME);
 	notify.instance = self;
 	
-	self->tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT,
-				     &notify );
+	self->tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, 
+				     &notify);
 	ASSERT(self->tsap != NULL, return;);
 
-
 	/*
 	 * invoke state machine  
 	 * and notify that I'm ready to accept connect_request
@@ -150,26 +154,22 @@
   	if(self->d_handler)
  		self->d_handler(self);
 }
-
-
-
-
 		
-static void query_lsapsel(struct ircomm_cb * self){
-
+static void query_lsapsel(struct ircomm_cb * self)
+{
 	DEBUG(0, "ircomm:query_lsapsel..\n");
 
 	/*  
 	 *  since we've got Parameters field of IAS, we are to get peersap.
 	 */
 	
-	if(!(self->servicetype & THREE_WIRE_RAW)){
-		iriap_getvaluebyclass_request
-			(self->daddr, "IrDA:IrCOMM", "IrDA:TinyTP:LsapSel",
-			 ircomm_getvalue_confirm, self );
+	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,"ircomm:query_lsap:"
-		      "THREE_WIRE_RAW is not implemented!\n");
+		DEBUG(0, __FUNCTION__ "THREE_WIRE_RAW is not implemented!\n");
 	}
 }
 
@@ -183,7 +183,6 @@
 
 void ircomm_discovery_indication( DISCOVERY *discovery)
 {
-
 	struct ircomm_cb *self;
 
  	DEBUG( 0, "ircomm_discovery_indication\n");
@@ -193,6 +192,7 @@
 	ASSERT(self->magic == IRCOMM_MAGIC, return;);
 
 	self->daddr = discovery->daddr;
+	self->saddr = discovery->saddr;
 
 	DEBUG( 0, "ircomm_discovery_indication:daddr=%08x\n", self->daddr);
 
@@ -201,7 +201,6 @@
 	DEBUG(0, "ircomm:querying parameters..\n");
 #if 0
 	iriap_getvaluebyclass_request(self->daddr, "IrDA:IrCOMM",
-
 				      "Parameters",
 				      ircomm_getvalue_confirm,
 				      self);
@@ -214,8 +213,8 @@
 
 struct ircomm_cb * ircomm_attach_cable( __u8 servicetype,
 					struct notify_t notify, 
-					void *handler ){
-
+					void *handler )
+{
 	int i;
 	struct ircomm_cb *self = NULL;
 	struct notify_t server_notify;
@@ -317,15 +316,11 @@
 	return (self);
 }
 
-
-
-
-int ircomm_detach_cable(struct ircomm_cb *self){
-
+int ircomm_detach_cable(struct ircomm_cb *self)
+{
 	ASSERT( self != NULL, return -EIO;);
 	ASSERT( self->magic == IRCOMM_MAGIC, return -EIO;);
 
-
 	DEBUG(0,"ircomm_detach_cable:\n");
 
 	/* shutdown ircomm layer */
@@ -360,5 +355,6 @@
 
 	self->tsap = NULL;
 	self->in_use = 0;
+
 	return 0;
 }
diff -u --recursive --new-file v2.2.2/linux/net/irda/ircomm/ircomm_common.c linux/net/irda/ircomm/ircomm_common.c
--- v2.2.2/linux/net/irda/ircomm/ircomm_common.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/ircomm/ircomm_common.c	Sun Mar  7 15:26:44 1999
@@ -236,7 +236,9 @@
  * ---------------------------------------------------------------------- 
  */
 
-void ircomm_accept_data_indication(void *instance, void *sap, struct sk_buff *skb){
+void ircomm_accept_data_indication(void *instance, void *sap, 
+				   struct sk_buff *skb)
+{
 	
 	struct ircomm_cb *self = (struct ircomm_cb *)instance;
 
@@ -250,7 +252,8 @@
 
 void ircomm_accept_connect_confirm(void *instance, void *sap,
 				   struct qos_info *qos, 
-				   int maxsdusize, struct sk_buff *skb){
+				   int maxsdusize, struct sk_buff *skb)
+{
 
 	struct ircomm_cb *self = (struct ircomm_cb *)instance;
 
@@ -277,8 +280,8 @@
 void ircomm_accept_connect_indication(void *instance, void *sap,
 				      struct qos_info *qos,
 				      int maxsdusize,
-				      struct sk_buff *skb ){
-
+				      struct sk_buff *skb )
+{
 	struct ircomm_cb *self = (struct ircomm_cb *)instance;
 
 	ASSERT( self != NULL, return;);
@@ -297,8 +300,10 @@
 	ircomm_do_event( self, TTP_CONNECT_INDICATION, skb);
 }
 
-void ircomm_accept_disconnect_indication(void *instance, void *sap, LM_REASON reason,
-					 struct sk_buff *skb){
+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;);
@@ -309,7 +314,8 @@
 	ircomm_do_event( self, TTP_DISCONNECT_INDICATION, skb);
 }
 
-void ircomm_accept_flow_indication( void *instance, void *sap, LOCAL_FLOW cmd){
+void ircomm_accept_flow_indication( void *instance, void *sap, LOCAL_FLOW cmd)
+{
 	
 	struct ircomm_cb *self = (struct ircomm_cb *)instance;
 
@@ -349,10 +355,9 @@
  * ----------------------------------------------------------------------
  */
 
-
 static void issue_connect_request(struct ircomm_cb *self,
-				  struct sk_buff *userdata ){
-
+				  struct sk_buff *userdata )
+{
 	/* TODO: we have to send/build userdata field which contains 
 	   InitialControlParameters */
 	/* but userdata field is not implemeted in irttp.c.. */
@@ -365,7 +370,8 @@
 		break;
 
 	case DEFAULT: 
-		irttp_connect_request(self->tsap, self->dlsap, self->daddr,
+		irttp_connect_request(self->tsap, self->dlsap, 
+				      self->saddr, self->daddr,
 				      NULL, self->maxsdusize, NULL);  
  		break; 
 		
@@ -373,7 +379,8 @@
 	case NINE_WIRE:
 	case CENTRONICS:
 
-		irttp_connect_request(self->tsap, self->dlsap, self->daddr, 
+		irttp_connect_request(self->tsap, self->dlsap, 
+				      self->saddr, self->daddr, 
 				      NULL, self->maxsdusize, NULL); 
 		break;
 
@@ -383,8 +390,8 @@
 	}
 }	
 
-
-static void disconnect_indication(struct ircomm_cb *self, struct sk_buff *skb){
+static void disconnect_indication(struct ircomm_cb *self, struct sk_buff *skb)
+{
 
 	/*
 	 * Not implemented parameter"Reason".That is optional.
@@ -399,7 +406,8 @@
 }
 
 static void connect_indication(struct ircomm_cb *self, struct qos_info *qos, 
-			       struct sk_buff *skb){
+			       struct sk_buff *skb)
+{
 
 /* If controlparameters don't exist, we use the servicetype"DEFAULT".*/
 /* 	if( !ircomm_parse_controlchannel( self, data)) */
@@ -412,13 +420,15 @@
     
 #if 0
 /*   it's for THREE_WIRE_RAW.*/
-static void connect_indication_three_wire_raw(void){ 
+static void connect_indication_three_wire_raw(void)
+{ 
 	DEBUG(0,"ircomm:connect_indication_threewire():not implemented!");
 }    
 #endif 
 
 
-static void connect_confirmation(struct ircomm_cb *self, struct sk_buff *skb){
+static void connect_confirmation(struct ircomm_cb *self, struct sk_buff *skb)
+{
 
 	/* give a connect_confirm to the client */
 	if( self->notify.connect_confirm )
@@ -427,7 +437,8 @@
 }
 
 static void issue_connect_response(struct ircomm_cb *self,
-				   struct sk_buff *skb ){
+				   struct sk_buff *skb)
+{
 
 	DEBUG(0,"ircomm:issue_connect_response:\n");
 	
@@ -441,7 +452,8 @@
 }
 
 static void issue_disconnect_request(struct ircomm_cb *self,
-				struct sk_buff *userdata ){
+				     struct sk_buff *userdata)
+{
 	if(self->servicetype == THREE_WIRE_RAW){
 		DEBUG(0,"ircomm:issue_disconnect_request():3wireraw is not implemented!");
 	}
@@ -450,7 +462,8 @@
 }
     
 static void issue_data_request(struct ircomm_cb *self,
-			       struct sk_buff *userdata ){
+			       struct sk_buff *userdata )
+{
 	int err;
 
 	if(self->servicetype == THREE_WIRE_RAW){
@@ -469,7 +482,8 @@
 }
 
 static void issue_control_request(struct ircomm_cb *self,
-				  struct sk_buff *userdata ){
+				  struct sk_buff *userdata )
+{
 	if(self->servicetype == THREE_WIRE_RAW){
 		DEBUG(0,"THREE_WIRE_RAW is not implemented\n");
 		
@@ -478,8 +492,8 @@
 	}
 }
 
-
-static void process_data(struct ircomm_cb *self, struct sk_buff *skb ){
+static void process_data(struct ircomm_cb *self, struct sk_buff *skb )
+{
 	
 	DEBUG(4,"ircomm:process_data:skb_len is(%d),clen_is(%d)\n",
 	      (int)skb->len ,(int)skb->data[0]);
@@ -496,7 +510,8 @@
 					     skb);
 }
 
-void ircomm_data_indication(struct ircomm_cb *self, struct sk_buff *skb){
+void 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");
 }
@@ -510,14 +525,16 @@
  */
 
 static void ircomm_do_event( struct ircomm_cb *self, IRCOMM_EVENT event,
-			     struct sk_buff *skb) {
+			     struct sk_buff *skb) 
+{
 	
 	DEBUG( 4, "ircomm_do_event: STATE = %s, EVENT = %s\n",
 	       ircommstate[self->state], ircommevent[event]);
 	(*state[ self->state ]) ( self, event, skb);
 }
 
-void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state) {
+void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state) 
+{
 	self->state = state;
 	DEBUG( 0, "ircomm_next_state: NEXT STATE = %d(%s), sv(%d)\n", 
 	       (int)state, ircommstate[self->state],self->servicetype);
@@ -530,7 +547,8 @@
  */
 
 static void ircomm_state_discovery( struct ircomm_cb *self,
-				    IRCOMM_EVENT event, struct sk_buff *skb ){
+				    IRCOMM_EVENT event, struct sk_buff *skb )
+{
 	DEBUG(0,"ircomm_state_discovery: "
 	      "why call me? \n");
 	if(skb)
@@ -543,7 +561,8 @@
  */
 
 static void ircomm_state_idle( struct ircomm_cb *self, IRCOMM_EVENT event, 
-			       struct sk_buff *skb ){
+			       struct sk_buff *skb )
+{
 	switch(event){
 	case IRCOMM_CONNECT_REQUEST:
 
@@ -577,7 +596,8 @@
  */
 
 static void ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event, 
-			  struct sk_buff *skb ){
+			  struct sk_buff *skb )
+{
 	switch(event){
 	case TTP_CONNECT_CONFIRM:
 		ircomm_next_state(self, COMM_CONN);
@@ -607,7 +627,8 @@
  * ircomm_state_waitr
  */
 static void ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event, 
-			  struct sk_buff *skb ) {
+			  struct sk_buff *skb ) 
+{
 	
 	switch(event){
 	case IRCOMM_CONNECT_RESPONSE:
@@ -651,7 +672,8 @@
  */
 
 static void ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event, 
-			  struct sk_buff *skb ){
+			      struct sk_buff *skb )
+{
 	switch(event){
 	case TTP_DATA_INDICATION:
 		process_data(self, skb);
@@ -696,7 +718,8 @@
  */
 
 
-void ircomm_connect_request(struct ircomm_cb *self, int maxsdusize){
+void ircomm_connect_request(struct ircomm_cb *self, int maxsdusize)
+{
 
 	/*
 	 * TODO:build a packet which contains "initial control parameters"
@@ -713,7 +736,8 @@
 }
 
 void ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata,
-			     int maxsdusize){
+			     int maxsdusize)
+{
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IRCOMM_MAGIC, return;);
@@ -746,7 +770,9 @@
 	ircomm_do_event(self, IRCOMM_CONNECT_RESPONSE, userdata);
 }	
 
-void ircomm_disconnect_request(struct ircomm_cb *self, struct sk_buff *userdata){
+void ircomm_disconnect_request(struct ircomm_cb *self, 
+			       struct sk_buff *userdata)
+{
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IRCOMM_MAGIC, return;);
@@ -756,7 +782,8 @@
 }	
 
 
-void ircomm_data_request(struct ircomm_cb *self, struct sk_buff *userdata){
+void ircomm_data_request(struct ircomm_cb *self, struct sk_buff *userdata)
+{
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IRCOMM_MAGIC, return;);
@@ -780,7 +807,8 @@
  *  ----------------------------------------------------------------------
  */
 
-static void ircomm_tx_ctrlbuffer(struct ircomm_cb *self ){
+static void ircomm_tx_ctrlbuffer(struct ircomm_cb *self )
+{
 
 	__u8 clen;
 	struct sk_buff *skb = self->ctrl_skb;
@@ -817,7 +845,8 @@
 }
 
 
-void ircomm_control_request(struct ircomm_cb *self){
+void ircomm_control_request(struct ircomm_cb *self)
+{
 	
 	struct sk_buff *skb;
 
@@ -839,8 +868,9 @@
 }
 
 
-static void append_tuple(struct ircomm_cb *self,
-			 __u8 instruction, __u8 pl , __u8 *value){
+static void append_tuple(struct ircomm_cb *self, __u8 instruction, __u8 pl , 
+			 __u8 *value)
+{
 
 	__u8 *frame;
 	struct sk_buff *skb;
@@ -886,7 +916,8 @@
  * to peer device
  */
 
-void ircomm_append_ctrl(struct ircomm_cb *self,  __u8 instruction){
+void ircomm_append_ctrl(struct ircomm_cb *self,  __u8 instruction)
+{
 
 	__u8  pv[70];
 	__u8  *value = &pv[0];
@@ -1028,7 +1059,8 @@
 
 static void ircomm_parse_control(struct ircomm_cb *self,
 				 struct sk_buff *skb,
-				 int type){
+				 int type)
+{
 
 	__u8 *data;
 	__u8 pi,pl,pv[64];
@@ -1210,7 +1242,8 @@
 
 #ifdef MODULE
 
-int init_module(void) {
+int init_module(void) 
+{
 	ircomm_init();
 
 	DEBUG( 4, "ircomm:init_module:done\n");
@@ -1238,7 +1271,8 @@
  *
  */
 int ircomm_proc_read(char *buf, char **start, off_t offset,
-		     int len, int unused){
+		     int len, int unused)
+{
 	int i, index;
 
 	len = 0;
@@ -1284,7 +1318,6 @@
 	}
 	return len;
 }
-
 
 #endif /* CONFIG_PROC_FS */
 
diff -u --recursive --new-file v2.2.2/linux/net/irda/irda_device.c linux/net/irda/irda_device.c
--- v2.2.2/linux/net/irda/irda_device.c	Wed Jan 20 23:14:07 1999
+++ linux/net/irda/irda_device.c	Sun Mar  7 15:26:44 1999
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irda_device.c
- * Version:       0.3
+ * Version:       0.4
  * Description:   Abstract device driver layer and helper functions
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Wed Sep  2 20:22:08 1998
- * Modified at:   Mon Jan 18 11:05:59 1999
+ * Modified at:   Tue Feb 16 17:36:04 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -30,10 +30,15 @@
 #include <linux/if_arp.h>
 #include <linux/netdevice.h>
 #include <linux/init.h>
+#include <linux/tty.h>
 
-#include <net/pkt_sched.h>
+#include <asm/ioctls.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/dma.h>
 
+#include <net/pkt_sched.h>
+
 #include <net/irda/irda_device.h>
 #include <net/irda/irlap_frame.h>
 #include <net/irda/timer.h>
@@ -45,11 +50,10 @@
 extern int esi_init(void);
 extern int tekram_init(void);
 extern int actisys_init(void);
+extern int girbil_init(void);
 
 hashbin_t *irda_device = NULL;
 
-void irda_device_start_todo_timer( struct irda_device *self, int timeout);
-
 /* Netdevice functions */
 static int irda_device_net_rebuild_header(struct sk_buff *skb);
 static int irda_device_net_hard_header(struct sk_buff *skb, 
@@ -67,8 +71,6 @@
 
 __initfunc(int irda_device_init( void))
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
-
 	/* Allocate master array */
 	irda_device = hashbin_new( HB_LOCAL);
 	if ( irda_device == NULL) {
@@ -98,7 +100,9 @@
 #ifdef CONFIG_ACTISYS_DONGLE
 	actisys_init();
 #endif
-
+#ifdef CONFIG_GIRBIL_DONGLE
+	girbil_init();
+#endif
 	return 0;
 }
 
@@ -178,7 +182,7 @@
 	 * a name like "irda0" and the self->descriptin will get a name
 	 * like "irda0 <-> irtty0" 
 	 */
-	strncpy( self->description, self->name, 4);
+	strncpy( self->description, self->name, 5);
 	strcat( self->description, " <-> ");
 	strncat( self->description, name, 23);
 
@@ -280,16 +284,11 @@
  */
 static void __irda_device_change_speed( struct irda_device *self, int speed)
 {
-	ASSERT( self != NULL, return;);
-
-	if ( self->magic != IRDA_DEVICE_MAGIC) {
-		DEBUG( 0, __FUNCTION__ 
-		       "(), irda device is gone! Maybe you need to update "
-		       "your irmanager and/or irattach!");
-		       
-		       return;
-	}
+	DEBUG(4, __FUNCTION__ "(), <%ld>\n", jiffies);
 
+	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.
@@ -304,9 +303,9 @@
 			self->qos.baud_rate.value = speed;
 		}
 	} else {
-		DEBUG( 0, __FUNCTION__ "(), Warning, wait_until_sent() "
-		       "is not implemented by the irda_device!\n");
-     
+		DEBUG(0, __FUNCTION__ "(), Warning, wait_until_sent() "
+		      "has not implemented by the device driver!\n");
+		
 	}
 }
 
@@ -323,9 +322,8 @@
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IRDA_DEVICE_MAGIC, return;);
 
-	irda_execute_as_process( self, 
-				 (TODO_CALLBACK) __irda_device_change_speed, 
-				 speed);
+	irda_execute_as_process(
+		self, (TODO_CALLBACK) __irda_device_change_speed, speed);
 }
 
 inline int irda_device_is_media_busy( struct irda_device *self)
@@ -368,28 +366,6 @@
 	__irda_device_change_speed( self, self->new_speed);
 }
 
-/*
- * Function irda_device_start_todo_timer (self, timeout)
- *
- *    Start todo timer. This function is used to delay execution of certain
- *    functions. Its implemented using timers since delaying a timer or a
- *    bottom halves function can be very difficult othervise.
- *
- */
-void irda_device_start_todo_timer( struct irda_device *self, int timeout)
-{
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRDA_DEVICE_MAGIC, return;);
-
-	del_timer( &self->todo_timer);
-	
-	self->todo_timer.data     = (unsigned long) self;
-	self->todo_timer.function = &irda_device_todo_expired;
-	self->todo_timer.expires  = jiffies + timeout;
-	
-	add_timer( &self->todo_timer);
-}
-
 static struct enet_statistics *irda_device_get_stats( struct device *dev)
 {
 	struct irda_device *priv = (struct irda_device *) dev->priv;
@@ -420,7 +396,7 @@
 	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->hard_header     = irda_device_net_hard_header; */
         dev->hard_header_len = 0;
         dev->addr_len        = 0;
 
@@ -435,7 +411,7 @@
 	
 	dev_init_buffers( dev);
 
-	dev->flags = 0; /* IFF_NOARP | IFF_POINTOPOINT; */
+	dev->flags = 0;
 	
 	return 0;
 }
@@ -453,16 +429,15 @@
 	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)
+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 PPP_HARD_HDR_LEN; */
 	
 	return 0;
 }
@@ -535,14 +510,44 @@
 }
 
 #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_DONGLE)
+		len += sprintf( buf+len, "DONGLE ");
+
+	len += sprintf( buf+len, "\n");
+
+	return len;
+}
+
 /*
- * Function irlap_proc_read (buf, start, offset, len, unused)
+ * 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)
+int irda_device_proc_read(char *buf, char **start, off_t offset, int len, 
+			  int unused)
 {
 	struct irda_device *self;
 	unsigned long flags;
@@ -552,32 +557,33 @@
 
 	len = 0;
 
-	self = (struct irda_device *) hashbin_get_first( irda_device);
+	self = (struct irda_device *) hashbin_get_first(irda_device);
 	while ( self != NULL) {
-		len += sprintf( buf+len, "device name: %s\n", self->name);
-		len += sprintf( buf+len, "description: %s\n", 
-				self->description);
-		len += sprintf( buf+len, "  tbusy=%s\n", self->netdev.tbusy ? 
-				"TRUE" : "FALSE");
-		len += sprintf( buf+len, "  bps\tmaxtt\tdsize\twinsize\taddbofs\tmintt\tldisc\n");
+		len += sprintf(buf+len, "%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");
 		
-		len += sprintf( buf+len, "  %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);
+		self = (struct irda_device *) hashbin_get_next(irda_device);
 	}
 	restore_flags(flags);
 
diff -u --recursive --new-file v2.2.2/linux/net/irda/iriap.c linux/net/irda/iriap.c
--- v2.2.2/linux/net/irda/iriap.c	Wed Jan 20 23:14:07 1999
+++ linux/net/irda/iriap.c	Sun Mar  7 15:26:44 1999
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      iriap.c
- * Version:       0.1
+ * Version:       0.8
  * Description:   Information Access Protocol (IAP)
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Aug 21 00:02:07 1997
- * Modified at:   Tue Dec 15 16:00:35 1998
+ * Modified at:   Thu Feb 11 01:22:44 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
@@ -33,18 +33,35 @@
 
 #include <net/irda/irda.h>
 #include <net/irda/irttp.h>
+#include <net/irda/irmod.h>
 #include <net/irda/irlmp.h>
 #include <net/irda/irias_object.h>
 #include <net/irda/iriap_event.h>
 #include <net/irda/iriap.h>
 
+/* FIXME: This one should go in irlmp.c */
+static const char *ias_charset_types[] = {
+	"CS_ASCII",
+	"CS_ISO_8859_1",
+	"CS_ISO_8859_2",
+	"CS_ISO_8859_3",
+	"CS_ISO_8859_4",
+	"CS_ISO_8859_5",
+	"CS_ISO_8859_6",
+	"CS_ISO_8859_7",
+	"CS_ISO_8859_8",
+	"CS_ISO_8859_9",
+	"CS_UNICODE"
+};
+
 hashbin_t *iriap = NULL;
 
+extern char *lmp_reasons[];
+
 static struct iriap_cb *iriap_open( __u8 slsap, int mode);
 static void __iriap_close( struct iriap_cb *self);
-static void iriap_disconnect_indication( void *instance, void *sap, 
-					 LM_REASON reason, 
-					 struct sk_buff *skb);
+static void iriap_disconnect_indication(void *instance, void *sap, 
+					LM_REASON reason, struct sk_buff *skb);
 
 /*
  * Function iriap_init (void)
@@ -56,7 +73,7 @@
 {
 	struct ias_object *obj;
 
-	DEBUG( 4, "--> iriap_init\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 	
 	/* Allocate master array */
 	iriap = hashbin_new( HB_LOCAL);
@@ -91,8 +108,6 @@
 	 */
 	iriap_open( LSAP_IAS, IAS_SERVER);
 	
-	DEBUG( 4, "iriap_init -->\n");
-	
 	return 0;
 }
 
@@ -151,14 +166,14 @@
 		DEBUG( 0, "iriap_open: Unable to allocated LSAP!\n");
 		return NULL;
 	}
-	DEBUG( 4, "iriap_register: source LSAP sel=%02x\n", slsap_sel);
+	DEBUG( 4, __FUNCTION__ "(), source LSAP sel=%02x\n", slsap_sel);
 	
 	self->magic = IAS_MAGIC;
 	self->lsap = lsap;
 	self->slsap_sel = slsap_sel;
 	self->mode = mode;
 
-	init_timer( &self->watchdog_timer);
+	/* init_timer( &self->watchdog_timer); */
 
 	hashbin_insert( iriap, (QUEUE*) self, slsap_sel, NULL);
 	
@@ -178,10 +193,12 @@
  */
 static void __iriap_close( struct iriap_cb *self)
 {
+	DEBUG( 4, __FUNCTION__ "()\n");
+
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IAS_MAGIC, return;);
 
-	del_timer( &self->watchdog_timer);
+	/* del_timer( &self->watchdog_timer); */
 
 	self->magic = 0;
 
@@ -195,7 +212,9 @@
  */
 void iriap_close( struct iriap_cb *self)
 {
-	DEBUG( 4, "iriap_close()\n");
+	struct iriap_cb *entry;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IAS_MAGIC, return;);
@@ -205,7 +224,9 @@
 		self->lsap = NULL;
 	}
 
-	hashbin_remove( iriap, self->slsap_sel, NULL);
+	entry = (struct iriap_cb *) hashbin_remove( iriap, self->slsap_sel, 
+						    NULL);
+	ASSERT( entry == self, return;);
 
 	__iriap_close( self);
 }
@@ -221,7 +242,7 @@
 {
 	struct iriap_cb *self;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);
 
 	self = (struct iriap_cb *) instance;
 
@@ -230,20 +251,24 @@
 
 	ASSERT( iriap != NULL, return;);
 
-	del_timer( &self->watchdog_timer);
+	/* del_timer( &self->watchdog_timer); */
 
 	if ( self->mode == IAS_CLIENT) {
 		DEBUG( 4, __FUNCTION__ "(), disconnect as client\n");
 
-		/* Inform service user */
+		/* 
+		 * Inform service user that the request failed by sending 
+		 * it a NULL value.
+		 */
 		if ( self->confirm)
-			self->confirm( 0, NULL, self->priv);
-
+ 			self->confirm( 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, 
@@ -265,15 +290,15 @@
 {
 	struct sk_buff *skb;
 
-	DEBUG( 4, "iriap_disconnect_request()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IAS_MAGIC, return;);
 
 	skb = dev_alloc_skb( 64);
 	if (skb == NULL) {
-		DEBUG( 0,"iriap_getvaluebyclass: "
-		       "Could not allocate an sk_buff of length %d\n", 64);
+		DEBUG( 0, __FUNCTION__
+		       "(), Could not allocate an sk_buff of length %d\n", 64);
 		return;
 	}
 
@@ -316,9 +341,9 @@
  *    Retreive all values from attribute in all objects with given class
  *    name
  */
-void iriap_getvaluebyclass_request( __u32 daddr, char *name, char *attr, 
-				    CONFIRM_CALLBACK callback,
-				    void *priv)
+void iriap_getvaluebyclass_request( char *name, char *attr, 
+				    __u32 saddr, __u32 daddr,
+				    CONFIRM_CALLBACK callback, void *priv)
 {
 	struct sk_buff *skb;
 	struct iriap_cb *self;
@@ -326,16 +351,18 @@
 	int name_len, attr_len;
 	__u8 slsap = LSAP_ANY;  /* Source LSAP to use */
 
-	DEBUG( 4, "iriap_getvaluebyclass_request()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 	
 	self = iriap_open( slsap, IAS_CLIENT);
-	if ( self == NULL)
+	if (!self)
 		return;
 
 	self->mode = IAS_CLIENT;
 	self->confirm = callback;
 	self->priv = priv;
+
 	self->daddr = daddr;
+	self->saddr = saddr;
 
 	/* 
 	 *  Save operation, so we know what the later indication is about
@@ -343,14 +370,11 @@
 	self->operation = GET_VALUE_BY_CLASS; 
 
 	/* Give ourselves 7 secs to finish this operation */
-	iriap_start_watchdog_timer( self, 700);
+	/* iriap_start_watchdog_timer( self, 700); */
 	
 	skb = dev_alloc_skb( 64);
-	if (skb == NULL) {
-		DEBUG( 0,"iriap_getvaluebyclass: "
-		       "Could not allocate an sk_buff of length %d\n", 64);
+	if (!skb)
 		return;
-	}
 
 	name_len = strlen( name);
 	attr_len = strlen( attr);
@@ -377,8 +401,7 @@
  *    to service user.
  *
  */
-void iriap_getvaluebyclass_confirm( struct iriap_cb *self, 
-				    struct sk_buff *skb) 
+void iriap_getvaluebyclass_confirm(struct iriap_cb *self, struct sk_buff *skb) 
 {
 	struct ias_value *value;
 	__u16 obj_id;
@@ -387,6 +410,7 @@
 	int   value_len;
 	__u8 *fp;
 	int n;
+	int charset;
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IAS_MAGIC, return;);
@@ -399,7 +423,7 @@
 	/* Get length, MSB first */
 	len = ntohs( *(__u16 *)( fp+n)); n += 2;
 
-	DEBUG( 4, "iriap_getvaluebyclass_confirm: len=%d\n", len);
+	DEBUG( 4, __FUNCTION__ "(), len=%d\n", len);
 
 	/* Get object ID, MSB first */
 	obj_id = ntohs( *(__u16 *)( fp+n)); n += 2;
@@ -407,39 +431,54 @@
 	type = fp[n++];
 	DEBUG( 4, __FUNCTION__ "(), Value type = %d\n", type);
 
-
 	switch( type) {
 	case IAS_INTEGER:
 		value = irias_new_integer_value( ntohl(*(__u32 *)(fp+n)));
 		/* 
 		 *  Legal values restricted to 0x01-0x6f, page 15 irttp 
 		 */
-		DEBUG( 4, "iriap_getvaluebyclass_confirm: lsap=%d\n", 
-		       value->t.integer); 
+		DEBUG( 4, __FUNCTION__ "(), lsap=%d\n", value->t.integer); 
 		break;
 	case IAS_STRING:
-		/* FIXME: check len of string, and if string is/should be
-		 *  null terminated? */
-		ASSERT( fp[n++] == 0, return;); /* ASCII only! */
+		charset = fp[n++];
+
+		switch(charset) {
+		case CS_ASCII:
+			break;
+/* 		case CS_ISO_8859_1: */
+/* 		case CS_ISO_8859_2: */
+/* 		case CS_ISO_8859_3: */
+/* 		case CS_ISO_8859_4: */
+/* 		case CS_ISO_8859_5: */
+/* 		case CS_ISO_8859_6: */
+/* 		case CS_ISO_8859_7: */
+/* 		case CS_ISO_8859_8: */
+/* 		case CS_ISO_8859_9: */
+/* 		case CS_UNICODE: */
+		default:
+			DEBUG(0, __FUNCTION__"(), charset %s, not supported\n",
+			      ias_charset_types[charset]);
+			return;
+			/* break; */
+		}
 		value_len = fp[n++];
-		DEBUG( 0, __FUNCTION__ "(), strlen=%d\n", value_len);
+		DEBUG(4, __FUNCTION__ "(), strlen=%d\n", value_len);
 		ASSERT( value_len < 64, return;);
 		
-		DEBUG( 0, "Got string %s\n", fp+n);
-
+		/* Make sure the string is null-terminated */
+		fp[n+value_len] = 0x00;
+		
+		DEBUG(4, "Got string %s\n", fp+n);
 		value = irias_new_string_value( fp+n);
-
 		break;
 	case IAS_OCT_SEQ:
 		value_len = ntohs( *(__u16 *)( fp+n)); n += 2;
 		
 		/* FIXME:should be 1024, but.... */
-		DEBUG( 0, __FUNCTION__ "():octet sequence:len=%d\n",
-		       value_len);
+		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;
@@ -458,39 +497,37 @@
 /*
  * Function iriap_getvaluebyclass_response ()
  *
- *    Send answer to getvaluebyclass_indication back to peer LM-IAS
+ *    Send answer back to remote LM-IAS
  * 
  */
-void iriap_getvaluebyclass_response( struct iriap_cb *self,
-				     __u16 obj_id, 
-				     __u8 ret_code,
-				     struct ias_value *value)
+void iriap_getvaluebyclass_response(struct iriap_cb *self, __u16 obj_id, 
+				    __u8 ret_code, struct ias_value *value)
 {
 	struct sk_buff *skb;
 	__u8 *fp;
 	int n;
 
-	DEBUG( 4, "iriap_getvaluebyclass_response()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT( value != NULL, return;);
+	ASSERT( value->len <= 1024, return;);
 
 	/* Initialize variables */
 	n = 0;
 
 	/* 
-	 *  FIXME: adjust the size of the response after the length of the 
-	 *  value 
+	 *  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.
 	 */
-	skb = dev_alloc_skb( 64);
-	if (skb == NULL) {
-		DEBUG( 0, __FUNCTION__ "(),"
-		       "Could not allocate an skb of length %d\n", 64);
+	skb = dev_alloc_skb(value->len + LMP_HEADER + LAP_HEADER + 9);
+	if (!skb)
 		return;
-	}
 
 	/* Reserve space for MUX and LAP header */
- 	skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER);
+ 	skb_reserve( skb, LMP_HEADER+LAP_HEADER);
 	skb_put( skb, 6);
 	
 	fp = skb->data;
@@ -520,13 +557,6 @@
 		*((__u32 *)(fp+n)) = htonl(value->t.integer); n+=4;
 		break;
 	case IAS_OCT_SEQ:
-		
-		/* FIXME:
-		 * we can send only 55 octets at this time. 
-		 * we should be able to send 1024 octets.       TH
-		 */
-
-		ASSERT(value->len <= 55, return ;);
 		skb_put( skb, 3 + value->len);
 		fp[n++] = value->type;
 		*((__u16 *)(fp+n)) = htons(value->len); n+=2;
@@ -540,8 +570,7 @@
 		break;
 
 	default:
-		DEBUG( 0, "iriap_getvaluebyclass_response: "
-		       "type not implemented!\n");
+		DEBUG(0, __FUNCTION__ "(), type not implemented!\n");
 		break;
 	}
 	iriap_do_r_connect_event( self, IAP_CALL_RESPONSE, skb);
@@ -553,8 +582,8 @@
  *    getvaluebyclass is requested from peer LM-IAS
  *
  */
-void iriap_getvaluebyclass_indication( struct iriap_cb *self,
-				       struct sk_buff *skb)
+void iriap_getvaluebyclass_indication(struct iriap_cb *self, 
+				      struct sk_buff *skb)
 {
 	__u8 *fp;
 	int n;
@@ -562,11 +591,10 @@
 	int attr_len;
 	char name[64];
 	char attr[64];
- 	char both[128];
  	struct ias_object *obj;
 	struct ias_attrib *attrib;
 
-	DEBUG( 4, "iriap_getvaluebyclass_indication()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IAS_MAGIC, return;);
@@ -588,30 +616,26 @@
 	/* 
 	 *  Now, do some advanced parsing! :-) 
 	 */
-	DEBUG( 9, "LM-IAS: Looking up %s: %s\n", name, attr);
-
-	sprintf( both, "%s:%s", name, attr);
-	DEBUG( 0, "LM-IAS: looking for %s\n", both);
-
-	obj = irias_find_object( name);
-
+	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);
 		return;
 	}
-	DEBUG( 0, "LM-IAS: found %s, id=%d\n", obj->name, obj->id);
+	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);
-		iriap_getvaluebyclass_response( self, obj->id, 
-						IAS_ATTRIB_UNKNOWN, &missing);
+		iriap_getvaluebyclass_response(self, obj->id,
+					       IAS_ATTRIB_UNKNOWN, &missing);
 		return;
 	}
 	
-	DEBUG( 0, "LM-IAS: found %s\n", attrib->name);
+	DEBUG(4, "LM-IAS: found %s\n", attrib->name);
 	
 	/*
 	 * We have a match; send the value.
@@ -633,17 +657,14 @@
 	struct sk_buff *skb;
 	__u8 *frame;
 
-	DEBUG( 6, "iriap_send_ack()\n");
+	DEBUG( 6, __FUNCTION__ "()\n");
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IAS_MAGIC, return;);
 
-	skb =  dev_alloc_skb( 64);
-	if (skb == NULL) {
-		DEBUG( 0, "iriap_send_ack: "
-		       "Could not allocate an sk_buff of length %d\n", 64);
+	skb = dev_alloc_skb( 64);
+	if (!skb)
 		return;
-	}
 
 	/* Reserve space for MUX and LAP header */
  	skb_reserve( skb, 4);
@@ -671,9 +692,9 @@
 	ASSERT( self->magic == IAS_MAGIC, return;);
 	ASSERT( userdata != NULL, return;);
 	
-	DEBUG( 4, "iriap_connect_confirm()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 	
-	del_timer( &self->watchdog_timer);
+	/* del_timer( &self->watchdog_timer); */
 
 	iriap_do_client_event( self, IAP_LM_CONNECT_CONFIRM, userdata);
 }
@@ -684,13 +705,12 @@
  *    Remote LM-IAS is requesting connection
  *
  */
-void iriap_connect_indication( void *instance, void *sap, 
-			       struct qos_info *qos, int max_sdu_size,
-			       struct sk_buff *userdata)
+void iriap_connect_indication(void *instance, void *sap, struct qos_info *qos,
+			      int max_sdu_size, struct sk_buff *userdata)
 {
 	struct iriap_cb *self;
 
-	DEBUG( 4, "iriap_connect_indication()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 
 	self = ( struct iriap_cb *) instance;
 
@@ -713,7 +733,7 @@
 	__u8  *frame;
 	__u8  opcode;
 	
-	DEBUG( 4, "iriap_data_indication()\n"); 
+	DEBUG( 4, __FUNCTION__ "()\n"); 
 	
 	self = ( struct iriap_cb *) instance;
 
@@ -769,8 +789,7 @@
 		iriap_close( self);
 		break;
 	default:
-		DEBUG( 0, "iriap_data_indication: Unknown op-code: %02x\n", 
-		       opcode);
+		DEBUG(0, __FUNCTION__ "(), Unknown op-code: %02x\n", opcode);
 		break;
 	}
 }
@@ -786,7 +805,7 @@
 	__u8 *fp;
 	__u8  opcode;
 
-	DEBUG( 4, "iriap_call_indication()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IAS_MAGIC, return;);
@@ -816,7 +835,9 @@
 {
 	struct iriap_cb *self = ( struct iriap_cb *) data;
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	return;
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IAS_MAGIC, return;);
@@ -834,23 +855,7 @@
 	"IAS_STRING"
 };
 
-/* FIXME: This one should go in irlmp.c */
-static char *ias_charset_types[] = {
-	"CS_ASCII",
-	"CS_ISO_8859_1",
-	"CS_ISO_8859_2",
-	"CS_ISO_8859_3",
-	"CS_ISO_8859_4",
-	"CS_ISO_8859_5",
-	"CS_ISO_8859_6",
-	"CS_ISO_8859_7",
-	"CS_ISO_8859_8",
-	"CS_ISO_8859_9",
-	"CS_UNICODE"
-};
-
-int irias_proc_read( char *buf, char **start, off_t offset, int len, 
-		     int unused)
+int irias_proc_read(char *buf, char **start, off_t offset, int len, int unused)
 {
 	struct ias_object *obj;
 	struct ias_attrib *attrib;
diff -u --recursive --new-file v2.2.2/linux/net/irda/iriap_event.c linux/net/irda/iriap_event.c
--- v2.2.2/linux/net/irda/iriap_event.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/iriap_event.c	Sun Mar  7 15:26:44 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Aug 21 00:02:07 1997
- * Modified at:   Wed Dec  9 02:20:02 1998
+ * Modified at:   Tue Jan 26 12:29:36 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -184,6 +184,8 @@
 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;);
 
@@ -191,13 +193,14 @@
 	case IAP_CALL_REQUEST_GVBC:
 		iriap_next_client_state( self, S_CONNECTING);
 		self->skb = skb;
-		irlmp_connect_request( self->lsap, LSAP_IAS, self->daddr, 
-				       NULL, NULL);
+		ret = irlmp_connect_request( self->lsap, LSAP_IAS, 
+					     self->saddr, self->daddr, 
+					     NULL, NULL);
 		break;
 	case IAP_LM_DISCONNECT_INDICATION:
 		break;
 	default:
-		DEBUG( 0, "state_s_disconnect: Unknown event %d\n", event);
+		DEBUG( 0, __FUNCTION__"(), Unknown event %d\n", event);
 		break;
 	}
 }
diff -u --recursive --new-file v2.2.2/linux/net/irda/irlan/Config.in linux/net/irda/irlan/Config.in
--- v2.2.2/linux/net/irda/irlan/Config.in	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/irlan/Config.in	Sun Mar  7 15:26:44 1999
@@ -1,7 +1 @@
-
 dep_tristate 'IrLAN protocol' CONFIG_IRLAN $CONFIG_IRDA
-
-if [ "$CONFIG_IRLAN" != "n" ]; then
-  dep_tristate '   IrLAN client support' CONFIG_IRLAN_CLIENT $CONFIG_IRLAN
-  dep_tristate '   IrLAN server support' CONFIG_IRLAN_SERVER $CONFIG_IRLAN
-fi
diff -u --recursive --new-file v2.2.2/linux/net/irda/irlan/Makefile linux/net/irda/irlan/Makefile
--- v2.2.2/linux/net/irda/irlan/Makefile	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/irlan/Makefile	Sun Mar  7 15:26:44 1999
@@ -9,44 +9,13 @@
 
 MOD_LIST_NAME := IRDA_MODULES
 O_TARGET := irlan.o
-O_OBJS	 := irlan_common.o irlan_eth.o irlan_event.o
+O_OBJS	 := irlan_common.o irlan_eth.o irlan_event.o irlan_client.o irlan_provider.o irlan_filter.o irlan_provider_event.o irlan_client_event.o
 M_OBJS   := $(O_TARGET)
 MI_OBJS  :=
 
 OX_OBJS  += 
 
-ifeq ($(CONFIG_IRLAN_CLIENT),y)
-O_OBJS += irlan_cli.o irlan_cli_event.o
-else
-  ifeq ($(CONFIG_IRLAN_CLIENT),m)
-#  MI_OBJS += irlan_cli.o irlan_cli_event.o
-  M_OBJS += irlan_client.o
-  endif
-endif
-
-ifeq ($(CONFIG_IRLAN_SERVER),y)
-O_OBJS += irlan_srv.o irlan_srv_event.o
-else
-  ifeq ($(CONFIG_IRLAN_SERVER),m)
-#  MI_OBJS += irlan_srv.o irlan_srv_event.o
-  M_OBJS += irlan_server.o
-  endif
-endif
-
-# Special rule to build the composite modules
-ifeq ($(CONFIG_IRLAN),m)
-irlan_client.o: irlan_cli.o irlan_cli_event.o
-	$(LD) $(LD_RFLAG) -r -o $@ irlan_cli.o irlan_cli_event.o
-
-irlan_server.o: irlan_srv.o irlan_srv_event.o
-	$(LD) $(LD_RFLAG) -r -o $@ irlan_srv.o irlan_srv_event.o
-endif
-
 include $(TOPDIR)/Rules.make
 
 tar:
 		tar -cvf /dev/f1 .
-
-
-
-
diff -u --recursive --new-file v2.2.2/linux/net/irda/irlan/irlan_cli.c linux/net/irda/irlan/irlan_cli.c
--- v2.2.2/linux/net/irda/irlan/irlan_cli.c	Wed Jan 20 23:14:07 1999
+++ linux/net/irda/irlan/irlan_cli.c	Wed Dec 31 16:00:00 1969
@@ -1,676 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      irlan_cli.c
- * Version:       0.8
- * Description:   IrDA LAN Access Protocol Client
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Mon Jan 18 13:24:26 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>
- *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
- * 
- *     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.
- *
- *     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.
- *
- ********************************************************************/
-
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/if_arp.h>
-#include <net/arp.h>
-
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <asm/byteorder.h>
-
-#include <net/irda/irda.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/timer.h>
-
-#include <net/irda/irlan_common.h>
-#include <net/irda/irlan_event.h>
-#include <net/irda/irlan_eth.h>
-#include <net/irda/irlan_cli.h>
-
-/*
- *  Private functions
- */
-static struct irlan_cb *irlan_client_open( __u32 saddr, __u32 daddr);
-static void irlan_client_close( struct irlan_cb *self);
-
-
-static int irlan_client_eth_open( struct device *dev)
-{
-	/* struct irlan_cb *self = (struct irlan_cb *) dev->priv; */
-	
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( dev != NULL, return -1;);
-
-	/* Ready to play! */
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
-
-	MOD_INC_USE_COUNT;
-	
-	return 0;
-}
-
-/*
- * Function irlan_eth_close (dev)
- *
- *    Stop the Client ether network device, his function will be called by
- *    ifconfig down.
- */
-static int irlan_client_eth_close(struct device *dev)
-{
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	ASSERT( dev != NULL, return -1;);
-	
-	/* Stop device */
-	dev->tbusy = 1;
-	dev->start = 0;
-
-	MOD_DEC_USE_COUNT;
-	
-	return 0;
-}
-
-/*
- * Function irlan_client_eth_init (dev)
- *
- *    
- *
- */
-int irlan_client_eth_init( struct device *dev) 
-{
-	irlan_eth_init( dev);
-
-	/* Overrride some functions */
-	dev->open  = irlan_client_eth_open;
-	dev->stop = irlan_client_eth_close;
-
-	return 0;
-}
-
-/*
- * Function irlan_client_init (dev)
- *
- *   Allocates the master array. Called by modprobe().
- */
-__initfunc(int irlan_client_init( void))
-{
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	/* Register with IrLMP as a service user */
-	irlmp_register_layer( S_LAN, CLIENT, TRUE, 
-			      irlan_discovery_indication);
-
-	/* Do some fast discovery! */
-	irlmp_discovery_request( 8);
-
-	return 0;
-}
-
-/*
- * Function irlan_client_cleanup (void)
- *
- *    Removes all instances of the IrLAN network device driver, and the
- *    master array. Called by rmmod().
- *
- */
-void irlan_client_cleanup(void) 
-{
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	irlmp_unregister_layer( S_LAN, CLIENT);
-}
-
-/*
- * Function irlan_client_open (void)
- *
- *    This function allocates and opens a new instance of the IrLAN network
- *    device driver.
- *
- */
-static struct irlan_cb *irlan_client_open( __u32 saddr, __u32 daddr) 
-{
-	struct irlan_cb *self;
-	int result;
-
-	DEBUG( 4, "IrLAN: irlan_client_open()\n");
-
-	ASSERT( irlan != NULL, return NULL;);
-	
-	self = irlan_open();
-	if ( self == NULL)
-		return NULL;
-
-	/* Use default name instead! */
-	/* sprintf( self->ifname, "irlan%d", ); */
- 	self->dev.name = self->ifname;
-	self->dev.priv = (void *) self;
-	self->dev.next = NULL;
-	self->dev.init = irlan_client_eth_init;
-	
-	self->saddr = saddr;
-	self->daddr = daddr;
-
-	/*
-	 *  Insert ourself into the hashbin
-	 */
-	hashbin_insert( irlan, (QUEUE *) self, saddr, NULL);
-
-	if (( result = register_netdev( &self->dev)) != 0) {
-		DEBUG( 0, "IrLAN, Register_netdev() failed!\n");
-		return NULL;
-	}
-
-	irlan_next_state( self, IRLAN_IDLE);
-
-	irlan_client_open_tsaps( self);
-	
-	return self;
-}
-
-/*
- * Function irlan_client_close (self)
- *
- *    
- *
- */
-static void irlan_client_close( struct irlan_cb *self)
-{
-	struct irlan_cb *entry;
-
-	DEBUG( 0, __FUNCTION__ "()\n");
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-	entry = hashbin_remove( irlan, self->daddr, NULL);
-
-	ASSERT( entry == self, return;);
-
-	/* __irlan_close( self); */
-}
-
-/*
- * Function irlan_discovery_indication (daddr)
- *
- *    Remote device with IrLAN server support discovered
- *
- */
-void irlan_discovery_indication( DISCOVERY *discovery) 
-{
-	struct irlan_cb *self;
-	__u32 saddr, daddr;
-	
-	ASSERT( irlan != NULL, return;);
-	ASSERT( discovery != NULL, return;);
-
-	saddr = discovery->saddr;
-	daddr = discovery->daddr;
-
-	/* 
-	 *  Check if an instance is already dealing with this device
-	 *  (saddr) 
-	 */
-	self = (struct irlan_cb *) hashbin_find( irlan, saddr, NULL);
-      	if ( self != NULL) {
-		ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-		DEBUG( 4, __FUNCTION__ "(), Found instance!\n");
-		if ( self->state == IRLAN_IDLE) {
-			/* daddr may have changed! */
-			self->daddr = daddr;
-
-			irlan_do_client_event( self, 
-					       IRLAN_DISCOVERY_INDICATION, 
-					       NULL);
-		} else {
-			DEBUG( 0, __FUNCTION__ "(), state=%s\n", 
-			       irlan_state[ self->state]);
-			/*  
-			 *  If we get here, it's obvious that the last 
-			 *  connection attempt has failed, so its best 
-			 *  to go back to idle!
-			 */
-			irlan_do_client_event( self, IRLAN_LMP_DISCONNECT, 
-					       NULL);
-		}
-		return;
-	}
-	
-	/* 
-	 * We have no instance for daddr, so time to start a new instance.
-	 */
-	DEBUG( 0, __FUNCTION__ "(), Opening new instance for saddr=%#x\n",
-	       saddr);
-
-	if (( self = irlan_client_open( saddr, daddr)) == NULL) {
-		DEBUG( 0, "irlan_client_open failed!\n");
-		return;
-	}	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-	
-	DEBUG( 4, "Setting irlan_client state!\n");
-	if ( self->state == IRLAN_IDLE) {
-		irlan_do_client_event( self, IRLAN_DISCOVERY_INDICATION, NULL);
-	} else {
-		DEBUG( 0, __FUNCTION__ "(), Hmm, got here too!\n");
-	}
-}
-
-/*
- * Function irlan_client_disconnect_indication (handle)
- *
- *    Callback function for the IrTTP layer. Indicates a disconnection of
- *    the specified connection (handle)
- */
-void irlan_client_disconnect_indication( void *instance, void *sap, 
-					 LM_REASON reason, 
-					 struct sk_buff *userdata) 
-{
-	struct irlan_cb *self;
-	struct tsap_cb *tsap;
-
-	self = ( struct irlan_cb *) instance;
-	tsap = ( struct tsap_cb *) sap;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);	
-	ASSERT( tsap != NULL, return;);
-	ASSERT( tsap->magic == TTP_TSAP_MAGIC, return;);
-	
-	DEBUG( 4, __FUNCTION__ "(), reason=%d\n", reason);
-	
-	if ( tsap == self->tsap_data) {
-		DEBUG( 4, "IrLAN, data channel disconnected by peer!\n");
-		self->connected = FALSE;
-	} else if ( tsap == self->tsap_ctrl) {
-		DEBUG( 4, "IrLAN, control channel disconnected by peer!\n");
-	} else {
-		DEBUG( 0, "Error, disconnect on unknown handle!\n");
-	}
-	
-	/* Stop IP from transmitting more packets */
-	/* irlan_client_flow_indication( handle, FLOW_STOP, priv); */
-
-	irlan_do_client_event( self, IRLAN_LMP_DISCONNECT, NULL);
-}
-	
-/*
- * Function irlan_control_data_indication (handle, skb)
- *
- *    This function gets the data that is received on the control channel
- *
- */
-void irlan_client_ctrl_data_indication( void *instance, void *sap, 
-					struct sk_buff *skb)
-{
-	struct irlan_cb *self;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	self = ( struct irlan_cb *) instance;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
-	
-	DEBUG( 4, "Got IRLAN_DATA_INDICATION!\n");
-	irlan_do_client_event( self, IRLAN_DATA_INDICATION, skb); 
-}
-
-/*
- * Function irlan_client_open_tsaps (self)
- *
- *    Initialize callbacks and open IrTTP TSAPs
- *
- */
-void irlan_client_open_tsaps( struct irlan_cb *self) 
-{
-	/* struct irlan_frame frame; */
-	struct notify_t notify_ctrl;
-	struct notify_t notify_data;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	irda_notify_init( &notify_ctrl);
-	irda_notify_init( &notify_data);
-
-	/* Set up callbacks */
-	notify_ctrl.data_indication       = irlan_client_ctrl_data_indication;
-	notify_ctrl.connect_confirm       = irlan_client_connect_confirm;
-	notify_ctrl.disconnect_indication = irlan_client_disconnect_indication;
-	notify_ctrl.instance              = self;
-	strncpy( notify_ctrl.name, "IrLAN ctrl", NOTIFY_MAX_NAME);
-	
-	notify_data.data_indication       = irlan_eth_rx;
-	notify_data.udata_indication      = irlan_eth_rx;
-	notify_data.connect_confirm       = irlan_client_connect_confirm;
- 	notify_data.flow_indication       = irlan_eth_flow_indication;
-	notify_data.disconnect_indication = irlan_client_disconnect_indication;
-	notify_data.instance              = self;
-	strncpy( notify_data.name, "IrLAN data", NOTIFY_MAX_NAME);
-
-	/* Create TSAP's */
-	self->tsap_ctrl = irttp_open_tsap( LSAP_ANY, 
-					   DEFAULT_INITIAL_CREDIT, 
-					   &notify_ctrl);
-	self->tsap_data = irttp_open_tsap( LSAP_ANY, 
-					   DEFAULT_INITIAL_CREDIT,
-					   &notify_data);
-}
-
-/*
- * Function irlan_client_connect_confirm (handle, skb)
- *
- *    Connection to peer IrLAN laye confirmed
- *
- */
-void irlan_client_connect_confirm( void *instance, void *sap, 
-				   struct qos_info *qos, int max_sdu_size,
-				   struct sk_buff *skb) 
-{
-	struct irlan_cb *self;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	self = ( struct irlan_cb *) instance;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-	/* TODO: we could set the MTU depending on the max_sdu_size */
-
-	irlan_do_client_event( self, IRLAN_CONNECT_COMPLETE, NULL);
-}
-
-/*
- * Function irlan_client_reconnect_data_channel (self)
- *
- *    Try to reconnect data channel (currently not used)
- *
- */
-void irlan_client_reconnect_data_channel( struct irlan_cb *self) 
-{
-	struct sk_buff *skb;
-	__u8 *frame;
-		
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-	
-	skb =  dev_alloc_skb( 128);
-	if (skb == NULL) {
-		DEBUG( 0, __FUNCTION__
-		       "(), Could not allocate an sk_buff of length %d\n", 64);
-		return;
-	}
-
-	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-	skb_put( skb, 2);
-	
-	frame = skb->data;
-	
- 	frame[0] = CMD_RECONNECT_DATA_CHAN;
-	frame[1] = 0x01;
- 	insert_array_param( skb, "RECONNECT_KEY", 
-			    self->t.client.reconnect_key, 
-			    self->t.client.key_len);
-	
-	irttp_data_request( self->tsap_ctrl, skb);	
-}
-
-/*
- * Function irlan_client_extract_params (skb)
- *
- *    Extract all parameters from received buffer, then feed them to 
- *    check_params for parsing
- *
- */
-void irlan_client_extract_params( struct irlan_cb *self, 
-				  struct sk_buff *skb)
-{
-	__u8 *frame;
-	__u8 *ptr;
-	int count;
-	int ret;
-	int val_len;
-	int i;
-
-	ASSERT( skb != NULL, return;);	
-	
-	DEBUG( 4, __FUNCTION__ "() skb->len=%d\n", (int) skb->len);
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-	
-	if ( skb == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Got NULL skb!\n");
-		return;
-	}
-	frame = skb->data;
-
-	/* 
-	 *  Check return code and print it if not success 
-	 */
-	if ( frame[0])
-		print_ret_code( frame[0]);
-	
-	/* How many parameters? */
-	count = frame[1];
-
-	DEBUG( 4, "Got %d parameters\n", count);
-	
-	ptr = frame+2;
-
-	/* For all parameters */
- 	for ( i=0; i<count;i++) {
-		ret = irlan_get_response_param( ptr, self->name, self->value, 
-						&val_len);
-		if ( ret == -1) {
-			DEBUG( 0, __FUNCTION__ "(), IrLAN, Error!\n");
-			return;
-		}
-		ptr+=ret;
-		check_response_param( self, self->name, self->value, val_len);
- 	}
-}
-
-/*
- * Function check_param (param, value)
- *
- *    Check which parameter is received and update local variables
- *
- */
-void check_response_param( struct irlan_cb *self, char *param, 
-			   char *value, int val_len) 
-{
-	int i;
-	__u8 *bytes;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-	/*
-	 *  Media type
-	 */
-	if ( strcmp( param, "MEDIA") == 0) {
-		if ( strcmp( value, "802.3") == 0)
-			self->media = MEDIA_802_3;
-		else
-			self->media = MEDIA_802_5;
-		return;
-	}
-	/*
-	 *  IRLAN version
-	 */
-	if ( strcmp( param, "IRLAN_VER") == 0) {
-		DEBUG( 4, "IrLAN version %d.%d\n", 
-			(__u8) value[0], (__u8) value[1]);
-		return;
-	}
-	/*
-	 *  Which remote TSAP to use for data channel
-	 */
-	if ( strcmp( param, "DATA_CHAN") == 0) {
-		self->dtsap_sel_data = value[0];
-		DEBUG( 4, "Data TSAP = %02x\n", self->dtsap_sel_data);
-		return;
-	}
-	/*
-	 *  RECONNECT_KEY, in case the link goes down!
-	 */
-	if ( strcmp( param, "RECONNECT_KEY") == 0) {
-		DEBUG( 4, "Got reconnect key: ");
-		/* for (i = 0; i < val_len; i++) */
-/* 			printk( "%02x", value[i]); */
-		memcpy( self->t.client.reconnect_key, value, val_len);
-		self->t.client.key_len = val_len;
-		DEBUG( 4, "\n");
-	}
-	/*
-	 *  FILTER_ENTRY, have we got the ethernet address?
-	 */
-	if ( strcmp( param, "FILTER_ENTRY") == 0) {
-		bytes = value;
-		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++) 
-			self->dev.dev_addr[i] = bytes[i];
-#if 0
-	/*
-	 * When we get a new MAC address do a gratuitous ARP. This is useful
-	 * if we have changed access points on the same subnet.
-	 */
-		DEBUG( 4, "IrLAN: Sending gratuitous ARP\n");
-		arp_send( ARPOP_REQUEST, ETH_P_ARP, self->dev.pa_addr,
-			&self->dev, self->dev.pa_addr, NULL,
-			self->dev.dev_addr, NULL);
-#endif
-	}
-}
-
-/*
- * Function irlan_client_get_value_confirm (obj_id, value)
- *
- *    Got results from previous GetValueByClass request
- *
- */
-void irlan_client_get_value_confirm( __u16 obj_id, struct ias_value *value,
-				     void *priv) 
-{
-	struct irlan_cb *self;
-	
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( priv != NULL, return;);
-
-	self = ( struct irlan_cb *) priv;
-
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-	switch ( value->type) {
-	case IAS_INTEGER:
-		self->dtsap_sel_ctrl = value->t.integer;
-
-		if ( value->t.integer != -1) {
-			irlan_do_client_event( self, IRLAN_IAS_PROVIDER_AVAIL,
-					       NULL);
-			return;
-		}
-		break;
-	case IAS_STRING:
-		DEBUG( 0, __FUNCTION__ "(), got string %s\n", value->t.string);
-		break;
-	case IAS_OCT_SEQ:
-		DEBUG( 0, __FUNCTION__ "(), OCT_SEQ not implemented\n");
-		break;
-	case IAS_MISSING:
-		DEBUG( 0, __FUNCTION__ "(), MISSING not implemented\n");
-		break;
-	default:
-		DEBUG( 0, __FUNCTION__ "(), unknown type!\n");
-		break;
-	}
-	irlan_do_client_event( self, IRLAN_IAS_PROVIDER_NOT_AVAIL, NULL);
-}
-
-#ifdef MODULE
-
-MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
-MODULE_DESCRIPTION("The Linux IrDA LAN protocol"); 
-
-/*
- * Function init_module (void)
- *
- *    Initialize the IrLAN module, this function is called by the
- *    modprobe(1) program.
- */
-int init_module(void) 
-{
-	DEBUG( 4, __FUNCTION__ "(), irlan_client.c\n");
-
-	irlan_client_init();
-
-	return 0;
-}
-
-/*
- * Function cleanup_module (void)
- *
- *    Remove the IrLAN module, this function is called by the rmmod(1)
- *    program
- */
-void cleanup_module(void) 
-{
-	DEBUG( 4, "--> irlan, cleanup_module\n");
-	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
-
-	/* Free some memory */
- 	irlan_client_cleanup();
-
-	DEBUG( 4, "irlan, cleanup_module -->\n");
-}
-
-#endif /* MODULE */
-
-
-
-
-
-
-
-
-
diff -u --recursive --new-file v2.2.2/linux/net/irda/irlan/irlan_cli_event.c linux/net/irda/irlan/irlan_cli_event.c
--- v2.2.2/linux/net/irda/irlan/irlan_cli_event.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/irlan/irlan_cli_event.c	Wed Dec 31 16:00:00 1969
@@ -1,494 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      irlan_cli_event.c
- * Version:       0.1
- * Description:   IrLAN Client FSM (Finite State Machine)
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Wed Dec  9 02:36:49 1998
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     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.
- *
- *     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.
- *
- ********************************************************************/
-
-#include <linux/skbuff.h>
-
-#include <net/irda/irda.h>
-#include <net/irda/irmod.h>
-#include <net/irda/iriap.h>
-#include <net/irda/irlmp.h>
-#include <net/irda/irttp.h>
-
-#include <net/irda/irlan_common.h>
-#include <net/irda/irlan_cli.h>
-#include <net/irda/irlan_event.h>
-
-static int irlan_client_state_idle ( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb);
-static int irlan_client_state_query( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb);
-static int irlan_client_state_conn ( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb);
-static int irlan_client_state_info ( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb);
-static int irlan_client_state_media( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb);
-static int irlan_client_state_open ( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb);
-static int irlan_client_state_wait ( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb);
-static int irlan_client_state_arb  ( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb);
-static int irlan_client_state_data ( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb);
-static int irlan_client_state_close( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb);
-static int irlan_client_state_sync ( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb);
-
-static int (*state[])( struct irlan_cb *, IRLAN_EVENT event, 
-		       struct sk_buff *) = 
-{ 
-	irlan_client_state_idle,
-	irlan_client_state_query,
-	irlan_client_state_conn,
-	irlan_client_state_info,
-	irlan_client_state_media,
-	irlan_client_state_open,
-	irlan_client_state_wait,
-	irlan_client_state_arb,
-	irlan_client_state_data,
-	irlan_client_state_close,
-	irlan_client_state_sync
-};
-
-void irlan_do_client_event( struct irlan_cb *self, 
-			    IRLAN_EVENT event, 
-			    struct sk_buff *skb) 
-{
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-	(*state[ self->state]) ( self, event, skb);
-}
-
-/*
- * Function irlan_client_state_idle (event, skb, info)
- *
- *    IDLE, We are waiting for an indication that there is a provider
- *    available.
- */
-static int irlan_client_state_idle( struct irlan_cb *self, 
-				    IRLAN_EVENT event, 
-				    struct sk_buff *skb) 
-{
-	DEBUG( 4, "irlan_client_state_idle()\n");
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLAN_MAGIC, return -1;);
-	
-	switch( event) {
-	case IRLAN_DISCOVERY_INDICATION:
-		/* Get some values from peer IAS */
-#if 0
-		iriap_getvaluebyclass_request( self->daddr,
-					       /*  "PnP", "DeviceID",  */
-					       "Device", "DeviceName",
-					       irlan_client_get_value_confirm,
-					       self);
-#endif
-		iriap_getvaluebyclass_request( self->daddr,
-					       "IrLAN", "IrDA:TinyTP:LsapSel",
-					       irlan_client_get_value_confirm,
-					       self);
-
-		irlan_next_state( self, IRLAN_QUERY);
-		break;
-	default:
-		DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event);
-		break;
-	}
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-	return 0;
-}
-
-/*
- * Function irlan_client_state_query (event, skb, info)
- *
- *    QUERY, We have queryed the remote IAS and is ready to connect
- *    to provider, just waiting for the confirm.
- *
- */
-static int irlan_client_state_query( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb) 
-{
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLAN_MAGIC, return -1;);
-	
-	switch( event) {
-	case IRLAN_IAS_PROVIDER_AVAIL:
-		ASSERT( self->dtsap_sel_ctrl != 0, return -1;);
-
-		self->t.client.open_retries = 0;
-		
-		irttp_connect_request( self->tsap_ctrl, self->dtsap_sel_ctrl, 
-				       self->daddr, NULL, IRLAN_MTU, NULL);
-		irlan_next_state( self, IRLAN_CONN);
-		break;
-	case IRLAN_IAS_PROVIDER_NOT_AVAIL:
-		DEBUG( 0, __FUNCTION__ "(), IAS_PROVIDER_NOT_AVAIL\n");
-		irlan_next_state( self, IRLAN_IDLE);
-		break;
-	case IRLAN_LMP_DISCONNECT:
-	case IRLAN_LAP_DISCONNECT:
-		irlan_next_state( self, IRLAN_IDLE);
-		break;
-	default:
-		DEBUG( 0, __FUNCTION__"(), Unknown event %d\n", event);
-		break;
-	}
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-	
-	return 0;
-}
-
-/*
- * Function irlan_client_state_conn (event, skb, info)
- *
- *    CONN, We have connected to a provider but has not issued any
- *    commands yet.
- *
- */
-static int irlan_client_state_conn( struct irlan_cb *self, 
-				    IRLAN_EVENT event, 
-				    struct sk_buff *skb) 
-{
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	ASSERT( self != NULL, return -1;);
-	
-	switch( event) {
-	case IRLAN_CONNECT_COMPLETE:
-		/* Send getinfo cmd */
-		irlan_get_provider_info( self);
-		irlan_next_state( self, IRLAN_INFO);
-		break;
-	case IRLAN_LMP_DISCONNECT:
-	case IRLAN_LAP_DISCONNECT:
-		irlan_next_state( self, IRLAN_IDLE);
-		break;
-	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
-		break;
-	}
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-	
-	return 0;
-}
-
-/*
- * Function irlan_client_state_info (self, event, skb, info)
- *
- *    INFO, We have issued a GetInfo command and is awaiting a reply.
- */
-static int irlan_client_state_info( struct irlan_cb *self, 
-				    IRLAN_EVENT event, 
-				    struct sk_buff *skb) 
-{
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( self != NULL, return -1;);
-	
-	switch( event) {
-	case IRLAN_DATA_INDICATION:
-		ASSERT( skb != NULL, return -1;);
-	
-		irlan_client_extract_params( self, skb);
-		
-		irlan_next_state( self, IRLAN_MEDIA);
-		
-		irlan_get_media_char( self);
-		break;
-		
-	case IRLAN_LMP_DISCONNECT:
-	case IRLAN_LAP_DISCONNECT:
-		irlan_next_state( self, IRLAN_IDLE);
-		break;
-	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
-		break;
-	}
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-	
-	return 0;
-}
-
-/*
- * Function irlan_client_state_media (self, event, skb, info)
- *
- *    MEDIA, The irlan_client has issued a GetMedia command and is awaiting a
- *    reply.
- *
- */
-static int irlan_client_state_media( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb) 
-{
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	ASSERT( self != NULL, return -1;);
-
-	switch( event) {
-	case IRLAN_DATA_INDICATION:
-		irlan_client_extract_params( self, skb);
-		irlan_open_data_channel( self);
-		irlan_next_state( self, IRLAN_OPEN);
-		break;
-	case IRLAN_LMP_DISCONNECT:
-	case IRLAN_LAP_DISCONNECT:
-		irlan_next_state( self, IRLAN_IDLE);
-		break;
-	default:
-		DEBUG( 0, "irlan_client_state_media, Unknown event %d\n", 
-		       event);
-		break;
-	}
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-	
-	return 0;
-}
-
-/*
- * Function irlan_client_state_open (self, event, skb, info)
- *
- *    OPEN, The irlan_client has issued a OpenData command and is awaiting a
- *    reply
- *
- */
-static int irlan_client_state_open( struct irlan_cb *self, 
-				    IRLAN_EVENT event, 
-				    struct sk_buff *skb) 
-{
-	struct qos_info qos;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	ASSERT( self != NULL, return -1;);
-
-	switch( event) {
-	case IRLAN_DATA_INDICATION:
-		irlan_client_extract_params( self, skb);
-		
-		/*
-		 *  Check if we have got the remote TSAP for data 
-		 *  communications
-		 */
-	  	ASSERT( self->dtsap_sel_data != 0, return -1;);
-
-		qos.link_disc_time.bits = 0x01; /* 3 secs */
-
-		irttp_connect_request( self->tsap_data, 
-				       self->dtsap_sel_data, self->daddr,
-				       NULL, IRLAN_MTU, NULL);
-		
-  		irlan_next_state( self, IRLAN_DATA);
-		break;
-
-	case IRLAN_LMP_DISCONNECT:
-	case IRLAN_LAP_DISCONNECT:
-		irlan_next_state( self, IRLAN_IDLE);
-		break;
-	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", 
-		       event);
-		break;
-	}
-	
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-
-	return 0;
-}
-
-/*
- * Function irlan_client_state_wait (self, event, skb, info)
- *
- *    WAIT, The irlan_client is waiting for the local provider to enter the
- *    provider OPEN state.
- *
- */
-static int irlan_client_state_wait( struct irlan_cb *self, 
-				    IRLAN_EVENT event, 
-				    struct sk_buff *skb) 
-{
-	DEBUG( 4, "irlan_client_state_wait()\n");
-	
-	ASSERT( self != NULL, return -1;);
-	
-	switch( event) {
-	case IRLAN_LMP_DISCONNECT:
-	case IRLAN_LAP_DISCONNECT:
-		irlan_next_state( self, IRLAN_IDLE);
-		break;
-	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", 
-		       event);
-		break;
-	}
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-	
-	return 0;
-}
-
-static int irlan_client_state_arb( struct irlan_cb *self, 
-				   IRLAN_EVENT event, 
-				   struct sk_buff *skb) 
-{
-	DEBUG( 0, __FUNCTION__ "(), not implemented!\n");
-	
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-	return 0;
-}
-
-/*
- * Function irlan_client_state_data (self, event, skb, info)
- *
- *    DATA, The data channel is connected, allowing data transfers between
- *    the local and remote machines.
- *
- */
-static int irlan_client_state_data( struct irlan_cb *self, 
-				    IRLAN_EVENT event, 
-				    struct sk_buff *skb) 
-{
-	struct irmanager_event mgr_event;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLAN_MAGIC, return -1;);
-
-	switch( event) {
-	case IRLAN_CONNECT_COMPLETE:
-		irlan_get_unicast_addr( self);
-		irlan_open_unicast_addr( self);
-		/* irlan_set_broadcast_filter( self, TRUE);  */
-
-		DEBUG( 4, "IrLAN, We are now connected!\n");
-
-		/* irlan_next_state( LAN_DATA); */
-		break;
-	case IRLAN_DATA_INDICATION:
-		irlan_client_extract_params( self, skb);
-
-		/* irlan_client_flow_indication( self->data_tsap, FLOW_START,  */
-/* 					self); */
-
-		/* Make sure the code below only runs once */
-		if ( !self->connected) {
-			mgr_event.event = EVENT_IRLAN_START;
-			sprintf( mgr_event.devname, "%s", self->ifname);
-			irmanager_notify( &mgr_event);
-
-			self->connected = TRUE;
-		}
-		break;
-		
-	case IRLAN_LMP_DISCONNECT:
-	case IRLAN_LAP_DISCONNECT:
-		mgr_event.event = EVENT_IRLAN_STOP;
-		sprintf( mgr_event.devname, "%s", self->ifname);
-		irmanager_notify( &mgr_event);
-
-		irlan_next_state( self, IRLAN_IDLE);
-		break;
-	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
-		break;
-	}
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-	
-	return 0;
-}
-
-/*
- * Function irlan_client_state_close (self, event, skb, info)
- *
- *    
- *
- */
-static int irlan_client_state_close( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb) 
-{
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-
-	return 0;
-}
-
-/*
- * Function irlan_client_state_sync (self, event, skb, info)
- *
- *    
- *
- */
-static int irlan_client_state_sync( struct irlan_cb *self, 
-				    IRLAN_EVENT event, 
-				    struct sk_buff *skb) 
-{
-	DEBUG( 0, __FUNCTION__ "()\n");
-	
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-	
-	return 0;
-}
-
diff -u --recursive --new-file v2.2.2/linux/net/irda/irlan/irlan_client.c linux/net/irda/irlan/irlan_client.c
--- v2.2.2/linux/net/irda/irlan/irlan_client.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irlan/irlan_client.c	Sun Mar  7 15:26:44 1999
@@ -0,0 +1,617 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_client.c
+ * Version:       0.9
+ * Description:   IrDA LAN Access Protocol (IrLAN) Client
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Aug 31 20:14:37 1997
+ * Modified at:   Wed Feb 17 23:29:34 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>
+ *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
+ * 
+ *     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.
+ *
+ *     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.
+ *
+ ********************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+#include <net/arp.h>
+
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/byteorder.h>
+
+#include <net/irda/irda.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/timer.h>
+
+#include <net/irda/irlan_common.h>
+#include <net/irda/irlan_event.h>
+#include <net/irda/irlan_eth.h>
+#include <net/irda/irlan_provider.h>
+#include <net/irda/irlan_client.h>
+
+#undef CONFIG_IRLAN_GRATUITOUS_ARP
+
+static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap, 
+						    LM_REASON reason, 
+						    struct sk_buff *);
+
+static void irlan_client_ctrl_data_indication(void *instance, void *sap, 
+					      struct sk_buff *skb);
+
+static void irlan_client_ctrl_connect_confirm(void *instance, void *sap, 
+					      struct qos_info *qos, 
+					      int max_sdu_size,
+					      struct sk_buff *);
+
+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)
+{
+	struct irlan_cb *self = (struct irlan_cb *) data;
+	
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+	
+	/*  
+	 * If we are in peer mode, the client may not have got the discovery
+	 * indication it needs to make progress. If the client is still in 
+	 * IDLE state, we must kick it to, but only if the provider is not IDLE
+ 	 */
+	if ((self->access_type == ACCESS_PEER) && 
+	    (self->client.state == IRLAN_IDLE) &&
+	    (self->provider.state != IRLAN_IDLE)) {
+		irlan_client_wakeup(self, self->saddr, self->daddr);
+	}
+}
+
+void irlan_client_start_kick_timer(struct irlan_cb *self, int timeout)
+{
+	DEBUG(4, __FUNCTION__ "()\n");
+	
+	irda_start_timer(&self->client.kick_timer, timeout, 
+			 (unsigned long) self, 
+			 irlan_client_kick_timer_expired);
+}
+
+void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr)
+{
+	struct irmanager_event mgr_event;
+
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	if (self->client.state == IRLAN_IDLE) {
+		/* saddr may have changed! */
+		self->saddr = saddr;
+		
+		/* Check if network device is up */
+		if (self->dev.start) {
+			/* Open TSAPs */
+			irlan_client_open_ctrl_tsap(self);
+			irlan_provider_open_ctrl_tsap(self);
+			irlan_open_data_tsap(self);
+			
+			irlan_do_client_event(self, IRLAN_DISCOVERY_INDICATION,
+					      NULL);
+		} else if (self->notify_irmanager) {
+			/* 
+			 * Tell irmanager that the device can now be 
+			 * configured but only if the device was not taken
+			 * down by the user
+			 */
+			mgr_event.event = EVENT_IRLAN_START;
+			sprintf(mgr_event.devname, "%s", self->ifname);
+			irmanager_notify(&mgr_event);
+
+			/* 
+			 * We set this so that we only notify once, since if 
+			 * configuration of the network device fails, the user
+			 * will have to sort it out first anyway. No need to 
+			 * try again.
+			 */
+			self->notify_irmanager = FALSE;
+		}
+		/* Restart watchdog timer */
+		irlan_start_watchdog_timer(self, IRLAN_TIMEOUT);
+
+		/* Start kick timer */
+		irlan_client_start_kick_timer(self, 200);
+	} else {
+		DEBUG(2, __FUNCTION__ "(), state=%s\n", 
+		      irlan_state[ self->client.state]);
+		/*  
+		 *  If we get here, it's obvious that the last 
+		 *  connection attempt has failed, so its best 
+		 *  to go back to idle!
+		 */
+		irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
+	}
+}
+
+/*
+ * Function irlan_discovery_indication (daddr)
+ *
+ *    Remote device with IrLAN server support discovered
+ *
+ */
+void irlan_client_discovery_indication(DISCOVERY *discovery) 
+{
+	struct irlan_cb *self, *entry;
+	__u32 saddr, daddr;
+	
+	DEBUG(2, __FUNCTION__"()\n");
+
+	ASSERT(irlan != NULL, return;);
+	ASSERT(discovery != NULL, return;);
+
+	saddr = discovery->saddr;
+	daddr = discovery->daddr;
+
+	/* 
+	 *  Check if we already have an instance for dealing with this 
+	 *  provider.
+	 */
+	self = (struct irlan_cb *) hashbin_find(irlan, daddr, NULL);
+      	if (self) {
+		ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+		DEBUG(2, __FUNCTION__ "(), Found instance!\n");
+		
+		irlan_client_wakeup(self, saddr, daddr);
+
+		return;
+	}
+	
+	/* 
+	 * We have no instance for daddr, so try and find an unused one
+	 */
+	self = hashbin_find(irlan, DEV_ADDR_ANY, NULL);
+	if (self) {
+		DEBUG(2, __FUNCTION__ "(), Found instance with DEV_ADDR_ANY!\n");
+		/*
+		 * Rehash instance, now we have a client (daddr) to serve.
+		 */
+		entry = hashbin_remove(irlan, self->daddr, NULL);
+		ASSERT( entry == self, return;);
+
+		self->daddr = daddr;
+		self->saddr = saddr;
+
+		DEBUG(2, __FUNCTION__ "(), daddr=%08x\n", self->daddr);
+		hashbin_insert(irlan, (QUEUE*) self, self->daddr, NULL);
+		
+		/* Check if network device has been registered */
+		if (!self->netdev_registered)
+			irlan_register_netdev(self);
+		
+		/* Remember that we might have to start a new provider */
+		self->client.start_new_provider = TRUE;
+	} else {
+		DEBUG(2, __FUNCTION__ "(), Found none, starting new one!\n");
+		/* No instance available, so we have to start one! */
+		self = irlan_open(saddr, daddr, TRUE);
+		if (!self) {
+			DEBUG(2, __FUNCTION__ "(), irlan_open failed!\n");
+			return;
+		}
+		ASSERT( self != NULL, return;);
+	}
+	/* Restart watchdog timer */
+	irlan_start_watchdog_timer(self, IRLAN_TIMEOUT);
+}
+	
+/*
+ * Function irlan_client_data_indication (handle, skb)
+ *
+ *    This function gets the data that is received on the control channel
+ *
+ */
+static void irlan_client_ctrl_data_indication(void *instance, void *sap, 
+					      struct sk_buff *skb)
+{
+	struct irlan_cb *self;
+	
+	DEBUG(4, __FUNCTION__ "()\n");
+	
+	self = (struct irlan_cb *) instance;
+	
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
+	
+	irlan_do_client_event(self, IRLAN_DATA_INDICATION, skb); 
+}
+
+static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap, 
+						    LM_REASON reason, 
+						    struct sk_buff *userdata) 
+{
+	struct irlan_cb *self;
+	struct tsap_cb *tsap;
+
+	DEBUG(4, __FUNCTION__ "(), reason=%d\n", reason);
+	
+	self = (struct irlan_cb *) instance;
+	tsap = (struct tsap_cb *) sap;
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);	
+	ASSERT(tsap != NULL, return;);
+	ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
+	
+	ASSERT(tsap == self->client.tsap_ctrl, return;);
+
+	irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
+}
+
+/*
+ * Function irlan_client_open_tsaps (self)
+ *
+ *    Initialize callbacks and open IrTTP TSAPs
+ *
+ */
+void irlan_client_open_ctrl_tsap(struct irlan_cb *self)
+{
+	struct notify_t notify;
+	struct tsap_cb *tsap;
+
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	/* Check if already open */
+	if (self->client.tsap_ctrl)
+		return;
+
+	irda_notify_init(&notify);
+
+	/* Set up callbacks */
+	notify.data_indication       = irlan_client_ctrl_data_indication;
+	notify.connect_confirm       = irlan_client_ctrl_connect_confirm;
+	notify.disconnect_indication = irlan_client_ctrl_disconnect_indication;
+	notify.instance = self;
+	strncpy(notify.name, "IrLAN ctrl (c)", NOTIFY_MAX_NAME);
+	
+	tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);
+	if (!tsap) {
+		DEBUG(2, __FUNCTION__ "(), Got no tsap!\n");
+		return;
+	}
+	self->client.tsap_ctrl = tsap;
+}
+
+/*
+ * Function irlan_client_connect_confirm (handle, skb)
+ *
+ *    Connection to peer IrLAN laye confirmed
+ *
+ */
+static void irlan_client_ctrl_connect_confirm(void *instance, void *sap, 
+					      struct qos_info *qos, 
+					      int max_sdu_size,
+					      struct sk_buff *skb) 
+{
+	struct irlan_cb *self;
+
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	self = (struct irlan_cb *) instance;
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	/* TODO: we could set the MTU depending on the max_sdu_size */
+
+	irlan_do_client_event(self, IRLAN_CONNECT_COMPLETE, NULL);
+}
+
+/*
+ * Function irlan_client_reconnect_data_channel (self)
+ *
+ *    Try to reconnect data channel (currently not used)
+ *
+ */
+void irlan_client_reconnect_data_channel(struct irlan_cb *self) 
+{
+	struct sk_buff *skb;
+	__u8 *frame;
+		
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+	
+	skb = dev_alloc_skb(128);
+	if (!skb)
+		return;
+
+	/* Reserve space for TTP, LMP, and LAP header */
+	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_put(skb, 2);
+	
+	frame = skb->data;
+	
+ 	frame[0] = CMD_RECONNECT_DATA_CHAN;
+	frame[1] = 0x01;
+ 	irlan_insert_array_param(skb, "RECONNECT_KEY", 
+				 self->client.reconnect_key,
+				 self->client.key_len);
+	
+	irttp_data_request(self->client.tsap_ctrl, skb);	
+}
+
+/*
+ * Function irlan_client_extract_params (skb)
+ *
+ *    Extract all parameters from received buffer, then feed them to 
+ *    check_params for parsing
+ *
+ */
+void irlan_client_extract_params(struct irlan_cb *self, struct sk_buff *skb)
+{
+	__u8 *frame;
+	__u8 *ptr;
+	int count;
+	int ret;
+	__u16 val_len;
+	int i;
+        char *name;
+        char *value;
+
+	ASSERT(skb != NULL, return;);	
+	
+	DEBUG(4, __FUNCTION__ "() skb->len=%d\n", (int) skb->len);
+	
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+	
+	if (!skb) {
+		DEBUG(2, __FUNCTION__ "(), Got NULL skb!\n");
+		return;
+	}
+	frame = skb->data;
+	
+	/* 
+	 *  Check return code and print it if not success 
+	 */
+	if (frame[0]) {
+		print_ret_code(frame[0]);
+		return;
+	}
+	
+	name = kmalloc(255, GFP_ATOMIC);
+	if (!name)
+		return;
+	value = kmalloc(1016, GFP_ATOMIC);
+	if (!value) {
+		kfree(name);
+		return;
+	}
+
+	/* How many parameters? */
+	count = frame[1];
+
+	DEBUG(4, __FUNCTION__ "(), got %d parameters\n", count);
+	
+	ptr = frame+2;
+
+	/* For all parameters */
+ 	for (i=0; i<count;i++) {
+		ret = irlan_get_param(ptr, name, value, &val_len);
+		if (ret == -1) {
+			DEBUG(2, __FUNCTION__ "(), IrLAN, Error!\n");
+			break;
+		}
+		ptr+=ret;
+		irlan_check_response_param(self, name, value, val_len);
+ 	}
+	/* Cleanup */
+	kfree(name);
+	kfree(value);
+}
+
+/*
+ * Function check_param (param, value)
+ *
+ *    Check which parameter is received and update local variables
+ *
+ */
+static void irlan_check_response_param(struct irlan_cb *self, char *param, 
+				       char *value, int val_len) 
+{
+	struct in_device *in_dev;
+	__u8 *bytes;
+	int i;
+
+	DEBUG(4, __FUNCTION__ "(), parm=%s\n", param);
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	/*
+	 *  Media type
+	 */
+	if (strcmp(param, "MEDIA") == 0) {
+		if (strcmp(value, "802.3") == 0)
+			self->media = MEDIA_802_3;
+		else
+			self->media = MEDIA_802_5;
+		return;
+	}
+	if (strcmp(param, "FILTER_TYPE") == 0) {
+		if (strcmp(value, "DIRECTED") == 0)
+			self->client.filter_type |= IRLAN_DIRECTED;
+		else if (strcmp(value, "FUNCTIONAL") == 0)
+			self->client.filter_type |= IRLAN_FUNCTIONAL;
+		else if (strcmp(value, "GROUP") == 0)
+			self->client.filter_type |= IRLAN_GROUP;
+		else if (strcmp(value, "MAC_FRAME") == 0)
+			self->client.filter_type |= IRLAN_MAC_FRAME;
+		else if (strcmp(value, "MULTICAST") == 0)
+			self->client.filter_type |= IRLAN_MULTICAST;
+		else if (strcmp(value, "BROADCAST") == 0)
+			self->client.filter_type |= IRLAN_BROADCAST;
+		else if (strcmp(value, "IPX_SOCKET") == 0)
+			self->client.filter_type |= IRLAN_IPX_SOCKET;
+		
+	}
+	if (strcmp(param, "ACCESS_TYPE") == 0) {
+		if (strcmp(value, "DIRECT") == 0)
+			self->access_type = ACCESS_DIRECT;
+		else if (strcmp(value, "PEER") == 0)
+			self->access_type = ACCESS_PEER;
+		else if (strcmp(value, "HOSTED") == 0)
+			self->access_type = ACCESS_HOSTED;
+		else {
+			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], 
+		      (__u8) value[1]);
+
+		self->version[0] = value[0];
+		self->version[1] = value[1];
+		return;
+	}
+	/*
+	 *  Which remote TSAP to use for data channel
+	 */
+	if (strcmp(param, "DATA_CHAN") == 0) {
+		self->dtsap_sel_data = value[0];
+		DEBUG(4, "Data TSAP = %02x\n", self->dtsap_sel_data);
+		return;
+	}
+	if (strcmp(param, "CON_ARB") == 0) {
+		self->client.recv_arb_val = le16_to_cpup(value);
+		DEBUG(2, __FUNCTION__ "(), receive arb val=%d\n", 
+		      self->client.recv_arb_val);
+	}
+	if (strcmp(param, "MAX_FRAME") == 0) {
+		self->client.max_frame = le16_to_cpup(value);
+		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: ");
+		/* 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");
+	}
+	/*
+	 *  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",
+		      bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], 
+		      bytes[5]);
+		for (i = 0; i < 6; i++) 
+			self->dev.dev_addr[i] = bytes[i];
+
+#ifdef CONFIG_IRLAN_GRATUITOUS_ARP
+		/* 
+		 * When we get a new MAC address do a gratuitous ARP. This
+		 * is useful if we have changed access points on the same
+		 * subnet.  
+		 */
+		DEBUG(4, "IrLAN: Sending gratuitous ARP\n");
+		in_dev = self->dev.ip_ptr;
+		arp_send(ARPOP_REQUEST, ETH_P_ARP, 
+			  in_dev->ifa_list->ifa_address,
+			  &self->dev, 
+			  in_dev->ifa_list->ifa_address,
+			  NULL, self->dev.dev_addr, NULL);
+#endif
+	}
+}
+
+/*
+ * Function irlan_client_get_value_confirm (obj_id, value)
+ *
+ *    Got results from remote LM-IAS
+ *
+ */
+void irlan_client_get_value_confirm(__u16 obj_id, struct ias_value *value,
+				    void *priv) 
+{
+	struct irlan_cb *self;
+	
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(priv != NULL, return;);
+
+	self = (struct irlan_cb *) priv;
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	/* Check if request succeeded */
+	if (!value) {
+		DEBUG(2, __FUNCTION__ "(), got NULL value!\n");
+		irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL, 
+				      NULL);
+		return;
+	}
+
+	switch (value->type) {
+	case IAS_INTEGER:
+		self->dtsap_sel_ctrl = value->t.integer;
+
+		if (value->t.integer != -1) {
+			irlan_do_client_event(self, IRLAN_IAS_PROVIDER_AVAIL,
+					      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");
+		break;
+	default:
+		DEBUG(2, __FUNCTION__ "(), unknown type!\n");
+		break;
+	}
+	irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL, NULL);
+}
diff -u --recursive --new-file v2.2.2/linux/net/irda/irlan/irlan_client_event.c linux/net/irda/irlan/irlan_client_event.c
--- v2.2.2/linux/net/irda/irlan/irlan_client_event.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irlan/irlan_client_event.c	Sun Mar  7 15:26:44 1999
@@ -0,0 +1,532 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_client_event.c
+ * Version:       0.9
+ * Description:   IrLAN client state machine
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Aug 31 20:14:37 1997
+ * Modified at:   Thu Feb  4 16:08:07 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     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.
+ *
+ *     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.
+ *
+ ********************************************************************/
+
+#include <linux/skbuff.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/timer.h>
+#include <net/irda/irmod.h>
+#include <net/irda/iriap.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/irttp.h>
+
+#include <net/irda/irlan_common.h>
+#include <net/irda/irlan_client.h>
+#include <net/irda/irlan_event.h>
+
+static int irlan_client_state_idle (struct irlan_cb *self, IRLAN_EVENT event, 
+				    struct sk_buff *skb);
+static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event, 
+				    struct sk_buff *skb);
+static int irlan_client_state_conn (struct irlan_cb *self, IRLAN_EVENT event, 
+				    struct sk_buff *skb);
+static int irlan_client_state_info (struct irlan_cb *self, IRLAN_EVENT event, 
+				    struct sk_buff *skb);
+static int irlan_client_state_media(struct irlan_cb *self, IRLAN_EVENT event, 
+				    struct sk_buff *skb);
+static int irlan_client_state_open (struct irlan_cb *self, IRLAN_EVENT event, 
+				    struct sk_buff *skb);
+static int irlan_client_state_wait (struct irlan_cb *self, IRLAN_EVENT event, 
+				    struct sk_buff *skb);
+static int irlan_client_state_arb  (struct irlan_cb *self, IRLAN_EVENT event, 
+				    struct sk_buff *skb);
+static int irlan_client_state_data (struct irlan_cb *self, IRLAN_EVENT event, 
+				    struct sk_buff *skb);
+static int irlan_client_state_close(struct irlan_cb *self, IRLAN_EVENT event, 
+				    struct sk_buff *skb);
+static int irlan_client_state_sync (struct irlan_cb *self, IRLAN_EVENT event, 
+				    struct sk_buff *skb);
+
+static int (*state[])(struct irlan_cb *, IRLAN_EVENT event, struct sk_buff *) =
+{ 
+	irlan_client_state_idle,
+	irlan_client_state_query,
+	irlan_client_state_conn,
+	irlan_client_state_info,
+	irlan_client_state_media,
+	irlan_client_state_open,
+	irlan_client_state_wait,
+	irlan_client_state_arb,
+	irlan_client_state_data,
+	irlan_client_state_close,
+	irlan_client_state_sync
+};
+
+void irlan_do_client_event(struct irlan_cb *self, IRLAN_EVENT event, 
+			   struct sk_buff *skb) 
+{
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	(*state[ self->client.state]) (self, event, skb);
+}
+
+/*
+ * Function irlan_client_state_idle (event, skb, info)
+ *
+ *    IDLE, We are waiting for an indication that there is a provider
+ *    available.
+ */
+static int irlan_client_state_idle(struct irlan_cb *self, IRLAN_EVENT event, 
+				   struct sk_buff *skb) 
+{
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+	
+	switch(event) {
+	case IRLAN_DISCOVERY_INDICATION:
+		/* Get some values from peer IAS */
+		iriap_getvaluebyclass_request(
+			"IrLAN", "IrDA:TinyTP:LsapSel",
+			self->saddr, self->daddr,
+			irlan_client_get_value_confirm, self);
+		
+		irlan_next_client_state(self, IRLAN_QUERY);
+		break;
+	case IRLAN_WATCHDOG_TIMEOUT:
+		DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+		break;
+	default:
+		DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event);
+		break;
+	}
+	if (skb) 
+		dev_kfree_skb(skb);
+
+	return 0;
+}
+
+/*
+ * Function irlan_client_state_query (event, skb, info)
+ *
+ *    QUERY, We have queryed the remote IAS and is ready to connect
+ *    to provider, just waiting for the confirm.
+ *
+ */
+static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event, 
+				    struct sk_buff *skb) 
+{
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+	
+	switch(event) {
+	case IRLAN_IAS_PROVIDER_AVAIL:
+		ASSERT(self->dtsap_sel_ctrl != 0, return -1;);
+
+		self->client.open_retries = 0;
+		
+		irttp_connect_request(self->client.tsap_ctrl, 
+				      self->dtsap_sel_ctrl, 
+				      self->saddr, self->daddr, NULL, 
+				      IRLAN_MTU, NULL);
+		irlan_next_client_state(self, IRLAN_CONN);
+		break;
+	case IRLAN_IAS_PROVIDER_NOT_AVAIL:
+		DEBUG(2, __FUNCTION__ "(), IAS_PROVIDER_NOT_AVAIL\n");
+		irlan_next_client_state(self, IRLAN_IDLE);
+
+		/* Give the client a kick! */
+		if ((self->access_type == ACCESS_PEER) && 
+		    (self->provider.state != IRLAN_IDLE))
+			irlan_client_wakeup(self, self->saddr, self->daddr);
+		break;
+	case IRLAN_LMP_DISCONNECT:
+	case IRLAN_LAP_DISCONNECT:
+		irlan_next_client_state(self, IRLAN_IDLE);
+		break;
+	case IRLAN_WATCHDOG_TIMEOUT:
+		DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+		break;
+	default:
+		DEBUG(2, __FUNCTION__"(), Unknown event %d\n", event);
+		break;
+	}
+	if (skb)
+		dev_kfree_skb(skb);
+	
+	return 0;
+}
+
+/*
+ * Function irlan_client_state_conn (event, skb, info)
+ *
+ *    CONN, We have connected to a provider but has not issued any
+ *    commands yet.
+ *
+ */
+static int irlan_client_state_conn(struct irlan_cb *self, IRLAN_EVENT event, 
+				   struct sk_buff *skb) 
+{
+	DEBUG(4, __FUNCTION__ "()\n");
+	
+	ASSERT(self != NULL, return -1;);
+	
+	switch(event) {
+	case IRLAN_CONNECT_COMPLETE:
+		/* Send getinfo cmd */
+		irlan_get_provider_info(self);
+		irlan_next_client_state(self, IRLAN_INFO);
+		break;
+	case IRLAN_LMP_DISCONNECT:
+	case IRLAN_LAP_DISCONNECT:
+		irlan_next_client_state(self, IRLAN_IDLE);
+		break;
+	case IRLAN_WATCHDOG_TIMEOUT:
+		DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+		break;
+	default:
+		DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+		break;
+	}
+	if (skb)
+		dev_kfree_skb(skb);
+	
+	return 0;
+}
+
+/*
+ * Function irlan_client_state_info (self, event, skb, info)
+ *
+ *    INFO, We have issued a GetInfo command and is awaiting a reply.
+ */
+static int irlan_client_state_info(struct irlan_cb *self, IRLAN_EVENT event, 
+				   struct sk_buff *skb) 
+{
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return -1;);
+	
+	switch(event) {
+	case IRLAN_DATA_INDICATION:
+		ASSERT(skb != NULL, return -1;);
+	
+		irlan_client_extract_params(self, skb);
+		
+		irlan_next_client_state(self, IRLAN_MEDIA);
+		
+		irlan_get_media_char(self);
+		break;
+		
+	case IRLAN_LMP_DISCONNECT:
+	case IRLAN_LAP_DISCONNECT:
+		irlan_next_client_state(self, IRLAN_IDLE);
+		break;
+	case IRLAN_WATCHDOG_TIMEOUT:
+		DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+		break;
+	default:
+		DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+		break;
+	}
+	if (skb)
+		dev_kfree_skb(skb);
+	
+	return 0;
+}
+
+/*
+ * Function irlan_client_state_media (self, event, skb, info)
+ *
+ *    MEDIA, The irlan_client has issued a GetMedia command and is awaiting a
+ *    reply.
+ *
+ */
+static int irlan_client_state_media(struct irlan_cb *self, IRLAN_EVENT event, 
+				    struct sk_buff *skb) 
+{
+	DEBUG(4, __FUNCTION__ "()\n");
+	
+	ASSERT(self != NULL, return -1;);
+
+	switch(event) {
+	case IRLAN_DATA_INDICATION:
+		irlan_client_extract_params(self, skb);
+		irlan_open_data_channel(self);
+		irlan_next_client_state(self, IRLAN_OPEN);
+		break;
+	case IRLAN_LMP_DISCONNECT:
+	case IRLAN_LAP_DISCONNECT:
+		irlan_next_client_state(self, IRLAN_IDLE);
+		break;
+	case IRLAN_WATCHDOG_TIMEOUT:
+		DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+		break;
+	default:
+		DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+		break;
+	}
+	if (skb)
+		dev_kfree_skb(skb);
+	
+	return 0;
+}
+
+/*
+ * Function irlan_client_state_open (self, event, skb, info)
+ *
+ *    OPEN, The irlan_client has issued a OpenData command and is awaiting a
+ *    reply
+ *
+ */
+static int irlan_client_state_open(struct irlan_cb *self, IRLAN_EVENT event, 
+				   struct sk_buff *skb) 
+{
+	struct qos_info qos;
+
+	DEBUG(4, __FUNCTION__ "()\n");
+	
+	ASSERT(self != NULL, return -1;);
+
+	switch(event) {
+	case IRLAN_DATA_INDICATION:
+		irlan_client_extract_params(self, skb);
+		
+		/*
+		 *  Check if we have got the remote TSAP for data 
+		 *  communications
+		 */
+	  	ASSERT(self->dtsap_sel_data != 0, return -1;);
+
+		/* Check which access type we are dealing with */
+		switch(self->access_type) {
+		case ACCESS_PEER:
+		    if (self->provider.state == IRLAN_OPEN) {
+			    
+			    irlan_next_client_state(self, IRLAN_ARB);
+			    irlan_do_client_event(self, IRLAN_CHECK_CON_ARB, 
+						  NULL);
+		    } else {
+			
+			    irlan_next_client_state(self, IRLAN_WAIT);
+		    }
+		    break;
+		case ACCESS_DIRECT:
+		case ACCESS_HOSTED:
+			qos.link_disc_time.bits = 0x01; /* 3 secs */
+			
+			irttp_connect_request(self->tsap_data, 
+					      self->dtsap_sel_data, 
+					      self->saddr, self->daddr, &qos, 
+					      IRLAN_MTU, NULL);
+			
+			irlan_next_client_state(self, IRLAN_DATA);
+
+			if (self->client.start_new_provider) {
+				irlan_open(DEV_ADDR_ANY, DEV_ADDR_ANY, FALSE);
+				self->client.start_new_provider = FALSE;
+			}
+			break;
+		default:
+			DEBUG(2, __FUNCTION__ "(), unknown access type!\n");
+			break;
+		}
+		break;
+	case IRLAN_LMP_DISCONNECT:
+	case IRLAN_LAP_DISCONNECT:
+		irlan_next_client_state(self, IRLAN_IDLE);
+		break;
+	case IRLAN_WATCHDOG_TIMEOUT:
+		DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+		break;
+	default:
+		DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+		break;
+	}
+	
+	if (skb)
+		dev_kfree_skb(skb);
+
+	return 0;
+}
+
+/*
+ * Function irlan_client_state_wait (self, event, skb, info)
+ *
+ *    WAIT, The irlan_client is waiting for the local provider to enter the
+ *    provider OPEN state.
+ *
+ */
+static int irlan_client_state_wait(struct irlan_cb *self, IRLAN_EVENT event, 
+				   struct sk_buff *skb) 
+{
+	DEBUG(4, __FUNCTION__ "()\n");
+	
+	ASSERT(self != NULL, return -1;);
+	
+	switch(event) {
+	case IRLAN_PROVIDER_SIGNAL:
+		irlan_next_client_state(self, IRLAN_ARB);
+		irlan_do_client_event(self, IRLAN_CHECK_CON_ARB, NULL);
+		break;
+	case IRLAN_LMP_DISCONNECT:
+	case IRLAN_LAP_DISCONNECT:
+		irlan_next_client_state(self, IRLAN_IDLE);
+		break;
+	case IRLAN_WATCHDOG_TIMEOUT:
+		DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+		break;
+	default:
+		DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+		break;
+	}
+	if (skb)
+		dev_kfree_skb(skb);
+	
+	return 0;
+}
+
+static int irlan_client_state_arb(struct irlan_cb *self, IRLAN_EVENT event, 
+				  struct sk_buff *skb) 
+{
+	struct qos_info qos;
+
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return -1;);
+	
+	switch(event) {
+	case IRLAN_CHECK_CON_ARB:
+		if (self->client.recv_arb_val == self->provider.send_arb_val) {
+			irlan_next_client_state(self, IRLAN_CLOSE);
+			irlan_close_data_channel(self);
+		} else if (self->client.recv_arb_val < 
+			   self->provider.send_arb_val) 
+		{
+			qos.link_disc_time.bits = 0x01; /* 3 secs */
+
+			irlan_next_client_state(self, IRLAN_DATA);
+			irttp_connect_request(self->tsap_data, 
+					      self->dtsap_sel_data, 
+					      self->saddr, self->daddr, &qos, 
+					      IRLAN_MTU, NULL);
+		} else if (self->client.recv_arb_val >
+			   self->provider.send_arb_val) 
+		{
+			DEBUG(2, __FUNCTION__ "(), lost the battle :-(\n");
+		}
+		break;
+	case IRLAN_DATA_CONNECT_INDICATION:
+		irlan_next_client_state(self, IRLAN_DATA);
+		break;
+	case IRLAN_LMP_DISCONNECT:
+	case IRLAN_LAP_DISCONNECT:
+		irlan_next_client_state(self, IRLAN_IDLE);
+		break;
+	case IRLAN_WATCHDOG_TIMEOUT:
+		DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+		break;
+	default:
+		DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+		break;
+	}
+	if (skb)
+		dev_kfree_skb(skb);
+	
+	return 0;
+}
+
+/*
+ * Function irlan_client_state_data (self, event, skb, info)
+ *
+ *    DATA, The data channel is connected, allowing data transfers between
+ *    the local and remote machines.
+ *
+ */
+static int irlan_client_state_data(struct irlan_cb *self, IRLAN_EVENT event, 
+				   struct sk_buff *skb) 
+{
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+
+	switch(event) {
+	case IRLAN_DATA_INDICATION:
+		irlan_client_extract_params(self, skb);
+		break;		
+	case IRLAN_LMP_DISCONNECT: /* FALLTHROUGH */
+	case IRLAN_LAP_DISCONNECT:
+		irlan_next_client_state(self, IRLAN_IDLE);
+		break;
+	default:
+		DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+		break;
+	}
+	if (skb)
+		dev_kfree_skb(skb);
+	
+	return 0;
+}
+
+/*
+ * Function irlan_client_state_close (self, event, skb, info)
+ *
+ *    
+ *
+ */
+static int irlan_client_state_close(struct irlan_cb *self, IRLAN_EVENT event, 
+				    struct sk_buff *skb) 
+{
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	if (skb)
+		dev_kfree_skb(skb);
+
+	return 0;
+}
+
+/*
+ * Function irlan_client_state_sync (self, event, skb, info)
+ *
+ *    
+ *
+ */
+static int irlan_client_state_sync(struct irlan_cb *self, IRLAN_EVENT event, 
+				   struct sk_buff *skb) 
+{
+	DEBUG(2, __FUNCTION__ "()\n");
+	
+	if (skb)
+		dev_kfree_skb(skb);
+	
+	return 0;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -u --recursive --new-file v2.2.2/linux/net/irda/irlan/irlan_common.c linux/net/irda/irlan/irlan_common.c
--- v2.2.2/linux/net/irda/irlan/irlan_common.c	Wed Jan 20 23:14:07 1999
+++ linux/net/irda/irlan/irlan_common.c	Sun Mar  7 15:26:44 1999
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irlan_common.c
- * Version:       0.1
+ * Version:       0.9
  * Description:   IrDA LAN Access Protocol Implementation
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Tue Jan 19 23:11:30 1999
+ * Modified at:   Wed Feb 17 23:49:10 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -44,17 +44,59 @@
 #include <net/irda/timer.h>
 
 #include <net/irda/irlan_common.h>
+#include <net/irda/irlan_client.h>
+#include <net/irda/irlan_provider.h> 
+#include <net/irda/irlan_eth.h>
+#include <net/irda/irlan_filter.h>
 
-static void __irlan_close( struct irlan_cb *self);
+/* extern char sysctl_devname[]; */
 
 /*
  *  Master structure
  */
 hashbin_t *irlan = NULL;
 
+/* 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",
+	"IRLAN_QUERY",
+	"IRLAN_CONN", 
+	"IRLAN_INFO",
+	"IRLAN_MEDIA",
+	"IRLAN_OPEN",
+	"IRLAN_WAIT",
+	"IRLAN_ARB", 
+	"IRLAN_DATA",
+	"IRLAN_CLOSE",
+	"IRLAN_SYNC"
+};
+
+static char *irlan_access[] = {
+	"UNKNOWN",
+	"DIRECT",
+	"PEER",
+	"HOSTED"
+};
+
+static char *irlan_media[] = {
+	"UNKNOWN",
+	"802.3",
+	"802.5"
+};
+
+static void __irlan_close(struct irlan_cb *self);
+static int __irlan_insert_param(struct sk_buff *skb, char *param, int type, 
+				__u8 value_byte, __u16 value_short, 
+				__u8 *value_array, __u16 value_len);
+static void irlan_close_tsaps(struct irlan_cb *self);
+
 #ifdef CONFIG_PROC_FS
-static int irlan_proc_read( char *buf, char **start, off_t offset, 
-			    int len, int unused);
+static int irlan_proc_read(char *buf, char **start, off_t offset, int len, 
+			   int unused);
 
 extern struct proc_dir_entry proc_irda;
 
@@ -64,7 +106,164 @@
 	0, NULL,
 	&irlan_proc_read,
 };
+#endif /* CONFIG_PROC_FS */
+
+void irlan_watchdog_timer_expired(unsigned long data)
+{
+	struct irmanager_event mgr_event;
+	struct irlan_cb *self = (struct irlan_cb *) data;
+	
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	/* Check if device still configured */
+	if (self->dev.start) {
+		mgr_event.event = EVENT_IRLAN_STOP;
+		sprintf(mgr_event.devname, "%s", self->ifname);
+		irmanager_notify(&mgr_event);
+
+		/*
+		 *  We set this to false, so that irlan_dev_close known that
+		 *  notify_irmanager should actually be set to TRUE again 
+		 *  instead of FALSE, since this close has not been initiated
+		 *  by the user.
+		 */
+		self->notify_irmanager = FALSE;
+	} else
+		irlan_close(self);
+}
+
+void irlan_start_watchdog_timer(struct irlan_cb *self, int timeout)
+{
+	DEBUG(4, __FUNCTION__ "()\n");
+	
+	irda_start_timer(&self->watchdog_timer, timeout, (unsigned long) self,
+			 irlan_watchdog_timer_expired);
+}
+
+static int irlan_eth_open(struct device *dev)
+{
+	struct irlan_cb *self;
+	
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(dev != NULL, return -1;);
+
+	self = (struct irlan_cb *) dev->priv;
+
+	ASSERT(self != NULL, return -1;);
+
+	/* Ready to play! */
+/* 	dev->tbusy = 0; */ /* Wait until data link is ready */
+	dev->interrupt = 0;
+	dev->start = 1;
+
+	self->notify_irmanager = TRUE;
+
+	MOD_INC_USE_COUNT;
+	
+	return 0;
+}
+
+/*
+ * Function irlan_eth_close (dev)
+ *
+ *    Stop the ether network device, his function will usually be called by
+ *    ifconfig down. We should now disconnect the link, We start the 
+ *    close timer, so that the instance will be removed if we are unable
+ *    to discover the remote device after the disconnect.
+ */
+static int irlan_eth_close(struct device *dev)
+{
+	struct irlan_cb *self = (struct irlan_cb *) dev->priv;
+
+	DEBUG(4, __FUNCTION__ "()\n");
+	
+	/* Stop device */
+	dev->tbusy = 1;
+	dev->start = 0;
+
+	MOD_DEC_USE_COUNT;
+
+	irlan_close_data_channel(self);
+
+	irlan_close_tsaps(self);
+
+	irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
+	irlan_do_provider_event(self, IRLAN_LMP_DISCONNECT, NULL);	
+	
+	irlan_start_watchdog_timer(self, IRLAN_TIMEOUT);
+
+	/* Device closed by user */
+	if (self->notify_irmanager)
+		self->notify_irmanager = FALSE;
+	else
+		self->notify_irmanager = TRUE;
+
+	return 0;
+}
+/*
+ * Function irlan_eth_init (dev)
+ *
+ *    The network device initialization function.
+ *
+ */
+int irlan_eth_init(struct device *dev)
+{
+	struct irmanager_event mgr_event;
+	struct irlan_cb *self;
+
+	DEBUG(4, __FUNCTION__"()\n");
+
+	ASSERT(dev != NULL, return -1;);
+       
+	self = (struct irlan_cb *) dev->priv;
+
+	dev->open               = irlan_eth_open;
+	dev->stop               = irlan_eth_close;
+	dev->hard_start_xmit    = irlan_eth_xmit; 
+	dev->get_stats	        = irlan_eth_get_stats;
+	dev->set_multicast_list = irlan_eth_set_multicast_list;
+
+	dev->tbusy = 1;
+	
+	ether_setup(dev);
+	
+	dev->tx_queue_len = TTP_MAX_QUEUE;
+
+#ifdef 0
+	/*  
+	 *  OK, since we are emulating an IrLAN sever we will have to give
+	 *  ourself an ethernet address!
+	 *  FIXME: this must be more dynamically
+	 */
+	dev->dev_addr[0] = 0x40;
+	dev->dev_addr[1] = 0x00;
+	dev->dev_addr[2] = 0x00;
+	dev->dev_addr[3] = 0x00;
+	dev->dev_addr[4] = 0x23;
+	dev->dev_addr[5] = 0x45;
 #endif
+	/* 
+	 * Network device has now been registered, so tell irmanager about
+	 * it, so it can be configured with network parameters
+	 */
+	mgr_event.event = EVENT_IRLAN_START;
+	sprintf(mgr_event.devname, "%s", self->ifname);
+	irmanager_notify(&mgr_event);
+
+	/* 
+	 * We set this so that we only notify once, since if 
+	 * configuration of the network device fails, the user
+	 * will have to sort it out first anyway. No need to 
+	 * try again.
+	 */
+	self->notify_irmanager = FALSE;
+
+	return 0;
+}
 
 /*
  * Function irlan_init (void)
@@ -72,61 +271,147 @@
  *    Initialize IrLAN layer
  *
  */
-__initfunc(int irlan_init( void))
+__initfunc(int irlan_init(void))
 {
+	struct irlan_cb *new;
+
+	DEBUG(4, __FUNCTION__"()\n");
+
 	/* Allocate master array */
-	irlan = hashbin_new( HB_LOCAL); 
-	if ( irlan == NULL) {
-		printk( KERN_WARNING "IrLAN: Can't allocate hashbin!\n");
+	irlan = hashbin_new(HB_LOCAL); 
+	if (irlan == NULL) {
+		printk(KERN_WARNING "IrLAN: Can't allocate hashbin!\n");
 		return -ENOMEM;
 	}
 #ifdef CONFIG_PROC_FS
-	proc_register( &proc_irda, &proc_irlan);
+	proc_register(&proc_irda, &proc_irlan);
 #endif /* CONFIG_PROC_FS */
 
+	DEBUG(4, __FUNCTION__ "()\n");
+	
+	/* Register with IrLMP as a service user */
+	irlmp_register_layer(S_LAN, CLIENT, TRUE, 
+			     irlan_client_discovery_indication);
+	
+	/* Register with IrLMP as a service */
+ 	irlmp_register_layer(S_LAN, SERVER, FALSE, NULL);
+
+	/* Start the first IrLAN instance */
+ 	new = irlan_open(DEV_ADDR_ANY, DEV_ADDR_ANY, FALSE);
+
+	/* Do some fast discovery! */
+	irlmp_discovery_request(8);
+
 	return 0;
 }
 
 void irlan_cleanup(void) 
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	irlmp_unregister_layer(S_LAN, SERVER);
+
+	irlmp_unregister_layer(S_LAN, CLIENT);
 
 #ifdef CONFIG_PROC_FS
-	proc_unregister( &proc_irda, proc_irlan.low_ino);
-#endif
+	proc_unregister(&proc_irda, proc_irlan.low_ino);
+#endif /* CONFIG_PROC_FS */
 	/*
 	 *  Delete hashbin and close all irlan client instances in it
 	 */
-	hashbin_delete( irlan, (FREE_FUNC) __irlan_close);
+	hashbin_delete(irlan, (FREE_FUNC) __irlan_close);
 }
 
+/*
+ * Function irlan_register_netdev (self)
+ *
+ *    Registers the network device to be used. We should don't register until
+ *    we have been binded to a particular provider or client.
+ */
+int irlan_register_netdev(struct irlan_cb *self)
+{
+	int i=0;
+
+	DEBUG(4, __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);
+	}
+	self->dev.name = self->ifname;
+	
+	if (register_netdev(&self->dev) != 0) {
+		DEBUG(2, __FUNCTION__ 
+		      "(), register_netdev() failed!\n");
+		return -1;
+	}
+	self->netdev_registered = TRUE;
+	
+	return 0;
+}
 
 /*
  * Function irlan_open (void)
  *
- *    
- *
+ *    Open new instance of a client/provider, we should only register the 
+ *    network device if this instance is ment for a particular client/provider
  */
-struct irlan_cb *irlan_open(void)
+struct irlan_cb *irlan_open(__u32 saddr, __u32 daddr, int netdev)
 {
 	struct irlan_cb *self;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(2, __FUNCTION__ "()\n");
 
 	/* 
 	 *  Initialize the irlan structure. 
 	 */
-	self = kmalloc( sizeof(struct irlan_cb), GFP_ATOMIC);
-	if ( self == NULL)
+	self = kmalloc(sizeof(struct irlan_cb), GFP_ATOMIC);
+	if (self == NULL)
 		return NULL;
 	
-	memset( self, 0, sizeof( struct irlan_cb));
+	memset(self, 0, sizeof(struct irlan_cb));
 
 	/*
 	 *  Initialize local device structure
 	 */
 	self->magic = IRLAN_MAGIC;
 
+	ASSERT(irlan != NULL, return NULL;);
+	
+	sprintf(self->ifname, "%s", "unknown");
+
+	self->dev.priv = (void *) self;
+	self->dev.next = NULL;
+	self->dev.init = irlan_eth_init;
+	
+	self->saddr = saddr;
+	self->daddr = daddr;
+
+	/* Provider access can only be PEER, DIRECT, or HOSTED */
+	self->access_type = access;
+	self->media = MEDIA_802_3;
+
+	self->notify_irmanager = TRUE;
+
+	init_timer(&self->watchdog_timer);
+	init_timer(&self->client.kick_timer);
+
+	hashbin_insert(irlan, (QUEUE *) self, daddr, NULL);
+		
+	irlan_next_client_state(self, IRLAN_IDLE);
+	irlan_next_provider_state(self, IRLAN_IDLE);
+
+	irlan_open_data_tsap(self);
+  	irlan_provider_open_ctrl_tsap(self);
+	irlan_client_open_ctrl_tsap(self);
+
+	/* Register network device now, or wait until some later time? */
+	if (netdev)
+		irlan_register_netdev(self);
+
 	return self;
 }
 /*
@@ -137,63 +422,281 @@
  *    hashbin_remove() first!!!
  *
  */
-void __irlan_close( struct irlan_cb *self)
+static void __irlan_close(struct irlan_cb *self)
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(2, __FUNCTION__ "()\n");
 	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
 
-	/* 
-	 *  Disconnect open TSAP connections
-	 */
-	if ( self->tsap_data) {
-		irttp_disconnect_request( self->tsap_data, NULL, P_HIGH);
-		
-		/* FIXME: this will close the tsap before the disconenct
-		 * frame has been sent 
+	del_timer(&self->watchdog_timer);
+	del_timer(&self->client.kick_timer);
+
+	/* Close all open connections and remove TSAPs */
+	irlan_close_tsaps(self);
+
+	if (self->netdev_registered)
+		unregister_netdev(&self->dev);
+	
+	self->magic = 0;
+	kfree(self);
+}
+
+/*
+ * Function irlan_close (self)
+ *
+ *    Close instance
+ *
+ */
+void irlan_close(struct irlan_cb *self)
+{
+	struct irlan_cb *entry;
+	
+	DEBUG(2, __FUNCTION__ "()\n");
+
+        ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	/* Check if device is still configured */
+	if (self->dev.start) {
+		DEBUG(2, __FUNCTION__ 
+		       "(), Device still configured, closing later!\n");
+		return;
+	}
+	DEBUG(2, __FUNCTION__ "(), daddr=%08x\n", self->daddr);
+	entry = hashbin_remove(irlan, self->daddr, NULL);
+
+	ASSERT(entry == self, return;);
+	
+        __irlan_close(self);
+}
+
+void irlan_connect_indication(void *instance, void *sap, struct qos_info *qos,
+			      int max_sdu_size, struct sk_buff *skb)
+{
+	struct irlan_cb *self;
+	struct tsap_cb *tsap;
+
+	DEBUG(2, __FUNCTION__ "()\n");
+	
+	self = (struct irlan_cb *) instance;
+	tsap = (struct tsap_cb *) sap;
+	
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+	ASSERT(tsap == self->tsap_data,return;);
+
+	DEBUG(2, "IrLAN, We are now connected!\n");
+	del_timer(&self->watchdog_timer);
+
+	irlan_do_provider_event(self, IRLAN_DATA_CONNECT_INDICATION, skb);
+	irlan_do_client_event(self, IRLAN_DATA_CONNECT_INDICATION, skb);
+
+	if (self->access_type == ACCESS_PEER) {
+		/* 
+		 * Data channel is open, so we are now allowed to
+		 * configure the remote filter 
 		 */
-		/* irttp_close_tsap( self->tsap_data); */
+		irlan_get_unicast_addr(self);
+		irlan_open_unicast_addr(self);
 	}
-	if ( self->tsap_ctrl) {
-		irttp_disconnect_request( self->tsap_ctrl, NULL, P_HIGH);
-		
-		/* irttp_close_tsap( self->tsap_control); */
+	/* Ready to transfer Ethernet frames */
+	self->dev.tbusy = 0;
+}
+
+void irlan_connect_confirm(void *instance, void *sap, struct qos_info *qos, 
+			   int max_sdu_size, struct sk_buff *skb) 
+{
+	struct irlan_cb *self;
+
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	self = (struct irlan_cb *) instance;
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	/* TODO: we could set the MTU depending on the max_sdu_size */
+
+	DEBUG(2, "IrLAN, We are now connected!\n");
+	del_timer(&self->watchdog_timer);
+
+	/* 
+	 * Data channel is open, so we are now allowed to configure the remote
+	 * filter 
+	 */
+	irlan_get_unicast_addr(self);
+	irlan_open_unicast_addr(self);
+
+	/* Ready to transfer Ethernet frames */
+	self->dev.tbusy = 0;
+}
+
+/*
+ * Function irlan_client_disconnect_indication (handle)
+ *
+ *    Callback function for the IrTTP layer. Indicates a disconnection of
+ *    the specified connection (handle)
+ */
+void irlan_disconnect_indication(void *instance, void *sap, LM_REASON reason, 
+				 struct sk_buff *userdata) 
+{
+	struct irlan_cb *self;
+	struct tsap_cb *tsap;
+
+	DEBUG(2, __FUNCTION__ "(), reason=%d\n", reason);
+	
+	self = (struct irlan_cb *) instance;
+	tsap = (struct tsap_cb *) sap;
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);	
+	ASSERT(tsap != NULL, return;);
+	ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
+	
+	ASSERT(tsap == self->tsap_data, return;);
+
+	DEBUG(2, "IrLAN, data channel disconnected by peer!\n");
+
+	switch(reason) {
+	case LM_USER_REQUEST: /* User request */
+		irlan_close(self);
+		break;
+	case LM_LAP_DISCONNECT: /* Unexpected IrLAP disconnect */
+		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");
+		break;
+	case LM_LAP_RESET:  /* IrLAP reset */
+		DEBUG(2, __FUNCTION__ "(), LM_CONNECT_FAILURE not impl\n");
+		break;
+	case LM_INIT_DISCONNECT:
+		DEBUG(2, __FUNCTION__ "(), LM_CONNECT_FAILURE not impl\n");
+		break;
+	default:
+		break;
 	}
 	
-	unregister_netdev( &self->dev);
+	/* Stop IP from transmitting more packets */
+	/* irlan_client_flow_indication(handle, FLOW_STOP, priv); */
 
-	/*
-	 *  Make sure that nobody uses this instance anymore!
+	irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
+	irlan_do_provider_event(self, IRLAN_LMP_DISCONNECT, NULL);
+}
+
+void irlan_open_data_tsap(struct irlan_cb *self)
+{
+	struct notify_t notify;
+	struct tsap_cb *tsap;
+
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	/* Check if already open */
+	if (self->tsap_data)
+		return;
+
+	irda_notify_init(&notify);
+
+	notify.data_indication       = irlan_eth_receive;
+	notify.udata_indication      = irlan_eth_receive;
+	notify.connect_indication    = irlan_connect_indication;
+	notify.connect_confirm       = irlan_connect_confirm;
+ 	notify.flow_indication       = irlan_eth_flow_indication;
+	notify.disconnect_indication = irlan_disconnect_indication;
+	notify.instance              = self;
+	strncpy(notify.name, "IrLAN data", NOTIFY_MAX_NAME);
+
+	tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);
+	if (!tsap) {
+		DEBUG(2, __FUNCTION__ "(), Got no tsap!\n");
+		return;
+	}
+	self->tsap_data = tsap;
+
+	/* 
+	 *  This is the data TSAP selector which we will pass to the client
+	 *  when the client ask for it.
 	 */
-	self->magic = 0;
-	
-	/*
-	 *  Dealloacte structure
+	self->stsap_sel_data = self->tsap_data->stsap_sel;
+}
+
+static void irlan_close_tsaps(struct irlan_cb *self)
+{
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	/* 
+	 *  Disconnect and close all open TSAP connections
 	 */
-	kfree( self);
+	if (self->tsap_data) {
+		irttp_disconnect_request(self->tsap_data, NULL, P_NORMAL);
+		irttp_close_tsap(self->tsap_data);
+		self->tsap_data = NULL;
+		
+	}
+	if (self->client.tsap_ctrl) {
+		irttp_disconnect_request(self->client.tsap_ctrl, NULL, 
+					 P_NORMAL);
+		irttp_close_tsap(self->client.tsap_ctrl);
+		self->client.tsap_ctrl = NULL;
+	}
+	if (self->provider.tsap_ctrl) {
+		irttp_disconnect_request(self->provider.tsap_ctrl, NULL, 
+					 P_NORMAL);
+		irttp_close_tsap(self->provider.tsap_ctrl);
+		self->provider.tsap_ctrl = NULL;
+	}
 }
 
 /*
- * Function irlan_close (self)
+ * Function irlan_ias_register (self, tsap_sel)
  *
- *    
+ *    Register with LM-IAS
  *
  */
-void irlan_close( struct irlan_cb *self)
+void irlan_ias_register(struct irlan_cb *self, __u8 tsap_sel)
 {
-	struct irlan_cb *entry;
-	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	struct ias_object *obj;
+	struct ias_value *new_value;
 
-        ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
 	
-	entry = hashbin_remove( irlan, self->daddr, NULL);
-
-	ASSERT( entry == self, return;);
+	/* 
+	 * Check if object has already been registred by a previous provider.
+	 * If that is the case, we just change the value of the attribute
+	 */
+	if (!irias_find_object("IrLAN")) {
+		obj = irias_new_object("IrLAN", IAS_IRLAN_ID);
+		irias_add_integer_attrib(obj, "IrDA:TinyTP:LsapSel", tsap_sel);
+		irias_insert_object(obj);
+	} else {
+		new_value = irias_new_integer_value(tsap_sel);
+		irias_object_change_attribute("IrLAN", "IrDA:TinyTP:LsapSel",
+					      new_value);
+	}
 	
-        __irlan_close( self);
+        /* Register PnP object only if not registred before */
+        if (!irias_find_object("PnP")) {
+		obj = irias_new_object("PnP", IAS_PNP_ID);
+#if 0
+		irias_add_string_attrib(obj, "Name", sysctl_devname);
+#else
+		irias_add_string_attrib(obj, "Name", "Linux");
+#endif
+		irias_add_string_attrib(obj, "DeviceID", "HWP19F0");
+		irias_add_integer_attrib(obj, "CompCnt", 2);
+		irias_add_string_attrib(obj, "Comp#01", "PNP8294");
+		irias_add_string_attrib(obj, "Comp#02", "PNP8389");
+		irias_add_string_attrib(obj, "Manufacturer", "Linux-IrDA Project");
+		irias_insert_object(obj);
+	}
 }
 
 /*
@@ -202,33 +705,30 @@
  *    Send Get Provider Information command to peer IrLAN layer
  *
  */
-void irlan_get_provider_info( struct irlan_cb *self)
+void irlan_get_provider_info(struct irlan_cb *self)
 {
 	struct sk_buff *skb;
 	__u8 *frame;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
 
-	skb = dev_alloc_skb( 64);
-	if (skb == NULL) {
-		DEBUG( 0, __FUNCTION__
-		       "(), Could not allocate an skb of length %d\n", 64);
+	skb = dev_alloc_skb(64);
+	if (!skb)
 		return;
-	}
 
 	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-	skb_put( skb, 2);
+	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_put(skb, 2);
 	
 	frame = skb->data;
 	
  	frame[0] = CMD_GET_PROVIDER_INFO;
 	frame[1] = 0x00;                 /* Zero parameters */
 	
-	irttp_data_request( self->tsap_ctrl, skb);
+	irttp_data_request(self->client.tsap_ctrl, skb);
 }
 
 /*
@@ -237,26 +737,22 @@
  *    Send an Open Data Command to provider
  *
  */
-void irlan_open_data_channel( struct irlan_cb *self) 
+void irlan_open_data_channel(struct irlan_cb *self) 
 {
 	struct sk_buff *skb;
 	__u8 *frame;
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
 	
-	skb =  dev_alloc_skb( 64);
-	if (skb == NULL) {
-		DEBUG( 0, __FUNCTION__
-		       "(), Could not allocate an skb of length %d\n", 64);
+	skb = dev_alloc_skb(64);
+	if (!skb)
 		return;
-	}
 
-	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-	skb_put( skb, 2);
+	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_put(skb, 2);
 	
 	frame = skb->data;
 	
@@ -264,13 +760,41 @@
  	frame[0] = CMD_OPEN_DATA_CHANNEL;
 	frame[1] = 0x02; /* Two parameters */
 
-	insert_string_param( skb, "MEDIA", "802.3");
-	insert_string_param( skb, "ACCESS_TYPE", "DIRECT");
-	/* insert_string_param( skb, "MODE", "UNRELIABLE"); */
+	irlan_insert_string_param(skb, "MEDIA", "802.3");
+	irlan_insert_string_param(skb, "ACCESS_TYPE", "DIRECT");
+	/* irlan_insert_string_param(skb, "MODE", "UNRELIABLE"); */
 
 /* 	self->use_udata = TRUE; */
 
-	irttp_data_request( self->tsap_ctrl, skb);
+	irttp_data_request(self->client.tsap_ctrl, skb);
+}
+
+void irlan_close_data_channel(struct irlan_cb *self) 
+{
+	struct sk_buff *skb;
+	__u8 *frame;
+	
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	skb = dev_alloc_skb(64);
+	if (!skb)
+		return;
+
+	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_put(skb, 2);
+	
+	frame = skb->data;
+	
+	/* Build frame */
+ 	frame[0] = CMD_CLOSE_DATA_CHAN;
+	frame[1] = 0x01; /* Two parameters */
+
+	irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
+
+	irttp_data_request(self->client.tsap_ctrl, skb);
 }
 
 /*
@@ -280,84 +804,74 @@
  *    address.
  *
  */
-void irlan_open_unicast_addr( struct irlan_cb *self) 
+void irlan_open_unicast_addr(struct irlan_cb *self) 
 {
 	struct sk_buff *skb;
 	__u8 *frame;
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);	
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);	
 	
-	skb = dev_alloc_skb( 128);
-	if (skb == NULL) {
-		DEBUG( 0, __FUNCTION__
-		       "(), Could not allocate an skb of length %d\n", 64);
+	skb = dev_alloc_skb(128);
+	if (!skb)
 		return;
-	}
 
 	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-	skb_put( skb, 2);
+	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_put(skb, 2);
 	
 	frame = skb->data;
 	
  	frame[0] = CMD_FILTER_OPERATION;
 	frame[1] = 0x03;                 /* Three parameters */
- 	insert_byte_param( skb, "DATA_CHAN" , self->dtsap_sel_data);
- 	insert_string_param( skb, "FILTER_TYPE", "DIRECTED");
- 	insert_string_param( skb, "FILTER_MODE", "FILTER"); 
+ 	irlan_insert_byte_param(skb, "DATA_CHAN" , self->dtsap_sel_data);
+ 	irlan_insert_string_param(skb, "FILTER_TYPE", "DIRECTED");
+ 	irlan_insert_string_param(skb, "FILTER_MODE", "FILTER"); 
 	
-	irttp_data_request( self->tsap_ctrl, skb);
+	irttp_data_request(self->client.tsap_ctrl, skb);
 }
 
 /*
  * Function irlan_set_broadcast_filter (self, status)
  *
  *    Make IrLAN provider accept ethernet frames addressed to the broadcast
- *    address. Be careful with the use of this one, sice there may be a lot
+ *    address. Be careful with the use of this one, since there may be a lot
  *    of broadcast traffic out there. We can still function without this
  *    one but then _we_ have to initiate all communication with other
- *    hosts, sice ARP request for this host will not be answered.
+ *    hosts, since ARP request for this host will not be answered.
  */
-void irlan_set_broadcast_filter( struct irlan_cb *self, int status) 
+void irlan_set_broadcast_filter(struct irlan_cb *self, int status) 
 {
 	struct sk_buff *skb;
 	__u8 *frame;
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(2, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
 	
-	/* Should only be used by client */
-	if (!self->client)
+ 	skb = dev_alloc_skb(128);
+	if (!skb)
 		return;
 
- 	skb =  dev_alloc_skb( 128);
-	if (skb == NULL) {
-		DEBUG( 0, __FUNCTION__
-		       "(), Could not allocate an skb of length %d\n", 64);
-		return;
-	}
-
 	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-	skb_put( skb, 2);
+	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_put(skb, 2);
 	
 	frame = skb->data;
 	
  	frame[0] = CMD_FILTER_OPERATION;
 	frame[1] = 0x03;                 /* Three parameters */
- 	insert_byte_param( skb, "DATA_CHAN", self->dtsap_sel_data);
- 	insert_string_param( skb, "FILTER_TYPE", "BROADCAST");
-	if ( status)
-		insert_string_param( skb, "FILTER_MODE", "FILTER"); 
+ 	irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
+ 	irlan_insert_string_param(skb, "FILTER_TYPE", "BROADCAST");
+	if (status)
+		irlan_insert_string_param(skb, "FILTER_MODE", "FILTER"); 
 	else
-		insert_string_param( skb, "FILTER_MODE", "NONE"); 
+		irlan_insert_string_param(skb, "FILTER_MODE", "NONE"); 
 	
-	irttp_data_request( self->tsap_ctrl, skb);
+	irttp_data_request(self->client.tsap_ctrl, skb);
 }
 
 /*
@@ -367,43 +881,36 @@
  *    address. 
  *
  */
-void irlan_set_multicast_filter( struct irlan_cb *self, int status) 
+void irlan_set_multicast_filter(struct irlan_cb *self, int status) 
 {
 	struct sk_buff *skb;
 	__u8 *frame;
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(2, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
 
-	/* Should only be used by client */
-	if (!self->client)
+ 	skb = dev_alloc_skb(128);
+	if (!skb)
 		return;
 	
- 	skb =  dev_alloc_skb( 128);
-	if (skb == NULL) {
-		DEBUG( 0, __FUNCTION__
-		       "(), Could not allocate an skb of length %d\n", 64);
-		return;
-	}
-
 	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-	skb_put( skb, 2);
+	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_put(skb, 2);
 	
 	frame = skb->data;
 	
  	frame[0] = CMD_FILTER_OPERATION;
 	frame[1] = 0x03;                 /* Three parameters */
- 	insert_byte_param( skb, "DATA_CHAN", self->dtsap_sel_data);
- 	insert_string_param( skb, "FILTER_TYPE", "MULTICAST");
-	if ( status)
-		insert_string_param( skb, "FILTER_MODE", "ALL"); 
+ 	irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
+ 	irlan_insert_string_param(skb, "FILTER_TYPE", "MULTICAST");
+	if (status)
+		irlan_insert_string_param(skb, "FILTER_MODE", "ALL"); 
 	else
-		insert_string_param( skb, "FILTER_MODE", "NONE"); 
+		irlan_insert_string_param(skb, "FILTER_MODE", "NONE"); 
 	
-	irttp_data_request( self->tsap_ctrl, skb);
+	irttp_data_request(self->client.tsap_ctrl, skb);
 }
 
 /*
@@ -414,36 +921,33 @@
  *    can construct its packets.
  *
  */
-void irlan_get_unicast_addr( struct irlan_cb *self) 
+void irlan_get_unicast_addr(struct irlan_cb *self) 
 {
 	struct sk_buff *skb;
 	__u8 *frame;
 		
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(2, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
 	
-	skb =  dev_alloc_skb( 128);
-	if (skb == NULL) {
-		DEBUG( 0, "irlan_client_get_unicast_addr: "
-		       "Could not allocate an sk_buff of length %d\n", 64);
+	skb = dev_alloc_skb(128);
+	if (!skb)
 		return;
-	}
 
 	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-	skb_put( skb, 2);
+	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_put(skb, 2);
 	
 	frame = skb->data;
 	
  	frame[0] = CMD_FILTER_OPERATION;
 	frame[1] = 0x03;                 /* Three parameters */
- 	insert_byte_param( skb, "DATA_CHAN", self->dtsap_sel_data);
- 	insert_string_param( skb, "FILTER_TYPE", "DIRECTED");
- 	insert_string_param( skb, "FILTER_OPERATION", "DYNAMIC"); 
+ 	irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
+ 	irlan_insert_string_param(skb, "FILTER_TYPE", "DIRECTED");
+ 	irlan_insert_string_param(skb, "FILTER_OPERATION", "DYNAMIC"); 
 	
-	irttp_data_request( self->tsap_ctrl, skb);
+	irttp_data_request(self->client.tsap_ctrl, skb);
 }
 
 /*
@@ -452,26 +956,23 @@
  *    
  *
  */
-void irlan_get_media_char( struct irlan_cb *self) 
+void irlan_get_media_char(struct irlan_cb *self) 
 {
 	struct sk_buff *skb;
 	__u8 *frame;
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
 	
-	skb = dev_alloc_skb( 64);
-	if (skb == NULL) {
-		DEBUG( 0,"irlan_server_get_media_char: "
-		       "Could not allocate an sk_buff of length %d\n", 64);
+	skb = dev_alloc_skb(64);
+	if (!skb)
 		return;
-	}
 
 	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-	skb_put( skb, 2);
+	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_put(skb, 2);
 	
 	frame = skb->data;
 	
@@ -479,9 +980,9 @@
  	frame[0] = CMD_GET_MEDIA_CHAR;
 	frame[1] = 0x01; /* One parameter */
 	
-	insert_string_param( skb, "MEDIA", "802.3");
+	irlan_insert_string_param(skb, "MEDIA", "802.3");
 	
-	irttp_data_request( self->tsap_ctrl, skb);
+	irttp_data_request(self->client.tsap_ctrl, skb);
 }
 
 /*
@@ -490,47 +991,14 @@
  *    Insert byte parameter into frame
  *
  */
-int insert_byte_param( struct sk_buff *skb, char *param, __u8 value)
+int irlan_insert_byte_param(struct sk_buff *skb, char *param, __u8 value)
 {
-	__u8 *frame;
-	__u8 len_param;
-	__u16 len_value;
-	int n=0;
-	
-	if ( skb == NULL) {
-		DEBUG( 0, "insert_param: Got NULL skb\n");
-		return 0;
-	}
-	
-	len_param = strlen( param);
-	len_value = 1;
-
-	/*
-	 *  Insert at end of sk-buffer
-	 */
-	frame = skb->tail;
-
-	/* Make space for data */
-	if ( skb_tailroom(skb) < (len_param+len_value+3)) {
-		DEBUG( 0, "insert_param: No more space at end of skb\n");
-		return 0;
-	}	
-	skb_put( skb, len_param+len_value+3);
-
-	/* Insert parameter length */
-	frame[n++] = len_param;
-	
-	/* Insert parameter */
-	memcpy( frame+n, param, len_param); 
-	n += len_param;
-	
-	/* Insert value length ( 2 byte little endian format, LSB first) */
-	frame[n++] = len_value & 0xff;
-	frame[n++] = len_value >> 8;
+	return __irlan_insert_param(skb, param, IRLAN_BYTE, value, 0, NULL, 0);
+}
 
-	frame[n++] = value;
-	
-	return len_param+len_value+3;
+int irlan_insert_short_param(struct sk_buff *skb, char *param, __u16 value)
+{
+	return __irlan_insert_param(skb, param, IRLAN_SHORT, 0, value, NULL, 0);
 }
 
 /*
@@ -539,96 +1007,25 @@
  *    Insert string parameter into frame
  *
  */
-int insert_string_param( struct sk_buff *skb, char *param, char *value)
+int irlan_insert_string_param(struct sk_buff *skb, char *param, char *string)
 {
-	__u8 *frame;
-	__u8 len_param;
-	__u16 len_value;
-	int n=0;
-	
-	if ( skb == NULL) {
-		DEBUG( 0, "insert_param: Got NULL skb\n");
-		return 0;
-	}	
-	len_param = strlen( param);
-	len_value = strlen( value);
+	int string_len = strlen(string);
 
-	/*
-	 *  Insert at end of sk-buffer
-	 */
-	frame = skb->tail;
-
-	/* Make space for data */
-	if ( skb_tailroom(skb) < (len_param+len_value+3)) {
-		DEBUG( 0, "insert_param: No more space at end of skb\n");
-		return 0;
-	}	
-	skb_put( skb, len_param+len_value+3);
-
-	/* Insert parameter length */
-	frame[n++] = len_param;
-	
-	/* Insert parameter */
-	memcpy( frame+n, param, len_param); 
-	n += len_param;
-	
-	/* Insert value length ( 2 byte little endian format, LSB first) */
-	frame[n++] = len_value & 0xff;
-	frame[n++] = len_value >> 8;
-
-	memcpy( frame+n, value, len_value); 
-	n+=len_value;
-	
-	return len_param+len_value+3;
+	return __irlan_insert_param(skb, param, IRLAN_ARRAY, 0, 0, string, 
+				    string_len);
 }
 
 /*
- * Function insert_array_param( skb, param, value, len_value)
+ * Function insert_array_param(skb, param, value, len_value)
  *
  *    Insert array parameter into frame
  *
  */
-int insert_array_param( struct sk_buff *skb, char *name, __u8 *value, 
-			__u16 value_len)
+int irlan_insert_array_param(struct sk_buff *skb, char *name, __u8 *array,
+			     __u16 array_len)
 {
-	__u8 *frame;
-	__u8 name_len;
-	int n=0;
-	
-	if ( skb == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Got NULL skb\n");
-		return 0;
-	}	
-	name_len = strlen( name);
-
-	/*
-	 *  Insert at end of sk-buffer
-	 */
-	frame = skb->tail;
-
-	/* Make space for data */
-	if ( skb_tailroom(skb) < (name_len+value_len+3)) {
-		DEBUG( 0, __FUNCTION__ "(), No more space at end of skb\n");
-		return 0;
-	}	
-	skb_put( skb, name_len+value_len+3);
-
-	/* Insert parameter length */
-	frame[n++] = name_len;
-	
-	/* Insert parameter */
-	memcpy( frame+n, name, name_len); 
-	n += name_len;
-	
-	/* Insert value length ( 2 byte little endian format, LSB first) */
-	/* FIXME: should we use htons() here? */
-	frame[n++] = value_len & 0xff;
-	frame[n++] = value_len >> 8;
-
-	memcpy( frame+n, value, value_len); 
-	n+=value_len;
-	
-	return name_len+value_len+3;
+	return __irlan_insert_param(skb, name, IRLAN_ARRAY, 0, 0, array, 
+				    array_len);
 }
 
 /*
@@ -640,130 +1037,121 @@
  *    | Name Length[1] | Param Name[1..255] | Val Length[2] | Value[0..1016]|
  *    -----------------------------------------------------------------------
  */
-int insert_param( struct sk_buff *skb, char *param, int type, char *value_char,
- 		  __u8 value_byte, __u16 value_short) 
+static int __irlan_insert_param(struct sk_buff *skb, char *param, int type, 
+				__u8 value_byte, __u16 value_short, 
+				__u8 *value_array, __u16 value_len)
 {
 	__u8 *frame;
-	__u8 len_param;
-	__u16 len_value;
-	int n;
+	__u8 param_len;
+	int n=0;
 	
-	if ( skb == NULL) {
-		DEBUG( 0, "insert_param: Got NULL skb\n");
+	if (skb == NULL) {
+		DEBUG(2, __FUNCTION__ "(), Got NULL skb\n");
 		return 0;
-	}
-	
-	n = 0;
+	}	
 
-	len_param = strlen( param);
-	switch ( type) {
-	case 1:
-		ASSERT( value_char != NULL, return 0;);
-		len_value = strlen( value_char);
+	param_len = strlen(param);
+	switch (type) {
+	case IRLAN_BYTE:
+		value_len = 1;
 		break;
-	case 2:
-		len_value = 1;
+	case IRLAN_SHORT:
+		value_len = 2;
 		break;
-	case 3:
-		len_value = 2;
+	case IRLAN_ARRAY:
+		ASSERT(value_array != NULL, return 0;);
+		ASSERT(value_len > 0, return 0;);
 		break;
 	default:
-		DEBUG( 0, "Error in insert_param!\n");
+		DEBUG(2, __FUNCTION__ "(), Unknown parameter type!\n");
 		return 0;
 		break;
 	}
 	
-	/*
-	 *  Insert at end of sk-buffer
-	 */
+	/* Insert at end of sk-buffer */
 	frame = skb->tail;
 
 	/* Make space for data */
-	if ( skb_tailroom(skb) < (len_param+len_value+3)) {
-		DEBUG( 0, "insert_param: No more space at end of skb\n");
+	if (skb_tailroom(skb) < (param_len+value_len+3)) {
+		DEBUG(2, __FUNCTION__ "(), No more space at end of skb\n");
 		return 0;
 	}	
-	skb_put( skb, len_param+len_value+3);
-
+	skb_put(skb, param_len+value_len+3);
+	
 	/* Insert parameter length */
-	frame[n++] = len_param;
+	frame[n++] = param_len;
 	
 	/* Insert parameter */
-	memcpy( frame+n, param, len_param); n += len_param;
+	memcpy(frame+n, param, param_len); n += param_len;
 	
-	/* Insert value length ( 2 byte little endian format, LSB first) */
-	frame[n++] = len_value & 0xff;
-	frame[n++] = len_value >> 8;
+	/* Insert value length (2 byte little endian format, LSB first) */
+	*((__u16 *) (frame+n)) = cpu_to_le16(value_len); n += 2;
 
 	/* Insert value */
 	switch (type) {
-	case 1:
-		memcpy( frame+n, value_char, len_value); n+=len_value;
-		break;
-	case 2:
+	case IRLAN_BYTE:
 		frame[n++] = value_byte;
 		break;
-	case 3:
-		frame[n++] = value_short & 0xff;
-		frame[n++] = (value_short >> 8) & 0xff;
+	case IRLAN_SHORT:
+		*((__u16 *) (frame+n)) = cpu_to_le16(value_short); n += 2;
+		break;
+	case IRLAN_ARRAY:
+		memcpy(frame+n, value_array, value_len); n+=value_len;
 		break;
 	default:
 		break;
 	}
-	ASSERT( n == (len_param+len_value+3), return 0;);
+	ASSERT(n == (param_len+value_len+3), return 0;);
 
-	return len_param+len_value+3;
+	return param_len+value_len+3;
 }
 
 /*
  * Function irlan_get_response_param (buf, param, value)
  *
  *    Extracts a single parameter name/value pair from buffer and updates
- *    the buffer pointer to point to the next name/value pair.
- * 
+ *    the buffer pointer to point to the next name/value pair. 
  */
-int irlan_get_response_param( __u8 *buf, char *name, char *value, int *len)
+int irlan_get_param(__u8 *buf, char *name, char *value, __u16 *len)
 {
 	__u8 name_len;
 	__u16 val_len;
 	int n=0;
-
-	DEBUG( 4, "irlan_get_response_param()\n");
 	
-	/* get length of parameter name ( 1 byte) */
+	DEBUG(4, __FUNCTION__ "()\n");
+	
+	/* get length of parameter name (1 byte) */
 	name_len = buf[n++];
 	
 	if (name_len > 254) {
-		DEBUG( 0, __FUNCTION__ "(), name_len > 254\n");
-		return -1;
+		DEBUG(2, __FUNCTION__ "(), name_len > 254\n");
+		return -RSP_INVALID_COMMAND_FORMAT;
 	}
 	
 	/* get parameter name */
-	memcpy( name, buf+n, name_len);
+	memcpy(name, buf+n, name_len);
 	name[ name_len] = '\0';
 	n+=name_len;
 	
 	/*  
-	 *  Get length of parameter value ( 2 bytes in little endian 
+	 *  Get length of parameter value (2 bytes in little endian 
 	 *  format) 
 	 */
-	val_len = buf[n++] & 0xff;
-	val_len |= buf[n++] << 8;
+	val_len = le16_to_cpup(buf+n); n+=2;
 	
 	if (val_len > 1016) {
-		DEBUG( 0, __FUNCTION__ "(), parameter length to long\n");
-		return -1;
+		DEBUG(2, __FUNCTION__ "(), parameter length to long\n");
+		return -RSP_INVALID_COMMAND_FORMAT;
 	}
-	
 	*len = val_len;
 
 	/* get parameter value */
-	memcpy( value, buf+n, val_len);
+	memcpy(value, buf+n, val_len);
 	value[ val_len] = '\0';
 	n+=val_len;
 	
-	DEBUG( 4, "Parameter: %s ", name); 
-	DEBUG( 4, "Value: %s\n", value); 
+	DEBUG(4, "Parameter: %s ", name); 
+	DEBUG(4, "Value: %s\n", value); 
 
 	return n;
 }
@@ -774,37 +1162,55 @@
  *
  *    Give some info to the /proc file system
  */
-static int irlan_proc_read( char *buf, char **start, off_t offset, 
-			    int len, int unused)
+static int irlan_proc_read(char *buf, char **start, off_t offset, int len, 
+			   int unused)
 {
  	struct irlan_cb *self;
-	
-	ASSERT( irlan != NULL, return 0;);
+	unsigned long flags;
+     
+	save_flags(flags);
+	cli();
+
+	ASSERT(irlan != NULL, return 0;);
 	
 	len = 0;
 	
-	len += sprintf( buf+len, "IrLAN\n");
-
-	self = ( struct irlan_cb *) hashbin_get_first( irlan);
-	while ( self != NULL) {
-		ASSERT( self->magic == IRLAN_MAGIC, return len;);
-
-		len += sprintf( buf+len, "ifname: %s, ",
-				self->ifname);
-		/* len += sprintf( buf+len, "state: %s, ", */
-/* 				irlan_client_state[ self->state]); */
-		len += sprintf( buf+len, "saddr: %#08x\n",
-				self->saddr);
-		len += sprintf( buf+len, "daddr: %#08x\n",
-				self->daddr);
-		len += sprintf( buf+len, "tbusy: %s\n", self->dev.tbusy ? 
-				"TRUE" : "FALSE");
+	len += sprintf(buf+len, "IrLAN instances:\n");
+	
+	self = (struct irlan_cb *) hashbin_get_first(irlan);
+	while (self != NULL) {
+		ASSERT(self->magic == IRLAN_MAGIC, return len;);
 		
-		len += sprintf( buf+len, "\n");
+		len += sprintf(buf+len, "ifname: %s,\n",
+			       self->ifname);
+		len += sprintf(buf+len, "client state: %s, ",
+			       irlan_state[ self->client.state]);
+		len += sprintf(buf+len, "provider state: %s,\n",
+			       irlan_state[ self->provider.state]);
+		len += sprintf(buf+len, "saddr: %#08x, ",
+			       self->saddr);
+		len += sprintf(buf+len, "daddr: %#08x\n",
+			       self->daddr);
+		len += sprintf(buf+len, "version: %d.%d,\n",
+			       self->version[1], self->version[0]);
+		len += sprintf(buf+len, "access type: %s\n", 
+			       irlan_access[ self->access_type]);
+		len += sprintf(buf+len, "media: %s\n", 
+			       irlan_media[ self->media]);
+
+		len += sprintf(buf+len, "local filter:\n");
+		len += sprintf(buf+len, "remote filter: ");
+		len += irlan_print_filter(self->client.filter_type, buf+len);
+
+		len += sprintf(buf+len, "tx busy: %s\n", self->dev.tbusy ? 
+			       "TRUE" : "FALSE");
 
-		self = ( struct irlan_cb *) hashbin_get_next( irlan);
-		DEBUG( 4, "self=%p\n", self);
+		len += sprintf(buf+len, "\n");
+
+		self = (struct irlan_cb *) hashbin_get_next(irlan);
  	} 
+	restore_flags(flags);
+
 	return len;
 }
 #endif
@@ -815,41 +1221,41 @@
  *    Print return code of request to peer IrLAN layer.
  *
  */
-void print_ret_code( __u8 code) 
+void print_ret_code(__u8 code) 
 {
-	switch( code) {
+	switch(code) {
 	case 0:
-		printk( KERN_INFO "Success\n");
+		printk(KERN_INFO "Success\n");
 		break;
 	case 1:
-		printk( KERN_WARNING "Insufficient resources\n");
+		printk(KERN_WARNING "Insufficient resources\n");
 		break;
 	case 2:
-		printk( KERN_WARNING "Invalid command format\n");
+		printk(KERN_WARNING "Invalid command format\n");
 		break;
 	case 3:
-		printk( KERN_WARNING "Command not supported\n");
+		printk(KERN_WARNING "Command not supported\n");
 		break;
 	case 4:
-		printk( KERN_WARNING "Parameter not supported\n");
+		printk(KERN_WARNING "Parameter not supported\n");
 		break;
 	case 5:
-		printk( KERN_WARNING "Value not supported\n");
+		printk(KERN_WARNING "Value not supported\n");
 		break;
 	case 6:
-		printk( KERN_WARNING "Not open\n");
+		printk(KERN_WARNING "Not open\n");
 		break;
 	case 7:
-		printk( KERN_WARNING "Authentication required\n");
+		printk(KERN_WARNING "Authentication required\n");
 		break;
 	case 8:
-		printk( KERN_WARNING "Invalid password\n");
+		printk(KERN_WARNING "Invalid password\n");
 		break;
 	case 9:
-		printk( KERN_WARNING "Protocol error\n");
+		printk(KERN_WARNING "Protocol error\n");
 		break;
 	case 255:
-		printk( KERN_WARNING "Asynchronous status\n");
+		printk(KERN_WARNING "Asynchronous status\n");
 		break;
 	}
 }
@@ -859,6 +1265,10 @@
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
 MODULE_DESCRIPTION("The Linux IrDA LAN protocol"); 
 
+MODULE_PARM(eth, "i");
+MODULE_PARM(access, "i");
+MODULE_PARM(timeout, "i");
+
 /*
  * Function init_module (void)
  *
@@ -867,8 +1277,6 @@
  */
 int init_module(void) 
 {
-	DEBUG( 4, __FUNCTION__ "(), irlan.c\n");
-
 	irlan_init();
 
 	return 0;
@@ -882,15 +1290,9 @@
  */
 void cleanup_module(void) 
 {
-	DEBUG( 4, "--> irlan, cleanup_module\n");
-	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
-
 	/* Free some memory */
  	irlan_cleanup();
-
-	DEBUG( 4, "irlan, cleanup_module -->\n");
 }
 
 #endif /* MODULE */
-
 
diff -u --recursive --new-file v2.2.2/linux/net/irda/irlan/irlan_eth.c linux/net/irda/irlan/irlan_eth.c
--- v2.2.2/linux/net/irda/irlan/irlan_eth.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/irlan/irlan_eth.c	Sun Mar  7 15:26:44 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Oct 15 08:37:58 1998
- * Modified at:   Wed Dec  9 11:14:53 1998
+ * Modified at:   Wed Feb  3 19:58:28 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>
@@ -35,158 +35,50 @@
 #include <net/irda/irlan_eth.h>
 
 /*
- * Function irlan_eth_init (dev)
- *
- *    The network device initialization function. Called only once.
- *
- */
-int irlan_eth_init( struct device *dev)
-{
-	struct irlan_cb *self;
-
-	DEBUG( 4, __FUNCTION__"()\n");
-
-	ASSERT( dev != NULL, return -1;);
-       
-	self = (struct irlan_cb *) dev->priv;
-
-/*  	dev->open               = irlan_eth_open;  */
-/* 	dev->stop	        = irlan_eth_close; */
-
-	dev->hard_start_xmit    = irlan_eth_tx; 
-	dev->get_stats	        = irlan_eth_get_stats;
-	dev->set_multicast_list = irlan_eth_set_multicast_list;
-
-	dev->tbusy = 1;
-	
-	ether_setup( dev);
-	
-	dev->tx_queue_len = TTP_MAX_QUEUE;
-
-	return 0;
-}
-
-/*
- * Function irlan_eth_open (dev)
- *
- *    Start the IrLAN ether network device, this function will be called by
- *    "ifconfig irlan0 up".
- *
- */
-int irlan_eth_open( struct device *dev)
-{
-	/* struct irlan_cb *self = (struct irlan_cb *) dev->priv; */
-	
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( dev != NULL, return -1;);
-
-	/* Ready to play! */
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
-
-	/* MOD_INC_USE_COUNT; */
-	
-	return 0;
-}
-
-/*
- * Function irlan_eth_close (dev)
- *
- *    Stop the Client ether network device, his function will be called by
- *    ifconfig down.
- */
-int irlan_eth_close(struct device *dev)
-{
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	ASSERT( dev != NULL, return -1;);
-	
-	/* Stop device */
-	dev->tbusy = 1;
-	dev->start = 0;
-
-	/* MOD_DEC_USE_COUNT; */
-	
-	return 0;
-}
-
-/*
  * Function irlan_eth_tx (skb)
  *
  *    Transmits ethernet frames over IrDA link.
  *
  */
-int irlan_eth_tx( struct sk_buff *skb, struct device *dev)
+int irlan_eth_xmit(struct sk_buff *skb, struct device *dev)
 {
 	struct irlan_cb *self;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 	
 	self = (struct irlan_cb *) dev->priv;
 
-	ASSERT( self != NULL, return 0;);
-	ASSERT( self->magic == IRLAN_MAGIC, return 0;);
+	ASSERT(self != NULL, return 0;);
+	ASSERT(self->magic == IRLAN_MAGIC, return 0;);
 
-	if ( dev->tbusy) {
+	/* Lock transmit buffer */
+	if (irda_lock((void *) &dev->tbusy) == FALSE) {
 		/*
 		 * If we get here, some higher level has decided we are broken.
 		 * There should really be a "kick me" function call instead.
 		 */
 		int tickssofar = jiffies - dev->trans_start; 
-		DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n");
 		
-		if ( tickssofar < 5) 
+		if (tickssofar < 5) 
  			return -EBUSY;
 		
  		dev->tbusy = 0;
  		dev->trans_start = jiffies;
 	}
-	/*
-	 * If some higher layer thinks we've missed an tx-done interrupt
-	 * we are passed NULL. Caution: dev_tint() handles the cli()/sti()
-	 * itself.
-	 */
-	if ( skb == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), skb==NULL\n");
-
-		return 0;
-	}
-	/*
-	 *  Check that we are connected
-         */
-	if ( !self->connected) {
-		DEBUG( 4, __FUNCTION__ "(), Not connected, dropping frame!\n");
-
-		dev_kfree_skb( skb);
-                ++self->stats.tx_dropped;
-		
-                return 0;
-	}
 	
-	/*
-	 * Block a timer-based transmit from overlapping. This could better be
-	 * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
-	 */
-	if ( test_and_set_bit(0, (void*) &dev->tbusy) != 0) {
- 		printk( KERN_WARNING "%s: Transmitter access conflict.\n", 
-			dev->name);
-		return 0;
-	}	
-	DEBUG( 4, "Room left at head: %d\n", skb_headroom(skb));
-	DEBUG( 4, "Room left at tail: %d\n", skb_tailroom(skb));
-	DEBUG( 4, "Required room: %d\n", IRLAN_MAX_HEADER);
+	DEBUG(4, "Room left at head: %d\n", skb_headroom(skb));
+	DEBUG(4, "Room left at tail: %d\n", skb_tailroom(skb));
+	DEBUG(4, "Required room: %d\n", IRLAN_MAX_HEADER);
 	
-	/* Skb headroom large enough to contain IR-headers? */
-	if (( skb_headroom( skb) < IRLAN_MAX_HEADER) || ( skb_shared( skb))) {
+	/* skb headroom large enough to contain IR-headers? */
+	if ((skb_headroom(skb) < IRLAN_MAX_HEADER) || (skb_shared(skb))) {
 		struct sk_buff *new_skb = 
 			skb_realloc_headroom(skb, IRLAN_MAX_HEADER);
-		ASSERT( new_skb != NULL, return 0;);
-		ASSERT( skb_headroom( new_skb) >= IRLAN_MAX_HEADER, return 0;);
+		ASSERT(new_skb != NULL, return 0;);
+		ASSERT(skb_headroom(new_skb) >= IRLAN_MAX_HEADER, return 0;);
 
 		/*  Free original skb, and use the new one */
-		dev_kfree_skb( skb);
+		dev_kfree_skb(skb);
 		skb = new_skb;
 	} 
 
@@ -198,14 +90,14 @@
 	 *  Now queue the packet in the transport layer
 	 *  FIXME: clean up the code below! DB
 	 */
-	if ( self->use_udata) {
-		irttp_udata_request( self->tsap_data, skb);
+	if (self->use_udata) {
+		irttp_udata_request(self->tsap_data, skb);
 		dev->tbusy = 0;
 	
 		return 0;
 	}
 
-	if ( irttp_data_request( self->tsap_data, skb) == -1) {
+	if (irttp_data_request(self->tsap_data, skb) == -1) {
 		/*  
 		 *  IrTTPs tx queue is full, so we just have to drop the
 		 *  frame! You might think that we should just return -1
@@ -215,53 +107,51 @@
 		 *  really confuse do_dev_queue_xmit() in dev.c! I have
 		 *  tried :-) DB
 		 */
-		DEBUG( 4, __FUNCTION__ "(), Dropping frame\n");
-		dev_kfree_skb( skb);
+		dev_kfree_skb(skb);
 		++self->stats.tx_dropped;
 		
 		return 0;
 	}
-	dev->tbusy = 0;
+	dev->tbusy = 0; /* Finished! */
 	
 	return 0;
 }
 
 /*
- * Function irlan_eth_rx (handle, skb)
+ * Function irlan_eth_receive (handle, skb)
  *
  *    This function gets the data that is received on the data channel
  *
  */
-void irlan_eth_rx( void *instance, void *sap, struct sk_buff *skb)
+void irlan_eth_receive(void *instance, void *sap, struct sk_buff *skb)
 {
 	struct irlan_cb *self;
 
-	self = ( struct irlan_cb *) instance;
+	self = (struct irlan_cb *) instance;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
 
 	if (skb == NULL) {
 		++self->stats.rx_dropped; 
 		return;
 	}
-	IS_SKB( skb, return;);
-	ASSERT( skb->len > 1, return;);
+	ASSERT(skb->len > 1, return;);
 		
-	DEBUG( 4, "Got some ether data: length=%d\n", (int)skb->len); 
-	
 	/* 
 	 * Adopt this frame! Important to set all these fields since they 
 	 * might have been previously set by the low level IrDA network
 	 * device driver 
 	 */
 	skb->dev = &self->dev;
-	skb->protocol=eth_type_trans( skb, skb->dev); /* Remove eth header */
+	skb->protocol=eth_type_trans(skb, skb->dev); /* Remove eth header */
 	
-	netif_rx( skb);   /* Eat it! */
+	netif_rx(skb);   /* Eat it! */
 	
 	self->stats.rx_packets++;
 	self->stats.rx_bytes += skb->len; 
+
+/* 	net_bh(); */
 }
 
 /*
@@ -270,25 +160,25 @@
  *    Do flow control between IP/Ethernet and IrLAN/IrTTP. This is done by 
  *    controlling the dev->tbusy variable.
  */
-void irlan_eth_flow_indication( void *instance, void *sap, LOCAL_FLOW flow)
+void irlan_eth_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
 {
 	struct irlan_cb *self;
 	struct device *dev;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
 	self = (struct irlan_cb *) instance;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
 	
 	dev = &self->dev;
 
-	ASSERT( dev != NULL, return;);
+	ASSERT(dev != NULL, return;);
 	
-	switch ( flow) {
+	switch (flow) {
 	case FLOW_STOP:
-		DEBUG( 4, "IrLAN, stopping Ethernet layer\n");
+		DEBUG(4, "IrLAN, stopping Ethernet layer\n");
 
 		dev->tbusy = 1;
 		break;
@@ -296,7 +186,7 @@
 		/* 
 		 *  Tell upper layers that its time to transmit frames again
 		 */
-		DEBUG( 4, "IrLAN, starting Ethernet layer\n");
+		DEBUG(4, "IrLAN, starting Ethernet layer\n");
 
 		dev->tbusy = 0;
 
@@ -304,10 +194,10 @@
 		 *  Ready to receive more frames, so schedule the network
 		 *  layer
 		 */
-		mark_bh( NET_BH);		
+		mark_bh(NET_BH);		
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown flow command!\n");
+		DEBUG(0, __FUNCTION__ "(), Unknown flow command!\n");
 	}
 }
 
@@ -317,13 +207,13 @@
  *    If we don't want to use ARP. Currently not used!!
  *
  */
-void irlan_eth_rebuild_header( void *buff, struct device *dev, 
-			       unsigned long dest, struct sk_buff *skb)
+void irlan_eth_rebuild_header(void *buff, struct device *dev, 
+			      unsigned long dest, struct sk_buff *skb)
 {
-	struct ethhdr *eth = ( struct ethhdr *) buff;
+	struct ethhdr *eth = (struct ethhdr *) buff;
 
-	memcpy( eth->h_source, dev->dev_addr, dev->addr_len);
-	memcpy( eth->h_dest, dev->dev_addr, dev->addr_len);
+	memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
+	memcpy(eth->h_dest, dev->dev_addr, dev->addr_len);
 
 	/* return 0; */
 }
@@ -335,47 +225,47 @@
  *
  */
 #define HW_MAX_ADDRS 4 /* Must query to get it! */
-void irlan_eth_set_multicast_list( struct device *dev) 
+void irlan_eth_set_multicast_list(struct device *dev) 
 {
  	struct irlan_cb *self;
 
  	self = dev->priv; 
 
-	DEBUG( 4, __FUNCTION__ "()\n");
-
- 	ASSERT( self != NULL, return;); 
- 	ASSERT( self->magic == IRLAN_MAGIC, return;);
+	DEBUG(0, __FUNCTION__ "()\n");
+	return;
+ 	ASSERT(self != NULL, return;); 
+ 	ASSERT(self->magic == IRLAN_MAGIC, return;);
 
 	if (dev->flags&IFF_PROMISC) {
 		/* Enable promiscuous mode */
-		DEBUG( 0, "Promiscous mode not implemented\n");
+		DEBUG(0, "Promiscous mode not implemented\n");
 		/* outw(MULTICAST|PROMISC, ioaddr); */
 	}
-	else if ((dev->flags&IFF_ALLMULTI) || dev->mc_count > HW_MAX_ADDRS) {
+	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");
+		DEBUG(4, __FUNCTION__ "(), Setting multicast filter\n");
 		/* hardware_set_filter(NULL); */
 
-		irlan_set_multicast_filter( self, TRUE);
+		irlan_set_multicast_filter(self, TRUE);
 	}
 	else if (dev->mc_count) {
-		DEBUG( 4, __FUNCTION__ "(), Setting multicast filter\n");
+		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);
+		irlan_set_multicast_filter(self, TRUE);
 	}
 	else {
-		DEBUG( 4, __FUNCTION__ "(), Clearing multicast filter\n");
-		irlan_set_multicast_filter( self, FALSE);
+		DEBUG(4, __FUNCTION__ "(), Clearing multicast filter\n");
+		irlan_set_multicast_filter(self, FALSE);
 	}
 
-	if ( dev->flags & IFF_BROADCAST) {
-		DEBUG( 4, __FUNCTION__ "(), Setting broadcast filter\n");
-		irlan_set_broadcast_filter( self, TRUE);
+	if (dev->flags & IFF_BROADCAST) {
+		DEBUG(4, __FUNCTION__ "(), Setting broadcast filter\n");
+		irlan_set_broadcast_filter(self, TRUE);
 	} else {
-		DEBUG( 4, __FUNCTION__ "(), Clearing broadcast filter\n");
-		irlan_set_broadcast_filter( self, FALSE);
+		DEBUG(4, __FUNCTION__ "(), Clearing broadcast filter\n");
+		irlan_set_broadcast_filter(self, FALSE);
 	}
 }
 
@@ -385,12 +275,12 @@
  *    Get the current statistics for this device
  *
  */
-struct enet_statistics *irlan_eth_get_stats( struct device *dev) 
+struct enet_statistics *irlan_eth_get_stats(struct device *dev) 
 {
 	struct irlan_cb *self = (struct irlan_cb *) dev->priv;
 
-	ASSERT( self != NULL, return NULL;);
-	ASSERT( self->magic == IRLAN_MAGIC, return NULL;);
+	ASSERT(self != NULL, return NULL;);
+	ASSERT(self->magic == IRLAN_MAGIC, return NULL;);
 
 	return &self->stats;
 }
diff -u --recursive --new-file v2.2.2/linux/net/irda/irlan/irlan_event.c linux/net/irda/irlan/irlan_event.c
--- v2.2.2/linux/net/irda/irlan/irlan_event.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/irlan/irlan_event.c	Sun Mar  7 15:26:44 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Oct 20 09:10:16 1998
- * Modified at:   Sat Dec  5 14:52:22 1998
+ * Modified at:   Wed Feb  3 21:42:27 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -38,11 +38,23 @@
 	"IRLAN_SYNC",
 };
 
-void irlan_next_state( struct irlan_cb *self, 
-		       IRLAN_STATE state) 
+void irlan_next_client_state( struct irlan_cb *self, IRLAN_STATE state) 
 {
+	DEBUG(2, __FUNCTION__"(), %s\n", irlan_state[state]);
+
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IRLAN_MAGIC, return;);
 
-	self->state = state;
+	self->client.state = state;
 }
+
+void irlan_next_provider_state( struct irlan_cb *self, IRLAN_STATE state) 
+{
+	DEBUG(2, __FUNCTION__"(), %s\n", irlan_state[state]);
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRLAN_MAGIC, return;);
+
+	self->provider.state = state;
+}
+
diff -u --recursive --new-file v2.2.2/linux/net/irda/irlan/irlan_filter.c linux/net/irda/irlan/irlan_filter.c
--- v2.2.2/linux/net/irda/irlan/irlan_filter.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irlan/irlan_filter.c	Sun Mar  7 15:26:44 1999
@@ -0,0 +1,235 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_filter.c
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Fri Jan 29 11:16:38 1999
+ * Modified at:   Sun Feb  7 23:48:07 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.
+ *     
+ ********************************************************************/
+
+#include <linux/skbuff.h>
+
+#include <net/irda/irlan_common.h>
+
+/*
+ * Function handle_filter_request (self, skb)
+ *
+ *    Handle filter request from client peer device
+ *
+ */
+void handle_filter_request(struct irlan_cb *self, struct sk_buff *skb)
+{
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	if ((self->provider.filter_type == IRLAN_DIRECTED) && 
+	    (self->provider.filter_operation == DYNAMIC))
+	{
+		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;
+		self->provider.mac_address[3] = 0x00;
+		
+		/* Use arbitration value to generate MAC address */
+		if (self->access_type == ACCESS_PEER) {
+			self->provider.mac_address[4] = 
+				self->provider.send_arb_val & 0xff;
+			self->provider.mac_address[5] = 
+				(self->provider.send_arb_val >> 8) & 0xff;;
+		} else {
+			/* Just generate something for now */
+			self->provider.mac_address[4] = jiffies & 0xff;
+			self->provider.mac_address[5] = (jiffies >> 8) & 0xff;
+		}
+
+		skb->data[0] = 0x00; /* Success */
+		skb->data[1] = 0x03;
+		irlan_insert_string_param(skb, "FILTER_MODE", "NONE");
+		irlan_insert_short_param(skb, "MAX_ENTRY", 0x0001);
+		irlan_insert_array_param(skb, "FILTER_ENTRY", self->provider.mac_address, 6);
+		return;
+	}
+	
+	if ((self->provider.filter_type == IRLAN_DIRECTED) && 
+	    (self->provider.filter_mode == FILTER))
+	{
+		DEBUG(0, "Directed filter on\n");
+		skb->data[0] = 0x00; /* Success */
+		skb->data[1] = 0x00;
+		return;
+	}
+	if ((self->provider.filter_type == IRLAN_DIRECTED) && 
+	    (self->provider.filter_mode == NONE))
+	{
+		DEBUG(0, "Directed filter off\n");
+		skb->data[0] = 0x00; /* Success */
+		skb->data[1] = 0x00;
+		return;
+	}
+
+	if ((self->provider.filter_type == IRLAN_BROADCAST) && 
+	    (self->provider.filter_mode == FILTER))
+	{
+		DEBUG(0, "Broadcast filter on\n");
+		skb->data[0] = 0x00; /* Success */
+		skb->data[1] = 0x00;
+		return;
+	}
+	if ((self->provider.filter_type == IRLAN_BROADCAST) && 
+	    (self->provider.filter_mode == NONE))
+	{
+		DEBUG(0, "Broadcast filter off\n");
+		skb->data[0] = 0x00; /* Success */
+		skb->data[1] = 0x00;
+		return;
+	}
+	if ((self->provider.filter_type == IRLAN_MULTICAST) && 
+	    (self->provider.filter_mode == FILTER))
+	{
+		DEBUG(0, "Multicast filter on\n");
+		skb->data[0] = 0x00; /* Success */
+		skb->data[1] = 0x00;
+		return;
+	}
+	if ((self->provider.filter_type == IRLAN_MULTICAST) && 
+	    (self->provider.filter_mode == NONE))
+	{
+		DEBUG(0, "Multicast filter off\n");
+		skb->data[0] = 0x00; /* Success */
+		skb->data[1] = 0x00;
+		return;
+	}
+	if ((self->provider.filter_type == IRLAN_MULTICAST) && 
+	    (self->provider.filter_operation == GET))
+	{
+		DEBUG(0, "Multicast filter get\n");
+		skb->data[0] = 0x00; /* Success? */
+		skb->data[1] = 0x02;
+		irlan_insert_string_param(skb, "FILTER_MODE", "NONE");
+		irlan_insert_short_param(skb, "MAX_ENTRY", 16);
+		return;
+	}
+	skb->data[0] = 0x00; /* Command not supported */
+	skb->data[1] = 0x00;
+
+	DEBUG(0, "Not implemented!\n");
+}
+
+/*
+ * Function check_request_param (self, param, value)
+ *
+ *    Check parameters in request from peer device
+ *
+ */
+static void irlan_check_command_param(struct irlan_cb *self, char *param, 
+				      char *value)
+{
+	__u8 *bytes;
+
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	bytes = value;
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	DEBUG(4, "%s, %s\n", param, value);
+
+	/*
+	 *  This is experimental!! DB.
+	 */
+	 if (strcmp(param, "MODE") == 0) {
+		DEBUG(0, __FUNCTION__ "()\n");
+		self->use_udata = TRUE;
+		return;
+	}
+
+	/*
+	 *  FILTER_TYPE
+	 */
+	if (strcmp(param, "FILTER_TYPE") == 0) {
+		if (strcmp(value, "DIRECTED") == 0) {
+			self->provider.filter_type = IRLAN_DIRECTED;
+			return;
+		}
+		if (strcmp(value, "MULTICAST") == 0) {
+			self->provider.filter_type = IRLAN_MULTICAST;
+			return;
+		}
+		if (strcmp(value, "BROADCAST") == 0) {
+			self->provider.filter_type = IRLAN_BROADCAST;
+			return;
+		}
+	}
+	/*
+	 *  FILTER_MODE
+	 */
+	if (strcmp(param, "FILTER_MODE") == 0) {
+		if (strcmp(value, "ALL") == 0) {
+			self->provider.filter_mode = ALL;
+			return;
+		}
+		if (strcmp(value, "FILTER") == 0) {
+			self->provider.filter_mode = FILTER;
+			return;
+		}
+		if (strcmp(value, "NONE") == 0) {
+			self->provider.filter_mode = FILTER;
+			return;
+		}
+	}
+	/*
+	 *  FILTER_OPERATION
+	 */
+	if (strcmp(param, "FILTER_OPERATION") == 0) {
+		if (strcmp(value, "DYNAMIC") == 0) {
+			self->provider.filter_operation = DYNAMIC;
+			return;
+		}
+		if (strcmp(value, "GET") == 0) {
+			self->provider.filter_operation = GET;
+			return;
+		}
+	}
+}
+
+int irlan_print_filter(int filter_type, char *buf)
+{
+	int len = 0;
+
+	if (filter_type & IRLAN_DIRECTED)
+		len += sprintf(buf+len, "%s", "DIRECTED ");
+	if (filter_type & IRLAN_FUNCTIONAL)
+		len += sprintf(buf+len, "%s", "FUNCTIONAL ");
+	if (filter_type & IRLAN_GROUP)
+		len += sprintf(buf+len, "%s", "GROUP ");
+	if (filter_type & IRLAN_MAC_FRAME)
+		len += sprintf(buf+len, "%s", "MAC_FRAME ");
+	if (filter_type & IRLAN_MULTICAST)
+		len += sprintf(buf+len, "%s", "MULTICAST ");
+	if (filter_type & IRLAN_BROADCAST)
+		len += sprintf(buf+len, "%s", "BROADCAST ");
+	if (filter_type & IRLAN_IPX_SOCKET)
+		len += sprintf(buf+len, "%s", "IPX_SOCKET");
+
+	len += sprintf(buf+len, "\n");
+
+	return len;
+}
diff -u --recursive --new-file v2.2.2/linux/net/irda/irlan/irlan_provider.c linux/net/irda/irlan/irlan_provider.c
--- v2.2.2/linux/net/irda/irlan/irlan_provider.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irlan/irlan_provider.c	Sun Mar  7 15:26:44 1999
@@ -0,0 +1,431 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_provider.c
+ * Version:       0.9
+ * Description:   IrDA LAN Access Protocol Implementation
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Aug 31 20:14:37 1997
+ * Modified at:   Thu Feb  4 16:08:33 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>
+ *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
+ * 
+ *     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.
+ *
+ *     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.
+ *
+ ********************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/byteorder.h>
+
+#include <net/irda/irda.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/timer.h>
+
+#include <net/irda/irlan_common.h>
+#include <net/irda/irlan_eth.h>
+#include <net/irda/irlan_event.h>
+#include <net/irda/irlan_provider.h>
+#include <net/irda/irlan_filter.h>
+#include <net/irda/irlan_client.h>
+
+/*
+ * Function irlan_provider_control_data_indication (handle, skb)
+ *
+ *    This function gets the data that is received on the control channel
+ *
+ */
+void irlan_provider_data_indication(void *instance, void *sap, 
+				    struct sk_buff *skb) 
+{
+	struct irlan_cb *self;
+	__u8 code;
+	
+	DEBUG(4, __FUNCTION__ "()\n");
+	
+	self = (struct irlan_cb *) instance;
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	ASSERT(skb != NULL, return;);
+
+	code = skb->data[0];
+	switch(code) {
+	case CMD_GET_PROVIDER_INFO:
+		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");
+		irlan_do_provider_event(self, IRLAN_GET_MEDIA_CMD, skb); 
+		break;
+	case CMD_OPEN_DATA_CHANNEL:
+		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");
+		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");
+		break;
+	case CMD_CLOSE_DATA_CHAN:
+		DEBUG(2, "Got CLOSE_DATA_CHAN command!\n");
+		DEBUG(2, __FUNCTION__"(), NOT IMPLEMENTED\n");
+		break;
+	default:
+		DEBUG(2, __FUNCTION__ "(), Unknown command!\n");
+		break;
+	}
+}
+
+/*
+ * Function irlan_provider_connect_indication (handle, skb, priv)
+ *
+ *    Got connection from peer IrLAN layer
+ *
+ */
+void irlan_provider_connect_indication(void *instance, void *sap, 
+				       struct qos_info *qos, int max_sdu_size,
+				       struct sk_buff *skb)
+{
+	struct irlan_cb *self, *entry, *new;
+	struct tsap_cb *tsap;
+
+	DEBUG(2, __FUNCTION__ "()\n");
+	
+	self = (struct irlan_cb *) instance;
+	tsap = (struct tsap_cb *) sap;
+	
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+	
+	ASSERT(tsap == self->provider.tsap_ctrl,return;);
+	ASSERT(self->provider.state == IRLAN_IDLE, return;);
+
+	/* Check if this provider is unused */
+	if (self->daddr == DEV_ADDR_ANY) {
+		/*
+		 * Rehash instance, now we have a client (daddr) to serve.
+		 */
+		entry = hashbin_remove(irlan, self->daddr, NULL);
+		ASSERT( entry == self, return;);
+		
+		self->daddr = irttp_get_daddr(tsap);
+		DEBUG(2, __FUNCTION__ "(), daddr=%08x\n", self->daddr);
+		hashbin_insert(irlan, (QUEUE*) self, self->daddr, NULL);
+	} else {
+		/*
+		 * If we already have the daddr set, this means that the
+		 * client must already have started (peer mode). We must
+		 * make sure that this connection attempt is from the same
+		 * device as the client is dealing with!  
+		 */
+		ASSERT(self->daddr == irttp_get_daddr(tsap), return;);
+	}
+	
+	/* Update saddr, since client may have moved to a new link */
+	self->saddr = irttp_get_saddr(tsap);
+	DEBUG(2, __FUNCTION__ "(), saddr=%08x\n", self->saddr);
+	
+	/* Check if network device has been registered */
+	if (!self->netdev_registered)
+		irlan_register_netdev(self);
+	
+	irlan_do_provider_event(self, IRLAN_CONNECT_INDICATION, NULL);
+
+	/*  
+	 * If we are in peer mode, the client may not have got the discovery
+	 * indication it needs to make progress. If the client is still in 
+	 * IDLE state, we must kick it to 
+	 */
+	if ((self->access_type == ACCESS_PEER) && 
+	    (self->client.state == IRLAN_IDLE))
+		irlan_client_wakeup(self, self->saddr, self->daddr);
+
+	/* 
+	 * This provider is now in use, so start a new provider instance to
+         * serve other clients. This will also change the LM-IAS entry so that
+	 * other clients don't try to connect to us, now that we are busy.
+	 */
+	new = irlan_open(DEV_ADDR_ANY, DEV_ADDR_ANY, FALSE);
+	self->client.start_new_provider = FALSE;
+}
+
+/*
+ * Function irlan_provider_connect_response (handle)
+ *
+ *    Accept incomming connection
+ *
+ */
+void irlan_provider_connect_response(struct irlan_cb *self,
+				     struct tsap_cb *tsap)
+{
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	/* Just accept */
+	irttp_connect_response(tsap, IRLAN_MTU, NULL);
+
+	/* Check if network device has been registered */
+	if (!self->netdev_registered)
+		irlan_register_netdev(self);
+		
+}
+
+void irlan_provider_disconnect_indication(void *instance, void *sap, 
+					  LM_REASON reason, 
+					  struct sk_buff *userdata) 
+{
+	struct irlan_cb *self;
+	struct tsap_cb *tsap;
+
+	DEBUG(4, __FUNCTION__ "(), reason=%d\n", reason);
+	
+	self = (struct irlan_cb *) instance;
+	tsap = (struct tsap_cb *) sap;
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);	
+	ASSERT(tsap != NULL, return;);
+	ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
+	
+	ASSERT(tsap == self->provider.tsap_ctrl, return;);
+	
+	irlan_do_provider_event(self, IRLAN_LMP_DISCONNECT, NULL);
+}
+
+/*
+ * Function irlan_parse_open_data_cmd (self, skb)
+ *
+ *    
+ *
+ */
+int irlan_parse_open_data_cmd(struct irlan_cb *self, struct sk_buff *skb)
+{
+	int ret;
+	
+	ret = irlan_provider_extract_params(self, CMD_OPEN_DATA_CHANNEL, skb);
+
+	return ret;
+}
+
+/*
+ * Function extract_params (skb)
+ *
+ *    Extract all parameters from received buffer, then feed them to 
+ *    check_params for parsing
+ *
+ */
+int irlan_provider_extract_params(struct irlan_cb *self, int cmd,
+				  struct sk_buff *skb) 
+{
+	__u8 *frame;
+	__u8 *ptr;
+	int count;
+	__u8 name_len;
+	__u16 val_len;
+	int i;
+	char *name;
+        char *value;
+	int ret = RSP_SUCCESS;
+	
+	ASSERT(skb != NULL, return -RSP_PROTOCOL_ERROR;);
+	
+	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;);
+	
+	if (!skb)
+		return -RSP_PROTOCOL_ERROR;
+
+	frame = skb->data;
+
+	name = kmalloc(255, GFP_ATOMIC);
+	if (!name)
+		return -RSP_INSUFFICIENT_RESOURCES;
+	value = kmalloc(1016, GFP_ATOMIC);
+	if (!value) {
+		kfree(name);
+		return -RSP_INSUFFICIENT_RESOURCES;
+	}
+
+	/* How many parameters? */
+	count = frame[1];
+
+	DEBUG(4, "Got %d parameters\n", count);
+	
+	ptr = frame+2;
+	
+	/* For all parameters */
+ 	for (i=0; i<count;i++) {
+		ret = irlan_get_param(ptr, name, value, &val_len);
+		if (ret < 0) {
+			DEBUG(2, __FUNCTION__ "(), IrLAN, Error!\n");
+			break;
+		}
+		ptr+=ret;
+		ret = RSP_SUCCESS;
+		irlan_check_command_param(self, name, value);
+	}
+	/* Cleanup */
+	kfree(name);
+	kfree(value);
+
+	return ret;
+}
+
+/*
+ * Function irlan_provider_send_reply (self, info)
+ *
+ *    Send reply to query to peer IrLAN layer
+ *
+ */
+void irlan_provider_send_reply(struct irlan_cb *self, int command, 
+			       int ret_code)
+{
+	struct sk_buff *skb;
+
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	skb = dev_alloc_skb(128);
+	if (!skb)
+		return;
+
+	/* Reserve space for TTP, LMP, and LAP header */
+	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_put(skb, 2);
+       
+	switch (command) {
+	case CMD_GET_PROVIDER_INFO:
+		skb->data[0] = 0x00; /* Success */
+		skb->data[1] = 0x02; /* 2 parameters */
+		switch (self->media) {
+		case MEDIA_802_3:
+			irlan_insert_string_param(skb, "MEDIA", "802.3");
+			break;
+		case MEDIA_802_5:
+			irlan_insert_string_param(skb, "MEDIA", "802.5");
+			break;
+		default:
+			DEBUG(2, __FUNCTION__ "(), unknown media type!\n");
+			break;
+		}
+		irlan_insert_short_param(skb, "IRLAN_VER", 0x0101);
+		break;
+	case CMD_GET_MEDIA_CHAR:
+		skb->data[0] = 0x00; /* Success */
+		skb->data[1] = 0x05; /* 5 parameters */
+		irlan_insert_string_param(skb, "FILTER_TYPE", "DIRECTED");
+		irlan_insert_string_param(skb, "FILTER_TYPE", "BROADCAST");
+		irlan_insert_string_param(skb, "FILTER_TYPE", "MULTICAST");
+
+		switch(self->access_type) {
+		case ACCESS_DIRECT:
+			irlan_insert_string_param(skb, "ACCESS_TYPE", "DIRECT");
+			break;
+		case ACCESS_PEER:
+			irlan_insert_string_param(skb, "ACCESS_TYPE", "PEER");
+			break;
+		case ACCESS_HOSTED:
+			irlan_insert_string_param(skb, "ACCESS_TYPE", "HOSTED");
+			break;
+		default:
+			DEBUG(2, __FUNCTION__ "(), Unknown access type\n");
+			break;
+		}
+		irlan_insert_short_param(skb, "MAX_FRAME", 0x05ee);
+		break;
+	case CMD_OPEN_DATA_CHANNEL:
+		skb->data[0] = 0x00; /* Success */
+		if (self->provider.send_arb_val) {
+			skb->data[1] = 0x03; /* 3 parameters */
+			irlan_insert_short_param(skb, "CON_ARB", 
+						 self->provider.send_arb_val);
+		} else
+			skb->data[1] = 0x02; /* 2 parameters */
+		irlan_insert_byte_param(skb, "DATA_CHAN", self->stsap_sel_data);
+		irlan_insert_array_param(skb, "RECONNECT_KEY", "LINUX RULES!",
+					 12);
+		break;
+	case CMD_FILTER_OPERATION:
+		handle_filter_request(self, skb);
+		break;
+	default:
+		DEBUG(2, __FUNCTION__ "(), Unknown command!\n");
+		break;
+	}
+
+	irttp_data_request(self->provider.tsap_ctrl, skb);
+}
+
+/*
+ * Function irlan_provider_register(void)
+ *
+ *    Register provider support so we can accept incomming connections.
+ * 
+ */
+void irlan_provider_open_ctrl_tsap(struct irlan_cb *self)
+{
+	struct notify_t notify;
+	struct tsap_cb *tsap;
+	
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	/* Check if already open */
+	if (self->provider.tsap_ctrl)
+		return;
+	
+	/*
+	 *  First register well known control TSAP
+	 */
+	irda_notify_init(&notify);
+	notify.data_indication       = irlan_provider_data_indication;
+	notify.connect_indication    = irlan_provider_connect_indication;
+	notify.disconnect_indication = irlan_provider_disconnect_indication;
+	notify.instance = self;
+	strncpy(notify.name, "IrLAN ctrl (p)", 16);
+
+	tsap = irttp_open_tsap(LSAP_ANY, 1, &notify);
+	if (!tsap) {
+		DEBUG(2, __FUNCTION__ "(), Got no tsap!\n");
+		return;
+	}
+	self->provider.tsap_ctrl = tsap;
+
+	/* Register with LM-IAS */
+	irlan_ias_register(self,tsap->stsap_sel);
+}
+
diff -u --recursive --new-file v2.2.2/linux/net/irda/irlan/irlan_provider_event.c linux/net/irda/irlan/irlan_provider_event.c
--- v2.2.2/linux/net/irda/irlan/irlan_provider_event.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irlan/irlan_provider_event.c	Sun Mar  7 15:26:44 1999
@@ -0,0 +1,240 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_provider_event.c
+ * Version:       0.9
+ * Description:   IrLAN provider state machine)
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Aug 31 20:14:37 1997
+ * Modified at:   Wed Feb  3 21:43:06 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     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.
+ *
+ *     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.
+ *
+ ********************************************************************/
+
+#include <net/irda/irda.h>
+#include <net/irda/iriap.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/irttp.h>
+
+#include <net/irda/irlan_provider.h>
+#include <net/irda/irlan_event.h>
+
+static int irlan_provider_state_idle(struct irlan_cb *self, IRLAN_EVENT event, 
+				     struct sk_buff *skb);
+static int irlan_provider_state_info(struct irlan_cb *self, IRLAN_EVENT event, 
+				     struct sk_buff *skb);
+static int irlan_provider_state_open(struct irlan_cb *self, IRLAN_EVENT event, 
+				     struct sk_buff *skb);
+static int irlan_provider_state_data(struct irlan_cb *self, IRLAN_EVENT event, 
+				     struct sk_buff *skb);
+
+static int (*state[])(struct irlan_cb *self, IRLAN_EVENT event, 
+		      struct sk_buff *skb) = 
+{ 
+	irlan_provider_state_idle,
+	NULL, /* Query */
+	NULL, /* Info */
+	irlan_provider_state_info,
+	NULL, /* Media */
+	irlan_provider_state_open,
+	NULL, /* Wait */
+	NULL, /* Arb */
+	irlan_provider_state_data,
+	NULL, /* Close */
+	NULL, /* Sync */
+};
+
+void irlan_do_provider_event(struct irlan_cb *self, IRLAN_EVENT event, 
+			     struct sk_buff *skb) 
+{
+	ASSERT(*state[ self->provider.state] != NULL, return;);
+
+	(*state[self->provider.state]) (self, event, skb);
+}
+
+/*
+ * Function irlan_provider_state_idle (event, skb, info)
+ *
+ *    IDLE, We are waiting for an indication that there is a provider
+ *    available.
+ */
+static int irlan_provider_state_idle(struct irlan_cb *self, IRLAN_EVENT event,
+				     struct sk_buff *skb)
+{
+	DEBUG(4, __FUNCTION__ "()\n");
+	
+	ASSERT(self != NULL, return -1;);
+	
+	switch(event) {
+	case IRLAN_CONNECT_INDICATION:
+	     irlan_provider_connect_response( self, self->provider.tsap_ctrl);
+	     irlan_next_provider_state( self, IRLAN_INFO);
+	     break;
+	default:
+		DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event);
+		break;
+	}
+	if (skb)
+		dev_kfree_skb(skb);
+
+	return 0;
+}
+
+/*
+ * Function irlan_provider_state_info (self, event, skb, info)
+ *
+ *    INFO, We have issued a GetInfo command and is awaiting a reply.
+ */
+static int irlan_provider_state_info(struct irlan_cb *self, IRLAN_EVENT event, 
+				     struct sk_buff *skb) 
+{
+	int ret;
+
+	DEBUG(4, __FUNCTION__ "()\n");
+	
+	ASSERT(self != NULL, return -1;);
+
+	switch(event) {
+	case IRLAN_GET_INFO_CMD:
+		/* Be sure to use 802.3 in case of peer mode */
+		if (self->access_type == ACCESS_PEER)
+			self->media = MEDIA_802_3;
+
+		irlan_provider_send_reply(self, CMD_GET_PROVIDER_INFO, 
+					  RSP_SUCCESS);
+		/* Keep state */
+		break;
+	case IRLAN_GET_MEDIA_CMD: 
+		irlan_provider_send_reply(self, CMD_GET_MEDIA_CHAR, 
+					  RSP_SUCCESS);
+		/* Keep state */
+		break;		
+	case IRLAN_OPEN_DATA_CMD:
+		ret = irlan_parse_open_data_cmd(self, skb);
+		if (self->access_type == ACCESS_PEER) {
+			/* FIXME: make use of random functions! */
+			self->provider.send_arb_val = (jiffies & 0xffff);
+		}
+		irlan_provider_send_reply(self, CMD_OPEN_DATA_CHANNEL, ret);
+
+		if (ret == RSP_SUCCESS) {
+			irlan_next_provider_state(self, IRLAN_OPEN);
+
+			/* Signal client that we are now open */
+			irlan_do_client_event(self, IRLAN_PROVIDER_SIGNAL, NULL);
+		}
+		break;
+	case IRLAN_LMP_DISCONNECT:  /* FALLTHROUGH */
+	case IRLAN_LAP_DISCONNECT:
+		irlan_next_provider_state(self, IRLAN_IDLE);
+		break;
+	default:
+		DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
+		break;
+	}
+	if (skb)
+		dev_kfree_skb(skb);
+	
+	return 0;
+}
+
+/*
+ * Function irlan_provider_state_open (self, event, skb, info)
+ *
+ *    OPEN, The client has issued a OpenData command and is awaiting a
+ *    reply
+ *
+ */
+static int irlan_provider_state_open(struct irlan_cb *self, IRLAN_EVENT event, 
+				     struct sk_buff *skb)
+{
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return -1;);
+
+	switch(event) {
+	case IRLAN_FILTER_CONFIG_CMD:
+		irlan_provider_extract_params(self, CMD_FILTER_OPERATION, skb);
+		irlan_provider_send_reply(self, CMD_FILTER_OPERATION, 
+					  RSP_SUCCESS);
+		/* Keep state */
+		break;
+	case IRLAN_DATA_CONNECT_INDICATION: 
+		irlan_next_provider_state(self, IRLAN_DATA);
+		irlan_provider_connect_response(self, self->tsap_data);
+		break;
+	case IRLAN_LMP_DISCONNECT:  /* FALLTHROUGH */
+	case IRLAN_LAP_DISCONNECT:
+		irlan_next_provider_state(self, IRLAN_IDLE);
+		break;
+	default:
+		DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+		break;
+	}
+	if (skb)
+		dev_kfree_skb(skb);
+
+	return 0;
+}
+
+/*
+ * Function irlan_provider_state_data (self, event, skb, info)
+ *
+ *    DATA, The data channel is connected, allowing data transfers between
+ *    the local and remote machines.
+ *
+ */
+static int irlan_provider_state_data(struct irlan_cb *self, IRLAN_EVENT event, 
+				     struct sk_buff *skb) 
+{
+	struct irmanager_event mgr_event;
+
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+
+	switch(event) {
+	case IRLAN_FILTER_CONFIG_CMD:
+		irlan_provider_extract_params(self, CMD_FILTER_OPERATION, skb);
+		irlan_provider_send_reply(self, CMD_FILTER_OPERATION, 
+					  RSP_SUCCESS);
+		break;
+	case IRLAN_LMP_DISCONNECT: /* FALLTHROUGH */
+	case IRLAN_LAP_DISCONNECT:
+		mgr_event.event = EVENT_IRLAN_STOP;
+		sprintf(mgr_event.devname, "%s", self->ifname);
+		irmanager_notify(&mgr_event);
+
+		irlan_next_provider_state(self, IRLAN_IDLE);
+		break;
+	default:
+		DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
+		break;
+	}
+	if (skb)
+		dev_kfree_skb(skb);
+	
+	return 0;
+}
+
+
+
+
+
+
+
+
+
+
diff -u --recursive --new-file v2.2.2/linux/net/irda/irlan/irlan_srv.c linux/net/irda/irlan/irlan_srv.c
--- v2.2.2/linux/net/irda/irlan/irlan_srv.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/irlan/irlan_srv.c	Wed Dec 31 16:00:00 1969
@@ -1,915 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      irlan_srv.c
- * Version:       0.1
- * Description:   IrDA LAN Access Protocol Implementation
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Mon Dec 14 19:10:49 1998
- * 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 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.
- *
- ********************************************************************/
-
-#include <linux/module.h> 
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/init.h>
-
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <asm/byteorder.h>
-
-
-#include <net/irda/irda.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/timer.h>
-
-#include <net/irda/irlan_common.h>
-#include <net/irda/irlan_eth.h>
-#include <net/irda/irlan_event.h>
-#include <net/irda/irlan_srv.h>
-
-/*
- *  Private functions
- */
-static void __irlan_server_close( struct irlan_cb *self);
-static int irlan_server_dev_init( struct device *dev);
-static int irlan_server_dev_open(struct device *dev);
-static int irlan_server_dev_close(struct device *dev);
-static void irlan_check_param( struct irlan_cb *self, char *param, char *value);
-
-/*
- * Function irlan_server_init (dev)
- *
- *   Allocates the master array. Called by modprobe().
- */
-__initfunc(int irlan_server_init( void))
-{
-	DEBUG( 4, "--> irlan_server_init\n");
-
-	/* Register with IrLMP as a service */
-	irlmp_register_layer( S_LAN, SERVER, FALSE, NULL);
-	
- 	irlan_server_register();
-		
-	DEBUG( 4, "irlan_server_init -->\n");
-		
-	return 0;
-}
-
-/*
- * Function irlan_server_cleanup (void)
- *
- *    Removes all instances of the IrLAN network device driver, and the
- *    master array. Called by rmmod().
- */
-void irlan_server_cleanup(void) 
-{
-	DEBUG( 4, "--> irlan_server_cleanup\n");
-
-	irlmp_unregister_layer( S_LAN, SERVER);
-
-	/*
-	 *  Delete hashbin and close all irlan client instances in it
-	 */
-	/* hashbin_delete( irlan, (FREE_FUNC) __irlan_server_close); */
-	
-	DEBUG( 4, "irlan_server_cleanup -->\n");
-}
-
-/*
- * Function irlan_server_open (void)
- *
- *    This function allocates and opens a new instance of the IrLAN network
- *    device driver.
- */
-struct irlan_cb *irlan_server_open(void) 
-{
-	struct irlan_cb *self;
-	int result;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	/* 
-	 *  Initialize the irlan_server structure. 
-	 */
-
-	self = kmalloc( sizeof(struct irlan_cb), GFP_ATOMIC);
-	if ( self == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Unable to kmalloc!\n");
-		return NULL;
-	}
-	memset( self, 0, sizeof(struct irlan_cb));
-
-	/*
-	 *  Initialize local device structure
-	 */
-	self->magic = IRLAN_MAGIC;
-
-	self->dev.name = self->ifname;
-	self->dev.init = irlan_server_dev_init;
-	self->dev.priv = (void *) self;
-	self->dev.next = NULL;
-
-	if (( result = register_netdev( &self->dev)) != 0) {
-		DEBUG( 0, __FUNCTION__ "(), register_netdev() failed!\n");
-		return NULL;
-	}
-
-	irlan_next_state( self, IRLAN_IDLE);
-
-	hashbin_insert( irlan , (QUEUE *) self, (int) self, NULL);
-	
-	return self;
-}
-
-/*
- * Function irlan_server_dev_init (dev)
- *
- *    The network device initialization function. Called only once.
- *
- */
-static int irlan_server_dev_init( struct device *dev)
-{
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( dev != NULL, return -1;);
-       
-	irlan_eth_init( dev);
-
-	/* Overrride some functions */
-	dev->open               = irlan_server_dev_open;
-	dev->stop	        = irlan_server_dev_close;
-	
-	/*  
-	 *  OK, since we are emulating an IrLAN sever we will have to give
-	 *  ourself an ethernet address!
-	 *  FIXME: this must be more dynamically
-	 */
-	dev->dev_addr[0] = 0x40;
-	dev->dev_addr[1] = 0x00;
-	dev->dev_addr[2] = 0x00;
-	dev->dev_addr[3] = 0x00;
-	dev->dev_addr[4] = 0x23;
-	dev->dev_addr[5] = 0x45;
-
-	return 0;
-}
-
-/*
- * Function irlan_server_dev_open (dev)
- *
- *    Start the Servers ether network device, this function will be called by
- *    "ifconfig server0 up".  
- */
-static int irlan_server_dev_open( struct device *dev)
-{
-	/* struct irlan_cb *self = (struct irlan_cb *) dev->priv; */
-	
-	DEBUG( 4, "irlan_server_dev_open()\n");
-
-	ASSERT( dev != NULL, return -1;);
-
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
-
-	MOD_INC_USE_COUNT;
-	
-	return 0;
-}
-
-static void __irlan_server_close( struct irlan_cb *self)
-{
-	DEBUG( 4, "--> irlan_server_close()\n");
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-	
-	/* 
-	 *  Disconnect open TSAP connections
-	 */
-	if ( self->tsap_data) {
-		irttp_disconnect_request( self->tsap_data, NULL, P_HIGH);
-		
-		/* FIXME: this will close the tsap before the disconenct
-		 * frame has been sent 
-		 */
-		/* irttp_close_tsap( self->tsap_data); */
-	}
-	if ( self->tsap_ctrl) {
-		irttp_disconnect_request( self->tsap_ctrl, NULL, P_HIGH);
-		
-		/* irttp_close_tsap( self->tsap_control); */
-	}
-
-	unregister_netdev( &self->dev);
-
-	self->magic = ~IRLAN_MAGIC;
-	
-	kfree( self);
-
-	DEBUG( 4, "irlan_server_close() -->\n");
-}
-
-/*
- * Function irlan_server_close (self)
- *
- *    This function closes and marks the IrLAN instance as not in use. 
- */
-void irlan_server_close( struct irlan_cb *self)
-{
-	struct irlan_cb *entry;
-
-	DEBUG( 4, "--> irlan_server_close()\n");
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-	
-	entry = hashbin_remove( irlan, (int) self, NULL);
-
-	ASSERT( entry == self, return;);
-	
-	__irlan_server_close( self);
-
-	DEBUG( 4, "irlan_server_close() -->\n");	
-}
-
-/*
- * Function irlan_server_dev_close (dev)
- *
- *    Stop the IrLAN ether network device, his function will be called by
- *    ifconfig down.
- */
-static int irlan_server_dev_close( struct device *dev)
-{
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( dev != NULL, return -1;);
-	
-	dev->tbusy = 1;
-	dev->start = 0;
-
-	MOD_DEC_USE_COUNT;
-	
-	return 0;
-}
-
-
-/*
- * Function irlan_server_disconnect_indication (handle, reason, priv)
- *
- *    Callback function for the IrTTP layer. Indicates a disconnection of
- *    the specified connection (handle)
- *
- */
-void irlan_server_disconnect_indication( void *instance, void *sap, 
-					 LM_REASON reason, 
-					 struct sk_buff *skb) 
-{
-	struct irlan_info info;
-	struct irlan_cb *self;
-	struct tsap_cb *tsap;
-	
-	DEBUG( 4, __FUNCTION__ "(), Reason=%d\n", reason);
-	
-	self = ( struct irlan_cb *) instance;
-	tsap = ( struct tsap_cb *) sap;
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);	
-
-	info.daddr = self->daddr;
-	
-	if ( tsap == self->tsap_data) {
-		DEBUG( 0, "IrLAN, data channel disconnected by peer!\n");
-		self->connected = FALSE;
-	} else if ( tsap == self->tsap_ctrl) {
-		DEBUG( 0, "IrLAN, control channel disconnected by peer!\n");
-	} else {
-		DEBUG( 0, "Error, disconnect on unknown handle!\n");
-	}
-	
-	/* Stop IP from transmitting more packets */
-	/* irlan_flow_indication( handle, FLOW_STOP, priv); */
-
-	irlan_do_server_event( self, IRLAN_LMP_DISCONNECT, NULL, NULL);
-}
-	
-/*
- * Function irlan_server_control_data_indication (handle, skb)
- *
- *    This function gets the data that is received on the control channel
- *
- */
-void irlan_server_control_data_indication( void *instance, void *sap, 
-					   struct sk_buff *skb) 
-{
-	struct irlan_cb *self;
-	__u8 code;
-	
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	self = ( struct irlan_cb *) instance;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-	ASSERT( skb != NULL, return;);
-
-	code = skb->data[0];
-	switch( code) {
-	case CMD_GET_PROVIDER_INFO:
-		DEBUG( 4, "Got GET_PROVIDER_INFO command!\n");
-		irlan_do_server_event( self, IRLAN_GET_INFO_CMD, skb, NULL); 
-		break;
-
-	case CMD_GET_MEDIA_CHAR:
-		DEBUG( 4, "Got GET_MEDIA_CHAR command!\n");
-		irlan_do_server_event( self, IRLAN_GET_MEDIA_CMD, skb, NULL); 
-		break;
-	case CMD_OPEN_DATA_CHANNEL:
-		DEBUG( 4, "Got OPEN_DATA_CHANNEL command!\n");
-		irlan_do_server_event( self, IRLAN_OPEN_DATA_CMD, skb, NULL); 
-		break;
-	case CMD_FILTER_OPERATION:
-		DEBUG( 4, "Got FILTER_OPERATION command!\n");
-		irlan_do_server_event( self, IRLAN_FILTER_CONFIG_CMD, skb, 
-				       NULL);
-		break;
-	case CMD_RECONNECT_DATA_CHAN:
-		DEBUG( 0, __FUNCTION__"(), Got RECONNECT_DATA_CHAN command\n");
-		DEBUG( 0, __FUNCTION__"(), NOT IMPLEMENTED\n");
-		break;
-	case CMD_CLOSE_DATA_CHAN:
-		DEBUG( 0, "Got CLOSE_DATA_CHAN command!\n");
-		DEBUG( 0, __FUNCTION__"(), NOT IMPLEMENTED\n");
-		break;
-	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown command!\n");
-		break;
-	}
-}
-
-/*
- * Function irlan_server_connect_indication (handle, skb, priv)
- *
- *    Got connection from peer IrLAN layer
- *
- */
-void irlan_server_connect_indication( void *instance, void *sap, 
-				      struct qos_info *qos, int max_sdu_size,
-				      struct sk_buff *skb)
-{
-	struct irlan_cb *self;
-	struct irlan_info info;
-	struct tsap_cb *tsap;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	self = ( struct irlan_cb *) instance;
-	tsap = ( struct tsap_cb *) sap;
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-	
-	info.tsap = tsap;
-	
-	if ( tsap == self->tsap_data)
-		irlan_do_server_event( self, IRLAN_DATA_CONNECT_INDICATION, 
-				       NULL, &info);
-	else
-		irlan_do_server_event( self, IRLAN_CONNECT_INDICATION, NULL, 
-				       &info);
-}
-
-/*
- * Function irlan_server_connect_response (handle)
- *
- *    Accept incomming connection
- *
- */
-void irlan_server_connect_response( struct irlan_cb *self, 
-				    struct tsap_cb *tsap)
-{
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-	/* FIXME: define this value */
-	irttp_connect_response( tsap, 1518, NULL);
-}
-
-/*
- * Function irlan_server_get_provider_info (self)
- *
- *    Send Get Provider Information command to peer IrLAN layer
- *
- */
-void irlan_server_get_provider_info( struct irlan_cb *self) 
-{
-	struct sk_buff *skb;
-	__u8 *frame;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-	skb =  dev_alloc_skb( 64);
-	if (skb == NULL) {
-		DEBUG( 0,"irlan_server_get_provider_info: "
-		       "Could not allocate an sk_buff of length %d\n", 64);
-		return;
-	}
-
-	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-	skb_put( skb, 2);
-	
-	frame = skb->data;
-	
- 	frame[0] = CMD_GET_PROVIDER_INFO;
-	frame[1] = 0x00;                 /* Zero parameters */
-	
-	irttp_data_request( self->tsap_ctrl, skb);
-}
-
-/*
- * Function irlan_parse_open_data_cmd (self, skb)
- *
- *    
- *
- */
-int irlan_parse_open_data_cmd( struct irlan_cb *self, struct sk_buff *skb)
-{
-	int ret = RSP_SUCCESS;
-	
-	irlan_server_extract_params( self, CMD_OPEN_DATA_CHANNEL, skb);
-
-	return ret;
-}
-
-/*
- * Function extract_params (skb)
- *
- *    Extract all parameters from received buffer, then feed them to 
- *    check_params for parsing
- *
- */
-int irlan_server_extract_params( struct irlan_cb *self, int cmd,
-				struct sk_buff *skb) 
-{
-	__u8 *frame;
-	__u8 *ptr;
-	int count;
-	__u8 name_len;
-	__u16 val_len;
-	int i;
-	
-	ASSERT( skb != NULL, return -RSP_PROTOCOL_ERROR;);
-	
-	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;);
-	
-	if ( skb == NULL) {
-		DEBUG( 0, "extract_params: Got NULL skb!\n");
-		return -RSP_PROTOCOL_ERROR;
-	}
-	frame = skb->data;
-
-	/* How many parameters? */
-	count = frame[1];
-
-	DEBUG( 4, "Got %d parameters\n", count);
-	
-	ptr = frame+2;
-
-	/* For all parameters */
- 	for ( i=0; i<count;i++) {
-		/* get length of parameter name ( 1 byte) */
-		name_len = *ptr++;
-
-		if (name_len > 255) {
-			DEBUG( 0, "extract_params, name_len > 255\n");
-			return -RSP_PROTOCOL_ERROR;
-		}
-
-		/* get parameter name */
-		memcpy( self->name, ptr, name_len);
-		self->name[ name_len] = '\0';
-		ptr+=name_len;
-		
-		/*  
-		 *  Get length of parameter value ( 2 bytes in little endian 
-		 *  format) 
-		 */
-		val_len = *ptr++ & 0xff;	
-		val_len |= *ptr++ << 8;
-		
-		if (val_len > 1016) {
-			DEBUG( 0, 
-			       "extract_params, parameter length to long\n");
-			return -RSP_PROTOCOL_ERROR;
-		}
-		
-		/* get parameter value */
- 		memcpy( self->value, ptr, val_len);
- 		self->value[ val_len] = '\0';
- 		ptr+=val_len;
-		
- 		DEBUG( 4, "Parameter: %s ", self->name); 
- 		DEBUG( 4, "Value: %s\n", self->value); 
-		
-		irlan_check_param( self, self->name, self->value);
-	}
-	return RSP_SUCCESS;
-}
-
-/*
- * Function handle_filter_request (self, skb)
- *
- *    Handle filter request from client peer device
- *
- */
-void handle_filter_request( struct irlan_cb *self, struct sk_buff *skb)
-{
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-	if (( self->t.server.filter_type == IR_DIRECTED) && 
-	    ( self->t.server.filter_operation == DYNAMIC))
-	{
-		DEBUG( 0, "Giving peer a dynamic Ethernet address\n");
-
-		self->t.server.mac_address[0] = 0x40;
-		self->t.server.mac_address[1] = 0x00;
-		self->t.server.mac_address[2] = 0x00;
-		self->t.server.mac_address[3] = 0x00;
-		self->t.server.mac_address[4] = 0x12;
-		self->t.server.mac_address[5] = 0x34;
-
-		skb->data[0] = 0x00; /* Success */
-		skb->data[1] = 0x03;
-		insert_param( skb, "FILTER_MODE", 1, "NONE", 0, 0);
-		insert_param( skb, "MAX_ENTRY", 3, NULL, 0, 0x0001);
-		insert_array_param( skb, "FILTER_ENTRY", self->t.server.mac_address, 6);
-		return;
-	}
-	
-	if (( self->t.server.filter_type == IR_DIRECTED) && 
-	    ( self->t.server.filter_mode == FILTER))
-	{
-		DEBUG( 0, "Directed filter on\n");
-		skb->data[0] = 0x00; /* Success */
-		skb->data[1] = 0x00;
-		return;
-	}
-	if (( self->t.server.filter_type == IR_DIRECTED) && 
-	    ( self->t.server.filter_mode == NONE))
-	{
-		DEBUG( 0, "Directed filter off\n");
-		skb->data[0] = 0x00; /* Success */
-		skb->data[1] = 0x00;
-		return;
-	}
-
-	if (( self->t.server.filter_type == IR_BROADCAST) && 
-	    ( self->t.server.filter_mode == FILTER))
-	{
-		DEBUG( 0, "Broadcast filter on\n");
-		skb->data[0] = 0x00; /* Success */
-		skb->data[1] = 0x00;
-		return;
-	}
-	if (( self->t.server.filter_type == IR_BROADCAST) && 
-	    ( self->t.server.filter_mode == NONE))
-	{
-		DEBUG( 0, "Broadcast filter off\n");
-		skb->data[0] = 0x00; /* Success */
-		skb->data[1] = 0x00;
-		return;
-	}
-	if (( self->t.server.filter_type == IR_MULTICAST) && 
-	    ( self->t.server.filter_mode == FILTER))
-	{
-		DEBUG( 0, "Multicast filter on\n");
-		skb->data[0] = 0x00; /* Success */
-		skb->data[1] = 0x00;
-		return;
-	}
-	if (( self->t.server.filter_type == IR_MULTICAST) && 
-	    ( self->t.server.filter_mode == NONE))
-	{
-		DEBUG( 0, "Multicast filter off\n");
-		skb->data[0] = 0x00; /* Success */
-		skb->data[1] = 0x00;
-		return;
-	}
-	if (( self->t.server.filter_type == IR_MULTICAST) && 
-	    ( self->t.server.filter_operation == GET))
-	{
-		DEBUG( 0, "Multicast filter get\n");
-		skb->data[0] = 0x00; /* Success? */
-		skb->data[1] = 0x02;
-		insert_param( skb, "FILTER_MODE", 1, "NONE", 0, 0);
-		insert_param( skb, "MAX_ENTRY", 3, NULL, 0, 16);
-		return;
-	}
-	skb->data[0] = 0x00; /* Command not supported */
-	skb->data[1] = 0x00;
-
-	DEBUG( 0, "Not implemented!\n");
-}
-
-/*
- * Function check_request_param (self, param, value)
- *
- *    Check parameters in request from peer device
- *
- */
-static void irlan_check_param( struct irlan_cb *self, char *param, char *value)
-{
-	__u8 *bytes;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	bytes = value;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-	DEBUG( 4, "%s, %s\n", param, value);
-
-	/*
-	 *  This is experimental!! DB.
-	 */
-	 if ( strcmp( param, "MODE") == 0) {
-		DEBUG( 0, __FUNCTION__ "()\n");
-		self->use_udata = TRUE;
-		return;
-	}
-
-	/*
-	 *  FILTER_TYPE
-	 */
-	if ( strcmp( param, "FILTER_TYPE") == 0) {
-		if ( strcmp( value, "DIRECTED") == 0) {
-			self->t.server.filter_type = IR_DIRECTED;
-			return;
-		}
-		if ( strcmp( value, "MULTICAST") == 0) {
-			self->t.server.filter_type = IR_MULTICAST;
-			return;
-		}
-		if ( strcmp( value, "BROADCAST") == 0) {
-			self->t.server.filter_type = IR_BROADCAST;
-			return;
-		}
-	}
-	/*
-	 *  FILTER_MODE
-	 */
-	if ( strcmp( param, "FILTER_MODE") == 0) {
-		if ( strcmp( value, "ALL") == 0) {
-			self->t.server.filter_mode = ALL;
-			return;
-		}
-		if ( strcmp( value, "FILTER") == 0) {
-			self->t.server.filter_mode = FILTER;
-			return;
-		}
-		if ( strcmp( value, "NONE") == 0) {
-			self->t.server.filter_mode = FILTER;
-			return;
-		}
-	}
-	/*
-	 *  FILTER_OPERATION
-	 */
-	if ( strcmp( param, "FILTER_OPERATION") == 0) {
-		if ( strcmp( value, "DYNAMIC") == 0) {
-			self->t.server.filter_operation = DYNAMIC;
-			return;
-		}
-		if ( strcmp( value, "GET") == 0) {
-			self->t.server.filter_operation = GET;
-			return;
-		}
-	}
-}
-
-/*
- * Function irlan_server_send_reply (self, info)
- *
- *    Send reply to query to peer IrLAN layer
- *
- */
-void irlan_server_send_reply( struct irlan_cb *self, int command, int ret_code)
-{
-	struct sk_buff *skb;
-
-	DEBUG( 4, "irlan_server_send_reply()\n");
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-	skb =  dev_alloc_skb( 128);
-	if (skb == NULL) {
-		DEBUG( 0,"irlan_server_send_reply: "
-		       "Could not allocate an sk_buff of length %d\n", 128);
-		return;
-	}
-
-	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-	skb_put( skb, 2);
-       
-	switch ( command) {
-	case CMD_GET_PROVIDER_INFO:
-		skb->data[0] = 0x00; /* Success */
-		skb->data[1] = 0x02; /* 2 parameters */
-		insert_param( skb, "MEDIA", 1, "802.3", 0, 0);
-		insert_param( skb, "IRLAN_VER", 3, NULL, 0, 0x0101);
-		break;
-	case CMD_GET_MEDIA_CHAR:
-		skb->data[0] = 0x00; /* Success */
-		skb->data[1] = 0x05; /* 5 parameters */
-		insert_param( skb, "FILTER_TYPE", 1, "DIRECTED", 0, 0);
-		insert_param( skb, "FILTER_TYPE", 1, "BROADCAST", 0, 0);
-		insert_param( skb, "FILTER_TYPE", 1, "MULTICAST", 0, 0);
-		insert_param( skb, "ACCESS_TYPE", 1, "DIRECTED", 0, 0);
-		insert_param( skb, "MAX_FRAME", 3, NULL, 0, 0x05ee);
-		break;
-	case CMD_OPEN_DATA_CHANNEL:
-		skb->data[0] = 0x00; /* Success */
-		skb->data[1] = 0x02; /* 2 parameters */
-		insert_param( skb, "DATA_CHAN", 2, NULL, self->stsap_sel_data, 0);
-		insert_param( skb, "RECONNECT_KEY", 1, "LINUX RULES!", 0, 0);
-		break;
-	case CMD_FILTER_OPERATION:
-		handle_filter_request( self, skb);
-		break;
-	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown command!\n");
-		break;
-	}
-
-	irttp_data_request( self->tsap_ctrl, skb);
-}
-
-/*
- * Function irlan_server_register(void)
- *
- *    Register server support so we can accept incomming connections. We
- *    must register both a TSAP for control and data
- * 
- */
-void irlan_server_register(void)
-{
-	struct notify_t notify;
-	struct irlan_cb *self;
-	struct ias_object *obj;
-	struct tsap_cb *tsap;
-	
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	/*
-	 *  Open irlan_server instance
-	 */
-	self = irlan_server_open();
-	if ( !self || self->magic != IRLAN_MAGIC) {
-		DEBUG( 0, __FUNCTION__"(), Unable to open server!\n");
-		return;
-	}
-	/*
-	 *  First register well known control TSAP
-	 */
-	irda_notify_init( &notify);
-	notify.data_indication       = irlan_server_control_data_indication;
-	notify.connect_indication    = irlan_server_connect_indication;
-	notify.disconnect_indication = irlan_server_disconnect_indication;
-	notify.instance = self;
-	strncpy( notify.name, "IrLAN srv. ctrl", 16);
-
-	/* FIXME: should not use a static value here! */
-	tsap = irttp_open_tsap( TSAP_IRLAN, 1, &notify);
-	if ( tsap == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Got no handle!!\n");
-		return;
-	}
-	self->tsap_ctrl = tsap;
-
-	/*
-	 *  Now register data TSAP
-	 */
-	irda_notify_init( &notify);
-	notify.data_indication       = irlan_eth_rx;
-	notify.udata_indication      = irlan_eth_rx;
-	notify.connect_indication    = irlan_server_connect_indication;
-	notify.disconnect_indication = irlan_server_disconnect_indication;
-	notify.instance = self;
-	strncpy( notify.name, "IrLAN srv. data", 16);
-
-	/*
-	 *  Register well known address with IrTTP
-	 */ 
-	tsap = irttp_open_tsap( LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);
-	if ( tsap == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Got no handle!\n");
-		return;
-	}
-	self->tsap_data = tsap;
-
-	/* 
-	 *  This is the data TSAP selector which we will pass to the client
-	 *  when the client ask for it.
-	 */
-	self->stsap_sel_data = tsap->stsap_sel;
-	ASSERT( self->stsap_sel_data > 0, return;);
-
-	DEBUG( 0, "irlan_server_register(), Using Source TSAP selector=%02x\n",
-	       self->stsap_sel_data);
-	
-	/* 
-	 *  Register with LM-IAS
-	 */
-	obj = irias_new_object( "IrLAN", IAS_IRLAN_ID);
-	irias_add_integer_attrib( obj, "IrDA:TinyTP:LsapSel", TSAP_IRLAN);
-	irias_insert_object( obj);
-
-	obj = irias_new_object( "PnP", IAS_PNP_ID);
-	irias_add_string_attrib( obj, "Name", "Linux");
-	irias_add_string_attrib( obj, "DeviceID", "HWP19F0");
-	irias_add_integer_attrib( obj, "CompCnt", 2);
-	irias_add_string_attrib( obj, "Comp#01", "PNP8294");
-	irias_add_string_attrib( obj, "Comp#01", "PNP8389");
-	irias_add_string_attrib( obj, "Manufacturer", "Linux/IR Project");
-	irias_insert_object( obj);
-}
-
-#ifdef MODULE
-
-MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
-MODULE_DESCRIPTION("The Linux IrDA LAN Server protocol"); 
-
-/*
- * Function init_module (void)
- *
- *    Initialize the IrLAN module, this function is called by the
- *    modprobe(1) program.
- */
-int init_module(void) 
-{
-/* 	int result; */
-
-	DEBUG( 4, "--> IrLAN irlan_server: init_module\n");
-
-	irlan_server_init();
-
-	DEBUG( 4, "IrLAN irlan_server: init_module -->\n");	
-
-	return 0;
-}
-
-/*
- * Function cleanup_module (void)
- *
- *    Remove the IrLAN module, this function is called by the rmmod(1)
- *    program
- */
-void cleanup_module(void) 
-{
-	DEBUG( 4, "--> irlan_server, cleanup_module\n");
-	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
-
-	/* Free some memory */
- 	irlan_server_cleanup();
-
-	DEBUG( 4, "irlan_server, cleanup_module -->\n");
-}
-
-#endif /* MODULE */
diff -u --recursive --new-file v2.2.2/linux/net/irda/irlan/irlan_srv_event.c linux/net/irda/irlan/irlan_srv_event.c
--- v2.2.2/linux/net/irda/irlan/irlan_srv_event.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/irlan/irlan_srv_event.c	Wed Dec 31 16:00:00 1969
@@ -1,268 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      irlan_srv_event.c
- * Version:       0.1
- * Description:   IrLAN Server FSM (Finite State Machine)
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Wed Dec  9 02:39:05 1998
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     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.
- *
- *     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.
- *
- ********************************************************************/
-
-#include <net/irda/irda.h>
-#include <net/irda/iriap.h>
-#include <net/irda/irlmp.h>
-#include <net/irda/irttp.h>
-
-#include <net/irda/irlan_srv.h>
-#include <net/irda/irlan_event.h>
-
-static int irlan_server_state_idle ( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb, 
-				     struct irlan_info *info);
-static int irlan_server_state_info ( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb, 
-				     struct irlan_info *info);
-static int irlan_server_state_open ( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb, 
-				     struct irlan_info *info);
-static int irlan_server_state_data ( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb, 
-				     struct irlan_info *info);
-
-static int (*state[])( struct irlan_cb *self, IRLAN_EVENT event, 
-		       struct sk_buff *skb, struct irlan_info *info) = 
-{ 
-	irlan_server_state_idle,
-	NULL, /* Query */
-	NULL, /* Info */
-	irlan_server_state_info,
-	NULL, /* Media */
-	irlan_server_state_open,
-	NULL, /* Wait */
-	NULL, /* Arb */
-	irlan_server_state_data,
-	NULL, /* Close */
-	NULL, /* Sync */
-};
-
-void irlan_do_server_event( struct irlan_cb *self, 
-			    IRLAN_EVENT event, 
-			    struct sk_buff *skb, 
-			    struct irlan_info *info) 
-{
-	(*state[ self->state]) ( self, event, skb, info);
-}
-
-/*
- * Function irlan_server_state_idle (event, skb, info)
- *
- *    IDLE, We are waiting for an indication that there is a provider
- *    available.
- */
-static int irlan_server_state_idle( struct irlan_cb *self, 
-				    IRLAN_EVENT event, 
-				    struct sk_buff *skb, 
-				    struct irlan_info *info) 
-{
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	ASSERT( self != NULL, return -1;);
-	
-	switch( event) {
-	case IRLAN_CONNECT_INDICATION:
-	     ASSERT( info != NULL, return 0;);
-	     irlan_server_connect_response( self, info->tsap);
-	     irlan_next_state( self, IRLAN_INFO);
-	     break;
-	default:
-		DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", 
-		       event);
-		break;
-	}
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-	return 0;
-}
-
-/*
- * Function irlan_server_state_info (self, event, skb, info)
- *
- *    INFO, We have issued a GetInfo command and is awaiting a reply.
- */
-static int irlan_server_state_info( struct irlan_cb *self, 
-				    IRLAN_EVENT event, 
-				    struct sk_buff *skb, 
-				    struct irlan_info *info) 
-{
-	int ret;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	ASSERT( self != NULL, return -1;);
-
-	switch( event) {
-	case IRLAN_GET_INFO_CMD: 
-		irlan_server_send_reply( self, CMD_GET_PROVIDER_INFO, 
-					 RSP_SUCCESS);
-		/* Keep state */
-		break;
-
-	case IRLAN_GET_MEDIA_CMD: 
-		irlan_server_send_reply( self, CMD_GET_MEDIA_CHAR, 
-					 RSP_SUCCESS);
-		/* Keep state */
-		break;
-		
-	case IRLAN_OPEN_DATA_CMD:
-		ret = irlan_parse_open_data_cmd( self, skb);
-		irlan_server_send_reply( self, CMD_OPEN_DATA_CHANNEL, ret);
-
-		if ( ret == RSP_SUCCESS)
-			irlan_next_state( self, IRLAN_OPEN);
-		break;
-	case IRLAN_LMP_DISCONNECT:
-	case IRLAN_LAP_DISCONNECT:
-		irlan_next_state( self, IRLAN_IDLE);
-		break;
-	default:
-		DEBUG( 0, "irlan_server_state_info, Unknown event %d\n", 
-		       event);
-		break;
-	}
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-	
-	return 0;
-}
-
-/*
- * Function irlan_server_state_open (self, event, skb, info)
- *
- *    OPEN, The client has issued a OpenData command and is awaiting a
- *    reply
- *
- */
-static int irlan_server_state_open( struct irlan_cb *self, 
-				    IRLAN_EVENT event, 
-				    struct sk_buff *skb, 
-				    struct irlan_info *info) 
-{
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( self != NULL, return -1;);
-
-	switch( event) {
-	case IRLAN_FILTER_CONFIG_CMD:
-		irlan_server_extract_params( self, CMD_FILTER_OPERATION, skb);
-		irlan_server_send_reply( self, CMD_FILTER_OPERATION, 
-					 RSP_SUCCESS);
-		/* Keep state */
-		break;
-		
-	case IRLAN_DATA_CONNECT_INDICATION: 
-		DEBUG( 4, "DATA_CONNECT_INDICATION\n");
-		irlan_next_state( self, IRLAN_DATA);
-		irlan_server_connect_response( self, info->tsap);
-		break;
-		
-	case IRLAN_LMP_DISCONNECT:
-	case IRLAN_LAP_DISCONNECT:
-		irlan_next_state( self, IRLAN_IDLE);
-		break;
-	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", 
-		       event);
-		break;
-	}
-	
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-
-	return 0;
-}
-
-/*
- * Function irlan_server_state_data (self, event, skb, info)
- *
- *    DATA, The data channel is connected, allowing data transfers between
- *    the local and remote machines.
- *
- */
-static int irlan_server_state_data( struct irlan_cb *self, 
-				    IRLAN_EVENT event, 
-				    struct sk_buff *skb, 
-				    struct irlan_info *info) 
-{
-	struct irmanager_event mgr_event;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLAN_MAGIC, return -1;);
-
-	switch( event) {
-	case IRLAN_FILTER_CONFIG_CMD:
-		irlan_server_extract_params( self, CMD_FILTER_OPERATION, skb);
-		irlan_server_send_reply( self, CMD_FILTER_OPERATION, 
-					 RSP_SUCCESS);
-
-		/* Make sure the code below only runs once */
-		if ( !self->connected) {
-			mgr_event.event = EVENT_IRLAN_START;
-			sprintf( mgr_event.devname, "%s", self->ifname);
-			irmanager_notify( &mgr_event);
-
-			self->connected = TRUE;
-		}
-		break;
-		
-	case IRLAN_LMP_DISCONNECT:
-	case IRLAN_LAP_DISCONNECT:
-		mgr_event.event = EVENT_IRLAN_STOP;
-		sprintf( mgr_event.devname, "%s", self->ifname);
-		irmanager_notify( &mgr_event);
-
-		irlan_next_state( self, IRLAN_IDLE);
-		break;
-	default:
-		DEBUG( 0, "irlan_server_state_data, Unknown event %d\n", 
-		       event);
-		break;
-	}
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-	
-	return 0;
-}
-
-
-
-
-
-
-
-
-
-
diff -u --recursive --new-file v2.2.2/linux/net/irda/irlap.c linux/net/irda/irlap.c
--- v2.2.2/linux/net/irda/irlap.c	Wed Jan 20 23:14:07 1999
+++ linux/net/irda/irlap.c	Sun Mar  7 15:26:44 1999
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irlap.c
- * Version:       0.8
+ * Version:       0.9
  * Description:   An IrDA LAP driver for Linux
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Sat Jan 16 22:19:27 1999
+ * Modified at:   Sat Feb 20 01:39:58 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
@@ -43,12 +43,23 @@
 #include <net/irda/irlap_comp.h>
 
 hashbin_t *irlap = NULL;
+int sysctl_slot_timeout = SLOT_TIMEOUT;
 
 static void __irlap_close( struct irlap_cb *self);
 
+static char *lap_reasons[] = {
+	"ERROR, NOT USED",
+	"LAP_DISC_INDICATION",
+	"LAP_NO_RESPONSE",
+	"LAP_RESET_INDICATION",
+	"LAP_FOUND_NONE",
+	"LAP_MEDIA_BUSY",
+	"LAP_PRIMARY_CONFLICT",
+	"ERROR, NOT USED",
+};
+
 #ifdef CONFIG_PROC_FS
-int irlap_proc_read( char *buf, char **start, off_t offset, int len, 
-		     int unused);
+int irlap_proc_read( char *, char **, off_t, int, int);
 
 #endif /* CONFIG_PROC_FS */
 
@@ -138,8 +149,6 @@
 
 	irlmp_register_irlap( self, self->saddr, &self->notify);
 	
-	DEBUG( 4, "irlap_open -->\n");
-
 	return self;
 }
 
@@ -166,7 +175,7 @@
 	irlap_flush_all_queues( self);
        
 	self->irdev = NULL;
-	self->magic = ~LAP_MAGIC;
+	self->magic = 0;
 	
 	kfree( self);
 }
@@ -194,7 +203,7 @@
 	/* Be sure that we manage to remove ourself from the hash */
 	lap = hashbin_remove( irlap, self->saddr, NULL);
 	if ( !lap) {
-		DEBUG( 0, __FUNCTION__ "(), Didn't find myself!\n");
+		DEBUG( 1, __FUNCTION__ "(), Didn't find myself!\n");
 		return;
 	}
 	__irlap_close( lap);
@@ -206,17 +215,17 @@
  *    Another device is attempting to make a connection
  *
  */
-void irlap_connect_indication( struct irlap_cb *self, struct sk_buff *skb) 
+void irlap_connect_indication(struct irlap_cb *self, struct sk_buff *skb) 
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
 
-	irlap_init_qos_capabilities( self, NULL); /* No user QoS! */
+	irlap_init_qos_capabilities(self, NULL); /* No user QoS! */
 	
-	irlmp_link_connect_indication( self->notify.instance, &self->qos_tx, 
-				       skb);
+	irlmp_link_connect_indication(self->notify.instance, self->saddr, 
+				      self->daddr, &self->qos_tx, skb);
 }
 
 /*
@@ -247,21 +256,17 @@
 	ASSERT( self->magic == LAP_MAGIC, return;);
 
  	self->daddr = daddr;
-
+	
 	/*
 	 *  If the service user specifies QoS values for this connection, 
 	 *  then use them
 	 */
 	irlap_init_qos_capabilities( self, qos_user);
 	
-	if ( self->state == LAP_NDM) {
+	if ( self->state == LAP_NDM)
 		irlap_do_event( self, CONNECT_REQUEST, NULL, NULL);
-	} else {
-		DEBUG( 0, __FUNCTION__ "() Wrong state!\n");
-		
-		irlap_disconnect_indication( self, LAP_MEDIA_BUSY);
-	}
-	       
+	else
+		self->connect_pending = TRUE;
 }
 
 /*
@@ -302,12 +307,11 @@
 	if ( self->qos_tx.compression.value) {
 		skb = irlap_decompress_frame( self, skb);
 		if ( !skb) {
-			DEBUG( 0, __FUNCTION__ "(), Decompress error!\n");
+			DEBUG( 1, __FUNCTION__ "(), Decompress error!\n");
 			return;
 		}
 	}
 #endif
-
 	irlmp_link_data_indication( self->notify.instance, LAP_RELIABLE, skb);
 }
 
@@ -319,7 +323,7 @@
  */
 void irlap_unit_data_indication( struct irlap_cb *self, struct sk_buff *skb)
 {
-	DEBUG( 0, __FUNCTION__ "()\n"); 
+	DEBUG( 1, __FUNCTION__ "()\n"); 
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LAP_MAGIC, return;);
@@ -333,7 +337,7 @@
 		
 		skb = irlap_decompress_frame( self, skb);
 		if ( !skb) {
-			DEBUG( 0, __FUNCTION__ "(), Decompress error!\n");
+			DEBUG( 1, __FUNCTION__ "(), Decompress error!\n");
 			return;
 		}
 	}
@@ -356,14 +360,14 @@
 	ASSERT( self->magic == LAP_MAGIC, return;);
 	ASSERT( skb != NULL, return;);
 
-	DEBUG( 4, "irlap_data_request: tx_list=%d\n", 
+	DEBUG( 4, __FUNCTION__ "(), tx_list=%d\n", 
 		   skb_queue_len( &self->tx_list));
 
 #ifdef CONFIG_IRDA_COMPRESSION
 	if ( self->qos_tx.compression.value) {
 		skb = irlap_compress_frame( self, skb);
 		if ( !skb) {
-			DEBUG( 0, __FUNCTION__ "(), Compress error!\n");
+			DEBUG( 1, __FUNCTION__ "(), Compress error!\n");
 			return;
 		}
 	}
@@ -401,8 +405,7 @@
 		}
 		irlap_do_event( self, SEND_I_CMD, skb, NULL);
 	} else
-		skb_queue_tail( &self->tx_list, skb);
-	
+		skb_queue_tail( &self->tx_list, skb);	
 }
 
 /*
@@ -410,14 +413,26 @@
  *
  *    Request to disconnect connection by service user
  */
-void irlap_disconnect_request( struct irlap_cb *self) 
+void irlap_disconnect_request(struct irlap_cb *self) 
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(3, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LAP_MAGIC, return;);
-
-	irlap_do_event( self, DISCONNECT_REQUEST, NULL, NULL);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
+	
+	switch (self->state) {
+	case LAP_XMIT_P:        /* FALLTROUGH */
+	case LAP_XMIT_S:        /* FALLTROUGH */
+ 	case LAP_CONN:          /* FALLTROUGH */
+ 	case LAP_RESET_WAIT:    /* FALLTROUGH */
+ 	case LAP_RESET_CHECK:   
+		irlap_do_event(self, DISCONNECT_REQUEST, NULL, NULL);
+		break;
+	default:
+		DEBUG(0, __FUNCTION__ "(), disconnect pending!\n");
+		self->disconnect_pending = TRUE;
+		break;
+	}
 }
 
 /*
@@ -428,7 +443,7 @@
  */
 void irlap_disconnect_indication( struct irlap_cb *self, LAP_REASON reason) 
 {
-	DEBUG( 4, __FUNCTION__ "()\n"); 
+	DEBUG( 1, __FUNCTION__ "(), reason=%s\n", lap_reasons[reason]); 
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LAP_MAGIC, return;);
@@ -442,18 +457,18 @@
 	
 	switch( reason) {
 	case LAP_RESET_INDICATION:
-		DEBUG( 0, "Sending reset request!\n");
+		DEBUG( 1, __FUNCTION__ "(), Sending reset request!\n");
 		irlap_do_event( self, RESET_REQUEST, NULL, NULL);
 		break;
-	case LAP_NO_RESPONSE:		
-	case LAP_DISC_INDICATION:
-	case LAP_FOUND_NONE:
+	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);
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Reason %d not implemented!\n", 
+		DEBUG( 1, __FUNCTION__ "(), Reason %d not implemented!\n", 
 		       reason);
 	}
 }
@@ -471,24 +486,48 @@
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LAP_MAGIC, return;);
 	ASSERT( discovery != NULL, return;);
+	
+	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 = 6; /* Number of slots */
+		
+		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 < 2) {
+			DEBUG( 1, __FUNCTION__ 
+			       "(), to low value for slot timeout!\n");
+			sysctl_slot_timeout = 2;
+		}
+		/* 
+		 * Highest value is actually 8, but we allow higher since
+		 * some devices seems to require it.
+		 */
+		if ( sysctl_slot_timeout > 16) {
+			DEBUG( 1, __FUNCTION__ 
+			       "(), to high value for slot timeout!\n");
+			sysctl_slot_timeout = 16;
+		}
+
+		self->slot_timeout = sysctl_slot_timeout;
+		
 		irlap_do_event( self, DISCOVERY_REQUEST, NULL, &info);
 	} else { 
  		DEBUG( 4, __FUNCTION__ 
- 			"(), discovery only possible in NDM mode\n");
+		       "(), discovery only possible in NDM mode\n");
 		irlap_discovery_confirm( self, NULL);
  	} 
 }
@@ -506,6 +545,14 @@
 	
 	ASSERT( self->notify.instance != NULL, return;);
 	
+	/* 
+	 * Check for successful discovery, since we are then allowed to clear 
+	 * 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);
+	
 	/* Inform IrLMP */
 	irlmp_link_discovery_confirm( self->notify.instance, discovery_log);
 	
@@ -552,7 +599,6 @@
 	default:
 		break;
 	}
-	/* TODO: layering violation! */
 	irlmp_status_indication( quality_of_link, NO_CHANGE);
 }
 
@@ -564,7 +610,7 @@
  */
 void irlap_reset_indication( struct irlap_cb *self)
 {
-	DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG( 1, __FUNCTION__ "()\n");
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LAP_MAGIC, return;);
@@ -583,7 +629,7 @@
  */
 void irlap_reset_confirm(void)
 {
-	DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG( 1, __FUNCTION__ "()\n");
 }
 
 /*
@@ -672,7 +718,7 @@
 
 	/*  ns as expected?  */
 	if ( ns == self->vr) {
-		DEBUG( 4, "*** irlap_validate_ns_received: expected!\n");
+		DEBUG( 4, __FUNCTION__ "(), expected!\n");
 		return NS_EXPECTED;
 	}
 	/*
@@ -696,7 +742,7 @@
 
 	/*  nr as expected?  */
 	if ( nr == self->vs) {
-		DEBUG( 4, "*** irlap_validate_nr_received: expected!\n");
+		DEBUG( 4, __FUNCTION__ "(), expected!\n");
 		return NR_EXPECTED;
 	}
 
@@ -724,7 +770,7 @@
  */
 void irlap_initiate_connection_state( struct irlap_cb *self) 
 {
-	DEBUG( 4, "irlap_initiate_connection_state()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 	
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LAP_MAGIC, return;);
@@ -818,26 +864,26 @@
  *    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, int speed)
 {
-	DEBUG( 4, __FUNCTION__ "(), setting speed to %d\n", speed);
+	DEBUG(4, __FUNCTION__ "(), setting speed to %d\n", speed);
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
 
-	if ( !self->irdev) {
-		DEBUG( 0, __FUNCTION__ "(), driver missing!\n");
+	if (!self->irdev) {
+		DEBUG( 1, __FUNCTION__ "(), driver missing!\n");
 		return;
 	}
 
-	irda_device_change_speed( self->irdev, speed);
+	irda_device_change_speed(self->irdev, speed);
 
 	self->qos_rx.baud_rate.value = speed;
 	self->qos_tx.baud_rate.value = speed;
 }
 
 #ifdef CONFIG_IRDA_COMPRESSION
-void irlap_init_comp_qos_capabilities( struct irlap_cb *self)
+void irlap_init_comp_qos_capabilities(struct irlap_cb *self)
 {
 	struct irda_compressor *comp;
 	__u8 mask; /* Current bit tested */
@@ -888,8 +934,8 @@
  *    IrLAP itself. Normally, IrLAP will not specify any values, but it can
  *    be used to restrict certain values.
  */
-void irlap_init_qos_capabilities( struct irlap_cb *self, 
-				  struct qos_info *qos_user)
+void irlap_init_qos_capabilities(struct irlap_cb *self,
+				 struct qos_info *qos_user)
 {
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LAP_MAGIC, return;);
@@ -911,8 +957,8 @@
 	 *  allowed to supply these values. We check each parameter since the
 	 *  user may not have set all of them.
 	 */
-	if ( qos_user != NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Found user specified QoS!\n");
+	if (qos_user) {
+		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;
@@ -966,6 +1012,7 @@
 	self->bofs_count = 11;
 
 	/* Use these until connection has been made */
+	self->slot_timeout = sysctl_slot_timeout;
 	self->final_timeout = FINAL_TIMEOUT;
 	self->poll_timeout = POLL_TIMEOUT;
 	self->wd_timeout = WD_TIMEOUT;
@@ -974,6 +1021,8 @@
 	self->qos_tx.additional_bofs.value = 11;
 
 	irlap_flush_all_queues( self);
+
+	self->disconnect_pending = FALSE;
 }
 
 /*
@@ -982,8 +1031,8 @@
  *    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, 
+				       struct qos_info *qos) 
 {
 	DEBUG( 4, __FUNCTION__ "()\n");
 	
@@ -1010,15 +1059,13 @@
 	 *  TODO: these values should be calculated from the final timer
          *  as well
 	 */
-	if ( qos->link_disc_time.value == 3)
+	if (qos->link_disc_time.value == 3)
 		self->N1 = 0;
 	else
-		/* self->N1 = 6; */
 		self->N1 = 3000 / qos->max_turn_time.value;
 	
 	DEBUG( 4, "Setting N1 = %d\n", self->N1);
 	
-	/* self->N2 = qos->link_disc_time.value * 2; */
 	self->N2 = qos->link_disc_time.value * 1000 / qos->max_turn_time.value;
 	DEBUG( 4, "Setting N2 = %d\n", self->N2);
 
@@ -1033,7 +1080,7 @@
 
 #ifdef CONFIG_IRDA_COMPRESSION
 	if ( qos->compression.value) {
-		DEBUG( 0, __FUNCTION__ "(), Initializing compression\n");
+		DEBUG( 1, __FUNCTION__ "(), Initializing compression\n");
 		irda_set_compression( self, qos->compression.value);
 
 		irlap_compressor_init( self, 0);
@@ -1065,7 +1112,7 @@
 		ASSERT( self != NULL, return -ENODEV;);
 		ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
 
-		len += sprintf( buf+len, "IrLAP[%d] <-> %s ",
+		len += sprintf( buf+len, "irlap%d <-> %s ",
 				i++, self->irdev->name);
 		len += sprintf( buf+len, "state: %s\n", 
 				irlap_state[ self->state]);
diff -u --recursive --new-file v2.2.2/linux/net/irda/irlap_comp.c linux/net/irda/irlap_comp.c
--- v2.2.2/linux/net/irda/irlap_comp.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/irlap_comp.c	Sun Mar  7 15:26:44 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Fri Oct  9 09:18:07 1998
- * Modified at:   Mon Dec 14 11:55:27 1998
+ * Modified at:   Mon Feb  8 01:23:52 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       ppp.c, isdn_ppp.c
  * 
@@ -81,8 +81,7 @@
 	if ( !node) {
 		DEBUG( 0, __FUNCTION__ "(), compressor not found!\n");
 		return;
-	}
-	
+	}	
 	kfree( node);
 }
 
@@ -99,7 +98,7 @@
 
 	__u8 options[CILEN_DEFLATE];
 
-	DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 
 	ASSERT( self != NULL, return -ENODEV;);
 	ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
@@ -180,7 +179,7 @@
 	int debug = TRUE;
 	__u8 options[CILEN_DEFLATE];
 
-	DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LAP_MAGIC, return;);
@@ -240,8 +239,8 @@
 	
 	ASSERT( skb != NULL, return NULL;);
 	
-	DEBUG( 0, __FUNCTION__ "() skb->len=%d, jiffies=%ld\n", (int) skb->len,
-	       jiffies);
+	DEBUG(4, __FUNCTION__ "() skb->len=%d, jiffies=%ld\n", (int) skb->len,
+	      jiffies);
 
 	ASSERT( self != NULL, return NULL;);
 	ASSERT( self->magic == LAP_MAGIC, return NULL;);
@@ -267,7 +266,7 @@
 						 skb->data, new_skb->data, 
 						 skb->len, new_skb->len);
 	if( count <= 0) {
-		DEBUG( 0, __FUNCTION__ "(), Unable to compress frame!\n");
+		DEBUG(4, __FUNCTION__ "(), Unable to compress frame!\n");
 		dev_kfree_skb( new_skb);
 
 		/* Tell peer that this frame is not compressed */
@@ -284,8 +283,8 @@
 
 	dev_kfree_skb( skb);
 	
-	DEBUG( 0, __FUNCTION__ "() new_skb->len=%d\n, jiffies=%ld", 
-	       (int) new_skb->len, jiffies);
+	DEBUG(4, __FUNCTION__ "() new_skb->len=%d\n, jiffies=%ld", 
+	      (int) new_skb->len, jiffies);
 	
 	return new_skb;
 }
@@ -336,7 +335,7 @@
 	count = irda_decompress( self->decompressor.state, skb->data, 
 				 skb->len, new_skb->data, new_skb->len);
 	if ( count <= 0) {
-		DEBUG( 0, __FUNCTION__ "(), Unable to decompress frame!\n");
+		DEBUG( 4, __FUNCTION__ "(), Unable to decompress frame!\n");
 		
 		dev_kfree_skb( new_skb);
 		return skb;
@@ -344,7 +343,7 @@
 
 	skb_trim( new_skb, count);
 	
-	DEBUG( 0, __FUNCTION__ "() new_skb->len=%d\n", (int) new_skb->len);
+	DEBUG( 4, __FUNCTION__ "() new_skb->len=%d\n", (int) new_skb->len);
 
 	return new_skb;
 }
diff -u --recursive --new-file v2.2.2/linux/net/irda/irlap_event.c linux/net/irda/irlap_event.c
--- v2.2.2/linux/net/irda/irlap_event.c	Wed Jan 20 23:14:07 1999
+++ linux/net/irda/irlap_event.c	Sun Mar  7 15:26:44 1999
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irlap_event.c
- * Version:       0.1
+ * Version:       0.8
  * 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:   Tue Jan 19 22:58:45 1999
+ * Modified at:   Thu Feb 11 00:38:58 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>,
@@ -71,7 +71,7 @@
 static int irlap_state_reset_check( struct irlap_cb *, IRLAP_EVENT event, 
 				    struct sk_buff *, struct irlap_info *);
 
-static char *irlap_event[] = {
+static const char *irlap_event[] = {
 	"DISCOVERY_REQUEST",
 	"CONNECT_REQUEST",
 	"CONNECT_RESPONSE",
@@ -103,7 +103,7 @@
 	"BACKOFF_TIMER_EXPIRED",
 };
 
-char *irlap_state[] = {
+const char *irlap_state[] = {
 	"LAP_NDM",
 	"LAP_QUERY",
 	"LAP_REPLY",
@@ -198,53 +198,63 @@
 /*
  * Function irlap_do_event (event, skb, info)
  *
- *    Rushes through the state machine without any delay. If state = XMIT
+ *    Rushes through the state machine without any delay. If state == XMIT
  *    then send queued data frames. 
  */
 void irlap_do_event( struct irlap_cb *self, IRLAP_EVENT event, 
 		     struct sk_buff *skb, struct irlap_info *info) 
 {
 	int ret;
-	int iter = 0;
 	
-	if ( !self || self->magic != LAP_MAGIC) {
-		DEBUG( 0, "irlap_do_event: bad pointer *self\n");
+	if ( !self || self->magic != LAP_MAGIC)
 		return;
-	}
-		
-  	DEBUG( 4, "irlap_do_event: event = %s, state = %s\n", 
+	
+  	DEBUG( 4, __FUNCTION__ "(), event = %s, state = %s\n", 
 	       irlap_event[ event], irlap_state[ self->state]); 
-
-	/* 
-	 *  Do event, this implementation does not deal with pending events. 
-	 *  This is because I don't see the need for this. DB
-	 */
+	
 	ret = (*state[ self->state]) ( self, event, skb, info);
 	
 	/* 
-	 *  Check if we have switched to XMIT state? If so, send queued data 
-	 *  frames if any, if -1 is returned it means that we are not allowed 
-	 *  to send any more frames.  
+	 *  Check if there are any pending events that needs to be executed
 	 */
-	while (( self->state == LAP_XMIT_P) || ( self->state == LAP_XMIT_S)) { 
-		if ( skb_queue_len( &self->tx_list) > 0) {
+	switch (self->state) {
+	case LAP_XMIT_P: /* FALLTHROUGH */
+	case LAP_XMIT_S:
+		/* 
+		 * Check if there are any queued data frames, and do not
+		 * 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)) {
+			/* Try to send away all queued data frames */
+			while ((skb = skb_dequeue(&self->tx_list)) != NULL) {
+				ret = (*state[ self->state])(self, SEND_I_CMD,
+							     skb, NULL);
+				if ( ret == -EPROTO)
+					break; /* Try again later! */
+			}
+		} else if (self->disconnect_pending) {
+			DEBUG(0, __FUNCTION__ "(), disconnecting!\n");
+			self->disconnect_pending = FALSE;
 			
-			struct sk_buff *skb = skb_dequeue( &self->tx_list); 
-			ASSERT( skb != NULL, return;);
+			ret = (*state[self->state])(self, DISCONNECT_REQUEST,
+						    NULL, NULL);
+		}
+		break;
+	case LAP_NDM:
+		/* Check if we should try to connect */
+		if (self->connect_pending) {
+			self->connect_pending = FALSE;
 			
-			DEBUG( 4, "** Sending queued data frames\n");
-			ret = (*state[ self->state])( self, SEND_I_CMD, skb,
-						      NULL);
-			if ( ret == -EPROTO)
-				return; /* Try again later! */
-		} else
-			return;
-
-		/* Just in case :-) */
-		if (iter++ > 100) {
-			DEBUG( 0, __FUNCTION__ "(), *** breaking!! ***\n");
-			return;
+			ret = (*state[self->state])(self, CONNECT_REQUEST, 
+						    NULL, NULL);
 		}
+		break;
+/* 	case LAP_CONN: */
+/* 	case LAP_RESET_WAIT: */
+/* 	case LAP_RESET_CHECK: */
+	default:
+		break;
 	}
 }
 
@@ -256,10 +266,8 @@
  */
 void irlap_next_state( struct irlap_cb *self, IRLAP_STATE state) 
 {	
-	if ( !self || self->magic != LAP_MAGIC) {
-		DEBUG( 4, "irlap_next_state: I have lost myself!\n");
+	if ( !self || self->magic != LAP_MAGIC)
 		return;
-	}
 	
 	DEBUG( 4, "next LAP state = %s\n", irlap_state[ state]);
 
@@ -308,7 +316,7 @@
 			irlap_send_snrm_frame( self, &self->qos_rx);
 			
 			/* Start Final-bit timer */
-			irlap_start_final_timer( self, self->final_timeout);
+			irlap_start_final_timer(self, self->final_timeout);
 
 			self->retry_count = 0;
 			irlap_next_state( self, LAP_SETUP);
@@ -328,7 +336,7 @@
 		ASSERT( info != NULL, return -1;);
 
 	 	if ( irda_device_is_media_busy( self->irdev)) {
- 			DEBUG(0, "irlap_discovery_request: media busy!\n"); 
+ 			DEBUG(0, __FUNCTION__ "(), media busy!\n"); 
 			/* irlap->log.condition = MEDIA_BUSY; */
 			
 			/* Always switch state before calling upper layers */
@@ -345,7 +353,7 @@
 						info->discovery);
 		self->s++;
 
-		irlap_start_slot_timer( self, SLOT_TIMEOUT);
+		irlap_start_slot_timer( self, self->slot_timeout);
 		irlap_next_state( self, LAP_QUERY);
 		break;
 
@@ -424,7 +432,7 @@
 							self->s, TRUE,
 							self->discovery_cmd);
 			self->s++;
-			irlap_start_slot_timer( self, SLOT_TIMEOUT);
+			irlap_start_slot_timer( self, self->slot_timeout);
 			
 			/* Keep state */
 			irlap_next_state( self, LAP_QUERY);
@@ -477,8 +485,8 @@
 
 	switch( event) {
 	case QUERY_TIMER_EXPIRED:
-		DEBUG( 0, __FUNCTION__ "(), QUERY_TIMER_EXPIRED <%ld>\n",
-		       jiffies);
+		DEBUG(2, __FUNCTION__ "(), QUERY_TIMER_EXPIRED <%ld>\n",
+		      jiffies);
 		irlap_next_state( self, LAP_NDM);
 		break;
 	case RECV_DISCOVERY_XID_CMD:
@@ -510,12 +518,12 @@
 		dev_kfree_skb( skb);
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %d, %s\n", event,
-		       irlap_event[event]);
+		DEBUG(1, __FUNCTION__ "(), Unknown event %d, %s\n", event,
+		      irlap_event[event]);
 
-		if ( skb != NULL)
+		if ( skb)
 			dev_kfree_skb( skb);
-
+		
 		ret = -1;
 		break;
 	}
@@ -571,20 +579,20 @@
 		irlap_next_state( self, LAP_NDM);
 #endif
 		break;
-
+		
 	case RECV_DISCOVERY_XID_CMD:
 		DEBUG( 3, __FUNCTION__ "(), event RECV_DISCOVER_XID_CMD!\n");
 		irlap_next_state( self, LAP_NDM);
 		break;
-
+		
 	case DISCONNECT_REQUEST:
 		irlap_send_dm_frame( self);
 		irlap_next_state( self, LAP_CONN);
 		break;
 
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %d, %s\n", event, 
-		       irlap_event[event]);
+		DEBUG(1, __FUNCTION__ "(), Unknown event %d, %s\n", event, 
+		      irlap_event[event]);
 		ret = -1;
 		break;
 	}
@@ -682,7 +690,9 @@
 
 		irlap_apply_connection_parameters( self, &self->qos_tx); 
 		self->retry_count = 0;
-		irlap_send_rr_frame( self, CMD_FRAME);
+		
+		/* This frame will just be sent at the old speed */
+		/* irlap_send_rr_frame( self, CMD_FRAME); */
 
 		irlap_start_final_timer( self, self->final_timeout/2);
 		irlap_next_state( self, LAP_NRM_P);
@@ -724,9 +734,10 @@
 /*
  * Function irlap_state_xmit_p (self, event, skb, info)
  * 
- *    XMIT, Only the primary station has right to transmit, and we therefor
- *    do not expect to receive any transmissions from other stations.  
- *
+ *    XMIT, Only the primary station has right to transmit, and we
+ *    therefore do not expect to receive any transmissions from other
+ *    stations.
+ * 
  */
 static int irlap_state_xmit_p( struct irlap_cb *self, IRLAP_EVENT event, 
 			       struct sk_buff *skb, struct irlap_info *info) 
@@ -785,6 +796,12 @@
 				DEBUG( 4, __FUNCTION__ "(), window <= 1\n");
 				irlap_send_data_primary_poll( self, skb);
 				irlap_next_state( self, LAP_NRM_P);
+				
+				/* 
+				 * Make sure state machine does not try to send
+				 * any more frames 
+				 */
+				ret = -EPROTO;
 			}
 #ifdef CONFIG_IRDA_FAST_RR
 			/* Peer may want to reply immediately */
@@ -817,7 +834,8 @@
 		irlap_next_state( self, LAP_NRM_P);
 		break;
 	default:
-		/* DEBUG( 0, "irlap_state_xmit: Unknown event"); */
+		DEBUG(0, __FUNCTION__ "(), Unknown event %s\n", 
+		      irlap_event[event]);
 		ret = -EINVAL;
 		break;
 	}
@@ -834,7 +852,7 @@
 {
 	int ret = 0;
 
-	DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG(1, __FUNCTION__ "()\n");
 	
 	ASSERT( self != NULL, return -1;);
 	ASSERT( self->magic == LAP_MAGIC, return -1;);	
@@ -870,7 +888,7 @@
 		}
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
+		DEBUG(1, __FUNCTION__ "(), Unknown event %d\n", event);
 		ret = -1;
 		break;	
 	}
@@ -961,8 +979,8 @@
 			/* Keep state */
 			irlap_next_state( self, LAP_NRM_P);
 		} else if ( ret == NR_INVALID) {
-			DEBUG( 0, "irlap_state_nrm_p: received RR with "
-			       "invalid nr !\n");
+			DEBUG(1, "irlap_state_nrm_p: received RR with "
+			      "invalid nr !\n");
 			del_timer( &self->final_timer);
 
 			irlap_next_state( self, LAP_RESET_WAIT);
@@ -1181,8 +1199,8 @@
 			}
 			break;
 		}
-		DEBUG( 0, "irlap_state_nrm_p: Not implemented!\n");
-		DEBUG( 0, "event=%s, ns_status=%d, nr_status=%d\n", 
+		DEBUG(1, __FUNCTION__ "(), Not implemented!\n");
+		DEBUG(1, __FUNCTION__ "(), event=%s, ns_status=%d, nr_status=%d\n", 
 		       irlap_event[ event], ns_status, nr_status);
 		break;
 	case RECV_UI_FRAME:
@@ -1257,7 +1275,7 @@
 		}
 		break;
 	case RECV_DISC_FRAME: /* FIXME: Check how this is in the standard! */
-		DEBUG( 0, __FUNCTION__ "(), RECV_DISC_FRAME()\n");
+		DEBUG(1, __FUNCTION__ "(), RECV_DISC_FRAME()\n");
 
 		/* Always switch state before calling upper layers */
 		irlap_next_state( self, LAP_NDM);
@@ -1277,7 +1295,8 @@
 		
 		break;
 	default:
-		/* DEBUG( 0, "irlap_state_nrm_p: Unknown event"); */
+		DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
+		      irlap_event[event]);
 		ret = -1;
 		break;
 	}
@@ -1322,8 +1341,8 @@
 		irlap_next_state( self, LAP_PCLOSE);
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %s\n", 
-		       irlap_event[event]);
+		DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
+		      irlap_event[event]);
 		ret = -1;
 		break;	
 	}
@@ -1403,8 +1422,8 @@
 		break;
 
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %s\n", 
-		       irlap_event[ event]);
+		DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
+		      irlap_event[ event]);
 		ret = -1;
 		break;	
 	}
@@ -1468,16 +1487,22 @@
 				DEBUG( 4, "(), window <= 1\n");
 				irlap_send_data_secondary_final( self, skb);
 				irlap_next_state( self, LAP_NRM_S);
+
+				/* 
+				 * Make sure state machine does not try to send
+				 * any more frames 
+				 */
+				ret = -EPROTO;
 			}
 		} else {
-			DEBUG( 0, __FUNCTION__ "(), Unable to send!\n");
+			DEBUG(1, __FUNCTION__ "(), Unable to send!\n");
 			skb_queue_head( &self->tx_list, skb);
 			ret = -EPROTO;
 		}
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %s\n", 
-		       irlap_event[ event]);
+		DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
+		      irlap_event[ event]);
 		ret = -EINVAL;
 		break;
 	}
@@ -1543,8 +1568,7 @@
 			/* Keep state */
 			irlap_next_state( self, LAP_NRM_S); 
 		} else {
-			DEBUG( 0, __FUNCTION__ "(), "
-			       "invalid nr not implemented!\n");
+			DEBUG(1, __FUNCTION__ "(), invalid nr not implemented!\n");
 		} 
 		if ( skb)
 			dev_kfree_skb( skb);
@@ -1731,7 +1755,7 @@
 		break;
 	case RECV_SNRM_CMD:
 		del_timer( &self->wd_timer);
-		DEBUG( 0, "irlap_state_nrm_s: received SNRM cmd\n");
+		DEBUG(1, __FUNCTION__ "(), received SNRM cmd\n");
 		irlap_next_state( self, LAP_RESET_CHECK);
 
 		irlap_reset_indication( self);
@@ -1743,7 +1767,8 @@
 		 *  Wait until retry_count * n matches negotiated threshold/
 		 *  disconnect time (note 2 in IrLAP p. 82)
 		 */
-		DEBUG( 0, "retry_count = %d\n", self->retry_count);
+		DEBUG(1, __FUNCTION__ "(), retry_count = %d\n", 
+		      self->retry_count);
 
 		if (( self->retry_count < (self->N2/2))  && 
 		    ( self->retry_count != self->N1/2)) {
@@ -1800,8 +1825,8 @@
 		break;
 
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %d, (%s)\n", 
-		       event, irlap_event[event]);
+		DEBUG(1, __FUNCTION__ "(), Unknown event %d, (%s)\n", 
+		      event, irlap_event[event]);
 		ret = -1;
 		break;
 	}
@@ -1828,7 +1853,7 @@
 {
 	int ret = 0;
 
-	DEBUG( 0, __FUNCTION__ "(), event=%s\n", irlap_event[ event]); 
+	DEBUG(1, __FUNCTION__ "(), event=%s\n", irlap_event[ event]); 
 
 	ASSERT( self != NULL, return -ENODEV;);
 	ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
@@ -1848,8 +1873,8 @@
 		irlap_start_wd_timer( self, WD_TIMEOUT);
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %d, (%s)\n", 
-		       event, irlap_event[event]);
+		DEBUG(1, __FUNCTION__ "(), Unknown event %d, (%s)\n", 
+		      event, irlap_event[event]);
 		ret = -1;
 		break;
 	}
diff -u --recursive --new-file v2.2.2/linux/net/irda/irlap_frame.c linux/net/irda/irlap_frame.c
--- v2.2.2/linux/net/irda/irlap_frame.c	Wed Jan 20 23:14:07 1999
+++ linux/net/irda/irlap_frame.c	Sun Mar  7 15:26:44 1999
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irlap_frame.c
- * Version:       0.3
+ * Version:       0.8
  * Description:   Build and transmit IrLAP frames
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Aug 19 10:27:26 1997
- * Modified at:   Tue Jan 19 22:58:13 1999
+ * Modified at:   Sat Feb 20 01:40:14 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Resrved.
@@ -26,7 +26,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 
-#include <linux/skbuff.h>
 #include <linux/if.h>
 #include <linux/if_ether.h>
 #include <linux/netdevice.h>
@@ -49,7 +48,7 @@
  *    need to do this since it's per packet relevant information.
  *
  */
-__inline__ void irlap_insert_mtt( struct irlap_cb *self, struct sk_buff *skb)
+void irlap_insert_mtt( struct irlap_cb *self, struct sk_buff *skb)
 {
 	struct irlap_skb_cb *cb;
 
@@ -76,18 +75,41 @@
 }
 
 /*
+ * Function irlap_queue_xmit (self, skb)
+ *
+ *    A little wrapper for dev_queue_xmit, so we can insert some common
+ *    code into it.
+ */
+void irlap_queue_xmit(struct irlap_cb *self, struct sk_buff *skb)
+{
+	/* Some init stuff */
+	skb->dev = self->netdev;
+	skb->h.raw = skb->nh.raw = skb->mac.raw = skb->data;
+ 	skb->protocol = htons(ETH_P_IRDA);
+
+	/* 
+	 * Insert MTT (min. turn time) into skb, so that the device driver 
+	 * knows which MTT to use 
+	 */
+	irlap_insert_mtt(self, skb);
+	
+	dev_queue_xmit(skb);
+	self->stats.tx_packets++;
+}
+
+/*
  * Function irlap_send_snrm_cmd (void)
  *
  *    Transmits a connect SNRM command frame
  */
-void irlap_send_snrm_frame( struct irlap_cb *self, struct qos_info *qos) 
+void irlap_send_snrm_frame(struct irlap_cb *self, struct qos_info *qos) 
 {
 	struct sk_buff *skb;
 	__u8 *frame;
 	int len;
 	int n;
 
-	DEBUG( 4, "irlap_send_snrm_cmd()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LAP_MAGIC, return;);
@@ -95,14 +117,11 @@
 	n = 0;
 
 	/* Allocate frame */
-	skb = dev_alloc_skb( 64);
-	if (skb == NULL) {
-		DEBUG( 0,"irlap_send_snrm_cmd: "
-		       "Could not allocate an sk_buff of length %d\n", 64);
+	skb = dev_alloc_skb(64);
+	if (!skb)
 		return;
-	}
 
-	skb_put( skb, 2); 
+	skb_put(skb, 2); 
 	frame = skb->data;
 
 	/* Insert address field */
@@ -116,23 +135,20 @@
 	 *  If we are establishing a connection then insert QoS paramerters 
 	 */
 	if (qos) {
-		skb_put( skb, 9); /* 21 left */
-		memcpy( frame+n, &self->saddr, 4); n += 4;
-		memcpy( frame+n, &self->daddr, 4); n += 4;
+		skb_put(skb, 9); /* 21 left */
+		*((__u32 *)(frame+n)) = cpu_to_le32(self->saddr); n += 4;
+		*((__u32 *)(frame+n)) = cpu_to_le32(self->daddr); n += 4;
+
+/* 		memcpy(frame+n, &self->saddr, 4); n += 4; */
+/* 		memcpy(frame+n, &self->daddr, 4); n += 4; */
 
 		frame[n++] = self->caddr;
 				
-		/* skb_put( skb, 21); */
-		len = irda_insert_qos_negotiation_params( qos, frame+n);
+		len = irda_insert_qos_negotiation_params(qos, frame+n);
 		/* Should not be dangerous to do this afterwards */
-		skb_put( skb, len);
+		skb_put(skb, len);
 	}
-	skb->dev = self->netdev;
-	skb->h.raw = skb->data;
-	irlap_insert_mtt( self, skb);
-
-	dev_queue_xmit( skb);
-	self->stats.tx_packets++;
+	irlap_queue_xmit(self, skb);
 }
 
 /*
@@ -154,7 +170,8 @@
 	frame = ( struct snrm_frame *) skb->data;
 
 	/* Copy peer device address */
-	memcpy( &info->daddr, &frame->saddr, 4);
+	/* memcpy( &info->daddr, &frame->saddr, 4); */
+	info->daddr = le32_to_cpu(frame->saddr);
 
 	/* Copy connection address */
 	info->caddr = frame->ncaddr;
@@ -168,29 +185,25 @@
  *    Send UA (Unnumbered Acknowledgement) frame
  *
  */
-void irlap_send_ua_response_frame( struct irlap_cb *self, 
-				   struct qos_info *qos)
+void irlap_send_ua_response_frame(struct irlap_cb *self, struct qos_info *qos)
 {
 	struct sk_buff *skb;
 	__u8 *frame;
 	int n;
 	int len;
 	
-	DEBUG( 4, __FUNCTION__ "() <%ld>\n", jiffies);
+	DEBUG(2, __FUNCTION__ "() <%ld>\n", jiffies);
 	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
 
 	skb = NULL;
 	n = 0;
 
 	/* Allocate frame */
-	skb =  dev_alloc_skb( 64);
-	if (skb == NULL) {
-		DEBUG( 0, __FUNCTION__
-		       "Could not allocate an sk_buff of length %d\n", 64);
+	skb =  dev_alloc_skb(64);
+	if (!skb)
 		return;
-	}
 
 	skb_put( skb, 10);
 	frame = skb->data;
@@ -198,21 +211,20 @@
 	/* Build UA response */
 	frame[n++] = self->caddr;
  	frame[n++] = UA_RSP | PF_BIT;
-	memcpy( frame+n, &self->saddr, 4); n += 4;
-	memcpy( frame+n, &self->daddr, 4); n += 4;
+
+	*((__u32 *)(frame+n)) = cpu_to_le32(self->saddr); n += 4;
+	*((__u32 *)(frame+n)) = cpu_to_le32(self->daddr); n += 4;
+
+/* 	memcpy( frame+n, &self->saddr, 4); n += 4; */
+/* 	memcpy( frame+n, &self->daddr, 4); n += 4; */
 	
 	/* Should we send QoS negotiation parameters? */
-	if ( qos) {
-		len = irda_insert_qos_negotiation_params( qos, frame+n);
-		skb_put( skb, len);
+	if (qos) {
+		len = irda_insert_qos_negotiation_params(qos, frame+n);
+		skb_put(skb, len);
 	}
 
-	skb->dev = self->netdev;
-	skb->h.raw = skb->data;
-	irlap_insert_mtt( self, skb);
-
-	dev_queue_xmit( skb);
-	self->stats.tx_packets++;
+	irlap_queue_xmit(self, skb);
 }
 
 
@@ -230,12 +242,9 @@
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LAP_MAGIC, return;);
 
-	skb =  dev_alloc_skb( 32);
-	if (skb == NULL) {
-		DEBUG( 0,"irlap_send_disc_frame: "
-		       "Could not allocate an sk_buff of length %d\n", 64);
+	skb = dev_alloc_skb(32);
+	if (!skb)
 		return;
-	}
 
 	skb_put( skb, 2);
 	frame = skb->data;
@@ -246,13 +255,8 @@
 		frame[0] = self->caddr;
 
 	frame[1] = DM_RSP | PF_BIT;
-	
-	skb->dev = self->netdev;
-	skb->h.raw = skb->data;
-	irlap_insert_mtt( self, skb);
 
-	dev_queue_xmit( skb);
-	self->stats.tx_packets++;
+	irlap_queue_xmit(self, skb);	
 }
 
 /*
@@ -261,33 +265,27 @@
  *    Send disconnect (DISC) frame
  *
  */
-void irlap_send_disc_frame( struct irlap_cb *self) 
+void irlap_send_disc_frame(struct irlap_cb *self) 
 {
 	struct sk_buff *skb = NULL;
 	__u8 *frame;
 	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LAP_MAGIC, return;);
+	DEBUG(3, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
 
-	skb =  dev_alloc_skb( 32);
-	if (skb == NULL) {
-		DEBUG( 0,"irlap_send_disc_frame: "
-		       "Could not allocate an sk_buff of length %d\n", 64);
+	skb = dev_alloc_skb(32);
+	if (!skb)
 		return;
-	}
 
-	skb_put( skb, 2);
+	skb_put(skb, 2);
 	frame = skb->data;
 	
 	frame[0] = self->caddr | CMD_FRAME;
 	frame[1] = DISC_CMD | PF_BIT;
-	
-	skb->dev = self->netdev;
-	skb->h.raw = skb->data;
-	irlap_insert_mtt( self, skb);
 
-	dev_queue_xmit( skb);
-	self->stats.tx_packets++;
+	irlap_queue_xmit(self, skb);
 }
 
 /*
@@ -309,12 +307,9 @@
 	ASSERT( self->magic == LAP_MAGIC, return;);
 	ASSERT( discovery != NULL, return;);
 
-	skb =  dev_alloc_skb( 64);
-	if (skb == NULL) {
-		DEBUG( 0,"irlap_send_discovery_xid_frame: "
-		       "Could not allocate an sk_buff of length %d\n", 64);
+	skb = dev_alloc_skb(64);
+	if (!skb)
 		return;
-	}
 
 	skb_put( skb, 14);
 	frame = ( struct xid_frame *) skb->data;
@@ -328,12 +323,15 @@
 	}
 	frame->ident = XID_FORMAT;
 
-	memcpy( &frame->saddr, &self->saddr, 4);
+	frame->saddr = cpu_to_le32(self->saddr);
+/* 	memcpy( &frame->saddr, &self->saddr, 4); */
 
 	if ( command)
-		memcpy( &frame->daddr, &bcast, 4);
+		/* memcpy( &frame->daddr, &bcast, 4); */
+		frame->daddr = cpu_to_le32(bcast);
 	else
-		memcpy( &frame->daddr, &self->daddr, 4);	
+		/* memcpy( &frame->daddr, &self->daddr, 4); */
+		frame->daddr = cpu_to_le32(self->daddr);
 	
 	switch( S) {
 	case 1:
@@ -364,7 +362,7 @@
 	if ( !command || ( frame->slotnr == 0xff)) {
 		int i;
 
-		if( discovery->hint[0] & HINT_EXTENSION)
+		if (discovery->hint[0] & HINT_EXTENSION)
 			skb_put( skb, 3+discovery->info_len);
 		else
 			skb_put( skb, 2+discovery->info_len);
@@ -382,15 +380,9 @@
 			discovery->info_len);
 
 	} 
-
 	ASSERT( self->netdev != NULL, return;);
 
-	skb->dev = self->netdev;
-	skb->h.raw = skb->data;
-	irlap_insert_mtt( self, skb);
-
-	dev_queue_xmit( skb);
-	self->stats.tx_packets++;
+	irlap_queue_xmit(self, skb);
 }
 
 /*
@@ -479,7 +471,8 @@
 	xid = (struct xid_frame *) skb->data;
 	
 	/* Copy peer device address */
-	memcpy( &info->daddr, &xid->saddr, 4);
+	/* memcpy( &info->daddr, &xid->saddr, 4); */
+	info->daddr = le32_to_cpu(xid->saddr);
 
 	switch ( xid->flags & 0x03) {
 	case 0x00:
@@ -567,13 +560,11 @@
 		self->recycle_rr_skb = NULL;
 	}
 #endif      
-	if ( !skb) {
+	if (!skb) {
 		skb = dev_alloc_skb( 32);
-		if (skb == NULL) {
-			printk( KERN_WARNING "irlap_send_rr_frame: "
-				"Could not allocate an skb of length %d\n", 32);
+		if (!skb)
 			return;
-		}
+   
 		skb_put( skb, 2);
 	}
 	ASSERT( skb->len == 2, return;);
@@ -585,14 +576,9 @@
 
 	frame[1] = RR | PF_BIT | (self->vr << 5);
 
-   	DEBUG( 4, __FUNCTION__ "(), vr=%d, %ld\n", self->vr, jiffies); 
-
-	skb->dev = self->netdev;
-	skb->h.raw = skb->data;
-	irlap_insert_mtt( self, skb);
+   	DEBUG(4, __FUNCTION__ "(), vr=%d, %ld\n", self->vr, jiffies); 
 
-	dev_queue_xmit( skb);
-	self->stats.tx_packets++;
+	irlap_queue_xmit(self, skb);
 }
 
 /*
@@ -613,7 +599,7 @@
 	frame = skb->data;
 	info->nr = frame[1] >> 5;
 
-	DEBUG( 4, __FUNCTION__ "(), nr=%d, %ld\n", info->nr, jiffies);
+	DEBUG(4, __FUNCTION__ "(), nr=%d, %ld\n", info->nr, jiffies);
 
 	/*
 	 *  Make sure the state-machine is in the right state for receiving, 
@@ -660,11 +646,8 @@
 	ASSERT( self->magic == LAP_MAGIC, return;);
 
 	skb = dev_alloc_skb( 32);
-	if (skb == NULL) {
-		printk( KERN_WARNING "irlap_send_frmr_frame: "
-			"Could not allocate an sk_buff of length %d\n", 32);
+	if (!skb)
 		return;
-	}
 
 	skb_put( skb, 2);
 	frame = skb->data;
@@ -680,12 +663,7 @@
 
    	DEBUG( 4, __FUNCTION__ "(), vr=%d, %ld\n",self->vr, jiffies); 
 
-	skb->dev = self->netdev;
-	skb->h.raw = skb->data;
-	irlap_insert_mtt( self, skb);
-
-	dev_queue_xmit( skb);
-	self->stats.tx_packets++;
+	irlap_queue_xmit(self, skb);
 }
 
 /*
@@ -716,15 +694,15 @@
  *    Received UA (Unnumbered Acknowledgement) frame
  *
  */
-static void irlap_recv_ua_frame( struct irlap_cb *self, struct sk_buff *skb, 
-				 struct irlap_info *info) 
+static void irlap_recv_ua_frame(struct irlap_cb *self, struct sk_buff *skb, 
+				struct irlap_info *info) 
 {
- 	DEBUG( 4, __FUNCTION__ "()\n"); 
+ 	DEBUG(4, __FUNCTION__ "(), <%ld>\n", jiffies); 
 
-	ASSERT( skb != NULL, return;);
-	ASSERT( info != NULL, return;);
+	ASSERT(skb != NULL, return;);
+	ASSERT(info != NULL, return;);
 
-	irlap_do_event( self, RECV_UA_RSP, skb, info);
+	irlap_do_event(self, RECV_UA_RSP, skb, info);
 }
 
 /*
@@ -756,7 +734,6 @@
 		
 		/* * Copy buffer */
 		tx_skb = skb_clone( skb, GFP_ATOMIC);
-		/* tx_skb = skb_copy( skb, GFP_ATOMIC);  */
 		if ( tx_skb == NULL) {
 			dev_kfree_skb( skb);
 			return;
@@ -813,7 +790,6 @@
 		
 		/* Copy buffer */
 		tx_skb = skb_clone( skb, GFP_ATOMIC);
-		/* tx_skb = skb_copy( skb, GFP_ATOMIC);  */
 		if ( tx_skb == NULL) {
 			dev_kfree_skb( skb);
 			return;
@@ -890,7 +866,6 @@
 		skb->data[1] = I_FRAME | (self->vs << 1);
 		
 		tx_skb = skb_clone( skb, GFP_ATOMIC);
-		/* tx_skb = skb_copy( skb, GFP_ATOMIC); */
 		if ( tx_skb == NULL) {
 			dev_kfree_skb( skb);
 			return;
@@ -950,7 +925,6 @@
 		skb->data[1] = I_FRAME | (self->vs << 1);
 		
 		tx_skb = skb_clone( skb, GFP_ATOMIC);
-		/* tx_skb = skb_copy( skb, GFP_ATOMIC); */
 		if ( tx_skb == NULL) {
 			dev_kfree_skb( skb);
 			return;
@@ -1006,7 +980,6 @@
 		irlap_wait_min_turn_around( self, &self->qos_tx);
 
 		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;
@@ -1098,12 +1071,7 @@
 	frame[0] = self->caddr;
 	frame[0] |= (command) ? CMD_FRAME : 0;
 
-	skb->dev = self->netdev;
-	skb->h.raw = skb->data;
-	irlap_insert_mtt( self, skb);
-
-	dev_queue_xmit( skb);
-	self->stats.tx_packets++;
+	irlap_queue_xmit(self, skb);
 }
 
 /*
@@ -1137,16 +1105,11 @@
 		vs = (frame[1] >> 1) & 0x07;
 		pf = (frame[1] >> 4) & 0x01;
 		
-		DEBUG( 0, __FUNCTION__ "(), vs=%d, vr=%d, p=%d, %ld\n", 
-		       vs, vr, pf, jiffies);
+		DEBUG(0, __FUNCTION__ "(), vs=%d, vr=%d, p=%d, %ld\n", 
+		      vs, vr, pf, jiffies);
 	}
 #endif	
-	skb->dev = self->netdev;
-	skb->h.raw = skb->data;
-	irlap_insert_mtt( self, skb);
-
-	dev_queue_xmit( skb);
-	self->stats.tx_packets++;
+	irlap_queue_xmit(self, skb);
 }
 
 /*
@@ -1170,8 +1133,8 @@
 	info->pf = frame[1] & PF_BIT;      /* Final bit */
 	info->ns = (frame[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); 
+ 	DEBUG(4, __FUNCTION__"(), ns=%d, nr=%d, pf=%d, %ld\n", 
+	      info->ns, info->nr, info->pf>>4, jiffies); 
 
 	/*
 	 *  Make sure the state-machine is in the right state for receiving, 
@@ -1376,7 +1339,7 @@
 		irlap_next_state( self, LAP_NDM);
 		break;
 	case DISC_CMD:
-		DEBUG( 0, "DISC cmd frame received!\n");
+		DEBUG( 2, "DISC cmd frame received!\n");
 		irlap_do_event( self, RECV_DISC_FRAME, skb, &info);
 		break;
 	case TEST_CMD:
diff -u --recursive --new-file v2.2.2/linux/net/irda/irlmp.c linux/net/irda/irlmp.c
--- v2.2.2/linux/net/irda/irlmp.c	Wed Jan 20 23:14:07 1999
+++ linux/net/irda/irlmp.c	Sun Mar  7 15:26:44 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 17 20:54:32 1997
- * Modified at:   Sat Jan 16 22:13:20 1999
+ * Modified at:   Sat Feb 20 01:28:39 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
@@ -44,9 +44,21 @@
 /* Master structure */
 struct irlmp_cb *irlmp = NULL;
 
+/* These can be altered by the sysctl interface */
 int sysctl_discovery = 0;
+int sysctl_discovery_slots = 6;
 char sysctl_devname[65];
 
+char *lmp_reasons[] = {
+	"ERROR, NOT USED",
+	"LM_USER_REQUEST",
+	"LM_LAP_DISCONNECT",
+	"LM_CONNECT_FAILURE",
+	"LM_LAP_RESET",
+	"LM_INIT_DISCONNECT",
+	"ERROR, NOT USED",
+};
+
 __u8 *irlmp_hint_to_service( __u8 *hint);
 #ifdef CONFIG_PROC_FS
 int irlmp_proc_read( char *buf, char **start, off_t offset, int len, 
@@ -61,8 +73,6 @@
  */
 __initfunc(int irlmp_init(void))
 {
-	DEBUG( 4, "--> irlmp_init\n");
-
 	/* Initialize the irlmp structure. */
 	if ( irlmp == NULL) {
 		irlmp = kmalloc( sizeof(struct irlmp_cb), GFP_KERNEL);
@@ -128,7 +138,7 @@
 	ASSERT( irlmp != NULL, return NULL;);
 	ASSERT( irlmp->magic == LMP_MAGIC, return NULL;);
 
-	DEBUG( 4, "irlmp_open_lsap(), slsap_sel=%02x\n", slsap_sel);
+	DEBUG( 4, __FUNCTION__ "(), slsap_sel=%02x\n", slsap_sel);
 
 	/* 
 	 *  Does the client care which Source LSAP selector it gets? 
@@ -166,6 +176,7 @@
 	self->magic = LMP_LSAP_MAGIC;
 	self->slsap_sel = slsap_sel;
 	self->dlsap_sel = LSAP_ANY;
+	self->connected = FALSE;
 
 	init_timer( &self->watchdog_timer);
 
@@ -190,7 +201,7 @@
  */
 static void __irlmp_close_lsap( struct lsap_cb *self)
 {
-	DEBUG( 4, "irlmp_close()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
@@ -205,12 +216,7 @@
 	ASSERT( irlmp != NULL, return;);
 	irlmp->cache.valid = FALSE;
 #endif
-	/*
-	 *  Deallocate structure
-	 */
 	kfree( self);
-
-	DEBUG( 4, "irlmp_close() -->\n");
 }
 
 /*
@@ -243,7 +249,7 @@
 		lsap = hashbin_remove( lap->lsaps, self->slsap_sel, NULL);
 	}
 	if ( lsap == NULL) {
-		DEBUG( 0, __FUNCTION__ 
+		DEBUG( 1, __FUNCTION__ 
 		       "(), Looks like somebody has removed me already!\n");
 		return;
 	}
@@ -285,11 +291,14 @@
 	lap->irlap = irlap;
 	lap->magic = LMP_LAP_MAGIC;
 	lap->saddr = saddr;
+	lap->daddr = DEV_ADDR_ANY;
 	lap->lsaps = hashbin_new( HB_GLOBAL);
  	lap->cachelog = hashbin_new( HB_LOCAL);
 
 	irlmp_next_lap_state( lap, LAP_STANDBY);
 	
+	init_timer(&lap->idle_timer);
+
 	/*
 	 *  Insert into queue of unconnected LSAPs
 	 */
@@ -309,20 +318,22 @@
  *    IrLAP layer has been removed!
  *
  */
-void irlmp_unregister_irlap( __u32 saddr)
+void irlmp_unregister_irlap(__u32 saddr)
 {
 	struct lap_cb *self;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	self = hashbin_remove( irlmp->links, saddr, NULL);
-	if ( self != NULL) {
-		ASSERT( self->magic == LMP_LAP_MAGIC, return;);
+	self = hashbin_remove(irlmp->links, saddr, NULL);
+	if (self) {
+		ASSERT(self->magic == LMP_LAP_MAGIC, return;);
 
-		self->magic = ~LMP_LAP_MAGIC;
-		kfree( self);
+		del_timer(&self->idle_timer);	
+
+		self->magic = 0;
+		kfree(self);
 	} else {
-		DEBUG( 0, "irlmp_unregister_irlap(), Didn't find LAP!\n");
+		DEBUG(1, __FUNCTION__ "(), Didn't find LAP layer!\n");
 	}
 }
 
@@ -334,98 +345,123 @@
 
 	d = (DISCOVERY *) hashbin_get_first( log);
 	while( d != NULL) {
-		DEBUG( 0, "Discovery:\n");
-		DEBUG( 0, "  daddr=%08x\n", d->daddr);
-		DEBUG( 0, "  name=%s\n", d->info);
+		DEBUG( 1, "Discovery:\n");
+		DEBUG( 1, "  daddr=%08x\n", d->daddr);
+		DEBUG( 1, "  name=%s\n", d->info);
 
 		d = (DISCOVERY *) hashbin_get_next( log);
 	}
 }
 
+static struct lap_cb *irlmp_find_link( __u32 daddr)
+{
+	struct lap_cb *lap;
+	unsigned long flags;
+
+	DEBUG( 1, __FUNCTION__ 
+	       "(), client didn't supply saddr, so try to look it up!\n");
+
+	/* 
+	 *  Find out which link to connect on, and make sure nothing strange
+	 *  happens while we traverse the list
+	 */
+	save_flags( flags);
+	cli();
+
+	lap = (struct lap_cb *) hashbin_get_first( irlmp->links);
+	while ( lap != NULL) {
+		ASSERT( lap->magic == LMP_LAP_MAGIC, return NULL;);
+		/* dump_discoveries( lap->cachelog); */
+
+		if ( hashbin_find( lap->cachelog, daddr, NULL)) {
+			DEBUG( 4, __FUNCTION__
+			       "() found link to connect on!\n");
+			return lap;
+		}
+		lap = (struct lap_cb *) hashbin_get_next( irlmp->links);
+	}
+	restore_flags(flags);
+
+	return NULL;
+}
+
 /*
  * Function irlmp_connect_request (handle, dlsap, userdata)
  *
  *    Connect with a peer LSAP  
  *
  */
-void irlmp_connect_request( struct lsap_cb *self, __u8 dlsap_sel, __u32 daddr, 
-			    struct qos_info *qos, struct sk_buff *userdata) 
+int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel, 
+			  __u32 saddr, __u32 daddr, 
+			  struct qos_info *qos, struct sk_buff *userdata) 
 {
 	struct sk_buff *skb = NULL;
 	struct lap_cb *lap;
 	struct lsap_cb *lsap;
-	unsigned long flags;
 
-	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__ 
+	       "(), slsap_sel=%02x, dlsap_sel=%02x, saddr=%08x, daddr=%08x\n", 
+	       self->slsap_sel, dlsap_sel, saddr, daddr);
 	
-	DEBUG( 4, "irlmp_connect_request(), "
-	       "slsap_sel=%02x, dlsap_sel=%02x, daddr=%08x\n", 
-	       self->slsap_sel, dlsap_sel, daddr);
-
 	if ( self->connected) {
-		DEBUG( 0, __FUNCTION__ "(), Error: already connected!!\n");
+		DEBUG( 1, __FUNCTION__ "(), Error: already connected!!\n");
 		
-		return;
+		return -EISCONN;
 	}
 
 	/* Any userdata? */
 	if ( userdata == NULL) {
 		skb = dev_alloc_skb( 64);
 		if (skb == NULL) {
-			DEBUG( 0, __FUNCTION__ 
+			DEBUG( 1, __FUNCTION__ 
 			       "(), Could not allocate sk_buff of length %d\n",
 			       64);
-			return;
+			return -1;
 		}
 		skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER);
 	} else
 		skb = userdata;
 	
 	/* Make room for MUX control header ( 3 bytes) */
-	ASSERT( skb_headroom( skb) >= LMP_CONTROL_HEADER, return;);
+	ASSERT( skb_headroom( skb) >= LMP_CONTROL_HEADER, return -1;);
 	skb_push( skb, LMP_CONTROL_HEADER);
 
 	self->dlsap_sel = dlsap_sel;
 	self->tmp_skb = skb;
 	
-	/* 
-	 *  Find out which link to connect on, and make sure nothing strange
-	 *  happens while we traverse the list
-	 */
-	save_flags( flags);
-	cli();
-
-	lap = (struct lap_cb *) hashbin_get_first( irlmp->links);
-	while ( lap != NULL) {
-		ASSERT( lap->magic == LMP_LAP_MAGIC, return;);
-		/* dump_discoveries( lap->cachelog); */
-
-		if ( hashbin_find( lap->cachelog, daddr, NULL)) {
-			DEBUG( 4, "irlmp_connect_request() found link to connect on!\n");
-			self->lap = lap;
-			break;
-		}
-		lap = (struct lap_cb *) hashbin_get_next( irlmp->links);
-	}
-	restore_flags(flags);
+	/*  
+	 * Find the link to where we should try to connect since there may
+	 * be more than one IrDA port on this machine. If the client has
+	 * passed us the saddr (and already knows which link to use), then
+	 * we use that to find the link, if not then we have to look in the
+	 * discovery log and check if any of the links has discovered a
+	 * device with the given daddr 
+	 */
+	if ( saddr)
+		lap = hashbin_find( irlmp->links, saddr, NULL);
+	else
+		lap = irlmp_find_link( daddr);
 	
+	if ( lap == NULL) {
+		DEBUG( 1, __FUNCTION__ "(), Unable to find a usable link!\n");
+		
+		return -EHOSTUNREACH;
+	}
+	self->lap = lap;
+
 	/* 
 	 *  Remove LSAP from list of unconnected LSAPs and insert it into the 
 	 *  list of connected LSAPs for the particular link */
 	lsap = hashbin_remove( irlmp->unconnected_lsaps, self->slsap_sel, 
 			       NULL);
 
-	/* Check if we found a link to connect on */
-	if ( self->lap == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Unable to find a usable link!\n");
-		return;
-	}
-
-	ASSERT( lsap != NULL, return;);
-	ASSERT( lsap->magic == LMP_LSAP_MAGIC, return;);
-	ASSERT( lsap->lap != NULL, return;);
-	ASSERT( lsap->lap->magic == LMP_LAP_MAGIC, return;);
+	ASSERT( lsap != NULL, return -1;);
+	ASSERT( lsap->magic == LMP_LSAP_MAGIC, return -1;);
+	ASSERT( lsap->lap != NULL, return -1;);
+	ASSERT( lsap->lap->magic == LMP_LAP_MAGIC, return -1;);
 
 	hashbin_insert( self->lap->lsaps, (QUEUE *) self, self->slsap_sel, 
 			NULL);
@@ -435,13 +471,15 @@
 	/*
 	 *  User supplied qos specifications?
 	 */
-	if ( qos)
+	if (qos)
 		self->qos = *qos;
 	
 	DEBUG( 4, "*** Connecting SLSAP=%02x, DLSAP= %02x\n",
 	       self->slsap_sel, self->dlsap_sel);
 	
 	irlmp_do_lsap_event( self, LM_CONNECT_REQUEST, skb);
+
+	return 0;
 }
 
 /*
@@ -454,7 +492,7 @@
 {
 	int max_seg_size;
 
-	DEBUG( 4, "irlmp_connect_indication()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 	
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
@@ -470,9 +508,8 @@
 	skb_pull( skb, LMP_CONTROL_HEADER);
 
 	if ( self->notify.connect_indication)
-		self->notify.connect_indication( self->notify.instance, self, 
-						 &self->qos, max_seg_size, 
-						 skb);
+		self->notify.connect_indication(self->notify.instance, self, 
+						&self->qos, max_seg_size, skb);
 }
 
 /*
@@ -483,7 +520,7 @@
  */
 void irlmp_connect_response( struct lsap_cb *self, struct sk_buff *userdata) 
 {
-	DEBUG( 4, "irlmp_connect_response()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 	
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
@@ -541,14 +578,14 @@
 {
 	struct lsap_cb *lsap;
 
-	DEBUG( 4, "irlmp_disconnect_request()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
 
 	/* Already disconnected? */
 	if ( !self->connected) {
-		DEBUG( 0, __FUNCTION__ "(), already disconnected!\n");
+		DEBUG( 1, __FUNCTION__ "(), already disconnected!\n");
 		return;
 	}
 
@@ -596,20 +633,20 @@
 {
 	struct lsap_cb *lsap;
 
-	DEBUG( 4, __FUNCTION__ "()\n");	
+	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( 4, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
+	DEBUG( 3, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
 	       self->slsap_sel, self->dlsap_sel);
 
 	self->connected = FALSE;
 	self->dlsap_sel = LSAP_ANY;
 
 	/* 
-	 *  Remove assosiation betwen this LSAP and the kink it used 
+	 *  Remove association between this LSAP and the link it used 
 	 */
 	ASSERT( self->lap != NULL, return;);
 	ASSERT( self->lap->lsaps != NULL, return;);
@@ -622,11 +659,6 @@
 			lsap->slsap_sel, NULL);
 
 	self->lap = NULL;
-
-	/* FIXME: the reasons should be extracted somewhere else? */
-	if ( userdata) {
-		DEBUG( 4, __FUNCTION__ "(), reason=%02x\n", userdata->data[3]);
-	}
 	
 	/*
 	 *  Inform service user
@@ -647,13 +679,18 @@
 {
 	struct lap_cb *lap;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG( 4, __FUNCTION__ "(), nslots=%d\n", nslots);
 
 	ASSERT( irlmp != NULL, return;);
 
 	if ( !sysctl_discovery)
 		return;
 
+	if ((nslots != 1)&&(nslots != 6)&&(nslots != 8)&&(nslots != 16)) {
+		DEBUG( 1, __FUNCTION__ "(), invalid number of slots value!\n");
+		nslots = sysctl_discovery_slots = 8;
+	}
+
 	/*
 	 *  Construct new discovery info to be used by IrLAP,
 	 *  TODO: no need to do this every time!
@@ -670,6 +707,7 @@
 	
 	strncpy( irlmp->discovery_cmd.info, sysctl_devname, 31);
 	irlmp->discovery_cmd.info_len = strlen( irlmp->discovery_cmd.info);
+	irlmp->discovery_cmd.nslots = nslots;
 	
 	/*
 	 * Try to send discovery packets on all links
@@ -678,7 +716,7 @@
 	while ( lap != NULL) {
 		ASSERT( lap->magic == LMP_LAP_MAGIC, return;);
 
-		DEBUG( 4, "irlmp_discovery_request() sending request!\n");
+		DEBUG( 4, __FUNCTION__ "() sending request!\n");
 		irlmp_do_lap_event( lap, LM_LAP_DISCOVERY_REQUEST, NULL);
 		
 		lap = ( struct lap_cb *) hashbin_get_next( irlmp->links);
@@ -698,8 +736,8 @@
 	__u8 *service;
 	int i = 0;
 
-	printk( KERN_INFO "IrDA Discovered: %s\n", discovery->info);
-	printk( KERN_INFO "    Services: ");
+	DEBUG(1, "IrDA Discovered: %s\n", discovery->info);
+	DEBUG(1, "    Services: ");
 
 	service = irlmp_hint_to_service( discovery->hint);
 	if (service != NULL) {
@@ -712,7 +750,7 @@
 					      service[i], NULL);
 			if ( entry && entry->discovery_callback) {
 				DEBUG( 4, "discovery_callback!\n");
-					entry->discovery_callback( discovery);
+				entry->discovery_callback( discovery);
 			} else {
 				/* 
 				 * Found no clients for dealing with this
@@ -783,11 +821,6 @@
 	DEBUG( 4, "discovery->daddr = 0x%08x\n", discovery->daddr); 
 	self->daddr = discovery->daddr;
 
-	/*
-	 *  Create a new discovery log if neccessary
-	 */
-	/* if ( self->cachelog == NULL) */
-/* 		self->cachelog = hashbin_new( HB_LOCAL); */
 	ASSERT( self->cachelog != NULL, return;);
 
 	/*
@@ -858,7 +891,7 @@
  */
 void irlmp_data_indication( struct lsap_cb *self, struct sk_buff *skb) 
 {
- 	DEBUG( 4, "irlmp_data_indication()\n"); 
+ 	DEBUG( 4, __FUNCTION__ "()\n"); 
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
@@ -877,13 +910,11 @@
  *    
  *
  */
-void irlmp_udata_request( struct lsap_cb *self, struct sk_buff *skb) 
+inline void irlmp_udata_request( struct lsap_cb *self, struct sk_buff *skb) 
 {
  	DEBUG( 4, __FUNCTION__ "()\n"); 
 
 	ASSERT( skb != NULL, return;);
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
 	
 	/* Make room for MUX header */
 	ASSERT( skb_headroom( skb) >= LMP_HEADER, return;);
@@ -922,7 +953,7 @@
  */
 void irlmp_connectionless_data_request( struct sk_buff *skb)
 {
-	DEBUG( 0, __FUNCTION__ "(), Sorry not implemented\n"); 
+	DEBUG( 1, __FUNCTION__ "(), Sorry not implemented\n"); 
 }
 
 /*
@@ -933,12 +964,12 @@
  */
 void irlmp_connectionless_data_indication( struct sk_buff *skb)
 {
-	DEBUG( 0, __FUNCTION__ "()\n"); 
+	DEBUG( 1, __FUNCTION__ "()\n"); 
 }
 
 void irlmp_status_request(void) 
 {
-	DEBUG( 0, "irlmp_status_request(), Not implemented\n");
+	DEBUG( 1, "irlmp_status_request(), Not implemented\n");
 }
 
 void irlmp_status_indication( LINK_STATUS link, LOCK_STATUS lock) 
@@ -952,38 +983,41 @@
  *    Returns a list of all servics contained in the given hint bits. This
  *    funtion assumes that the hint bits have the size of two bytes only
  */
-__u8 *irlmp_hint_to_service( __u8 *hint)
+__u8 *irlmp_hint_to_service(__u8 *hint)
 {
 	__u8 *service;
 	int i = 0;
 
-	/* Allocate array to store services in */
+	/* 
+	 * 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( 0, "irlmp_hint_to_service: Unable to kmalloc!\n");
+		DEBUG(1, __FUNCTION__ "(), Unable to kmalloc!\n");
 		return NULL;
 	}
 
 	if ( !hint[0]) {
-		printk( "<None>\n");
+		DEBUG(1, "<None>\n");
 		return NULL;
 	}
 	if ( hint[0] & HINT_PNP)
-		printk( "PnP Compatible ");
+		DEBUG(1, "PnP Compatible ");
 	if ( hint[0] & HINT_PDA)
-		printk( "PDA/Palmtop ");
+		DEBUG(1, "PDA/Palmtop ");
 	if ( hint[0] & HINT_COMPUTER)
-		printk( "Computer ");
+		DEBUG(1, "Computer ");
 	if ( hint[0] & HINT_PRINTER) {
-		printk( "Printer\n");
+		DEBUG(1, "Printer ");
 		service[i++] = S_PRINTER;
 	}
 	if ( hint[0] & HINT_MODEM)
-		printk( "Modem ");
+		DEBUG(1, "Modem ");
 	if ( hint[0] & HINT_FAX)
-		printk( "Fax ");
+		DEBUG(1, "Fax ");
 	if ( hint[0] & HINT_LAN) {
-		printk( "LAN Access\n");			
+		DEBUG(1, "LAN Access ");		
 		service[i++] = S_LAN;
 	}
 	/* 
@@ -992,22 +1026,22 @@
 	 *  (IrLMP p. 29)
 	 */
 	if ( hint[0] & HINT_EXTENSION) {
-		if ( hint[1] & HINT_TELEPHONY)
-			printk( "Telephony ");
-		
-		if ( hint[1] & HINT_FILE_SERVER)
-			printk( "File Server ");
+		if ( hint[1] & HINT_TELEPHONY) {
+			DEBUG(1, "Telephony ");
+			service[i++] = S_TELEPHONY;
+		} if ( hint[1] & HINT_FILE_SERVER)
+			DEBUG(1, "File Server ");
 		
 		if ( hint[1] & HINT_COMM) {
-			printk( "IrCOMM ");
+			DEBUG(1, "IrCOMM ");
 			service[i++] = S_COMM;
 		}
 		if ( hint[1] & HINT_OBEX) {
-			printk( "IrOBEX ");
+			DEBUG(1, "IrOBEX ");
 			service[i++] = S_OBEX;
 		}
 	}
-	printk( "\n");
+	DEBUG(1, "\n");
 
 	service[i] = S_END;
 	
@@ -1050,7 +1084,7 @@
 		hint[1] |= HINT_OBEX;
 		break;
 	default:
-		DEBUG( 0, "irlmp_service_to_hint(), Unknown service!\n");
+		DEBUG( 1, __FUNCTION__ "(), Unknown service!\n");
 		break;
 	}
 }
@@ -1089,7 +1123,7 @@
 	/* Make a new registration */
  	entry = kmalloc( sizeof( struct irlmp_registration), GFP_ATOMIC);
 	if ( !entry) {
-		DEBUG( 0, "irlmp_register(), Unable to kmalloc!\n");
+		DEBUG( 1, __FUNCTION__ "(), Unable to kmalloc!\n");
 		return;
 	}
 
@@ -1120,7 +1154,7 @@
 	}
 
 	if ( !entry) {
-		DEBUG( 0, "Unable to find entry to unregister!\n");
+		DEBUG( 1, __FUNCTION__ "Unable to find entry to unregister!\n");
 		return;
 	}
 
@@ -1164,7 +1198,7 @@
 	ASSERT( irlmp->magic == LMP_MAGIC, return TRUE;);
 	ASSERT( slsap_sel != LSAP_ANY, return TRUE;);
 
-	DEBUG( 4, "irlmp_slsap_inuse()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 
 	/*
 	 *  Check if slsap is already in use. To do this we have to loop over
@@ -1208,8 +1242,7 @@
       
 	lsap_sel = irlmp->free_lsap_sel++;
 
-	DEBUG( 4, "irlmp_find_free_slsap(), picked next free lsap_sel=%02x\n",
-	       lsap_sel);
+	DEBUG( 4, __FUNCTION__ "(), next free lsap_sel=%02x\n", lsap_sel);
 
 	return lsap_sel;
 }
@@ -1227,21 +1260,25 @@
 
 	switch (lap_reason) {		
 	case LAP_DISC_INDICATION: /* Received a disconnect request from peer */
+		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");
 		reason = LM_LAP_DISCONNECT;
 		break;
 	case LAP_RESET_INDICATION:
+		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");
 		reason = LM_CONNECT_FAILURE;
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ 
+		DEBUG( 1, __FUNCTION__ 
 		       "(), Unknow IrLAP disconnect reason %d!\n", lap_reason);
 		reason = LM_LAP_DISCONNECT;
 		break;
@@ -1250,6 +1287,26 @@
 	return reason;
 }	
 
+__u32 irlmp_get_saddr(struct lsap_cb *self)
+{
+	DEBUG(0, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return 0;);
+	ASSERT(self->lap != NULL, return 0;);
+
+	return self->lap->saddr;
+}
+
+__u32 irlmp_get_daddr(struct lsap_cb *self)
+{
+	DEBUG(0, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return 0;);
+	ASSERT(self->lap != NULL, return 0;);
+	
+	return self->lap->daddr;
+}
+
 #ifdef CONFIG_PROC_FS
 /*
  * Function irlmp_proc_read (buf, start, offset, len, unused)
@@ -1295,8 +1352,7 @@
 		len += sprintf( buf+len, "lap state: %s, ", 
 				irlmp_state[ lap->lap_state]);
 
-		len += sprintf( buf+len, 
-				"saddr: %#08x, daddr: %#08x, ",
+		len += sprintf( buf+len, "saddr: %#08x, daddr: %#08x, ",
 				lap->saddr, lap->daddr); 
 		len += sprintf( buf+len, "\n");
 
diff -u --recursive --new-file v2.2.2/linux/net/irda/irlmp_event.c linux/net/irda/irlmp_event.c
--- v2.2.2/linux/net/irda/irlmp_event.c	Wed Jan 20 23:14:07 1999
+++ linux/net/irda/irlmp_event.c	Sun Mar  7 15:26:44 1999
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irlmp_event.c
- * Version:       0.1
+ * Version:       0.8
  * Description:   An IrDA LMP event driver for Linux
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Sat Jan 16 22:22:29 1999
+ * Modified at:   Thu Feb 11 01:24:21 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
@@ -32,13 +32,13 @@
 #include <net/irda/irlmp_frame.h>
 #include <net/irda/irlmp_event.h>
 
-char *irlmp_state[] = {
+const char *irlmp_state[] = {
 	"LAP_STANDBY",
 	"LAP_U_CONNECT",
 	"LAP_ACTIVE",
 };
 
-char *irlsap_state[] = {
+const char *irlsap_state[] = {
 	"LSAP_DISCONNECTED",
 	"LSAP_CONNECT",
 	"LSAP_CONNECT_PEND",
@@ -47,7 +47,7 @@
 	"LSAP_SETUP_PEND",
 };
 
-static char *irlmp_event[] = {
+static const char *irlmp_event[] = {
 	"LM_CONNECT_REQUEST",
  	"LM_CONNECT_CONFIRM",
 	"LM_CONNECT_RESPONSE",
@@ -71,6 +71,7 @@
 	"LM_LAP_DISCONNECT_REQUEST",
 	"LM_LAP_DISCOVERY_REQUEST",
  	"LM_LAP_DISCOVERY_CONFIRM",
+	"LM_LAP_IDLE_TIMEOUT",
 };
 
 /* LAP Connection control proto declarations */
@@ -150,7 +151,7 @@
 	
 	DEBUG( 4, "IrLMP, discovery timer expired!\n");
 	
-	irlmp_discovery_request( 8);
+	irlmp_discovery_request( sysctl_discovery_slots);
 
 	/* Restart timer */
 	irlmp_start_discovery_timer( irlmp, 300);
@@ -168,6 +169,18 @@
 	irlmp_do_lsap_event( self, LM_WATCHDOG_TIMEOUT, NULL);
 }
 
+void irlmp_idle_timer_expired(unsigned long data)
+{
+	struct lap_cb *self = (struct lap_cb *) data;
+	
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+
+	irlmp_do_lap_event( self, LM_LAP_IDLE_TIMEOUT, NULL);
+}
+
 /*********************************************************************
  *
  *    LAP connection control states
@@ -207,10 +220,10 @@
 		irlap_connect_response( self->irlap, skb);
 		break;
 	case LM_LAP_CONNECT_REQUEST:
-		DEBUG( 4, "irlmp_state_standby() LS_CONNECT_REQUEST\n");
+		DEBUG(4, __FUNCTION__ "() LS_CONNECT_REQUEST\n");
 
 		/* FIXME: need to set users requested QoS */
-		irlap_connect_request( self->irlap, self->daddr, NULL, 0);
+		irlap_connect_request(self->irlap, self->daddr, NULL, 0);
 
 		irlmp_next_lap_state( self, LAP_U_CONNECT);
 		break;
@@ -221,7 +234,7 @@
 		irlmp_next_lap_state( self, LAP_STANDBY);
 		break;
 	default:
-		DEBUG( 4, "irlmp_state_standby: Unknown event\n");
+		DEBUG(4, __FUNCTION__ "(), Unknown event\n");
 		break;
 	}
 }
@@ -239,7 +252,7 @@
 	struct lsap_cb *lsap;
 	struct lsap_cb *lsap_current;
 	
-	DEBUG( 4, __FUNCTION__ "()\n"); 
+	DEBUG(2, __FUNCTION__ "(), event=%s\n", irlmp_event[ event]);
 
 	switch( event) {
 	case LM_LAP_CONNECT_CONFIRM:
@@ -253,7 +266,7 @@
 		}		
 		break;
 	case LM_LAP_DISCONNECT_INDICATION:
-		DEBUG( 4, __FUNCTION__ "(), IRLAP_DISCONNECT_INDICATION\n");
+		DEBUG(2, __FUNCTION__ "(), IRLAP_DISCONNECT_INDICATION\n");
 	
 		irlmp_next_lap_state( self, LAP_STANDBY);
 
@@ -312,25 +325,31 @@
 		 */
 		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_next(self->lsaps);
+			irlmp_do_lsap_event(lsap, LM_LAP_CONNECT_CONFIRM, skb);
+ 			lsap = (struct lsap_cb*) hashbin_get_next(self->lsaps);
 		}
-		
 		/* Keep state */
 		break;
 	case LM_LAP_DISCONNECT_REQUEST:
 		DEBUG( 4, __FUNCTION__ "(), LM_LAP_DISCONNECT_REQUEST\n");
 
 		/*
-		 *  Need to find out if we should close IrLAP or not
+		 *  Need to find out if we should close IrLAP or not. If there
+		 *  is only one LSAP connection left on this link, that LSAP 
+		 *  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) == 0) {
-			DEBUG( 0, __FUNCTION__ 
-			       "(), no more LSAPs so time to disconnect IrLAP\n");
-			irlmp_next_lap_state( self, LAP_STANDBY);
-		
-			irlap_disconnect_request( self->irlap);
+		if (hashbin_get_size(self->lsaps) == 1)
+			irlmp_start_idle_timer(self, LM_IDLE_TIMEOUT);
+
+		break;
+	case LM_LAP_IDLE_TIMEOUT:
+		if (hashbin_get_size(self->lsaps) == 0) {
+			DEBUG(0, __FUNCTION__ 
+			      "(), no more LSAPs so time to close IrLAP\n");
+			irlmp_next_lap_state(self, LAP_STANDBY);
+			
+			irlap_disconnect_request(self->irlap);
 		}
 		break;
 	case LM_LAP_DISCONNECT_INDICATION:
@@ -395,7 +414,6 @@
 	case LM_CONNECT_INDICATION:
 		irlmp_next_lsap_state( self, LSAP_CONNECT_PEND);
 
-
 		/* 
 		 *  Bind this LSAP to the IrLAP link where the connect was
 		 *  received 
@@ -415,8 +433,7 @@
 		irlmp_do_lap_event( self->lap, LM_LAP_CONNECT_REQUEST, skb);
 		break;
 	default:
-		/* DEBUG( 4, "irlmp_state_disconnected: Unknown event %d\n",
-		   event); */
+		DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;
 	}
 }
@@ -448,7 +465,7 @@
 		irlmp_next_lsap_state( self, LSAP_DATA_TRANSFER_READY);
 		break;
 	default:
-		DEBUG( 4, "irlmp_state_connect: Unknown event\n");
+		DEBUG( 4, __FUNCTION__ "(), Unknown event\n");
 		break;
 	}
 }
@@ -489,8 +506,7 @@
 		break;
 		
 	default:
-		DEBUG( 4, "irlmp_state_connect_pend: Unknown event %d\n", 
-		       event);
+		DEBUG( 4, __FUNCTION__ "Unknown event %d\n", event);
 		break;	
 	}	
 }
@@ -571,12 +587,13 @@
 		ASSERT( self->lap != NULL, return;);
 		ASSERT( self->lap->magic == LMP_LAP_MAGIC, return;);
 	
-		reason = irlmp_convert_lap_reason( self->lap->reason);
+		ASSERT(skb != NULL, return;);
+		ASSERT(skb->len > 3, return;);
+		reason = skb->data[3];
 
 		 /* Try to close the LAP connection */
 		DEBUG( 4, __FUNCTION__ "(), trying to close IrLAP\n");
-		irlmp_do_lap_event( self->lap, LM_LAP_DISCONNECT_REQUEST, 
-				    NULL);
+		irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
 
 		irlmp_disconnect_indication( self, reason, skb);
 
@@ -602,7 +619,7 @@
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
 
-	DEBUG( 4, "irlmp_state_setup()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 
 	switch( event) {
 	case LM_CONNECT_CONFIRM:
@@ -622,10 +639,21 @@
 		ASSERT( self->lap != NULL, return;);
 		ASSERT( self->lap->magic == LMP_LAP_MAGIC, return;);
 		
-		reason = irlmp_convert_lap_reason( self->lap->reason);
-		
+		ASSERT(skb != NULL, return;);
+		ASSERT(skb->len > 3, return;);
+		reason = skb->data[3];
+
 		irlmp_disconnect_indication( self, reason, skb);
 		break;
+	case LM_WATCHDOG_TIMEOUT:
+		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);
+		
+		irlmp_disconnect_indication( self, LM_CONNECT_FAILURE, NULL);
+		break;
 	default:
 		DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;	
@@ -643,6 +671,7 @@
 static void irlmp_state_setup_pend( struct lsap_cb *self, IRLMP_EVENT event, 
 				    struct sk_buff *skb) 
 {
+	LM_REASON reason;
 
 	DEBUG( 4, __FUNCTION__ "()\n"); 
 
@@ -656,18 +685,23 @@
 				    self->tmp_skb);
 		irlmp_next_lsap_state( self, LSAP_SETUP);
 		break;
-	case LM_DISCONNECT_INDICATION:
-		del_timer( &self->watchdog_timer);
-
-		irlmp_next_lsap_state( self, LSAP_DISCONNECTED);
-		break;
 	case LM_WATCHDOG_TIMEOUT:
 		DEBUG( 0, __FUNCTION__ "() WATCHDOG_TIMEOUT!\n");
 
-		/* FIXME: should we do a disconnect_indication? */
 		ASSERT( self->lap != NULL, return;);
-		irlmp_do_lap_event( self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
+		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);
+		break;
+	case LM_LAP_DISCONNECT_INDICATION: /* LS_Disconnect.indication */
+		del_timer( &self->watchdog_timer);
+
 		irlmp_next_lsap_state( self, LSAP_DISCONNECTED);
+		
+		reason = irlmp_convert_lap_reason( self->lap->reason);
+		
+		irlmp_disconnect_indication( self, reason, NULL);
 		break;
 	default:
 		DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event);
diff -u --recursive --new-file v2.2.2/linux/net/irda/irlmp_frame.c linux/net/irda/irlmp_frame.c
--- v2.2.2/linux/net/irda/irlmp_frame.c	Wed Jan 20 23:14:07 1999
+++ linux/net/irda/irlmp_frame.c	Sun Mar  7 15:26:44 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Aug 19 02:09:59 1997
- * Modified at:   Sat Jan 16 22:14:04 1999
+ * Modified at:   Thu Feb 18 08:48:28 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>
@@ -196,15 +196,15 @@
  *    IrLAP has disconnected 
  *
  */
-void irlmp_link_disconnect_indication( struct lap_cb *lap, 
-				       struct irlap_cb *irlap, 
-				       LAP_REASON reason, 
-				       struct sk_buff *userdata)
+void irlmp_link_disconnect_indication(struct lap_cb *lap, 
+				      struct irlap_cb *irlap, 
+				      LAP_REASON reason, 
+				      struct sk_buff *userdata)
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(2, __FUNCTION__ "()\n");
 
-	ASSERT( lap != NULL, return;);
-	ASSERT( lap->magic == LMP_LAP_MAGIC, return;);
+	ASSERT(lap != NULL, return;);
+	ASSERT(lap->magic == LMP_LAP_MAGIC, return;);
 
 	lap->reason = reason;
 
@@ -213,7 +213,7 @@
 	/*
 	 *  Inform station state machine
 	 */
-	irlmp_do_lap_event( lap, LM_LAP_DISCONNECT_INDICATION, NULL);
+	irlmp_do_lap_event(lap, LM_LAP_DISCONNECT_INDICATION, NULL);
 }
 
 /*
@@ -222,13 +222,18 @@
  *    Incoming LAP connection!
  *
  */
-void irlmp_link_connect_indication( struct lap_cb *self, struct qos_info *qos,
+void irlmp_link_connect_indication( struct lap_cb *self, __u32 saddr, 
+				    __u32 daddr, struct qos_info *qos,
 				    struct sk_buff *skb) 
 {
 	DEBUG( 4, __FUNCTION__ "()\n");
 
 	/* Copy QoS settings for this session */
 	self->qos = qos;
+
+	/* Update destination device address */
+	self->daddr = daddr;
+	ASSERT(self->saddr == saddr, return;);
 
 	irlmp_do_lap_event( self, LM_LAP_CONNECT_INDICATION, skb);
 }
diff -u --recursive --new-file v2.2.2/linux/net/irda/irlpt/irlpt_cli.c linux/net/irda/irlpt/irlpt_cli.c
--- v2.2.2/linux/net/irda/irlpt/irlpt_cli.c	Wed Jan 20 23:14:07 1999
+++ linux/net/irda/irlpt/irlpt_cli.c	Sun Mar  7 15:26:44 1999
@@ -1,6 +1,6 @@
 /*********************************************************************
  *
- * Filename:      irlpt.c
+ * Filename:      irlpt_cli.c
  * Version:       
  * Description:   
  * Status:        Experimental.
@@ -49,18 +49,21 @@
 
 static void irlpt_client_discovery_indication( DISCOVERY *);
 
-static void irlpt_client_connect_confirm( void *instance, void *sap, 
+static void irlpt_client_connect_confirm( void *instance, 
+					  void *sap, 
 					  struct qos_info *qos, 
 					  int max_seg_size, 
 					  struct sk_buff *skb);
-static void irlpt_client_disconnect_indication( void *instance, void *sap, 
+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, $Revision: 1.10 $/$Date: 1998/11/10 22:50:57 $ (Thomas Davis)";
+static char *version = "IrLPT client, v2 (Thomas Davis)";
 
 struct file_operations client_fops = {
 	irlpt_seek,    /* seek */
@@ -102,6 +105,9 @@
 	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);
@@ -130,19 +136,20 @@
 			break;
 		}
 		
-		len += sprintf(buf+len, "service_type: %s\n", 
-			       irlpt_service_type[index]);
-		len += sprintf(buf+len, "port_type: %s\n", 
+		len += sprintf(buf+len, "service_type: %s, port type: %s\n", 
+			       irlpt_service_type[index],
 			       irlpt_port_type[ self->porttype]);
-		len += sprintf(buf+len, "daddr: 0x%08x\n", self->daddr);
-		len += sprintf(buf+len, "fsm_state: %s\n", 
-			       irlpt_client_fsm_state[self->state]);
-		len += sprintf(buf+len, "retries: %d\n", self->open_retries);
-		len += sprintf(buf+len, "dlsap: %d\n", self->dlsap_sel);
 
-		len += sprintf(buf+len, "count: %d\n", self->count);
-		len += sprintf(buf+len, "rx_queue: %d\n", 
-			       skb_queue_len(&self->rx_queue));
+		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);
@@ -163,7 +170,7 @@
 #endif /* CONFIG_PROC_FS */
 
 /*
- * Function irlpt_init (dev)
+ * Function irlpt_client_init (dev)
  *
  *   Initializes the irlpt control structure
  *
@@ -176,7 +183,8 @@
 
 	irlpt_clients = hashbin_new( HB_LOCAL); 
 	if ( irlpt_clients == NULL) {
-		printk( KERN_WARNING "IrLPT: Can't allocate hashbin!\n");
+		printk( KERN_WARNING 
+			"IrLPT client: Can't allocate hashbin!\n");
 		return -ENOMEM;
 	}
 
@@ -195,9 +203,7 @@
 
 #ifdef MODULE
 /*
- * Function irlpt_cleanup (void)
- *
- *
+ * Function irlpt_client_cleanup (void)
  *
  */
 static void irlpt_client_cleanup(void)
@@ -207,7 +213,7 @@
 	irlmp_unregister_layer( S_PRINTER, CLIENT);
 
 	/*
-	 *  Delete hashbin and close all irlan client instances in it
+	 *  Delete hashbin and close all irlpt client instances in it
 	 */
 	hashbin_delete( irlpt_clients, (FREE_FUNC) irlpt_client_close);
 
@@ -221,9 +227,7 @@
 
 
 /*
- * Function irlpt_open (void)
- *
- *    This is the entry-point which starts all the fun! Currently this
+ * Function irlpt_client_open (void)
  *
  */
 static struct irlpt_cb *irlpt_client_open( __u32 daddr)
@@ -232,15 +236,24 @@
 
 	DEBUG( irlpt_client_debug, "--> "__FUNCTION__ "\n");
 
-	self = kmalloc(sizeof(struct irlpt_cb), GFP_ATOMIC);
-	if (self == NULL)
-		return NULL;
+	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));
 
-	memset(self, 0, sizeof(struct irlpt_cb));
+		ASSERT( self != NULL, return NULL;);
 
-	ASSERT( self != NULL, return NULL;);
+		sprintf(self->ifname, "irlpt%d", 
+			hashbin_get_size(irlpt_clients));
+
+		hashbin_insert( irlpt_clients, (QUEUE *) self, daddr, NULL);
+
+	}
 
- 	sprintf(self->ifname, "irlpt%d", hashbin_get_size(irlpt_clients));
 	self->ir_dev.minor = MISC_DYNAMIC_MINOR;
 	self->ir_dev.name = self->ifname;
 	self->ir_dev.fops = &client_fops;
@@ -251,14 +264,13 @@
 	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);
 
-	hashbin_insert( irlpt_clients, (QUEUE *) self, daddr, NULL);
-
-	/*	MOD_INC_USE_COUNT; */
+	MOD_INC_USE_COUNT;
 
 	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
 
@@ -280,17 +292,15 @@
 	ASSERT( self->magic == IRLPT_MAGIC, return;);
 
 	while (( skb = skb_dequeue(&self->rx_queue)) != NULL) {
-		DEBUG(3, "irlpt_client_close: freeing SKB\n");
+		DEBUG(irlpt_client_debug, 
+		      __FUNCTION__ ": freeing SKB\n");
                 dev_kfree_skb( skb);
 	}
 
 	misc_deregister(&self->ir_dev);
+	self->in_use = FALSE;
 
-	self->magic = ~IRLPT_MAGIC;
-
-	kfree( self);
-
-	/* MOD_DEC_USE_COUNT; */
+	MOD_DEC_USE_COUNT;
 
 	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
 }
@@ -306,49 +316,51 @@
 {
 	struct irlpt_info info;
 	struct irlpt_cb *self;
-	__u32 daddr;
+	__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 = discovery->daddr;
+	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) {
-		ASSERT( self->magic == IRLPT_MAGIC, return;);
-		if ( self->state == IRLPT_CLIENT_IDLE) {
-			irlpt_client_do_event( self, 
-					       IRLPT_DISCOVERY_INDICATION, 
-					       NULL, &info);
+      	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;
 		}
-		return;
-	}
-    
-
-	/*
-	 * 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__ 
-		      ":irlpt_client_open failed!\n");
 	}
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLPT_MAGIC, return;);
 
-	self->daddr = info.daddr = daddr;
+	self->daddr = daddr;
+	self->saddr = saddr;
+	self->timeout = irlpt_client_expired;
+
+	irda_start_timer( &self->lpt_timer, 5000, (unsigned long) self, 
+			  self->timeout);
 	
-	if (self->state == IRLPT_CLIENT_IDLE) {
-		irlpt_client_do_event( self, IRLPT_DISCOVERY_INDICATION, 
-				       NULL, &info);
-	}
+#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");
 }
@@ -357,7 +369,8 @@
  * Function irlpt_disconnect_indication (handle)
  *
  */
-static void irlpt_client_disconnect_indication( void *instance, void *sap, 
+static void irlpt_client_disconnect_indication( void *instance,
+						void *sap, 
 						LM_REASON reason,
 						struct sk_buff *skb)
 {
@@ -373,8 +386,8 @@
 
 	info.daddr = self->daddr;
 
-        DEBUG( irlpt_client_debug, __FUNCTION__ 
-	       ": reason=%d (%s), peersap=%d\n",
+        DEBUG( irlpt_client_debug, 
+	       __FUNCTION__ ": reason=%d (%s), peersap=%d\n",
 	       reason, irlpt_reasons[reason], self->dlsap_sel);
 
 	self->connected = IRLPT_DISCONNECTED;
@@ -413,6 +426,7 @@
 
 	info.daddr = self->daddr;
 
+#if 0
 	/*
 	 *  Check if we have got some QoS parameters back! This should be the
 	 *  negotiated QoS for the link.
@@ -421,6 +435,7 @@
 		DEBUG( irlpt_client_debug, __FUNCTION__ ": Frame Size: %d\n",
 		       qos->data_size.value);
 	}
+#endif
 
 	self->irlap_data_size = (qos->data_size.value - IRLPT_MAX_HEADER);
 	self->connected = TRUE;
@@ -489,7 +504,6 @@
  *    Fixed to match changes in iriap.h, DB.
  *
  */
-
 void irlpt_client_get_value_confirm(__u16 obj_id, struct ias_value *value, 
 				    void *priv)
 {
@@ -505,10 +519,13 @@
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IRLPT_MAGIC, return;);
 
-	/* can't stop here..  if we get a bad obj, must tell the state
-	   machine that!
-	ASSERT( type == IAS_INTEGER, return;);
-	*/
+	/* Check if request succeeded */
+	if ( !value) {
+		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;
@@ -518,11 +535,10 @@
 		       ": obj_id = %d, value = %d\n", 
 		       obj_id, value->t.integer);
 
-		irlpt_client_do_event( self, IAS_PROVIDER_AVAIL, 
-				       NULL, &info);
+		irlpt_client_do_event( self, IAS_PROVIDER_AVAIL, NULL, &info);
 	} else
-		irlpt_client_do_event( self, IAS_PROVIDER_NOT_AVAIL, 
-				       NULL, &info);
+		irlpt_client_do_event( self, IAS_PROVIDER_NOT_AVAIL, NULL, 
+				       &info);
 
 	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
 }
@@ -536,9 +552,12 @@
 	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);
@@ -549,17 +568,51 @@
 	        DEBUG( irlpt_client_debug, __FUNCTION__ 
 		       ": issue THREE_WIRE_RAW connect\n");
 		irlmp_connect_request( self->lsap, self->dlsap_sel, 
-				       self->daddr, NULL, NULL);
+				       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_CONTROL_HEADER+LAP_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 protocol");
+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)
@@ -570,11 +623,11 @@
 int init_module(void)
 {
 
-        DEBUG( irlpt_client_debug, "--> irlpt client: init_module\n");
+        DEBUG( irlpt_client_debug, "--> IrLPT client: init_module\n");
 
         irlpt_client_init();
 
-        DEBUG( irlpt_client_debug, "irlpt client: init_module -->\n");
+        DEBUG( irlpt_client_debug, "IrLPT client: init_module -->\n");
 
         return 0;
 }
@@ -587,13 +640,13 @@
  */
 void cleanup_module(void)
 {
-        DEBUG( irlpt_client_debug, "--> irlpt client: cleanup_module\n");
+        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");
+        DEBUG( irlpt_client_debug, "IrLPT client: cleanup_module -->\n");
 }
 
 #endif /* MODULE */
diff -u --recursive --new-file v2.2.2/linux/net/irda/irlpt/irlpt_cli_fsm.c linux/net/irda/irlpt/irlpt_cli_fsm.c
--- v2.2.2/linux/net/irda/irlpt/irlpt_cli_fsm.c	Wed Jan 20 23:14:07 1999
+++ linux/net/irda/irlpt/irlpt_cli_fsm.c	Sun Mar  7 15:26:44 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Jan 12 11:06:00 1999
- * Modified at:   Tue Jan 12 11:14:22 1999
+ * Modified at:   Tue Jan 26 12:02:31 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>
@@ -35,50 +35,53 @@
 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,
+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,
+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,
+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_waitr ( 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,
+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 = 3;
+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) = 
+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_waitr,
 	irlpt_client_state_conn,
 };
 
-void irlpt_client_do_event( struct irlpt_cb *self, IRLPT_EVENT event, 
-				   struct sk_buff *skb, 
-				   struct irlpt_info *info) 
+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");
+	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", 
+	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);
@@ -86,9 +89,10 @@
 	DEBUG( irlpt_client_fsm_debug, __FUNCTION__ " -->\n");
 }
 
-void irlpt_client_next_state( struct irlpt_cb *self, IRLPT_CLIENT_STATE state) 
+void irlpt_client_next_state( struct irlpt_cb *self, 
+			      IRLPT_CLIENT_STATE state) 
 {
-	DEBUG( irlpt_client_fsm_debug,"--> "  __FUNCTION__ ":\n");
+	DEBUG( irlpt_client_fsm_debug, "--> "  __FUNCTION__ ":\n");
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IRLPT_MAGIC, return;);
@@ -102,16 +106,17 @@
 }
 
 /*
- * Function client_state_idle (event, skb, info)
+ * 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, 
+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");
+	DEBUG( irlpt_client_fsm_debug, "--> "  __FUNCTION__ ":\n");
 
 	ASSERT( self != NULL, return -1;);
 	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
@@ -120,11 +125,13 @@
 	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( info->daddr, 
-					"IrLPT", "IrDA:IrLMP:LsapSel",
-					irlpt_client_get_value_confirm,
-					(void *) self);
+		       ": 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;
 
@@ -145,36 +152,53 @@
 }
 
 /*
- * Function client_state_query
+ * 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, 
+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");
+	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");
+		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);
+		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");
+		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",
+		DEBUG( irlpt_client_fsm_debug, 
+		       __FUNCTION__ ": Unknown event %d (%s)\n",
 		       event, irlpt_fsm_event[event]);
 		break;
 	}
@@ -189,11 +213,12 @@
 }
 
 /*
- * Function client_state_info 
+ * 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,
+static int irlpt_client_state_ready( struct irlpt_cb *self, 
+				     IRLPT_EVENT event,
 				     struct sk_buff *skb, 
 				     struct irlpt_info *info) 
 {
@@ -204,8 +229,8 @@
 
 	switch( event) {
 	case IRLPT_CONNECT_REQUEST:
-	        DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
-		       ": IRLPT_CONNECT_REQUEST\n");
+	        DEBUG( irlpt_client_fsm_debug, 
+		       __FUNCTION__ ": IRLPT_CONNECT_REQUEST\n");
 		irlpt_client_connect_request(self);
 		irlpt_client_next_state( self, IRLPT_CLIENT_WAITI);
 		break;
@@ -213,6 +238,9 @@
 	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:
@@ -233,11 +261,12 @@
 
 
 /*
- * Function client_state_waiti 
+ * Function irlpt_client_state_waiti 
  *
  *
  */
-static int irlpt_client_state_waiti( struct irlpt_cb *self, IRLPT_EVENT event, 
+static int irlpt_client_state_waiti( struct irlpt_cb *self, 
+				     IRLPT_EVENT event, 
 				     struct sk_buff *skb, 
 				     struct irlpt_info *info) 
 {
@@ -250,10 +279,17 @@
 	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__ ": 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;
 
@@ -274,63 +310,18 @@
 }
 
 /*
- * Function client_state_waitr 
- *
- *
- */
-static int irlpt_client_state_waitr( 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);
-		break;
-
-	case LMP_DISCONNECT:
-		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": LMP_DISCONNECT\n");
-		irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
-		break;
-
-	case LAP_DISCONNECT:
-		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": LAP_DISCONNECT\n");
-		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 client_state_conn (event, skb, info)
+ * 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, 
+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");
+	DEBUG( irlpt_client_fsm_debug, "--> " __FUNCTION__ ":\n");
 
 	ASSERT( self != NULL, return -1;);
 	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
@@ -346,6 +337,10 @@
 	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;
 
diff -u --recursive --new-file v2.2.2/linux/net/irda/irlpt/irlpt_common.c linux/net/irda/irlpt/irlpt_common.c
--- v2.2.2/linux/net/irda/irlpt/irlpt_common.c	Mon Jan 25 17:44:34 1999
+++ linux/net/irda/irlpt/irlpt_common.c	Sun Mar  7 15:26:44 1999
@@ -68,7 +68,7 @@
 
 char *irlpt_reasons[] = {
 	"SERVICE_CLOSE",     /* Service has closed the connection */
-	"DISC_INDICATION",   /* Received a disconnect request from peer entity*/
+	"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 */
@@ -81,7 +81,6 @@
 	"IRLPT_CLIENT_QUERY",
 	"IRLPT_CLIENT_READY",
 	"IRLPT_CLIENT_WAITI",
-	"IRLPT_CLIENT_WAITR",
 	"IRLPT_CLIENT_CONN"
 };
 
@@ -108,9 +107,8 @@
 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! */
-
-static struct wait_queue *irlpt_wait;
+				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 $";
@@ -152,7 +150,6 @@
 	char *ptr = buffer;
 	struct irlpt_cb *self;
 	struct sk_buff *skb = NULL;
-	struct wait_queue wait = { current, NULL };
 
 	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
 
@@ -170,11 +167,12 @@
 		switch (self->eof) {
 		case LM_USER_REQUEST:
 			self->eof = FALSE;
-			DEBUG(3, "irlpt_read: returning 0\n");
+			DEBUG(irlpt_common_debug, 
+			      __FUNCTION__ ": returning 0\n");
 			return 0;
 		case LM_LAP_DISCONNECT:
 			self->eof = FALSE;
-			return -EIO;
+			return 0;
 		case LM_LAP_RESET:
 			self->eof = FALSE;
 			return -ECONNRESET;
@@ -208,11 +206,7 @@
 			       len, count, self->eof);
 
 			if (!signal_pending(current) && !self->eof) {
-			        add_wait_queue(&irlpt_wait, &wait);
-				current->state = TASK_INTERRUPTIBLE;
-				schedule();
-				current->state = TASK_RUNNING;
-				remove_wait_queue(&irlpt_wait, &wait);
+				interruptible_sleep_on(&self->read_wait);
 			} else
 				break;
 		}
@@ -228,7 +222,6 @@
 {
 	struct irlpt_cb *self;
 	struct sk_buff *skb;
-	struct wait_queue wait = { current, NULL };
 
 	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
 
@@ -240,26 +233,25 @@
 	DEBUG( irlpt_common_debug, __FUNCTION__ 
 	       ": count = %d\n", count);
 
-	if (self->state != IRLPT_CLIENT_CONN) {
+	DEBUG( irlpt_common_debug, __FUNCTION__ 
+	       ": pkt_count = %d\n", self->pkt_count);
+	if (self->pkt_count > 8) {
 		DEBUG( irlpt_common_debug, __FUNCTION__ 
-		       ": state != IRLPT_CONN (possible link problems?)\n");
-		return -ENOLINK;
+		       ": 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->pkt_count > 8) {
+
+	if (self->state != IRLPT_CLIENT_CONN) {
 		DEBUG( irlpt_common_debug, __FUNCTION__ 
-		       ": too many outstanding buffers, going to sleep\n");
-		add_wait_queue(&self->write_wait, &wait);
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		current->state = TASK_RUNNING;
-		remove_wait_queue(&self->write_wait, &wait);
+		       ": state != IRLPT_CONN (possible link problems?)\n");
+		return -ENOLINK;
 	}
 
 	DEBUG( irlpt_common_debug, __FUNCTION__ 
-	       ":count = %d, irlap_data_size = %d, IRLPT_MAX_HEADER = %d\n",
+	       ": count = %d, irlap_data_size = %d, IRLPT_MAX_HEADER = %d\n",
 		count, self->irlap_data_size, IRLPT_MAX_HEADER);
 
  	if (count > (self->irlap_data_size - IRLPT_MAX_HEADER)) {
@@ -272,7 +264,8 @@
 
 	skb = dev_alloc_skb(count + IRLPT_MAX_HEADER);
 	if ( skb == NULL) {
-		printk( KERN_INFO __FUNCTION__ ": couldn't allocate skbuff!\n");
+		printk( KERN_INFO 
+			__FUNCTION__ ": couldn't allocate skbuff!\n");
 		return 0;
 	}
 
@@ -292,6 +285,9 @@
 
 	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);
@@ -305,60 +301,13 @@
 	return -ESPIPE;
 }
 
-#if 0
-
-/*
- * Function irlpt_select (inode, filp, mode, table)
- *
- *    Implementation for the select() call
- *
- */
-int irlpt_select( struct inode *inode, struct file *filp, int mode, 
-			 select_table *table)
-{
-	struct irlpt_cb *self;
-
-	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
-	
-	self = irlpt_find_handle(MINOR( inode->i_rdev));
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
-
-	switch (mode) {
-	case SEL_IN:
-		if ( skb_queue_len( &self->rx_queue))
-			return 1; /* Readable */
-		select_wait( &self->read_wait, table);
-		break;
-	case SEL_OUT:
-		if ( self->connected)
-			return 1;
-		select_wait( &self->write_wait, table);
-		break;
-	case SEL_EX:
-		if ( self->connected)
-			return 1;
-		select_wait( &self->ex_wait, table);
-		break;
-	default:
-		break;
-	}
-
-	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
-
-	return 0;
-}
-
-#else
-
 /*
- * Function irobex_poll (file, wait)
+ * Function irlpt_poll (file, wait)
  *
  *    
  *
  */
-static u_int irlpt_poll(struct file *file, poll_table *wait)
+u_int irlpt_poll(struct file *file, poll_table *wait)
 {
 	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
 
@@ -367,8 +316,6 @@
 	return 0;
 }
 
-#endif
-
 /*
  * Function open_irlpt (inode, file)
  *
@@ -378,6 +325,7 @@
 int irlpt_open(struct inode *inode, struct file *file)
 {
 	struct irlpt_cb *self;
+	struct irlpt_info info;
 
 	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
 
@@ -386,22 +334,6 @@
 	ASSERT( self != NULL, return -1;);
 	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
 
-#if 0
-	if (self->state == IRLPT_IDLE) {
-		DEBUG( irlpt_common_debug, __FUNCTION__ 
-		       ": state == IRLPT_IDLE! (no device found yet)\n");
-		return -ENODEV;
-	}
-
-	if (self->state == IRLPT_QUERY ||
-	    self->state == IRLPT_READY ||
-	    self->state == IRLPT_WAITI) {
-		DEBUG( irlpt_common_debug, __FUNCTION__ ": state == IRLPT_QUERY, " 
-		       "IRLPT_READY or IRLPT_WAITI (link problems)!\n");
-		return -EBUSY;
-	}
-#endif
-
 	if (self->count++) {
 		DEBUG( irlpt_common_debug, __FUNCTION__ 
 		       ": count not zero; actual = %d\n", self->count);
@@ -409,6 +341,35 @@
 		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;
@@ -420,9 +381,12 @@
  *
  *
  */
-int irlpt_close(struct inode *inode, struct file *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");
 
@@ -433,12 +397,42 @@
 	ASSERT( self != NULL, return -1;);
 	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
 
-	DEBUG(irlpt_common_debug, __FUNCTION__ ": self->count=%d\n", self->count);
+	DEBUG(irlpt_common_debug, 
+	      __FUNCTION__ ": self->count=%d\n", self->count);
+
 	if (self->count > 0)
 		self->count--;
 
-	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
+	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_CONTROL_HEADER+LAP_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;
 }
 
@@ -485,6 +479,10 @@
 }
 
 #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)
diff -u --recursive --new-file v2.2.2/linux/net/irda/irlpt/irlpt_srvr.c linux/net/irda/irlpt/irlpt_srvr.c
--- v2.2.2/linux/net/irda/irlpt/irlpt_srvr.c	Wed Jan 20 23:14:07 1999
+++ linux/net/irda/irlpt/irlpt_srvr.c	Sun Mar  7 15:26:44 1999
@@ -49,31 +49,34 @@
 
 int irlpt_server_init(void);
 static void irlpt_server_cleanup(void);
-static void irlpt_server_disconnect_indication( void *instance, void *sap, 
+static void irlpt_server_disconnect_indication( void *instance, 
+						void *sap, 
 						LM_REASON reason,
 						struct sk_buff *skb);
-static void irlpt_server_connect_confirm( void *instance, void *sap, 
+static void irlpt_server_connect_confirm( void *instance, 
+					  void *sap, 
 					  struct qos_info *qos,  
 					  int max_seg_size,
 					  struct sk_buff *skb);
-static void irlpt_server_connect_indication( void *instance, void *sap, 
+static void irlpt_server_connect_indication( void *instance, 
+					     void *sap, 
 					     struct qos_info *qos, 
 					     int max_seg_size,
 					     struct sk_buff *skb);
-static void irlpt_server_data_indication( void *instance, void *sap, 
+static void 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 struct wait_queue *irlpt_server_wait;
-
 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, $Revision: 1.9 $/$Date: 1998/10/22 12:02:22 $ (Thomas Davis)";
+
+static char *version = "IrLPT server, v2 (Thomas Davis)";
 
 struct file_operations irlpt_fops = {
 	irlpt_seek,	/* seek */
@@ -96,7 +99,7 @@
 #ifdef CONFIG_PROC_FS
 
 /*
- * Function proc_irlpt_read (buf, start, offset, len, unused)
+ * Function irlpt_server_proc_read (buf, start, offset, len, unused)
  *
  *
  *
@@ -137,21 +140,19 @@
 			break;
 		}
 
-		len += sprintf(buf+len, "servicetype: %s\n", 
-			       irlpt_service_type[index]);
-		len += sprintf(buf+len, "porttype: %s\n", 
+		len += sprintf(buf+len, "servicetype: %s, porttype: %s\n",
+			       irlpt_service_type[index],
 			       irlpt_port_type[irlpt_server->porttype]);
-		len += sprintf(buf+len, "daddr: %d\n", 
-			       irlpt_server->daddr);
-		len += sprintf(buf+len, "state: %s\n", 
-			       irlpt_server_fsm_state[irlpt_server->state]);
-		len += sprintf(buf+len, "retries: %d\n", 
-			       irlpt_server->open_retries);
-		len += sprintf(buf+len, "peersap: %d\n", 
+		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, "count: %d\n", 
+		len += sprintf(buf+len, "retries: %d, count: %d\n", 
+			       irlpt_server->open_retries,
 			       irlpt_server->count);
-		len += sprintf(buf+len, "rx_queue: %d\n", 
+		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");
 	}
@@ -258,11 +259,14 @@
  * Function irlpt_disconnect_indication (handle)
  *
  */
-static void irlpt_server_disconnect_indication( void *instance, void *sap, 
+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");
@@ -272,17 +276,22 @@
 	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",
+	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(&irlpt_server_wait);
+        wake_up_interruptible(&self->read_wait);
+	wake_up_interruptible(&self->write_wait);
+	wake_up_interruptible(&self->ex_wait);
 
-	DEBUG( irlpt_server_debug, __FUNCTION__ ": skb_queue_len=%d\n",
+	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);
@@ -298,12 +307,12 @@
  *
  *    LSAP connection confirmed!
  */
-static void irlpt_server_connect_confirm( void *instance, void *sap, 
+static void irlpt_server_connect_confirm( void *instance, 
+					  void *sap, 
 					  struct qos_info *qos,
 					  int max_seg_size,
 					  struct sk_buff *skb)
 {
-	struct irlpt_info info;
 	struct irlpt_cb *self;
 
 	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
@@ -312,21 +321,6 @@
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IRLPT_MAGIC, return;);
 
-	info.daddr = self->daddr;
-
-	/*
-	 *  Check if we have got some QoS parameters back! This should be the
-	 *  negotiated QoS for the link.
-	 */
-	if ( qos) {
-		DEBUG( irlpt_server_debug, __FUNCTION__ 
-		       ": IrLPT Negotiated BAUD_RATE: %02x\n", 
-		       qos->baud_rate.bits);			
-		DEBUG( irlpt_server_debug, __FUNCTION__ 
-		       ": IrLPT Negotiated BAUD_RATE: %d bps.\n", 
-		       qos->baud_rate.value);
-	}
-
 	self->connected = TRUE;
 
 	irlpt_server_do_event( self, LMP_CONNECT, NULL, NULL);
@@ -338,19 +332,20 @@
  * Function irlpt_connect_indication (handle)
  *
  */
-static void irlpt_server_connect_indication( void *instance, void *sap, 
+static void irlpt_server_connect_indication( void *instance, 
+					     void *sap, 
 					     struct qos_info *qos, 
 					     int max_seg_size,
 					     struct sk_buff *skb)
 {
 	struct irlpt_cb *self;
 	struct irlpt_info info;
-	struct lsap_cb *lsap;
 
 	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
 
 	self = ( struct irlpt_cb *) instance;
-	lsap = (struct lsap_cb *) sap;
+
+	info.lsap  = (struct lsap_cb *) sap;
 	
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IRLPT_MAGIC, return;);
@@ -358,8 +353,6 @@
 	self->connected = IRLPT_CONNECTED;
 	self->eof = FALSE;
 
-	info.lsap = lsap;
-
 	irlpt_server_do_event( self, LMP_CONNECT, NULL, &info);
 
 	if (skb) {
@@ -370,12 +363,13 @@
 }
 
 /*
- * Function irlpt_data_indication (handle, skb)
+ * Function irlpt_server_data_indication (handle, skb)
  *
  *    This function gets the data that is received on the data channel
  *
  */
-static void irlpt_server_data_indication( void *instance, void *sap, 
+static void irlpt_server_data_indication( void *instance, 
+					  void *sap, 
 					  struct sk_buff *skb) 
 {
 
@@ -397,7 +391,7 @@
 #endif
 	
 	skb_queue_tail(&self->rx_queue, skb);
-        wake_up_interruptible(&irlpt_server_wait);
+        wake_up_interruptible(&self->read_wait);
 
 	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
 }
@@ -419,9 +413,8 @@
 	/*
 	 *  First register control TSAP
 	 */
-
 	if ( !irlpt_server || irlpt_server->magic != IRLPT_MAGIC) {
-		DEBUG( 0, "irlpt_register_server:, unable to obtain handle!\n");
+		DEBUG( 0, __FUNCTION__ ": unable to obtain handle!\n");
 		return;
 	}
 
@@ -432,12 +425,13 @@
 	notify.disconnect_indication = irlpt_server_disconnect_indication;
 	notify.data_indication = irlpt_server_data_indication;
 	notify.instance = irlpt_server;
-	strcpy(notify.name, "IrLPT");
+	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
@@ -461,35 +455,9 @@
  */
 static void deregister_irlpt_server(void)
 {
-#if 0
-	struct notify_t notify;
-#endif
 	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
 
-#if 0
-	/*
-	 *  First register control TSAP
-	 */
-
-	if ( !irlpt_server || irlpt_server->magic != IRLPT_MAGIC) {
-		DEBUG( 0, "irlpt_register_server:, 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");
-
-	irlpt_server->lsap = irlmp_open_lsap( irlpt_server_lsap, &notify);
-
-	irlpt_server->connected = IRLPT_WAITING;
-	irlpt_server->service_LSAP = irlpt_server_lsap;
-#endif
+	irlpt_server->connected = IRLPT_DISCONNECTED;
 
 	/* 
 	 *  de-Register with LM-IAS
@@ -504,7 +472,9 @@
 #ifdef MODULE
 
 MODULE_AUTHOR("Thomas Davis <ratbert@radiks.net>");
-MODULE_DESCRIPTION("The Linux IrDA/IrLPT protocol");
+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)
@@ -515,11 +485,11 @@
 int init_module(void)
 {
 
-        DEBUG( irlpt_server_debug, "--> irlpt server: init_module\n");
+        DEBUG( irlpt_server_debug, "--> IrLPT server: init_module\n");
 
         irlpt_server_init();
 
-        DEBUG( irlpt_server_debug, "irlpt server: init_module -->\n");
+        DEBUG( irlpt_server_debug, "IrLPT server: init_module -->\n");
 
         return 0;
 }
@@ -532,14 +502,14 @@
  */
 void cleanup_module(void)
 {
-	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
-        DEBUG( 3, "--> irlpt server: cleanup_module\n");
+        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");
+        DEBUG( irlpt_server_debug, "IrLPT server: cleanup_module -->\n");
 }
 
 #endif /* MODULE */
diff -u --recursive --new-file v2.2.2/linux/net/irda/irlpt/irlpt_srvr_fsm.c linux/net/irda/irlpt/irlpt_srvr_fsm.c
--- v2.2.2/linux/net/irda/irlpt/irlpt_srvr_fsm.c	Mon Jan 25 17:44:34 1999
+++ linux/net/irda/irlpt/irlpt_srvr_fsm.c	Sun Mar  7 15:26:44 1999
@@ -4,8 +4,10 @@
  * 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.
+ *     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 
@@ -38,9 +40,10 @@
 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 = 3;
+int irlpt_server_fsm_debug = 4; /* don't change this! */
 
-static int (*irlpt_server_state[])( struct irlpt_cb *self, IRLPT_EVENT event, 
+static int (*irlpt_server_state[])( struct irlpt_cb *self, 
+				    IRLPT_EVENT event, 
 				    struct sk_buff *skb,
 				    struct irlpt_info *info) = 
 { 
@@ -48,10 +51,13 @@
 	irlpt_server_state_conn,
 };
 
-void irlpt_server_do_event( struct irlpt_cb *self, IRLPT_EVENT event, 
-			    struct sk_buff *skb, struct irlpt_info *info) 
+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", 
+	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;);
@@ -62,7 +68,8 @@
 	DEBUG( irlpt_server_fsm_debug, __FUNCTION__ " -->\n");
 }
 
-void irlpt_server_next_state( struct irlpt_cb *self, IRLPT_CLIENT_STATE state) 
+void irlpt_server_next_state( struct irlpt_cb *self, 
+			      IRLPT_CLIENT_STATE state) 
 {
 
 	DEBUG( irlpt_server_fsm_debug, __FUNCTION__ ": NEXT STATE = %s\n", 
@@ -82,7 +89,8 @@
  *    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, 
+static int irlpt_server_state_idle( struct irlpt_cb *self, 
+				    IRLPT_EVENT event, 
 				    struct sk_buff *skb, 
 				    struct irlpt_info *info) 
 {
@@ -96,10 +104,12 @@
 	switch( event) {
 	case LMP_CONNECT:
 		DEBUG( irlpt_server_fsm_debug, __FUNCTION__ 
-		       ": LM_CONNECT, remote lsap=%d\n", 
-		       info->dlsap_sel);
+		       ": LM_CONNECT, remote lsap: 0x%08x\n",
+		       info->lsap->dlsap_sel);
 
-		self->dlsap_sel = info->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) { 
@@ -107,12 +117,9 @@
 				": can't allocate sk_buff of length 64\n");
 			return 0;
 		}
-		ALLOC_SKB_MAGIC(r_skb);
 		skb_reserve( r_skb, LMP_MAX_HEADER);
-		skb->len = 0;
 		irlmp_connect_response( self->lsap, r_skb);
 		irlpt_server_next_state( self, IRLPT_SERVER_CONN);
-
 		break;
 
 	default:
diff -u --recursive --new-file v2.2.2/linux/net/irda/irmod.c linux/net/irda/irmod.c
--- v2.2.2/linux/net/irda/irmod.c	Wed Jan 20 23:14:07 1999
+++ linux/net/irda/irmod.c	Sun Mar  7 15:26:44 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Dec 15 13:55:39 1997
- * Modified at:   Tue Jan 19 23:34:18 1999
+ * Modified at:   Thu Feb 18 08:51:50 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997 Dag Brattli, All Rights Reserved.
@@ -24,14 +24,28 @@
 
 #include <linux/config.h>
 #include <linux/module.h> 
+
 #include <linux/init.h>
-#include <asm/segment.h>
 #include <linux/poll.h>
+#include <asm/segment.h>
+
+#include <linux/proc_fs.h>
 
 #include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irlap.h>
+#ifdef CONFIG_IRDA_COMPRESSION
+#include <net/irda/irlap_comp.h>
+#endif /* CONFIG_IRDA_COMPRESSION */
 #include <net/irda/irlmp.h>
 #include <net/irda/iriap.h>
+#include <net/irda/irias_object.h>
 #include <net/irda/irttp.h>
+#include <net/irda/irda_device.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/timer.h>
+
+extern struct proc_dir_entry proc_irda;
 
 struct irda_cb irda; /* One global instance */
 
@@ -57,15 +71,15 @@
 extern int irlpt_client_init(void);
 extern int irlpt_server_init(void);
 
-static int irda_open( struct inode * inode, struct file *file);
-static int irda_ioctl( struct inode *inode, struct file *filp, 
-			 unsigned int cmd, unsigned long arg);
-static int irda_close( struct inode *inode, struct file *file);
-static ssize_t irda_read( struct file *file, 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);
-static u_int irda_poll( struct file *file, poll_table *wait);
+static int irda_open(struct inode * inode, struct file *file);
+static int irda_ioctl(struct inode *inode, struct file *filp, 
+		      unsigned int cmd, unsigned long arg);
+static int irda_close(struct inode *inode, struct file *file);
+static ssize_t irda_read(struct file *file, 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);
+static u_int irda_poll(struct file *file, poll_table *wait);
 
 static struct file_operations irda_fops = {
 	NULL,	       /* seek */
@@ -82,13 +96,95 @@
 	NULL,          /* fasync */
 };
 
+/* IrTTP */
+EXPORT_SYMBOL(irttp_open_tsap);
+EXPORT_SYMBOL(irttp_close_tsap);
+EXPORT_SYMBOL(irttp_connect_response);
+EXPORT_SYMBOL(irttp_data_request);
+EXPORT_SYMBOL(irttp_disconnect_request);
+EXPORT_SYMBOL(irttp_flow_request);
+EXPORT_SYMBOL(irttp_connect_request);
+EXPORT_SYMBOL(irttp_udata_request);
+
+/* Main IrDA module */
+#ifdef CONFIG_IRDA_DEBUG
+EXPORT_SYMBOL(irda_debug);
+#endif
+EXPORT_SYMBOL(irda_notify_init);
+EXPORT_SYMBOL(irmanager_notify);
+EXPORT_SYMBOL(irda_lock);
+EXPORT_SYMBOL(proc_irda);
+
+/* IrIAP/IrIAS */
+EXPORT_SYMBOL(iriap_getvaluebyclass_request);
+EXPORT_SYMBOL(irias_object_change_attribute);
+EXPORT_SYMBOL(irias_add_integer_attrib);
+EXPORT_SYMBOL(irias_add_octseq_attrib);
+EXPORT_SYMBOL(irias_add_string_attrib);
+EXPORT_SYMBOL(irias_insert_object);
+EXPORT_SYMBOL(irias_new_object);
+EXPORT_SYMBOL(irias_delete_object);
+EXPORT_SYMBOL(irias_find_object);
+EXPORT_SYMBOL(irias_find_attrib);
+EXPORT_SYMBOL(irias_new_integer_value);
+EXPORT_SYMBOL(irias_new_string_value);
+EXPORT_SYMBOL(irias_new_octseq_value);
+
+/* IrLMP */
+EXPORT_SYMBOL(irlmp_discovery_request);
+EXPORT_SYMBOL(irlmp_register_layer);
+EXPORT_SYMBOL(irlmp_unregister_layer);
+EXPORT_SYMBOL(irlmp_data_request);
+EXPORT_SYMBOL(irlmp_open_lsap);
+EXPORT_SYMBOL(irlmp_close_lsap);
+EXPORT_SYMBOL(irlmp_connect_request);
+EXPORT_SYMBOL(irlmp_connect_response);
+EXPORT_SYMBOL(irlmp_disconnect_request);
+EXPORT_SYMBOL(irlmp_get_daddr);
+EXPORT_SYMBOL(irlmp_get_saddr);
+EXPORT_SYMBOL(lmp_reasons);
+
+/* Queue */
+EXPORT_SYMBOL(hashbin_find);
+EXPORT_SYMBOL(hashbin_new);
+EXPORT_SYMBOL(hashbin_insert);
+EXPORT_SYMBOL(hashbin_delete);
+EXPORT_SYMBOL(hashbin_remove);
+EXPORT_SYMBOL(hashbin_get_next);
+EXPORT_SYMBOL(hashbin_get_first);
+
+/* IrLAP */
+#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(async_wrap_skb);
+EXPORT_SYMBOL(async_unwrap_char);
+EXPORT_SYMBOL(irda_start_timer);
+EXPORT_SYMBOL(irda_get_mtt);
+EXPORT_SYMBOL(setup_dma);
+
+#ifdef CONFIG_IRTTY
+EXPORT_SYMBOL(irtty_set_dtr_rts);
+EXPORT_SYMBOL(irtty_register_dongle);
+EXPORT_SYMBOL(irtty_unregister_dongle);
+#endif
+
 __initfunc(int irda_init(void))
 {
-        printk( KERN_INFO "Linux Support for the IrDA (tm) protocols (Dag Brattli)\n");
+        printk(KERN_INFO "Linux-2.2 Support for the IrDA (tm) Protocols (Dag Brattli)\n");
 
-	irda_device_init();
-	irlap_init();
  	irlmp_init();
+	irlap_init();
+	irda_device_init();
+
 	iriap_init();
  	irttp_init();
 	
@@ -113,12 +209,6 @@
 #ifdef CONFIG_IRLAN
 	irlan_init();
 #endif
-#ifdef CONFIG_IRLAN_CLIENT
-	irlan_client_init();
-#endif
-#ifdef CONFIG_IRLAN_SERVER
-	irlan_server_init();
-#endif
 #ifdef CONFIG_IROBEX
 	irobex_init();
 #endif
@@ -135,9 +225,21 @@
 	irlpt_server_init();
 #endif
 
+#ifdef CONFIG_IRDA_COMPRESSION
+#ifdef CONFIG_IRDA_DEFLATE
+	irda_deflate_init();
+#endif /* CONFIG_IRDA_DEFLATE */
+#endif /* CONFIG_IRDA_COMPRESSION */
+
 	return 0;
 }
 
+/* 
+ * FIXME:
+ * This function should have been wrapped with #ifdef MODULE, but then
+ * irda_proto_cleanup() must be moved from af_irda.c to this file since
+ * that function must also be wrapped if this one is.
+ */
 void irda_cleanup(void)
 {
 	misc_deregister( &irda.dev);
@@ -168,10 +270,12 @@
  *    Lock variable. Returns false if the lock is already set.
  *    
  */
-inline int irda_lock( int *lock) {
-	if ( test_and_set_bit( 0, (void *) lock))  {
-             printk("Trying to lock, already locked variable!\n");
-	     return FALSE;
+inline int irda_lock(int *lock) 
+{
+	if (test_and_set_bit( 0, (void *) lock))  {
+		DEBUG(3, __FUNCTION__ 
+		      "(), Trying to lock, already locked variable!\n");
+		return FALSE;
         }  
 	return TRUE;
 }
@@ -182,8 +286,9 @@
  *    Unlock variable. Returns false if lock is already unlocked
  *
  */
-inline int irda_unlock( int *lock) {
-	if ( !test_and_clear_bit( 0, (void *) lock))  {
+inline int irda_unlock(int *lock) 
+{
+	if (!test_and_clear_bit(0, (void *) lock))  {
 		printk("Trying to unlock already unlocked variable!\n");
 		return FALSE;
         }
@@ -198,7 +303,6 @@
  */
 void irda_notify_init( struct notify_t *notify)
 {
-
 	notify->data_indication = NULL;
 	notify->udata_indication = NULL;
 	notify->connect_confirm = NULL;
@@ -402,9 +506,19 @@
 }
 
 #ifdef MODULE
+#ifdef CONFIG_PROC_FS
+void irda_proc_modcount(struct inode *inode, int fill)
+{
+	if (fill)
+		MOD_INC_USE_COUNT;
+	else
+		MOD_DEC_USE_COUNT;
+}
+#endif /* CONFIG_PROC_FS */
 
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
 MODULE_DESCRIPTION("The Linux IrDA protocol subsystem"); 
+MODULE_PARM(irda_debug, "1l");
 
 /*
  * Function init_module (void)
diff -u --recursive --new-file v2.2.2/linux/net/irda/irobex/irobex.c linux/net/irda/irobex/irobex.c
--- v2.2.2/linux/net/irda/irobex/irobex.c	Wed Jan 20 23:14:07 1999
+++ linux/net/irda/irobex/irobex.c	Sun Mar  7 15:26:44 1999
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irobex.c
- * Version:       0.3
+ * Version:       0.4
  * Description:   Kernel side of the IrOBEX layer
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Jun 25 21:21:07 1998
- * Modified at:   Sat Jan 16 22:18:03 1999
+ * Modified at:   Mon Feb  8 09:05:01 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -46,6 +46,8 @@
  */
 struct irobex_cb *irobex;
 
+extern char *lmp_reasons[];
+
 char *irobex_state[] = {
 	"OBEX_IDLE",
 	"OBEX_DISCOVER",
@@ -54,10 +56,29 @@
 	"OBEX_DATA",
 };
 
-static int irobex_dev_open( struct inode * inode, struct file *file);
+static void   irobex_cleanup(void);
+/* static struct irobex_cb *irobex_open(void); */
+/* static void   irobex_close( struct irobex_cb *self); */
+
+static void irobex_data_indication( void *instance, void *sap, 
+				    struct sk_buff *skb);
+static void irobex_disconnect_indication( void *instance, void *sap, 
+					  LM_REASON reason, 
+					  struct sk_buff *skb);
+static void irobex_disconnect_request( struct irobex_cb *self);
+static int irobex_connect_request(struct irobex_cb *self);
+static void irobex_connect_confirm( void *instance, void *sap, 
+				    struct qos_info *qos,
+				    int max_sdu_size, struct sk_buff *skb);
+static void irobex_discovery_indication( DISCOVERY *discovery);
+static void irobex_flow_indication( void *instance, void *sap, 
+				    LOCAL_FLOW flow);
+static void irobex_get_value_confirm(__u16 obj_id, struct ias_value *value, 
+				     void *priv);
+static void irobex_register_server( struct irobex_cb *self);
 static int irobex_ioctl( struct inode *inode, struct file *filp, 
 			 unsigned int cmd, unsigned long arg);
-
+static int irobex_dev_open( struct inode * inode, struct file *file);
 static int irobex_dev_close( struct inode *inode, struct file *file);
 static ssize_t irobex_read( struct file *file, char *buffer, size_t count, 
 			    loff_t *noidea);
@@ -105,6 +126,7 @@
  */
 __initfunc(int irobex_init(void))
 {
+	struct irmanager_event mgr_event;
 	struct irobex_cb *self;
 
 	self = kmalloc(sizeof(struct irobex_cb), GFP_ATOMIC);
@@ -134,6 +156,10 @@
 		
 	irlmp_register_layer( S_OBEX, CLIENT | SERVER, TRUE, 
 			      irobex_discovery_indication);
+
+/* 	mgr_event.event = EVENT_IROBEX_INIT; */
+/* 	sprintf( mgr_event.devname, "%s", self->devname); */
+/* 	irmanager_notify( &mgr_event); */
 	
 	return 0;
 }
@@ -145,7 +171,7 @@
  *
  */
 #ifdef MODULE
-void irobex_cleanup(void)
+static void irobex_cleanup(void)
 {
 	struct sk_buff *skb;
 	struct irobex_cb *self;
@@ -163,6 +189,7 @@
 	irlmp_unregister_layer( S_OBEX, CLIENT | SERVER);
 
 	if ( self->tsap) {
+		irttp_disconnect_request(self->tsap, NULL, P_NORMAL);
 		irttp_close_tsap( self->tsap);
 		self->tsap = NULL;
 	}
@@ -207,8 +234,7 @@
   
 	DEBUG( 4, __FUNCTION__ ": count=%d, skb_len=%d, state=%s, eof=%d\n", 
 	       count, skb_queue_len( &self->rx_queue), 
-	       irobex_state[self->state], 
-	       self->eof);
+	       irobex_state[self->state], self->eof);
 
 	if ( self->state != OBEX_DATA) {
 		DEBUG( 0, __FUNCTION__ "(), link not connected yet!\n");
@@ -446,8 +472,8 @@
 
 	self = irobex;
 	
-	ASSERT( self != NULL, return -ENOTTY;);
-	ASSERT( self->magic = IROBEX_MAGIC, return -ENOTTY;);
+	ASSERT(self != NULL, return -ENOTTY;);
+	ASSERT(self->magic == IROBEX_MAGIC, return -ENOTTY;);
 	
 	if ( _IOC_TYPE(cmd) != IROBEX_IOC_MAGIC) 
 		return -EINVAL;
@@ -464,107 +490,11 @@
 	switch ( cmd) {
 	case IROBEX_IOCSCONNECT:
 		DEBUG( 4, __FUNCTION__ "(): IROBEX_IOCSCONNECT!\n");
-		
-		/* Already connected? */
-		if ( self->state == OBEX_DATA) {
-			DEBUG( 0, __FUNCTION__ "(), already connected!\n");
-			return 0;
-		}
-		
-		/* Timeout after 15 secs. */
-		irobex_start_watchdog_timer( self, 1000);
-
-		/*
-		 * If we have discovered a remote device we
-		 * check if the discovery is still fresh. If not, we don't
-		 * trust the address.
-		 */
-		if ( self->daddr && ((jiffies - self->time_discovered) > 500))
-			self->daddr = 0;
-
-		/* 
-		 * Try to discover remote remote device if it has not been 
-		 * discovered yet. 
-		 */
-		if ( !self->daddr) {
-			self->state = OBEX_DISCOVER;
-			
-			irlmp_discovery_request( 8);
-			
-			/* Wait for discovery to complete */
-			interruptible_sleep_on( &self->write_wait);
-			del_timer( &self->watchdog_timer);
-		}
-		
-		/* Give up if we are unable to discover any remote devices */
-		if ( !self->daddr) {
-			DEBUG( 0, __FUNCTION__ 
-			       "(), Unable to discover any devices!\n");
-			return -ENOTTY;
-		}
-		
-		/* Need to find remote destination TSAP selector? */
-		if ( !self->dtsap_sel) {
-			DEBUG( 0, __FUNCTION__ "() : Quering remote IAS!\n");
-			
-			self->state = OBEX_QUERY;
-			
-			/* Timeout after 5 secs. */
-			irobex_start_watchdog_timer( self, 500);
-			iriap_getvaluebyclass_request( 
-				self->daddr,
-				"OBEX", 
-				"IrDA:TinyTP:LsapSel",
-				irobex_get_value_confirm,
-				self);
-			
-			interruptible_sleep_on( &self->write_wait);
-			del_timer( &self->watchdog_timer);
-		}	
-		
-		if ( !self->dtsap_sel) {
-			DEBUG( 0, __FUNCTION__ 
-			       "(), Unable to query remote LM-IAS!\n");
-			return -ENOTTY;
-		}
-
-		self->state = OBEX_CONN;
-		
-		/* Timeout after 5 secs. */
-		irobex_start_watchdog_timer( self, 500);
-
-		irttp_connect_request( self->tsap, self->dtsap_sel, 
-				       self->daddr, NULL, SAR_DISABLE, 
-				       NULL);
-		
-		/* Go to sleep and wait for connection!  */
-		interruptible_sleep_on( &self->write_wait);
-		del_timer( &self->watchdog_timer);
-		
-		if ( self->state != OBEX_DATA) {
-			DEBUG( 0, __FUNCTION__ 
-			       "(), Unable to connect to remote device!\n");
-			return -ENOTTY;
-		}
-		
+		return irobex_connect_request( self);		
 		break;
 	case IROBEX_IOCSDISCONNECT:
 		DEBUG( 4, __FUNCTION__ "(): IROBEX_IOCSDISCONNECT!\n");
-
-		if ( self->state != OBEX_DATA)
-			return 0;
-
-		irttp_disconnect_request( self->tsap, NULL, P_NORMAL);
-
-		/* Reset values for this instance */
-		self->state = OBEX_IDLE;
-		self->eof = LM_USER_REQUEST;
-		self->daddr = 0;
-		self->dtsap_sel = 0;
-		self->rx_flow = FLOW_START;
-		self->tx_flow = FLOW_START;
-		
-		wake_up_interruptible( &self->read_wait);
+		irobex_disconnect_request( self);
 		break;
 	default:
 		return -EINVAL;
@@ -631,6 +561,7 @@
 
 	/* Close TSAP is its still there */
 	if ( self->tsap) {
+		irttp_disconnect_request(self->tsap, NULL, P_NORMAL);
 		irttp_close_tsap( self->tsap);
 		self->tsap = NULL;
 	}
@@ -658,11 +589,11 @@
  *    device it is, and which services it has.
  *
  */
-void irobex_discovery_indication( DISCOVERY *discovery) 
+static void irobex_discovery_indication( DISCOVERY *discovery)
 {
  	struct irobex_cb *self;
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG( 0, __FUNCTION__ "()\n");
 	
 	self = irobex;
 
@@ -671,6 +602,7 @@
 
 	/* Remember address and time if was discovered */
 	self->daddr = discovery->daddr;
+	self->saddr = discovery->saddr;
 	self->time_discovered = jiffies;
 	
 	/* Wake up process if its waiting for device to be discovered */
@@ -678,18 +610,37 @@
 		wake_up_interruptible( &self->write_wait);
 }
 
+static void irobex_disconnect_request( struct irobex_cb *self)
+{
+	if ( self->state != OBEX_DATA)
+		return;
+	
+	irttp_disconnect_request( self->tsap, NULL, P_NORMAL);
+	
+	/* Reset values for this instance */
+	self->state = OBEX_IDLE;
+	self->eof = LM_USER_REQUEST;
+	self->daddr = 0;
+	self->dtsap_sel = 0;
+	self->rx_flow = FLOW_START;
+	self->tx_flow = FLOW_START;
+		
+	wake_up_interruptible( &self->read_wait);
+}
+
 /*
  * Function irobex_disconnect_indication (handle, reason, priv)
  *
  *    Link has been disconnected
  *
  */
-void irobex_disconnect_indication( void *instance, void *sap, 
-				   LM_REASON reason, struct sk_buff *userdata)
+static void irobex_disconnect_indication( void *instance, void *sap, 
+					  LM_REASON reason, 
+					  struct sk_buff *userdata)
 {
 	struct irobex_cb *self;
 	
-	DEBUG( 4, __FUNCTION__ "(), reason=%d\n", reason);
+	DEBUG( 0, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);
 	
 	self = ( struct irobex_cb *) instance;
 	
@@ -712,14 +663,105 @@
 	        dev_kfree_skb( userdata);
 }
 
+int irobex_connect_request(struct irobex_cb *self)
+{
+	int count = 0;
+
+	/* Already connected? */
+	if ( self->state == OBEX_DATA) {
+		DEBUG( 0, __FUNCTION__ "(), already connected!\n");
+		return 0;
+	}
+	
+	/* Timeout after 15 secs. */
+	irobex_start_watchdog_timer( self, 1000);
+	
+	/*
+	 * If we have discovered a remote device we
+	 * check if the discovery is still fresh. If not, we don't
+	 * trust the address.
+	 */
+	if ( self->daddr && ((jiffies - self->time_discovered) > 1000)) {
+		DEBUG( 0, __FUNCTION__ "(), daddr is old <%d>!\n",
+		       jiffies - self->time_discovered);
+		self->daddr = 0;
+	}
+	
+	/* 
+	 * Try to discover remote remote device if it has not been 
+	 * discovered yet. 
+	 */
+	if ( !self->daddr) {
+		self->state = OBEX_DISCOVER;
+		
+		irlmp_discovery_request( 8);
+		
+		/* Wait for discovery to complete */
+		interruptible_sleep_on( &self->write_wait);
+		del_timer( &self->watchdog_timer);
+	}
+	
+	/* Give up if we are unable to discover any remote devices */
+	if ( !self->daddr) {
+		DEBUG( 0, __FUNCTION__ 
+		       "(), Unable to discover any devices!\n");
+		return -EHOSTUNREACH;
+	}
+	
+	/* Need to find remote destination TSAP selector? */
+	while ( !self->dtsap_sel) {
+		DEBUG( 0, __FUNCTION__ "() : Quering remote IAS!\n");
+		
+		self->state = OBEX_QUERY;
+		
+		/* Timeout after 5 secs. */
+		irobex_start_watchdog_timer( self, 500);
+		iriap_getvaluebyclass_request( 
+			"OBEX", "IrDA:TinyTP:LsapSel",
+			self->saddr, self->daddr,
+			irobex_get_value_confirm,
+			self);
+		
+		interruptible_sleep_on( &self->write_wait);
+		del_timer( &self->watchdog_timer);
+		
+		/* Give up after a few tries */
+		if (( count++ > 2) && !self->dtsap_sel) {
+			DEBUG( 0, __FUNCTION__ 
+			       "(), Unable to query remote LM-IAS!\n");
+			return -ETIMEDOUT;
+		}
+	}
+	self->state = OBEX_CONN;
+	
+	/* Timeout after 5 secs. */
+	irobex_start_watchdog_timer( self, 500);
+	
+	irttp_connect_request( self->tsap, self->dtsap_sel, 
+			       self->saddr, self->daddr, NULL, SAR_DISABLE, 
+			       NULL);
+	
+	/* Go to sleep and wait for connection!  */
+	interruptible_sleep_on( &self->write_wait);
+	del_timer( &self->watchdog_timer);
+	
+	if ( self->state != OBEX_DATA) {
+		DEBUG( 0, __FUNCTION__ 
+		       "(), Unable to connect to remote device!\n");
+		return -ETIMEDOUT;
+	}
+	return 0;
+}
+
 /*
  * Function irobex_connect_confirm (instance, sap, qos, userdata)
  *
  *    Connection to peer IrOBEX layer established
  *
  */
-void irobex_connect_confirm( void *instance, void *sap, struct qos_info *qos,
-			     int max_sdu_size, struct sk_buff *userdata)
+static void irobex_connect_confirm( void *instance, void *sap, 
+				    struct qos_info *qos,
+				    int max_sdu_size, struct sk_buff *userdata)
 {
 	struct irobex_cb *self;
 	
@@ -834,7 +876,8 @@
  *    This function gets the data that is received on the data channel
  *
  */
-void irobex_data_indication( void *instance, void *sap, struct sk_buff *skb) 
+static void irobex_data_indication( void *instance, void *sap, 
+				    struct sk_buff *skb) 
 {
 
 	struct irobex_cb *self;
@@ -876,7 +919,8 @@
  *    
  *
  */
-void irobex_flow_indication( void *instance, void *sap, LOCAL_FLOW flow) 
+static void irobex_flow_indication( void *instance, void *sap, 
+				    LOCAL_FLOW flow) 
 {
 	struct irobex_cb *self;
 
@@ -908,8 +952,8 @@
  *    Got results from previous GetValueByClass request
  *
  */
-void irobex_get_value_confirm( __u16 obj_id, struct ias_value *value, 
-			       void *priv)
+static void irobex_get_value_confirm( __u16 obj_id, struct ias_value *value, 
+				      void *priv)
 {
 	struct irobex_cb *self;
 	
@@ -919,7 +963,14 @@
 	self = ( struct irobex_cb *) priv;
 	
 	if ( !self || self->magic != IROBEX_MAGIC) {
-		DEBUG( 0, "irobex_get_value_confirm: bad magic!\n");
+		DEBUG( 0, __FUNCTION__ "(), bad magic!\n");
+		return;
+	}
+
+	/* Check if request succeeded */
+	if ( !value) {
+		DEBUG( 0, __FUNCTION__ "(), got NULL value!\n");
+
 		return;
 	}
 
@@ -996,7 +1047,7 @@
  *    must register both a TSAP for control and data
  * 
  */
-void irobex_register_server( struct irobex_cb *self)
+static void irobex_register_server( struct irobex_cb *self)
 {
 	struct notify_t notify;
 	struct ias_object *obj;
diff -u --recursive --new-file v2.2.2/linux/net/irda/irproc.c linux/net/irda/irproc.c
--- v2.2.2/linux/net/irda/irproc.c	Wed Jan 20 23:14:07 1999
+++ linux/net/irda/irproc.c	Sun Mar  7 15:26:44 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Thomas Davis, <ratbert@radiks.net>
  * Created at:    Sat Feb 21 21:33:24 1998
- * Modified at:   Tue Dec 15 09:21:50 1998
+ * Modified at:   Thu Feb 11 15:23:23 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>, 
@@ -31,27 +31,24 @@
 #include <net/irda/irlap.h>
 #include <net/irda/irlmp.h>
 
-static int proc_irda_21x_lookup(struct inode * dir, struct dentry *dentry);
+static int proc_irda_lookup(struct inode * dir, struct dentry *dentry);
 
 static int proc_irda_readdir(struct file *filp, void *dirent, 
  			     filldir_t filldir);
 
-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, 
-			    int unused);
-extern int irttp_proc_read( char *buf, char **start, off_t offset, int len, 
-			    int unused);
-extern int irias_proc_read( char *buf, char **start, off_t offset, int len,
- 			    int unused);
+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, 
+			   int unused);
+extern int irttp_proc_read(char *buf, char **start, off_t offset, int len, 
+			   int unused);
+extern int irias_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);
-
-/* int proc_irda_readdir(struct inode *inode, struct file *filp, void *dirent,  */
-/* 		      filldir_t filldir); */
+static int proc_discovery_read(char *buf, char **start, off_t offset, int len,
+			       int unused);
 
 enum irda_directory_inos {
 	PROC_IRDA_LAP = 1,
@@ -82,7 +79,7 @@
 struct inode_operations proc_irda_dir_inode_operations = {
         &proc_irda_dir_operations,   /* default net directory file-ops */
         NULL,                   /* create */
-	proc_irda_21x_lookup, 
+	proc_irda_lookup, 
         NULL,                   /* link */
         NULL,                   /* unlink */
         NULL,                   /* symlink */
@@ -186,13 +183,14 @@
  *
  */
 void irda_proc_register(void) {
-	proc_net_register( &proc_irda);
-	proc_register( &proc_irda, &proc_lap);
-	proc_register( &proc_irda, &proc_lmp);
-	proc_register( &proc_irda, &proc_ttp);
-	proc_register( &proc_irda, &proc_ias);
- 	proc_register( &proc_irda, &proc_irda_device); 
-	proc_register( &proc_irda, &proc_discovery);
+	proc_net_register(&proc_irda);
+	proc_irda.fill_inode = &irda_proc_modcount;
+	proc_register(&proc_irda, &proc_lap);
+	proc_register(&proc_irda, &proc_lmp);
+	proc_register(&proc_irda, &proc_ttp);
+	proc_register(&proc_irda, &proc_ias);
+ 	proc_register(&proc_irda, &proc_irda_device); 
+	proc_register(&proc_irda, &proc_discovery);
 }
 
 /*
@@ -202,22 +200,22 @@
  *
  */
 void irda_proc_unregister(void) {
-	proc_unregister( &proc_irda, proc_discovery.low_ino);
+	proc_unregister(&proc_irda, proc_discovery.low_ino);
  	proc_unregister(&proc_irda, proc_irda_device.low_ino);
-	proc_unregister( &proc_irda, proc_ias.low_ino);
-	proc_unregister( &proc_irda, proc_ttp.low_ino);
-	proc_unregister( &proc_irda, proc_lmp.low_ino);
-	proc_unregister( &proc_irda, proc_lap.low_ino);
-	proc_unregister( proc_net, proc_irda.low_ino);
+	proc_unregister(&proc_irda, proc_ias.low_ino);
+	proc_unregister(&proc_irda, proc_ttp.low_ino);
+	proc_unregister(&proc_irda, proc_lmp.low_ino);
+	proc_unregister(&proc_irda, proc_lap.low_ino);
+	proc_unregister(proc_net, proc_irda.low_ino);
 }
 
 /*
- * Function proc_irda_21x_lookup (dir, dentry)
+ * Function proc_irda_lookup (dir, dentry)
  *
- *    This is a copy of proc_lookup from the linux-2.1.x 
+ *    This is a copy of proc_lookup from the linux-2.2.x kernel
  *
  */
-int proc_irda_21x_lookup(struct inode * dir, struct dentry *dentry)
+int proc_irda_lookup(struct inode * dir, struct dentry *dentry)
 {
 	struct inode *inode;
 	struct proc_dir_entry * de;
@@ -261,8 +259,8 @@
  *    to the irda module
  * 
  */
-static int proc_irda_readdir( struct file *filp, void *dirent, 
-			      filldir_t filldir)
+static int proc_irda_readdir(struct file *filp, void *dirent, 
+			     filldir_t filldir)
 {
 	struct proc_dir_entry * de;
 	unsigned int ino;
@@ -319,8 +317,8 @@
  *    Print discovery information in /proc file system
  *
  */
-int proc_discovery_read( char *buf, char **start, off_t offset, int len, 
-			 int unused)
+int proc_discovery_read(char *buf, char **start, off_t offset, int len, 
+			int unused)
 {
 	DISCOVERY *discovery;
 	struct lap_cb *lap;
diff -u --recursive --new-file v2.2.2/linux/net/irda/irqueue.c linux/net/irda/irqueue.c
--- v2.2.2/linux/net/irda/irqueue.c	Wed Jan 20 23:14:07 1999
+++ linux/net/irda/irqueue.c	Sun Mar  7 15:26:44 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Jun  9 13:29:31 1998
- * Modified at:   Wed Jan 13 21:21:22 1999
+ * Modified at:   Mon Feb  8 09:05:51 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (C) 1998, Aage Kvalnes <aage@cs.uit.no>
@@ -55,6 +55,8 @@
 	 * Allocate new hashbin
 	 */
 	hashbin = kmalloc( sizeof(hashbin_t), GFP_ATOMIC);
+	if (!hashbin)
+		return NULL;
 
 	/*
 	 * Initialize structure
@@ -205,13 +207,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* entry, __u32 hashv, char* name)
 {
 	unsigned long flags = 0;
 	int bin;
 
-	DEBUG( 4, "hashbin_insert()\n");
+	DEBUG( 4, __FUNCTION__"()\n");
 
 	ASSERT( hashbin != NULL, return;);
 	ASSERT( hashbin->magic == HB_MAGIC, return;);
@@ -583,7 +584,7 @@
 void enqueue_first(QUEUE **queue, QUEUE* element)
 {
 	
-	DEBUG( 4, "enqueue_first()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 
 	/*
 	 * Check if queue is empty.
diff -u --recursive --new-file v2.2.2/linux/net/irda/irsysctl.c linux/net/irda/irsysctl.c
--- v2.2.2/linux/net/irda/irsysctl.c	Mon Jan 25 17:44:34 1999
+++ linux/net/irda/irsysctl.c	Sun Mar  7 15:26:44 1999
@@ -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 Jan  7 10:35:02 1999
+ * Modified at:   Mon Jan 25 13:55:54 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997 Dag Brattli, All Rights Reserved.
@@ -31,9 +31,11 @@
 #include <net/irda/irda.h>
 
 #define NET_IRDA 412 /* Random number */
-enum { DISCOVERY=1, DEVNAME, COMPRESSION, DEBUG };
+enum { DISCOVERY=1, DEVNAME, COMPRESSION, DEBUG, SLOTS, SLOT_TIMEOUT };
 
 extern int sysctl_discovery;
+extern int sysctl_discovery_slots;
+extern int sysctl_slot_timeout;
 int sysctl_compression = 0;
 extern char sysctl_devname[];
 
@@ -53,6 +55,10 @@
 	{ DEBUG, "debug", &irda_debug,
 	  sizeof(int), 0644, NULL, &proc_dointvec },
 #endif
+	{ SLOTS, "discovery_slots", &sysctl_discovery_slots,
+	  sizeof(int), 0644, NULL, &proc_dointvec },
+	{ SLOT_TIMEOUT, "slot_timeout", &sysctl_slot_timeout,
+	  sizeof(int), 0644, NULL, &proc_dointvec },
 	{ 0 }
 };
 
diff -u --recursive --new-file v2.2.2/linux/net/irda/irttp.c linux/net/irda/irttp.c
--- v2.2.2/linux/net/irda/irttp.c	Wed Jan 20 23:14:07 1999
+++ linux/net/irda/irttp.c	Sun Mar  7 15:26:44 1999
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irttp.c
- * Version:       0.4
+ * Version:       1.0
  * Description:   Tiny Transport Protocol (TTP) implementation
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:31 1997
- * Modified at:   Tue Jan 19 23:56:58 1999
+ * Modified at:   Sat Feb 20 01:30:39 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
@@ -35,26 +35,26 @@
 
 struct irttp_cb *irttp = NULL;
 
-static void __irttp_close_tsap( struct tsap_cb *self);
+static void __irttp_close_tsap(struct tsap_cb *self);
 
-static void irttp_data_indication( void *instance, void *sap, 
+static void irttp_data_indication(void *instance, void *sap, 
+				  struct sk_buff *skb);
+static void irttp_udata_indication(void *instance, void *sap, 
 				   struct sk_buff *skb);
-static void irttp_udata_indication( void *instance, void *sap, 
-				    struct sk_buff *skb);
-static void irttp_disconnect_indication( void *instance, void *sap,  
-					 LM_REASON reason,
-					 struct sk_buff *);
-static void irttp_connect_indication( void *instance, void *sap, 
-				      struct qos_info *qos, int max_sdu_size,
-				      struct sk_buff *skb);
-
-static void irttp_run_tx_queue( struct tsap_cb *self);
-static void irttp_run_rx_queue( struct tsap_cb *self);
-
-static void irttp_flush_queues( struct tsap_cb *self);
-static void irttp_fragment_skb( struct tsap_cb *self, struct sk_buff *skb);
-static struct sk_buff *irttp_reassemble_skb( struct tsap_cb *self);
-static void irttp_start_todo_timer( struct tsap_cb *self, int timeout);
+static void irttp_disconnect_indication(void *instance, void *sap,  
+					LM_REASON reason,
+					struct sk_buff *);
+static void irttp_connect_indication(void *instance, void *sap, 
+				     struct qos_info *qos, int max_sdu_size,
+				     struct sk_buff *skb);
+
+static void irttp_run_tx_queue(struct tsap_cb *self);
+static void irttp_run_rx_queue(struct tsap_cb *self);
+
+static void irttp_flush_queues(struct tsap_cb *self);
+static void irttp_fragment_skb(struct tsap_cb *self, struct sk_buff *skb);
+static struct sk_buff *irttp_reassemble_skb(struct tsap_cb *self);
+static void irttp_start_todo_timer(struct tsap_cb *self, int timeout);
 
 /*
  * Function irttp_init (void)
@@ -64,21 +64,19 @@
  */
 __initfunc(int irttp_init(void))
 {
-	DEBUG( 4, "--> irttp_init\n");
-
 	/* Initialize the irttp structure. */
-	if ( irttp == NULL) {
-		irttp = kmalloc( sizeof(struct irttp_cb), GFP_KERNEL);
-		if ( irttp == NULL)
+	if (irttp == NULL) {
+		irttp = kmalloc(sizeof(struct irttp_cb), GFP_KERNEL);
+		if (irttp == NULL)
 			return -ENOMEM;
 	}
-	memset( irttp, 0, sizeof(struct irttp_cb));
-
+	memset(irttp, 0, sizeof(struct irttp_cb));
+	
 	irttp->magic = TTP_MAGIC;
 
-	irttp->tsaps = hashbin_new( HB_LOCAL);
-	if ( !irttp->tsaps) {
-		printk( KERN_WARNING "IrDA: Can't allocate IrTTP hashbin!\n");
+	irttp->tsaps = hashbin_new(HB_LOCAL);
+	if (!irttp->tsaps) {
+		printk(KERN_WARNING "IrDA: Can't allocate IrTTP hashbin!\n");
 		return -ENOMEM;
 	}
 	
@@ -91,69 +89,69 @@
  *    Called by module destruction/cleanup code
  *
  */
+#ifdef MODULE
 void irttp_cleanup(void) 
 {
-	DEBUG( 4, "irttp_cleanup\n");
-	
 	/* Check for main structure */
-	ASSERT( irttp != NULL, return;);
-	ASSERT( irttp->magic == TTP_MAGIC, return;);
+	ASSERT(irttp != NULL, return;);
+	ASSERT(irttp->magic == TTP_MAGIC, return;);
 	
 	/*
 	 *  Delete hashbin and close all TSAP instances in it
 	 */
-	hashbin_delete( irttp->tsaps, (FREE_FUNC) __irttp_close_tsap);
+	hashbin_delete(irttp->tsaps, (FREE_FUNC) __irttp_close_tsap);
 
-	irttp->magic = ~TTP_MAGIC;
+	irttp->magic = 0;
 	
 	/* De-allocate main structure */
-	kfree( irttp);
+	kfree(irttp);
 
 	irttp = NULL;
 }
+#endif
 
 /*
  * Function irttp_open_tsap (stsap, notify)
  *
  *    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, 
+				struct notify_t *notify) 
 {
 	struct notify_t ttp_notify;
 	struct tsap_cb *self;
 	struct lsap_cb *lsap;
 
-	ASSERT( irttp != NULL, return NULL;);
-	ASSERT( irttp->magic == TTP_MAGIC, return NULL;);
+	ASSERT(irttp != NULL, return NULL;);
+	ASSERT(irttp->magic == TTP_MAGIC, return NULL;);
 
-	self = kmalloc( sizeof(struct tsap_cb), GFP_ATOMIC);
-	if ( self == NULL) {
-		printk( KERN_ERR "IrTTP: Can't allocate memory for "
+	self = kmalloc(sizeof(struct tsap_cb), GFP_ATOMIC);
+	if (self == NULL) {
+		printk(KERN_ERR "IrTTP: Can't allocate memory for "
 			"TSAP control block!\n");
 		return NULL;
 	}
-	memset( self, 0, sizeof(struct tsap_cb));
+	memset(self, 0, sizeof(struct tsap_cb));
 
-	init_timer( &self->todo_timer);
+	init_timer(&self->todo_timer);
 
 	/* Initialize callbacks for IrLMP to use */
 
-	irda_notify_init( &ttp_notify);
+	irda_notify_init(&ttp_notify);
 	ttp_notify.connect_confirm = irttp_connect_confirm;
 	ttp_notify.connect_indication = irttp_connect_indication;
 	ttp_notify.disconnect_indication = irttp_disconnect_indication;
 	ttp_notify.data_indication = irttp_data_indication;
 	ttp_notify.udata_indication = irttp_udata_indication;
 	ttp_notify.instance = self;
-	strncpy( ttp_notify.name, notify->name, NOTIFY_MAX_NAME);
+	strncpy(ttp_notify.name, notify->name, NOTIFY_MAX_NAME);
 
 	/*
 	 *  Create LSAP at IrLMP layer
 	 */
-	lsap = irlmp_open_lsap( stsap_sel, &ttp_notify);
-	if ( lsap == NULL) {
-		printk( KERN_ERR "IrTTP, Unable to get LSAP!!\n");
+	lsap = irlmp_open_lsap(stsap_sel, &ttp_notify);
+	if (lsap == NULL) {
+		printk(KERN_ERR "IrTTP, Unable to get LSAP!!\n");
 		return NULL;
 	}
 	
@@ -163,22 +161,23 @@
 	 *  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);
+	DEBUG(4, __FUNCTION__ "(), stsap_sel=%02x\n", self->stsap_sel);
 
 	self->notify = *notify;
 	self->lsap = lsap;
 	self->magic = TTP_TSAP_MAGIC;
+	self->connected = FALSE;
 
-	skb_queue_head_init( &self->rx_queue);
-	skb_queue_head_init( &self->tx_queue);
-	skb_queue_head_init( &self->rx_fragments);
+	skb_queue_head_init(&self->rx_queue);
+	skb_queue_head_init(&self->tx_queue);
+	skb_queue_head_init(&self->rx_fragments);
 
 	/*
 	 *  Insert ourself into the hashbin
 	 */
-	hashbin_insert( irttp->tsaps, (QUEUE *) self, self->stsap_sel, NULL);
+	hashbin_insert(irttp->tsaps, (QUEUE *) self, self->stsap_sel, NULL);
 
-	if ( credit > TTP_MAX_QUEUE)
+	if (credit > TTP_MAX_QUEUE)
 		self->initial_credit = TTP_MAX_QUEUE;
 	else
 		self->initial_credit = credit;
@@ -193,27 +192,22 @@
  *    deallocation of the TSAP, and resetting of the TSAPs values;
  *
  */
-static void __irttp_close_tsap( struct tsap_cb *self)
+static void __irttp_close_tsap(struct tsap_cb *self)
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
 	/* First make sure we're connected. */
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 
-	irttp_flush_queues( self);
+	irttp_flush_queues(self);
 
-	del_timer( &self->todo_timer);
+	del_timer(&self->todo_timer);
 
 	self->connected = FALSE;
 	self->magic = ~TTP_TSAP_MAGIC;
 
-	/*
-	 *  Deallocate structure
-	 */
-	kfree( self);
-
-	DEBUG( 4, "irttp_close_tsap() -->\n");
+	kfree(self);
 }
 
 /*
@@ -223,24 +217,41 @@
  *    associated with this TSAP
  *
  */
-void irttp_close_tsap( struct tsap_cb *self)
+int irttp_close_tsap(struct tsap_cb *self)
 {
 	struct tsap_cb *tsap;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	tsap = hashbin_remove( irttp->tsaps, self->stsap_sel, NULL);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
 
-	ASSERT( tsap == self, return;);
+	/* Make sure tsap has been disconnected */
+	if (self->connected) {
+		/* Check if disconnect is not pending */
+		if (!self->disconnect_pend) {
+			DEBUG(0, __FUNCTION__ "(), TSAP still connected!\n");
+			irttp_disconnect_request(self, NULL, P_NORMAL);
+		}
+		self->close_pend = TRUE;
+		irttp_start_todo_timer(self, 100);
+
+		return 0; /* Will be back! */
+	}
+	
+	tsap = hashbin_remove(irttp->tsaps, self->stsap_sel, NULL);
+
+	ASSERT(tsap == self, return -1;);
 
 	/* Close corresponding LSAP */
-	if ( self->lsap) {
-		irlmp_close_lsap( self->lsap);
+	if (self->lsap) {
+		irlmp_close_lsap(self->lsap);
 		self->lsap = NULL;
 	}
 
-	__irttp_close_tsap( self);
+	__irttp_close_tsap(self);
+
+	return 0;
 }
 
 /*
@@ -249,26 +260,26 @@
  *    Send unreliable data on this TSAP
  *
  */
-int irttp_udata_request( struct tsap_cb *self, struct sk_buff *skb) 
+int irttp_udata_request(struct tsap_cb *self, struct sk_buff *skb) 
 {
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return -1;);
-	ASSERT( skb != NULL, return -1;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+	ASSERT(skb != NULL, return -1;);
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
 	/* Check that nothing bad happens */
-	if (( skb->len == 0) || ( !self->connected)) {
-		DEBUG( 0, __FUNCTION__ "(), No data, or not connected\n");
+	if ((skb->len == 0) || (!self->connected)) {
+		DEBUG(1, __FUNCTION__ "(), No data, or not connected\n");
 		return -1;
 	}
 	
-	if ( skb->len > self->max_seg_size) {
-		DEBUG( 0, __FUNCTION__ "(), UData is to large for IrLAP!\n");
+	if (skb->len > self->max_seg_size) {
+		DEBUG(1, __FUNCTION__ "(), UData is to large for IrLAP!\n");
 		return -1;
 	}
 		    
-	irlmp_udata_request( self->lsap, skb);
+	irlmp_udata_request(self->lsap, skb);
 	self->stats.tx_packets++;
 
 	return 0;
@@ -280,19 +291,19 @@
  *    Queue frame for transmission. If SAR is enabled, fragement the frame 
  *    and queue the fragments for transmission
  */
-int irttp_data_request( struct tsap_cb *self, struct sk_buff *skb) 
+int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb) 
 {
 	__u8 *frame;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return -1;);
-	ASSERT( skb != NULL, return -1;);
+	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)) {
-		DEBUG( 4, __FUNCTION__ "(), No data, or not connected\n");
+	if ((skb->len == 0) || (!self->connected)) {
+		DEBUG(4, __FUNCTION__ "(), No data, or not connected\n");
 		return -1;
 	}
 
@@ -300,10 +311,8 @@
 	 *  Check if SAR is disabled, and the frame is larger than what fits
 	 *  inside an IrLAP frame
 	 */
-	if (( self->tx_max_sdu_size == 0) && 
-	    ( skb->len > self->max_seg_size)) 
-	{
-		DEBUG( 0, __FUNCTION__ 
+	if ((self->tx_max_sdu_size == 0) && (skb->len > self->max_seg_size)) {
+		DEBUG(1, __FUNCTION__ 
 		       "(), SAR disabled, and data is to large for IrLAP!\n");
 		return -1;
 	}
@@ -312,34 +321,33 @@
 	 *  Check if SAR is enabled, and the frame is larger than the 
 	 *  TxMaxSduSize 
 	 */
-	if (( self->tx_max_sdu_size != 0) && 
+	if ((self->tx_max_sdu_size != 0) && 
 	    (skb->len > self->tx_max_sdu_size))
 	{
-		DEBUG( 0, __FUNCTION__ "(), SAR enabled, "
+		DEBUG(1, __FUNCTION__ "(), SAR enabled, "
 		       "but data is larger than TxMaxSduSize!\n");
 		return -1;
 	}
 	/* 
 	 *  Check if transmit queue is full
 	 */
-	if ( skb_queue_len( &self->tx_queue) >= TTP_MAX_QUEUE) {
+	if (skb_queue_len(&self->tx_queue) >= TTP_MAX_QUEUE) {
 		/*
 		 *  Give it a chance to empty itself
 		 */
-		irttp_run_tx_queue( self);
+		irttp_run_tx_queue(self);
 		
 		return -1;
 	}
        
 	/* Queue frame, or queue frame segments */
-	if (( self->tx_max_sdu_size == 0) || 
-	    ( skb->len < self->max_seg_size)) {
+	if ((self->tx_max_sdu_size == 0) || (skb->len < self->max_seg_size)) {
 		/* Queue frame */
-		frame = skb_push( skb, TTP_HEADER);
+		frame = skb_push(skb, TTP_HEADER);
 		frame[0] = 0x00; /* Clear more bit */
 		
-		DEBUG( 4, __FUNCTION__ "(), queueing original skb\n");
-		skb_queue_tail( &self->tx_queue, skb);
+		DEBUG(4, __FUNCTION__ "(), queueing original skb\n");
+		skb_queue_tail(&self->tx_queue, skb);
 	} else {
 		/*
 		 *  Fragment the frame, this function will also queue the
@@ -347,25 +355,24 @@
 		 *  queue may be overfilled by all the segments for a little
 		 *  while
 		 */
-		irttp_fragment_skb( self, skb);
+		irttp_fragment_skb(self, skb);
 	}
 
 	/* Check if we can accept more data from client */
-	if (( !self->tx_sdu_busy) && 
-	    ( skb_queue_len( &self->tx_queue) > HIGH_THRESHOLD)) {
+	if ((!self->tx_sdu_busy) && 
+	    (skb_queue_len(&self->tx_queue) > HIGH_THRESHOLD)) {
 		
 		/* Tx queue filling up, so stop client */
 		self->tx_sdu_busy = TRUE;
 		
-	 	if ( self->notify.flow_indication) {
- 			self->notify.flow_indication( self->notify.instance, 
-						      self, 
-						      FLOW_STOP);
+	 	if (self->notify.flow_indication) {
+ 			self->notify.flow_indication(
+				self->notify.instance, self, FLOW_STOP);
 		}
  	}
 	
 	/* Try to make some progress */
-	irttp_run_tx_queue( self);
+	irttp_run_tx_queue(self);
 	
 	return 0;
 }
@@ -376,40 +383,40 @@
  *    If possible, transmit a frame queued for transmission.
  *
  */
-static void irttp_run_tx_queue( struct tsap_cb *self) 
+static void irttp_run_tx_queue(struct tsap_cb *self) 
 {
 	struct sk_buff *skb = NULL;
 	unsigned long flags;
 	__u8 *frame;
 	int n;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
-
-	if ( irda_lock( &self->tx_queue_lock) == FALSE)
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+	
+	if (irda_lock(&self->tx_queue_lock) == FALSE)
 		return;
 
-	while (( self->send_credit > 0) && !skb_queue_empty( &self->tx_queue)){
+	while ((self->send_credit > 0) && !skb_queue_empty(&self->tx_queue)){
 
-		skb = skb_dequeue( &self->tx_queue);
-		ASSERT( skb != NULL, return;);
+		skb = skb_dequeue(&self->tx_queue);
+		ASSERT(skb != NULL, return;);
 		
 		/* Make room for TTP header */
-		ASSERT( skb_headroom( skb) >= TTP_HEADER, return;);
+		ASSERT(skb_headroom(skb) >= TTP_HEADER, return;);
 				
 		/*
 		 *  Since we can transmit and receive frames concurrently, 
 		 *  the code below is a critical region and we must assure that
 		 *  nobody messes with the credits while we update them.
 		 */
-		save_flags( flags); 
+		save_flags(flags); 
 		cli();
 
 		n = self->avail_credit;
 		self->avail_credit = 0;
 		
 		/* Only space for 127 credits in frame */
-		if ( n > 127) {
+		if (n > 127) {
 			self->avail_credit = n-127;
 			n = 127;
 		}
@@ -418,7 +425,7 @@
 
 		restore_flags(flags);
 
-		DEBUG( 4, "irttp_xmit: Giving away %d credits\n", n);
+		DEBUG(4, "irttp_xmit: Giving away %d credits\n", n);
 		
 		/* 
 		 *  More bit must be set by the data_request() or fragment() 
@@ -426,38 +433,27 @@
 		 */
 		frame = skb->data;
 
-		DEBUG( 4, __FUNCTION__ "(), More=%s\n", frame[0] & 0x80 ? 
+		DEBUG(4, __FUNCTION__ "(), More=%s\n", frame[0] & 0x80 ? 
 		       "TRUE" : "FALSE" );
 
 		frame[0] |= (__u8) (n & 0x7f);
 		
-		irlmp_data_request( self->lsap, skb);
+		irlmp_data_request(self->lsap, skb);
 		self->stats.tx_packets++;
 
 		/* Check if we can accept more frames from client */
-		if (( self->tx_sdu_busy) && 
-		    ( skb_queue_len( &self->tx_queue) < LOW_THRESHOLD)) { 
+		if ((self->tx_sdu_busy) && 
+		    (skb_queue_len(&self->tx_queue) < LOW_THRESHOLD)) { 
 			self->tx_sdu_busy = FALSE;
 			
-			if ( self->notify.flow_indication)
-				self->notify.flow_indication( self->notify.instance, 
-							      self, 
-							      FLOW_START);
+			if (self->notify.flow_indication)
+				self->notify.flow_indication(
+				      self->notify.instance, self, FLOW_START);
 		}
 	}
 	
 	/* Reset lock */
 	self->tx_queue_lock = 0;
-
-	/* Check if there is any disconnect request pending */
-	if ( self->disconnect_pend) {
-		if ( self->disconnect_skb) {
-			irttp_disconnect_request( self, self->disconnect_skb,
-						  P_NORMAL);
-			self->disconnect_skb = NULL;
-		} else
-			irttp_disconnect_request( self, NULL, P_NORMAL);
-	}
 }
 
 /*
@@ -466,42 +462,39 @@
  *    Send a dataless flowdata TTP-PDU and give available credit to peer
  *    TSAP
  */
-void irttp_give_credit( struct tsap_cb *self) 
+void irttp_give_credit(struct tsap_cb *self) 
 {
 	struct sk_buff *tx_skb = NULL;
 	unsigned long flags;
 	int n;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);	
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);	
 
-	DEBUG( 4, "irttp_give_credit() send=%d,avail=%d,remote=%d\n", 
+	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);
-	if ( tx_skb == NULL) {
-		DEBUG( 0, "irttp_give_credit: "
-		       "Could not allocate an sk_buff of length %d\n", 64);
+	tx_skb = dev_alloc_skb(64);
+	if (!tx_skb)
 		return;
-	}
 
 	/* Reserve space for LMP, and LAP header */
-	skb_reserve( tx_skb, LMP_HEADER+LAP_HEADER);
+	skb_reserve(tx_skb, LMP_HEADER+LAP_HEADER);
 
 	/*
 	 *  Since we can transmit and receive frames concurrently, 
 	 *  the code below is a critical region and we must assure that
 	 *  nobody messes with the credits while we update them.
 	 */
-	save_flags( flags);
+	save_flags(flags);
 	cli();
 
 	n = self->avail_credit;
 	self->avail_credit = 0;
 	
 	/* Only space for 127 credits in frame */
-	if ( n > 127) {
+	if (n > 127) {
 		self->avail_credit = n - 127;
 		n = 127;
 	}
@@ -509,10 +502,10 @@
 
 	restore_flags(flags);
 
-	skb_put( tx_skb, 1);
-	tx_skb->data[0] = (__u8) ( n & 0x7f);
+	skb_put(tx_skb, 1);
+	tx_skb->data[0] = (__u8) (n & 0x7f);
 	
-	irlmp_data_request( self->lsap, tx_skb);
+	irlmp_data_request(self->lsap, tx_skb);
 	self->stats.tx_packets++;
 }
 
@@ -522,22 +515,21 @@
  *    
  *
  */
-void irttp_udata_indication( void *instance, void *sap, struct sk_buff *skb) 
+void irttp_udata_indication(void *instance, void *sap, struct sk_buff *skb) 
 {
 	struct tsap_cb *self;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
 	self = (struct tsap_cb *) instance;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
 
 	/* 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);
 	}
 	self->stats.rx_packets++;
 }
@@ -548,7 +540,7 @@
  *    Receive segment from IrLMP. 
  *
  */
-void irttp_data_indication( void *instance, void *sap, struct sk_buff *skb)
+void irttp_data_indication(void *instance, void *sap, struct sk_buff *skb)
 {
 	struct tsap_cb *self;
 	int more;
@@ -557,16 +549,16 @@
 	
 	self = (struct tsap_cb *) instance;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
 
 	frame = skb->data;
 	
 	n = frame[0] & 0x7f;     /* Extract the credits */
 	more = frame[0] & 0x80;
 
- 	DEBUG( 4, __FUNCTION__"(), got %d credits, TSAP sel=%02x\n", 
+ 	DEBUG(4, __FUNCTION__"(), got %d credits, TSAP sel=%02x\n", 
 	       n, self->stsap_sel);
 
 	self->stats.rx_packets++;
@@ -575,7 +567,7 @@
 	 *  Data or dataless frame? Dataless frames only contain the 
 	 *  TTP_HEADER
 	 */
-	if ( skb->len == 1) {
+	if (skb->len == 1) {
 		/* Dataless flowdata TTP-PDU */
 		self->send_credit += n;
 	} else {
@@ -587,27 +579,27 @@
 		 *  We don't remove the TTP header, since we must preserve the
 		 *  more bit, so the defragment routing knows what to do
 		 */
-		skb_queue_tail( &self->rx_queue, skb);
+		skb_queue_tail(&self->rx_queue, skb);
 	} 
 
-	irttp_run_rx_queue( self);
+	irttp_run_rx_queue(self);
 
 	/* 
 	 *  Give avay some credits to peer? 
 	 */
-	if (( skb_queue_empty( &self->tx_queue)) && 
-	    ( self->remote_credit < LOW_THRESHOLD) && 
-	    ( self->avail_credit > 0)) 
+	if ((skb_queue_empty(&self->tx_queue)) && 
+	    (self->remote_credit < LOW_THRESHOLD) && 
+	    (self->avail_credit > 0)) 
 	{
 		/* Schedule to start immediately after this thread */
-		irttp_start_todo_timer( self, 0);
+		irttp_start_todo_timer(self, 0);
 	}
 
 	/* If peer has given us some credites and we didn't have anyone
          * from before, the we need to shedule the tx queue? 
 	 */
-	if ( self->send_credit == n)
-		irttp_start_todo_timer( self, 0);
+	if (self->send_credit == n)
+		irttp_start_todo_timer(self, 0);
 }
 
 /*
@@ -617,26 +609,26 @@
  *    delivering frames if the receive queues are starting to get full, or 
  *    to tell IrTTP to start delivering frames again.
  */
-void irttp_flow_request( struct tsap_cb *self, LOCAL_FLOW flow)
+void irttp_flow_request(struct tsap_cb *self, LOCAL_FLOW flow)
 {
-	DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG(1, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 
-	switch ( flow) {
+	switch (flow) {
 	case FLOW_STOP:
-		DEBUG( 0, __FUNCTION__ "(), flow stop\n");
+		DEBUG(1, __FUNCTION__ "(), flow stop\n");
 		self->rx_sdu_busy = TRUE;
 		break;
 	case FLOW_START:
-		DEBUG( 0, __FUNCTION__ "(), flow start\n");
+		DEBUG(1, __FUNCTION__ "(), flow start\n");
 		self->rx_sdu_busy = FALSE;
 		
-		irttp_run_rx_queue( self);
+		irttp_run_rx_queue(self);
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown flow command!\n");
+		DEBUG(1, __FUNCTION__ "(), Unknown flow command!\n");
 	}
 }
 	
@@ -646,37 +638,35 @@
  *    Try to connect to remote destination TSAP selector
  *
  */
-void irttp_connect_request( struct tsap_cb *self, __u8 dtsap_sel, __u32 daddr,
-			    struct qos_info *qos, int max_sdu_size, 
-			    struct sk_buff *userdata) 
+void irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel, 
+			   __u32 saddr, __u32 daddr,
+			   struct qos_info *qos, int max_sdu_size, 
+			   struct sk_buff *userdata) 
 {
 	struct sk_buff *skb;
 	__u8 *frame;
 	__u8 n;
 	
-	DEBUG( 4, __FUNCTION__ "(), max_sdu_size=%d\n", max_sdu_size); 
+	DEBUG(4, __FUNCTION__ "(), max_sdu_size=%d\n", max_sdu_size); 
 	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 
 	/* Any userdata supplied? */
-	if ( userdata == NULL) {
-		skb = dev_alloc_skb( 64);
-		if (skb == NULL) {
-			DEBUG( 0, __FUNCTION__ "Could not allocate an "
-			       "sk_buff of length %d\n", 64);
+	if (userdata == NULL) {
+		skb = dev_alloc_skb(64);
+		if (!skb) 
 			return;
-		}
 		
 		/* Reserve space for MUX_CONTROL and LAP header */
-		skb_reserve( skb, (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER));
+		skb_reserve(skb, (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER));
 	} else {
 		skb = userdata;
 		/*  
 		 *  Check that the client has reserved enough space for 
 		 *  headers
 		 */
-		ASSERT( skb_headroom( userdata) >= 
+		ASSERT(skb_headroom(userdata) >= 
 			(TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER), return;);
 	}
 
@@ -696,7 +686,7 @@
 	/*
 	 *  Give away max 127 credits for now
 	 */
-	if ( n > 127) {
+	if (n > 127) {
 		self->avail_credit=n-127;
 		n = 127;
 	}
@@ -704,29 +694,29 @@
 	self->remote_credit = n;
 
 	/* SAR enabled? */
-	if ( max_sdu_size > 0) {
-		ASSERT( skb_headroom( skb) >= 
+	if (max_sdu_size > 0) {
+		ASSERT(skb_headroom(skb) >= 
 			(TTP_HEADER_WITH_SAR+LMP_CONTROL_HEADER+LAP_HEADER), 
 			return;);
 
 		/* Insert SAR parameters */
-		frame = skb_push( skb, TTP_HEADER_WITH_SAR);
+		frame = skb_push(skb, TTP_HEADER_WITH_SAR);
 		
 		frame[0] = TTP_PARAMETERS | n; 
 		frame[1] = 0x04; /* Length */
 		frame[2] = 0x01; /* MaxSduSize */
 		frame[3] = 0x02; /* Value length */
-		*((__u16 *) (frame+4))= htons( max_sdu_size); /* Big endian! */
+		*((__u16 *) (frame+4))= htons(max_sdu_size); /* Big endian! */
 	} else {
 		/* Insert plain TTP header */
-		frame = skb_push( skb, TTP_HEADER);
+		frame = skb_push(skb, TTP_HEADER);
 		
 		/* Insert initial credit in frame */
 		frame[0] = n & 0x7f;
 	}
 
 	/* Connect with IrLMP. No QoS parameters for now */
-	irlmp_connect_request( self->lsap, dtsap_sel, daddr, qos, skb);
+	irlmp_connect_request(self->lsap, dtsap_sel, saddr, daddr, qos, skb);
 }
 
 /*
@@ -735,24 +725,21 @@
  *    Sevice user confirms TSAP connection with peer. 
  *
  */
-void irttp_connect_confirm( void *instance, void *sap, struct qos_info *qos,
-			    int max_seg_size, struct sk_buff *skb) 
+void irttp_connect_confirm(void *instance, void *sap, struct qos_info *qos,
+			   int max_seg_size, struct sk_buff *skb) 
 {
 	struct tsap_cb *self;
 	__u8 *frame;
 	__u8 n;
 	int parameters;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 	
 	self = (struct tsap_cb *) instance;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
-
-	/* FIXME: just remove this when we know its working */
-	ASSERT( max_seg_size == qos->data_size.value, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
 
 	self->max_seg_size = max_seg_size-LMP_HEADER-LAP_HEADER;
 
@@ -760,40 +747,40 @@
 	 *  Check if we have got some QoS parameters back! This should be the
 	 *  negotiated QoS for the link.
 	 */
-	if ( qos) {
-		DEBUG( 4, "IrTTP, Negotiated BAUD_RATE: %02x\n", 
+	if (qos) {
+		DEBUG(4, "IrTTP, Negotiated BAUD_RATE: %02x\n", 
 		       qos->baud_rate.bits);			
-		DEBUG( 4, "IrTTP, Negotiated BAUD_RATE: %d bps.\n", 
+		DEBUG(4, "IrTTP, Negotiated BAUD_RATE: %d bps.\n", 
 		       qos->baud_rate.value);
 	}
 
 	frame = skb->data;
 	n = frame[0] & 0x7f;
 	
-	DEBUG( 4, __FUNCTION__ "(), Initial send_credit=%d\n", n);
+	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;	
-	if ( parameters) {
-		DEBUG( 4, __FUNCTION__ "(), Contains parameters!\n");
+	if (parameters) {
+		DEBUG(4, __FUNCTION__ "(), Contains parameters!\n");
 		
 		self->tx_max_sdu_size = ntohs(*(__u16 *)(frame+4));
-		DEBUG( 4, __FUNCTION__ "(), RxMaxSduSize=%d\n", 
+		DEBUG(4, __FUNCTION__ "(), RxMaxSduSize=%d\n", 
 		       self->tx_max_sdu_size);
 	}
 	
-	DEBUG( 4, "irttp_connect_confirm() send=%d,avail=%d,remote=%d\n", 
-	       self->send_credit, self->avail_credit, self->remote_credit);
+	DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n", 
+	      self->send_credit, self->avail_credit, self->remote_credit);
 
-	skb_pull( skb, TTP_HEADER);
+	skb_pull(skb, TTP_HEADER);
 
-	if ( self->notify.connect_confirm) {
-		self->notify.connect_confirm( self->notify.instance, self, 
-					      qos, self->tx_max_sdu_size, 
-					      skb);
+	if (self->notify.connect_confirm) {
+		self->notify.connect_confirm(self->notify.instance, self, 
+					     qos, self->tx_max_sdu_size, 
+					     skb);
 	}
 }
 
@@ -803,32 +790,33 @@
  *    Some other device is connecting to this TSAP
  *
  */
-void irttp_connect_indication( void *instance, void *sap, 
-			       struct qos_info *qos, int max_seg_size, 
-			       struct sk_buff *skb) 
+void irttp_connect_indication(void *instance, void *sap, 
+			      struct qos_info *qos, int max_seg_size, 
+			      struct sk_buff *skb) 
 {
 	struct tsap_cb *self;
+	struct lsap_cb *lsap;
 	__u8 *frame;
 	int parameters;
 	int n;
 
 	self = (struct tsap_cb *) instance;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
- 	ASSERT( skb != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+ 	ASSERT(skb != NULL, return;);
+
+	lsap = (struct lsap_cb *) sap;
 
 	/* FIXME: just remove this when we know its working */
-	ASSERT( max_seg_size == qos->data_size.value, return;);
+	ASSERT(max_seg_size == qos->data_size.value, return;);
 
 	self->max_seg_size = max_seg_size-LMP_HEADER-LAP_HEADER;
 
-	DEBUG( 4, "irttp_connect_indication(), TSAP sel=%02x\n", 
-	       self->stsap_sel);
+	DEBUG(4, __FUNCTION__ "(), TSAP sel=%02x\n", self->stsap_sel);
 
-	/* FIXME: Need to update dtsap_sel if its equal to LSAP_ANY */
-/* 	if ( self->dtsap_sel == LSAP_ANY) */
-/* 		self->dtsap_sel = lsap->dlsap_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;
@@ -837,22 +825,22 @@
 	self->tx_max_sdu_size = 0;
 	
 	parameters = frame[0] & 0x80;	
-	if ( parameters) {
-		DEBUG( 4, __FUNCTION__ "(), Contains parameters!\n");
+	if (parameters) {
+		DEBUG(4, __FUNCTION__ "(), Contains parameters!\n");
 		
 		self->tx_max_sdu_size = ntohs(*(__u16 *)(frame+4));
-		DEBUG( 4, __FUNCTION__ "(), MaxSduSize=%d\n", 
-		       self->tx_max_sdu_size);
+		DEBUG(4, __FUNCTION__ "(), MaxSduSize=%d\n", 
+		      self->tx_max_sdu_size);
 	}
 
-	DEBUG( 4, "irttp_connect_indication: initial send_credit=%d\n", n);
+	DEBUG(4, __FUNCTION__ "(), initial send_credit=%d\n", n);
 
-	skb_pull( skb, 1);
+	skb_pull(skb, 1);
 
-	if ( self->notify.connect_indication) {
-		self->notify.connect_indication( self->notify.instance, self, 
-						 qos, self->rx_max_sdu_size, 
-						 skb);
+	if (self->notify.connect_indication) {
+		self->notify.connect_indication(self->notify.instance, self, 
+						qos, self->rx_max_sdu_size, 
+						skb);
 	}
 }
 
@@ -863,37 +851,34 @@
  *    IrLMP!
  * 
  */
-void irttp_connect_response( struct tsap_cb *self, int max_sdu_size, 
-			     struct sk_buff *userdata)
+void irttp_connect_response(struct tsap_cb *self, int max_sdu_size, 
+			    struct sk_buff *userdata)
 {
 	struct sk_buff *skb;
 	__u8 *frame;
 	__u8 n;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 
-	DEBUG( 4, __FUNCTION__ "(), Source TSAP selector=%02x\n", 
-	       self->stsap_sel);
+	DEBUG(4, __FUNCTION__ "(), Source TSAP selector=%02x\n", 
+	      self->stsap_sel);
 	
 	/* Any userdata supplied? */
-	if ( userdata == NULL) {
-		skb = dev_alloc_skb( 64);
-		if (skb == NULL) {
-			DEBUG( 0, __FUNCTION__ "Could not allocate an "
-			       "sk_buff of length %d\n", 64);
+	if (userdata == NULL) {
+		skb = dev_alloc_skb(64);
+		if (!skb)
 			return;
-		}
 
 		/* Reserve space for MUX_CONTROL and LAP header */
-		skb_reserve( skb, (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER));
+		skb_reserve(skb, (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER));
 	} else {
 		skb = userdata;
 		/*  
 		 *  Check that the client has reserved enough space for 
 		 *  headers
 		 */
-		ASSERT( skb_headroom( skb) >= 
+		ASSERT(skb_headroom(skb) >= 
 			(TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER), return;);
 	}
 	
@@ -906,7 +891,7 @@
 	n = self->initial_credit;
 
 	/* Frame has only space for max 127 credits (7 bits) */
-	if ( n > 127) {
+	if (n > 127) {
 		self->avail_credit = n - 127;
 		n = 127;
 	}
@@ -915,117 +900,112 @@
 	self->connected = TRUE;
 
 	/* SAR enabled? */
-	if ( max_sdu_size > 0) {
-		ASSERT( skb_headroom( skb) >= 
-			(TTP_HEADER_WITH_SAR+LMP_CONTROL_HEADER+LAP_HEADER), 
-			return;);
+	if (max_sdu_size > 0) {
+		ASSERT(skb_headroom(skb) >= 
+		       (TTP_HEADER_WITH_SAR+LMP_CONTROL_HEADER+LAP_HEADER), 
+		       return;);
 		
 		/* Insert TTP header with SAR parameters */
-		frame = skb_push( skb, TTP_HEADER_WITH_SAR);
+		frame = skb_push(skb, TTP_HEADER_WITH_SAR);
 		
 		frame[0] = TTP_PARAMETERS | n;
 		frame[1] = 0x04; /* Length */
 		frame[2] = 0x01; /* MaxSduSize */
 		frame[3] = 0x02; /* Value length */
-		*((__u16 *) (frame+4))= htons( max_sdu_size);
+		*((__u16 *) (frame+4))= htons(max_sdu_size);
 	} else {
 		/* Insert TTP header */
-		frame = skb_push( skb, TTP_HEADER);
+		frame = skb_push(skb, TTP_HEADER);
 		
 		frame[0] = n & 0x7f;
 	}
 	 
-	irlmp_connect_response( self->lsap, skb);
+	irlmp_connect_response(self->lsap, skb);
 }
 
 /*
- * Function irttp_disconnect_request ( self)
+ * Function irttp_disconnect_request (self)
  *
  *    Close this connection please! If priority is high, the queued data 
  *    segments, if any, will be deallocated first
  *
  */
-void irttp_disconnect_request( struct tsap_cb *self, struct sk_buff *userdata, 
-			       int priority)
+void irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *userdata, 
+			      int priority)
 {
 	struct sk_buff *skb;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(2, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 
 	/* Already disconnected? */
-	if ( !self->connected) {
-		DEBUG( 4, __FUNCTION__ "(), already disconnected!\n");
+	if (!self->connected) {
+		DEBUG(4, __FUNCTION__ "(), already disconnected!\n");
 		return;
 	}
 
 	/* Disconnect already pending? */
-	if ( self->disconnect_pend) {
-		DEBUG( 0, __FUNCTION__ "(), disconnect already pending\n");
-		if ( userdata) {
-			dev_kfree_skb( userdata);
+	if (self->disconnect_pend) {
+		DEBUG(1, __FUNCTION__ "(), disconnect already pending\n");
+		if (userdata) {
+			dev_kfree_skb(userdata);
 		}
 
 		/* Try to make some progress */
-		irttp_run_rx_queue( self);
+		irttp_run_rx_queue(self);
 		return;
 	}
 
 	/*
 	 *  Check if there is still data segments in the transmit queue
 	 */
-	if ( skb_queue_len( &self->tx_queue) > 0) {
-		if ( priority == P_HIGH) {
-			DEBUG( 0, __FUNCTION__  "High priority!!()\n" );
+	if (skb_queue_len(&self->tx_queue) > 0) {
+		if (priority == P_HIGH) {
+			DEBUG(1, __FUNCTION__  "High priority!!()\n" );
 			
 			/* 
 			 *  No need to send the queued data, if we are 
 			 *  disconnecting right now since the data will
 			 *  not have any usable connection to be sent on
 			 */
-			irttp_flush_queues( self);
-		} else if ( priority == P_NORMAL) {
+			irttp_flush_queues(self);
+		} else if (priority == P_NORMAL) {
 			/* 
 			 *  Must delay disconnect til after all data segments
 			 *  have been sent an the tx_queue is empty
 			 */
-			if ( userdata)
+			if (userdata)
 				self->disconnect_skb = userdata;
 			else
 				self->disconnect_skb = NULL;
 
 			self->disconnect_pend = TRUE;
 
-			irttp_run_tx_queue( self);
-			/*  
-			 *  irttp_xmit will call us again when the tx_queue
-			 *  is empty
-			 */
+			irttp_run_tx_queue(self);
+
+			irttp_start_todo_timer(self, 100);
 			return;
 		}
 	}
-	DEBUG( 0, __FUNCTION__ "(), Disconnecting ...\n");
+	DEBUG(1, __FUNCTION__ "(), Disconnecting ...\n");
 
 	self->connected = FALSE;
 	
-	if ( !userdata) {
-		skb = dev_alloc_skb( 64);
-		if (skb == NULL) {
-			DEBUG( 0, __FUNCTION__ "(), Could not allocate an "
-			       "sk_buff of length %d\n", 64);
+	if (!userdata) {
+		skb = dev_alloc_skb(64);
+		if (!skb)
 			return;
-		}
-
+		
 		/* 
 		 *  Reserve space for MUX and LAP header 
 		 */
-		skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER);
-
+		skb_reserve(skb, LMP_CONTROL_HEADER+LAP_HEADER);
+		
 		userdata = skb;
 	}
-	irlmp_disconnect_request( self->lsap, userdata);
+	irlmp_disconnect_request(self->lsap, userdata);
 }
 
 /*
@@ -1034,26 +1014,26 @@
  *    Disconnect indication, TSAP disconnected by peer?
  *
  */
-void irttp_disconnect_indication( void *instance, void *sap, LM_REASON reason, 
-				  struct sk_buff *userdata) 
+void irttp_disconnect_indication(void *instance, void *sap, LM_REASON reason, 
+				 struct sk_buff *userdata) 
 {
 	struct tsap_cb *self;
 
-	DEBUG( 4, "irttp_disconnect_indication()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	self = ( struct tsap_cb *) instance;
+	self = (struct tsap_cb *) instance;
 	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 	
 	self->connected = FALSE;
 	
 	/* 
 	 *  Use callback to notify layer above 
 	 */
-	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);
 }
 
 /*
@@ -1062,43 +1042,43 @@
  *     Check if we have any frames to be transmitted, or if we have any
  *     available credit to give away.
  */
-void irttp_run_rx_queue( struct tsap_cb *self) 
+void irttp_run_rx_queue(struct tsap_cb *self) 
 {
 	struct sk_buff *skb;
 	__u8 *frame;
 	int more = 0;
 	void *instance;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 
 	instance = self->notify.instance;
-	ASSERT( instance != NULL, return;);
+	ASSERT(instance != NULL, return;);
 
-	DEBUG( 4, "irttp_do_events() send=%d,avail=%d,remote=%d\n", 
+	DEBUG(4, __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)
+	if (irda_lock(&self->rx_queue_lock) == FALSE)
 		return;
 	
 	/*
 	 *  Process receive queue
 	 */
-	while (( !skb_queue_empty( &self->rx_queue)) &&  !self->rx_sdu_busy) {
+	while ((!skb_queue_empty(&self->rx_queue)) &&  !self->rx_sdu_busy) {
 
-		skb = skb_dequeue( &self->rx_queue);
-		if ( !skb)
+		skb = skb_dequeue(&self->rx_queue);
+		if (!skb)
 			break; /* Should not happend, but ...  */
 		
 		self->avail_credit++;
 
 		frame = skb->data;
 		more = frame[0] & 0x80;
-		DEBUG( 4, __FUNCTION__ "(), More=%s\n", more ? "TRUE" : 
+		DEBUG(4, __FUNCTION__ "(), More=%s\n", more ? "TRUE" : 
 		       "FALSE");
 
 		/* Remove TTP header */
-		skb_pull( skb, TTP_HEADER);
+		skb_pull(skb, TTP_HEADER);
 
 		/* Add the length of the remaining data */
 		self->rx_sdu_size += skb->len;
@@ -1110,52 +1090,52 @@
 		 * implements byte streams without any message boundaries
 		 */
 		if ((self->no_defrag) || (self->rx_max_sdu_size == 0)) {
-			self->notify.data_indication( instance, self, skb);
+			self->notify.data_indication(instance, self, skb);
 			self->rx_sdu_size = 0;
-
+			
 			continue;
 		}
 
 		/* Check if this is a fragment, and not the last fragment */
-		if ( more) {
+		if (more) {
 			/*  
 			 *  Queue the fragment if we still are within the 
 			 *  limits of the maximum size of the rx_sdu
 			 */
-			if ( self->rx_sdu_size <= self->rx_max_sdu_size) {
-				DEBUG( 4, __FUNCTION__ 
+			if (self->rx_sdu_size <= self->rx_max_sdu_size) {
+				DEBUG(4, __FUNCTION__ 
 				       "(), queueing fragment\n");
 
-				skb_queue_tail( &self->rx_fragments, skb);
+				skb_queue_tail(&self->rx_fragments, skb);
 			} else {
-				DEBUG( 0, __FUNCTION__ "(), Error!\n");
+				DEBUG(1, __FUNCTION__ "(), Error!\n");
 			}
 		} else {
 			/*
 			 *  This is the last fragment, so time to reassemble!
 			 */
-			if ( self->rx_sdu_size <= self->rx_max_sdu_size) {
+			if (self->rx_sdu_size <= self->rx_max_sdu_size) {
 
 				/* A little optimizing. Only queue the 
 				 * fragment if there is other fragments. Since
 				 * if this is the last and only fragment, 
 				 * there is no need to reassemble 
 				 */
-				if ( !skb_queue_empty( &self->rx_fragments)) {
+				if (!skb_queue_empty(&self->rx_fragments)) {
 
-					DEBUG( 4, __FUNCTION__ 
+					DEBUG(4, __FUNCTION__ 
 					       "(), queueing fragment\n");
-					skb_queue_tail( &self->rx_fragments, 
+					skb_queue_tail(&self->rx_fragments, 
 							skb);
 
-					skb = irttp_reassemble_skb( self);
+					skb = irttp_reassemble_skb(self);
 				}
-				self->notify.data_indication( instance, self, 
-							      skb);
+				self->notify.data_indication(instance, self, 
+							     skb);
 			} else {
-				DEBUG( 0, __FUNCTION__ 
+				DEBUG(1, __FUNCTION__ 
 				       "(), Truncated frame\n");
-				self->notify.data_indication( 
+				self->notify.data_indication(
 					self->notify.instance, self, skb);
 			}
 			self->rx_sdu_size = 0;
@@ -1170,28 +1150,26 @@
  *
  *     Flushes (removes all frames) in transitt-buffer (tx_list)
  */
-void irttp_flush_queues( struct tsap_cb *self)
+void irttp_flush_queues(struct tsap_cb *self)
 {
 	struct sk_buff* skb;
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 	
 	/* Deallocate frames waiting to be sent */
-	while (( skb = skb_dequeue( &self->tx_queue)) != NULL) {
-		dev_kfree_skb( skb);
-	}
+	while ((skb = skb_dequeue(&self->tx_queue)) != NULL)
+		dev_kfree_skb(skb);
+	
 	/* Deallocate received frames */
-	while (( skb = skb_dequeue( &self->rx_queue)) != NULL) {
-		dev_kfree_skb( skb);
-	}
-	/* Deallocate received fragments */
-	while (( skb = skb_dequeue( &self->rx_fragments)) != NULL) {
-		dev_kfree_skb( skb);
-	}
+	while ((skb = skb_dequeue(&self->rx_queue)) != NULL)
+		dev_kfree_skb(skb);
 	
+	/* Deallocate received fragments */
+	while ((skb = skb_dequeue(&self->rx_fragments)) != NULL)
+		dev_kfree_skb(skb);
 }
 
 /*
@@ -1201,40 +1179,38 @@
  *    queue
  *
  */
-static struct sk_buff *irttp_reassemble_skb( struct tsap_cb *self)
+static struct sk_buff *irttp_reassemble_skb(struct tsap_cb *self)
 {
 	struct sk_buff *skb, *frag;
 	int n = 0;  /* Fragment index */
+	
+      	ASSERT(self != NULL, return NULL;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return NULL;);
 
-      	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);
+	DEBUG(4, __FUNCTION__ "(), self->rx_sdu_size=%d\n", 
+	      self->rx_sdu_size);
 
-	skb = dev_alloc_skb( self->rx_sdu_size);
-	if ( !skb) {
-		DEBUG( 0, __FUNCTION__ "(), unable to allocate skb\n");
+	skb = dev_alloc_skb(self->rx_sdu_size);
+	if (!skb)
 		return NULL;
-	}
 
-	skb_put( skb, self->rx_sdu_size);
+	skb_put(skb, self->rx_sdu_size);
 
 	/*
 	 *  Copy all fragments to a new buffer
 	 */
-	while (( frag = skb_dequeue( &self->rx_fragments)) != NULL) {
-		memcpy( skb->data+n, frag->data, frag->len);
+	while ((frag = skb_dequeue(&self->rx_fragments)) != NULL) {
+		memcpy(skb->data+n, frag->data, frag->len);
 		n += frag->len;
 		
-		dev_kfree_skb( frag);
+		dev_kfree_skb(frag);
 	}
-	DEBUG( 4, __FUNCTION__ "(), frame len=%d\n", n);
+	DEBUG(4, __FUNCTION__ "(), frame len=%d\n", n);
 	/* Set the new length */
 
-	DEBUG( 4, __FUNCTION__ "(), rx_sdu_size=%d\n", self->rx_sdu_size);
-	ASSERT( n <= self->rx_sdu_size, return NULL;);
-	skb_trim( skb, n);
+	DEBUG(4, __FUNCTION__ "(), rx_sdu_size=%d\n", self->rx_sdu_size);
+	ASSERT(n <= self->rx_sdu_size, return NULL;);
+	skb_trim(skb, n);
 
 	self->rx_sdu_size = 0;
 
@@ -1247,60 +1223,57 @@
  *    Fragments a frame and queues all the fragments for transmission
  *
  */
-static void irttp_fragment_skb( struct tsap_cb *self, struct sk_buff *skb)
+static void irttp_fragment_skb(struct tsap_cb *self, struct sk_buff *skb)
 {
 	struct sk_buff *frag;
 	__u8 *frame;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
 
 	/*
 	 *  Split frame into a number of segments
 	 */
-	while ( skb->len > 0) {
+	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__ 
+		if (skb->len < self->max_seg_size) {
+			DEBUG(4, __FUNCTION__ 
 			       "(), queuing last segment\n");
 
-			frame = skb_push( skb, TTP_HEADER);
+			frame = skb_push(skb, TTP_HEADER);
 			frame[0] = 0x00; /* Clear more bit */
-			skb_queue_tail( &self->tx_queue, skb);
+			skb_queue_tail(&self->tx_queue, skb);
 			
 			return;
 		}
 		
 		/* Make new segment */
-		frag = dev_alloc_skb( self->max_seg_size+
-					 TTP_HEADER+LMP_HEADER+
-					 LAP_HEADER);
-		if ( frag == NULL) {
-			DEBUG( 0, __FUNCTION__ 
-			       "(), Couldn't allocate skbuff!\n");
+		frag = dev_alloc_skb(self->max_seg_size+
+				      TTP_HEADER+LMP_HEADER+
+				      LAP_HEADER);
+		if (!frag)
 			return;
-		}
 
-		skb_reserve( frag, LMP_HEADER+LAP_HEADER);
+		skb_reserve(frag, LMP_HEADER+LAP_HEADER);
 
 		/*
 		 *  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);
+		frame = skb_put(frag, self->max_seg_size+TTP_HEADER);
 		frame[0] = TTP_MORE;
-		memcpy( frag->data+1, skb->data, self->max_seg_size);
+		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);
+		skb_pull(skb, self->max_seg_size);
 		
-		skb_queue_tail( &self->tx_queue, frag);
+		skb_queue_tail(&self->tx_queue, frag);
 	}
 }
 
@@ -1310,31 +1283,51 @@
  *    Todo timer has expired!
  *
  */
-static void irttp_todo_expired( unsigned long data)
+static void irttp_todo_expired(unsigned long data)
 {
-	struct tsap_cb *self = ( struct tsap_cb *) data;
+	struct tsap_cb *self = (struct tsap_cb *) data;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	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);
+	irttp_run_rx_queue(self);
+	irttp_run_tx_queue(self);
 
 	/*  Give avay some credits to peer?  */
-	if (( skb_queue_empty( &self->tx_queue)) && 
-	    ( self->remote_credit < LOW_THRESHOLD) && 
-	    ( self->avail_credit > 0)) 
+	if ((skb_queue_empty(&self->tx_queue)) && 
+	    (self->remote_credit < LOW_THRESHOLD) && 
+	    (self->avail_credit > 0)) 
 	{
-		DEBUG( 4, "irttp_do_events: sending credit!\n");
-		irttp_give_credit( self);
+		DEBUG(4, __FUNCTION__ "(), sending credit!\n");
+		irttp_give_credit(self);
 	}
-	
-	/* Rearm! */
-	/* irttp_start_todo_timer( self, 50); */
+
+	/* Check if time for disconnect */
+	if (self->disconnect_pend) {
+		/* Check if it's possible to disconnect yet */
+		if (skb_queue_empty(&self->tx_queue)) {
+			if (self->disconnect_skb) {
+				irttp_disconnect_request(
+					self, self->disconnect_skb, P_NORMAL);
+				self->disconnect_skb = NULL;
+			} else
+				irttp_disconnect_request(self, NULL, P_NORMAL);
+		} else {
+			/* Try again later */
+			irttp_start_todo_timer(self, 100);
+			
+			/* No reason to try and close now */
+			return;
+		}
+	}
+
+	/* Check if it's closing time */
+	if (self->close_pend)
+		irttp_close_tsap(self);
 }
 
 /*
@@ -1343,18 +1336,18 @@
  *    Start todo timer. 
  *
  */
-static void irttp_start_todo_timer( struct tsap_cb *self, int timeout)
+static void irttp_start_todo_timer(struct tsap_cb *self, int timeout)
 {
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 
-	del_timer( &self->todo_timer);
+	del_timer(&self->todo_timer);
 	
 	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);
+	add_timer(&self->todo_timer);
 }
 
 #ifdef CONFIG_PROC_FS
@@ -1363,65 +1356,64 @@
  *
  *    Give some info to the /proc file system
  */
-int irttp_proc_read( char *buf, char **start, off_t offset, int len, 
-		     int unused)
+int irttp_proc_read(char *buf, char **start, off_t offset, int len, int unused)
 {
 	struct tsap_cb *self;
 	unsigned long flags;
 	int i = 0;
 	
-	ASSERT( irttp != NULL, return 0;);
+	ASSERT(irttp != NULL, return 0;);
 	
 	len = 0;
 	
 	save_flags(flags);
 	cli();
 
-	self = ( struct tsap_cb *) hashbin_get_first( irttp->tsaps);
-	while ( self != NULL) {
-		if ( !self || self->magic != TTP_TSAP_MAGIC) {
-			DEBUG( 0, "irttp_proc_read: bad ptr self\n");
+	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");
 			return len;
 		}
 
-		len += sprintf( buf+len, "TSAP %d, ", i++);
-		len += sprintf( buf+len, "stsap_sel: %02x, ", 
+		len += sprintf(buf+len, "TSAP %d, ", i++);
+		len += sprintf(buf+len, "stsap_sel: %02x, ", 
 				self->stsap_sel);
-		len += sprintf( buf+len, "dtsap_sel: %02x\n", 
+		len += sprintf(buf+len, "dtsap_sel: %02x\n", 
 				self->dtsap_sel);
-		len += sprintf( buf+len, "  connected: %s, ",
+		len += sprintf(buf+len, "  connected: %s, ",
 				self->connected? "TRUE":"FALSE");
-		len += sprintf( buf+len, "avail credit: %d, ",
+		len += sprintf(buf+len, "avail credit: %d, ",
 				self->avail_credit);
-		len += sprintf( buf+len, "remote credit: %d, ",
+		len += sprintf(buf+len, "remote credit: %d, ",
 				self->remote_credit);
-		len += sprintf( buf+len, "send credit: %d\n",
+		len += sprintf(buf+len, "send credit: %d\n",
 				self->send_credit);
-		len += sprintf( buf+len, "  tx packets: %d, ",
+		len += sprintf(buf+len, "  tx packets: %d, ",
 				self->stats.tx_packets);
-		len += sprintf( buf+len, "rx packets: %d, ",
+		len += sprintf(buf+len, "rx packets: %d, ",
 				self->stats.rx_packets);
-		len += sprintf( buf+len, "tx_queue len: %d ", 
-				skb_queue_len( &self->tx_queue));
-		len += sprintf( buf+len, "rx_queue len: %d\n", 
-				skb_queue_len( &self->rx_queue));
-		len += sprintf( buf+len, "  tx_sdu_busy: %s, ",
+		len += sprintf(buf+len, "tx_queue len: %d ", 
+				skb_queue_len(&self->tx_queue));
+		len += sprintf(buf+len, "rx_queue len: %d\n", 
+				skb_queue_len(&self->rx_queue));
+		len += sprintf(buf+len, "  tx_sdu_busy: %s, ",
 				self->tx_sdu_busy? "TRUE":"FALSE");
-		len += sprintf( buf+len, "rx_sdu_busy: %s\n",
+		len += sprintf(buf+len, "rx_sdu_busy: %s\n",
 				self->rx_sdu_busy? "TRUE":"FALSE");
-		len += sprintf( buf+len, "  max_seg_size: %d, ",
+		len += sprintf(buf+len, "  max_seg_size: %d, ",
 				self->max_seg_size);
-		len += sprintf( buf+len, "tx_max_sdu_size: %d, ",
+		len += sprintf(buf+len, "tx_max_sdu_size: %d, ",
 				self->tx_max_sdu_size);
-		len += sprintf( buf+len, "rx_max_sdu_size: %d\n",
+		len += sprintf(buf+len, "rx_max_sdu_size: %d\n",
 				self->rx_max_sdu_size);
 
-		len += sprintf( buf+len, "  Used by (%s)\n", 
+		len += sprintf(buf+len, "  Used by (%s)\n", 
 				self->notify.name);
 
-		len += sprintf( buf+len, "\n");
+		len += sprintf(buf+len, "\n");
 		
-		self = ( struct tsap_cb *) hashbin_get_next( irttp->tsaps);
+		self = (struct tsap_cb *) hashbin_get_next(irttp->tsaps);
 	}
 	restore_flags(flags);
 
diff -u --recursive --new-file v2.2.2/linux/net/irda/qos.c linux/net/irda/qos.c
--- v2.2.2/linux/net/irda/qos.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/qos.c	Sun Mar  7 15:26:44 1999
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      qos.c
- * Version:       0.1
+ * Version:       0.8
  * Description:   IrLAP QoS negotiation
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Sep  9 00:00:26 1997
- * Modified at:   Sat Dec 12 12:21:42 1998
+ * Modified at:   Mon Feb  1 09:56:21 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -109,8 +109,8 @@
  *    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) 
+void irda_qos_negotiate(struct qos_info *qos_rx, struct qos_info *qos_tx, 
+			struct sk_buff *skb) 
 {
 	int n=0;
 #ifdef CONFIG_IRDA_COMPRESSION
@@ -162,7 +162,7 @@
 			break;
 		}
 
-		switch( code) {
+		switch(code) {
 		case PI_BAUD_RATE:
 			/* 
 			 *  Stations must agree on baud rate, so calculate
@@ -178,7 +178,8 @@
 			/*
 			 *  Negotiated independently for each station
 			 */
-			DEBUG( 4, "MAX_TURN_TIME: %02x\n", byte);
+			DEBUG(4, __FUNCTION__ "(), MAX_TURN_TIME: %02x\n", 
+			      byte);
 			qos_tx->max_turn_time.bits = byte;
 			break;
 		case PI_DATA_SIZE:
@@ -268,7 +269,7 @@
  *    Insert QoS negotiaion pararameters into frame
  *
  */
-int irda_insert_qos_negotiation_params( struct qos_info *qos, __u8 *frame)
+int irda_insert_qos_negotiation_params(struct qos_info *qos, __u8 *frame)
 {
 	int n;
 	__u16_host_order word;
diff -u --recursive --new-file v2.2.2/linux/net/irda/timer.c linux/net/irda/timer.c
--- v2.2.2/linux/net/irda/timer.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/timer.c	Sun Mar  7 15:26:44 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Aug 16 00:59:29 1997
- * Modified at:   Wed Dec  9 01:34:59 1998
+ * Modified at:   Thu Feb  4 10:49:38 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -100,11 +100,16 @@
 			  irlmp_watchdog_timer_expired);
 }
 
-inline void irlmp_start_discovery_timer( struct irlmp_cb *self, int timeout) 
+inline void irlmp_start_discovery_timer(struct irlmp_cb *self, int timeout) 
 {
-	irda_start_timer( &self->discovery_timer, timeout, 
-			  (unsigned long) self,
-			  irlmp_discovery_timer_expired);
+	irda_start_timer(&self->discovery_timer, timeout, (unsigned long) self,
+			 irlmp_discovery_timer_expired);
+}
+
+inline void irlmp_start_idle_timer(struct lap_cb *self, int timeout) 
+{
+	irda_start_timer(&self->idle_timer, timeout, (unsigned long) self,
+			 irlmp_idle_timer_expired);
 }
 
 /*
diff -u --recursive --new-file v2.2.2/linux/net/irda/wrapper.c linux/net/irda/wrapper.c
--- v2.2.2/linux/net/irda/wrapper.c	Wed Jan 20 23:14:07 1999
+++ linux/net/irda/wrapper.c	Sun Mar  7 15:26:44 1999
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      wrapper.c
- * Version:       
- * Description:   IrDA Wrapper layer
+ * Version:       1.0
+ * Description:   SIR wrapper layer
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Sat Jan 16 22:05:45 1999
+ * Modified at:   Tue Feb 16 17:27:23 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
@@ -36,7 +36,7 @@
 
 #define MIN_LENGTH 14
 
-__inline__ static int stuff_byte( __u8 byte, __u8 *buf);
+inline static int stuff_byte( __u8 byte, __u8 *buf);
 
 /*
  * Function async_wrap (skb, *tx_buff)
@@ -54,8 +54,6 @@
 		__u8 bytes[2];
 	} fcs;
 
-
- 	DEBUG( 6, __FUNCTION__ "()\n"); 
 	ASSERT( skb != NULL, return 0;);
 
 	/* Initialize variables */
@@ -63,7 +61,7 @@
 	n = 0;
 
 	if ( skb->len > 2048) {
-		DEBUG( 0,"async_xmit: Warning size=%d of sk_buff to big!\n", 
+		DEBUG( 0, __FUNCTION__ "Warning size=%d of sk_buff to big!\n", 
 		       (int) skb->len);
 
 		return 0;
@@ -119,15 +117,12 @@
  *    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)
+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 == NULL)  {
-		printk( KERN_INFO __FUNCTION__ "() memory squeeze, " 
-			"dropping frame.\n");
+	skb = dev_alloc_skb(len+1);
+	if (!skb)  {
 		idev->stats.rx_dropped++;
 		return;
 	}
@@ -141,7 +136,6 @@
 	skb_put( skb, len-2);
 	memcpy( skb->data, buf, len-2); 
 	
-	idev->rx_buff.len = 0;
 	/* 
 	 *  Feed it to IrLAP layer 
 	 */
@@ -150,11 +144,11 @@
 	skb->mac.raw  = skb->data;
 	skb->protocol = htons(ETH_P_IRDA);
 
-	netif_rx( skb);
+	netif_rx(skb);
 	idev->stats.rx_packets++;
 	idev->stats.rx_bytes += skb->len;	
 }
- 
+
 /*
  * Function async_unwrap (skb)
  *
@@ -166,16 +160,25 @@
 	/* State machine for receiving frames */	   
 	switch( idev->rx_buff.state) {
 	case OUTSIDE_FRAME:
-		if ( byte == BOF) {
+		switch( byte) {
+		case BOF:
 			idev->rx_buff.state = BEGIN_FRAME;
 			idev->rx_buff.in_frame = TRUE;
-		} else if ( byte == EOF) {
+			break;
+		case XBOF:
+			idev->xbofs++;
+			break;
+		case EOF:
 			irda_device_set_media_busy( idev, TRUE);
+			break;
+		default:
+			break;
 		}
 		break;
 	case BEGIN_FRAME:
 		switch ( byte) {
 		case BOF:
+			
 			/* Continue */
 			break;
 		case CE:
@@ -191,13 +194,10 @@
 			break;
 		default:
 			/* Got first byte of frame */
-			if ( idev->rx_buff.len < idev->rx_buff.truesize)  {
-				idev->rx_buff.data[ idev->rx_buff.len++] = byte;
+			idev->rx_buff.data[ idev->rx_buff.len++] = byte;
 			
-				idev->rx_buff.fcs = IR_FCS( INIT_FCS, byte);
-				idev->rx_buff.state = INSIDE_FRAME;
-			} else 
-				printk( "Rx buffer overflow\n");
+			idev->rx_buff.fcs = IR_FCS( INIT_FCS, byte);
+			idev->rx_buff.state = INSIDE_FRAME;
 			break;
 		}
 		break;
@@ -205,7 +205,6 @@
 		switch ( byte) {
 		case BOF:
 			/* New frame? */
-			DEBUG( 4, "New frame?\n");
 			idev->rx_buff.state = BEGIN_FRAME;
 			idev->rx_buff.len = 0;
 			irda_device_set_media_busy( idev, TRUE);
@@ -215,7 +214,6 @@
 			break;
 		case EOF:
 			/* Abort frame */
-			DEBUG( 0, "Abort frame (2)\n");
 			idev->rx_buff.state = OUTSIDE_FRAME;
 			idev->rx_buff.len = 0;
 			break;
@@ -228,10 +226,15 @@
 			if ( idev->rx_buff.len < idev->rx_buff.truesize)  {
 				idev->rx_buff.data[ idev->rx_buff.len++] = byte;
 			
-				idev->rx_buff.fcs = IR_FCS( idev->rx_buff.fcs, byte);
+				idev->rx_buff.fcs = IR_FCS(idev->rx_buff.fcs,
+							   byte);
 				idev->rx_buff.state = INSIDE_FRAME;
-			} else 
-				printk( "Rx buffer overflow\n");
+			} else {
+				DEBUG( 1, __FUNCTION__ 
+				       "(), Rx buffer overflow, aborting\n");
+				idev->rx_buff.state = OUTSIDE_FRAME;
+				idev->rx_buff.len = 0;
+			}
 			break;
 		}
 		break;
@@ -258,6 +261,7 @@
 			if ( idev->rx_buff.fcs == GOOD_FCS) {
 				async_bump( idev, idev->rx_buff.data, 
 					    idev->rx_buff.len);
+				idev->rx_buff.len = 0;
 			} else {
 				/* Wrong CRC, discard frame!  */
 				irda_device_set_media_busy( idev, TRUE); 
@@ -272,9 +276,14 @@
 			if ( idev->rx_buff.len < idev->rx_buff.truesize)  {
 				idev->rx_buff.data[ idev->rx_buff.len++] = byte;
 				
-				idev->rx_buff.fcs = IR_FCS( idev->rx_buff.fcs, byte);
-			} else 
-				printk( "Rx buffer overflow\n");
+				idev->rx_buff.fcs = IR_FCS( idev->rx_buff.fcs,
+							    byte);
+			} else {
+				DEBUG( 1, __FUNCTION__ 
+				       "(), Rx buffer overflow, aborting\n");
+				idev->rx_buff.state = OUTSIDE_FRAME;
+				idev->rx_buff.len = 0;
+			}
 			break;
 		}
 		break;
@@ -288,11 +297,11 @@
  *    buf. The buffer must at all times be able to have two bytes inserted.
  * 
  */
-__inline__ static int stuff_byte( __u8 byte, __u8 *buf) 
+inline static int stuff_byte( __u8 byte, __u8 *buf) 
 {
 	switch ( byte) {
-	case BOF:
-	case EOF:
+	case BOF: /* FALLTHROUGH */
+	case EOF: /* FALLTHROUGH */
 	case CE:
 		/* Insert transparently coded */
 		buf[0] = CE;               /* Send link escape */
@@ -307,4 +316,6 @@
 	}
 }
 	 
+
+
 
diff -u --recursive --new-file v2.2.2/linux/net/sunrpc/sched.c linux/net/sunrpc/sched.c
--- v2.2.2/linux/net/sunrpc/sched.c	Tue Jan 19 11:32:53 1999
+++ linux/net/sunrpc/sched.c	Tue Feb 23 17:11:26 1999
@@ -1000,8 +1000,8 @@
 			wreq->wb_flags, wreq->wb_pid, wreq->wb_page,
 			wreq->wb_offset, wreq->wb_bytes);
 		printk("          name=%s/%s\n",
-			wreq->wb_dentry->d_parent->d_name.name,
-			wreq->wb_dentry->d_name.name);
+			wreq->wb_file->f_dentry->d_parent->d_name.name,
+			wreq->wb_file->f_dentry->d_name.name);
 	}
 }
 #endif
diff -u --recursive --new-file v2.2.2/linux/net/unix/garbage.c linux/net/unix/garbage.c
--- v2.2.2/linux/net/unix/garbage.c	Fri Oct 23 22:01:27 1998
+++ linux/net/unix/garbage.c	Mon Mar  1 16:05:16 1999
@@ -17,11 +17,12 @@
  *
  *  - explicit stack instead of recursion
  *  - tail recurse on first born instead of immediate push/pop
+ *  - we gather the stuff that should not be killed into tree
+ *    and stack is just a path from root to the current pointer.
  *
  *  Future optimizations:
  *
  *  - don't just push entire root set; process in place
- *  - use linked list for internal stack
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -51,6 +52,16 @@
  *		That might be the reason of random oopses on close_fp() in
  *		unrelated processes.
  *
+ *	AV		28 Feb 1999
+ *		Kill the explicit allocation of stack. Now we keep the tree
+ *		with root in dummy + pointer (gc_current) to one of the nodes.
+ *		Stack is represented as path from gc_current to dummy. Unmark
+ *		now means "add to tree". Push == "make it a son of gc_current".
+ *		Pop == "move gc_current to parent". We keep only pointers to
+ *		parents (->gc_tree).
+ *	AV		1 Mar 1999
+ *		Damn. Added missing check for ->dead in listen queues scanning.
+ *
  */
  
 #include <linux/kernel.h>
@@ -65,7 +76,6 @@
 #include <linux/netdevice.h>
 #include <linux/file.h>
 #include <linux/proc_fs.h>
-#include <linux/vmalloc.h>
 
 #include <net/sock.h>
 #include <net/tcp.h>
@@ -74,9 +84,8 @@
 
 /* Internal data structures and random procedures: */
 
-static unix_socket **stack;	/* stack of objects to mark */
-static int in_stack = 0;	/* first free entry in stack */
-static int max_stack;		/* Top of stack */
+#define GC_HEAD ((unix_socket *)(-1))
+static unix_socket *gc_current=GC_HEAD;	/* stack of objects to mark */
 
 extern inline unix_socket *unix_get_socket(struct file *filp)
 {
@@ -122,32 +131,25 @@
 /*
  *	Garbage Collector Support Functions
  */
- 
-extern inline void push_stack(unix_socket *x)
-{
-	if (in_stack == max_stack)
-		panic("can't push onto full stack");
-	stack[in_stack++] = x;
-}
 
 extern inline unix_socket *pop_stack(void)
 {
-	if (in_stack == 0)
-		panic("can't pop empty gc stack");
-	return stack[--in_stack];
+	unix_socket *p=gc_current;
+	gc_current = p->protinfo.af_unix.gc_tree;
+	return p;
 }
 
 extern inline int empty_stack(void)
 {
-	return in_stack == 0;
+	return gc_current == GC_HEAD;
 }
 
 extern inline void maybe_unmark_and_push(unix_socket *x)
 {
-	if (!(x->protinfo.af_unix.marksweep&MARKED))
+	if (x->protinfo.af_unix.gc_tree)
 		return;
-	x->protinfo.af_unix.marksweep&=~MARKED;
-	push_stack(x);
+	x->protinfo.af_unix.gc_tree = gc_current;
+	gc_current = x;
 }
 
 
@@ -169,23 +171,9 @@
 		return;
 	in_unix_gc=1;
 	
-	if(stack==NULL || max_files>max_stack)
-	{
-		if(stack)
-			vfree(stack);
-		stack=(unix_socket **)vmalloc(max_files*sizeof(struct unix_socket *));
-		if(stack==NULL)
-		{
-			printk(KERN_NOTICE "unix_gc: deferred due to low memory.\n");
-			in_unix_gc=0;
-			return;
-		}
-		max_stack=max_files;
-	}
-	
 	forall_unix_sockets(i, s)
 	{
-		s->protinfo.af_unix.marksweep|=MARKED;
+		s->protinfo.af_unix.gc_tree=NULL;
 	}
 	/*
 	 *	Everything is now marked 
@@ -262,7 +250,7 @@
 				}
 			}
 			/* We have to scan not-yet-accepted ones too */
-			if (UNIXCB(skb).attr & MSG_SYN) {
+			if ((UNIXCB(skb).attr & MSG_SYN) && !skb->sk->dead) {
 				if (f==NULL)
 					f=skb->sk;
 				else
@@ -276,9 +264,9 @@
 
 		if (f) 
 		{
-			if ((f->protinfo.af_unix.marksweep&MARKED))
+			if (!f->protinfo.af_unix.gc_tree)
 			{
-				f->protinfo.af_unix.marksweep&=~MARKED;
+				f->protinfo.af_unix.gc_tree=GC_HEAD;
 				x=f;
 				f=NULL;
 				goto tail;
@@ -290,7 +278,7 @@
 
 	forall_unix_sockets(i, s)
 	{
-		if (s->protinfo.af_unix.marksweep&MARKED)
+		if (!s->protinfo.af_unix.gc_tree)
 		{
 			struct sk_buff *nextsk;
 			skb=skb_peek(&s->receive_queue);
diff -u --recursive --new-file v2.2.2/linux/scripts/ksymoops/oops.c linux/scripts/ksymoops/oops.c
--- v2.2.2/linux/scripts/ksymoops/oops.c	Thu Jan  7 15:11:42 1999
+++ linux/scripts/ksymoops/oops.c	Wed Feb 24 16:27:54 1999
@@ -976,7 +976,7 @@
 			"("						/*  4 */
 			  "(general protection.*)"
 			  "|(<[0-9]+>)"
-			  "|(([<(]?[0-9a-fA-F]+[>)]?[ \t]*)+)"
+			  "|(([<(]?[0-9a-fA-F]+[>)]?[ \t]+)+[<(]?[0-9a-fA-F]+[>)]?)"
 			")"
 			"(.*)$"				/* trailing garbage */
 			,
